Commit 56cdc04b by liumengfei

Merge branch 'developer' into production

parents 030cdb93 15ce2546
<?php
/**
* Product Media Attribute Write Service
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Joshine\Catalog\Api;
/**
* @todo implement this interface as a \Magento\Catalog\Model\Product\Attribute\Media\GalleryManagement.
* Move logic from service there.
* @api
* @since 100.0.2
*/
interface ProductAttributeMediaGalleryManagementInterface
{
/**
* Updates the specified products in item array.
*
* @api
* @param mixed $entry
* @return \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface[]
*/
public function add(
$entry
);
/**
* Create new gallery entry
*
* @param string $sku
* @param \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface $entry
* @return int gallery entry ID
* @throws \Magento\Framework\Exception\InputException
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @throws \Magento\Framework\Exception\StateException
*/
public function create(
$sku,
\Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface $entry
);
/**
* Update gallery entry
*
* @param string $sku
* @param \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface $entry
* @return bool
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @throws \Magento\Framework\Exception\StateException
*/
public function update(
$sku,
\Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface $entry
);
/**
* Retrieve the list of gallery entries associated with given product
*
* @param string $sku
* @return \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface[]
*/
public function getList($sku);
}
<?php
/**
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Joshine\Catalog\Api;
/**
* @api
* @since 100.0.2
*/
interface ProductRepositoryInterface
{
/**
* Create product
*
* @api
* @param mixed $product
* @return boolean
*/
public function create($product);
/**
* Create products
*
* @param \Magento\Catalog\Api\Data\ProductInterface $product
* @param bool $saveOptions
* @return \Magento\Catalog\Api\Data\ProductInterface
* @throws \Magento\Framework\Exception\InputException
* @throws \Magento\Framework\Exception\StateException
* @throws \Magento\Framework\Exception\CouldNotSaveException
*/
public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false);
/**
* Get info about product by product SKU
*
* @param string $sku
* @param bool $editMode
* @param int|null $storeId
* @param bool $forceReload
* @return \Magento\Catalog\Api\Data\ProductInterface
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function get($sku, $editMode = false, $storeId = null, $forceReload = false);
/**
* Get info about product by product id
*
* @param int $productId
* @param bool $editMode
* @param int|null $storeId
* @param bool $forceReload
* @return \Magento\Catalog\Api\Data\ProductInterface
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getById($productId, $editMode = false, $storeId = null, $forceReload = false);
/**
* Delete product
*
* @param \Magento\Catalog\Api\Data\ProductInterface $product
* @return bool Will returned True if deleted
* @throws \Magento\Framework\Exception\StateException
*/
public function delete(\Magento\Catalog\Api\Data\ProductInterface $product);
/**
* @param string $sku
* @return bool Will returned True if deleted
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @throws \Magento\Framework\Exception\StateException
*/
public function deleteById($sku);
/**
* Get product list
*
* @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
* @return \Magento\Catalog\Api\Data\ProductSearchResultsInterface
*/
public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria);
}
<?php
namespace Joshine\Catalog\Block\Adminhtml\Category\Tab;
use Magento\Catalog\Block\Adminhtml\Category\Tab\Product as JoshineProduct;
class Product extends JoshineProduct
{
public function setCollection($collection){
$collection->addAttributeToSelect('thumbnail');
parent::setCollection($collection);
}
protected function _prepareColumns(){
parent::_prepareColumns();
$this->addColumnAfter('image', array(
'header' => __('image'),
'index' => 'thumbnail',
'renderer' =>'Joshine\Catalog\Block\Adminhtml\Helper\Form\Image'
), 'sku');
$this->sortColumnsByOrder();
return $this;
}
}
<?php
namespace Joshine\Catalog\Block\Adminhtml\Helper\Form;
use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
class Image extends AbstractRenderer
{
public function render(DataObject $row)
{
$objectManager =\Magento\Framework\App\ObjectManager::getInstance();
$helperImport = $objectManager->get('\Magento\Catalog\Helper\Image');
$imageUrl = $helperImport->init($row, 'thumbnail')
->setImageFile($row->getData('thumbnail')) // image,small_image,thumbnail
->resize(380)
->getUrl();
if (empty($row->getData('thumbnail')) ){
return "<span> No pictures </span>";
}
return "<img src=". $imageUrl ." width='100' >";
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Joshine\Catalog\Helper;
use Magento\Catalog\Helper\Image;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler;
use Magento\Framework\App\Helper\Context;
/**
* Catalog data helper
*
* @api
*
* @SuppressWarnings(PHPMD.TooManyFields)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @since 100.0.2
*/
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
protected $galleryReadHandler;
/**
* Catalog Image Helper
*
* @var \Magento\Catalog\Helper\Image
*/
protected $imageHelper;
public function __construct(
GalleryReadHandler $galleryReadHandler, Context $context, Image $imageHelper)
{
$this->galleryReadHandler = $galleryReadHandler;
$this->imageHelper = $imageHelper;
parent::__construct($context);
}
public function getSecondProductImage(Product $product){
$this->galleryReadHandler->execute($product);
$images = $product->getMediaGalleryImages();
if(count($images)>=2){
$index = 0;
foreach ($images as $image) {
$index++;
if($index==2){
$image->setData(
'second_image',
$this->imageHelper->init($product, 'category_page_list')
->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false)
->setImageFile($image->getFile())
->getUrl()
);
$result = $image;
break;
}
}
return $result;
}else{
return null;
}
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Joshine\Catalog\Model\Product\Gallery;
use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface;
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Api\ImageContent;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\StateException;
use Magento\Framework\Api\ImageContentValidatorInterface;
use Magento\Framework\View\Asset\NotationResolver\Variable;
use Magento\Framework\Webapi\Rest\Request;
/**
* Class GalleryManagement
*
* Provides implementation of api interface ProductAttributeMediaGalleryManagementInterface
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class GalleryManagement implements \Joshine\Catalog\Api\ProductAttributeMediaGalleryManagementInterface
{
/**
* @var \Magento\Catalog\Api\ProductRepositoryInterface
*/
protected $productRepository;
/**
* @var ImageContentValidatorInterface
*/
protected $contentValidator;
/**
* @var ProductInterfaceFactory
*/
private $productInterfaceFactory;
protected $entry;
/**
* @param ProductRepositoryInterface $productRepository
* @param ImageContentValidatorInterface $contentValidator
* @param ProductInterfaceFactory|null $productInterfaceFactory
* @param DeleteValidator|null $deleteValidator
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
ProductRepositoryInterface $productRepository,
ImageContentValidatorInterface $contentValidator,
ProductAttributeMediaGalleryEntryInterface $entry,
?ProductInterfaceFactory $productInterfaceFactory = null
) {
$this->productRepository = $productRepository;
$this->contentValidator = $contentValidator;
$this->productInterfaceFactory = $productInterfaceFactory
?? ObjectManager::getInstance()->get(ProductInterfaceFactory::class);
$this->entry = $entry;
}
/**
* @inheritdoc
*/
public function add($content)
{
if (empty($content)) {
throw new StateException(__("request update date is null ,so failed"));
}
$ids = [];
$sku = $content[0]['sku'];
foreach ($content as $entry){
$entry_id = 0;
if (key_exists("id",$entry)){
$entry_id= (int)$entry["id"];
}
$this->entry->setMediaType($entry['media_type']);
$this->entry->setDisabled($entry['disabled']);
$this->entry->setPosition($entry['position']);
$this->entry->setLabel($entry['label']);
$this->entry->setTypes($entry['types']);
if ($entry_id){
$this->entry->setId($entry_id);
$result = $this->update($sku,$this->entry);
if ($result){
$id = $entry_id;
}else{
throw new StateException(__("$entry_id update failed"));
}
}else{
$this->entry->setFile($entry['file']);
$imageContent = new ImageContent();
$imageContent->setBase64EncodedData($entry['content']['base64_encoded_data']);
$imageContent->setName($entry['content']['name']);
$imageContent->setType($entry['content']['type']);
$this->entry->setContent($imageContent);
$id = $this->create($sku,$this->entry);
}
if (is_numeric((int)$id)){
$ids []= (int)$id;
}
$this->entry->setData([]);
}
if (!$ids){
throw new StateException(__('Batch upload of product images failed'));
}
$list = $this->getList($sku);
foreach ($list as $key => $v) {
if (!in_array($v->getId(),$ids)) {
unset($list[$key]);
}
}
array_multisort($list);
return $list;
}
/**
* @inheritdoc
*/
public function create($sku,ProductAttributeMediaGalleryEntryInterface $entry)
{
/** @var $entry ProductAttributeMediaGalleryEntryInterface */
$entryContent = $entry->getContent();
if (!$this->contentValidator->isValid($entryContent)) {
throw new InputException(__('The image content is invalid. Verify the content and try again.'));
}
$product = $this->productRepository->get($sku, true);
$existingMediaGalleryEntries = $product->getMediaGalleryEntries();
$existingEntryIds = [];
if ($existingMediaGalleryEntries == null) {
// set all media types if not specified
if ($entry->getTypes() == null) {
$entry->setTypes(array_keys($product->getMediaAttributes()));
}
$existingMediaGalleryEntries = [$entry];
} else {
foreach ($existingMediaGalleryEntries as $existingEntries) {
$existingEntryIds[$existingEntries->getId()] = $existingEntries->getId();
}
$existingMediaGalleryEntries[] = $entry;
}
$product = $this->productInterfaceFactory->create();
$product->setSku($sku);
$product->setMediaGalleryEntries($existingMediaGalleryEntries);
try {
$product = $this->productRepository->save($product);
} catch (\Exception $e) {
if ($e instanceof InputException) {
throw $e;
} else {
throw new StateException(__("The product can't be saved."));
}
}
foreach ($product->getMediaGalleryEntries() as $entry) {
if (!isset($existingEntryIds[$entry->getId()])) {
return $entry->getId();
}
}
throw new StateException(__('The new media gallery entry failed to save.'));
}
/**
* @inheritdoc
*/
public function update($sku, ProductAttributeMediaGalleryEntryInterface $entry)
{
$product = $this->productRepository->get($sku, true);
$existingMediaGalleryEntries = $product->getMediaGalleryEntries();
if ($existingMediaGalleryEntries == null) {
throw new NoSuchEntityException(
__('No image with the provided ID was found. Verify the ID and try again.')
);
}
$found = false;
$entryTypes = (array)$entry->getTypes();
foreach ($existingMediaGalleryEntries as $key => $existingEntry) {
$existingEntryTypes = (array)$existingEntry->getTypes();
$existingEntry->setTypes(array_diff($existingEntryTypes, $entryTypes));
if ($existingEntry->getId() == $entry->getId()) {
$found = true;
$existingMediaGalleryEntries[$key] = $entry;
}
}
if (!$found) {
throw new NoSuchEntityException(
__('No image with the provided ID was found. Verify the ID and try again.')
);
}
$product = $this->productInterfaceFactory->create();
$product->setSku($sku);
$product->setMediaGalleryEntries($existingMediaGalleryEntries);
try {
$this->productRepository->save($product);
} catch (\Exception $exception) {
throw new StateException(__("The product can't be saved."));
}
return true;
}
/**
* @inheritdoc
*/
public function getList($sku)
{
/** @var \Magento\Catalog\Model\Product $product */
$product = $this->productRepository->get($sku);
return $product->getMediaGalleryEntries();
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Joshine\Catalog\Model;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface;
use Magento\Catalog\Api\CategoryLinkManagementInterface;
use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Catalog\Api\Data\ProductExtension;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Attribute\ScopeOverriddenValue;
use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap;
use Magento\Catalog\Model\ProductRepository\MediaGalleryProcessor;
use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\Eav\Model\Entity\Attribute\Exception as AttributeException;
use Magento\Framework\Api\Data\ImageContentInterfaceFactory;
use Magento\Framework\Api\ImageContent;
use Magento\Framework\Api\ImageContentValidatorInterface;
use Magento\Framework\Api\ImageProcessorInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\DB\Adapter\ConnectionException;
use Magento\Framework\DB\Adapter\DeadlockException;
use Magento\Framework\DB\Adapter\LockWaitException;
use Magento\Framework\EntityManager\Operation\Read\ReadExtensions;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\StateException;
use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException;
use Magento\Framework\Exception\ValidatorException;
use Magento\Store\Model\Store;
use Magento\Catalog\Api\Data\EavAttributeInterface;
use Magento\CatalogInventory\Api\Data\StockItemInterface;
/**
* @inheritdoc
*
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.TooManyFields)
*/
class ProductRepository implements \Joshine\Catalog\Api\ProductRepositoryInterface
{
/**
* @var \Magento\Catalog\Api\ProductCustomOptionRepositoryInterface
*/
protected $optionRepository;
/**
* @var \Magento\Catalog\Model\ProductFactory
*/
protected $productFactory;
/**
* @var Product[]
*/
protected $instances = [];
/**
* @var Product[]
*/
protected $instancesById = [];
/**
* @var \Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper
*/
protected $initializationHelper;
/**
* @var \Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory
*/
protected $searchResultsFactory;
/**
* @var \Magento\Framework\Api\SearchCriteriaBuilder
*/
protected $searchCriteriaBuilder;
/**
* @var \Magento\Framework\Api\FilterBuilder
*/
protected $filterBuilder;
/**
* @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
*/
protected $collectionFactory;
/**
* @var \Magento\Catalog\Model\ResourceModel\Product
*/
protected $resourceModel;
/**
* @var Product\Initialization\Helper\ProductLinks
*/
protected $linkInitializer;
/**
* @var Product\LinkTypeProvider
*/
protected $linkTypeProvider;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManager;
/**
* @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
*/
protected $attributeRepository;
/**
* @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
*/
protected $metadataService;
/**
* @var \Magento\Framework\Api\ExtensibleDataObjectConverter
*/
protected $extensibleDataObjectConverter;
/**
* @var \Magento\Framework\Filesystem
*/
protected $fileSystem;
/**
* @deprecated 103.0.2
*
* @var ImageContentInterfaceFactory
*/
protected $contentFactory;
/**
* @deprecated 103.0.2
*
* @var ImageProcessorInterface
*/
protected $imageProcessor;
/**
* @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface
*/
protected $extensionAttributesJoinProcessor;
/**
* @deprecated 103.0.2
*
* @var \Magento\Catalog\Model\Product\Gallery\Processor
*/
protected $mediaGalleryProcessor;
/**
* @var MediaGalleryProcessor
*/
private $mediaProcessor;
/**
* @var CollectionProcessorInterface
*/
private $collectionProcessor;
/**
* @var int
*/
private $cacheLimit = 0;
/**
* @var \Magento\Framework\Serialize\Serializer\Json
*/
private $serializer;
/**
* @var ReadExtensions
*/
private $readExtensions;
/**
* @var CategoryLinkManagementInterface
*/
private $linkManagement;
/**
* @var ScopeOverriddenValue
*/
private $scopeOverriddenValue;
/**
* @var ProductInterface
*/
protected $productApi;
/**
* @var ProductExtension
*/
protected $productExtension;
/**
* @var StockItemInterface
*/
protected $stockItemInterface;
protected $entry;
/**
* ProductRepository constructor.
* @param \Magento\Catalog\Model\ProductFactory $productFactory
* @param \Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper $initializationHelper
* @param \Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory $searchResultsFactory
* @param ResourceModel\Product\CollectionFactory $collectionFactory
* @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
* @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository
* @param ResourceModel\Product $resourceModel
* @param Product\Initialization\Helper\ProductLinks $linkInitializer
* @param Product\LinkTypeProvider $linkTypeProvider
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\Api\FilterBuilder $filterBuilder
* @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $metadataServiceInterface
* @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
* @param Product\Option\Converter $optionConverter
* @param \Magento\Framework\Filesystem $fileSystem
* @param ImageContentValidatorInterface $contentValidator
* @param ImageContentInterfaceFactory $contentFactory
* @param MimeTypeExtensionMap $mimeTypeExtensionMap
* @param ImageProcessorInterface $imageProcessor
* @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor
* @param CollectionProcessorInterface $collectionProcessor [optional]
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
* @param int $cacheLimit [optional]
* @param ReadExtensions $readExtensions
* @param CategoryLinkManagementInterface $linkManagement
* @param ScopeOverriddenValue|null $scopeOverriddenValue
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
ProductInterface $productApi,
ProductExtension $productExtension,
StockItemInterface $stockItemInterface,
ProductAttributeMediaGalleryEntryInterface $entry,
\Magento\Catalog\Model\ProductFactory $productFactory,
\Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper $initializationHelper,
\Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory $searchResultsFactory,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory,
\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
\Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository,
\Magento\Catalog\Model\ResourceModel\Product $resourceModel,
\Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks $linkInitializer,
\Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Api\FilterBuilder $filterBuilder,
\Magento\Catalog\Api\ProductAttributeRepositoryInterface $metadataServiceInterface,
\Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
\Magento\Catalog\Model\Product\Option\Converter $optionConverter,
\Magento\Framework\Filesystem $fileSystem,
ImageContentValidatorInterface $contentValidator,
ImageContentInterfaceFactory $contentFactory,
MimeTypeExtensionMap $mimeTypeExtensionMap,
ImageProcessorInterface $imageProcessor,
\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor,
CollectionProcessorInterface $collectionProcessor = null,
\Magento\Framework\Serialize\Serializer\Json $serializer = null,
$cacheLimit = 1000,
ReadExtensions $readExtensions = null,
CategoryLinkManagementInterface $linkManagement = null,
?ScopeOverriddenValue $scopeOverriddenValue = null
) {
$this->productFactory = $productFactory;
$this->collectionFactory = $collectionFactory;
$this->initializationHelper = $initializationHelper;
$this->searchResultsFactory = $searchResultsFactory;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->resourceModel = $resourceModel;
$this->linkInitializer = $linkInitializer;
$this->linkTypeProvider = $linkTypeProvider;
$this->storeManager = $storeManager;
$this->attributeRepository = $attributeRepository;
$this->filterBuilder = $filterBuilder;
$this->metadataService = $metadataServiceInterface;
$this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
$this->fileSystem = $fileSystem;
$this->contentFactory = $contentFactory;
$this->imageProcessor = $imageProcessor;
$this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
$this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor();
$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Framework\Serialize\Serializer\Json::class);
$this->cacheLimit = (int)$cacheLimit;
$this->readExtensions = $readExtensions ?: \Magento\Framework\App\ObjectManager::getInstance()
->get(ReadExtensions::class);
$this->linkManagement = $linkManagement ?: \Magento\Framework\App\ObjectManager::getInstance()
->get(CategoryLinkManagementInterface::class);
$this->scopeOverriddenValue = $scopeOverriddenValue ?: \Magento\Framework\App\ObjectManager::getInstance()
->get(ScopeOverriddenValue::class);
$this->productApi = $productApi;
$this->productExtension = $productExtension;
$this->stockItemInterface = $stockItemInterface;
$this->entry = $entry;
}
/**
* @inheritdoc
*/
public function get($sku, $editMode = false, $storeId = null, $forceReload = false)
{
$cacheKey = $this->getCacheKey([$editMode, $storeId === null ? $storeId : (int) $storeId]);
$cachedProduct = $this->getProductFromLocalCache($sku, $cacheKey);
if ($cachedProduct === null || $forceReload) {
$product = $this->productFactory->create();
$productId = $this->resourceModel->getIdBySku($sku);
if (!$productId) {
throw new NoSuchEntityException(
__("The product that was requested doesn't exist. Verify the product and try again.")
);
}
if ($editMode) {
$product->setData('_edit_mode', true);
}
if ($storeId !== null) {
$product->setData('store_id', (int) $storeId);
}
$product->load($productId);
$this->cacheProduct($cacheKey, $product);
$cachedProduct = $product;
}
return $cachedProduct;
}
/**
* @inheritdoc
*/
public function getById($productId, $editMode = false, $storeId = null, $forceReload = false)
{
$cacheKey = $this->getCacheKey([$editMode, $storeId]);
if (!isset($this->instancesById[$productId][$cacheKey]) || $forceReload) {
$product = $this->productFactory->create();
if ($editMode) {
$product->setData('_edit_mode', true);
}
if ($storeId !== null) {
$product->setData('store_id', $storeId);
}
$product->load($productId);
if (!$product->getId()) {
throw new NoSuchEntityException(
__("The product that was requested doesn't exist. Verify the product and try again.")
);
}
$this->cacheProduct($cacheKey, $product);
}
return $this->instancesById[$productId][$cacheKey];
}
/**
* Get key for cache
*
* @param array $data
* @return string
*/
protected function getCacheKey($data)
{
$serializeData = [];
foreach ($data as $key => $value) {
if (is_object($value)) {
$serializeData[$key] = $value->getId();
} else {
$serializeData[$key] = $value;
}
}
$serializeData = $this->serializer->serialize($serializeData);
return sha1($serializeData);
}
/**
* Add product to internal cache and truncate cache if it has more than cacheLimit elements.
*
* @param string $cacheKey
* @param ProductInterface $product
* @return void
*/
private function cacheProduct($cacheKey, ProductInterface $product)
{
$this->instancesById[$product->getId()][$cacheKey] = $product;
$this->saveProductInLocalCache($product, $cacheKey);
if ($this->cacheLimit && count($this->instances) > $this->cacheLimit) {
$offset = round($this->cacheLimit / -2);
$this->instancesById = array_slice($this->instancesById, $offset, null, true);
$this->instances = array_slice($this->instances, $offset, null, true);
}
}
/**
* Merge data from DB and updates from request
*
* @param array $productData
* @param bool $createNew
* @return ProductInterface|Product
* @throws NoSuchEntityException
*/
protected function initializeProductData(array $productData, $createNew)
{
unset($productData['media_gallery']);
if ($createNew) {
$product = $this->productFactory->create();
$this->assignProductToWebsites($product);
} elseif (!empty($productData['id'])) {
$this->removeProductFromLocalCacheById($productData['id']);
$product = $this->getById($productData['id']);
} else {
$this->removeProductFromLocalCacheBySku($productData['sku']);
$product = $this->get($productData['sku']);
}
if(empty($productData['name'])){
$temp_sku = explode("_",$productData['sku']);
$tempProduct = $this->get($temp_sku[0]);
$productData['name'] = $tempProduct->getName();
if (count($temp_sku) > 1){
$productData['name'] .= " ". $productData['sku'];
}
}
foreach ($productData as $key => $value) {
$product->setData($key, $value);
}
return $product;
}
/**
* Assign product to websites.
*
* @param \Magento\Catalog\Model\Product $product
* @return void
*/
private function assignProductToWebsites(\Magento\Catalog\Model\Product $product)
{
if ($this->storeManager->getStore(true)->getCode() == \Magento\Store\Model\Store::ADMIN_CODE) {
$websiteIds = array_keys($this->storeManager->getWebsites());
} else {
$websiteIds = [$this->storeManager->getStore()->getWebsiteId()];
}
$product->setWebsiteIds($websiteIds);
}
/**
* Process new gallery media entry.
*
* @deprecated 103.0.2
* @see MediaGalleryProcessor::processNewMediaGalleryEntry()
*
* @param ProductInterface $product
* @param array $newEntry
* @return $this
* @throws InputException
* @throws StateException
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function processNewMediaGalleryEntry(
ProductInterface $product,
array $newEntry
) {
$this->getMediaGalleryProcessor()->processNewMediaGalleryEntry($product, $newEntry);
return $this;
}
/**
* Process product links, creating new links, updating and deleting existing links
*
* @param ProductInterface $product
* @param \Magento\Catalog\Api\Data\ProductLinkInterface[] $newLinks
* @return $this
* @throws NoSuchEntityException
*/
private function processLinks(ProductInterface $product, $newLinks)
{
if ($newLinks === null) {
// If product links were not specified, don't do anything
return $this;
}
// Clear all existing product links and then set the ones we want
$linkTypes = $this->linkTypeProvider->getLinkTypes();
foreach (array_keys($linkTypes) as $typeName) {
$this->linkInitializer->initializeLinks($product, [$typeName => []]);
}
// Set each linktype info
if (!empty($newLinks)) {
$productLinks = [];
foreach ($newLinks as $link) {
$productLinks[$link->getLinkType()][] = $link;
}
foreach ($productLinks as $type => $linksByType) {
$assignedSkuList = [];
/** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */
foreach ($linksByType as $link) {
$assignedSkuList[] = $link->getLinkedProductSku();
}
$linkedProductIds = $this->resourceModel->getProductsIdsBySkus($assignedSkuList);
$linksToInitialize = [];
foreach ($linksByType as $link) {
$linkDataArray = $this->extensibleDataObjectConverter
->toNestedArray($link, [], \Magento\Catalog\Api\Data\ProductLinkInterface::class);
$linkedSku = $link->getLinkedProductSku();
if (!isset($linkedProductIds[$linkedSku])) {
throw new NoSuchEntityException(
__('The Product with the "%1" SKU doesn\'t exist.', $linkedSku)
);
}
$linkDataArray['product_id'] = $linkedProductIds[$linkedSku];
$linksToInitialize[$linkedProductIds[$linkedSku]] = $linkDataArray;
}
$this->linkInitializer->initializeLinks($product, [$type => $linksToInitialize]);
}
}
$product->setProductLinks($newLinks);
return $this;
}
/**
* Process Media gallery data before save product.
*
* Compare Media Gallery Entries Data with existing Media Gallery
* * If Media entry has not value_id set it as new
* * If Existing entry 'value_id' absent in Media Gallery set 'removed' flag
* * Merge Existing and new media gallery
*
* @param ProductInterface $product contains only existing media gallery items
* @param array $mediaGalleryEntries array which contains all media gallery items
* @return $this
* @throws InputException
* @throws StateException
* @throws LocalizedException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
protected function processMediaGallery(ProductInterface $product, $mediaGalleryEntries)
{
$this->getMediaGalleryProcessor()->processMediaGallery($product, $mediaGalleryEntries);
return $this;
}
/**
* @param mixed $product
* @return bool|void
*/
public function create($product)
{
if (empty($product)) {
return 0;
}
$ids = [];
foreach ($product as $value){
$sku = $value['sku'];
$this->productApi->setName($value['name']);
$this->productApi->setAttributeSetId($value['attribute_set_id']);
$this->productApi->setSku($value['sku']);
$this->productApi->setPrice($value['price']);
$this->productApi->setStatus($value['status']);
$this->productApi->setVisibility($value['visibility']);
$this->productApi->setTypeId($value['type_id']);
$this->productApi->setWeight($value['weight']);
if (key_exists("options_container",$value)){
$this->productApi->setOptions($value['options_container']);
}
//库存
$this->stockItemInterface->setQty(999);
$this->stockItemInterface->setIsInStock(true);
$this->stockItemInterface->setIsQtyDecimal(false);
$this->stockItemInterface->setUseConfigMinQty(true);
$this->stockItemInterface->setMinQty(0);
$this->productExtension->setStockItem($this->stockItemInterface);
$this->productApi->setExtensionAttributes($this->productExtension);
$this->productApi->setCustomAttributes($value['custom_attributes']);
//图片
if (key_exists("media_gallery_entries",$value)){
$images = [];
foreach ($value['media_gallery_entries'] as $entry){
$this->entry->setMediaType($entry['media_type']);
$this->entry->setDisabled($entry['disabled']);
$this->entry->setFile($entry['file']);
$this->entry->setPosition($entry['position']);
$this->entry->setLabel($entry['label']);
$this->entry->setTypes($entry['types']);
$imageContent = new ImageContent();
$imageContent->setBase64EncodedData($entry['content']['base64_encoded_data']);
$imageContent->setName($entry['content']['name']);
$imageContent->setType($entry['content']['type']);
$this->entry->setContent($imageContent);
$images[] = $this->entry;
}
$this->productApi->setMediaGalleryEntries($images);
}
$product_id = $this->save($this->productApi,true);
$ids[] = ["id"=>(int)$product_id,"sku"=>$sku];
}
return $ids;
}
/**
* @inheritdoc
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function save(ProductInterface $product, $saveOptions = false)
{
#打印日志
\Magento\Framework\App\ObjectManager::getInstance()->get('Psr\Log\LoggerInterface')->info('rest/default/V1/products '.$product->getSku());
$assignToCategories = false;
$tierPrices = $product->getData('tier_price');
$productDataToChange = $product->getData();
try {
$existingProduct = $product->getId() ?
$this->getById($product->getId()) :
$this->get($product->getSku());
$product->setData(
$this->resourceModel->getLinkField(),
$existingProduct->getData($this->resourceModel->getLinkField())
);
if (!$product->hasData(\Magento\Catalog\Model\Product::STATUS)) {
$product->setStatus($existingProduct->getStatus());
}
/** @var ProductExtension $extensionAttributes */
$extensionAttributes = $product->getExtensionAttributes();
if (empty($extensionAttributes->__toArray())) {
$product->setExtensionAttributes($existingProduct->getExtensionAttributes());
$assignToCategories = true;
}
} catch (NoSuchEntityException $e) {
$existingProduct = null;
}
$productDataArray = $this->extensibleDataObjectConverter
->toNestedArray($product, [], ProductInterface::class);
$productDataArray = array_replace($productDataArray, $product->getData());
$ignoreLinksFlag = $product->getData('ignore_links_flag');
$productLinks = null;
if (!$ignoreLinksFlag && $ignoreLinksFlag !== null) {
$productLinks = $product->getProductLinks();
}
if (!isset($productDataArray['store_id'])) {
$productDataArray['store_id'] = (int) $this->storeManager->getStore()->getId();
}
$product = $this->initializeProductData($productDataArray, empty($existingProduct));
$this->processLinks($product, $productLinks);
if (isset($productDataArray['media_gallery'])) {
$this->processMediaGallery($product, $productDataArray['media_gallery']['images']);
}
if (!$product->getOptionsReadonly()) {
$product->setCanSaveCustomOptions(true);
}
$validationResult = $this->resourceModel->validate($product);
if (true !== $validationResult) {
throw new \Magento\Framework\Exception\CouldNotSaveException(
__('Invalid product data: %1', implode(',', $validationResult))
);
}
if ($tierPrices !== null) {
$product->setData('tier_price', $tierPrices);
}
try {
$stores = $product->getStoreIds();
$websites = $product->getWebsiteIds();
} catch (NoSuchEntityException $exception) {
$stores = null;
$websites = null;
}
if (!empty($existingProduct) && is_array($stores) && is_array($websites)) {
$hasDataChanged = false;
$productAttributes = $product->getAttributes();
if ($productAttributes !== null
&& $product->getStoreId() !== Store::DEFAULT_STORE_ID
&& (count($stores) > 1 || count($websites) === 1)
) {
foreach ($productAttributes as $attribute) {
$attributeCode = $attribute->getAttributeCode();
$value = $product->getData($attributeCode);
if ($existingProduct->getData($attributeCode) === $value
&& $attribute->getScope() !== EavAttributeInterface::SCOPE_GLOBAL_TEXT
&& !is_array($value)
&& !$attribute->isStatic()
&& !array_key_exists($attributeCode, $productDataToChange)
&& $value !== null
&& !$this->scopeOverriddenValue->containsValue(
ProductInterface::class,
$product,
$attributeCode,
$product->getStoreId()
)
) {
$product->setData(
$attributeCode,
$attributeCode === ProductAttributeInterface::CODE_SEO_FIELD_URL_KEY ? false : null
);
$hasDataChanged = true;
}
}
if ($hasDataChanged) {
$product->setData('_edit_mode', true);
}
}
}
$this->saveProduct($product);
if ($assignToCategories === true && $product->getCategoryIds()) {
$this->linkManagement->assignProductToCategories(
$product->getSku(),
$product->getCategoryIds()
);
}
$this->removeProductFromLocalCacheBySku($product->getSku());
$this->removeProductFromLocalCacheById($product->getId());
return $product->getId();
return $this->get($product->getSku(), false, $product->getStoreId());
}
/**
* @inheritdoc
*/
public function delete(ProductInterface $product)
{
$sku = $product->getSku();
$productId = $product->getId();
try {
$this->removeProductFromLocalCacheBySku($product->getSku());
$this->removeProductFromLocalCacheById($product->getId());
$this->resourceModel->delete($product);
} catch (ValidatorException $e) {
throw new CouldNotSaveException(__($e->getMessage()), $e);
} catch (\Exception $e) {
throw new \Magento\Framework\Exception\StateException(
__('The "%1" product couldn\'t be removed.', $sku),
$e
);
}
$this->removeProductFromLocalCacheBySku($sku);
$this->removeProductFromLocalCacheById($productId);
return true;
}
/**
* @inheritdoc
*/
public function deleteById($sku)
{
$product = $this->get($sku);
return $this->delete($product);
}
/**
* @inheritdoc
*/
public function getList(SearchCriteriaInterface $searchCriteria)
{
/** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
$collection = $this->collectionFactory->create();
$this->extensionAttributesJoinProcessor->process($collection);
$collection->addAttributeToSelect('*');
$collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner');
$collection->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner');
$this->joinPositionField($collection, $searchCriteria);
$this->collectionProcessor->process($searchCriteria, $collection);
$collection->load();
$collection->addCategoryIds();
$this->addExtensionAttributes($collection);
$searchResult = $this->searchResultsFactory->create();
$searchResult->setSearchCriteria($searchCriteria);
$searchResult->setItems($collection->getItems());
$searchResult->setTotalCount($collection->getSize());
foreach ($collection->getItems() as $product) {
$this->cacheProduct(
$this->getCacheKey(
[
false,
$product->getStoreId()
]
),
$product
);
}
return $searchResult;
}
/**
* Add extension attributes to loaded items.
*
* @param Collection $collection
* @return Collection
*/
private function addExtensionAttributes(Collection $collection) : Collection
{
foreach ($collection->getItems() as $item) {
$this->readExtensions->execute($item);
}
return $collection;
}
/**
* Helper function that adds a FilterGroup to the collection.
*
* @deprecated 102.0.0
* @param \Magento\Framework\Api\Search\FilterGroup $filterGroup
* @param Collection $collection
* @return void
*/
protected function addFilterGroupToCollection(
\Magento\Framework\Api\Search\FilterGroup $filterGroup,
Collection $collection
) {
$fields = [];
$categoryFilter = [];
foreach ($filterGroup->getFilters() as $filter) {
$conditionType = $filter->getConditionType() ?: 'eq';
if ($filter->getField() == 'category_id') {
$categoryFilter[$conditionType][] = $filter->getValue();
continue;
}
$fields[] = ['attribute' => $filter->getField(), $conditionType => $filter->getValue()];
}
if ($categoryFilter) {
$collection->addCategoriesFilter($categoryFilter);
}
if ($fields) {
$collection->addFieldToFilter($fields);
}
}
/**
* Clean internal product cache
*
* @return void
*/
public function cleanCache()
{
$this->instances = null;
$this->instancesById = null;
}
/**
* Retrieve media gallery processor.
*
* @return MediaGalleryProcessor
*/
private function getMediaGalleryProcessor()
{
if (null === $this->mediaProcessor) {
$this->mediaProcessor = \Magento\Framework\App\ObjectManager::getInstance()
->get(MediaGalleryProcessor::class);
}
return $this->mediaProcessor;
}
/**
* Retrieve collection processor
*
* @deprecated 102.0.0
* @return CollectionProcessorInterface
*/
private function getCollectionProcessor()
{
if (!$this->collectionProcessor) {
$this->collectionProcessor = \Magento\Framework\App\ObjectManager::getInstance()->get(
// phpstan:ignore "Class Magento\Catalog\Model\Api\SearchCriteria\ProductCollectionProcessor not found."
\Magento\Catalog\Model\Api\SearchCriteria\ProductCollectionProcessor::class
);
}
return $this->collectionProcessor;
}
/**
* Gets product from the local cache by SKU.
*
* @param string $sku
* @param string $cacheKey
* @return Product|null
*/
private function getProductFromLocalCache(string $sku, string $cacheKey)
{
$preparedSku = $this->prepareSku($sku);
return $this->instances[$preparedSku][$cacheKey] ?? null;
}
/**
* Removes product in the local cache by sku.
*
* @param string $sku
* @return void
*/
private function removeProductFromLocalCacheBySku(string $sku): void
{
$preparedSku = $this->prepareSku($sku);
unset($this->instances[$preparedSku]);
}
/**
* Removes product in the local cache by id.
*
* @param string|null $id
* @return void
*/
private function removeProductFromLocalCacheById(?string $id): void
{
unset($this->instancesById[$id]);
}
/**
* Saves product in the local cache by sku.
*
* @param Product $product
* @param string $cacheKey
* @return void
*/
private function saveProductInLocalCache(Product $product, string $cacheKey): void
{
$preparedSku = $this->prepareSku($product->getSku());
$this->instances[$preparedSku][$cacheKey] = $product;
}
/**
* Converts SKU to lower case and trims.
*
* @param string $sku
* @return string
*/
private function prepareSku(string $sku): string
{
return mb_strtolower(trim($sku));
}
/**
* Save product resource model.
*
* @param ProductInterface|Product $product
* @throws TemporaryCouldNotSaveException
* @throws InputException
* @throws CouldNotSaveException
* @throws LocalizedException
*/
private function saveProduct($product): void
{
try {
$this->removeProductFromLocalCacheBySku($product->getSku());
$this->removeProductFromLocalCacheById($product->getId());
$this->resourceModel->save($product);
} catch (ConnectionException $exception) {
throw new TemporaryCouldNotSaveException(
__('Database connection error'),
$exception,
$exception->getCode()
);
} catch (DeadlockException $exception) {
throw new TemporaryCouldNotSaveException(
__('Database deadlock found when trying to get lock'),
$exception,
$exception->getCode()
);
} catch (LockWaitException $exception) {
throw new TemporaryCouldNotSaveException(
__('Database lock wait timeout exceeded'),
$exception,
$exception->getCode()
);
} catch (AttributeException $exception) {
throw InputException::invalidFieldValue(
$exception->getAttributeCode(),
$product->getData($exception->getAttributeCode()),
$exception
);
} catch (ValidatorException $e) {
throw new CouldNotSaveException(__($e->getMessage()));
} catch (LocalizedException $e) {
throw $e;
} catch (\Exception $e) {
throw new CouldNotSaveException(
__('The product was unable to be saved. Please try again.'),
$e
);
}
}
/**
* Join category position field to make sorting by position possible.
*
* @param Collection $collection
* @param SearchCriteriaInterface $searchCriteria
* @return void
*/
private function joinPositionField(
Collection $collection,
SearchCriteriaInterface $searchCriteria
): void {
$categoryIds = [[]];
foreach ($searchCriteria->getFilterGroups() as $filterGroup) {
foreach ($filterGroup->getFilters() as $filter) {
if ($filter->getField() === 'category_id') {
$filterValue = $filter->getValue();
$categoryIds[] = is_array($filterValue) ? $filterValue : explode(',', $filterValue ?? '');
}
}
}
$categoryIds = array_unique(array_merge(...$categoryIds));
if (count($categoryIds) === 1) {
$collection->joinField(
'position',
'catalog_category_product',
'position',
'product_id=entity_id',
['category_id' => current($categoryIds)],
'left'
);
}
}
}
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Catalog\Block\Adminhtml\Category\Tab\Product" type="Joshine\Catalog\Block\Adminhtml\Category\Tab\Product" />
<preference for="Joshine\Catalog\Api\ProductAttributeMediaGalleryManagementInterface" type="Joshine\Catalog\Model\Product\Gallery\GalleryManagement" />
<preference for="Joshine\Catalog\Api\ProductRepositoryInterface" type="Joshine\Catalog\Model\ProductRepository" />
</config>
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Joshine_Catalog" setup_version="1.0.0">
</module>
</config>
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route url="/V1/products/media" method="POST">
<service class="Joshine\Catalog\Api\ProductAttributeMediaGalleryManagementInterface" method="add"/>
<resources>
<resource ref="Magento_Catalog::catalog"/>
</resources>
</route>
<route url="/V1/product" method="POST">
<service class="Joshine\Catalog\Api\ProductRepositoryInterface" method="create"/>
<resources>
<resource ref="Magento_Catalog::products" />
</resources>
</route>
</routes>
<?php
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Joshine_Catalog',
__DIR__
);
...@@ -14,10 +14,10 @@ ...@@ -14,10 +14,10 @@
var dis = $(this).siblings("ul").css("display"); var dis = $(this).siblings("ul").css("display");
if (dis == "none"){ if (dis == "none"){
$(this).siblings("ul").css("display","block"); $(this).siblings("ul").css("display","block");
$(this).children("span").html('^') $(this).children("strong").html('^')
}else{ }else{
$(this).siblings("ul").css("display","none"); $(this).siblings("ul").css("display","none");
$(this).children("span").html('>') $(this).children("strong").html('>')
} }
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment