Block.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Cms\Model\ResourceModel;
  7. use Magento\Cms\Api\Data\BlockInterface;
  8. use Magento\Framework\DB\Select;
  9. use Magento\Framework\EntityManager\EntityManager;
  10. use Magento\Framework\EntityManager\MetadataPool;
  11. use Magento\Framework\Exception\LocalizedException;
  12. use Magento\Framework\Model\AbstractModel;
  13. use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
  14. use Magento\Framework\Model\ResourceModel\Db\Context;
  15. use Magento\Store\Model\Store;
  16. use Magento\Store\Model\StoreManagerInterface;
  17. /**
  18. * CMS block model
  19. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  20. */
  21. class Block extends AbstractDb
  22. {
  23. /**
  24. * Store manager
  25. *
  26. * @var StoreManagerInterface
  27. */
  28. protected $_storeManager;
  29. /**
  30. * @var EntityManager
  31. */
  32. protected $entityManager;
  33. /**
  34. * @var MetadataPool
  35. */
  36. protected $metadataPool;
  37. /**
  38. * @param Context $context
  39. * @param StoreManagerInterface $storeManager
  40. * @param EntityManager $entityManager
  41. * @param MetadataPool $metadataPool
  42. * @param string $connectionName
  43. */
  44. public function __construct(
  45. Context $context,
  46. StoreManagerInterface $storeManager,
  47. EntityManager $entityManager,
  48. MetadataPool $metadataPool,
  49. $connectionName = null
  50. ) {
  51. $this->_storeManager = $storeManager;
  52. $this->entityManager = $entityManager;
  53. $this->metadataPool = $metadataPool;
  54. parent::__construct($context, $connectionName);
  55. }
  56. /**
  57. * Initialize resource model
  58. *
  59. * @return void
  60. */
  61. protected function _construct()
  62. {
  63. $this->_init('cms_block', 'block_id');
  64. }
  65. /**
  66. * @inheritDoc
  67. */
  68. public function getConnection()
  69. {
  70. return $this->metadataPool->getMetadata(BlockInterface::class)->getEntityConnection();
  71. }
  72. /**
  73. * Perform operations before object save
  74. *
  75. * @param AbstractModel $object
  76. * @return $this
  77. * @throws LocalizedException
  78. */
  79. protected function _beforeSave(AbstractModel $object)
  80. {
  81. if (!$this->getIsUniqueBlockToStores($object)) {
  82. throw new LocalizedException(
  83. __('A block identifier with the same properties already exists in the selected store.')
  84. );
  85. }
  86. return $this;
  87. }
  88. /**
  89. * Get block id.
  90. *
  91. * @param AbstractModel $object
  92. * @param mixed $value
  93. * @param string $field
  94. * @return bool|int|string
  95. * @throws LocalizedException
  96. * @throws \Exception
  97. */
  98. private function getBlockId(AbstractModel $object, $value, $field = null)
  99. {
  100. $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
  101. if (!is_numeric($value) && $field === null) {
  102. $field = 'identifier';
  103. } elseif (!$field) {
  104. $field = $entityMetadata->getIdentifierField();
  105. }
  106. $entityId = $value;
  107. if ($field != $entityMetadata->getIdentifierField() || $object->getStoreId()) {
  108. $select = $this->_getLoadSelect($field, $value, $object);
  109. $select->reset(Select::COLUMNS)
  110. ->columns($this->getMainTable() . '.' . $entityMetadata->getIdentifierField())
  111. ->limit(1);
  112. $result = $this->getConnection()->fetchCol($select);
  113. $entityId = count($result) ? $result[0] : false;
  114. }
  115. return $entityId;
  116. }
  117. /**
  118. * Load an object
  119. *
  120. * @param \Magento\Cms\Model\Block|AbstractModel $object
  121. * @param mixed $value
  122. * @param string $field field to load by (defaults to model id)
  123. * @return $this
  124. */
  125. public function load(AbstractModel $object, $value, $field = null)
  126. {
  127. $blockId = $this->getBlockId($object, $value, $field);
  128. if ($blockId) {
  129. $this->entityManager->load($object, $blockId);
  130. }
  131. return $this;
  132. }
  133. /**
  134. * Retrieve select object for load object data
  135. *
  136. * @param string $field
  137. * @param mixed $value
  138. * @param \Magento\Cms\Model\Block|AbstractModel $object
  139. * @return Select
  140. */
  141. protected function _getLoadSelect($field, $value, $object)
  142. {
  143. $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
  144. $linkField = $entityMetadata->getLinkField();
  145. $select = parent::_getLoadSelect($field, $value, $object);
  146. if ($object->getStoreId()) {
  147. $stores = [(int)$object->getStoreId(), Store::DEFAULT_STORE_ID];
  148. $select->join(
  149. ['cbs' => $this->getTable('cms_block_store')],
  150. $this->getMainTable() . '.' . $linkField . ' = cbs.' . $linkField,
  151. ['store_id']
  152. )
  153. ->where('is_active = ?', 1)
  154. ->where('cbs.store_id in (?)', $stores)
  155. ->order('store_id DESC')
  156. ->limit(1);
  157. }
  158. return $select;
  159. }
  160. /**
  161. * Check for unique of identifier of block to selected store(s).
  162. *
  163. * @param AbstractModel $object
  164. * @return bool
  165. * @SuppressWarnings(PHPMD.BooleanGetMethodName)
  166. */
  167. public function getIsUniqueBlockToStores(AbstractModel $object)
  168. {
  169. $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
  170. $linkField = $entityMetadata->getLinkField();
  171. $stores = (array)$object->getData('store_id');
  172. $isDefaultStore = $this->_storeManager->isSingleStoreMode()
  173. || array_search(Store::DEFAULT_STORE_ID, $stores) !== false;
  174. if (!$isDefaultStore) {
  175. $stores[] = Store::DEFAULT_STORE_ID;
  176. }
  177. $select = $this->getConnection()->select()
  178. ->from(['cb' => $this->getMainTable()])
  179. ->join(
  180. ['cbs' => $this->getTable('cms_block_store')],
  181. 'cb.' . $linkField . ' = cbs.' . $linkField,
  182. []
  183. )
  184. ->where('cb.identifier = ? ', $object->getData('identifier'));
  185. if (!$isDefaultStore) {
  186. $select->where('cbs.store_id IN (?)', $stores);
  187. }
  188. if ($object->getId()) {
  189. $select->where('cb.' . $entityMetadata->getIdentifierField() . ' <> ?', $object->getId());
  190. }
  191. if ($this->getConnection()->fetchRow($select)) {
  192. return false;
  193. }
  194. return true;
  195. }
  196. /**
  197. * Get store ids to which specified item is assigned
  198. *
  199. * @param int $id
  200. * @return array
  201. */
  202. public function lookupStoreIds($id)
  203. {
  204. $connection = $this->getConnection();
  205. $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
  206. $linkField = $entityMetadata->getLinkField();
  207. $select = $connection->select()
  208. ->from(['cbs' => $this->getTable('cms_block_store')], 'store_id')
  209. ->join(
  210. ['cb' => $this->getMainTable()],
  211. 'cbs.' . $linkField . ' = cb.' . $linkField,
  212. []
  213. )
  214. ->where('cb.' . $entityMetadata->getIdentifierField() . ' = :block_id');
  215. return $connection->fetchCol($select, ['block_id' => (int)$id]);
  216. }
  217. /**
  218. * Save an object.
  219. *
  220. * @param AbstractModel $object
  221. * @return $this
  222. * @throws \Exception
  223. */
  224. public function save(AbstractModel $object)
  225. {
  226. $this->entityManager->save($object);
  227. return $this;
  228. }
  229. /**
  230. * @inheritDoc
  231. */
  232. public function delete(AbstractModel $object)
  233. {
  234. $this->entityManager->delete($object);
  235. return $this;
  236. }
  237. }