Merge branch '3.2.x'

* 3.2.x:
  [ticket/14561] Remove requires for functions in tests
  [ticket/14561] Small change to progress bar output
  [ticket/14561] Fix function docblock in activate command
  [ticket/14561] Add a progress bar to reclean command
  [ticket/14561] Use the user loader where appropriate
  [ticket/14561] Add extra help explaining reclean command
  [ticket/14561] Import classes with use statements
  [ticket/14561] Remove unused use statements
  [ticket/14561] Refactor tests
  [ticket/14561] Reclean usernames command
  [ticket/14561] User activate command
  [ticket/14561] User delete command
This commit is contained in:
Tristan Darricau 2016-04-03 16:32:25 +02:00
commit b1085b7dcb
12 changed files with 1045 additions and 119 deletions

View file

@ -220,6 +220,21 @@ services:
tags: tags:
- { name: console.command } - { name: console.command }
console.command.user.activate:
class: phpbb\console\command\user\activate
arguments:
- '@user'
- '@dbal.conn'
- '@config'
- '@language'
- '@log'
- '@notification_manager'
- '@user_loader'
- '%core.root_path%'
- '%core.php_ext%'
tags:
- { name: console.command }
console.command.user.add: console.command.user.add:
class: phpbb\console\command\user\add class: phpbb\console\command\user\add
arguments: arguments:
@ -232,3 +247,25 @@ services:
- '%core.php_ext%' - '%core.php_ext%'
tags: tags:
- { name: console.command } - { name: console.command }
console.command.user.delete:
class: phpbb\console\command\user\delete
arguments:
- '@user'
- '@dbal.conn'
- '@language'
- '@log'
- '@user_loader'
- '%core.root_path%'
- '%core.php_ext%'
tags:
- { name: console.command }
console.command.user.reclean:
class: phpbb\console\command\user\reclean
arguments:
- '@user'
- '@dbal.conn'
- '@language'
tags:
- { name: console.command }

View file

