Smile-SA/magento2-module-custom-entity

View on GitHub
Model/CustomEntity.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

declare(strict_types=1);

namespace Smile\CustomEntity\Model;

use Magento\Eav\Api\AttributeSetRepositoryInterface;
use Magento\Eav\Api\Data\AttributeSetInterface;
use Magento\Framework\Api\AttributeValueFactory;
use Magento\Framework\Api\ExtensionAttributesFactory;
use Magento\Framework\Api\MetadataServiceInterface;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Filter\FilterManager;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\Registry;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Store\Model\Website;
use Smile\CustomEntity\Api\Data\CustomEntityExtensionInterface;
use Smile\CustomEntity\Api\Data\CustomEntityInterface;
use Smile\ScopedEav\Model\AbstractEntity;

/**
 * Custom entity model default implementation.
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class CustomEntity extends AbstractEntity implements IdentityInterface, CustomEntityInterface
{
    /**
     * Product cache tag
     */
    public const CACHE_TAG = 'sce';

    public const CACHE_CUSTOM_ENTITY_SET_TAG = 'sces';

    /**
     * @inheritdoc
     */
    protected $_cacheTag = self::CACHE_TAG;

    /**
     * @inheritdoc
     */
    protected $_eventPrefix = 'smile_custom_entity';

    /**
     * @inheritdoc
     */
    protected $_eventObject = 'smile_custom_entity';

    private MetadataServiceInterface $metadataService;

    /**
     * List of attributes defined in the interface.
     *
     * @var string[]
     */
    private array $interfaceAttributes = [
        self::ATTRIBUTE_SET_ID,
        self::CREATED_AT,
        self::UPDATED_AT,
        self::NAME,
        self::IS_ACTIVE,
    ];

    private FilterManager $filterManager;

    private AttributeSetRepositoryInterface $attributeSetRepository;

    private AttributeSetInterface $attributeSet;

    /**
     * Constructor.
     *
     * @param Context $context Context.
     * @param Registry $registry Registry.
     * @param ExtensionAttributesFactory $extensionFactory Extension factory.
     * @param AttributeValueFactory $customAttributeFactory Custom attribute factory.
     * @param StoreManagerInterface $storeManager Store manager.
     * @param MetadataServiceInterface $metadataService Metadata service.
     * @param FilterManager $filterManager Filter Manager.
     * @param AttributeSetRepositoryInterface $attributeSetRepository Attribute set repository.
     * @param AbstractResource|null $resource Resource model.
     * @param AbstractDb|null $resourceCollection Collection.
     * @param array $data Additional data.
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        Context $context,
        Registry $registry,
        ExtensionAttributesFactory $extensionFactory,
        AttributeValueFactory $customAttributeFactory,
        StoreManagerInterface $storeManager,
        MetadataServiceInterface $metadataService,
        FilterManager $filterManager,
        AttributeSetRepositoryInterface $attributeSetRepository,
        ?AbstractResource $resource = null,
        ?AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        parent::__construct(
            $context,
            $registry,
            $extensionFactory,
            $customAttributeFactory,
            $storeManager,
            $resource,
            $resourceCollection,
            $data
        );
        $this->metadataService = $metadataService;
        $this->filterManager = $filterManager;
        $this->attributeSetRepository = $attributeSetRepository;
    }

    /**
     * Get identities
     *
     * @return array|null
     */
    public function getIdentities(): ?array
    {
        $identities = [self::CACHE_TAG . '_' . $this->getId()];
        if ($this->dataHasChangedFor(self::IS_ACTIVE) && $this->getIsActive()) {
            $identities[] = self::CACHE_CUSTOM_ENTITY_SET_TAG . '_' . $this->getAttributeSetId();
        }

        return array_unique($identities);
    }

    /**
     * Get url key
     */
    public function getUrlKey(): ?string
    {
        $urlKey = $this->getData(self::URL_KEY);
        if ($urlKey === '' || $urlKey === null) {
            $urlKey = $this->filterManager->translitUrl($this->getName());
        }

        return $urlKey;
    }

    /**
     * Set url key.
     *
     * @param string $urlKey Url key
     * @return $this
     */
    public function setUrlKey(string $urlKey): self
    {
        return $this->setData(self::URL_KEY, $urlKey);
    }

    /**
     * Get url path.
     */
    public function getUrlPath(): string
    {
        return $this->getAttributeSetUrlKey() . '/' . $this->getUrlKey();
    }

    /**
     * Return attribute set.
     *
     * @throws NoSuchEntityException
     */
    public function getAttributeSet(): ?AttributeSetInterface
    {
        if (empty($this->attributeSet)) {
            $this->attributeSet = $this->attributeSetRepository->get($this->getAttributeSetId());
        }

        return $this->attributeSet;
    }

    /**
     * Return attribute set url key.
     *
     * @throws NoSuchEntityException
     */
    public function getAttributeSetUrlKey(): ?string
    {
        $attributeSetName = $this->getAttributeSet()->getAttributeSetName();

        return $this->filterManager->translitUrl($attributeSetName);
    }

    /**
     * @inheritdoc
     */
    public function beforeSave()
    {
        $urlKey = (string) $this->getData(self::URL_KEY);

        if ($urlKey === '') {
            $storeId = (int) $this->getStoreId();
            $useDefaults = $this->getData('use_default');

            if (
                $storeId === 0
                || $useDefaults === null
                || isset($useDefaults['url_key']) && !$useDefaults['url_key']
            ) {
                $this->setUrlKey($this->filterManager->translitUrl($this->getName() ?: $this->getOrigData('name')));
            }
        }

        return parent::beforeSave();
    }

    /**
     * Validate Product Data
     *
     * @return true|array
     */
    public function validate()
    {
        $this->_eventManager->dispatch($this->_eventPrefix . '_validate_before', $this->_getEventData());
        /** @var \Smile\ScopedEav\Model\ResourceModel\AbstractResource $resource */
        $resource = $this->_getResource();
        $result = $resource->validate($this);
        $this->_eventManager->dispatch($this->_eventPrefix . '_validate_after', $this->_getEventData());

        return $result;
    }

    /**
     * Retrieve product websites identifiers
     *
     * @return array|null
     */
    public function getWebsiteIds(): ?array
    {
        if (!$this->hasWebsiteIds()) {
            /** @var \Smile\CustomEntity\Model\ResourceModel\CustomEntity $resource */
            $resource = $this->_getResource();
            $ids = $resource->getWebsiteIds($this);
            $this->setWebsiteIds($ids);
        }

        return $this->getData('website_ids');
    }

    /**
     * Get all sore ids where product is presented
     *
     * @return array|null
     */
    public function getStoreIds(): ?array
    {
        if (!$this->hasStoreIds()) {
            $storeIds = [];
            $websiteIds = $this->getWebsiteIds();
            if ($websiteIds) {
                foreach ($websiteIds as $websiteId) {
                    /** @var Website $website */
                    $website = $this->_storeManager->getWebsite($websiteId);
                    $websiteStores = $website->getStoreIds();
                    // @codingStandardsIgnoreLine
                    $storeIds = array_merge($storeIds, $websiteStores);
                }
            }
            $this->setStoreIds($storeIds);
        }

        return $this->getData('store_ids');
    }

    /**
     * Retrieve existing extension attributes object or create a new one.
     */
    public function getExtensionAttributes(): ?CustomEntityExtensionInterface
    {
        /** @var CustomEntityExtensionInterface $extensionAttributes */
        $extensionAttributes = $this->_getExtensionAttributes();
        return $extensionAttributes;
    }

    /**
     * Set an extension attributes object.
     *
     * @param CustomEntityExtensionInterface $extensionAttributes Extension attributes.
     * @return $this
     */
    public function setExtensionAttributes(
        CustomEntityExtensionInterface $extensionAttributes
    ): self {
        return $this->_setExtensionAttributes($extensionAttributes);
    }

    /**
     * Returns custom entity ids match with url key and attribute set id.
     *
     * @param string   $urlKey         Url key.
     * @param int|null $attributeSetId Attribute set id.
     * @return mixed
     * @throws NoSuchEntityException
     * @SuppressWarnings(PHPMD.StaticAccess)
     */
    public function checkIdentifier(string $urlKey, ?int $attributeSetId = null)
    {
        $collection = $this->getCollection()
            ->addFieldToSelect('entity_id')
            ->addFieldToFilter('url_key', $urlKey)
            ->addFieldToFilter('is_active', '1')
            ->setPageSize(1);
        if ($attributeSetId !== null) {
            /** @var string $attributeSetId */
            $collection->addFieldToFilter('attribute_set_id', $attributeSetId);
        }
        if (!$collection->getSize()) {
            throw NoSuchEntityException::doubleField('url_key', $urlKey, 'attribute_set_id', $attributeSetId);
        }

        // @codingStandardsIgnoreLine add setPageSize MEQP1.Performance.InefficientMethods.FoundGetFirstItem
        return $collection->getFirstItem()->getId();
    }

    /**
     * @inheritdoc
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
     */
    protected function _construct(): void
    {
        $this->_init(\Smile\CustomEntity\Model\ResourceModel\CustomEntity::class);
    }

    /**
     * @inheritdoc
     */
    protected function getCustomAttributesCodes()
    {
        if ($this->customAttributesCodes === null) {
            $this->customAttributesCodes = $this->getEavAttributesCodes($this->metadataService);
            $this->customAttributesCodes = array_diff($this->customAttributesCodes, $this->interfaceAttributes);
        }

        return $this->customAttributesCodes;
    }
}