AbstractResource.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Model\ResourceModel;
  7. use Magento\Framework\App\ObjectManager;
  8. use Magento\Framework\DataObject;
  9. use Magento\Framework\Model\CallbackPool;
  10. use Magento\Framework\Serialize\Serializer\Json;
  11. /**
  12. * Abstract resource model
  13. *
  14. * @api
  15. * @since 100.0.2
  16. */
  17. abstract class AbstractResource
  18. {
  19. /**
  20. * @var Json
  21. * @since 101.0.0
  22. */
  23. protected $serializer;
  24. /**
  25. * @var \Psr\Log\LoggerInterface
  26. * @since 102.0.0
  27. */
  28. protected $_logger;
  29. /**
  30. * Constructor
  31. */
  32. public function __construct()
  33. {
  34. /**
  35. * Please override this one instead of overriding real __construct constructor
  36. */
  37. $this->_construct();
  38. }
  39. /**
  40. * Resource initialization
  41. *
  42. * @return void
  43. */
  44. abstract protected function _construct();
  45. /**
  46. * Get connection
  47. *
  48. * @return \Magento\Framework\DB\Adapter\AdapterInterface
  49. */
  50. abstract public function getConnection();
  51. /**
  52. * Start resource transaction
  53. *
  54. * @return $this
  55. * @api
  56. */
  57. public function beginTransaction()
  58. {
  59. $this->getConnection()->beginTransaction();
  60. return $this;
  61. }
  62. /**
  63. * Subscribe some callback to transaction commit
  64. *
  65. * @param callable|array $callback
  66. * @return $this
  67. * @api
  68. */
  69. public function addCommitCallback($callback)
  70. {
  71. CallbackPool::attach(spl_object_hash($this->getConnection()), $callback);
  72. return $this;
  73. }
  74. /**
  75. * Commit resource transaction
  76. *
  77. * @return $this
  78. * @api
  79. */
  80. public function commit()
  81. {
  82. $this->getConnection()->commit();
  83. /**
  84. * Process after commit callbacks
  85. */
  86. if ($this->getConnection()->getTransactionLevel() === 0) {
  87. $callbacks = CallbackPool::get(spl_object_hash($this->getConnection()));
  88. try {
  89. foreach ($callbacks as $callback) {
  90. call_user_func($callback);
  91. }
  92. } catch (\Exception $e) {
  93. $this->getLogger()->critical($e);
  94. }
  95. }
  96. return $this;
  97. }
  98. /**
  99. * Roll back resource transaction
  100. *
  101. * @return $this
  102. * @api
  103. */
  104. public function rollBack()
  105. {
  106. $this->getConnection()->rollBack();
  107. CallbackPool::clear(spl_object_hash($this->getConnection()));
  108. return $this;
  109. }
  110. /**
  111. * Serialize specified field in an object
  112. *
  113. * @param DataObject $object
  114. * @param string $field
  115. * @param mixed $defaultValue
  116. * @param bool $unsetEmpty
  117. * @return $this
  118. */
  119. protected function _serializeField(DataObject $object, $field, $defaultValue = null, $unsetEmpty = false)
  120. {
  121. $value = $object->getData($field);
  122. if (empty($value) && $unsetEmpty) {
  123. $object->unsetData($field);
  124. } else {
  125. $object->setData($field, $this->getSerializer()->serialize($value ?: $defaultValue));
  126. }
  127. return $this;
  128. }
  129. /**
  130. * Unserialize \Magento\Framework\DataObject field in an object
  131. *
  132. * @param \Magento\Framework\Model\AbstractModel $object
  133. * @param string $field
  134. * @param mixed $defaultValue
  135. * @return void
  136. */
  137. protected function _unserializeField(DataObject $object, $field, $defaultValue = null)
  138. {
  139. $value = $object->getData($field);
  140. if ($value) {
  141. $value = $this->getSerializer()->unserialize($object->getData($field));
  142. if (empty($value)) {
  143. $object->setData($field, $defaultValue);
  144. } else {
  145. $object->setData($field, $value);
  146. }
  147. } else {
  148. $object->setData($field, $defaultValue);
  149. }
  150. }
  151. /**
  152. * Prepare data for passed table
  153. *
  154. * @param DataObject $object
  155. * @param string $table
  156. * @return array
  157. */
  158. protected function _prepareDataForTable(DataObject $object, $table)
  159. {
  160. $data = [];
  161. $fields = $this->getConnection()->describeTable($table);
  162. foreach (array_keys($fields) as $field) {
  163. if ($object->hasData($field)) {
  164. $fieldValue = $object->getData($field);
  165. if ($fieldValue instanceof \Zend_Db_Expr) {
  166. $data[$field] = $fieldValue;
  167. } else {
  168. if (null !== $fieldValue) {
  169. $fieldValue = $this->_prepareTableValueForSave($fieldValue, $fields[$field]['DATA_TYPE']);
  170. $data[$field] = $this->getConnection()->prepareColumnValue($fields[$field], $fieldValue);
  171. } elseif (!empty($fields[$field]['NULLABLE'])) {
  172. $data[$field] = null;
  173. }
  174. }
  175. }
  176. }
  177. return $data;
  178. }
  179. /**
  180. * Prepare value for save
  181. *
  182. * @param mixed $value
  183. * @param string $type
  184. * @return mixed
  185. */
  186. protected function _prepareTableValueForSave($value, $type)
  187. {
  188. $type = strtolower($type);
  189. if ($type == 'decimal' || $type == 'numeric' || $type == 'float') {
  190. $value = \Magento\Framework\App\ObjectManager::getInstance()->get(
  191. \Magento\Framework\Locale\FormatInterface::class
  192. )->getNumber(
  193. $value
  194. );
  195. }
  196. return $value;
  197. }
  198. /**
  199. * Template method to return validate rules to be executed before entity is saved
  200. *
  201. * @return null
  202. */
  203. public function getValidationRulesBeforeSave()
  204. {
  205. return null;
  206. }
  207. /**
  208. * Prepare the list of entity fields that should be selected from DB. Apply filtration based on active fieldset.
  209. *
  210. * @param \Magento\Framework\Model\AbstractModel $object
  211. * @param string $tableName
  212. * @return array|string
  213. */
  214. protected function _getColumnsForEntityLoad(\Magento\Framework\Model\AbstractModel $object, $tableName)
  215. {
  216. $fieldsetColumns = $object->getFieldset();
  217. if (!empty($fieldsetColumns)) {
  218. $connection = $this->getConnection();
  219. if ($connection instanceof \Magento\Framework\DB\Adapter\AdapterInterface) {
  220. $entityTableColumns = $connection->describeTable($tableName);
  221. $columns = array_intersect($fieldsetColumns, array_keys($entityTableColumns));
  222. }
  223. }
  224. if (empty($columns)) {
  225. /** In case when fieldset was specified but no columns were matched with it, ID column is returned. */
  226. $columns = empty($fieldsetColumns) ? '*' : [$object->getIdFieldName()];
  227. }
  228. return $columns;
  229. }
  230. /**
  231. * Get serializer
  232. *
  233. * @return Json
  234. * @deprecated 101.0.0
  235. * @since 101.0.0
  236. */
  237. protected function getSerializer()
  238. {
  239. if (null === $this->serializer) {
  240. $this->serializer = ObjectManager::getInstance()->get(Json::class);
  241. }
  242. return $this->serializer;
  243. }
  244. /**
  245. * Get logger
  246. *
  247. * @return \Psr\Log\LoggerInterface
  248. * @deprecated 101.0.1
  249. */
  250. private function getLogger()
  251. {
  252. if (null === $this->_logger) {
  253. $this->_logger = ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class);
  254. }
  255. return $this->_logger;
  256. }
  257. }