diff options
author | Thomas Steur <thomas.steur@gmail.com> | 2013-10-01 05:05:54 +0400 |
---|---|---|
committer | Thomas Steur <thomas.steur@gmail.com> | 2013-10-01 05:05:54 +0400 |
commit | e58b0d1efc28225f5599946a40fefbee20f5a74f (patch) | |
tree | 708eb2fa7340543d7874899ee4baa89752a0dd29 /plugins/CorePluginsAdmin/PluginInstaller.php | |
parent | 58233e38185173cfd7a44656c9560e2a95ede3aa (diff) |
refs #607 added possibility to install a plugin or theme by uploading a ZIP file
Diffstat (limited to 'plugins/CorePluginsAdmin/PluginInstaller.php')
-rw-r--r-- | plugins/CorePluginsAdmin/PluginInstaller.php | 98 |
1 files changed, 97 insertions, 1 deletions
diff --git a/plugins/CorePluginsAdmin/PluginInstaller.php b/plugins/CorePluginsAdmin/PluginInstaller.php index ff58b45d9c..5f634f048e 100644 --- a/plugins/CorePluginsAdmin/PluginInstaller.php +++ b/plugins/CorePluginsAdmin/PluginInstaller.php @@ -11,6 +11,7 @@ namespace Piwik\Plugins\CorePluginsAdmin; use Piwik\Filechecks; use Piwik\Filesystem; +use Piwik\Log; use Piwik\SettingsPiwik; use Piwik\Unzip; @@ -49,6 +50,27 @@ class PluginInstaller $this->removeFolderIfExists($tmpPluginFolder); } + public function installOrUpdatePluginFromFile($pathToZip) + { + $tmpPluginFolder = PIWIK_USER_PATH . self::PATH_TO_DOWNLOAD . $this->pluginName; + $tmpPluginFolder = SettingsPiwik::rewriteTmpPathWithHostname($tmpPluginFolder); + + $this->makeSureFoldersAreWritable(); + $this->extractPluginFiles($pathToZip, $tmpPluginFolder); + + $this->makeSurePluginJsonExists($tmpPluginFolder); + $metadata = $this->getPluginMetadataIfValid($tmpPluginFolder); + + $this->pluginName = $metadata->name; + + $this->fixPluginFolderIfNeeded($tmpPluginFolder); + $this->copyPluginToDestination($tmpPluginFolder); + $this->removeFileIfExists($pathToZip); + $this->removeFolderIfExists($tmpPluginFolder); + + return $metadata; + } + private function makeSureFoldersAreWritable() { Filechecks::dieIfDirectoriesNotWritable(array(self::PATH_TO_DOWNLOAD, self::PATH_TO_EXTRACT)); @@ -98,11 +120,85 @@ class PluginInstaller private function makeSurePluginJsonExists($tmpPluginFolder) { - if (!file_exists($tmpPluginFolder . DIRECTORY_SEPARATOR . $this->pluginName . DIRECTORY_SEPARATOR . 'plugin.json')) { + $pluginJsonPath = $this->getPathToPluginJson($tmpPluginFolder); + + if (!file_exists($pluginJsonPath)) { throw new PluginInstallerException('Plugin is not valid, it is missing the plugin.json file.'); } } + private function getPluginMetadataIfValid($tmpPluginFolder) + { + $pluginJsonPath = $this->getPathToPluginJson($tmpPluginFolder); + + $metadata = file_get_contents($pluginJsonPath); + $metadata = json_decode($metadata); + + if (empty($metadata)) { + throw new PluginInstallerException('Plugin is not valid, plugin.json is empty or does not contain valid JSON.'); + } + + if (empty($metadata->name)) { + throw new PluginInstallerException('Plugin is not valid, the plugin.json file does not specify the plugin name.'); + } + + if (empty($metadata->version)) { + throw new PluginInstallerException('Plugin is not valid, the plugin.json file does not specify the plugin version.'); + } + + if (empty($metadata->description)) { + throw new PluginInstallerException('Plugin is not valid, the plugin.json file does not specify a description.'); + } + + return $metadata; + } + + private function getPathToPluginJson($tmpPluginFolder) + { + $firstSubFolder = $this->getNameOfFirstSubfolder($tmpPluginFolder); + $path = $tmpPluginFolder . DIRECTORY_SEPARATOR . $firstSubFolder . DIRECTORY_SEPARATOR . 'plugin.json'; + + return $path; + } + + /** + * @param $pluginDir + * @throws PluginInstallerException + * @return string + */ + private function getNameOfFirstSubfolder($pluginDir) + { + if ($dir = opendir($pluginDir)) { + $firstSubFolder = ''; + + while ($file = readdir($dir)) { + if ($file[0] != '.' && is_dir($pluginDir . DIRECTORY_SEPARATOR . $file)) { + $firstSubFolder = $file; + break; + } + } + + if (empty($firstSubFolder)) { + throw new PluginInstallerException('The plugin ZIP file does not contain a subfolder.'); + } + + return $firstSubFolder; + } + } + + private function fixPluginFolderIfNeeded($tmpPluginFolder) + { + $firstSubFolder = $this->getNameOfFirstSubfolder($tmpPluginFolder); + + if ($firstSubFolder === $this->pluginName) { + return; + } + + $from = $tmpPluginFolder . DIRECTORY_SEPARATOR . $firstSubFolder; + $to = $tmpPluginFolder . DIRECTORY_SEPARATOR . $this->pluginName; + rename($from, $to); + } + private function copyPluginToDestination($tmpPluginFolder) { $pluginTargetPath = PIWIK_USER_PATH . self::PATH_TO_EXTRACT . $this->pluginName; |