/**
  * After installation is completed.
  *
  * @return void
  */
 protected function _finish()
 {
     global $classLoader;
     // composer's class loader instance
     snapshot();
     Plugin::dropCache();
     // trick: makes plugin visible to AcoManager
     $classLoader->addPsr4($this->_plugin['name'] . "\\", normalizePath(ROOT . "/plugins/{$this->_plugin['name']}/src"), true);
     AcoManager::buildAcos($this->_plugin['name']);
     $this->_reset();
 }
 /**
  * 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;
 }
Пример #3
0
 /**
  * Switch site's theme.
  *
  * @return void
  */
 protected function _change()
 {
     $disabledThemes = plugin()->filter(function ($theme) {
         return $theme->isTheme && !in_array($theme->name, [option('front_theme'), option('back_theme')]);
     })->toArray();
     if (!count($disabledThemes)) {
         $this->err(__d('installer', '<info>There are no disabled themes!</info>'));
         $this->out();
         return;
     }
     $index = 1;
     $this->out();
     foreach ($disabledThemes as $theme) {
         $disabledThemes[$index] = $theme;
         $this->out(__d('installer', '[{0, number, integer}] {1} [{2}]', [$index, $theme->humanName, $theme->isAdmin ? __d('installer', 'backend') : __d('installer', 'frontend')]));
         $index++;
     }
     $this->out();
     $message = __d('installer', "Which theme would you like to activate?\n[Q]uit");
     while (true) {
         $in = $this->in($message);
         if (strtoupper($in) === 'Q') {
             $this->err(__d('installer', 'Operation aborted'));
             break;
         } elseif (intval($in) < 1 || !isset($disabledThemes[intval($in)])) {
             $this->err(__d('installer', 'Invalid option'));
         } else {
             $task = $this->dispatchShell("Installer.themes change -t {$disabledThemes[$in]->name}");
             if ($task === 0) {
                 $this->out(__d('installer', 'Theme changed!'));
                 Plugin::dropCache();
             } else {
                 $this->err(__d('installer', 'Theme could not be changed.'), 2);
                 $this->out();
             }
             break;
         }
     }
     $this->out();
 }
Пример #4
0
 /**
  * Disables a plugin.
  *
  * @return void
  */
 protected function _disable()
 {
     $enabledPlugins = plugin()->filter(function ($plugin) {
         return $plugin->status && !$plugin->isTheme;
     })->toArray();
     if (!count($enabledPlugins)) {
         $this->err(__d('installer', '<info>There are no active plugins!</info>'));
         $this->out();
         return;
     }
     $index = 1;
     $this->out();
     foreach ($enabledPlugins as $plugin) {
         $enabledPlugins[$index] = $plugin;
         $this->out(__d('installer', '[{0, number, integer}] {1}', [$index, $plugin->humanName]));
         $index++;
     }
     $this->out();
     $message = __d('installer', "Which plugin would you like to disable?\n[Q]uit");
     while (true) {
         $in = $this->in($message);
         if (strtoupper($in) === 'Q') {
             $this->err(__d('installer', 'Operation aborted'));
             break;
         } elseif (intval($in) < 1 || !isset($enabledPlugins[intval($in)])) {
             $this->err(__d('installer', 'Invalid option'));
         } else {
             $plugin = plugin($enabledPlugins[$in]->name());
             $this->hr();
             $this->out(__d('installer', '<info>The following plugin will be DISABLED</info>'));
             $this->hr();
             $this->out(__d('installer', 'Name:        {0}', $plugin->name));
             $this->out(__d('installer', 'Description: {0}', $plugin->composer['description']));
             $this->out(__d('installer', 'Status:      {0}', $plugin->status ? __d('installer', 'Active') : __d('installer', 'Disabled')));
             $this->out(__d('installer', 'Path:        {0}', $plugin->path));
             $this->hr();
             $this->out();
             $confirm = $this->in(__d('installer', 'Please type in "{0}" to disable this plugin', $enabledPlugins[$in]->name));
             if ($confirm === $enabledPlugins[$in]->name) {
                 $task = $this->dispatchShell("Installer.plugins toggle -p {$enabledPlugins[$in]->name} -s disable");
                 if ($task === 0) {
                     $this->out(__d('installer', 'Plugin disabled!'));
                     Plugin::dropCache();
                 } else {
                     $this->err(__d('installer', 'Plugin could not be disabled.'), 2);
                     $this->out();
                 }
             }
             break;
         }
     }
     $this->out();
 }
Пример #5
0
 /**
  * Gets a collection list of plugin that depends on this plugin.
  *
  * @return \Cake\Collection\Collection List of plugins
  */
 public function requiredBy()
 {
     if ($cache = $this->config('required_by')) {
         return collection($cache);
     }
     Plugin::dropCache();
     $out = [];
     $plugins = Plugin::get()->filter(function ($v, $k) {
         return $v->name() !== $this->name();
     });
     foreach ($plugins as $plugin) {
         if ($dependencies = $plugin->dependencies($plugin->name)) {
             $packages = array_map(function ($item) {
                 list(, $package) = packageSplit($item, true);
                 return strtolower($package);
             }, array_keys($dependencies));
             if (in_array(strtolower($this->name()), $packages)) {
                 $out[] = $plugin;
             }
         }
     }
     $this->config('required_by', $out);
     return collection($out);
 }