<?php /** * Copyright © 2016 Ihor Vansach (ihor@magefan.com). All rights reserved. * See LICENSE.txt for license details (http://opensource.org/licenses/osl-3.0.php). * * Glory to Ukraine! Glory to the heroes! */ namespace Magefan\Blog\Model\ResourceModel; /** * Blog category resource model */ class Category extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { /** * @var \Magento\Framework\Stdlib\DateTime */ protected $dateTime; /** * Construct * * @param \Magento\Framework\Model\ResourceModel\Db\Context $context * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param string|null $resourcePrefix */ public function __construct( \Magento\Framework\Model\ResourceModel\Db\Context $context, \Magento\Framework\Stdlib\DateTime $dateTime, $resourcePrefix = null ) { parent::__construct($context, $resourcePrefix); $this->dateTime = $dateTime; } /** * Initialize resource model * Get tablename from config * * @return void */ protected function _construct() { $this->_init('magefan_blog_category', 'category_id'); } /** * Process category data before deleting * * @param \Magento\Framework\Model\AbstractModel $object * @return $this */ protected function _beforeDelete(\Magento\Framework\Model\AbstractModel $object) { $condition = ['category_id = ?' => (int)$object->getId()]; $this->getConnection()->delete($this->getTable('magefan_blog_category_store'), $condition); $this->getConnection()->delete($this->getTable('magefan_blog_post_category'), $condition); return parent::_beforeDelete($object); } /** * Process category data before saving * * @param \Magento\Framework\Model\AbstractModel $object * @return $this * @throws \Magento\Framework\Exception\LocalizedException */ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) { foreach (['custom_theme_from', 'custom_theme_to'] as $field) { $value = $object->getData($field) ?: null; $object->setData($field, $this->dateTime->formatDate($value)); } $identifierGenerator = \Magento\Framework\App\ObjectManager::getInstance() ->create('Magefan\Blog\Model\ResourceModel\PageIdentifierGenerator'); $identifierGenerator->generate($object); if (!$this->isValidPageIdentifier($object)) { throw new \Magento\Framework\Exception\LocalizedException( __('The category URL key contains capital letters or disallowed symbols.') ); } if ($this->isNumericPageIdentifier($object)) { throw new \Magento\Framework\Exception\LocalizedException( __('The category URL key cannot be made of only numbers.') ); } return parent::_beforeSave($object); } /** * Assign category to store views * * @param \Magento\Framework\Model\AbstractModel $object * @return $this */ protected function _afterSave(\Magento\Framework\Model\AbstractModel $object) { $oldStoreIds = $this->lookupStoreIds($object->getId()); $newStoreIds = (array)$object->getStoreIds(); if (!$newStoreIds) { $newStoreIds = [0]; } $table = $this->getTable('magefan_blog_category_store'); $insert = array_diff($newStoreIds, $oldStoreIds); $delete = array_diff($oldStoreIds, $newStoreIds); if ($delete) { $where = ['category_id = ?' => (int)$object->getId(), 'store_id IN (?)' => $delete]; $this->getConnection()->delete($table, $where); } if ($insert) { $data = []; foreach ($insert as $storeId) { $data[] = ['category_id' => (int)$object->getId(), 'store_id' => (int)$storeId]; } $this->getConnection()->insertMultiple($table, $data); } return parent::_afterSave($object); } /** * Load an object using 'identifier' field if there's no field specified and value is not numeric * * @param \Magento\Framework\Model\AbstractModel $object * @param mixed $value * @param string $field * @return $this */ public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null) { if (!is_numeric($value) && is_null($field)) { $field = 'identifier'; } return parent::load($object, $value, $field); } /** * Perform operations after object load * * @param \Magento\Framework\Model\AbstractModel $object * @return $this */ protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object) { if ($object->getId()) { $storeIds = $this->lookupStoreIds($object->getId()); $object->setData('store_ids', $storeIds); } return parent::_afterLoad($object); } /** * Check if category identifier exist for specific store * return category id if category exists * * @param string $identifier * @param int $storeId * @return int */ protected function _getLoadByIdentifierSelect($identifier, $storeIds, $isActive = null) { $select = $this->getConnection()->select()->from( ['cp' => $this->getMainTable()] )->join( ['cps' => $this->getTable('magefan_blog_category_store')], 'cp.category_id = cps.category_id', [] )->where( 'cp.identifier = ?', $identifier )->where( 'cps.store_id IN (?)', $storeIds ); if (!is_null($isActive)) { $select->where('cp.is_active = ?', $isActive); } return $select; } /** * Check whether category identifier is numeric * * @param \Magento\Framework\Model\AbstractModel $object * @return bool */ protected function isNumericPageIdentifier(\Magento\Framework\Model\AbstractModel $object) { return preg_match('/^[0-9]+$/', $object->getData('identifier')); } /** * Check whether category identifier is valid * * @param \Magento\Framework\Model\AbstractModel $object * @return bool */ protected function isValidPageIdentifier(\Magento\Framework\Model\AbstractModel $object) { return preg_match('/^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/', $object->getData('identifier')); } /** * Check if category identifier exist for specific store * return page id if page exists * * @param string $identifier * @param int|array $storeId * @return int */ public function checkIdentifier($identifier, $storeIds) { if (!is_array($storeIds)) { $storeIds = [$storeIds]; } $storeIds[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID; $select = $this->_getLoadByIdentifierSelect($identifier, $storeIds, 1); $select->reset(\Zend_Db_Select::COLUMNS)->columns('cp.category_id')->order('cps.store_id DESC')->limit(1); return $this->getConnection()->fetchOne($select); } /** * Get store ids to which specified item is assigned * * @param int $categoryId * @return array */ public function lookupStoreIds($categoryId) { $adapter = $this->getConnection(); $select = $adapter->select()->from( $this->getTable('magefan_blog_category_store'), 'store_id' )->where( 'category_id = ?', (int)$categoryId ); return $adapter->fetchCol($select); } }