1<?php 2/** 3 * Copyright since 2007 PrestaShop SA and Contributors 4 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA 5 * 6 * NOTICE OF LICENSE 7 * 8 * This source file is subject to the Open Software License (OSL 3.0) 9 * that is bundled with this package in the file LICENSE.md. 10 * It is also available through the world-wide-web at this URL: 11 * https://opensource.org/licenses/OSL-3.0 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to license@prestashop.com so we can send you a copy immediately. 15 * 16 * DISCLAIMER 17 * 18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer 19 * versions in the future. If you wish to customize PrestaShop for your 20 * needs please refer to https://devdocs.prestashop.com/ for more information. 21 * 22 * @author PrestaShop SA and Contributors <contact@prestashop.com> 23 * @copyright Since 2007 PrestaShop SA and Contributors 24 * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) 25 */ 26 27namespace PrestaShop\PrestaShop\Adapter\Module\Tab; 28 29use PrestaShop\PrestaShop\Adapter\Module\Module; 30use PrestaShopBundle\Entity\Repository\LangRepository; 31use PrestaShopBundle\Entity\Repository\TabRepository; 32use PrestaShopBundle\Entity\Tab; 33use Psr\Log\LoggerInterface; 34use Symfony\Component\Translation\TranslatorInterface; 35use Tab as TabClass; 36 37/** 38 * Class responsible of unregister existing tabs of Back Office's menu. 39 */ 40class ModuleTabUnregister 41{ 42 /** 43 * @var LangRepository 44 */ 45 protected $langRepository; 46 47 /** 48 * @var TabRepository 49 */ 50 protected $tabRepository; 51 52 /** 53 * @var LoggerInterface 54 */ 55 private $logger; 56 57 /** 58 * @var TranslatorInterface 59 */ 60 private $translator; 61 62 public function __construct(TabRepository $tabRepository, LangRepository $langRepository, LoggerInterface $logger, TranslatorInterface $translator) 63 { 64 $this->langRepository = $langRepository; 65 $this->tabRepository = $tabRepository; 66 $this->logger = $logger; 67 $this->translator = $translator; 68 } 69 70 /** 71 * Uninstall all module-defined tabs. 72 * 73 * This is done automatically as part of the module uninstallation. 74 * 75 * @return void 76 */ 77 public function unregisterTabs(Module $module) 78 { 79 // We use the Tab repository to have only 80 // installed tabs related to the module 81 $tabs = $this->tabRepository->findByModule($module->get('name')); 82 83 foreach ($tabs as $tab) { 84 $this->unregisterTab($tab); 85 $this->removeDuplicatedParent($tab); 86 } 87 } 88 89 /** 90 * @param Module $module 91 */ 92 public function disableTabs(Module $module) 93 { 94 $this->tabRepository->changeEnabledByModuleName($module->get('name'), false); 95 } 96 97 /** 98 * Uninstalls a tab given its defined structure. 99 * 100 * @param Tab $tab the instance of entity tab 101 */ 102 private function unregisterTab(Tab $tab) 103 { 104 // We need to use the legacy class because of the right management 105 $tab_legacy = new TabClass($tab->getId()); 106 107 if (!$tab_legacy->delete()) { 108 $this->logger->warning( 109 $this->translator->trans( 110 'Failed to uninstall admin tab "%name%".', 111 [ 112 '%name%' => $tab->getClassName(), 113 ], 114 'Admin.Modules.Notification' 115 ) 116 ); 117 } 118 } 119 120 /** 121 * When we add a level of children in the menu tabs, we created a dummy parent. 122 * We must delete it when it has no more children than the original tab. 123 * 124 * @param Tab $tab 125 */ 126 private function removeDuplicatedParent(Tab $tab) 127 { 128 $remainingChildren = $this->tabRepository->findByParentId($tab->getIdParent()); 129 // Or more than one children, the parent tab is still used. 130 // If there is no children, the deletion is likely to be done manually by the module. 131 if (count($remainingChildren) !== 1) { 132 return; 133 } 134 135 $parent = $this->tabRepository->find($tab->getIdParent()); 136 $child = end($remainingChildren); 137 138 // We know we have a tab to delete if the parent name is the remaining child name+_MTR 139 if ($parent->getClassName() === $child->getClassName() . ModuleTabRegister::SUFFIX) { 140 $legacyTabParent = new TabClass($parent->getId()); 141 // Setting a wrong id_parent will prevent the children to move 142 $legacyTabParent->id_parent = -1; 143 $legacyTabParent->delete(); 144 145 $legacyTab = new TabClass($child->getId()); 146 $legacyTab->id_parent = $parent->getIdParent(); 147 $legacyTab->save(); 148 // Updating the id_parent will override the position, that's why we save 2 times 149 $legacyTab->position = $parent->getPosition(); 150 $legacyTab->save(); 151 } 152 } 153} 154