├── README.md ├── registration.php ├── view └── frontend │ ├── templates │ └── brand │ │ └── view │ │ └── details.phtml │ └── layout │ └── brand_brand_view.xml ├── etc ├── frontend │ └── routes.xml ├── module.xml ├── events.xml ├── config.xml ├── setup │ └── events.xml ├── di.xml ├── acl.xml └── adminhtml │ └── system.xml ├── Api ├── Data │ ├── BrandSearchResultsInterface.php │ └── BrandInterface.php └── BrandRepositoryInterface.php ├── composer.json ├── Model ├── ResourceModel │ ├── Brand.php │ └── Brand │ │ └── Collection.php ├── Brand │ ├── CanonicalUrlRewriteGenerator.php │ └── CurrentUrlRewritesRegenerator.php ├── Product │ └── Attribute │ │ └── Source │ │ └── Brand.php ├── BrandRepository.php ├── BrandUrlPathGenerator.php ├── BrandUrlRewriteGenerator.php └── Brand.php ├── Test └── Unit │ ├── Setup │ └── BrandSetupTest.php │ └── Model │ ├── Product │ └── Attribute │ │ └── Source │ │ └── BrandTest.php │ └── ResourceModel │ └── Brand │ └── CollectionTest.php ├── LICENSE ├── Setup ├── InstallData.php ├── BrandSetup.php └── InstallSchema.php ├── Observer └── ProcessUrlRewriteSavingObserver.php ├── Block └── Brand │ └── View.php └── Controller └── Brand └── View.php /README.md: -------------------------------------------------------------------------------- 1 | # magento2-module-brand 2 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 6 |

getBrand()->getName() ?>

7 |

getBrand()->getDescription() ?>

