Enhance AddPlugin command - adding DownloadPlugin command

This commit is contained in:
MilosEsokia
2019-05-16 17:14:43 +02:00
committed by MilosEsokia
parent 9131cdca85
commit fc8478d40e
3 changed files with 207 additions and 26 deletions

View File

@@ -24,6 +24,7 @@ use Alchemy\Phrasea\Command\Plugin\AddPlugin;
use Alchemy\Phrasea\Command\Plugin\RemovePlugin; use Alchemy\Phrasea\Command\Plugin\RemovePlugin;
use Alchemy\Phrasea\Command\Plugin\EnablePlugin; use Alchemy\Phrasea\Command\Plugin\EnablePlugin;
use Alchemy\Phrasea\Command\Plugin\DisablePlugin; use Alchemy\Phrasea\Command\Plugin\DisablePlugin;
use Alchemy\Phrasea\Command\Plugin\DownloadPlugin;
use Alchemy\Phrasea\CLI; use Alchemy\Phrasea\CLI;
use Alchemy\Phrasea\Command\Setup\CheckEnvironment; use Alchemy\Phrasea\Command\Setup\CheckEnvironment;
use Alchemy\Phrasea\Core\CLIProvider\DoctrineMigrationServiceProvider; use Alchemy\Phrasea\Core\CLIProvider\DoctrineMigrationServiceProvider;
@@ -50,7 +51,7 @@ $app = new CLI("
This program comes with ABSOLUTELY NO WARRANTY. This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `about:license' for details.\n\n" under certain conditions; type `about:license' for details.\n\n"
. ' SETUP', $version->getName() . ' ' . $version->getNumber()); . ' SETUP', $version->getName() . ' ' . $version->getNumber());
$app->register(new DoctrineMigrationServiceProvider()); $app->register(new DoctrineMigrationServiceProvider());
@@ -70,6 +71,7 @@ if ($configurationTester->isInstalled()) {
} }
$app->command(new AddPlugin()); $app->command(new AddPlugin());
$app->command(new DownloadPlugin());
$app->command(new ListPlugin()); $app->command(new ListPlugin());
$app->command(new RemovePlugin()); $app->command(new RemovePlugin());
$app->command(new PluginsReset()); $app->command(new PluginsReset());

View File

@@ -14,6 +14,7 @@ namespace Alchemy\Phrasea\Command\Plugin;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\ArrayInput;
class AddPlugin extends AbstractPluginCommand class AddPlugin extends AbstractPluginCommand
{ {
@@ -29,41 +30,67 @@ class AddPlugin extends AbstractPluginCommand
protected function doExecutePluginAction(InputInterface $input, OutputInterface $output) protected function doExecutePluginAction(InputInterface $input, OutputInterface $output)
{ {
$source = $input->getArgument('source'); $source = $input->getArgument('source');
$shouldDownload = $this->shouldDownloadPlugin($source);
$temporaryDir = $this->container['temporary-filesystem']->createTemporaryDirectory(); if ($shouldDownload){
$command = $this->getApplication()->find('plugins:download');
$arguments = [
'command' => 'plugins:download',
'source' => $source
];
$output->write("Importing <info>$source</info>..."); $downloadInput = new ArrayInput($arguments);
$this->container['plugins.importer']->import($source, $temporaryDir); $command->run($downloadInput, $output);
$output->writeln(" <comment>OK</comment>");
$output->write("Validating plugin..."); } else {
$manifest = $this->container['plugins.plugins-validator']->validatePlugin($temporaryDir);
$output->writeln(" <comment>OK</comment> found <info>".$manifest->getName()."</info>");
$targetDir = $this->container['plugin.path'] . DIRECTORY_SEPARATOR . $manifest->getName(); $temporaryDir = $this->container['temporary-filesystem']->createTemporaryDirectory();
$output->write("Setting up composer..."); $output->write("Importing <info>$source</info>...");
$this->container['plugins.composer-installer']->install($temporaryDir); $this->container['plugins.importer']->import($source, $temporaryDir);
$output->writeln(" <comment>OK</comment>"); $output->writeln(" <comment>OK</comment>");
$output->write("Installing plugin <info>".$manifest->getName()."</info>..."); $output->write("Validating plugin...");
$this->container['filesystem']->mirror($temporaryDir, $targetDir); $manifest = $this->container['plugins.plugins-validator']->validatePlugin($temporaryDir);
$output->writeln(" <comment>OK</comment>"); $output->writeln(" <comment>OK</comment> found <info>".$manifest->getName()."</info>");
$output->write("Copying public files <info>".$manifest->getName()."</info>..."); $targetDir = $this->container['plugin.path'] . DIRECTORY_SEPARATOR . $manifest->getName();
$this->container['plugins.assets-manager']->update($manifest);
$output->writeln(" <comment>OK</comment>");
$output->write("Removing temporary directory..."); $output->write("Setting up composer...");
$this->container['filesystem']->remove($temporaryDir); $this->container['plugins.composer-installer']->install($temporaryDir);
$output->writeln(" <comment>OK</comment>"); $output->writeln(" <comment>OK</comment>");
$output->write("Activating plugin..."); $output->write("Installing plugin <info>".$manifest->getName()."</info>...");
$this->container['conf']->set(['plugins', $manifest->getName(), 'enabled'], true); $this->container['filesystem']->mirror($temporaryDir, $targetDir);
$output->writeln(" <comment>OK</comment>"); $output->writeln(" <comment>OK</comment>");
$this->updateConfigFiles($input, $output); $output->write("Copying public files <info>".$manifest->getName()."</info>...");
$this->container['plugins.assets-manager']->update($manifest);
$output->writeln(" <comment>OK</comment>");
return 0; $output->write("Removing temporary directory...");
$this->container['filesystem']->remove($temporaryDir);
$output->writeln(" <comment>OK</comment>");
$output->write("Activating plugin...");
$this->container['conf']->set(['plugins', $manifest->getName(), 'enabled'], true);
$output->writeln(" <comment>OK</comment>");
$this->updateConfigFiles($input, $output);
return 0;
}
}
protected function shouldDownloadPlugin($source)
{
$allowedScheme = array('https','ssh');
$scheme = parse_url($source, PHP_URL_SCHEME);
if (in_array($scheme, $allowedScheme)){
return true;
} else{
return false;
}
} }
} }