@ -82,11 +82,20 @@ $lang = array_merge($lang, array(
'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.', 'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.',
'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.', 'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.',
'CLI_DESCRIPTION_USER_ACTIVATE' => 'Activate (or deactivate) a user account.',
'CLI_DESCRIPTION_USER_ACTIVATE_USERNAME' => 'Username of the account to activate.',
'CLI_DESCRIPTION_USER_ACTIVATE_DEACTIVATE' => 'Deactivate the users account',
'CLI_DESCRIPTION_USER_ACTIVATE_ACTIVE' => 'The user is already active.',
'CLI_DESCRIPTION_USER_ACTIVATE_INACTIVE' => 'The user is already inactive.',
'CLI_DESCRIPTION_USER_ADD' => 'Add a new user.', 'CLI_DESCRIPTION_USER_ADD' => 'Add a new user.',
'CLI_DESCRIPTION_USER_ADD_OPTION_USERNAME' => 'Username of the new user', 'CLI_DESCRIPTION_USER_ADD_OPTION_USERNAME' => 'Username of the new user',
'CLI_DESCRIPTION_USER_ADD_OPTION_PASSWORD' => 'Password of the new user', 'CLI_DESCRIPTION_USER_ADD_OPTION_PASSWORD' => 'Password of the new user',
'CLI_DESCRIPTION_USER_ADD_OPTION_EMAIL' => 'E-mail address of the new user', 'CLI_DESCRIPTION_USER_ADD_OPTION_EMAIL' => 'E-mail address of the new user',
'CLI_DESCRIPTION_USER_ADD_OPTION_NOTIFY' => 'Send account activation email to the new user (not sent by default)', 'CLI_DESCRIPTION_USER_ADD_OPTION_NOTIFY' => 'Send account activation email to the new user (not sent by default)',
'CLI_DESCRIPTION_USER_DELETE' => 'Delete a user account.',
'CLI_DESCRIPTION_USER_DELETE_USERNAME' => 'Username of the user to delete',
'CLI_DESCRIPTION_USER_DELETE_OPTION_POSTS' => 'Delete all posts by the user. Without this option, the users posts will be retained.',
'CLI_DESCRIPTION_USER_RECLEAN' => 'Re-clean usernames.',
'CLI_EXTENSION_DISABLE_FAILURE' => 'Could not disable extension %s', 'CLI_EXTENSION_DISABLE_FAILURE' => 'Could not disable extension %s',
'CLI_EXTENSION_DISABLE_SUCCESS' => 'Successfully disabled extension %s', 'CLI_EXTENSION_DISABLE_SUCCESS' => 'Successfully disabled extension %s',
@ -126,12 +135,22 @@ $lang = array_merge($lang, array(
'CLI_THUMBNAIL_NOTHING_TO_DELETE' => 'No thumbnails to delete.', 'CLI_THUMBNAIL_NOTHING_TO_DELETE' => 'No thumbnails to delete.',
'CLI_USER_ADD_SUCCESS' => 'Successfully added user %s.', 'CLI_USER_ADD_SUCCESS' => 'Successfully added user %s.',
'CLI_USER_DELETE_CONFIRM' => 'Are you sure you want to delete %s? [y/N]',
'CLI_USER_RECLEAN_START' => 'Re-cleaning usernames',
'CLI_USER_RECLEAN_DONE' => [
0 => 'Re-cleaning complete. No usernames needed to be cleaned.',
1 => 'Re-cleaning complete. %d username was cleaned.',
2 => 'Re-cleaning complete. %d usernames were cleaned.',
],
)); ));
// Additional help for commands. // Additional help for commands.
$lang = array_merge($lang, array( $lang = array_merge($lang, array(
'CLI_HELP_CRON_RUN' => $lang['CLI_DESCRIPTION_CRON_RUN'] . ' Optionally you can specify a cron task name to run only the specified cron task.', 'CLI_HELP_CRON_RUN' => $lang['CLI_DESCRIPTION_CRON_RUN'] . ' Optionally you can specify a cron task name to run only the specified cron task.',
'CLI_HELP_USER_ACTIVATE' => 'Activate a user account, or deactivate an account using the <info>--deactivate</info> option.
To optionally send an activation email to the user, use the <info>--send-email</info> option.',
'CLI_HELP_USER_ADD' => 'The <info>%command.name%</info> command adds a new user: 'CLI_HELP_USER_ADD' => 'The <info>%command.name%</info> command adds a new user:
If this command is run without options, you will be prompted to enter them. If this command is run without options, you will be prompted to enter them.
To optionally send an email to the new user, use the <info>--send-email</info> option.', To optionally send an email to the new user, use the <info>--send-email</info> option.',
'CLI_HELP_USER_RECLEAN' => 'Re-clean usernames will check all stored usernames and ensure clean versions are also stored. Cleaned usernames are a case insensitive form, NFC normalized and transformed to ASCII.',
)); ));

View file

