Category.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <?php
  2. /**
  3. * Copyright © 2017 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;
  9. use Magefan\Blog\Model\Url;
  10. /**
  11. * Category model
  12. *
  13. * @method \Magefan\Blog\Model\ResourceModel\Category _getResource()
  14. * @method \Magefan\Blog\Model\ResourceModel\Category getResource()
  15. * @method int getStoreId()
  16. * @method $this setStoreId(int $value)
  17. * @method string getTitle()
  18. * @method $this setTitle(string $value)
  19. * @method string getMetaKeywords()
  20. * @method $this setMetaKeywords(string $value)
  21. * @method string getMetaDescription()
  22. * @method $this setMetaDescription(string $value)
  23. * @method string getIdentifier()
  24. * @method $this setIdentifier(string $value)
  25. */
  26. class Category extends \Magento\Framework\Model\AbstractModel
  27. {
  28. /**
  29. * Category's Statuses
  30. */
  31. const STATUS_ENABLED = 1;
  32. const STATUS_DISABLED = 0;
  33. /**
  34. * Prefix of model events names
  35. *
  36. * @var string
  37. */
  38. protected $_eventPrefix = 'magefan_blog_category';
  39. /**
  40. * Parameter name in event
  41. *
  42. * In observe method you can use $observer->getEvent()->getObject() in this case
  43. *
  44. * @var string
  45. */
  46. protected $_eventObject = 'blog_category';
  47. /**
  48. * @var \Magento\Framework\UrlInterface
  49. */
  50. protected $_url;
  51. /**
  52. * @var \Magefan\Blog\Model\ResourceModel\Post\CollectionFactory
  53. */
  54. protected $postCollectionFactory;
  55. /**
  56. * @var array
  57. */
  58. static private $loadedCategoriesRepository = [];
  59. /**
  60. * @var string
  61. */
  62. protected $controllerName;
  63. /**
  64. * Initialize dependencies.
  65. *
  66. * @param \Magento\Framework\Model\Context $context
  67. * @param \Magento\Framework\Registry $registry
  68. * @param \Magefan\Blog\Model\Url $url
  69. * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
  70. * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
  71. * @param array $data
  72. */
  73. public function __construct(
  74. \Magento\Framework\Model\Context $context,
  75. \Magento\Framework\Registry $registry,
  76. Url $url,
  77. \Magefan\Blog\Model\ResourceModel\Post\CollectionFactory $postCollectionFactory,
  78. \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
  79. \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
  80. array $data = []
  81. ) {
  82. $this->_url = $url;
  83. $this->postCollectionFactory = $postCollectionFactory;
  84. parent::__construct($context, $registry, $resource, $resourceCollection, $data);
  85. }
  86. /**
  87. * Initialize resource model
  88. *
  89. * @return void
  90. */
  91. protected function _construct()
  92. {
  93. $this->_init('Magefan\Blog\Model\ResourceModel\Category');
  94. $this->controllerName = URL::CONTROLLER_CATEGORY;
  95. }
  96. /**
  97. * Load object data
  98. *
  99. * @param integer $modelId
  100. * @param null|string $field
  101. * @return $this
  102. * @deprecated
  103. */
  104. public function load($modelId, $field = null)
  105. {
  106. $object = parent::load($modelId, $field);
  107. if (!isset(self::$loadedCategoriesRepository[$object->getId()])) {
  108. self::$loadedCategoriesRepository[$object->getId()] = $object;
  109. }
  110. return $object;
  111. }
  112. private function loadFromRepository($categoryId)
  113. {
  114. if (!isset(self::$loadedCategoriesRepository[$categoryId])) {
  115. $category = clone $this;
  116. $category->load($categoryId);
  117. }
  118. return self::$loadedCategoriesRepository[$categoryId];
  119. }
  120. /**
  121. * Retrieve controller name
  122. * @return string
  123. */
  124. public function getControllerName()
  125. {
  126. return $this->controllerName;
  127. }
  128. /**
  129. * Retrieve model title
  130. * @param boolean $plural
  131. * @return string
  132. */
  133. public function getOwnTitle($plural = false)
  134. {
  135. return $plural ? 'Categories' : 'Category';
  136. }
  137. /**
  138. * Retrieve true if category is active
  139. * @return boolean [description]
  140. */
  141. public function isActive()
  142. {
  143. return ($this->getStatus() == self::STATUS_ENABLED);
  144. }
  145. /**
  146. * Retrieve available category statuses
  147. * @return array
  148. */
  149. public function getAvailableStatuses()
  150. {
  151. return [self::STATUS_DISABLED => __('Disabled'), self::STATUS_ENABLED => __('Enabled')];
  152. }
  153. /**
  154. * Check if category identifier exist for specific store
  155. * return category id if category exists
  156. *
  157. * @param string $identifier
  158. * @param int $storeId
  159. * @return int
  160. */
  161. public function checkIdentifier($identifier, $storeId)
  162. {
  163. return $this->_getResource()->checkIdentifier($identifier, $storeId);
  164. }
  165. /**
  166. * Retrieve parent category ids
  167. * @return array
  168. */
  169. public function getParentIds()
  170. {
  171. $k = 'parent_ids';
  172. if (!$this->hasData($k)) {
  173. $this->setData($k,
  174. $this->getPath() ? explode('/', $this->getPath()) : []
  175. );
  176. }
  177. return $this->getData($k);
  178. }
  179. /**
  180. * Retrieve parent category id
  181. * @return array
  182. */
  183. public function getParentId()
  184. {
  185. $parentIds = $this->getParentIds();
  186. if ($parentIds) {
  187. return $parentIds[count($parentIds) - 1];
  188. }
  189. return 0;
  190. }
  191. /**
  192. * Retrieve parent category
  193. * @return self || false
  194. */
  195. public function getParentCategory()
  196. {
  197. $k = 'parent_category';
  198. if (null === $this->getData($k)) {
  199. $this->setData($k, false);
  200. if ($pId = $this->getParentId()) {
  201. $category = $this->loadFromRepository($pId);
  202. if ($category->getId()) {
  203. if ($category->isVisibleOnStore($this->getStoreId())) {
  204. $this->setData($k, $category);
  205. }
  206. }
  207. }
  208. }
  209. return $this->getData($k);
  210. }
  211. /**
  212. * Check if current category is parent category
  213. * @param self $category
  214. * @return boolean
  215. */
  216. public function isParent($category)
  217. {
  218. if (is_object($category)) {
  219. $category = $category->getId();
  220. }
  221. return in_array($category, $this->getParentIds());
  222. }
  223. /**
  224. * Retrieve children category ids
  225. * @return array
  226. */
  227. public function getChildrenIds()
  228. {
  229. $k = 'children_ids';
  230. if (!$this->hasData($k)) {
  231. $categories = \Magento\Framework\App\ObjectManager::getInstance()
  232. ->create($this->_collectionName);
  233. $ids = [];
  234. foreach($categories as $category) {
  235. if ($category->isParent($this)) {
  236. $ids[] = $category->getId();
  237. }
  238. }
  239. $this->setData($k,
  240. $ids
  241. );
  242. }
  243. return $this->getData($k);
  244. }
  245. /**
  246. * Check if current category is child category
  247. * @param self $category
  248. * @return boolean
  249. */
  250. public function isChild($category)
  251. {
  252. return $category->isParent($this);
  253. }
  254. /**
  255. * Retrieve category depth level
  256. * @return int
  257. */
  258. public function getLevel()
  259. {
  260. return count($this->getParentIds());
  261. }
  262. /**
  263. * Retrieve catgegory url route path
  264. * @return string
  265. */
  266. public function getUrl()
  267. {
  268. return $this->_url->getUrlPath($this->getIdentifier(), $this->controllerName);
  269. }
  270. /**
  271. * Retrieve category url
  272. * @return string
  273. */
  274. public function getCategoryUrl()
  275. {
  276. return $this->_url->getUrl($this, $this->controllerName);
  277. }
  278. /**
  279. * Retrieve catgegory canonical url
  280. * @return string
  281. */
  282. public function getCanonicalUrl()
  283. {
  284. return $this->_url->getCanonicalUrl($this);
  285. }
  286. /**
  287. * Retrieve meta title
  288. * @return string
  289. */
  290. public function getMetaTitle()
  291. {
  292. $title = $this->getData('meta_title');
  293. if (!$title) {
  294. $title = $this->getData('title');
  295. }
  296. return trim($title);
  297. }
  298. /**
  299. * Retrieve meta description
  300. * @return string
  301. */
  302. public function getMetaDescription()
  303. {
  304. $desc = $this->getData('meta_description');
  305. if (!$desc) {
  306. $desc = $this->getData('content');
  307. }
  308. $desc = strip_tags($desc);
  309. if (mb_strlen($desc) > 160) {
  310. $desc = mb_substr($desc, 0, 160);
  311. }
  312. return trim($desc);
  313. }
  314. /**
  315. * Retrieve if is visible on store
  316. * @return bool
  317. */
  318. public function isVisibleOnStore($storeId)
  319. {
  320. return $this->getIsActive() && array_intersect([0, $storeId], $this->getStoreIds());
  321. }
  322. /**
  323. * Retrieve number of posts in this category
  324. *
  325. * @return int
  326. */
  327. public function getPostsCount()
  328. {
  329. $key = 'posts_count';
  330. if (!$this->hasData($key)) {
  331. $posts = $this->postCollectionFactory->create()
  332. ->addActiveFilter()
  333. ->addStoreFilter($this->getStoreId())
  334. ->addCategoryFilter($this);
  335. $this->setData($key, (int)$posts->getSize());
  336. }
  337. return $this->getData($key);
  338. }
  339. /**
  340. * Prepare all additional data
  341. * @param string $format
  342. * @return self
  343. */
  344. public function initDinamicData()
  345. {
  346. $keys = [
  347. 'meta_description',
  348. 'meta_title',
  349. ];
  350. foreach ($keys as $key) {
  351. $method = 'get' . str_replace('_', '',
  352. ucwords($key, '_')
  353. );
  354. $this->$method();
  355. }
  356. return $this;
  357. }
  358. /**
  359. * Duplicate category and return new object
  360. * @return self
  361. */
  362. public function duplicate()
  363. {
  364. $object = clone $this;
  365. $object
  366. ->unsetData('category_id')
  367. ->setTitle($object->getTitle() . ' (' . __('Duplicated') . ')')
  368. ->setData('is_active', 0);
  369. return $object->save();
  370. }
  371. }