/**
  * Disables the given plugin.
  *
  * @param \CMS\Core\Package\PluginPackage $plugin The plugin to disable
  * @return bool True on success
  */
 protected function _disable(PluginPackage $plugin)
 {
     $requiredBy = Plugin::checkReverseDependency($plugin->name);
     if (!empty($requiredBy)) {
         $names = [];
         foreach ($requiredBy as $p) {
             $names[] = $p->name();
         }
         $this->err(__d('installer', 'Plugin "{0}" cannot be disabled as it is required by: {1}', $plugin->humanName, implode(', ', $names)));
         return false;
     }
     if (!$this->params['no-callbacks']) {
         $trigger = $this->_triggerBeforeEvents($plugin);
         if (!$trigger) {
             return false;
         }
     }
     return $this->_finish($plugin);
 }
 /**
  * Runs uninstallation logic inside a safe transactional thread. This prevent
  * DB inconsistencies on uninstall failure.
  *
  * @return bool True on success, false otherwise
  */
 protected function _runTransactional()
 {
     // to avoid any possible issue
     snapshot();
     if (!is_writable(TMP)) {
         $this->err(__d('installer', 'Enable write permissions in /tmp directory before uninstall any plugin or theme.'));
         return false;
     }
     if (!$this->params['plugin']) {
         $this->err(__d('installer', 'No plugin/theme was given to remove.'));
         return false;
     }
     $this->loadModel('System.Plugins');
     try {
         $plugin = plugin($this->params['plugin']);
         $pluginEntity = $this->Plugins->find()->where(['name' => $this->params['plugin']])->limit(1)->first();
     } catch (\Exception $ex) {
         $plugin = $pluginEntity = false;
     }
     if (!$plugin || !$pluginEntity) {
         $this->err(__d('installer', 'Plugin "{0}" was not found.', $this->params['plugin']));
         return false;
     }
     $this->_plugin = $plugin;
     $type = $plugin->isTheme ? 'theme' : 'plugin';
     if ($plugin->isTheme && in_array($plugin->name, [option('front_theme'), option('back_theme')])) {
         $this->err(__d('installer', '{0} "{1}" is currently being used and cannot be removed.', $type == 'plugin' ? __d('installer', 'The plugin') : __d('installer', 'The theme'), $plugin->humanName));
         return false;
     }
     $requiredBy = Plugin::checkReverseDependency($this->params['plugin']);
     if (!empty($requiredBy)) {
         $names = [];
         foreach ($requiredBy as $p) {
             $names[] = $p->name();
         }
         $this->err(__d('installer', '{0} "{1}" cannot be removed as it is required by: {2}', $type == 'plugin' ? __d('installer', 'The plugin') : __d('installer', 'The theme'), $plugin->humanName, implode(', ', $names)));
         return false;
     }
     if (!$this->_canBeDeleted($plugin->path)) {
         return false;
     }
     if (!$this->params['no-callbacks']) {
         try {
             $event = $this->trigger("Plugin.{$plugin->name}.beforeUninstall");
             if ($event->isStopped() || $event->result === false) {
                 $this->err(__d('installer', 'Task was explicitly rejected by {0}.', $type == 'plugin' ? __d('installer', 'the plugin') : __d('installer', 'the theme')));
                 return false;
             }
         } catch (\Exception $e) {
             $this->err(__d('installer', 'Internal error, {0} did not respond to "beforeUninstall" callback correctly.', $type == 'plugin' ? __d('installer', 'the plugin') : __d('installer', 'the theme')));
             return false;
         }
     }
     if (!$this->Plugins->delete($pluginEntity)) {
         $this->err(__d('installer', '{0} "{1}" could not be unregistered from DB.', $type == 'plugin' ? __d('installer', 'The plugin') : __d('installer', 'The theme'), $plugin->humanName));
         return false;
     }
     $this->_removeOptions();
     $this->_clearAcoPaths();
     $folder = new Folder($plugin->path);
     $folder->delete();
     snapshot();
     if (!$this->params['no-callbacks']) {
         try {
             $this->trigger("Plugin.{$plugin->name}.afterUninstall");
         } catch (\Exception $e) {
             $this->err(__d('installer', '{0} did not respond to "afterUninstall" callback.', $type == 'plugin' ? __d('installer', 'The plugin') : __d('installer', 'The theme')));
         }
     }
     Plugin::unload($plugin->name);
     Plugin::dropCache();
     return true;
 }