@ -0,0 +1,218 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @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\user;
use phpbb\config\config;
use phpbb\console\command\command;
use phpbb\db\driver\driver_interface;
use phpbb\language\language;
use phpbb\log\log_interface;
use phpbb\notification\manager;
use phpbb\user;
use phpbb\user_loader;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class activate extends command
{
/** @var driver_interface */
protected $db;
/** @var config */
protected $config;
/** @var language */
protected $language;
/** @var log_interface */
protected $log;
/** @var manager */
protected $notifications;
/** @var user_loader */
protected $user_loader;
/**
* phpBB root path
*
* @var string
*/
protected $phpbb_root_path;
/**
* PHP extension.
*
* @var string
*/
protected $php_ext;
/**
* Construct method
*
* @param user $user
* @param driver_interface $db
* @param config $config
* @param language $language
* @param log_interface $log
* @param manager $notifications
* @param user_loader $user_loader
* @param string $phpbb_root_path
* @param string $php_ext
*/
public function __construct(user $user, driver_interface $db, config $config, language $language, log_interface $log, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->config = $config;
$this->language = $language;
$this->log = $log;
$this->notifications = $notifications;
$this->user_loader = $user_loader;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->language->add_lang('acp/users');
parent::__construct($user);
}
/**
* Sets the command name and description
*
* @return null
*/
protected function configure()
{
$this
->setName('user:activate')
->setDescription($this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE'))
->setHelp($this->language->lang('CLI_HELP_USER_ACTIVATE'))
->addArgument(
'username',
InputArgument::REQUIRED,
$this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_USERNAME')
)
->addOption(
'deactivate',
'd',
InputOption::VALUE_NONE,
$this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_DEACTIVATE')
)
->addOption(
'send-email',
null,
InputOption::VALUE_NONE,
$this->language->lang('CLI_DESCRIPTION_USER_ADD_OPTION_NOTIFY')
)
;
}
/**
* Executes the command user:activate
*
* Activate (or deactivate) a user account
*
* @param InputInterface $input The input stream used to get the options
* @param OutputInterface $output The output stream, used to print messages
*
* @return int 0 if all is well, 1 if any errors occurred
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('username');
$mode = ($input->getOption('deactivate')) ? 'deactivate' : 'activate';
$user_id = $this->user_loader->load_user_by_username($name);
$user_row = $this->user_loader->get_user($user_id);
if ($user_row['user_id'] == ANONYMOUS)
{
$io->error($this->language->lang('NO_USER'));
return 1;
}
// Check if the user is already active (or inactive)
if ($mode == 'activate' && $user_row['user_type'] != USER_INACTIVE)
{
$io->error($this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_ACTIVE'));
return 1;
}
else if ($mode == 'deactivate' && $user_row['user_type'] == USER_INACTIVE)
{
$io->error($this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_INACTIVE'));
return 1;
}
// Activate the user account
if (!function_exists('user_active_flip'))
{
require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
user_active_flip($mode, $user_row['user_id']);
// Notify the user upon activation
if ($mode == 'activate' && $this->config['require_activation'] == USER_ACTIVATION_ADMIN)
{
$this->send_notification($user_row, $input);
}
// Log and display the result
$msg = ($mode == 'activate') ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED';
$log = ($mode == 'activate') ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE';
$this->log->add('admin', ANONYMOUS, '', $log, false, array($user_row['username']));
$this->log->add('user', ANONYMOUS, '', $log . '_USER', false, array(
'reportee_id' => $user_row['user_id']
));
$io->success($this->language->lang($msg));
return 0;
}
/**
* Send account activation notification to user
*
* @param array $user_row The user data array
* @param InputInterface $input The input stream used to get the options
* @return null
*/
protected function send_notification($user_row, InputInterface $input)
{
$this->notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']);
if ($input->getOption('send-email'))
{
if (!class_exists('messenger'))
{
require($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
}
$messenger = new \messenger(false);
$messenger->template('admin_welcome_activated', $user_row['user_lang']);
$messenger->set_addresses($user_row);
$messenger->anti_abuse_headers($this->config, $this->user);
$messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($user_row['username']))
);
$messenger->send(NOTIFY_EMAIL);
}
}
}

View file

