diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml
index a1cc599aa7..3b05ef9d46 100644
--- a/phpBB/config/default/container/services_console.yml
+++ b/phpBB/config/default/container/services_console.yml
@@ -154,6 +154,7 @@ services:
arguments:
- @user
- @ext.composer.manager
+ - @language
tags:
- { name: console.command }
@@ -171,6 +172,7 @@ services:
arguments:
- @user
- @ext.composer.manager
+ - @language
tags:
- { name: console.command }
@@ -188,6 +190,7 @@ services:
arguments:
- @user
- @ext.composer.manager
+ - @language
tags:
- { name: console.command }
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index 537cc1a5d1..7f341abd07 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -242,6 +242,13 @@ $lang = array_merge($lang, array(
'COLOUR_SWATCH' => 'Web-safe colour swatch',
'COMPOSER_UNSUPPORTED_OPERATION' => 'Operation unsupported for the package type ā%sā.',
+ 'COMPOSER_UPDATING_DEPENDENCIES' => 'Updating packages',
+ 'COMPOSER_LOADING_REPOSITORIES' => 'Loading remote packages information',
+ 'COMPOSER_ERROR_CONFLICT' => 'Your requirements could not be resolved to an installable set of packages.',
+ 'COMPOSER_REPOSITORY_UNAVAILABLE' => 'An error occurred when fetching the repository %s.',
+ 'COMPOSER_INSTALLING_PACKAGE' => ' - Installing %1$s (%2$s)',
+ 'COMPOSER_DELETING' => ' - Deleting %s',
+ 'COMPOSER_UPDATE_NOTHING' => 'Nothing to update',
'CONFIG_UPDATED' => 'Configuration updated successfully.',
'CRON_LOCK_ERROR' => 'Could not obtain cron lock.',
diff --git a/phpBB/phpbb/composer/extension_manager.php b/phpBB/phpbb/composer/extension_manager.php
index 360e2fca5b..a86b91fffa 100644
--- a/phpBB/phpbb/composer/extension_manager.php
+++ b/phpBB/phpbb/composer/extension_manager.php
@@ -13,6 +13,7 @@
namespace phpbb\composer;
+use Composer\IO\IOInterface;
use phpbb\composer\exception\managed_with_clean_error_exception;
use phpbb\composer\exception\managed_with_enable_error_exception;
use phpbb\composer\exception\managed_with_error_exception;
@@ -54,7 +55,7 @@ class extension_manager extends manager
/**
* {@inheritdoc}
*/
- public function install(array $packages)
+ public function install(array $packages, IOInterface $io = null)
{
$packages = $this->normalize_version($packages);
@@ -70,7 +71,7 @@ class extension_manager extends manager
throw new runtime_exception($this->exception_prefix, 'ALREADY_INSTALLED_MANUALLY', [implode('|', array_keys($installed_manually))]);
}
- $this->do_install($packages);
+ $this->do_install($packages, $io);
}
/**
diff --git a/phpBB/phpbb/composer/installer.php b/phpBB/phpbb/composer/installer.php
index 94cf0c634c..498fb6cdcb 100644
--- a/phpBB/phpbb/composer/installer.php
+++ b/phpBB/phpbb/composer/installer.php
@@ -15,7 +15,7 @@ namespace phpbb\composer;
use Composer\Composer;
use Composer\Factory;
-use Composer\IO\BufferIO;
+use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Json\JsonFile;
use Composer\Package\CompletePackage;
@@ -25,7 +25,6 @@ use Composer\Repository\RepositoryInterface;
use Composer\Util\RemoteFilesystem;
use phpbb\config\config;
use phpbb\exception\runtime_exception;
-use Symfony\Component\Console\Output\OutputInterface;
/**
* Class to install packages through composer while freezing core dependencies.
@@ -85,19 +84,27 @@ class installer
* @param array $packages Packages to install.
* Each entry may be a name or an array associating a version constraint to a name
* @param array $whitelist White-listed packages (packages that can be installed/updated/removed)
+ * @param IOInterface $io IO object used for the output
+ *
* @throws runtime_exception
*/
- public function install(array $packages, $whitelist)
+ public function install(array $packages, $whitelist, IOInterface $io = null)
{
+ if (!$io)
+ {
+ $io = new NullIO();
+ }
+
$this->generate_ext_json_file($packages);
$original_vendor_dir = getenv('COMPOSER_VENDOR_DIR');
putenv('COMPOSER_VENDOR_DIR=' . $this->root_path . $this->packages_vendor_dir);
- $io = new BufferIO('', OutputInterface::VERBOSITY_DEBUG);
$composer = Factory::create($io, $this->get_composer_ext_json_filename(), false);
$install = \Composer\Installer::create($io, $composer);
+ $composer->getDownloadManager()->setOutputProgress(false);
+
$install
->setVerbose(true)
->setPreferSource(false)
@@ -112,17 +119,12 @@ class installer
->setRunScripts(false)
->setDryRun(false);
+ $result = 0;
try
{
- $install->run();
- $output = $io->getOutput();
- $error_pos = strpos($output, 'Your requirements could not be resolved to an installable set of packages.');
-
- if ($error_pos)
- {
- // TODO Extract the precise error and use language string
- throw new \RuntimeException(substr($output, $error_pos));
- }
+ $result = $install->run();
+ //$output = $io->getOutput();
+ //$error_pos = strpos($output, 'Your requirements could not be resolved to an installable set of packages.');
}
catch (\Exception $e)
{
@@ -132,6 +134,11 @@ class installer
{
putenv('COMPOSER_VENDOR_DIR=' . $original_vendor_dir);
}
+
+ if ($result !== 0)
+ {
+ throw new runtime_exception($io->get_composer_error(), []);
+ }
}
/**
@@ -154,7 +161,7 @@ class installer
$composer = Factory::create($io, $this->get_composer_ext_json_filename(), false);
$installed = [];
- $packages = $composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
+ $packages = $composer->getPackage()->getRequires();//$composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
foreach ($packages as $package)
{
@@ -282,6 +289,7 @@ class installer
$packages),
'replace' => $core_packages,
'repositories' => $this->get_composer_repositories(),
+ 'minimum-stability' => 'dev',
];
$json_file = new JsonFile($this->get_composer_ext_json_filename());
diff --git a/phpBB/phpbb/composer/io/console_io.php b/phpBB/phpbb/composer/io/console_io.php
new file mode 100644
index 0000000000..bf1754d4c0
--- /dev/null
+++ b/phpBB/phpbb/composer/io/console_io.php
@@ -0,0 +1,217 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\composer\io;
+
+use Composer\IO\ConsoleIO;
+use phpbb\language\language;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class console_io extends ConsoleIO
+{
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * @var array
+ */
+ protected $composer_error;
+
+ /**
+ * Constructor.
+ *
+ * @param InputInterface $input The input instance
+ * @param OutputInterface $output The output instance
+ * @param HelperSet $helperSet The helperSet instance
+ */
+ public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet, language $language)
+ {
+ $this->language = $language;
+
+ parent::__construct($input, $output, $helperSet);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write($messages, $newline = true)
+ {
+ $messages = (array) $messages;
+ $translated_messages = [];
+
+ foreach ($messages as $message)
+ {
+ $lang_key = $message;
+ $parameters = [];
+ $level = 0;
+
+ $message = trim(strip_tags($message), "\n\r");
+
+ if (strpos($message, 'Deleting ') === 0)
+ {
+ $elements = explode(' ', $message);
+ $lang_key = 'COMPOSER_DELETING';
+ $parameters = [$elements[1]];
+ }
+
+ //$translated_message = $this->language->lang_array($lang_key, $parameters);
+ $translated_message = call_user_func_array([$this->language, 'lang'], array_merge((array)$lang_key, $parameters));
+
+ switch ($level)
+ {
+ case 1:
+ $translated_message = '' . $translated_message . '';
+ break;
+ case 2:
+ $translated_message = '' . $translated_message . '';
+ break;
+ case 3:
+ $translated_message = '' . $translated_message . '';
+ break;
+ case 4:
+ $translated_message = '' . $translated_message . '';
+ break;
+ }
+
+ $translated_messages[] = $translated_message;
+ }
+
+ parent::write($translated_messages, $newline);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function writeError($messages, $newline = true)
+ {
+ $messages = (array) $messages;
+ $translated_messages = [];
+
+ foreach ($messages as $message)
+ {
+ $lang_key = $message;
+ $parameters = [];
+ $level = 0;
+
+ $message = trim(strip_tags($message), "\n\r");
+
+ if (strpos($message, ' Problem ') === 0)
+ {
+ if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE)
+ {
+ continue;
+ }
+
+ $lang_key = "\n" . $message . "\n";
+ $level = 4;
+ }
+ else if ($message === 'Updating dependencies')
+ {
+ $lang_key = 'COMPOSER_UPDATING_DEPENDENCIES';
+ $level = 1;
+ }
+ else if ($message === 'Loading composer repositories with package information')
+ {
+ $lang_key = 'COMPOSER_LOADING_REPOSITORIES';
+ $level = 1;
+ }
+ else if ($message === 'Your requirements could not be resolved to an installable set of packages.')
+ {
+ $this->composer_error[] = ['COMPOSER_ERROR_CONFLICT', []];
+ continue;
+ }
+ else if (strpos($message, 'could not be fully loaded, package information was loaded from the local cache and may be out of date') !== false)
+ {
+ $end_repo = strpos($message, 'could not be fully loaded, package information was loaded from the local cache and may be out of date');
+ $repo = substr($message, 0, $end_repo - 1);
+
+ $lang_key = 'COMPOSER_REPOSITORY_UNAVAILABLE';
+ $parameters = [$repo];
+ $level = 3;
+ }
+ else if (strpos($message, 'file could not be downloaded') !== false)
+ {
+ continue;
+ }
+ else if (strpos($message, ' - Installing ') === 0)
+ {
+ $elements = explode(' ', $message);
+ $lang_key = 'COMPOSER_INSTALLING_PACKAGE';
+ $parameters = [$elements[4], trim($elements[5], '()')];
+ }
+ else if ($message === 'Nothing to install or update')
+ {
+ $lang_key = 'COMPOSER_UPDATE_NOTHING';
+ $level = 3;
+ }
+ else if ($message === ' Downloading')
+ {
+ continue;
+ }
+ else if ($message === ' Loading from cache')
+ {
+ continue;
+ }
+ else if ($message === 'Writing lock file')
+ {
+ continue;
+ }
+ else if (empty($message))
+ {
+ continue;
+ }
+
+ //$translated_message = $this->language->lang_array($lang_key, $parameters);
+ $translated_message = call_user_func_array([$this->language, 'lang'], array_merge((array)$lang_key, $parameters));
+
+ switch ($level)
+ {
+ case 1:
+ $translated_message = '' . $translated_message . '';
+ break;
+ case 2:
+ $translated_message = '' . $translated_message . '';
+ break;
+ case 3:
+ $translated_message = '' . $translated_message . '';
+ break;
+ case 4:
+ $translated_message = '' . $translated_message . '';
+ break;
+ }
+
+ $translated_messages[] = $translated_message;
+ }
+
+ parent::writeError($translated_messages, $newline);
+ }
+
+ public function get_composer_error()
+ {
+ $error = '';
+ foreach ($this->composer_error as $error_line)
+ {
+ // $error .= $this->language->lang_array($error_line[0], $error_line[1]);
+ $error .= call_user_func_array([$this->language, 'lang'], array_merge((array)$error_line[0], $error_line[1]));
+ $error .= "\n";
+ }
+
+ $this->composer_error = [];
+
+ return $error;
+ }
+}
diff --git a/phpBB/phpbb/composer/manager.php b/phpBB/phpbb/composer/manager.php
index ed4ce6528b..5d942c11d0 100644
--- a/phpBB/phpbb/composer/manager.php
+++ b/phpBB/phpbb/composer/manager.php
@@ -13,6 +13,7 @@
namespace phpbb\composer;
+use Composer\IO\IOInterface;
use phpbb\composer\exception\runtime_exception;
/**
@@ -65,7 +66,7 @@ class manager implements manager_interface
/**
* {@inheritdoc}
*/
- public function install(array $packages)
+ public function install(array $packages, IOInterface $io = null)
{
$packages = $this->normalize_version($packages);
@@ -75,20 +76,21 @@ class manager implements manager_interface
throw new runtime_exception($this->exception_prefix, 'ALREADY_INSTALLED', [implode('|', $already_managed)]);
}
- $this->do_install($packages);
+ $this->do_install($packages, $io);
}
/**
* Really install the packages.
*
* @param array $packages Packages to install.
+ * @param IOInterface $io IO object used for the output
*/
- protected function do_install($packages)
+ protected function do_install($packages, IOInterface $io = null)
{
$managed_packages = array_merge($this->get_all_managed_packages(), $packages);
ksort($managed_packages);
- $this->installer->install($managed_packages, array_keys($packages));
+ $this->installer->install($managed_packages, array_keys($packages), $io);
$this->managed_packages = null;
}
@@ -96,7 +98,7 @@ class manager implements manager_interface
/**
* {@inheritdoc}
*/
- public function update(array $packages)
+ public function update(array $packages, IOInterface $io = null)
{
$packages = $this->normalize_version($packages);
@@ -110,13 +112,13 @@ class manager implements manager_interface
$managed_packages = array_merge($this->get_all_managed_packages(), $packages);
ksort($managed_packages);
- $this->installer->install($managed_packages, array_keys($packages));
+ $this->installer->install($managed_packages, array_keys($packages), $io);
}
/**
* {@inheritdoc}
*/
- public function remove(array $packages)
+ public function remove(array $packages, IOInterface $io = null)
{
$packages = $this->normalize_version($packages);
@@ -130,7 +132,7 @@ class manager implements manager_interface
$managed_packages = array_diff_key($this->get_all_managed_packages(), $packages);
ksort($managed_packages);
- $this->installer->install($managed_packages, array_keys($packages));
+ $this->installer->install($managed_packages, array_keys($packages), $io);
$this->managed_packages = null;
}
diff --git a/phpBB/phpbb/composer/manager_interface.php b/phpBB/phpbb/composer/manager_interface.php
index 13f9498b35..b5d0177342 100644
--- a/phpBB/phpbb/composer/manager_interface.php
+++ b/phpBB/phpbb/composer/manager_interface.php
@@ -6,6 +6,7 @@
* Time: 23:12
*/
namespace phpbb\composer;
+use Composer\IO\IOInterface;
use phpbb\composer\exception\runtime_exception;
@@ -19,30 +20,33 @@ interface manager_interface
*
* @param array $packages Packages to install.
* Each entry may be a name or an array associating a version constraint to a name
+ * @param IOInterface $io IO object used for the output
*
* @throws runtime_exception
*/
- public function install(array $packages);
+ public function install(array $packages, IOInterface $io = null);
/**
* Updates or installs a set of packages
*
* @param array $packages Packages to update.
* Each entry may be a name or an array associating a version constraint to a name
+ * @param IOInterface $io IO object used for the output
*
* @throws runtime_exception
*/
- public function update(array $packages);
+ public function update(array $packages, IOInterface $io = null);
/**
* Removes a set of packages
*
* @param array $packages Packages to remove.
* Each entry may be a name or an array associating a version constraint to a name
+ * @param IOInterface $io IO object used for the output
*
* @throws runtime_exception
*/
- public function remove(array $packages);
+ public function remove(array $packages, IOInterface $io = null);
/**
* Tells whether or not a package is managed by Composer.
diff --git a/phpBB/phpbb/console/command/extension/install.php b/phpBB/phpbb/console/command/extension/install.php
index 4d83fe2cef..aa9d5a6867 100644
--- a/phpBB/phpbb/console/command/extension/install.php
+++ b/phpBB/phpbb/console/command/extension/install.php
@@ -13,8 +13,10 @@
namespace phpbb\console\command\extension;
-use phpbb\composer\manager;
+use phpbb\composer\io\console_io;
use phpbb\composer\manager_interface;
+use phpbb\language\language;
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -27,9 +29,15 @@ class install extends \phpbb\console\command\command
*/
protected $manager;
- public function __construct(\phpbb\user $user, manager_interface $manager)
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ public function __construct(\phpbb\user $user, manager_interface $manager, language $language)
{
$this->manager = $manager;
+ $this->language = $language;
parent::__construct($user);
}
@@ -60,11 +68,13 @@ class install extends \phpbb\console\command\command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $io = new SymfonyStyle($input, $output);
+ $output->getFormatter()->setStyle('warning', new OutputFormatterStyle('black', 'yellow'));
+ $io = new SymfonyStyle($input, $output);
+ $composer_io = new console_io($input, $output, $this->getHelperSet(), $this->language);
$extensions = $input->getArgument('extensions');
- $this->manager->install($extensions);
+ $this->manager->install($extensions, $composer_io);
$io->success('All extensions installed');
diff --git a/phpBB/phpbb/console/command/extension/remove.php b/phpBB/phpbb/console/command/extension/remove.php
index 16a3ad263f..d1f59dec5c 100644
--- a/phpBB/phpbb/console/command/extension/remove.php
+++ b/phpBB/phpbb/console/command/extension/remove.php
@@ -13,8 +13,10 @@
namespace phpbb\console\command\extension;
-use phpbb\composer\manager;
+use phpbb\composer\io\console_io;
use phpbb\composer\manager_interface;
+use phpbb\language\language;
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -27,9 +29,15 @@ class remove extends \phpbb\console\command\command
*/
protected $manager;
- public function __construct(\phpbb\user $user, manager_interface $manager)
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ public function __construct(\phpbb\user $user, manager_interface $manager, language $language)
{
$this->manager = $manager;
+ $this->language = $language;
parent::__construct($user);
}
@@ -60,11 +68,13 @@ class remove extends \phpbb\console\command\command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $io = new SymfonyStyle($input, $output);
+ $output->getFormatter()->setStyle('warning', new OutputFormatterStyle('black', 'yellow'));
+ $io = new SymfonyStyle($input, $output);
+ $composer_io = new console_io($input, $output, $this->getHelperSet(), $this->language);
$extensions = $input->getArgument('extensions');
- $this->manager->remove($extensions);
+ $this->manager->remove($extensions, $composer_io);
$io->success('All extensions removed');
diff --git a/phpBB/phpbb/console/command/extension/update.php b/phpBB/phpbb/console/command/extension/update.php
index e3f8935985..7a38294ed4 100644
--- a/phpBB/phpbb/console/command/extension/update.php
+++ b/phpBB/phpbb/console/command/extension/update.php
@@ -13,8 +13,10 @@
namespace phpbb\console\command\extension;
-use phpbb\composer\manager;
+use phpbb\composer\io\console_io;
use phpbb\composer\manager_interface;
+use phpbb\language\language;
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -27,9 +29,15 @@ class update extends \phpbb\console\command\command
*/
protected $manager;
- public function __construct(\phpbb\user $user, manager_interface $manager)
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ public function __construct(\phpbb\user $user, manager_interface $manager, language $language)
{
$this->manager = $manager;
+ $this->language = $language;
parent::__construct($user);
}
@@ -60,11 +68,13 @@ class update extends \phpbb\console\command\command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $io = new SymfonyStyle($input, $output);
+ $output->getFormatter()->setStyle('warning', new OutputFormatterStyle('black', 'yellow'));
+ $io = new SymfonyStyle($input, $output);
+ $composer_io = new console_io($input, $output, $this->getHelperSet(), $this->language);
$extensions = $input->getArgument('extensions');
- $this->manager->update($extensions);
+ $this->manager->update($extensions, $composer_io);
$io->success('All extensions updated');