diff --git a/Api/Data/NodeInterface.php b/Api/Data/NodeInterface.php index 113bfef9..82d1a22f 100644 --- a/Api/Data/NodeInterface.php +++ b/Api/Data/NodeInterface.php @@ -25,6 +25,7 @@ interface NodeInterface const IS_ACTIVE = 'is_active'; const ADDITIONAL_DATA = 'additional_data'; const SELECTED_ITEM_ID = 'selected_item_id'; + const CUSTOMER_GROUPS = 'customer_groups'; /** * Get node id @@ -298,4 +299,21 @@ public function getSelectedItemId(); * @return $this */ public function setSelectedItemId($selectedItemId); + + /** + * Get customer groups + * + */ + public function getCustomerGroups(); + + /** + * @return $this + */ + public function setCustomerGroups($customerGroups); + + /** + * @param int $customerGroupId + * @return bool + */ + public function isVisible($customerGroupId); } diff --git a/Block/Adminhtml/Edit/Tab/Nodes.php b/Block/Adminhtml/Edit/Tab/Nodes.php index 5e2fa62c..17e90769 100644 --- a/Block/Adminhtml/Edit/Tab/Nodes.php +++ b/Block/Adminhtml/Edit/Tab/Nodes.php @@ -7,6 +7,7 @@ use Magento\Framework\Registry; use Snowdog\Menu\Api\NodeRepositoryInterface; use Snowdog\Menu\Controller\Adminhtml\Menu\Edit; +use Snowdog\Menu\Model\CustomerGroupsProvider; use Snowdog\Menu\Model\Menu\Node\Image\File as ImageFile; use Snowdog\Menu\Model\NodeTypeProvider; use Snowdog\Menu\Model\VueProvider; @@ -45,6 +46,11 @@ class Nodes extends Template implements TabInterface */ private $vueProvider; + /** + * @var CustomerGroupsProvider + */ + private $customerGroupsProvider; + public function __construct( Template\Context $context, NodeRepositoryInterface $nodeRepository, @@ -52,6 +58,7 @@ public function __construct( NodeTypeProvider $nodeTypeProvider, Registry $registry, VueProvider $vueProvider, + CustomerGroupsProvider $customerGroupsProvider, array $data = [] ) { parent::__construct($context, $data); @@ -60,6 +67,7 @@ public function __construct( $this->nodeTypeProvider = $nodeTypeProvider; $this->imageFile = $imageFile; $this->vueProvider = $vueProvider; + $this->customerGroupsProvider = $customerGroupsProvider; } public function renderNodes() @@ -185,7 +193,8 @@ private function renderNodeList($level, $parent, $data) 'image_width' => $node->getImageWidth(), 'image_height' => $node->getImageHeight(), 'columns' => $this->renderNodeList($level + 1, $node->getId(), $data) ?: [], - 'selected_item_id' => $node->getSelectedItemId() + 'selected_item_id' => $node->getSelectedItemId(), + 'customer_groups' => $node->getCustomerGroups() ]; } return $menu; @@ -208,4 +217,9 @@ public function getVueComponents(): array { return $this->vueProvider->getComponents(); } + + public function getCustomerGroups() + { + return $this->customerGroupsProvider->getAll(); + } } diff --git a/Block/Menu.php b/Block/Menu.php index 9ce9f743..dd076269 100644 --- a/Block/Menu.php +++ b/Block/Menu.php @@ -2,9 +2,8 @@ namespace Snowdog\Menu\Block; -use Magento\Framework\Api\Search\FilterGroupBuilder; -use Magento\Framework\Api\Search\SearchCriteriaFactory; use Magento\Framework\App\Cache\Type\Block; +use Magento\Framework\App\Http\Context; use Magento\Framework\DataObject; use Magento\Framework\View\Element\Template; use Magento\Framework\Event\Manager as EventManager; @@ -19,9 +18,13 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class Menu extends Template implements DataObject\IdentityInterface { + const XML_SNOWMENU_GENERAL_CUSTOMER_GROUPS = 'snowmenu/general/customer_groups'; + /** * @var MenuRepositoryInterface */ @@ -41,15 +44,6 @@ class Menu extends Template implements DataObject\IdentityInterface private $menu = null; - /** - * @var SearchCriteriaFactory - */ - private $searchCriteriaFactory; - - /** - * @var FilterGroupBuilder - */ - private $filterGroupBuilder; /** * @var EventManager */ @@ -85,6 +79,11 @@ class Menu extends Template implements DataObject\IdentityInterface */ private $escaper; + /** + * @var Context + */ + private $httpContext; + /** * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -94,25 +93,23 @@ public function __construct( MenuRepositoryInterface $menuRepository, NodeRepositoryInterface $nodeRepository, NodeTypeProvider $nodeTypeProvider, - SearchCriteriaFactory $searchCriteriaFactory, - FilterGroupBuilder $filterGroupBuilder, TemplateResolver $templateResolver, ImageFile $imageFile, Escaper $escaper, + Context $httpContext, array $data = [] ) { parent::__construct($context, $data); $this->menuRepository = $menuRepository; $this->nodeRepository = $nodeRepository; $this->nodeTypeProvider = $nodeTypeProvider; - $this->searchCriteriaFactory = $searchCriteriaFactory; - $this->filterGroupBuilder = $filterGroupBuilder; $this->eventManager = $eventManager; $this->templateResolver = $templateResolver; $this->imageFile = $imageFile; $this->escaper = $escaper; $this->setTemplate($this->getMenuTemplate($this->_template)); $this->submenuTemplate = $this->getSubmenuTemplate(); + $this->httpContext = $httpContext; } /** @@ -178,6 +175,9 @@ public function getCacheKeyInfo() if ($nodeCacheKeyInfo) { $info = array_merge($info, $nodeCacheKeyInfo); } + if ($this->_scopeConfig->isSetFlag(self::XML_SNOWMENU_GENERAL_CUSTOMER_GROUPS)) { + $info[] = 'cust_group_' . $this->getCustomerGroupId(); + } return $info; } @@ -410,7 +410,8 @@ private function getMenuNodeBlock($node) ->setImageAltText($node->getImageAltText()) ->setCustomTemplate($node->getNodeTemplate()) ->setAdditionalData($node->getAdditionalData()) - ->setSelectedItemId($node->getSelectedItemId()); + ->setSelectedItemId($node->getSelectedItemId()) + ->setCustomerGroups($node->getCustomerGroups()); return $nodeBlock; } @@ -442,12 +443,17 @@ private function getSubmenuBlock($nodes, $parentNode, $level = 0) private function fetchData() { $nodes = $this->nodeRepository->getByMenu($this->loadMenu()->getId()); + $currentCustomerGroup = $this->getCustomerGroupId(); + $customerGroupEnabled = $this->_scopeConfig->getValue(self::XML_SNOWMENU_GENERAL_CUSTOMER_GROUPS); $result = []; $types = []; foreach ($nodes as $node) { if (!$node->getIsActive()) { continue; } + if ($customerGroupEnabled && !$node->isVisible($currentCustomerGroup)) { + continue; + } $level = $node->getLevel(); $parent = $node->getParentId() ?: 0; @@ -502,4 +508,9 @@ private function getSubmenuTemplate() return $this->getMenuTemplate($baseSubmenuTemplate); } + + public function getCustomerGroupId() + { + return $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_GROUP); + } } diff --git a/CHANGELOG.md b/CHANGELOG.md index ea883ebe..b45da1ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added - `width` and `height` attributes to menu node images (DEV-102271) +- Option to specify customer groups for each node (DEV-94738) - Snowdog branding in admin panel (DEV-105762) - Automatically open collapsed menu node when dragging another node inside (DEV-101986) - Duplicate node functionality (DEV-104364) diff --git a/Model/CustomerGroupsProvider.php b/Model/CustomerGroupsProvider.php new file mode 100644 index 00000000..ca5a9197 --- /dev/null +++ b/Model/CustomerGroupsProvider.php @@ -0,0 +1,35 @@ +groupCollectionFactory = $groupCollectionFactory; + } + + public function getAll() + { + $customerGroups = []; + + /** @var Group $customerGroup */ + foreach ($this->groupCollectionFactory->create() as $customerGroup) { + $customerGroups[] = [ + 'label' => $customerGroup->getCode(), + 'value' => $customerGroup->getId() + ]; + } + + return $customerGroups; + } +} diff --git a/Model/GraphQl/Resolver/DataProvider/Node.php b/Model/GraphQl/Resolver/DataProvider/Node.php index 6b5e7665..6c52e85e 100644 --- a/Model/GraphQl/Resolver/DataProvider/Node.php +++ b/Model/GraphQl/Resolver/DataProvider/Node.php @@ -111,7 +111,9 @@ private function convertData(NodeInterface $node): array self::SUBMENU_TEMPLATE_FIELD => $node->getSubmenuTemplate(), NodeInterface::CREATION_TIME => $node->getCreationTime(), NodeInterface::UPDATE_TIME => $node->getUpdateTime(), - NodeInterface::ADDITIONAL_DATA => $node->getAdditionalData() + NodeInterface::ADDITIONAL_DATA => $node->getAdditionalData(), + NodeInterface::SELECTED_ITEM_ID => $node->getSelectedItemId(), + NodeInterface::CUSTOMER_GROUPS => $node->getCustomerGroups() ]; } diff --git a/Model/Menu/Node.php b/Model/Menu/Node.php index 4e39d4a4..4291d991 100644 --- a/Model/Menu/Node.php +++ b/Model/Menu/Node.php @@ -1,14 +1,36 @@ serializer = $serializer; + } + protected function _construct() { $this->_init(\Snowdog\Menu\Model\ResourceModel\Menu\Node::class); @@ -325,4 +347,48 @@ public function setSelectedItemId($selectedItemId) { return $this->setData(NodeInterface::SELECTED_ITEM_ID, $selectedItemId); } + + public function getCustomerGroups() + { + $customerGroups = $this->_getData(NodeInterface::CUSTOMER_GROUPS); + if ($customerGroups == null) { + return []; + } + $customerGroups = explode(',', $customerGroups); + if (is_array($customerGroups) && !empty($customerGroups)) { + return $customerGroups; + } + + return []; + } + + public function setCustomerGroups($customerGroups) + { + if (empty($customerGroups)) { + $this->setData(NodeInterface::CUSTOMER_GROUPS); + return $this; + } + + if (is_string($customerGroups) && $this->serializer->unserialize($customerGroups)) { + return $this->setData(NodeInterface::CUSTOMER_GROUPS, $customerGroups); + } + + return $this->setData(NodeInterface::CUSTOMER_GROUPS, $this->serializer->serialize($customerGroups)); + } + + public function isVisible($customerGroupId) + { + $customerGroups = $this->getCustomerGroups(); + if (empty($customerGroups)) { + return true; + } + + foreach ($customerGroups as $customerGroup) { + if ((int) $customerGroup === (int) $customerGroupId) { + return true; + } + } + + return false; + } } diff --git a/Model/Menu/Node/Image/Node.php b/Model/Menu/Node/Image/Node.php index 8eef98b0..1ac72231 100644 --- a/Model/Menu/Node/Image/Node.php +++ b/Model/Menu/Node/Image/Node.php @@ -67,7 +67,7 @@ public function updateNodeImage(int $nodeId, ?string $image): void public function getNodeListImages(array $nodeIds): array { $searchCriteria = $this->searchCriteriaBuilder - ->addFilter(NodeInterface::NODE_ID, $nodeIds, 'in') + ->addFilter('main_table.' . NodeInterface::NODE_ID, $nodeIds, 'in') ->addFilter(NodeInterface::IMAGE, true, 'notnull') ->addFilter(NodeInterface::IMAGE, '', 'neq') ->create(); diff --git a/Model/Menu/NodeRepository.php b/Model/Menu/NodeRepository.php index dc69be42..5ef0831f 100644 --- a/Model/Menu/NodeRepository.php +++ b/Model/Menu/NodeRepository.php @@ -15,6 +15,7 @@ use Snowdog\Menu\Model\Menu\NodeFactory; use Snowdog\Menu\Model\ResourceModel\Menu\Node\CollectionFactory; use Magento\Framework\Api\SortOrder; +use Magento\Framework\DB\Sql\Expression; class NodeRepository implements NodeRepositoryInterface { diff --git a/Model/ResourceModel/Menu/Node.php b/Model/ResourceModel/Menu/Node.php index 4f65adc5..8f0609fd 100644 --- a/Model/ResourceModel/Menu/Node.php +++ b/Model/ResourceModel/Menu/Node.php @@ -4,15 +4,52 @@ namespace Snowdog\Menu\Model\ResourceModel\Menu; +use Magento\Framework\Model\AbstractModel; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Context; +use Magento\Framework\Serialize\SerializerInterface; class Node extends AbstractDb { + protected $serializer; + + public function __construct( + Context $context, + SerializerInterface $serializer, + $connectionName = null + ) { + $this->serializer = $serializer; + parent::__construct($context, $connectionName); + } + protected function _construct() { $this->_init('snowmenu_node', 'node_id'); } + protected function _afterSave(AbstractModel $object) + { + $connection = $this->getConnection(); + $connection->delete('snowmenu_customer', ['node_id = ?' => $object->getNodeId()]); + + $nodeCustomerGroups = $object->getData('customer_groups'); + if ($nodeCustomerGroups && is_string($nodeCustomerGroups)) { + $nodeCustomerGroups = $this->serializer->unserialize($nodeCustomerGroups); + } + $insertData = []; + foreach ($nodeCustomerGroups ?? [] as $customerGroup) { + $insertData[] = [ + 'node_id' => $object->getNodeId(), + 'group_id' => $customerGroup + ]; + } + if ($nodeCustomerGroups) { + $connection->insertMultiple('snowmenu_customer', $insertData); + } + + return parent::_afterSave($object); + } + public function getFields(): array { return $this->getConnection()->describeTable($this->getMainTable()); diff --git a/Model/ResourceModel/Menu/Node/Collection.php b/Model/ResourceModel/Menu/Node/Collection.php index dc015074..3076fecc 100644 --- a/Model/ResourceModel/Menu/Node/Collection.php +++ b/Model/ResourceModel/Menu/Node/Collection.php @@ -1,10 +1,37 @@ scopeConfig = $scopeConfig; + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource); + } + protected function _construct() { $this->_init( @@ -12,4 +39,21 @@ protected function _construct() \Snowdog\Menu\Model\ResourceModel\Menu\Node::class ); } + + protected function _initSelect() + { + parent::_initSelect(); + + if (!$this->scopeConfig->isSetFlag(Menu::XML_SNOWMENU_GENERAL_CUSTOMER_GROUPS)) { + return $this; + } + + $this->getSelect()->joinLeft( + ['customer' => 'snowmenu_customer'], + 'main_table.node_id = customer.node_id', + ['customer_groups' => new Expression('GROUP_CONCAT(group_id SEPARATOR \',\')')] + )->group('main_table.node_id'); + + return $this; + } } diff --git a/Service/Menu/SaveRequestProcessor.php b/Service/Menu/SaveRequestProcessor.php index c2c765c4..219a8072 100644 --- a/Service/Menu/SaveRequestProcessor.php +++ b/Service/Menu/SaveRequestProcessor.php @@ -205,8 +205,12 @@ private function processNodeObject( $this->processImageParameters($nodeData, $nodeObject); $nodeObject->setSelectedItemId($nodeData['selected_item_id'] ?? null); + $nodeObject->setCustomerGroups($nodeData[NodeInterface::CUSTOMER_GROUPS] ?? null); } + /** + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ private function processImageParameters(array $nodeData, NodeInterface &$nodeObject): void { $nodeObject->setImageAltText($nodeData[NodeInterface::IMAGE_ALT_TEXT] ?? null); @@ -230,7 +234,11 @@ private function processImageParameters(array $nodeData, NodeInterface &$nodeObj if (empty($nodeData[NodeInterface::IMAGE_WIDTH]) || empty($nodeData[NodeInterface::IMAGE_HEIGHT]) ) { - $imageSize = $this->nodeImageFile->getImageSize($nodeData[NodeInterface::IMAGE]); + try { + $imageSize = $this->nodeImageFile->getImageSize($nodeData[NodeInterface::IMAGE]); + } catch (\Exception $e) { + $imageSize = null; + } if (!empty($imageSize)) { $nodeObject diff --git a/Setup/InstallData.php b/Setup/InstallData.php deleted file mode 100644 index 57212099..00000000 --- a/Setup/InstallData.php +++ /dev/null @@ -1,16 +0,0 @@ -startSetup(); - - $table = $installer->getConnection()->newTable( - $installer->getTable('snowmenu_menu') - )->addColumn( - 'menu_id', - Table::TYPE_INTEGER, - null, - ['identity' => true, 'nullable' => false, 'primary' => true, 'unsigned' => true,], - 'Entity ID' - )->addColumn( - 'title', - Table::TYPE_TEXT, - 255, - ['nullable' => false,], - 'Demo Title' - )->addColumn( - 'identifier', - Table::TYPE_TEXT, - 255, - ['nullable' => false], - 'Menu identifier' - )->addColumn( - 'creation_time', - Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => Table::TIMESTAMP_INIT,], - 'Creation Time' - )->addColumn( - 'update_time', - Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => Table::TIMESTAMP_INIT_UPDATE,], - 'Modification Time' - )->addColumn( - 'is_active', - Table::TYPE_SMALLINT, - null, - ['nullable' => false, 'default' => '1',], - 'Is Active' - ); - $installer->getConnection()->createTable($table); - - $table = $installer->getConnection()->newTable( - $installer->getTable('snowmenu_node') - )->addColumn( - 'node_id', - Table::TYPE_INTEGER, - null, - ['identity' => true, 'nullable' => false, 'primary' => true, 'unsigned' => true,], - 'Node ID' - )->addColumn( - 'menu_id', - Table::TYPE_INTEGER, - null, - ['nullable' => false], - 'Menu ID' - )->addColumn( - 'type', - Table::TYPE_TEXT, - 255, - ['nullable' => false], - 'Node Type' - )->addColumn( - 'content', - Table::TYPE_TEXT, - null, - [], - 'Node contents' - )->addColumn( - 'classes', - Table::TYPE_TEXT, - 255, - [], - 'CSS class name' - )->addColumn( - 'parent_id', - Table::TYPE_INTEGER, - null, - ['unsigned' => true], - 'Parent Node ID' - )->addColumn( - 'position', - Table::TYPE_INTEGER, - null, - ['nullable' => false, 'unsigned' => true], - 'Node position' - )->addColumn( - 'level', - Table::TYPE_INTEGER, - null, - ['nullable' => false, 'unsigned' => true], - 'Node level' - )->addColumn( - 'title', - Table::TYPE_TEXT, - 255, - ['nullable' => false,], - 'Demo Title' - )->addColumn( - 'creation_time', - Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => Table::TIMESTAMP_INIT,], - 'Creation Time' - )->addColumn( - 'update_time', - Table::TYPE_TIMESTAMP, - null, - ['nullable' => false, 'default' => Table::TIMESTAMP_INIT_UPDATE,], - 'Modification Time' - )->addColumn( - 'is_active', - Table::TYPE_SMALLINT, - null, - ['nullable' => false, 'default' => '1',], - 'Is Active' - ); - $installer->getConnection()->createTable($table); - - $table = $installer->getConnection()->newTable( - $installer->getTable('snowmenu_store') - )->addColumn( - 'menu_id', - Table::TYPE_INTEGER, - null, - ['nullable' => false, 'primary' => true, 'unsigned' => true,], - 'Menu ID' - )->addColumn( - 'store_id', - Table::TYPE_INTEGER, - null, - ['nullable' => false, 'primary' => true, 'unsigned' => true,], - 'Store ID' - ); - $installer->getConnection()->createTable($table); - - $installer->endSetup(); - } -} diff --git a/Setup/UpgradeSchema.php b/Setup/UpgradeSchema.php deleted file mode 100644 index 0135c16d..00000000 --- a/Setup/UpgradeSchema.php +++ /dev/null @@ -1,339 +0,0 @@ -. - * @category - * @package - * @copyright Copyright Snowdog (http://snow.dog) - */ - -namespace Snowdog\Menu\Setup; - -use Magento\Framework\DB\Ddl\Table; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\SchemaSetupInterface; -use Magento\Framework\Setup\UpgradeSchemaInterface; -use Snowdog\Menu\Api\Data\NodeInterface; - -// @codingStandardsIgnoreFile -class UpgradeSchema implements UpgradeSchemaInterface -{ - /** - * {@inheritdoc} - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) - { - $setup->startSetup(); - - if (version_compare($context->getVersion(), '0.1.0', '<')) { - $this->changeTitleType($setup); - } - - if (version_compare($context->getVersion(), '0.2.0', '<')) { - $this->addMenuCssClassField($setup); - } - - if (version_compare($context->getVersion(), '0.2.1', '<')) { - $this->addTargetAttribute($setup); - } - - if (version_compare($context->getVersion(), '0.2.2', '<')) { - $this->updateTargetAttribute($setup); - } - - if (version_compare($context->getVersion(), '0.2.3', '<')) { - $this->addForeignKeys($setup); - } - - if (version_compare($context->getVersion(), '0.2.4', '<')) { - $this->addTemplateFields($setup); - } - - if (version_compare($context->getVersion(), '0.2.5', '<')) { - $this->addNodeImageFields($setup); - } - - if (version_compare($context->getVersion(), '0.2.6', '<')) { - $this->addNodeSelectedItemId($setup); - } - - if (version_compare($context->getVersion(), '0.2.7', '<')) { - $this->addNodeImageSizeFields($setup); - } - - $setup->endSetup(); - } - - /** - * @param SchemaSetupInterface $setup - * @return $this - */ - private function addMenuCssClassField(SchemaSetupInterface $setup) - { - $setup->getConnection()->addColumn( - $setup->getTable('snowmenu_menu'), - 'css_class', - [ - 'type' => Table::TYPE_TEXT, - 'length' => 255, - 'nullable' => true, - 'after' => 'identifier', - 'default' => 'menu', - 'comment' => 'CSS Class' - ] - ); - - return $this; - } - - private function changeTitleType(SchemaSetupInterface $setup) - { - $setup->getConnection()->modifyColumn( - $setup->getTable('snowmenu_node'), - 'title', - [ - 'type' => Table::TYPE_TEXT, - 'nullable' => false - ], - 'Demo Title' - ); - } - - private function addTargetAttribute(SchemaSetupInterface $setup) - { - $setup->getConnection()->addColumn( - $setup->getTable('snowmenu_node'), - 'target', - [ - 'type' => Table::TYPE_TEXT, - 'length' => 10, - 'nullable' => true, - 'after' => 'title', - 'default' => '_self', - 'comment' => 'Link target', - ] - ); - - return $this; - } - - private function updateTargetAttribute(SchemaSetupInterface $setup) - { - $table = $setup->getTable('snowmenu_node'); - $connection = $setup->getConnection(); - - $connection->update( - $table, - ['target' => 0], - "target = '_self'" - ); - $connection->update( - $table, - ['target' => 1], - "target = '_blank'" - ); - $connection->modifyColumn( - $table, - 'target', - [ - 'type' => Table::TYPE_BOOLEAN, - 'default' => 0, - ] - ); - } - - private function addForeignKeys(SchemaSetupInterface $setup) - { - $menuTable = $setup->getTable('snowmenu_menu'); - $nodeTable = $setup->getTable('snowmenu_node'); - $storeTable = $setup->getTable('snowmenu_store'); - $setup->getConnection()->modifyColumn( - $nodeTable, - 'menu_id', - [ - 'type' => Table::TYPE_INTEGER, - 'length' => 10, - 'nullable' => false, - 'unsigned' => true, - 'comment' => 'Menu ID' - ] - ); - - $setup->getConnection()->modifyColumn( - $storeTable, - 'store_id', - [ - 'type' => Table::TYPE_SMALLINT, - 'length' => 5, - 'nullable' => false, - 'primary' => true, - 'unsigned' => true, - 'comment' => 'Store ID' - ] - ); - - $setup->getConnection()->addForeignKey( - $setup->getFkName( - 'snowmenu_node', - 'menu_id', - 'snowmenu_menu', - 'menu_id' - ), - $nodeTable, - 'menu_id', - $menuTable, - 'menu_id', - Table::ACTION_CASCADE - ); - - $setup->getConnection()->addForeignKey( - $setup->getFkName( - 'snowmenu_store', - 'menu_id', - 'snowmenu_menu', - 'menu_id' - ), - $storeTable, - 'menu_id', - $menuTable, - 'menu_id', - Table::ACTION_CASCADE - ); - - $setup->getConnection()->addForeignKey( - $setup->getFkName( - 'snowmenu_store', - 'store_id', - 'store', - 'store_id' - ), - $storeTable, - 'store_id', - $setup->getTable('store'), - 'store_id', - Table::ACTION_CASCADE - ); - } - - /** - * @param SchemaSetupInterface $setup - * @return $this - */ - private function addTemplateFields(SchemaSetupInterface $setup) - { - $setup->getConnection()->addColumn( - $setup->getTable('snowmenu_node'), - 'submenu_template', - [ - 'type' => Table::TYPE_TEXT, - 'length' => 255, - 'nullable' => true, - 'after' => 'target', - 'comment' => 'Submenu Template', - ] - ); - - $setup->getConnection()->addColumn( - $setup->getTable('snowmenu_node'), - 'node_template', - [ - 'type' => Table::TYPE_TEXT, - 'length' => 255, - 'nullable' => true, - 'after' => 'target', - 'comment' => 'Node Template', - ] - ); - - return $this; - } - - /** - * @return $this - */ - private function addNodeImageFields(SchemaSetupInterface $setup) - { - $connection = $setup->getConnection(); - $table = $setup->getTable('snowmenu_node'); - - $connection->addColumn( - $table, - 'image', - [ - 'type' => Table::TYPE_TEXT, - 'nullable' => true, - 'after' => 'target', - 'comment' => 'Image' - ] - ); - - $connection->addColumn( - $table, - 'image_alt_text', - [ - 'type' => Table::TYPE_TEXT, - 'nullable' => true, - 'after' => 'image', - 'comment' => 'Image Alt Text' - ] - ); - - return $this; - } - - private function addNodeSelectedItemId(SchemaSetupInterface $setup) - { - $connection = $setup->getConnection(); - $table = $setup->getTable('snowmenu_node'); - - $connection->addColumn( - $table, - NodeInterface::SELECTED_ITEM_ID, - [ - 'type' => Table::TYPE_SMALLINT, - 'length' => 6, - 'unsigned' => true, - 'nullable' => true, - 'comment' => 'Selected Item Id' - ] - ); - - return $this; - } - - /** - * @return $this - */ - private function addNodeImageSizeFields(SchemaSetupInterface $setup) - { - $connection = $setup->getConnection(); - $table = $setup->getTable('snowmenu_node'); - - $connection->addColumn( - $table, - NodeInterface::IMAGE_WIDTH, - [ - 'type' => Table::TYPE_INTEGER, - 'nullable' => true, - 'after' => NodeInterface::IMAGE_ALT_TEXT, - 'comment' => 'Image Width' - ] - ); - - $connection->addColumn( - $table, - NodeInterface::IMAGE_HEIGHT, - [ - 'type' => Table::TYPE_INTEGER, - 'nullable' => true, - 'after' => NodeInterface::IMAGE_WIDTH, - 'comment' => 'Image Height' - ] - ); - - return $this; - } -} diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml new file mode 100644 index 00000000..0cd14336 --- /dev/null +++ b/etc/adminhtml/system.xml @@ -0,0 +1,21 @@ + + + + + + +
+ Snowdog_Menu::settings + + snowdog + + + + + Controls serving different menus to different customer groups + Magento\Config\Model\Config\Source\Yesno + + +
+
+
diff --git a/etc/config.xml b/etc/config.xml index b8246cd4..9ba186d7 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -11,6 +11,9 @@ + + 0 + 1 diff --git a/etc/db_schema.xml b/etc/db_schema.xml new file mode 100644 index 00000000..21d02c1d --- /dev/null +++ b/etc/db_schema.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + +
+
diff --git a/etc/db_schema_whitelist.json b/etc/db_schema_whitelist.json new file mode 100644 index 00000000..94d4d708 --- /dev/null +++ b/etc/db_schema_whitelist.json @@ -0,0 +1,71 @@ +{ + "snowmenu_menu": { + "column": { + "menu_id": true, + "title": true, + "identifier": true, + "creation_time": true, + "update_time": true, + "is_active": true, + "css_class": true + }, + "constraint": { + "PRIMARY": true + } + }, + "snowmenu_node": { + "column": { + "node_id": true, + "menu_id": true, + "type": true, + "content": true, + "classes": true, + "parent_id": true, + "position": true, + "level": true, + "title": true, + "creation_time": true, + "update_time": true, + "is_active": true, + "target": true, + "submenu_template": true, + "node_template": true, + "image": true, + "image_alt_text": true, + "selected_item_id": true, + "image_width": true, + "image_heigth": true, + "customer_groups": true + }, + "constraint": { + "PRIMARY": true, + "SNOWMENU_NODE_MENU_ID_SNOWMENU_MENU_MENU_ID": true + }, + "index": { + "SNOWMENU_NODE_NODE_ID": true + } + }, + "snowmenu_store": { + "column": { + "menu_id": true, + "store_id": true + }, + "constraint": { + "PRIMARY": true, + "SNOWMENU_STORE_MENU_ID_SNOWMENU_MENU_MENU_ID": true, + "SNOWMENU_STORE_STORE_ID_STORE_STORE_ID": true + } + }, + "snowmenu_customer": { + "column": { + "node_id": true, + "group_id": true + }, + "index": { + "SNOWMENU_CUSTOMER_NODE_ID": true + }, + "constraint": { + "SNOWMENU_CUSTOMER_NODE_ID_SNOWMENU_NODE_NODE_ID": true + } + } +} \ No newline at end of file diff --git a/etc/module.xml b/etc/module.xml index 634814e2..1db65ee8 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - + diff --git a/view/adminhtml/templates/menu/nodes.phtml b/view/adminhtml/templates/menu/nodes.phtml index 46e72570..2d1b2723 100644 --- a/view/adminhtml/templates/menu/nodes.phtml +++ b/view/adminhtml/templates/menu/nodes.phtml @@ -44,6 +44,7 @@ $vueComponents = $block->getVueComponents(); "imageDeleteUrl" : "getImageDeleteUrl() ?>", "imageUploadFileId": "getImageUploadFileId() ?>", "lazyMinItemsCount": "1000", + "customerGroups" : getCustomerGroups()) ?>, "translation": { "nodes" : "", "click" : "", @@ -73,7 +74,9 @@ $vueComponents = $block->getVueComponents(); "imageAltText" : "", "imageWidth" : "", "imageHeight" : "", - "selectedItemId" : "" + "selectedItemId" : "", + "customerGroups" : "", + "customerGroupsDescription" : "" } } } diff --git a/view/adminhtml/web/vue/app.vue b/view/adminhtml/web/vue/app.vue index 6df9ef7a..0efeaa4c 100644 --- a/view/adminhtml/web/vue/app.vue +++ b/view/adminhtml/web/vue/app.vue @@ -137,7 +137,8 @@ node_template: null, submenu_template: null, columns: [], - is_active: 0 + is_active: 0, + customer_groups: [] }); }, setUniqueIds(node) { diff --git a/view/adminhtml/web/vue/menu-type.vue b/view/adminhtml/web/vue/menu-type.vue index ec577e58..db3c6e38 100644 --- a/view/adminhtml/web/vue/menu-type.vue +++ b/view/adminhtml/web/vue/menu-type.vue @@ -17,6 +17,7 @@
+
+ + +
+ + + {{ config.translation.customerGroupsDescription }} + +
+
+