@ -13,28 +13,34 @@
namespace phpbb\console\command\user; namespace phpbb\console\command\user;
use phpbb\config\config;
use phpbb\console\command\command;
use phpbb\db\driver\driver_interface;
use phpbb\exception\runtime_exception; use phpbb\exception\runtime_exception;
use phpbb\language\language;
use phpbb\passwords\manager;
use phpbb\user;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
class add extends \phpbb\console\command\command class add extends command
{ {
/** @var array Array of interactively acquired options */ /** @var array Array of interactively acquired options */
protected $data; protected $data;
/** @var \phpbb\db\driver\driver_interface */ /** @var driver_interface */
protected $db; protected $db;
/** @var \phpbb\config\config */ /** @var config */
protected $config; protected $config;
/** @var \phpbb\language\language */ /** @var language */
protected $language; protected $language;
/** @var \phpbb\passwords\manager */ /** @var manager */
protected $password_manager; protected $password_manager;
/** /**
@ -54,15 +60,15 @@ class add extends \phpbb\console\command\command
/** /**
* Construct method * Construct method
* *
* @param \phpbb\user $user * @param user $user
* @param \phpbb\db\driver\driver_interface $db * @param driver_interface $db
* @param \phpbb\config\config $config * @param config $config
* @param \phpbb\language\language $language * @param language $language
* @param \phpbb\passwords\manager $password_manager * @param manager $password_manager
* @param string $phpbb_root_path * @param string $phpbb_root_path
* @param string $php_ext * @param string $php_ext
*/ */
public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\language\language $language, \phpbb\passwords\manager $password_manager, $phpbb_root_path, $php_ext) public function __construct(user $user, driver_interface $db, config $config, language $language, manager $password_manager, $phpbb_root_path, $php_ext)
{ {
$this->db = $db; $this->db = $db;
$this->config = $config; $this->config = $config;

View file

@ -0,0 +1,170 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @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\user;
use phpbb\console\command\command;
use phpbb\db\driver\driver_interface;
use phpbb\language\language;
use phpbb\log\log_interface;
use phpbb\user;
use phpbb\user_loader;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Style\SymfonyStyle;
class delete extends command
{
/** @var driver_interface */
protected $db;
/** @var language */
protected $language;
/** @var log_interface */
protected $log;
/** @var user_loader */
protected $user_loader;
/**
* phpBB root path
*
* @var string
*/
protected $phpbb_root_path;
/**
* PHP extension.
*
* @var string
*/
protected $php_ext;
/**
* Construct method
*
* @param user $user
* @param driver_interface $db
* @param language $language
* @param log_interface $log
* @param user_loader $user_loader
* @param string $phpbb_root_path
* @param string $php_ext
*/
public function __construct(user $user, driver_interface $db, language $language, log_interface $log, user_loader $user_loader, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->language = $language;
$this->log = $log;
$this->user_loader = $user_loader;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->language->add_lang('acp/users');
parent::__construct($user);
}
/**
* Sets the command name and description
*
* @return null
*/
protected function configure()
{
$this
->setName('user:delete')
->setDescription($this->language->lang('CLI_DESCRIPTION_USER_DELETE'))
->addArgument(
'username',
InputArgument::REQUIRED,
$this->language->lang('CLI_DESCRIPTION_USER_DELETE_USERNAME')
)
->addOption(
'delete-posts',
null,
InputOption::VALUE_NONE,
$this->language->lang('CLI_DESCRIPTION_USER_DELETE_OPTION_POSTS')
)
;
}
/**
* Executes the command user:delete
*
* Deletes a user from the database. An option to delete the user's posts
* is available, by default posts will be retained.
*
* @param InputInterface $input The input stream used to get the options
* @param OutputInterface $output The output stream, used to print messages
*
* @return int 0 if all is well, 1 if any errors occurred
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getArgument('username');
$mode = ($input->getOption('delete-posts')) ? 'remove' : 'retain';
if ($name)
{
$io = new SymfonyStyle($input, $output);
$user_id = $this->user_loader->load_user_by_username($name);
$user_row = $this->user_loader->get_user($user_id);
if ($user_row['user_id'] == ANONYMOUS)
{
$io->error($this->language->lang('NO_USER'));
return 1;
}
if (!function_exists('user_delete'))
{
require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
user_delete($mode, $user_row['user_id'], $user_row['username']);
$this->log->add('admin', ANONYMOUS, '', 'LOG_USER_DELETED', false, array($user_row['username']));
$io->success($this->language->lang('USER_DELETED'));
}
return 0;
}
/**
* Interacts with the user.
* Confirm they really want to delete the account...last chance!
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
$helper = $this->getHelper('question');
$question = new ConfirmationQuestion(
$this->language->lang('CLI_USER_DELETE_CONFIRM', $input->getArgument('username')),
false
);
if (!$helper->ask($input, $output, $question))
{
$input->setArgument('username', false);
}
}
}

View file

@ -0,0 +1,198 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @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\user;
use phpbb\console\command\command;
use phpbb\db\driver\driver_interface;
use phpbb\language\language;
use phpbb\user;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class reclean extends command
{
/** @var driver_interface */
protected $db;
/** @var language */
protected $language;
/** @var int A count of the number of re-cleaned user names */
protected $processed;
/** @var ProgressBar */
protected $progress;
/**
* Construct method
*
* @param user $user
* @param driver_interface $db
* @param language $language
*/
public function __construct(user $user, driver_interface $db, language $language)
{
$this->db = $db;
$this->language = $language;
parent::__construct($user);
}
/**
* Sets the command name and description
*
* @return null
*/
protected function configure()
{
$this
->setName('user:reclean')
->setDescription($this->language->lang('CLI_DESCRIPTION_USER_RECLEAN'))
->setHelp($this->language->lang('CLI_HELP_USER_RECLEAN'))
;
}
/**
* Executes the command user:reclean
*
* Cleans user names that are unclean.
*
* @param InputInterface $input The input stream used to get the options
* @param OutputInterface $output The output stream, used to print messages
*
* @return int 0 if all is well, 1 if any errors occurred
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->section($this->language->lang('CLI_USER_RECLEAN_START'));
$this->processed = 0;
$this->progress = $this->create_progress_bar($this->get_count(), $io, $output);
$this->progress->setMessage($this->language->lang('CLI_USER_RECLEAN_START'));
$this->progress->start();
$stage = 0;
while ($stage !== true)
{
$stage = $this->reclean_usernames($stage);
}
$this->progress->finish();
$io->newLine(2);
$io->success($this->language->lang('CLI_USER_RECLEAN_DONE', $this->processed));
return 0;
}
/**
* Re-clean user names
* Only user names that are unclean will be re-cleaned
*
* @param int $start An offset index
* @return bool|int Return the next offset index or true if all records have been processed.
*/
protected function reclean_usernames($start = 0)
{
$limit = 500;
$i = 0;
$this->db->sql_transaction('begin');
$sql = 'SELECT user_id, username, username_clean FROM ' . USERS_TABLE;
$result = $this->db->sql_query_limit($sql, $limit, $start);
while ($row = $this->db->sql_fetchrow($result))
{
$i++;
$username_clean = $this->db->sql_escape(utf8_clean_string($row['username']));
if ($username_clean != $row['username_clean'])
{
$sql = 'UPDATE ' . USERS_TABLE . "
SET username_clean = '$username_clean'
WHERE user_id = {$row['user_id']}";
$this->db->sql_query($sql);
$this->processed++;
}
$this->progress->advance();
}
$this->db->sql_freeresult($result);
$this->db->sql_transaction('commit');
return ($i < $limit) ? true : $start + $i;
}
/**
* Create a styled progress bar
*
* @param integer $max Max value for the progress bar
* @param SymfonyStyle $io
* @param OutputInterface $output The output stream, used to print messages
* @return ProgressBar
*/
protected function create_progress_bar($max, SymfonyStyle $io, OutputInterface $output)
{
$progress = $io->createProgressBar($max);
if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE)
{
$progress->setFormat('<info>[%percent:3s%%]</info> %message%');
$progress->setOverwrite(false);
}
else if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE)
{
$progress->setFormat('<info>[%current:s%/%max:s%]</info><comment>[%elapsed%/%estimated%][%memory%]</comment> %message%');
$progress->setOverwrite(false);
}
else
{
$io->newLine(2);
$progress->setFormat(
" %current:s%/%max:s% %bar% %percent:3s%%\n" .
" %elapsed:6s%/%estimated:-6s% %memory:6s%\n");
$progress->setBarWidth(60);
}
if (!defined('PHP_WINDOWS_VERSION_BUILD'))
{
$progress->setEmptyBarCharacter('░'); // light shade character \u2591
$progress->setProgressCharacter('');
$progress->setBarCharacter('▓'); // dark shade character \u2593
}
return $progress;
}
/**
* Get the count of users in the database
*
* @return int
*/
protected function get_count()
{
$sql = 'SELECT COUNT(user_id) AS count FROM ' . USERS_TABLE;
$result = $this->db->sql_query($sql);
$count = (int) $this->db->sql_fetchfield('count');
$this->db->sql_freeresult($result);
return $count;
}
}

View file

@ -0,0 +1,86 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use phpbb\console\command\user\activate;
require_once dirname(__FILE__) . '/base.php';
class phpbb_console_user_activate_test extends phpbb_console_user_base
{
protected $notifications;
public function setUp()
{
parent::setUp();
$this->notifications = $this->getMockBuilder('\phpbb\notification\manager')
->disableOriginalConstructor()
->getMock();
}
public function get_command_tester()
{
$application = new Application();
$application->add(new activate(
$this->user,
$this->db,
$this->config,
$this->language,
$this->log,
$this->notifications,
$this->user_loader,
$this->phpbb_root_path,
$this->php_ext
));
$command = $application->find('user:activate');
$this->command_name = $command->getName();
return new CommandTester($command);
}
public function activate_test_data()
{
return array(
// Test an inactive user
array('Test', false, 'USER_ADMIN_ACTIVATED'),
array('Test', true, 'CLI_DESCRIPTION_USER_ACTIVATE_INACTIVE'),
// Test an active user
array('Test 2', false, 'CLI_DESCRIPTION_USER_ACTIVATE_ACTIVE'),
array('Test 2', true, 'USER_ADMIN_DEACTIVED'),
// Test a non existent user
array('Foo', false, 'NO_USER'),
array('Foo', true, 'NO_USER'),
);
}
/**
* @dataProvider activate_test_data
*/
public function test_activate($username, $deactivate, $expected)
{
$command_tester = $this->get_command_tester();
$command_tester->execute(array(
'command' => $this->command_name,
'username' => $username,
'--deactivate' => $deactivate,
));
$this->assertContains($expected, $command_tester->getDisplay());
}
}

View file

@ -15,75 +15,27 @@ use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Tester\CommandTester;
use phpbb\console\command\user\add; use phpbb\console\command\user\add;
require_once dirname(__FILE__) . '/../../../phpBB/includes/functions_user.php'; require_once dirname(__FILE__) . '/base.php';
class phpbb_console_command_user_add_test extends phpbb_database_test_case class phpbb_console_user_add_test extends phpbb_console_user_base
{ {
protected $db; public function get_command_tester()
protected $config;
protected $user;
protected $language;
protected $passwords_manager;
protected $command_name;
protected $question;
protected $phpbb_root_path;
protected $php_ext;
public function getDataSet()
{ {
return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml'); $application = new Application();
} $application->add(new add(
$this->user,
public function setUp() $this->db,
{ $this->config,
global $db, $cache, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_root_path, $phpEx;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('cache.driver', new phpbb_mock_cache());
$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
$cache = $phpbb_container->get('cache.driver');
$config = $this->config = new \phpbb\config\config(array(
'board_timezone' => 'UTC',
'default_lang' => 'en',
'email_enable' => false,
'min_name_chars' => 3,
'max_name_chars' => 10,
'min_pass_chars' => 3,
'max_pass_chars' => 10,
'pass_complex' => 'PASS_TYPE_ANY',
));
$db = $this->db = $this->new_dbal();
$this->language = $this->getMockBuilder('\phpbb\language\language')
->disableOriginalConstructor()
->getMock();
$this->language->expects($this->any())
->method('lang')
->will($this->returnArgument(0));
$user = $this->user = $this->getMock('\phpbb\user', array(), array(
$this->language, $this->language,
'\phpbb\datetime' $this->passwords_manager,
$this->phpbb_root_path,
$this->php_ext
)); ));
$driver_helper = new \phpbb\passwords\driver\helper($this->config); $command = $application->find('user:add');
$passwords_drivers = array( $this->command_name = $command->getName();
'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($this->config, $driver_helper), $this->question = $command->getHelper('question');
'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($this->config, $driver_helper), return new CommandTester($command);
'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($this->config, $driver_helper),
'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($this->config, $driver_helper),
);
$passwords_helper = new \phpbb\passwords\helper;
$this->passwords_manager = new \phpbb\passwords\manager($this->config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers));
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
parent::setUp();
} }
public function test_add_no_dialog() public function test_add_no_dialog()
@ -137,47 +89,4 @@ class phpbb_console_command_user_add_test extends phpbb_database_test_case
$this->assertContains('TOO_SHORT', $command_tester->getDisplay()); $this->assertContains('TOO_SHORT', $command_tester->getDisplay());
$this->assertContains('EMAIL_INVALID', $command_tester->getDisplay()); $this->assertContains('EMAIL_INVALID', $command_tester->getDisplay());
} }
public function get_command_tester()
{
$application = new Application();
$application->add(new add(
$this->user,
$this->db,
$this->config,
$this->language,
$this->passwords_manager,
$this->phpbb_root_path,
$this->php_ext
));
$command = $application->find('user:add');
$this->command_name = $command->getName();
$this->question = $command->getHelper('question');
return new CommandTester($command);
}
public function get_user_id($username)
{
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . '
WHERE ' . 'username = ' . "'" . $username . "'";
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
return $row['user_id'];
}
public function getInputStream($input)
{
$stream = fopen('php://memory', 'r+', false);
fputs($stream, $input);
rewind($stream);
return $stream;
}
} }

