AbstractDb.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Model\ResourceModel\Db;
  7. use Magento\Framework\App\ResourceConnection;
  8. use Magento\Framework\Exception\AlreadyExistsException;
  9. use Magento\Framework\Exception\LocalizedException;
  10. use Magento\Framework\Model\ResourceModel\AbstractResource;
  11. use Magento\Framework\DB\Adapter\DuplicateException;
  12. use Magento\Framework\Phrase;
  13. /**
  14. * Abstract resource model
  15. *
  16. * @SuppressWarnings(PHPMD.NumberOfChildren)
  17. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  18. * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
  19. * @api
  20. * @since 100.0.2
  21. */
  22. abstract class AbstractDb extends AbstractResource
  23. {
  24. /**
  25. * Cached resources singleton
  26. *
  27. * @var \Magento\Framework\App\ResourceConnection
  28. */
  29. protected $_resources;
  30. /**
  31. * Prefix for resources that will be used in this resource model
  32. *
  33. * @var string
  34. */
  35. protected $connectionName = \Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION;
  36. /**
  37. * Connections cache for this resource model
  38. *
  39. * @var array
  40. */
  41. protected $_connections = [];
  42. /**
  43. * Resource model name that contains entities (names of tables)
  44. *
  45. * @var string
  46. */
  47. protected $_resourceModel;
  48. /**
  49. * Tables used in this resource model
  50. *
  51. * @var array
  52. */
  53. protected $_tables = [];
  54. /**
  55. * Main table name
  56. *
  57. * @var string
  58. */
  59. protected $_mainTable;
  60. /**
  61. * Main table primary key field name
  62. *
  63. * @var string
  64. */
  65. protected $_idFieldName;
  66. /**
  67. * Primary key auto increment flag
  68. *
  69. * @var bool
  70. */
  71. protected $_isPkAutoIncrement = true;
  72. /**
  73. * Use is object new method for save of object
  74. *
  75. * @var bool
  76. */
  77. protected $_useIsObjectNew = false;
  78. /**
  79. * Fields of main table
  80. *
  81. * @var array
  82. */
  83. protected $_mainTableFields;
  84. /**
  85. * Main table unique keys field names
  86. * could array(
  87. * array('field' => 'db_field_name1', 'title' => 'Field 1 should be unique')
  88. * array('field' => 'db_field_name2', 'title' => 'Field 2 should be unique')
  89. * array(
  90. * 'field' => array('db_field_name3', 'db_field_name3'),
  91. * 'title' => 'Field 3 and Field 4 combination should be unique'
  92. * )
  93. * )
  94. * or string 'my_field_name' - will be autoconverted to
  95. * array( array( 'field' => 'my_field_name', 'title' => 'my_field_name' ) )
  96. *
  97. * @var array
  98. */
  99. protected $_uniqueFields = null;
  100. /**
  101. * Serializable fields declaration
  102. * Structure: array(
  103. * <field_name> => array(
  104. * <default_value_for_serialization>,
  105. * <default_for_unserialization>,
  106. * <whether_to_unset_empty_when serializing> // optional parameter
  107. * ),
  108. * )
  109. *
  110. * @var array
  111. */
  112. protected $_serializableFields = [];
  113. /**
  114. * @var TransactionManagerInterface
  115. */
  116. protected $transactionManager;
  117. /**
  118. * @var ObjectRelationProcessor
  119. */
  120. protected $objectRelationProcessor;
  121. /**
  122. * Constructor
  123. *
  124. * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
  125. * @param string $connectionName
  126. */
  127. public function __construct(
  128. \Magento\Framework\Model\ResourceModel\Db\Context $context,
  129. $connectionName = null
  130. ) {
  131. $this->transactionManager = $context->getTransactionManager();
  132. $this->_resources = $context->getResources();
  133. $this->objectRelationProcessor = $context->getObjectRelationProcessor();
  134. if ($connectionName !== null) {
  135. $this->connectionName = $connectionName;
  136. }
  137. parent::__construct();
  138. }
  139. /**
  140. * Provide variables to serialize
  141. *
  142. * @return array
  143. */
  144. public function __sleep()
  145. {
  146. $properties = array_keys(get_object_vars($this));
  147. $properties = array_diff($properties, ['_resources', '_connections']);
  148. return $properties;
  149. }
  150. /**
  151. * Restore global dependencies
  152. *
  153. * @return void
  154. */
  155. public function __wakeup()
  156. {
  157. $this->_resources = \Magento\Framework\App\ObjectManager::getInstance()
  158. ->get(\Magento\Framework\App\ResourceConnection::class);
  159. }
  160. /**
  161. * Standard resource model initialization
  162. *
  163. * @param string $mainTable
  164. * @param string $idFieldName
  165. * @return void
  166. */
  167. protected function _init($mainTable, $idFieldName)
  168. {
  169. $this->_setMainTable($mainTable, $idFieldName);
  170. }
  171. /**
  172. * Initialize connections and tables for this resource model
  173. * If one or both arguments are string, will be used as prefix
  174. * If $tables is null and $connections is string, $tables will be the same
  175. *
  176. * @param string|array $connections
  177. * @param string|array|null $tables
  178. * @return $this
  179. */
  180. protected function _setResource($connections, $tables = null)
  181. {
  182. if (is_array($connections)) {
  183. foreach ($connections as $key => $value) {
  184. $this->_connections[$key] = $this->_resources->getConnection($value);
  185. }
  186. } elseif (is_string($connections)) {
  187. $this->connectionName = $connections;
  188. }
  189. if ($tables === null && is_string($connections)) {
  190. $this->_resourceModel = $this->connectionName;
  191. } elseif (is_array($tables)) {
  192. foreach ($tables as $key => $value) {
  193. $this->_tables[$key] = $this->_resources->getTableName($value);
  194. }
  195. } elseif (is_string($tables)) {
  196. $this->_resourceModel = $tables;
  197. }
  198. return $this;
  199. }
  200. /**
  201. * Set main entity table name and primary key field name
  202. * If field name is omitted {table_name}_id will be used
  203. *
  204. * @param string $mainTable
  205. * @param string|null $idFieldName
  206. * @return $this
  207. */
  208. protected function _setMainTable($mainTable, $idFieldName = null)
  209. {
  210. $this->_mainTable = $mainTable;
  211. if (null === $idFieldName) {
  212. $idFieldName = $mainTable . '_id';
  213. }
  214. $this->_idFieldName = $idFieldName;
  215. return $this;
  216. }
  217. /**
  218. * Get primary key field name
  219. *
  220. * @throws LocalizedException
  221. * @return string
  222. * @api
  223. */
  224. public function getIdFieldName()
  225. {
  226. if (empty($this->_idFieldName)) {
  227. throw new LocalizedException(new \Magento\Framework\Phrase('Empty identifier field name'));
  228. }
  229. return $this->_idFieldName;
  230. }
  231. /**
  232. * Returns main table name - extracted from "module/table" style and
  233. * validated by db adapter
  234. *
  235. * @throws LocalizedException
  236. * @return string
  237. * @api
  238. */
  239. public function getMainTable()
  240. {
  241. if (empty($this->_mainTable)) {
  242. throw new LocalizedException(new \Magento\Framework\Phrase('Empty main table name'));
  243. }
  244. return $this->getTable($this->_mainTable);
  245. }
  246. /**
  247. * Get real table name for db table, validated by db adapter
  248. *
  249. * @param string $tableName
  250. * @return string
  251. * @api
  252. */
  253. public function getTable($tableName)
  254. {
  255. if (is_array($tableName)) {
  256. $cacheName = join('@', $tableName);
  257. list($tableName, $entitySuffix) = $tableName;
  258. } else {
  259. $cacheName = $tableName;
  260. $entitySuffix = null;
  261. }
  262. if ($entitySuffix !== null) {
  263. $tableName .= '_' . $entitySuffix;
  264. }
  265. if (!isset($this->_tables[$cacheName])) {
  266. $connectionName = $this->connectionName;
  267. $this->_tables[$cacheName] = $this->_resources->getTableName($tableName, $connectionName);
  268. }
  269. return $this->_tables[$cacheName];
  270. }
  271. /**
  272. * Get connection by resource name
  273. *
  274. * @param string $resourceName
  275. * @return \Magento\Framework\DB\Adapter\AdapterInterface|false
  276. */
  277. protected function _getConnection($resourceName)
  278. {
  279. if (isset($this->_connections[$resourceName])) {
  280. return $this->_connections[$resourceName];
  281. }
  282. $fullResourceName = ($this->connectionName ? $this->connectionName . '_' : '') . $resourceName;
  283. $connectionInstance = $this->_resources->getConnection($fullResourceName);
  284. // cache only active connections to detect inactive ones as soon as they become active
  285. if ($connectionInstance) {
  286. $this->_connections[$resourceName] = $connectionInstance;
  287. }
  288. return $connectionInstance;
  289. }
  290. /**
  291. * Get connection
  292. *
  293. * @return \Magento\Framework\DB\Adapter\AdapterInterface|false
  294. */
  295. public function getConnection()
  296. {
  297. $fullResourceName = ($this->connectionName ? $this->connectionName : ResourceConnection::DEFAULT_CONNECTION);
  298. return $this->_resources->getConnection($fullResourceName);
  299. }
  300. /**
  301. * Load an object
  302. *
  303. * @param \Magento\Framework\Model\AbstractModel $object
  304. * @param mixed $value
  305. * @param string $field field to load by (defaults to model id)
  306. * @return $this
  307. */
  308. public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null)
  309. {
  310. $object->beforeLoad($value, $field);
  311. if ($field === null) {
  312. $field = $this->getIdFieldName();
  313. }
  314. $connection = $this->getConnection();
  315. if ($connection && $value !== null) {
  316. $select = $this->_getLoadSelect($field, $value, $object);
  317. $data = $connection->fetchRow($select);
  318. if ($data) {
  319. $object->setData($data);
  320. }
  321. }
  322. $this->unserializeFields($object);
  323. $this->_afterLoad($object);
  324. $object->afterLoad();
  325. $object->setOrigData();
  326. $object->setHasDataChanges(false);
  327. return $this;
  328. }
  329. /**
  330. * Retrieve select object for load object data
  331. *
  332. * @param string $field
  333. * @param mixed $value
  334. * @param \Magento\Framework\Model\AbstractModel $object
  335. * @return \Magento\Framework\DB\Select
  336. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  337. */
  338. protected function _getLoadSelect($field, $value, $object)
  339. {
  340. $field = $this->getConnection()->quoteIdentifier(sprintf('%s.%s', $this->getMainTable(), $field));
  341. $select = $this->getConnection()->select()->from($this->getMainTable())->where($field . '=?', $value);
  342. return $select;
  343. }
  344. /**
  345. * Save object object data
  346. *
  347. * @param \Magento\Framework\Model\AbstractModel $object
  348. * @return $this
  349. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  350. * @throws \Exception
  351. * @throws AlreadyExistsException
  352. * @api
  353. */
  354. public function save(\Magento\Framework\Model\AbstractModel $object)
  355. {
  356. if ($object->isDeleted()) {
  357. return $this->delete($object);
  358. }
  359. $this->beginTransaction();
  360. try {
  361. if (!$this->isModified($object)) {
  362. $this->processNotModifiedSave($object);
  363. $this->commit();
  364. $object->setHasDataChanges(false);
  365. return $this;
  366. }
  367. $object->validateBeforeSave();
  368. $object->beforeSave();
  369. if ($object->isSaveAllowed()) {
  370. $this->_serializeFields($object);
  371. $this->_beforeSave($object);
  372. $this->_checkUnique($object);
  373. $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
  374. if ($this->isObjectNotNew($object)) {
  375. $this->updateObject($object);
  376. } else {
  377. $this->saveNewObject($object);
  378. }
  379. $this->unserializeFields($object);
  380. $this->processAfterSaves($object);
  381. }
  382. $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
  383. $object->setHasDataChanges(false);
  384. } catch (DuplicateException $e) {
  385. $this->rollBack();
  386. $object->setHasDataChanges(true);
  387. throw new AlreadyExistsException(new Phrase('Unique constraint violation found'), $e);
  388. } catch (\Exception $e) {
  389. $this->rollBack();
  390. $object->setHasDataChanges(true);
  391. throw $e;
  392. }
  393. return $this;
  394. }
  395. /**
  396. * Delete the object
  397. *
  398. * @param \Magento\Framework\Model\AbstractModel $object
  399. * @return $this
  400. * @throws \Exception
  401. */
  402. public function delete(\Magento\Framework\Model\AbstractModel $object)
  403. {
  404. $connection = $this->transactionManager->start($this->getConnection());
  405. try {
  406. $object->beforeDelete();
  407. $this->_beforeDelete($object);
  408. $this->objectRelationProcessor->delete(
  409. $this->transactionManager,
  410. $connection,
  411. $this->getMainTable(),
  412. $this->getConnection()->quoteInto($this->getIdFieldName() . '=?', $object->getId()),
  413. $object->getData()
  414. );
  415. $this->_afterDelete($object);
  416. $object->isDeleted(true);
  417. $object->afterDelete();
  418. $this->transactionManager->commit();
  419. $object->afterDeleteCommit();
  420. } catch (\Exception $e) {
  421. $this->transactionManager->rollBack();
  422. throw $e;
  423. }
  424. return $this;
  425. }
  426. /**
  427. * Add unique field restriction
  428. *
  429. * @param array|string $field
  430. * @return $this
  431. */
  432. public function addUniqueField($field)
  433. {
  434. if ($this->_uniqueFields === null) {
  435. $this->_initUniqueFields();
  436. }
  437. if (is_array($this->_uniqueFields)) {
  438. $this->_uniqueFields[] = $field;
  439. }
  440. return $this;
  441. }
  442. /**
  443. * Reset unique fields restrictions
  444. *
  445. * @return $this
  446. */
  447. public function resetUniqueField()
  448. {
  449. $this->_uniqueFields = [];
  450. return $this;
  451. }
  452. /**
  453. * Unserialize serializeable object fields
  454. *
  455. * @param \Magento\Framework\Model\AbstractModel $object
  456. * @return void
  457. * @SuppressWarnings(PHPMD.UnusedLocalVariable)
  458. */
  459. public function unserializeFields(\Magento\Framework\Model\AbstractModel $object)
  460. {
  461. foreach ($this->_serializableFields as $field => $parameters) {
  462. list($serializeDefault, $unserializeDefault) = $parameters;
  463. $this->_unserializeField($object, $field, $unserializeDefault);
  464. }
  465. }
  466. /**
  467. * Initialize unique fields
  468. *
  469. * @return $this
  470. */
  471. protected function _initUniqueFields()
  472. {
  473. $this->_uniqueFields = [];
  474. return $this;
  475. }
  476. /**
  477. * Get configuration of all unique fields
  478. *
  479. * @return array
  480. */
  481. public function getUniqueFields()
  482. {
  483. if ($this->_uniqueFields === null) {
  484. $this->_initUniqueFields();
  485. }
  486. return $this->_uniqueFields;
  487. }
  488. /**
  489. * Prepare data for save
  490. *
  491. * @param \Magento\Framework\Model\AbstractModel $object
  492. * @return array
  493. */
  494. protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $object)
  495. {
  496. return $this->_prepareDataForTable($object, $this->getMainTable());
  497. }
  498. /**
  499. * Check that model data fields that can be saved
  500. * has really changed comparing with origData
  501. *
  502. * @param \Magento\Framework\Model\AbstractModel $object
  503. * @return bool
  504. */
  505. public function hasDataChanged($object)
  506. {
  507. if (!$object->getOrigData()) {
  508. return true;
  509. }
  510. $fields = $this->getConnection()->describeTable($this->getMainTable());
  511. foreach (array_keys($fields) as $field) {
  512. if ($object->getOrigData($field) != $object->getData($field)) {
  513. return true;
  514. }
  515. }
  516. return false;
  517. }
  518. /**
  519. * Prepare value for save
  520. *
  521. * @param mixed $value
  522. * @param string $type
  523. * @return mixed
  524. */
  525. protected function _prepareValueForSave($value, $type)
  526. {
  527. return $this->_prepareTableValueForSave($value, $type);
  528. }
  529. /**
  530. * Check for unique values existence
  531. *
  532. * @param \Magento\Framework\Model\AbstractModel $object
  533. * @return $this
  534. * @throws AlreadyExistsException
  535. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  536. * @SuppressWarnings(PHPMD.NPathComplexity)
  537. */
  538. protected function _checkUnique(\Magento\Framework\Model\AbstractModel $object)
  539. {
  540. $existent = [];
  541. $fields = $this->getUniqueFields();
  542. if (!empty($fields)) {
  543. if (!is_array($fields)) {
  544. $this->_uniqueFields = [['field' => $fields, 'title' => $fields]];
  545. }
  546. $data = new \Magento\Framework\DataObject($this->_prepareDataForSave($object));
  547. $select = $this->getConnection()->select()->from($this->getMainTable());
  548. foreach ($fields as $unique) {
  549. $select->reset(\Magento\Framework\DB\Select::WHERE);
  550. foreach ((array)$unique['field'] as $field) {
  551. $value = $data->getData($field);
  552. if ($value === null) {
  553. $select->where($field . ' IS NULL');
  554. } else {
  555. $select->where($field . '=?', trim($value));
  556. }
  557. }
  558. if ($object->getId() || (string)$object->getId() === '0') {
  559. $select->where($this->getIdFieldName() . '!=?', $object->getId());
  560. }
  561. $test = $this->getConnection()->fetchRow($select);
  562. if ($test) {
  563. $existent[] = $unique['title'];
  564. }
  565. }
  566. }
  567. if (!empty($existent)) {
  568. if (count($existent) == 1) {
  569. $error = new \Magento\Framework\Phrase('%1 already exists.', [$existent[0]]);
  570. } else {
  571. $error = new \Magento\Framework\Phrase('%1 already exist.', [implode(', ', $existent)]);
  572. }
  573. throw new AlreadyExistsException($error);
  574. }
  575. return $this;
  576. }
  577. /**
  578. * Perform actions after object load
  579. *
  580. * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object
  581. * @return $this
  582. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  583. */
  584. protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
  585. {
  586. return $this;
  587. }
  588. /**
  589. * Perform actions before object save
  590. *
  591. * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object
  592. * @return $this
  593. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  594. */
  595. protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
  596. {
  597. return $this;
  598. }
  599. /**
  600. * Perform actions after object save
  601. *
  602. * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object
  603. * @return $this
  604. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  605. */
  606. protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
  607. {
  608. return $this;
  609. }
  610. /**
  611. * Perform actions before object delete
  612. *
  613. * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object
  614. * @return $this
  615. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  616. */
  617. protected function _beforeDelete(\Magento\Framework\Model\AbstractModel $object)
  618. {
  619. return $this;
  620. }
  621. /**
  622. * Perform actions after object delete
  623. *
  624. * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object
  625. * @return $this
  626. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  627. */
  628. protected function _afterDelete(\Magento\Framework\Model\AbstractModel $object)
  629. {
  630. return $this;
  631. }
  632. /**
  633. * Serialize serializable fields of the object
  634. *
  635. * @param \Magento\Framework\Model\AbstractModel $object
  636. * @return void
  637. * @SuppressWarnings(PHPMD.UnusedLocalVariable)
  638. */
  639. protected function _serializeFields(\Magento\Framework\Model\AbstractModel $object)
  640. {
  641. foreach ($this->_serializableFields as $field => $parameters) {
  642. list($serializeDefault, $unserializeDefault) = $parameters;
  643. $this->_serializeField($object, $field, $serializeDefault, isset($parameters[2]));
  644. }
  645. }
  646. /**
  647. * Retrieve table checksum
  648. *
  649. * @param string|array $table
  650. * @return int|array|false
  651. */
  652. public function getChecksum($table)
  653. {
  654. if (!$this->getConnection()) {
  655. return false;
  656. }
  657. $checksum = $this->getConnection()->getTablesChecksum($table);
  658. if (count($checksum) == 1) {
  659. return $checksum[$table];
  660. }
  661. return $checksum;
  662. }
  663. /**
  664. * Get the array of data fields that was changed or added
  665. *
  666. * @param \Magento\Framework\Model\AbstractModel $object
  667. * @return array
  668. */
  669. protected function prepareDataForUpdate($object)
  670. {
  671. $data = $object->getData();
  672. foreach ($object->getStoredData() as $key => $value) {
  673. if (array_key_exists($key, $data) && $data[$key] === $value) {
  674. unset($data[$key]);
  675. }
  676. }
  677. $dataObject = clone $object;
  678. $dataObject->setData($data);
  679. $data = $this->_prepareDataForTable($dataObject, $this->getMainTable());
  680. unset($data[$this->getIdFieldName()]);
  681. unset($dataObject);
  682. return $data;
  683. }
  684. /**
  685. * Check if object is new
  686. *
  687. * @param \Magento\Framework\Model\AbstractModel $object
  688. * @return bool
  689. */
  690. protected function isObjectNotNew(\Magento\Framework\Model\AbstractModel $object)
  691. {
  692. return $object->getId() !== null && (!$this->_useIsObjectNew || !$object->isObjectNew());
  693. }
  694. /**
  695. * Save New Object
  696. *
  697. * @param \Magento\Framework\Model\AbstractModel $object
  698. * @throws LocalizedException
  699. * @return void
  700. */
  701. protected function saveNewObject(\Magento\Framework\Model\AbstractModel $object)
  702. {
  703. $bind = $this->_prepareDataForSave($object);
  704. if ($this->_isPkAutoIncrement) {
  705. unset($bind[$this->getIdFieldName()]);
  706. }
  707. $this->getConnection()->insert($this->getMainTable(), $bind);
  708. if ($this->_isPkAutoIncrement) {
  709. $object->setId($this->getConnection()->lastInsertId($this->getMainTable()));
  710. }
  711. if ($this->_useIsObjectNew) {
  712. $object->isObjectNew(false);
  713. }
  714. }
  715. /**
  716. * Update existing object
  717. *
  718. * @param \Magento\Framework\Model\AbstractModel $object
  719. * @throws LocalizedException
  720. * @return void
  721. */
  722. protected function updateObject(\Magento\Framework\Model\AbstractModel $object)
  723. {
  724. $condition = $this->getConnection()->quoteInto($this->getIdFieldName() . '=?', $object->getId());
  725. /**
  726. * Not auto increment primary key support
  727. */
  728. if ($this->_isPkAutoIncrement) {
  729. $data = $this->prepareDataForUpdate($object);
  730. if (!empty($data)) {
  731. $this->getConnection()->update($this->getMainTable(), $data, $condition);
  732. }
  733. } else {
  734. $select = $this->getConnection()->select()->from(
  735. $this->getMainTable(),
  736. [$this->getIdFieldName()]
  737. )->where(
  738. $condition
  739. );
  740. if ($this->getConnection()->fetchOne($select) !== false) {
  741. $data = $this->prepareDataForUpdate($object);
  742. if (!empty($data)) {
  743. $this->getConnection()->update($this->getMainTable(), $data, $condition);
  744. }
  745. } else {
  746. $this->getConnection()->insert(
  747. $this->getMainTable(),
  748. $this->_prepareDataForSave($object)
  749. );
  750. }
  751. }
  752. }
  753. /**
  754. * Sequences of after save call
  755. *
  756. * @param \Magento\Framework\Model\AbstractModel $object
  757. * @return void
  758. */
  759. protected function processAfterSaves(\Magento\Framework\Model\AbstractModel $object)
  760. {
  761. $this->_afterSave($object);
  762. $object->afterSave();
  763. }
  764. /**
  765. * Check if object was modified
  766. *
  767. * @param \Magento\Framework\Model\AbstractModel $object
  768. * @return bool
  769. */
  770. protected function isModified(\Magento\Framework\Model\AbstractModel $object)
  771. {
  772. return $object->hasDataChanges();
  773. }
  774. /**
  775. * Process object which was modified
  776. *
  777. * @param \Magento\Framework\Model\AbstractModel $object
  778. * @return $this
  779. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  780. */
  781. protected function processNotModifiedSave(\Magento\Framework\Model\AbstractModel $object)
  782. {
  783. return $this;
  784. }
  785. /**
  786. * Perform actions after entity load
  787. *
  788. * @param \Magento\Framework\DataObject $object
  789. * @return void
  790. */
  791. public function afterLoad(\Magento\Framework\DataObject $object)
  792. {
  793. $this->_afterLoad($object);
  794. }
  795. /**
  796. * Perform actions before entity save
  797. *
  798. * @param \Magento\Framework\DataObject $object
  799. * @return void
  800. * @since 100.1.0
  801. */
  802. public function beforeSave(\Magento\Framework\DataObject $object)
  803. {
  804. $this->_beforeSave($object);
  805. }
  806. /**
  807. * Perform actions after entity save
  808. *
  809. * @param \Magento\Framework\DataObject $object
  810. * @return void
  811. * @since 100.1.0
  812. */
  813. public function afterSave(\Magento\Framework\DataObject $object)
  814. {
  815. $this->_afterSave($object);
  816. }
  817. /**
  818. * Perform actions before entity delete
  819. *
  820. * @param \Magento\Framework\DataObject $object
  821. * @return void
  822. * @since 100.1.0
  823. */
  824. public function beforeDelete(\Magento\Framework\DataObject $object)
  825. {
  826. $this->_beforeDelete($object);
  827. }
  828. /**
  829. * Perform actions after entity delete
  830. *
  831. * @param \Magento\Framework\DataObject $object
  832. * @return void
  833. * @since 100.1.0
  834. */
  835. public function afterDelete(\Magento\Framework\DataObject $object)
  836. {
  837. $this->_afterDelete($object);
  838. }
  839. /**
  840. * Serialize serializable fields of the object
  841. *
  842. * @param \Magento\Framework\Model\AbstractModel $object
  843. * @return \Magento\Framework\Model\AbstractModel|void
  844. * @since 100.1.0
  845. */
  846. public function serializeFields(\Magento\Framework\Model\AbstractModel $object)
  847. {
  848. $this->_serializeFields($object);
  849. return $object;
  850. }
  851. }