diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml
index f39218ed9c..15f597520c 100644
--- a/phpBB/config/default/container/services_console.yml
+++ b/phpBB/config/default/container/services_console.yml
@@ -156,3 +156,30 @@ services:
- @text_reparser_collection
tags:
- { name: console.command }
+
+ console.command.thumbnail.generate:
+ class: phpbb\console\command\thumbnail\generate
+ arguments:
+ - @dbal.conn
+ - @user
+ - @cache
+ - %core.root_path%
+ - %core.php_ext%
+ tags:
+ - { name: console.command }
+
+ console.command.thumbnail.recreate:
+ class: phpbb\console\command\thumbnail\recreate
+ arguments:
+ - @user
+ tags:
+ - { name: console.command }
+
+ console.command.thumbnail.delete:
+ class: phpbb\console\command\thumbnail\delete
+ arguments:
+ - @dbal.conn
+ - @user
+ - %core.root_path%
+ tags:
+ - { name: console.command }
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index fdbc4aebd0..77dc5b6b62 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -225,6 +225,12 @@ $lang = array_merge($lang, array(
'BACK' => 'Back',
+ 'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.',
+ 'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.',
+ 'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run',
+
+ 'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.',
+
'COLOUR_SWATCH' => 'Web-safe colour swatch',
'CONFIG_UPDATED' => 'Configuration updated successfully.',
'CRON_LOCK_ERROR' => 'Could not obtain cron lock.',
diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php
new file mode 100644
index 0000000000..81f1baf1db
--- /dev/null
+++ b/phpBB/phpbb/console/command/thumbnail/delete.php
@@ -0,0 +1,111 @@
+
+* @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\console\command\thumbnail;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class delete extends \phpbb\console\command\command
+{
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ /**
+ * phpBB root path
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param \phpbb\user $user The user object (used to get language information)
+ * @param string $phpbb_root_path Root path
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path)
+ {
+ $this->db = $db;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ parent::__construct();
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('thumbnail:delete')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_DELETE'))
+ ;
+ }
+
+ /**
+ * Executes the command thumbnail:delete.
+ *
+ * @param InputInterface $input The input stream used to get the argument and verboe option.
+ * @param OutputInterface $output The output stream, used for printing verbose-mode and error information.
+ *
+ * @return int 0 if all is ok, 1 if a thumbnail couldn't be deleted.
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE thumbnail = 1';
+ $result = $this->db->sql_query($sql);
+
+ $thumbnail_deleted = array();
+ $return = 0;
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $thumbnail_path = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename'];
+
+ if (@unlink($thumbnail_path))
+ {
+ $thumbnail_deleted[] = $row['attach_id'];
+ if ($input->getOption('verbose'))
+ {
+ $output->writeln($this->user->lang('THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename']));
+ }
+ }
+ else
+ {
+ if ($input->getOption('verbose'))
+ {
+ $return = 1;
+ $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . '');
+ }
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (sizeof($thumbnail_deleted))
+ {
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
+ SET thumbnail = 0
+ WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_deleted);
+ $this->db->sql_query($sql);
+ }
+
+ return $return;
+ }
+}
diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php
new file mode 100644
index 0000000000..dcf60e4fe2
--- /dev/null
+++ b/phpBB/phpbb/console/command/thumbnail/generate.php
@@ -0,0 +1,133 @@
+
+* @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\console\command\thumbnail;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class generate extends \phpbb\console\command\command
+{
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var \phpbb\cache\service */
+ protected $cache;
+
+ /**
+ * phpBB root path
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * PHP extension.
+ *
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param \phpbb\user $user The user object (used to get language information)
+ * @param \phpbb\cache\service $cache The cache service
+ * @param string $phpbb_root_path Root path
+ * @param string $php_ext PHP extension
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\cache\service $cache, $phpbb_root_path, $php_ext)
+ {
+ $this->db = $db;
+ $this->user = $user;
+ $this->cache = $cache;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ parent::__construct();
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('thumbnail:generate')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_GENERATE'))
+ ;
+ }
+
+ /**
+ * Executes the command thumbnail:generate.
+ *
+ * @param InputInterface $input The input stream used to get the argument and verboe option.
+ * @param OutputInterface $output The output stream, used for printing verbose-mode and error information.
+ *
+ * @return int 0.
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $extensions = $this->cache->obtain_attach_extensions(true);
+
+ $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE thumbnail = 0';
+ $result = $this->db->sql_query($sql);
+
+ if (!function_exists('create_thumbnail'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext);
+ }
+
+ $thumbnail_created = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (isset($extensions[$row['extension']]['display_cat']) && $extensions[$row['extension']]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE)
+ {
+ $source = $this->phpbb_root_path . 'files/' . $row['physical_filename'];
+ $destination = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename'];
+
+ if (!create_thumbnail($source, $destination, $row['mimetype']))
+ {
+ if ($input->getOption('verbose'))
+ {
+ $output->writeln('' . $this->user->lang('THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . '');
+ }
+ }
+ else
+ {
+ $thumbnail_created[] = $row['attach_id'];
+ if ($input->getOption('verbose'))
+ {
+ $output->writeln($this->user->lang('THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename']));
+ }
+ }
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (sizeof($thumbnail_created))
+ {
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
+ SET thumbnail = 1
+ WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_created);
+ $this->db->sql_query($sql);
+ }
+
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php
new file mode 100644
index 0000000000..569642f2a4
--- /dev/null
+++ b/phpBB/phpbb/console/command/thumbnail/recreate.php
@@ -0,0 +1,84 @@
+
+* @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\console\command\thumbnail;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class recreate extends \phpbb\console\command\command
+{
+ /** @var \phpbb\user */
+ protected $user;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\user $user The user object (used to get language information)
+ */
+ public function __construct(\phpbb\user $user)
+ {
+ $this->user = $user;
+ parent::__construct();
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('thumbnail:recreate')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_RECREATE'))
+ ;
+ }
+
+ /**
+ * Executes the command thumbnail:recreate.
+ *
+ * @param InputInterface $input The input stream used to get the argument and verboe option.
+ * @param OutputInterface $output The output stream, used for printing verbose-mode and error information.
+ *
+ * @return int 0 if all is ok, 1 if a thumbnail couldn't be deleted.
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $parameters = array(
+ 'command' => 'thumbnail:delete'
+ );
+
+ if ($input->getOption('verbose'))
+ {
+ $parameters['-v'] = true;
+ }
+
+ $this->getApplication()->setAutoExit(false);
+
+ $input_delete = new ArrayInput($parameters);
+ $return = $this->getApplication()->run($input_delete, $output);
+
+ if ($return == 0)
+ {
+ $parameters['command'] = 'thumbnail:generate';
+
+ $input_create = new ArrayInput($parameters);
+ $return = $this->getApplication()->run($input_create, $output);
+ }
+
+ $this->getApplication()->setAutoExit(true);
+
+ return $return;
+ }
+}