121
tests/console/user/base.php Normal file
View file

@ -0,0 +1,121 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
abstract class phpbb_console_user_base extends phpbb_database_test_case
{
protected $db;
protected $config;
protected $user;
protected $language;
protected $log;
protected $passwords_manager;
protected $command_name;
protected $question;
protected $user_loader;
protected $phpbb_root_path;
protected $php_ext;
public function getDataSet()
{
return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml');
}
public function setUp()
{
global $auth, $db, $cache, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_root_path, $phpEx;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('cache.driver', new phpbb_mock_cache());
$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
$auth = $this->getMock('\phpbb\auth\auth');
$cache = $phpbb_container->get('cache.driver');
$config = $this->config = new \phpbb\config\config(array(
'board_timezone' => 'UTC',
'default_lang' => 'en',
'email_enable' => false,
'min_name_chars' => 3,
'max_name_chars' => 10,
'min_pass_chars' => 3,
'max_pass_chars' => 10,
'pass_complex' => 'PASS_TYPE_ANY',
));
$db = $this->db = $this->new_dbal();
$this->language = $this->getMockBuilder('\phpbb\language\language')
->disableOriginalConstructor()
->getMock();
$this->language->expects($this->any())
->method('lang')
->will($this->returnArgument(0));
$user = $this->user = $this->getMock('\phpbb\user', array(), array(
$this->language,
'\phpbb\datetime'
));
$this->user_loader = new \phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);
$driver_helper = new \phpbb\passwords\driver\helper($this->config);
$passwords_drivers = array(
'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($this->config, $driver_helper),
'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($this->config, $driver_helper),
'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($this->config, $driver_helper),
'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($this->config, $driver_helper),
);
$passwords_helper = new \phpbb\passwords\helper;
$this->passwords_manager = new \phpbb\passwords\manager($this->config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers));
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
$this->log = $this->getMockBuilder('\phpbb\log\log')
->disableOriginalConstructor()
->getMock();
$phpbb_container->set('auth.provider.db', new phpbb_mock_auth_provider());
$provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config);
$provider_collection->add('auth.provider.db');
$phpbb_container->set(
'auth.provider_collection',
$provider_collection
);
parent::setUp();
}
public function get_user_id($username)
{
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . '
WHERE ' . 'username = ' . "'" . $username . "'";
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
return $row['user_id'];
}
public function getInputStream($input)
{
$stream = fopen('php://memory', 'r+', false);
fputs($stream, $input);
rewind($stream);
return $stream;
}
}

