Category.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <?php
  2. /**
  3. * Copyright © 2016 Ihor Vansach (ihor@magefan.com). All rights reserved.
  4. * See LICENSE.txt for license details (http://opensource.org/licenses/osl-3.0.php).
  5. *
  6. * Glory to Ukraine! Glory to the heroes!
  7. */
  8. namespace Magefan\Blog\Model\ResourceModel;
  9. /**
  10. * Blog category resource model
  11. */
  12. class Category extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
  13. {
  14. /**
  15. * @var \Magento\Framework\Stdlib\DateTime
  16. */
  17. protected $dateTime;
  18. /**
  19. * Construct
  20. *
  21. * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
  22. * @param \Magento\Framework\Stdlib\DateTime $dateTime
  23. * @param string|null $resourcePrefix
  24. */
  25. public function __construct(
  26. \Magento\Framework\Model\ResourceModel\Db\Context $context,
  27. \Magento\Framework\Stdlib\DateTime $dateTime,
  28. $resourcePrefix = null
  29. ) {
  30. parent::__construct($context, $resourcePrefix);
  31. $this->dateTime = $dateTime;
  32. }
  33. /**
  34. * Initialize resource model
  35. * Get tablename from config
  36. *
  37. * @return void
  38. */
  39. protected function _construct()
  40. {
  41. $this->_init('magefan_blog_category', 'category_id');
  42. }
  43. /**
  44. * Process category data before deleting
  45. *
  46. * @param \Magento\Framework\Model\AbstractModel $object
  47. * @return $this
  48. */
  49. protected function _beforeDelete(\Magento\Framework\Model\AbstractModel $object)
  50. {
  51. $condition = ['category_id = ?' => (int)$object->getId()];
  52. $this->getConnection()->delete($this->getTable('magefan_blog_category_store'), $condition);
  53. $this->getConnection()->delete($this->getTable('magefan_blog_post_category'), $condition);
  54. return parent::_beforeDelete($object);
  55. }
  56. /**
  57. * Process category data before saving
  58. *
  59. * @param \Magento\Framework\Model\AbstractModel $object
  60. * @return $this
  61. * @throws \Magento\Framework\Exception\LocalizedException
  62. */
  63. protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
  64. {
  65. foreach (['custom_theme_from', 'custom_theme_to'] as $field) {
  66. $value = $object->getData($field) ?: null;
  67. $object->setData($field, $this->dateTime->formatDate($value));
  68. }
  69. $identifierGenerator = \Magento\Framework\App\ObjectManager::getInstance()
  70. ->create('Magefan\Blog\Model\ResourceModel\PageIdentifierGenerator');
  71. $identifierGenerator->generate($object);
  72. if (!$this->isValidPageIdentifier($object)) {
  73. throw new \Magento\Framework\Exception\LocalizedException(
  74. __('The category URL key contains capital letters or disallowed symbols.')
  75. );
  76. }
  77. if ($this->isNumericPageIdentifier($object)) {
  78. throw new \Magento\Framework\Exception\LocalizedException(
  79. __('The category URL key cannot be made of only numbers.')
  80. );
  81. }
  82. return parent::_beforeSave($object);
  83. }
  84. /**
  85. * Assign category to store views
  86. *
  87. * @param \Magento\Framework\Model\AbstractModel $object
  88. * @return $this
  89. */
  90. protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
  91. {
  92. $oldStoreIds = $this->lookupStoreIds($object->getId());
  93. $newStoreIds = (array)$object->getStoreIds();
  94. if (!$newStoreIds) {
  95. $newStoreIds = [0];
  96. }
  97. $table = $this->getTable('magefan_blog_category_store');
  98. $insert = array_diff($newStoreIds, $oldStoreIds);
  99. $delete = array_diff($oldStoreIds, $newStoreIds);
  100. if ($delete) {
  101. $where = ['category_id = ?' => (int)$object->getId(), 'store_id IN (?)' => $delete];
  102. $this->getConnection()->delete($table, $where);
  103. }
  104. if ($insert) {
  105. $data = [];
  106. foreach ($insert as $storeId) {
  107. $data[] = ['category_id' => (int)$object->getId(), 'store_id' => (int)$storeId];
  108. }
  109. $this->getConnection()->insertMultiple($table, $data);
  110. }
  111. return parent::_afterSave($object);
  112. }
  113. /**
  114. * Load an object using 'identifier' field if there's no field specified and value is not numeric
  115. *
  116. * @param \Magento\Framework\Model\AbstractModel $object
  117. * @param mixed $value
  118. * @param string $field
  119. * @return $this
  120. */
  121. public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null)
  122. {
  123. if (!is_numeric($value) && is_null($field)) {
  124. $field = 'identifier';
  125. }
  126. return parent::load($object, $value, $field);
  127. }
  128. /**
  129. * Perform operations after object load
  130. *
  131. * @param \Magento\Framework\Model\AbstractModel $object
  132. * @return $this
  133. */
  134. protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
  135. {
  136. if ($object->getId()) {
  137. $storeIds = $this->lookupStoreIds($object->getId());
  138. $object->setData('store_ids', $storeIds);
  139. }
  140. return parent::_afterLoad($object);
  141. }
  142. /**
  143. * Check if category identifier exist for specific store
  144. * return category id if category exists
  145. *
  146. * @param string $identifier
  147. * @param int $storeId
  148. * @return int
  149. */
  150. protected function _getLoadByIdentifierSelect($identifier, $storeIds)
  151. {
  152. $select = $this->getConnection()->select()->from(
  153. ['cp' => $this->getMainTable()]
  154. )->join(
  155. ['cps' => $this->getTable('magefan_blog_category_store')],
  156. 'cp.category_id = cps.category_id',
  157. []
  158. )->where(
  159. 'cp.identifier = ?',
  160. $identifier
  161. )->where(
  162. 'cps.store_id IN (?)',
  163. $storeIds
  164. );
  165. return $select;
  166. }
  167. /**
  168. * Check whether category identifier is numeric
  169. *
  170. * @param \Magento\Framework\Model\AbstractModel $object
  171. * @return bool
  172. */
  173. protected function isNumericPageIdentifier(\Magento\Framework\Model\AbstractModel $object)
  174. {
  175. return preg_match('/^[0-9]+$/', $object->getData('identifier'));
  176. }
  177. /**
  178. * Check whether category identifier is valid
  179. *
  180. * @param \Magento\Framework\Model\AbstractModel $object
  181. * @return bool
  182. */
  183. protected function isValidPageIdentifier(\Magento\Framework\Model\AbstractModel $object)
  184. {
  185. return preg_match('/^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/', $object->getData('identifier'));
  186. }
  187. /**
  188. * Check if category identifier exist for specific store
  189. * return page id if page exists
  190. *
  191. * @param string $identifier
  192. * @param int|array $storeId
  193. * @return int
  194. */
  195. public function checkIdentifier($identifier, $storeIds)
  196. {
  197. if (!is_array($storeIds)) {
  198. $storeIds = [$storeIds];
  199. }
  200. $storeIds[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
  201. $select = $this->_getLoadByIdentifierSelect($identifier, $storeIds);
  202. $select->reset(\Zend_Db_Select::COLUMNS)->columns('cp.category_id')->order('cps.store_id DESC')->limit(1);
  203. return $this->getConnection()->fetchOne($select);
  204. }
  205. /**
  206. * Get store ids to which specified item is assigned
  207. *
  208. * @param int $categoryId
  209. * @return array
  210. */
  211. public function lookupStoreIds($categoryId)
  212. {
  213. $adapter = $this->getConnection();
  214. $select = $adapter->select()->from(
  215. $this->getTable('magefan_blog_category_store'),
  216. 'store_id'
  217. )->where(
  218. 'category_id = ?',
  219. (int)$categoryId
  220. );
  221. return $adapter->fetchCol($select);
  222. }
  223. }