123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Model;
- use Magento\Framework\Phrase;
- /**
- * Abstract model class
- *
- * @api
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- * @SuppressWarnings(PHPMD.NumberOfChildren)
- * @SuppressWarnings(PHPMD.TooManyFields)
- * @since 100.0.2
- */
- abstract class AbstractModel extends \Magento\Framework\DataObject
- {
- /**
- * Prefix of model events names
- *
- * @var string
- */
- protected $_eventPrefix = 'core_abstract';
- /**
- * Parameter name in event
- *
- * In observe method you can use $observer->getEvent()->getObject() in this case
- *
- * @var string
- */
- protected $_eventObject = 'object';
- /**
- * Name of object id field
- *
- * @var string
- */
- protected $_idFieldName = 'id';
- /**
- * Data changes flag (true after setData|unsetData call)
- * @var bool
- */
- protected $_hasDataChanges = false;
- /**
- * Original data that was loaded
- *
- * @var array
- */
- protected $_origData;
- /**
- * Object delete flag
- *
- * @var bool
- */
- protected $_isDeleted = false;
- /**
- * Resource model instance
- *
- * @var \Magento\Framework\Model\ResourceModel\Db\AbstractDb
- */
- protected $_resource;
- /**
- * Resource collection
- *
- * @var \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
- */
- protected $_resourceCollection;
- /**
- * Name of the resource model
- *
- * @var string
- */
- protected $_resourceName;
- /**
- * Name of the resource collection model
- *
- * @var string
- */
- protected $_collectionName;
- /**
- * Model cache tag for clear cache in after save and after delete
- *
- * When you use true - all cache will be clean
- *
- * @var string|array|bool
- */
- protected $_cacheTag = false;
- /**
- * Flag which can stop data saving after before save
- * Can be used for next sequence: we check data in _beforeSave, if data are
- * not valid - we can set this flag to false value and save process will be stopped
- *
- * @var bool
- */
- protected $_dataSaveAllowed = true;
- /**
- * Flag which allow detect object state: is it new object (without id) or existing one (with id)
- *
- * @var bool
- */
- protected $_isObjectNew = null;
- /**
- * Validator for checking the model state before saving it
- *
- * @var \Zend_Validate_Interface|bool|null
- */
- protected $_validatorBeforeSave = null;
- /**
- * Application Event Dispatcher
- *
- * @var \Magento\Framework\Event\ManagerInterface
- */
- protected $_eventManager;
- /**
- * Application Cache Manager
- *
- * @var \Magento\Framework\App\CacheInterface
- */
- protected $_cacheManager;
- /**
- * @var \Magento\Framework\Registry
- */
- protected $_registry;
- /**
- * @var \Psr\Log\LoggerInterface
- */
- protected $_logger;
- /**
- * @var \Magento\Framework\App\State
- */
- protected $_appState;
- /**
- * @var \Magento\Framework\Model\ActionValidator\RemoveAction
- */
- protected $_actionValidator;
- /**
- * Array to store object's original data
- *
- * @var array
- */
- protected $storedData = [];
- /**
- * @param \Magento\Framework\Model\Context $context
- * @param \Magento\Framework\Registry $registry
- * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
- * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
- * @param array $data
- */
- public function __construct(
- \Magento\Framework\Model\Context $context,
- \Magento\Framework\Registry $registry,
- \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
- \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
- array $data = []
- ) {
- $this->_registry = $registry;
- $this->_appState = $context->getAppState();
- $this->_eventManager = $context->getEventDispatcher();
- $this->_cacheManager = $context->getCacheManager();
- $this->_resource = $resource;
- $this->_resourceCollection = $resourceCollection;
- $this->_logger = $context->getLogger();
- $this->_actionValidator = $context->getActionValidator();
- if (method_exists($this->_resource, 'getIdFieldName')
- || $this->_resource instanceof \Magento\Framework\DataObject
- ) {
- $this->_idFieldName = $this->_getResource()->getIdFieldName();
- }
- parent::__construct($data);
- $this->_construct();
- }
- /**
- * Model construct that should be used for object initialization
- *
- * @return void
- */
- protected function _construct()
- {
- }
- /**
- * Standard model initialization
- *
- * @param string $resourceModel
- * @return void
- */
- protected function _init($resourceModel)
- {
- $this->_setResourceModel($resourceModel);
- $this->_idFieldName = $this->_getResource()->getIdFieldName();
- }
- /**
- * Remove unneeded properties from serialization
- *
- * @return string[]
- */
- public function __sleep()
- {
- $properties = array_keys(get_object_vars($this));
- $properties = array_diff(
- $properties,
- [
- '_eventManager',
- '_cacheManager',
- '_registry',
- '_appState',
- '_actionValidator',
- '_logger',
- '_resourceCollection',
- '_resource',
- ]
- );
- return $properties;
- }
- /**
- * Init not serializable fields
- *
- * @return void
- */
- public function __wakeup()
- {
- $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
- $this->_registry = $objectManager->get(\Magento\Framework\Registry::class);
- $context = $objectManager->get(\Magento\Framework\Model\Context::class);
- if ($context instanceof \Magento\Framework\Model\Context) {
- $this->_appState = $context->getAppState();
- $this->_eventManager = $context->getEventDispatcher();
- $this->_cacheManager = $context->getCacheManager();
- $this->_logger = $context->getLogger();
- $this->_actionValidator = $context->getActionValidator();
- }
- }
- /**
- * Id field name setter
- *
- * @param string $name
- * @return $this
- */
- public function setIdFieldName($name)
- {
- $this->_idFieldName = $name;
- return $this;
- }
- /**
- * Id field name getter
- *
- * @return string
- */
- public function getIdFieldName()
- {
- return $this->_idFieldName;
- }
- /**
- * Identifier getter
- *
- * @return mixed
- */
- public function getId()
- {
- return $this->_getData($this->_idFieldName);
- }
- /**
- * Identifier setter
- *
- * @param mixed $value
- * @return $this
- */
- public function setId($value)
- {
- $this->setData($this->_idFieldName, $value);
- return $this;
- }
- /**
- * Set _isDeleted flag value (if $isDeleted parameter is defined) and return current flag value
- *
- * @param boolean $isDeleted
- * @return bool
- */
- public function isDeleted($isDeleted = null)
- {
- $result = $this->_isDeleted;
- if ($isDeleted !== null) {
- $this->_isDeleted = $isDeleted;
- }
- return $result;
- }
- /**
- * Check if initial object data was changed.
- *
- * Initial data is coming to object constructor.
- * Flag value should be set up to true after any external data changes
- *
- * @return bool
- */
- public function hasDataChanges()
- {
- return $this->_hasDataChanges;
- }
- /**
- * Overwrite data in the object.
- *
- * The $key parameter can be string or array.
- * If $key is string, the attribute value will be overwritten by $value
- *
- * If $key is an array, it will overwrite all the data in the object.
- *
- * @param string|array $key
- * @param mixed $value
- * @return $this
- */
- public function setData($key, $value = null)
- {
- if ($key === (array)$key) {
- if ($this->_data !== $key) {
- $this->_hasDataChanges = true;
- }
- $this->_data = $key;
- } else {
- if (!array_key_exists($key, $this->_data) || $this->_data[$key] !== $value) {
- $this->_hasDataChanges = true;
- }
- $this->_data[$key] = $value;
- }
- return $this;
- }
- /**
- * Unset data from the object.
- *
- * @param null|string|array $key
- * @return $this
- */
- public function unsetData($key = null)
- {
- if ($key === null) {
- $this->setData([]);
- } elseif (is_string($key)) {
- if (isset($this->_data[$key]) || array_key_exists($key, $this->_data)) {
- $this->_hasDataChanges = true;
- unset($this->_data[$key]);
- }
- } elseif ($key === (array)$key) {
- foreach ($key as $element) {
- $this->unsetData($element);
- }
- }
- return $this;
- }
- /**
- * Clears data changes status
- *
- * @param bool $value
- * @return $this
- */
- public function setDataChanges($value)
- {
- $this->_hasDataChanges = (bool)$value;
- return $this;
- }
- /**
- * Get object original data
- *
- * @param string $key
- * @return mixed
- */
- public function getOrigData($key = null)
- {
- if ($key === null) {
- return $this->_origData;
- }
- if (isset($this->_origData[$key])) {
- return $this->_origData[$key];
- }
- return null;
- }
- /**
- * Initialize object original data
- *
- * @FIXME changing original data can't be available as public interface
- *
- * @param string $key
- * @param mixed $data
- * @return $this
- */
- public function setOrigData($key = null, $data = null)
- {
- if ($key === null) {
- $this->_origData = $this->_data;
- } else {
- $this->_origData[$key] = $data;
- }
- return $this;
- }
- /**
- * Compare object data with original data
- *
- * @param string $field
- * @return bool
- */
- public function dataHasChangedFor($field)
- {
- $newData = $this->getData($field);
- $origData = $this->getOrigData($field);
- return $newData != $origData;
- }
- /**
- * Set resource names
- *
- * If collection name is omitted, resource name will be used with _collection appended
- *
- * @param string $resourceName
- * @param string|null $collectionName
- * @return void
- */
- protected function _setResourceModel($resourceName, $collectionName = null)
- {
- $this->_resourceName = $resourceName;
- if ($collectionName === null) {
- $collectionName = $resourceName . '\\' . 'Collection';
- }
- $this->_collectionName = $collectionName;
- }
- /**
- * Get resource instance
- *
- * @throws \Magento\Framework\Exception\LocalizedException
- * @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
- * @deprecated 101.0.0 because resource models should be used directly
- */
- protected function _getResource()
- {
- if (empty($this->_resourceName) && empty($this->_resource)) {
- throw new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase('The resource isn\'t set.')
- );
- }
- return $this->_resource ?: \Magento\Framework\App\ObjectManager::getInstance()->get($this->_resourceName);
- }
- /**
- * Retrieve model resource name
- *
- * @return string
- */
- public function getResourceName()
- {
- return $this->_resource ? get_class($this->_resource) : ($this->_resourceName ? $this->_resourceName : null);
- }
- /**
- * Get collection instance
- *
- * @TODO MAGETWO-23541: Incorrect dependencies between Model\AbstractModel and Data\Collection\Db from Framework
- * @throws \Magento\Framework\Exception\LocalizedException
- * @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
- * @deprecated 101.0.0 because collections should be used directly via factory
- */
- public function getResourceCollection()
- {
- if (empty($this->_resourceCollection) && empty($this->_collectionName)) {
- throw new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase('Model collection resource name is not defined.')
- );
- }
- return $this->_resourceCollection ? clone $this
- ->_resourceCollection : \Magento\Framework\App\ObjectManager::getInstance()
- ->create(
- $this->_collectionName
- );
- }
- /**
- * Retrieve collection instance
- *
- * @TODO MAGETWO-23541: Incorrect dependencies between Model\AbstractModel and Data\Collection\Db from Framework
- * @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
- * @deprecated 101.0.0 because collections should be used directly via factory
- */
- public function getCollection()
- {
- return $this->getResourceCollection();
- }
- /**
- * Load object data
- *
- * @param integer $modelId
- * @param null|string $field
- * @return $this
- * @deprecated 100.1.0 because entities must not be responsible for their own loading.
- * Service contracts should persist entities. Use resource model "load" or collections to implement
- * service contract model loading operations.
- */
- public function load($modelId, $field = null)
- {
- $this->_getResource()->load($this, $modelId, $field);
- return $this;
- }
- /**
- * Get array of objects transferred to default events processing
- *
- * @return array
- */
- protected function _getEventData()
- {
- return [
- 'data_object' => $this,
- $this->_eventObject => $this,
- ];
- }
- /**
- * Processing object before load data
- *
- * @param int $modelId
- * @param null|string $field
- * @return $this
- */
- protected function _beforeLoad($modelId, $field = null)
- {
- $params = ['object' => $this, 'field' => $field, 'value' => $modelId];
- $this->_eventManager->dispatch('model_load_before', $params);
- $params = array_merge($params, $this->_getEventData());
- $this->_eventManager->dispatch($this->_eventPrefix . '_load_before', $params);
- return $this;
- }
- /**
- * Processing object after load data
- *
- * @return $this
- */
- protected function _afterLoad()
- {
- $this->_eventManager->dispatch('model_load_after', ['object' => $this]);
- $this->_eventManager->dispatch($this->_eventPrefix . '_load_after', $this->_getEventData());
- return $this;
- }
- /**
- * Process operation before object load
- *
- * @param string $identifier
- * @param string|null $field
- * @return void
- * @since 101.0.0
- */
- public function beforeLoad($identifier, $field = null)
- {
- $this->_beforeLoad($identifier, $field);
- }
- /**
- * Object after load processing. Implemented as public interface for supporting objects after load in collections
- *
- * @return $this
- */
- public function afterLoad()
- {
- $this->_afterLoad();
- $this->updateStoredData();
- return $this;
- }
- /**
- * Check whether model has changed data.
- * Can be overloaded in child classes to perform advanced check whether model needs to be saved
- * e.g. using resourceModel->hasDataChanged() or any other technique
- *
- * @return boolean
- */
- protected function _hasModelChanged()
- {
- return $this->hasDataChanges();
- }
- /**
- * Check if save is allowed
- *
- * @return bool
- */
- public function isSaveAllowed()
- {
- return (bool) $this->_dataSaveAllowed;
- }
- /**
- * Set flag property _hasDataChanges
- *
- * @param bool $flag
- * @return void
- */
- public function setHasDataChanges($flag)
- {
- $this->_hasDataChanges = $flag;
- }
- /**
- * Save object data
- *
- * @return $this
- * @throws \Exception
- *
- * @deprecated 100.1.0 because entities must not be responsible for their own persistence.
- * Service contracts should persist entities. Use resource model "save" to implement
- * service contract persistence operations.
- */
- public function save()
- {
- $this->_getResource()->save($this);
- return $this;
- }
- /**
- * Callback function which called after transaction commit in resource model
- *
- * @return $this
- */
- public function afterCommitCallback()
- {
- $this->_eventManager->dispatch('model_save_commit_after', ['object' => $this]);
- $this->_eventManager->dispatch($this->_eventPrefix . '_save_commit_after', $this->_getEventData());
- return $this;
- }
- /**
- * Check object state (true - if it is object without id on object just created)
- * This method can help detect if object just created in _afterSave method
- * problem is what in after save object has id and we can't detect what object was
- * created in this transaction
- *
- * @param bool|null $flag
- * @return bool
- */
- public function isObjectNew($flag = null)
- {
- if ($flag !== null) {
- $this->_isObjectNew = $flag;
- }
- if ($this->_isObjectNew !== null) {
- return $this->_isObjectNew;
- }
- return !(bool)$this->getId();
- }
- /**
- * Processing object before save data
- *
- * @return $this
- */
- public function beforeSave()
- {
- if (!$this->getId()) {
- $this->isObjectNew(true);
- }
- $this->_eventManager->dispatch('model_save_before', ['object' => $this]);
- $this->_eventManager->dispatch($this->_eventPrefix . '_save_before', $this->_getEventData());
- return $this;
- }
- /**
- * Validate model before saving it
- *
- * @return $this
- * @throws \Magento\Framework\Validator\Exception
- */
- public function validateBeforeSave()
- {
- $validator = $this->_getValidatorBeforeSave();
- if ($validator && !$validator->isValid($this)) {
- $errors = $validator->getMessages();
- $exception = new \Magento\Framework\Validator\Exception(
- new Phrase(implode(PHP_EOL, $errors))
- );
- foreach ($errors as $errorMessage) {
- $exception->addMessage(new \Magento\Framework\Message\Error($errorMessage));
- }
- throw $exception;
- }
- return $this;
- }
- /**
- * Returns validator, which contains all rules to validate this model.
- *
- * Returns FALSE, if no validation rules exist.
- *
- * @return \Zend_Validate_Interface|false
- */
- protected function _getValidatorBeforeSave()
- {
- if ($this->_validatorBeforeSave === null) {
- $this->_validatorBeforeSave = $this->_createValidatorBeforeSave();
- }
- return $this->_validatorBeforeSave;
- }
- /**
- * Creates validator for the model with all validation rules in it.
- *
- * Returns FALSE, if no validation rules exist.
- *
- * @return \Zend_Validate_Interface|bool
- */
- protected function _createValidatorBeforeSave()
- {
- $modelRules = $this->_getValidationRulesBeforeSave();
- $resourceRules = $this->_getResource()->getValidationRulesBeforeSave();
- if (!$modelRules && !$resourceRules) {
- return false;
- }
- if ($modelRules && $resourceRules) {
- $validator = new \Zend_Validate();
- $validator->addValidator($modelRules);
- $validator->addValidator($resourceRules);
- } elseif ($modelRules) {
- $validator = $modelRules;
- } else {
- $validator = $resourceRules;
- }
- return $validator;
- }
- /**
- * Template method to return validate rules for the entity
- *
- * @return \Zend_Validate_Interface|null
- */
- protected function _getValidationRulesBeforeSave()
- {
- return null;
- }
- /**
- * Get list of cache tags applied to model object.
- *
- * Return false if cache tags are not supported by model
- *
- * @return array|false
- */
- public function getCacheTags()
- {
- $tags = false;
- if ($this->_cacheTag) {
- if ($this->_cacheTag === true) {
- $tags = [];
- } else {
- if (is_array($this->_cacheTag)) {
- $tags = $this->_cacheTag;
- } else {
- $tags = [$this->_cacheTag];
- }
- }
- }
- return $tags;
- }
- /**
- * Remove model object related cache
- *
- * @return $this
- */
- public function cleanModelCache()
- {
- $tags = $this->getCacheTags();
- if ($tags !== false) {
- $this->_cacheManager->clean($tags);
- }
- return $this;
- }
- /**
- * Processing object after save data
- *
- * @return $this
- */
- public function afterSave()
- {
- $this->cleanModelCache();
- $this->_eventManager->dispatch('model_save_after', ['object' => $this]);
- $this->_eventManager->dispatch('clean_cache_by_tags', ['object' => $this]);
- $this->_eventManager->dispatch($this->_eventPrefix . '_save_after', $this->_getEventData());
- $this->updateStoredData();
- return $this;
- }
- /**
- * Delete object from database
- *
- * @return $this
- * @throws \Exception
- * @deprecated 100.1.0 because entities must not be responsible for their own deletion.
- * Service contracts should delete entities. Use resource model "delete" method to implement
- * service contract persistence operations.
- */
- public function delete()
- {
- $this->_getResource()->delete($this);
- return $this;
- }
- /**
- * Processing object before delete data
- *
- * @return $this
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function beforeDelete()
- {
- if (!$this->_actionValidator->isAllowed($this)) {
- throw new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase('Delete operation is forbidden for current area')
- );
- }
- $this->_eventManager->dispatch('model_delete_before', ['object' => $this]);
- $this->_eventManager->dispatch($this->_eventPrefix . '_delete_before', $this->_getEventData());
- $this->cleanModelCache();
- return $this;
- }
- /**
- * Processing object after delete data
- *
- * @return $this
- */
- public function afterDelete()
- {
- $this->_eventManager->dispatch('model_delete_after', ['object' => $this]);
- $this->_eventManager->dispatch('clean_cache_by_tags', ['object' => $this]);
- $this->_eventManager->dispatch($this->_eventPrefix . '_delete_after', $this->_getEventData());
- $this->storedData = [];
- return $this;
- }
- /**
- * Processing manipulation after main transaction commit
- *
- * @return $this
- */
- public function afterDeleteCommit()
- {
- $this->_eventManager->dispatch('model_delete_commit_after', ['object' => $this]);
- $this->_eventManager->dispatch($this->_eventPrefix . '_delete_commit_after', $this->_getEventData());
- return $this;
- }
- /**
- * Retrieve model resource
- *
- * @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
- * @deprecated 101.0.0 because resource models should be used directly
- */
- public function getResource()
- {
- return $this->_getResource();
- }
- /**
- * Retrieve entity id
- *
- * @return mixed
- */
- public function getEntityId()
- {
- return $this->_getData('entity_id');
- }
- /**
- * Set entity id
- *
- * @param int $entityId
- * @return $this
- */
- public function setEntityId($entityId)
- {
- return $this->setData('entity_id', $entityId);
- }
- /**
- * Clearing object for correct deleting by garbage collector
- *
- * @return $this
- */
- public function clearInstance()
- {
- $this->_clearReferences();
- $this->_eventManager->dispatch($this->_eventPrefix . '_clear', $this->_getEventData());
- $this->_clearData();
- return $this;
- }
- /**
- * Clearing cyclic references
- *
- * @return $this
- */
- protected function _clearReferences()
- {
- return $this;
- }
- /**
- * Clearing object's data
- *
- * @return $this
- */
- protected function _clearData()
- {
- return $this;
- }
- /**
- * Synchronize object's stored data with the actual data
- *
- * @return $this
- */
- private function updateStoredData()
- {
- if (isset($this->_data)) {
- $this->storedData = $this->_data;
- } else {
- $this->storedData = [];
- }
- return $this;
- }
- /**
- * Model StoredData getter
- *
- * @return array
- */
- public function getStoredData()
- {
- return $this->storedData;
- }
- /**
- * Returns _eventPrefix
- *
- * @return string
- */
- public function getEventPrefix()
- {
- return $this->_eventPrefix;
- }
- }
|