View file

@ -0,0 +1,93 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use phpbb\console\command\user\delete;
require_once dirname(__FILE__) . '/base.php';
class phpbb_console_user_delete_test extends phpbb_console_user_base
{
public function get_command_tester()
{
$application = new Application();
$application->add(new delete(
$this->user,
$this->db,
$this->language,
$this->log,
$this->user_loader,
$this->phpbb_root_path,
$this->php_ext
));
$command = $application->find('user:delete');
$this->command_name = $command->getName();
$this->question = $command->getHelper('question');
return new CommandTester($command);
}
public function test_delete()
{
$command_tester = $this->get_command_tester();
$this->assertEquals(3, $this->get_user_id('Test'));
$this->question->setInputStream($this->getInputStream("yes\n"));
$command_tester->execute(array(
'command' => $this->command_name,
'username' => 'Test',
'--delete-posts' => false,
));
$this->assertNull($this->get_user_id('Test'));
$this->assertContains('USER_DELETED', $command_tester->getDisplay());
}
public function test_delete_non_user()
{
$command_tester = $this->get_command_tester();
$this->assertNull($this->get_user_id('Foo'));
$this->question->setInputStream($this->getInputStream("yes\n"));
$command_tester->execute(array(
'command' => $this->command_name,
'username' => 'Foo',
'--delete-posts' => false,
));
$this->assertContains('NO_USER', $command_tester->getDisplay());
}
public function test_delete_cancel()
{
$command_tester = $this->get_command_tester();
$this->assertEquals(3, $this->get_user_id('Test'));
$this->question->setInputStream($this->getInputStream("no\n"));
$command_tester->execute(array(
'command' => $this->command_name,
'username' => 'Test',
'--delete-posts' => false,
));
$this->assertNotNull($this->get_user_id('Test'));
}
}