View File

@@ -0,0 +1,152 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2016 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Command\Plugin;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\ArrayInput;
use Cz\Git\GitRepository as GitRepository;
class DownloadPlugin extends AbstractPluginCommand
{
public function __construct()
{
parent::__construct('plugins:download');
$this
->setDescription('Downloads a plugin to Phraseanet')
->addArgument('source', InputArgument::REQUIRED, 'The source is a remote url (.zip or .git)')
->addArgument('destination', InputArgument::OPTIONAL, 'Download destination');
}
protected function doExecutePluginAction(InputInterface $input, OutputInterface $output)
{
$source = $input->getArgument('source');
$destination = $input->getArgument('destination');
$destinationSubdir = '/plugin-'.md5($source);
if ($destination){
$destination = trim($destination);
$destination = rtrim($destination, '/');
$localDownloadPath = $destination;
} else {
$localDownloadPath = '/tmp/plugin-download' . $destinationSubdir;
}
if (!is_dir($localDownloadPath)) {
mkdir($localDownloadPath, 0755, true);
}
$extension = $this->getURIExtension($source);
if ($extension){
switch ($extension){
case 'zip':
$localUnpackPath = '/tmp/plugin-zip'. $destinationSubdir;
if (!is_dir($localUnpackPath)) {
mkdir($localUnpackPath, 0755, true);
}
$localArchiveFile = $localUnpackPath . '/plugin-downloaded.zip';
// download
$output->writeln("Downloading <info>$source</info>...");
set_time_limit(0);
$fp = fopen ($localArchiveFile, 'w+');
$ch = curl_init($source);;
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
curl_close($ch);
fclose($fp);
// unpack
$output->writeln("Unpacking <info>$source</info>...");
$zip = new \ZipArchive();
$errorUnpack = false;
if ($zip->open($localArchiveFile)) {
for ($i = 0; $i < $zip->numFiles; $i++) {
if (!($zip->extractTo($localDownloadPath, array($zip->getNameIndex($i))))) {
$errorUnpack = true;
}
}
$zip->close();
}
if ($errorUnpack){
$output->writeln("Failed unzipping <info>$source</info>");
} else {
$output->writeln("Plugin downloaded to <info>$localDownloadPath</info>");
}
// remove zip archive
$this->delDirTree($localUnpackPath);
break;
case 'git':
$output->writeln("Downloading <info>$source</info>...");
$repo = GitRepository::cloneRepository($source, $localDownloadPath);
$output->writeln("Plugin downloaded to <info>$localDownloadPath</info>");
break;
}
} else {
$output->writeln("The source <info>$source</info> is not supported. Only .zip and .git are supported.");
}
return 0;
}
protected function getURIExtension($source)
{
$validExtension = false;
$allowedExtension = array('zip','git');
$path = parse_url($source, PHP_URL_PATH);
if (strpos($path, '.') !== false) {
$pathParts = explode('.', $path);
$extension = $pathParts[1];
if (in_array($extension, $allowedExtension)){
$validExtension = true;
}
}
if ($validExtension){
return $extension;
} else {
return false;
}
}
protected static function delDirTree($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? self::delDirTree("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}
}