8 | -------------------------------------------------------------------------------- /etc/frontend/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | .html 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /etc/setup/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /view/frontend/layout/brand_brand_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Api/Data/BrandSearchResultsInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Model/ResourceModel/Brand.php: -------------------------------------------------------------------------------- 1 | _type)) { 24 | $this->setType(\Dmatthew\Brand\Model\Brand::ENTITY); 25 | } 26 | return parent::getEntityType(); 27 | } 28 | } -------------------------------------------------------------------------------- /Test/Unit/Setup/BrandSetupTest.php: -------------------------------------------------------------------------------- 1 | unit = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( 13 | 'Dmatthew\Brand\Setup\BrandSetup' 14 | ); 15 | } 16 | 17 | public function testGetDefaultEntitiesContainAllAttributes() 18 | { 19 | $defaultEntities = $this->unit->getDefaultEntities(); 20 | 21 | $this->assertEquals( 22 | [ 23 | 'name', 24 | 'description', 25 | 'url_key', 26 | 'meta_title', 27 | 'meta_description' 28 | ], 29 | array_keys($defaultEntities['dmatthew_brand']['attributes']) 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Matt Davis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | separator-top 6 | 7 | catalog 8 | Dmatthew_Brand::config_brand 9 | 10 | 11 | 12 | 13 | Magento\Catalog\Model\System\Config\Backend\Catalog\Url\Rewrite\Suffix 14 | You need to refresh the cache. 15 | 16 | 17 |
18 |
19 |
20 | -------------------------------------------------------------------------------- /Setup/InstallData.php: -------------------------------------------------------------------------------- 1 | brandSetupFactory = $brandSetupFactory; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) 34 | * @SuppressWarnings(PHPMD.ExcessiveMethodLength) 35 | * @SuppressWarnings(PHPMD.NPathComplexity) 36 | */ 37 | public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) 38 | { 39 | /** @var \Magento\Catalog\Setup\BrandSetup $brandSetup */ 40 | $brandSetup = $this->brandSetupFactory->create(['setup' => $setup]); 41 | 42 | $brandSetup->installEntities(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Observer/ProcessUrlRewriteSavingObserver.php: -------------------------------------------------------------------------------- 1 | brandUrlRewriteGenerator = $brandUrlRewriteGenerator; 29 | $this->urlPersist = $urlPersist; 30 | } 31 | 32 | /** 33 | * Generate urls for UrlRewrite and save it in storage. 34 | * 35 | * @param \Magento\Framework\Event\Observer $observer 36 | * @return void 37 | */ 38 | public function execute(EventObserver $observer) 39 | { 40 | /** @var $brand \Dmatthew\Brand\Model\Brand */ 41 | $brand = $observer->getEvent()->getBrand(); 42 | if ($brand->dataHasChangedFor('url_key')) { 43 | $urls = $this->brandUrlRewriteGenerator->generate($brand); 44 | $this->urlPersist->replace($urls); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Model/Brand/CanonicalUrlRewriteGenerator.php: -------------------------------------------------------------------------------- 1 | brandUrlPathGenerator = $brandUrlPathGenerator; 26 | $this->urlRewriteFactory = $urlRewriteFactory; 27 | } 28 | 29 | /** 30 | * Generate list based on store view 31 | * 32 | * @param int $storeId 33 | * @param Brand $brand 34 | * @return UrlRewrite[] 35 | */ 36 | public function generate($storeId, Brand $brand) 37 | { 38 | return [ 39 | $this->urlRewriteFactory->create() 40 | ->setEntityType(BrandUrlRewriteGenerator::ENTITY_TYPE) 41 | ->setEntityId($brand->getId()) 42 | ->setRequestPath($this->brandUrlPathGenerator->getUrlPathWithSuffix($brand, $storeId)) 43 | ->setTargetPath($this->brandUrlPathGenerator->getCanonicalUrlPath($brand)) 44 | ->setStoreId($storeId) 45 | ]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Api/Data/BrandInterface.php: -------------------------------------------------------------------------------- 1 | _brandFactory = $brandFactory; 42 | $this->_storeManager = $storeManager; 43 | $this->_configCacheType = $configCacheType; 44 | } 45 | 46 | /** 47 | * Get list of all available brands 48 | * 49 | * @return array 50 | */ 51 | public function getAllOptions() 52 | { 53 | $cacheKey = 'BRAND_SELECT_STORE_' . $this->_storeManager->getStore()->getCode(); 54 | if ($cache = $this->_configCacheType->load($cacheKey)) { 55 | $options = unserialize($cache); 56 | } else { 57 | $collection = $this->_brandFactory->create()->getResourceCollection()->loadByStore(); 58 | $options = $collection->toOptionArray(); 59 | $this->_configCacheType->save(serialize($options), $cacheKey); 60 | } 61 | return $options; 62 | } 63 | } -------------------------------------------------------------------------------- /Block/Brand/View.php: -------------------------------------------------------------------------------- 1 | _coreRegistry = $registry; 34 | $this->string = $string; 35 | parent::__construct($context, $data); 36 | } 37 | 38 | protected function _prepareLayout() 39 | { 40 | parent::_prepareLayout(); 41 | 42 | $brand = $this->getBrand(); 43 | if ($brand) { 44 | 45 | $metaTitle = $brand->getMetaTitle(); 46 | if ($metaTitle) { 47 | $this->pageConfig->getTitle()->set($metaTitle); 48 | } 49 | 50 | $metaDescription = $brand->getMetaDescription(); 51 | if ($metaDescription) { 52 | $this->pageConfig->setDescription($metaDescription); 53 | } else { 54 | $this->pageConfig->setDescription($this->string->substr($brand->getDescription(), 0, 255)); 55 | } 56 | } 57 | 58 | return $this; 59 | } 60 | 61 | /** 62 | * Retrieve current brand model object 63 | * 64 | * @return \Dmatthew\Brand\Model\Brand 65 | */ 66 | public function getBrand() 67 | { 68 | if (!$this->hasData('current_brand')) { 69 | $this->setData('current_brand', $this->_coreRegistry->registry('current_brand')); 70 | } 71 | return $this->getData('current_brand'); 72 | } 73 | } -------------------------------------------------------------------------------- /Test/Unit/Model/Product/Attribute/Source/BrandTest.php: -------------------------------------------------------------------------------- 1 | storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface'); 32 | $this->storeMock = $this->getMock('\Magento\Store\Model\Store', [], [], '', false); 33 | $this->cacheConfig = $this->getMock('\Magento\Framework\App\Cache\Type\Config', [], [], '', false); 34 | $this->objectManagerHelper = new ObjectManager($this); 35 | } 36 | 37 | /** 38 | * Test for getAllOptions method 39 | * 40 | * @param $cachedDataSrl 41 | * @param $cachedDataUnsrl 42 | * 43 | * @dataProvider testGetAllOptionsDataProvider 44 | */ 45 | public function testGetAllOptions($cachedDataSrl, $cachedDataUnsrl) 46 | { 47 | $this->storeMock->expects($this->once())->method('getCode')->will($this->returnValue('store_code')); 48 | $this->storeManagerMock->expects($this->once())->method('getStore')->will($this->returnValue($this->storeMock)); 49 | $this->cacheConfig->expects($this->once()) 50 | ->method('load') 51 | ->with($this->equalTo('BRAND_SELECT_STORE_store_code')) 52 | ->will($this->returnValue($cachedDataSrl)); 53 | 54 | $brand = $this->objectManagerHelper->getObject( 55 | 'Dmatthew\Brand\Model\Product\Attribute\Source\Brand', 56 | [ 57 | 'storeManager' => $this->storeManagerMock, 58 | 'configCacheType' => $this->cacheConfig, 59 | ] 60 | ); 61 | $this->assertEquals($cachedDataUnsrl, $brand->getAllOptions()); 62 | } 63 | 64 | /** 65 | * Data provider for testGetAllOptions 66 | * 67 | * @return array 68 | */ 69 | public function testGetAllOptionsDataProvider() 70 | { 71 | return 72 | [ 73 | ['cachedDataSrl' => 'a:1:{s:3:"key";s:4:"data";}', 'cachedDataUnsrl' => ['key' => 'data']] 74 | ]; 75 | } 76 | } -------------------------------------------------------------------------------- /Test/Unit/Model/ResourceModel/Brand/CollectionTest.php: -------------------------------------------------------------------------------- 1 | brandCollection = $this->getMockBuilder('Dmatthew\Brand\Model\ResourceModel\Brand\Collection') 28 | ->disableOriginalConstructor() 29 | ->getMock(); 30 | 31 | $this->brand = $this->getMockBuilder('Dmatthew\Brand\Model\ResourceModel\Brand') 32 | ->setMethods(['getName', 'getId']) 33 | ->disableOriginalConstructor() 34 | ->getMock(); 35 | 36 | /** 37 | * @var \Dmatthew\Brand\Model\ResourceModel\Brand\CollectionFactory|MockObject $brandCollectionFactory 38 | */ 39 | $brandCollectionFactory = 40 | $this->getMockBuilder('Dmatthew\Brand\Model\ResourceModel\Brand\CollectionFactory') 41 | ->setMethods(['create']) 42 | ->disableOriginalConstructor() 43 | ->getMock(); 44 | $brandCollectionFactory->expects($this->any())->method('create')->will( 45 | $this->returnValue($this->brandCollection) 46 | ); 47 | 48 | $helper = new ObjectManager($this); 49 | $this->model = $helper->getObject( 50 | 'Dmatthew\Brand\Model\ResourceModel\Brand\Collection', 51 | [ 52 | 'brandCollectionFactory' => $brandCollectionFactory 53 | ] 54 | ); 55 | } 56 | 57 | public function testToOptionArray() 58 | { 59 | $expect = [ 60 | ['label' => __('-- Please Select a Brand --'), 'value' => ''], 61 | ['label' => 'name', 'value' => 3], 62 | ]; 63 | 64 | $this->brandCollection->expects($this->once())->method('addAttributeToSelect')->with( 65 | $this->equalTo('name') 66 | )->will($this->returnValue($this->brandCollection)); 67 | $this->brandCollection->expects($this->once())->method('load'); 68 | $this->brandCollection->expects($this->any())->method('getIterator')->will( 69 | $this->returnValue(new \ArrayIterator([$this->brand])) 70 | ); 71 | 72 | $this->brand->expects($this->once())->method('getName')->will($this->returnValue('name')); 73 | $this->brand->expects($this->once())->method('getId')->will($this->returnValue(3)); 74 | 75 | $this->assertEquals($expect, $this->model->toOptionArray()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Model/BrandRepository.php: -------------------------------------------------------------------------------- 1 | brandFactory = $brandFactory; 33 | $this->resourceModel = $resourceModel; 34 | } 35 | 36 | /** 37 | * @inheritdoc 38 | */ 39 | public function save(\Dmatthew\Brand\Api\Data\BrandInterface $brand) 40 | { 41 | try { 42 | $this->resourceModel->save($brand); 43 | } catch (\Exception $e) { 44 | throw new \Magento\Framework\Exception\CouldNotSaveException( 45 | __( 46 | 'Could not save brand: %1', 47 | $e->getMessage() 48 | ), 49 | $e 50 | ); 51 | } 52 | unset($this->instances[$brand->getId()]); 53 | return $brand; 54 | } 55 | 56 | /** 57 | * @inheritdoc 58 | */ 59 | public function get($brandId, $storeId = null) 60 | { 61 | $cacheKey = null !== $storeId ? $storeId : 'all'; 62 | if (!isset($this->instances[$brandId][$cacheKey])) { 63 | /** @var Brand $brand */ 64 | $brand = $this->brandFactory->create(); 65 | if (null !== $storeId) { 66 | $brand->setStoreId($storeId); 67 | } 68 | $brand->load($brandId); 69 | if (!$brand->getId()) { 70 | throw NoSuchEntityException::singleField('id', $brandId); 71 | } 72 | $this->instances[$brandId][$cacheKey] = $brand; 73 | } 74 | return $this->instances[$brandId][$cacheKey]; 75 | } 76 | 77 | /** 78 | * @inheritdoc 79 | */ 80 | public function delete(\Dmatthew\Brand\Api\Data\BrandInterface $brand) 81 | { 82 | try { 83 | $brandId = $brand->getId(); 84 | $this->resourceModel->delete($brand); 85 | } catch (\Exception $e) { 86 | throw new \Magento\Framework\Exception\StateException( 87 | __( 88 | 'Cannot delete brand with id %1', 89 | $brand->getId() 90 | ), 91 | $e 92 | ); 93 | } 94 | unset($this->instances[$brandId]); 95 | return true; 96 | } 97 | 98 | /** 99 | * @inheritdoc 100 | */ 101 | public function deleteById($id) 102 | { 103 | $brand = $this->get($id); 104 | return $this->delete($brand); 105 | } 106 | 107 | /** 108 | * @inheritdoc 109 | */ 110 | public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria) 111 | { 112 | // TODO: Implement getList method 113 | throw new \BadMethodCallException(__CLASS__.'::'.__METHOD__.' has not been implemented yet'); 114 | } 115 | } -------------------------------------------------------------------------------- /Model/ResourceModel/Brand/Collection.php: -------------------------------------------------------------------------------- 1 | _brandCollectionFactory = $brandCollectionFactory; 49 | parent::__construct( 50 | $entityFactory, 51 | $logger, 52 | $fetchStrategy, 53 | $eventManager, 54 | $eavConfig, 55 | $resource, 56 | $eavEntityFactory, 57 | $resourceHelper, 58 | $universalFactory, 59 | $storeManager, 60 | $connection 61 | ); 62 | } 63 | 64 | /** 65 | * Init collection and determine table names. 66 | * 67 | * @return void 68 | */ 69 | protected function _construct() 70 | { 71 | $this->_init('Dmatthew\Brand\Model\Brand', 'Dmatthew\Brand\Model\ResourceModel\Brand'); 72 | } 73 | 74 | /** 75 | * Convert items array to array for select options. 76 | * 77 | * @param $addEmpty bool 78 | * @return array 79 | */ 80 | public function toOptionArray($addEmpty = true) 81 | { 82 | /** @var \Dmatthew\Brand\Model\ResourceModel\Brand\Collection $collection */ 83 | $collection = $this->_brandCollectionFactory->create(); 84 | 85 | $collection->addAttributeToSelect('name')->load(); 86 | 87 | $options = []; 88 | 89 | if ($addEmpty) { 90 | $options[] = ['label' => __('-- Please Select a Brand --'), 'value' => '']; 91 | } 92 | foreach ($collection as $brand) { 93 | $options[] = ['label' => $brand->getName(), 'value' => $brand->getId()]; 94 | } 95 | 96 | return $options; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Controller/Brand/View.php: -------------------------------------------------------------------------------- 1 | _storeManager = $storeManager; 65 | $this->_coreRegistry = $coreRegistry; 66 | $this->_logger = $logger; 67 | $this->resultForwardFactory = $resultForwardFactory; 68 | $this->resultPageFactory = $resultPageFactory; 69 | $this->brandRepository = $brandRepository; 70 | } 71 | 72 | /** 73 | * Brand view action 74 | */ 75 | public function execute() 76 | { 77 | $brand = $this->_initBrand(); 78 | if ($brand) { 79 | $page = $this->resultPageFactory->create(); 80 | return $page; 81 | } 82 | elseif (!$this->getResponse()->isRedirect()) { 83 | return $this->resultForwardFactory->create()->forward('noroute'); 84 | } 85 | } 86 | 87 | /** 88 | * Initialize requested brand object 89 | * 90 | * @return \Dmatthew\Brand\Model\Brand 91 | */ 92 | protected function _initBrand() 93 | { 94 | $this->_eventManager->dispatch( 95 | 'brand_controller_brand_init_before', 96 | ['controller_action' => $this] 97 | ); 98 | 99 | $brandId = (int) $this->getRequest()->getParam('id'); 100 | 101 | if (!$brandId) { 102 | return false; 103 | } 104 | 105 | try { 106 | $brand = $this->brandRepository->get($brandId, $this->_storeManager->getStore()->getId()); 107 | } catch (NoSuchEntityException $e) { 108 | return false; 109 | } 110 | 111 | // Register current data and dispatch final events 112 | $this->_coreRegistry->register('current_brand', $brand); 113 | $this->_coreRegistry->register('brand', $brand); 114 | 115 | try { 116 | $this->_eventManager->dispatch( 117 | 'brand_controller_brand_init_after', 118 | ['brand' => $brand, 'controller_action' => $this] 119 | ); 120 | } catch (\Magento\Framework\Exception\LocalizedException $e) { 121 | $this->_logger->critical($e); 122 | return false; 123 | } 124 | 125 | return $brand; 126 | } 127 | } -------------------------------------------------------------------------------- /Model/BrandUrlPathGenerator.php: -------------------------------------------------------------------------------- 1 | storeManager = $storeManager; 38 | $this->scopeConfig = $scopeConfig; 39 | $this->brandRepository = $brandRepository; 40 | } 41 | 42 | /** 43 | * Retrieve Brand Url path 44 | * 45 | * @param \Dmatthew\Brand\Model\Brand $brand 46 | * 47 | * @return string 48 | */ 49 | public function getUrlPath($brand) 50 | { 51 | $path = $brand->getData('url_path'); 52 | if ($path === null) { 53 | $path = $brand->getUrlKey() === false 54 | ? $this->prepareBrandDefaultUrlKey($brand) 55 | : $this->prepareBrandUrlKey($brand); 56 | } 57 | return $path; 58 | } 59 | 60 | /** 61 | * Prepare URL Key with stored brand data (fallback for "Use Default Value" logic) 62 | * 63 | * @param \Dmatthew\Brand\Model\Brand $brand 64 | * @return string 65 | */ 66 | protected function prepareBrandDefaultUrlKey(\Dmatthew\Brand\Model\Brand $brand) 67 | { 68 | $storedBrand = $this->brandRepository->get($brand->getId()); 69 | $storedUrlKey = $storedBrand->getUrlKey(); 70 | return $storedUrlKey ?: $brand->formatUrlKey($storedBrand->getName()); 71 | } 72 | 73 | /** 74 | * Retrieve Brand Url path with suffix 75 | * 76 | * @param \Dmatthew\Brand\Model\Brand $brand 77 | * @param int $storeId 78 | * @return string 79 | */ 80 | public function getUrlPathWithSuffix($brand, $storeId) 81 | { 82 | return $this->getUrlPath($brand) . $this->getBrandUrlSuffix($storeId); 83 | } 84 | 85 | /** 86 | * Get canonical brand url path 87 | * 88 | * @param \Dmatthew\Brand\Model\Brand $brand 89 | * @return string 90 | */ 91 | public function getCanonicalUrlPath($brand) 92 | { 93 | $path = 'brand/brand/view/id/' . $brand->getId(); 94 | return $path; 95 | } 96 | 97 | /** 98 | * Generate brand url key based on url_key entered by merchant or brand name 99 | * 100 | * @param \Dmatthew\Brand\Model\Brand $brand 101 | * @return string 102 | */ 103 | public function getUrlKey($brand) 104 | { 105 | return $brand->getUrlKey() === false ? false : $this->prepareBrandUrlKey($brand); 106 | } 107 | 108 | /** 109 | * Prepare url key for brand 110 | * 111 | * @param \Dmatthew\Brand\Model\Brand $brand 112 | * @return string 113 | */ 114 | protected function prepareBrandUrlKey(\Dmatthew\Brand\Model\Brand $brand) 115 | { 116 | $urlKey = $brand->getUrlKey(); 117 | return $brand->formatUrlKey($urlKey === '' || $urlKey === null ? $brand->getName() : $urlKey); 118 | } 119 | 120 | /** 121 | * Retrieve brand rewrite suffix for store 122 | * 123 | * @param int $storeId 124 | * @return string 125 | */ 126 | protected function getBrandUrlSuffix($storeId = null) 127 | { 128 | if ($storeId === null) { 129 | $storeId = $this->storeManager->getStore()->getId(); 130 | } 131 | 132 | if (!isset($this->brandUrlSuffix[$storeId])) { 133 | $this->brandUrlSuffix[$storeId] = $this->scopeConfig->getValue( 134 | self::XML_PATH_BRAND_URL_SUFFIX, 135 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE, 136 | $storeId 137 | ); 138 | } 139 | return $this->brandUrlSuffix[$storeId]; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Model/Brand/CurrentUrlRewritesRegenerator.php: -------------------------------------------------------------------------------- 1 | urlFinder = $urlFinder; 42 | $this->brandUrlPathGenerator = $brandUrlPathGenerator; 43 | $this->urlRewriteFactory = $urlRewriteFactory; 44 | } 45 | 46 | /** 47 | * Generate list based on current rewrites 48 | * 49 | * @param int $storeId 50 | * @param Brand $brand 51 | * @return UrlRewrite[] 52 | */ 53 | public function generate($storeId, Brand $brand) 54 | { 55 | $this->brand = $brand; 56 | 57 | $currentUrlRewrites = $this->urlFinder->findAllByData( 58 | [ 59 | UrlRewrite::STORE_ID => $storeId, 60 | UrlRewrite::ENTITY_ID => $this->brand->getId(), 61 | UrlRewrite::ENTITY_TYPE => BrandUrlRewriteGenerator::ENTITY_TYPE, 62 | ] 63 | ); 64 | 65 | $urlRewrites = []; 66 | foreach ($currentUrlRewrites as $currentUrlRewrite) { 67 | $url = $currentUrlRewrite->getIsAutogenerated() 68 | ? $this->generateForAutogenerated($currentUrlRewrite, $storeId) 69 | : $this->generateForCustom($currentUrlRewrite, $storeId); 70 | $urlRewrites = array_merge($urlRewrites, $url); 71 | } 72 | 73 | $this->brand = null; 74 | return $urlRewrites; 75 | } 76 | 77 | /** 78 | * @param UrlRewrite $url 79 | * @param int $storeId 80 | * @return array 81 | */ 82 | protected function generateForAutogenerated($url, $storeId) 83 | { 84 | if (!$this->brand->getData('save_rewrites_history')) { 85 | return []; 86 | } 87 | $targetPath = $this->brandUrlPathGenerator->getUrlPathWithSuffix($this->brand, $storeId); 88 | if ($url->getRequestPath() === $targetPath) { 89 | return []; 90 | } 91 | return [ 92 | $this->urlRewriteFactory->create() 93 | ->setEntityType(BrandUrlRewriteGenerator::ENTITY_TYPE) 94 | ->setEntityId($this->brand->getId()) 95 | ->setRequestPath($url->getRequestPath()) 96 | ->setTargetPath($targetPath) 97 | ->setRedirectType(OptionProvider::PERMANENT) 98 | ->setStoreId($storeId) 99 | ->setDescription($url->getDescription()) 100 | ->setIsAutogenerated(0) 101 | ->setMetadata($url->getMetadata()) 102 | ]; 103 | } 104 | 105 | /** 106 | * @param UrlRewrite $url 107 | * @param int $storeId 108 | * @return array 109 | */ 110 | protected function generateForCustom($url, $storeId) 111 | { 112 | $targetPath = $url->getRedirectType() 113 | ? $this->brandUrlPathGenerator->getUrlPathWithSuffix($this->brand, $storeId) 114 | : $url->getTargetPath(); 115 | if ($url->getRequestPath() === $targetPath) { 116 | return []; 117 | } 118 | return [ 119 | $this->urlRewriteFactory->create() 120 | ->setEntityType(BrandUrlRewriteGenerator::ENTITY_TYPE) 121 | ->setEntityId($this->brand->getId()) 122 | ->setRequestPath($url->getRequestPath()) 123 | ->setTargetPath($targetPath) 124 | ->setRedirectType($url->getRedirectType()) 125 | ->setStoreId($storeId) 126 | ->setDescription($url->getDescription()) 127 | ->setIsAutogenerated(0) 128 | ->setMetadata($url->getMetadata()) 129 | ]; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Setup/BrandSetup.php: -------------------------------------------------------------------------------- 1 | brandFactory = $brandFactory; 38 | parent::__construct($setup, $context, $cache, $attrGroupCollectionFactory); 39 | } 40 | 41 | /** 42 | * Creates brand model 43 | * 44 | * @param array $data 45 | * @return \Dmatthew\Brand\Model\Brand 46 | * @codeCoverageIgnore 47 | */ 48 | public function createCategory($data = []) 49 | { 50 | return $this->brandFactory->create($data); 51 | } 52 | 53 | /** 54 | * Default entities and attributes 55 | * 56 | * @return array 57 | * @SuppressWarnings(PHPMD.ExcessiveMethodLength) 58 | */ 59 | public function getDefaultEntities() 60 | { 61 | return [ 62 | 'dmatthew_brand' => [ 63 | 'entity_model' => 'Dmatthew\Brand\Model\ResourceModel\Brand', 64 | 'attribute_model' => 'Magento\Catalog\Model\ResourceModel\Eav\Attribute', 65 | 'table' => 'brand_entity', 66 | 'entity_attribute_collection' => 'Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection', 67 | 'attributes' => [ 68 | 'name' => [ 69 | 'type' => 'varchar', 70 | 'label' => 'Name', 71 | 'input' => 'text', 72 | 'source' => 'Dmatthew\Brand\Model\Product\Attribute\Source\Brand', 73 | 'frontend_class' => 'validate-length maximum-length-255', 74 | 'sort_order' => 1, 75 | 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, 76 | ], 77 | 'description' => [ 78 | 'type' => 'text', 79 | 'label' => 'Description', 80 | 'input' => 'textarea', 81 | 'required' => false, 82 | 'sort_order' => 2, 83 | 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, 84 | 'wysiwyg_enabled' => true, 85 | 'is_html_allowed_on_front' => true, 86 | ], 87 | 'url_key' => [ 88 | 'type' => 'varchar', 89 | 'label' => 'URL Key', 90 | 'input' => 'text', 91 | 'required' => false, 92 | 'sort_order' => 3, 93 | 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, 94 | 'group' => 'General Information', 95 | ], 96 | 'meta_title' => [ 97 | 'type' => 'varchar', 98 | 'label' => 'Meta Title', 99 | 'input' => 'text', 100 | 'required' => false, 101 | 'sort_order' => 10, 102 | 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, 103 | ], 104 | 'meta_description' => [ 105 | 'type' => 'varchar', 106 | 'label' => 'Meta Description', 107 | 'input' => 'textarea', 108 | 'required' => false, 109 | 'note' => 'Maximum 255 chars', 110 | 'class' => 'validate-length maximum-length-255', 111 | 'sort_order' => 20, 112 | 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, 113 | ], 114 | ], 115 | ] 116 | ]; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Model/BrandUrlRewriteGenerator.php: -------------------------------------------------------------------------------- 1 | canonicalUrlRewriteGenerator = $canonicalUrlRewriteGenerator; 52 | $this->currentUrlRewritesRegenerator = $currentUrlRewritesRegenerator; 53 | $this->objectRegistryFactory = $objectRegistryFactory; 54 | $this->storeViewService = $storeViewService; 55 | $this->storeManager = $storeManager; 56 | } 57 | 58 | /** 59 | * Generate brand url rewrites 60 | * 61 | * @param \Dmatthew\Brand\Model\Brand $brand 62 | * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] 63 | */ 64 | public function generate(Brand $brand) 65 | { 66 | $this->brand = $brand; 67 | $storeId = $this->brand->getStoreId(); 68 | 69 | $urls = $this->isGlobalScope($storeId) 70 | ? $this->generateForGlobalScope() 71 | : $this->generateForSpecificStoreView($storeId); 72 | 73 | $this->brand = null; 74 | return $urls; 75 | } 76 | 77 | /** 78 | * Check is global scope 79 | * 80 | * @param int|null $storeId 81 | * @return bool 82 | */ 83 | protected function isGlobalScope($storeId) 84 | { 85 | return null === $storeId || $storeId == Store::DEFAULT_STORE_ID; 86 | } 87 | 88 | /** 89 | * Generate list of urls for global scope 90 | * 91 | * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] 92 | */ 93 | protected function generateForGlobalScope() 94 | { 95 | $urls = []; 96 | $brandId = $this->brand->getId(); 97 | foreach ($this->brand->getStoreIds() as $storeId) { 98 | if (!$this->isGlobalScope($storeId) 99 | && !$this->storeViewService->doesEntityHaveOverriddenUrlKeyForStore($storeId, $brandId, Brand::ENTITY) 100 | ) { 101 | $urls = array_merge($urls, $this->generateForSpecificStoreView($storeId)); 102 | } 103 | } 104 | return $urls; 105 | } 106 | 107 | /** 108 | * Generate list of urls for specific store view 109 | * 110 | * @param int $storeId 111 | * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] 112 | */ 113 | protected function generateForSpecificStoreView($storeId) 114 | { 115 | /** 116 | * @var $urls \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] 117 | */ 118 | $urls = array_merge( 119 | $this->canonicalUrlRewriteGenerator->generate($storeId, $this->brand), 120 | $this->currentUrlRewritesRegenerator->generate($storeId, $this->brand) 121 | ); 122 | 123 | /* Reduce duplicates. Last wins */ 124 | $result = []; 125 | foreach ($urls as $url) { 126 | $result[$url->getTargetPath() . '-' . $url->getStoreId()] = $url; 127 | } 128 | return $result; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /Model/Brand.php: -------------------------------------------------------------------------------- 1 | _url = $url; 104 | $this->filter = $filter; 105 | $this->urlFinder = $urlFinder; 106 | parent::__construct( 107 | $context, 108 | $registry, 109 | $extensionFactory, 110 | $customAttributeFactory, 111 | $storeManager, 112 | $resource, 113 | $resourceCollection, 114 | $data 115 | ); 116 | } 117 | 118 | /** 119 | * Initialize resource mode 120 | * 121 | * @return void 122 | */ 123 | protected function _construct() 124 | { 125 | $this->_init('Dmatthew\Brand\Model\ResourceModel\Brand'); 126 | } 127 | 128 | /** 129 | * Get identities 130 | * 131 | * @return array 132 | */ 133 | public function getIdentities() 134 | { 135 | $identities = [self::CACHE_TAG . '_' . $this->getId()]; 136 | return $identities; 137 | } 138 | 139 | /** 140 | * Get brand name 141 | * 142 | * @return string 143 | */ 144 | public function getName() 145 | { 146 | return $this->_getData(self::NAME); 147 | } 148 | 149 | /** 150 | * Set brand name 151 | * 152 | * @param string $name 153 | * @return $this 154 | */ 155 | public function setName($name) 156 | { 157 | return $this->setData(self::NAME, $name); 158 | } 159 | 160 | /** 161 | * Get brand description 162 | * 163 | * @return string 164 | */ 165 | public function getDescription() 166 | { 167 | return $this->_getData(self::DESCRIPTION); 168 | } 169 | 170 | /** 171 | * Set brand description 172 | * 173 | * @param string $description 174 | * @return $this 175 | */ 176 | public function setDescription($description) 177 | { 178 | return $this->setData(self::DESCRIPTION, $description); 179 | } 180 | 181 | /** 182 | * @return string|null 183 | */ 184 | public function getCreatedAt() 185 | { 186 | return $this->_getData(self::CREATED_AT); 187 | } 188 | 189 | /** 190 | * @param string $createdAt 191 | * @return $this 192 | */ 193 | public function setCreatedAt($createdAt) 194 | { 195 | return $this->setData(self::NAME, $createdAt); 196 | } 197 | 198 | /** 199 | * @return string|null 200 | */ 201 | public function getUpdatedAt() 202 | { 203 | return $this->_getData(self::UPDATED_AT); 204 | } 205 | 206 | /** 207 | * @param string $updatedAt 208 | * @return $this 209 | */ 210 | public function setUpdatedAt($updatedAt) 211 | { 212 | return $this->setData(self::NAME, $updatedAt); 213 | } 214 | 215 | /** 216 | * Retrieve Store Id 217 | * 218 | * @return int 219 | */ 220 | public function getStoreId() 221 | { 222 | if ($this->hasData(self::STORE_ID)) { 223 | return $this->getData(self::STORE_ID); 224 | } 225 | return $this->_storeManager->getStore()->getId(); 226 | } 227 | 228 | /** 229 | * Set brand store id 230 | * 231 | * @param int $storeId 232 | * @return $this 233 | */ 234 | public function setStoreId($storeId) 235 | { 236 | return $this->setData(self::STORE_ID, $storeId); 237 | } 238 | 239 | /** 240 | * Retrieve array of store ids for this brand. 241 | * 242 | * @return array 243 | */ 244 | public function getStoreIds() 245 | { 246 | if (!$this->hasStoreIds()) { 247 | $storeIds = []; 248 | if ($stores = $this->_storeManager->getStores()) { 249 | $storeIds = array_keys($stores); 250 | } 251 | $this->setStoreIds($storeIds); 252 | } 253 | return $this->getData('store_ids'); 254 | } 255 | 256 | /** 257 | * Format URL key from name or defined key 258 | * 259 | * @param string $str 260 | * @return string 261 | */ 262 | public function formatUrlKey($str) 263 | { 264 | return $this->filter->translitUrl($str); 265 | } 266 | 267 | /** 268 | * Retrieve URL instance 269 | * 270 | * @return \Magento\Framework\UrlInterface 271 | */ 272 | public function getUrlInstance() 273 | { 274 | return $this->_url; 275 | } 276 | 277 | /** 278 | * Get brand url. 279 | * 280 | * @return string 281 | */ 282 | public function getUrl() 283 | { 284 | $url = $this->_getData('url'); 285 | if ($url === null) { 286 | if ($this->hasData('request_path') && $this->getRequestPath() != '') { 287 | $this->setData('url', $this->getUrlInstance()->getDirectUrl($this->getRequestPath())); 288 | return $this->getData('url'); 289 | } 290 | 291 | $rewrite = $this->urlFinder->findOneByData([ 292 | UrlRewrite::ENTITY_ID => $this->getId(), 293 | UrlRewrite::ENTITY_TYPE => BrandUrlRewriteGenerator::ENTITY_TYPE, 294 | UrlRewrite::STORE_ID => $this->getStoreId(), 295 | ]); 296 | if ($rewrite) { 297 | $this->setData('url', $this->getUrlInstance()->getDirectUrl($rewrite->getRequestPath())); 298 | return $this->getData('url'); 299 | } 300 | 301 | $this->setData('url', $this->getBrandIdUrl()); 302 | return $this->getData('url'); 303 | } 304 | return $url; 305 | } 306 | 307 | /** 308 | * Retrieve brand id URL 309 | * 310 | * @return string 311 | */ 312 | public function getBrandIdUrl() 313 | { 314 | $url = $this->getUrlInstance()->getUrl('brand/brand/view', ['id' => $this->getId()]); 315 | return $url; 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /Setup/InstallSchema.php: -------------------------------------------------------------------------------- 1 | startSetup(); 23 | 24 | /** 25 | * Create table 'brand_entity' 26 | */ 27 | $table = $installer->getConnection() 28 | ->newTable($installer->getTable('brand_entity')) 29 | ->addColumn( 30 | 'entity_id', 31 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 32 | null, 33 | ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], 34 | 'Entity ID' 35 | ) 36 | ->addColumn( 37 | 'created_at', 38 | \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, 39 | null, 40 | ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT], 41 | 'Creation Time' 42 | ) 43 | ->addColumn( 44 | 'updated_at', 45 | \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, 46 | null, 47 | ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE], 48 | 'Update Time' 49 | ) 50 | ->setComment('Brand Table'); 51 | $installer->getConnection()->createTable($table); 52 | 53 | /** 54 | * Create table 'brand_entity_datetime' 55 | */ 56 | $table = $installer->getConnection() 57 | ->newTable($installer->getTable('brand_entity_datetime')) 58 | ->addColumn( 59 | 'value_id', 60 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 61 | null, 62 | ['identity' => true, 'nullable' => false, 'primary' => true], 63 | 'Value ID' 64 | ) 65 | ->addColumn( 66 | 'attribute_id', 67 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 68 | null, 69 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 70 | 'Attribute ID' 71 | ) 72 | ->addColumn( 73 | 'store_id', 74 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 75 | null, 76 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 77 | 'Store ID' 78 | ) 79 | ->addColumn( 80 | 'entity_id', 81 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 82 | null, 83 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 84 | 'Entity ID' 85 | ) 86 | ->addColumn( 87 | 'value', 88 | \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME, 89 | null, 90 | [], 91 | 'Value' 92 | ) 93 | ->addIndex( 94 | $installer->getIdxName( 95 | 'brand_entity_datetime', 96 | ['entity_id', 'attribute_id', 'store_id'], 97 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE 98 | ), 99 | ['entity_id', 'attribute_id', 'store_id'], 100 | ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] 101 | ) 102 | ->addIndex( 103 | $installer->getIdxName('brand_entity_datetime', ['attribute_id']), 104 | ['attribute_id'] 105 | ) 106 | ->addIndex( 107 | $installer->getIdxName('brand_entity_datetime', ['store_id']), 108 | ['store_id'] 109 | ) 110 | ->addForeignKey( 111 | $installer->getFkName( 112 | 'brand_entity_datetime', 113 | 'attribute_id', 114 | 'eav_attribute', 115 | 'attribute_id' 116 | ), 117 | 'attribute_id', 118 | $installer->getTable('eav_attribute'), 119 | 'attribute_id', 120 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 121 | ) 122 | ->addForeignKey( 123 | $installer->getFkName( 124 | 'brand_entity_datetime', 125 | 'entity_id', 126 | 'brand_entity', 127 | 'entity_id' 128 | ), 129 | 'entity_id', 130 | $installer->getTable('brand_entity'), 131 | 'entity_id', 132 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 133 | ) 134 | ->addForeignKey( 135 | $installer->getFkName('brand_entity_datetime', 'store_id', 'store', 'store_id'), 136 | 'store_id', 137 | $installer->getTable('store'), 138 | 'store_id', 139 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 140 | ) 141 | ->setComment('Brand Datetime Attribute Backend Table'); 142 | $installer->getConnection()->createTable($table); 143 | 144 | /** 145 | * Create table 'brand_entity_decimal' 146 | */ 147 | $table = $installer->getConnection() 148 | ->newTable($installer->getTable('brand_entity_decimal')) 149 | ->addColumn( 150 | 'value_id', 151 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 152 | null, 153 | ['identity' => true, 'nullable' => false, 'primary' => true], 154 | 'Value ID' 155 | ) 156 | ->addColumn( 157 | 'attribute_id', 158 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 159 | null, 160 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 161 | 'Attribute ID' 162 | ) 163 | ->addColumn( 164 | 'store_id', 165 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 166 | null, 167 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 168 | 'Store ID' 169 | ) 170 | ->addColumn( 171 | 'entity_id', 172 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 173 | null, 174 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 175 | 'Entity ID' 176 | ) 177 | ->addColumn( 178 | 'value', 179 | \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, 180 | '12,4', 181 | [], 182 | 'Value' 183 | ) 184 | ->addIndex( 185 | $installer->getIdxName( 186 | 'brand_entity_decimal', 187 | ['entity_id', 'attribute_id', 'store_id'], 188 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE 189 | ), 190 | ['entity_id', 'attribute_id', 'store_id'], 191 | ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] 192 | ) 193 | ->addIndex( 194 | $installer->getIdxName('brand_entity_decimal', ['store_id']), 195 | ['store_id'] 196 | ) 197 | ->addIndex( 198 | $installer->getIdxName('brand_entity_decimal', ['attribute_id']), 199 | ['attribute_id'] 200 | ) 201 | ->addForeignKey( 202 | $installer->getFkName( 203 | 'brand_entity_decimal', 204 | 'attribute_id', 205 | 'eav_attribute', 206 | 'attribute_id' 207 | ), 208 | 'attribute_id', 209 | $installer->getTable('eav_attribute'), 210 | 'attribute_id', 211 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 212 | ) 213 | ->addForeignKey( 214 | $installer->getFkName( 215 | 'brand_entity_decimal', 216 | 'entity_id', 217 | 'brand_entity', 218 | 'entity_id' 219 | ), 220 | 'entity_id', 221 | $installer->getTable('brand_entity'), 222 | 'entity_id', 223 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 224 | ) 225 | ->addForeignKey( 226 | $installer->getFkName('brand_entity_decimal', 'store_id', 'store', 'store_id'), 227 | 'store_id', 228 | $installer->getTable('store'), 229 | 'store_id', 230 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 231 | ) 232 | ->setComment('Brand Decimal Attribute Backend Table'); 233 | $installer->getConnection()->createTable($table); 234 | 235 | /** 236 | * Create table 'brand_entity_int' 237 | */ 238 | $table = $installer->getConnection() 239 | ->newTable($installer->getTable('brand_entity_int')) 240 | ->addColumn( 241 | 'value_id', 242 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 243 | null, 244 | ['identity' => true, 'nullable' => false, 'primary' => true], 245 | 'Value ID' 246 | ) 247 | ->addColumn( 248 | 'attribute_id', 249 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 250 | null, 251 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 252 | 'Attribute ID' 253 | ) 254 | ->addColumn( 255 | 'store_id', 256 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 257 | null, 258 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 259 | 'Store ID' 260 | ) 261 | ->addColumn( 262 | 'entity_id', 263 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 264 | null, 265 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 266 | 'Entity ID' 267 | ) 268 | ->addColumn( 269 | 'value', 270 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 271 | null, 272 | [], 273 | 'Value' 274 | ) 275 | ->addIndex( 276 | $installer->getIdxName( 277 | 'brand_entity_int', 278 | ['entity_id', 'attribute_id', 'store_id'], 279 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE 280 | ), 281 | ['entity_id', 'attribute_id', 'store_id'], 282 | ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] 283 | ) 284 | ->addIndex( 285 | $installer->getIdxName('brand_entity_int', ['attribute_id']), 286 | ['attribute_id'] 287 | ) 288 | ->addIndex( 289 | $installer->getIdxName('brand_entity_int', ['store_id']), 290 | ['store_id'] 291 | ) 292 | ->addForeignKey( 293 | $installer->getFkName('brand_entity_int', 'attribute_id', 'eav_attribute', 'attribute_id'), 294 | 'attribute_id', 295 | $installer->getTable('eav_attribute'), 296 | 'attribute_id', 297 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 298 | ) 299 | ->addForeignKey( 300 | $installer->getFkName('brand_entity_int', 'entity_id', 'brand_entity', 'entity_id'), 301 | 'entity_id', 302 | $installer->getTable('brand_entity'), 303 | 'entity_id', 304 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 305 | ) 306 | ->addForeignKey( 307 | $installer->getFkName('brand_entity_int', 'store_id', 'store', 'store_id'), 308 | 'store_id', 309 | $installer->getTable('store'), 310 | 'store_id', 311 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 312 | ) 313 | ->setComment('Brand Integer Attribute Backend Table'); 314 | $installer->getConnection()->createTable($table); 315 | 316 | /** 317 | * Create table 'brand_entity_text' 318 | */ 319 | $table = $installer->getConnection() 320 | ->newTable($installer->getTable('brand_entity_text')) 321 | ->addColumn( 322 | 'value_id', 323 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 324 | null, 325 | ['identity' => true, 'nullable' => false, 'primary' => true], 326 | 'Value ID' 327 | ) 328 | ->addColumn( 329 | 'attribute_id', 330 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 331 | null, 332 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 333 | 'Attribute ID' 334 | ) 335 | ->addColumn( 336 | 'store_id', 337 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 338 | null, 339 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 340 | 'Store ID' 341 | ) 342 | ->addColumn( 343 | 'entity_id', 344 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 345 | null, 346 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 347 | 'Entity ID' 348 | ) 349 | ->addColumn( 350 | 'value', 351 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 352 | '64k', 353 | [], 354 | 'Value' 355 | ) 356 | ->addIndex( 357 | $installer->getIdxName( 358 | 'brand_entity_text', 359 | ['entity_id', 'attribute_id', 'store_id'], 360 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE 361 | ), 362 | ['entity_id', 'attribute_id', 'store_id'], 363 | ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] 364 | ) 365 | ->addIndex( 366 | $installer->getIdxName('brand_entity_text', ['attribute_id']), 367 | ['attribute_id'] 368 | ) 369 | ->addIndex( 370 | $installer->getIdxName('brand_entity_text', ['store_id']), 371 | ['store_id'] 372 | ) 373 | ->addForeignKey( 374 | $installer->getFkName( 375 | 'brand_entity_text', 376 | 'attribute_id', 377 | 'eav_attribute', 378 | 'attribute_id' 379 | ), 380 | 'attribute_id', 381 | $installer->getTable('eav_attribute'), 382 | 'attribute_id', 383 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 384 | ) 385 | ->addForeignKey( 386 | $installer->getFkName( 387 | 'brand_entity_text', 388 | 'entity_id', 389 | 'brand_entity', 390 | 'entity_id' 391 | ), 392 | 'entity_id', 393 | $installer->getTable('brand_entity'), 394 | 'entity_id', 395 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 396 | ) 397 | ->addForeignKey( 398 | $installer->getFkName('brand_entity_text', 'store_id', 'store', 'store_id'), 399 | 'store_id', 400 | $installer->getTable('store'), 401 | 'store_id', 402 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 403 | ) 404 | ->setComment('Brand Text Attribute Backend Table'); 405 | $installer->getConnection()->createTable($table); 406 | 407 | /** 408 | * Create table 'brand_entity_varchar' 409 | */ 410 | $table = $installer->getConnection() 411 | ->newTable($installer->getTable('brand_entity_varchar')) 412 | ->addColumn( 413 | 'value_id', 414 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 415 | null, 416 | ['identity' => true, 'nullable' => false, 'primary' => true], 417 | 'Value ID' 418 | ) 419 | ->addColumn( 420 | 'attribute_id', 421 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 422 | null, 423 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 424 | 'Attribute ID' 425 | ) 426 | ->addColumn( 427 | 'store_id', 428 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 429 | null, 430 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 431 | 'Store ID' 432 | ) 433 | ->addColumn( 434 | 'entity_id', 435 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 436 | null, 437 | ['unsigned' => true, 'nullable' => false, 'default' => '0'], 438 | 'Entity ID' 439 | ) 440 | ->addColumn( 441 | 'value', 442 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 443 | 255, 444 | [], 445 | 'Value' 446 | ) 447 | ->addIndex( 448 | $installer->getIdxName( 449 | 'brand_entity_varchar', 450 | ['entity_id', 'attribute_id', 'store_id'], 451 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE 452 | ), 453 | ['entity_id', 'attribute_id', 'store_id'], 454 | ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] 455 | ) 456 | ->addIndex( 457 | $installer->getIdxName('brand_entity_varchar', ['attribute_id']), 458 | ['attribute_id'] 459 | ) 460 | ->addIndex( 461 | $installer->getIdxName('brand_entity_varchar', ['store_id']), 462 | ['store_id'] 463 | ) 464 | ->addForeignKey( 465 | $installer->getFkName( 466 | 'brand_entity_varchar', 467 | 'attribute_id', 468 | 'eav_attribute', 469 | 'attribute_id' 470 | ), 471 | 'attribute_id', 472 | $installer->getTable('eav_attribute'), 473 | 'attribute_id', 474 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 475 | ) 476 | ->addForeignKey( 477 | $installer->getFkName( 478 | 'brand_entity_varchar', 479 | 'entity_id', 480 | 'brand_entity', 481 | 'entity_id' 482 | ), 483 | 'entity_id', 484 | $installer->getTable('brand_entity'), 485 | 'entity_id', 486 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 487 | ) 488 | ->addForeignKey( 489 | $installer->getFkName('brand_entity_varchar', 'store_id', 'store', 'store_id'), 490 | 'store_id', 491 | $installer->getTable('store'), 492 | 'store_id', 493 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 494 | ) 495 | ->setComment('Brand Varchar Attribute Backend Table'); 496 | $installer->getConnection()->createTable($table); 497 | } 498 | } --------------------------------------------------------------------------------