View file

@ -6,12 +6,14 @@
<column>username</column> <column>username</column>
<column>username_clean</column> <column>username_clean</column>
<column>user_sig</column> <column>user_sig</column>
<column>user_type</column>
<row> <row>
<value>1</value> <value>1</value>
<value></value> <value></value>
<value>Guest</value> <value>Guest</value>
<value>guest</value> <value>guest</value>
<value></value> <value></value>
<value>0</value>
</row> </row>
<row> <row>
<value>2</value> <value>2</value>
@ -19,6 +21,7 @@
<value>Admin</value> <value>Admin</value>
<value>admin</value> <value>admin</value>
<value></value> <value></value>
<value>3</value>
</row> </row>
<row> <row>
<value>3</value> <value>3</value>
@ -26,6 +29,23 @@
<value>Test</value> <value>Test</value>
<value>test</value> <value>test</value>
<value></value> <value></value>
<value>1</value>
</row>
<row>
<value>4</value>
<value></value>
<value>Test 2</value>
<value>test 2</value>
<value></value>
<value>0</value>
</row>
<row>
<value>5</value>
<value></value>
<value>Test Unclean</value>
<value>Test Unclean</value>
<value></value>
<value>0</value>
</row> </row>
</table> </table>
<table name="phpbb_groups"> <table name="phpbb_groups">

View file

@ -0,0 +1,49 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use phpbb\console\command\user\reclean;
require_once dirname(__FILE__) . '/base.php';
class phpbb_console_user_reclean_test extends phpbb_console_user_base
{
public function get_command_tester()
{
$application = new Application();
$application->add(new reclean(
$this->user,
$this->db,
$this->language
));
$command = $application->find('user:reclean');
$this->command_name = $command->getName();
return new CommandTester($command);
}
public function test_reclean()
{
$command_tester = $this->get_command_tester();
$exit_status = $command_tester->execute(array('command' => $this->command_name));
$this->assertSame(0, $exit_status);
$result = $this->db->sql_query('SELECT user_id FROM ' . USERS_TABLE . " WHERE username_clean = 'test unclean'");
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
$this->assertNotNull($row['user_id']);
}
}