mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
Merge branch 'master' into PHRAS-2544_Prod-grey_and_white_skins_colors
This commit is contained in:
@@ -24,6 +24,7 @@ use Alchemy\Phrasea\Command\Plugin\AddPlugin;
|
||||
use Alchemy\Phrasea\Command\Plugin\RemovePlugin;
|
||||
use Alchemy\Phrasea\Command\Plugin\EnablePlugin;
|
||||
use Alchemy\Phrasea\Command\Plugin\DisablePlugin;
|
||||
use Alchemy\Phrasea\Command\Plugin\DownloadPlugin;
|
||||
use Alchemy\Phrasea\CLI;
|
||||
use Alchemy\Phrasea\Command\Setup\CheckEnvironment;
|
||||
use Alchemy\Phrasea\Core\CLIProvider\DoctrineMigrationServiceProvider;
|
||||
@@ -50,7 +51,7 @@ $app = new CLI("
|
||||
This program comes with ABSOLUTELY NO WARRANTY.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `about:license' for details.\n\n"
|
||||
. ' SETUP', $version->getName() . ' ' . $version->getNumber());
|
||||
. ' SETUP', $version->getName() . ' ' . $version->getNumber());
|
||||
|
||||
$app->register(new DoctrineMigrationServiceProvider());
|
||||
|
||||
@@ -70,6 +71,7 @@ if ($configurationTester->isInstalled()) {
|
||||
}
|
||||
|
||||
$app->command(new AddPlugin());
|
||||
$app->command(new DownloadPlugin());
|
||||
$app->command(new ListPlugin());
|
||||
$app->command(new RemovePlugin());
|
||||
$app->command(new PluginsReset());
|
||||
|
@@ -120,7 +120,8 @@
|
||||
"google/recaptcha": "^1.1",
|
||||
"facebook/graph-sdk": "^5.6",
|
||||
"box/spout": "^2.7",
|
||||
"paragonie/random-lib": "^2.0"
|
||||
"paragonie/random-lib": "^2.0",
|
||||
"czproject/git-php": "^3.17"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsstream": "~1.5",
|
||||
|
48
composer.lock
generated
48
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "a9c7fed873d5bfe962c81d543b33330f",
|
||||
"content-hash": "64830cb4d53b32b47e02d4a19df9cef2",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alchemy-fr/tcpdf-clone",
|
||||
@@ -1156,6 +1156,48 @@
|
||||
],
|
||||
"time": "2016-08-09T20:10:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "czproject/git-php",
|
||||
"version": "v3.17.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/czproject/git-php.git",
|
||||
"reference": "a7b911b81a2fe626f748a4ac8955353c5777bc6c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/czproject/git-php/zipball/a7b911b81a2fe626f748a4ac8955353c5777bc6c",
|
||||
"reference": "a7b911b81a2fe626f748a4ac8955353c5777bc6c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^1.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jan Pecha",
|
||||
"email": "janpecha@email.cz"
|
||||
}
|
||||
],
|
||||
"description": "Library for work with Git repository in PHP.",
|
||||
"keywords": [
|
||||
"git"
|
||||
],
|
||||
"time": "2019-02-09T13:11:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dailymotion/sdk",
|
||||
"version": "1.6.5",
|
||||
@@ -7747,12 +7789,12 @@
|
||||
"version": "v1.6.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bovigo/vfsStream.git",
|
||||
"url": "https://github.com/mikey179/vfsStream.git",
|
||||
"reference": "0247f57b2245e8ad2e689d7cee754b45fbabd592"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bovigo/vfsStream/zipball/0247f57b2245e8ad2e689d7cee754b45fbabd592",
|
||||
"url": "https://api.github.com/repos/mikey179/vfsStream/zipball/0247f57b2245e8ad2e689d7cee754b45fbabd592",
|
||||
"reference": "0247f57b2245e8ad2e689d7cee754b45fbabd592",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@@ -51,4 +51,41 @@ abstract class AbstractPluginCommand extends Command
|
||||
$this->container['plugins.autoloader-generator']->write($manifests);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
}
|
||||
|
||||
protected function doInstallPlugin($source, InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$temporaryDir = $this->container['temporary-filesystem']->createTemporaryDirectory();
|
||||
|
||||
$output->write("Importing <info>$source</info>...");
|
||||
$this->container['plugins.importer']->import($source, $temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Validating plugin...");
|
||||
$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();
|
||||
|
||||
$output->write("Setting up composer...");
|
||||
$this->container['plugins.composer-installer']->install($temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Installing plugin <info>".$manifest->getName()."</info>...");
|
||||
$this->container['filesystem']->mirror($temporaryDir, $targetDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Copying public files <info>".$manifest->getName()."</info>...");
|
||||
$this->container['plugins.assets-manager']->update($manifest);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ 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;
|
||||
|
||||
class AddPlugin extends AbstractPluginCommand
|
||||
{
|
||||
@@ -29,41 +30,36 @@ class AddPlugin extends AbstractPluginCommand
|
||||
protected function doExecutePluginAction(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$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,
|
||||
'shouldInstallPlugin' => true
|
||||
];
|
||||
|
||||
$output->write("Importing <info>$source</info>...");
|
||||
$this->container['plugins.importer']->import($source, $temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
$downloadInput = new ArrayInput($arguments);
|
||||
$command->run($downloadInput, $output);
|
||||
|
||||
$output->write("Validating plugin...");
|
||||
$manifest = $this->container['plugins.plugins-validator']->validatePlugin($temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment> found <info>".$manifest->getName()."</info>");
|
||||
} else {
|
||||
|
||||
$targetDir = $this->container['plugin.path'] . DIRECTORY_SEPARATOR . $manifest->getName();
|
||||
|
||||
$output->write("Setting up composer...");
|
||||
$this->container['plugins.composer-installer']->install($temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Installing plugin <info>".$manifest->getName()."</info>...");
|
||||
$this->container['filesystem']->mirror($temporaryDir, $targetDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Copying public files <info>".$manifest->getName()."</info>...");
|
||||
$this->container['plugins.assets-manager']->update($manifest);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$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);
|
||||
$this->doInstallPlugin($source, $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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
157
lib/Alchemy/Phrasea/Command/Plugin/DownloadPlugin.php
Normal file
157
lib/Alchemy/Phrasea/Command/Plugin/DownloadPlugin.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?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')
|
||||
->addArgument('shouldInstallPlugin', InputArgument::OPTIONAL, 'True or false, determines if plugin should be installed after download');
|
||||
}
|
||||
|
||||
protected function doExecutePluginAction(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$source = $input->getArgument('source');
|
||||
$destination = $input->getArgument('destination');
|
||||
$shouldInstallPlugin = false;
|
||||
$shouldInstallPlugin = $input->getArgument('shouldInstallPlugin');
|
||||
|
||||
$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>");
|
||||
if ($shouldInstallPlugin) $this->doInstallPlugin($localDownloadPath, $input, $output);
|
||||
}
|
||||
|
||||
// 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>");
|
||||
if ($shouldInstallPlugin) $this->doInstallPlugin($localDownloadPath, $input, $output);
|
||||
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);
|
||||
}
|
||||
}
|
@@ -73,6 +73,9 @@ class SubdefSubstituer
|
||||
|
||||
$this->createMediaSubdef($record, 'document', $media);
|
||||
|
||||
$record->setMimeType($media->getFile()->getMimeType());
|
||||
$record->setType($media->getType());
|
||||
|
||||
$record->write_metas();
|
||||
|
||||
if ($shouldSubdefsBeRebuilt) {
|
||||
|
Reference in New Issue
Block a user