Skip to content
Extraits de code Groupes Projets
Valider 2cfe210d rédigé par mattab's avatar mattab
Parcourir les fichiers

Refs #546 Adding core "Uninstall" feature for Plugins and Themes + Cleanups +...

Refs #546 Adding core "Uninstall" feature for Plugins and Themes + Cleanups + fix build by moving constant to PluginsManager
Todo
 * ask for confirmation: "Do you want to uninstall X?" // warn that plugin-specific data may be deleted as part of calling the plugin's uninstall method, and may not be recoverable.
 * call uninstall() method on the plugin class
 * verify core plugins cant be uninstalled
parent ea091e48
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
......@@ -133,24 +133,11 @@ class Piwik_Config
*
* @return string
*/
public static function getGlobalConfigPath()
protected static function getGlobalConfigPath()
{
return PIWIK_USER_PATH . '/config/global.ini.php';
}
/**
* Backward compatibility stub
*
* @todo remove in 2.0
* @since 1.7
* @deprecated 1.7
* @return string
*/
public static function getDefaultDefaultConfigPath()
{
return self::getGlobalConfigPath();
}
/**
* Returns absolute path to the local configuration file
*
......@@ -272,12 +259,7 @@ class Piwik_Config
return $tmp;
}
$section = null;
// merge corresponding sections from global and local settings
if (isset($this->configGlobal[$name])) {
$section = $this->configGlobal[$name];
}
$section = $this->getFromDefaultConfig($name);
if (isset($this->configLocal[$name])) {
// local settings override the global defaults
......@@ -297,6 +279,14 @@ class Piwik_Config
return $tmp;
}
public function getFromDefaultConfig($name)
{
if (isset($this->configGlobal[$name])) {
return $this->configGlobal[$name];
}
return null;
}
/**
* Set value
*
......
......@@ -38,6 +38,10 @@ class Piwik_PluginsManager
protected $doLoadPlugins = true;
protected $loadedPlugins = array();
/**
* Default theme used in Piwik.
*/
const DEFAULT_THEME="Zeitgeist";
protected $doLoadAlwaysActivatedPlugins = true;
protected $pluginToAlwaysActivate = array(
......@@ -53,7 +57,7 @@ class Piwik_PluginsManager
'LanguagesManager',
// default Piwik theme, always enabled
Piwik_Twig::DEFAULT_THEME,
self::DEFAULT_THEME,
);
// If a plugin hooks onto at least an event starting with "Tracker.", we load the plugin during tracker
......@@ -122,6 +126,21 @@ class Piwik_PluginsManager
return in_array($name, $this->pluginToAlwaysActivate);
}
/**
* Returns true if the plugin can be uninstalled. Any non-core plugin can be uninstalled.
*
* @param $name
* @return bool
*/
public function isPluginUninstallable($name)
{
// Reading the plugins from the global.ini.php config file
$pluginsBundledWithPiwik = Piwik_Config::getInstance()->getFromDefaultConfig('Plugins');
$pluginsBundledWithPiwik = $pluginsBundledWithPiwik['Plugins'];
return !in_array($name, $pluginsBundledWithPiwik);
}
/**
* Returns true if plugin has been activated
*
......@@ -188,6 +207,32 @@ class Piwik_PluginsManager
return PIWIK_INCLUDE_PATH . '/plugins/';
}
/**
* Uninstalls a Plugin (deletes plugin files from the disk)
* Only deactivated plugins can be uninstalled
*
* @param $pluginName
*/
public function uninstallPlugin($pluginName)
{
if($this->isPluginActivated($pluginName)) {
throw new Exception("To uninstall the plugin $pluginName, first disable it in Piwik > Settings > Plugins");
}
if(!$this->isPluginInFilesystem($pluginName)) {
throw new Exception("You are trying to uninstall the plugin $pluginName but it was not found in the directory piwik/plugins/");
}
self::deletePluginFromFilesystem($pluginName);
if($this->isPluginInFilesystem($pluginName)) {
return false;
}
return true;
}
public static function deletePluginFromFilesystem($plugin)
{
Piwik::unlinkRecursive(PIWIK_INCLUDE_PATH . '/plugins/' . $plugin, $deleteRootToo = true);
}
/**
* Deactivate plugin
*
......@@ -253,8 +298,7 @@ class Piwik_PluginsManager
throw new Exception("Plugin '$pluginName' already activated.");
}
$existingPlugins = $this->readPluginsDirectory();
if (array_search($pluginName, $existingPlugins) === false) {
if (!$this->isPluginInFilesystem($pluginName)) {
// ToDo: This fails in tracker-mode. We should log this however.
//Piwik::log(sprintf("Unable to find the plugin '%s' in activatePlugin.", $pluginName));
return;
......@@ -289,6 +333,14 @@ class Piwik_PluginsManager
Piwik::deleteAllCacheOnUpdate();
}
protected function isPluginInFilesystem($pluginName)
{
$existingPlugins = $this->readPluginsDirectory();
$isPluginInFilesystem = array_search($pluginName, $existingPlugins) !== false;
return Piwik_Common::isValidFilename($pluginName)
&& $isPluginInFilesystem;
}
/**
* Returns the name of the non default theme currently enabled.
* If Zeitgeist is enabled, returns false (nb: Zeitgeist cannot be disabled)
......@@ -301,7 +353,7 @@ class Piwik_PluginsManager
foreach($plugins as $plugin) {
/* @var $plugin Piwik_Plugin */
if($plugin->isTheme()
&& $plugin->getPluginName() != Piwik_Twig::DEFAULT_THEME) {
&& $plugin->getPluginName() != self::DEFAULT_THEME) {
return $plugin->getPluginName();
}
}
......
......@@ -23,12 +23,7 @@ class Piwik_Twig
*/
private $twig;
/**
* Default theme used in Piwik.
*/
const DEFAULT_THEME="Zeitgeist";
public function __construct($theme = self::DEFAULT_THEME)
public function __construct()
{
$loader = $this->getDefaultThemeLoader();
......@@ -139,7 +134,7 @@ class Piwik_Twig
private function getDefaultThemeLoader()
{
$themeLoader = new Twig_Loader_Filesystem(array(
sprintf("%s/plugins/%s/templates/", PIWIK_INCLUDE_PATH, self::DEFAULT_THEME)
sprintf("%s/plugins/%s/templates/", PIWIK_INCLUDE_PATH, Piwik_PluginsManager::DEFAULT_THEME)
));
return $themeLoader;
......
......@@ -108,9 +108,5 @@ abstract class Piwik_Updates
}
}
public static function deletePluginFromFilesystem($plugin)
{
Piwik::unlinkRecursive(PIWIK_INCLUDE_PATH . '/plugins/' . $plugin, $deleteRootToo = true);
}
}
......@@ -19,9 +19,9 @@ class Piwik_Updates_1_9_3_b3 extends Piwik_Updates
// Insight was a temporary code name for Overlay
$pluginToDelete = 'Insight';
self::deletePluginFromConfigFile($pluginToDelete);
self::deletePluginFromFilesystem($pluginToDelete);
Piwik_PluginsManager::getInstance()->deletePluginFromFilesystem($pluginToDelete);
// We also clean up 1.9.1 and delete Feedburner plugin
self::deletePluginFromFilesystem('Feedburner');
Piwik_PluginsManager::getInstance()->deletePluginFromFilesystem('Feedburner');
}
}
......@@ -71,8 +71,9 @@ if (!function_exists('Piwik_ExitWithMessage')) {
* @param string $message Main message, must be html encoded before calling
* @param bool|string $optionalTrace Backtrace; will be displayed in lighter color
* @param bool $optionalLinks If true, will show links to the Piwik website for help
* @param bool $goBack if true, displays a link to go back
*/
function Piwik_ExitWithMessage($message, $optionalTrace = false, $optionalLinks = false)
function Piwik_ExitWithMessage($message, $optionalTrace = false, $optionalLinks = false, $optionalLinkBack = false)
{
@header('Content-Type: text/html; charset=utf-8');
if ($optionalTrace) {
......@@ -87,14 +88,20 @@ if (!function_exists('Piwik_ExitWithMessage')) {
<li><a target="_blank" href="http://demo.piwik.org">Piwik Online Demo</a></li>
</ul>';
}
if($optionalLinkBack) {
$optionalLinkBack = '<a href="javascript:window.back();">Go Back</a><br/>';
}
$headerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Zeitgeist/templates/simpleLayoutHeader.tpl');
$footerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Zeitgeist/templates/simpleLayoutFooter.tpl');
$headerPage = str_replace('{$HTML_TITLE}', 'Piwik &rsaquo; Error', $headerPage);
$content = '<p>' . $message . '</p>
<p><a href="index.php">Go to Piwik</a><br/>
<a href="index.php?module=Login">Login</a></p>
' . $optionalTrace . ' ' . $optionalLinks;
<p>'
. $optionalLinkBack
. '<a href="index.php">Go to Piwik</a><br/>
<a href="index.php?module=Login">Login</a>'
. '</p>'
. ' ' . $optionalTrace . ' ' . $optionalLinks;
echo $headerPage . $content . $footerPage;
exit;
......
......@@ -44,7 +44,7 @@ class Piwik_CorePluginsAdmin_Controller extends Piwik_Controller_Admin
return $view;
}
protected function getPluginsInfo( $themesOnly = false )
protected function getPluginsInfo($themesOnly = false)
{
$plugins = array();
......@@ -58,6 +58,7 @@ class Piwik_CorePluginsAdmin_Controller extends Piwik_Controller_Admin
$plugins[$pluginName] = array(
'activated' => Piwik_PluginsManager::getInstance()->isPluginActivated($pluginName),
'alwaysActivated' => Piwik_PluginsManager::getInstance()->isPluginAlwaysActivated($pluginName),
'uninstallable' => Piwik_PluginsManager::getInstance()->isPluginUninstallable($pluginName),
);
}
Piwik_PluginsManager::getInstance()->loadPluginTranslations();
......@@ -74,7 +75,7 @@ class Piwik_CorePluginsAdmin_Controller extends Piwik_Controller_Admin
'description' => '<strong><em>' . Piwik_Translate('CorePluginsAdmin_PluginCannotBeFound')
. '</strong></em>',
'version' => Piwik_Translate('General_Unknown'),
'theme' => false,
'theme' => false,
);
}
}
......@@ -103,23 +104,46 @@ class Piwik_CorePluginsAdmin_Controller extends Piwik_Controller_Admin
public function deactivate($redirectAfter = true)
{
Piwik::checkUserIsSuperUser();
$this->checkTokenInUrl();
$pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
$pluginName = $this->initPluginModification();
Piwik_PluginsManager::getInstance()->deactivatePlugin($pluginName);
$this->redirectAfterModification($redirectAfter);
}
protected function redirectAfterModification($redirectAfter)
{
if ($redirectAfter) {
Piwik_Url::redirectToReferer();
}
}
public function activate($redirectAfter = true)
protected function initPluginModification()
{
Piwik::checkUserIsSuperUser();
$this->checkTokenInUrl();
$pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
return $pluginName;
}
public function activate($redirectAfter = true)
{
$pluginName = $this->initPluginModification();
Piwik_PluginsManager::getInstance()->activatePlugin($pluginName);
if ($redirectAfter) {
Piwik_Url::redirectToReferer();
$this->redirectAfterModification($redirectAfter);
}
public function uninstall($redirectAfter = true)
{
$pluginName = $this->initPluginModification();
$uninstalled = Piwik_PluginsManager::getInstance()->uninstallPlugin($pluginName);
if(!$uninstalled) {
$path = Piwik_Common::getPathToPiwikRoot() . '/plugins/' . $pluginName . '/';
$messagePermissions = Piwik::getErrorMessageMissingPermissions($path);
$messageIntro = Piwik_Translate("Warning: \"%s\" could not be uninstalled. Piwik did not have enough permission to delete the files in $path. ",
$pluginName);
$exitMessage = $messageIntro . "<br/><br/>" . $messagePermissions;
Piwik_ExitWithMessage($exitMessage, $optionalTrace = false, $optionalLinks = false, $optionalLinkBack = true);
}
$this->redirectAfterModification($redirectAfter);
}
}
......@@ -32,7 +32,7 @@
&nbsp; <cite>By
{% if plugin.info.author_homepage is defined %}
<a title="{{ 'CorePluginsAdmin_AuthorHomepage'|translate }}" href="{{ plugin.info.author_homepage }}" target="_blank">
{% endif %}{{ plugin.info.author }}{% if plugin.info.author_homepage is defined %}</a>{% endif %}
{% endif %}{{ plugin.info.author }}{% if plugin.info.author_homepage is defined -%}</a>{% endif -%}
.</cite>
{% endif %}
</td>
......@@ -40,7 +40,9 @@
{% if plugin.activated %}
{{ 'CorePluginsAdmin_Active'|translate }}
{% else %}
{{ 'CorePluginsAdmin_Inactive'|translate }}
{{ 'CorePluginsAdmin_Inactive'|translate }} <br/>
- {% if plugin.uninstallable %}<a href='index.php?module=CorePluginsAdmin&action=uninstall&pluginName={{ name }}&token_auth={{
token_auth }}'>uninstall</a>{% endif %}
{% endif %}
</td>
......
......@@ -36,7 +36,7 @@ body#simple {
vertical-align:bottom;
}
#title {
padding-bottom:5px;
padding-bottom:15px;
border-bottom:1px solid #F0F0F0;
font:42px Georgia, serif;
}
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter