Merge pull request #3505 from PhrozenByte/feature/cmd-room-followup

Improve talk:room:* CLI commands
This commit is contained in:
Joas Schilling 2020-06-02 17:03:58 +02:00 коммит произвёл GitHub
Родитель d3de4491b4 0b13f861f8
Коммит 21b0d46559
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 2524 добавлений и 180 удалений

Просмотреть файл

@ -25,12 +25,11 @@ declare(strict_types=1);
namespace OCA\Talk\Command\Room; namespace OCA\Talk\Command\Room;
use Exception; use InvalidArgumentException;
use OC\Core\Command\Base; use OC\Core\Command\Base;
use OCA\Talk\Exceptions\RoomNotFoundException; use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Room; use OCA\Talk\Room;
use OCP\IUserManager; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@ -39,19 +38,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class Add extends Base { class Add extends Base {
use TRoomCommand; use TRoomCommand;
/** @var IUserManager */
public $userManager;
/** @var Manager */
public $manager;
public function __construct(IUserManager $userManager, Manager $manager) {
parent::__construct();
$this->userManager = $userManager;
$this->manager = $manager;
}
protected function configure(): void { protected function configure(): void {
$this $this
->setName('talk:room:add') ->setName('talk:room:add')
@ -70,11 +56,6 @@ class Add extends Base {
null, null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Invites all members of the given groups to the room' 'Invites all members of the given groups to the room'
)->addOption(
'circle',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Invites all members of the given circles to the room'
); );
} }
@ -82,7 +63,6 @@ class Add extends Base {
$token = $input->getArgument('token'); $token = $input->getArgument('token');
$users = $input->getOption('user'); $users = $input->getOption('user');
$groups = $input->getOption('group'); $groups = $input->getOption('group');
$circles = $input->getOption('circle');
try { try {
$room = $this->manager->getRoomByToken($token); $room = $this->manager->getRoomByToken($token);
@ -99,8 +79,7 @@ class Add extends Base {
try { try {
$this->addRoomParticipants($room, $users); $this->addRoomParticipants($room, $users);
$this->addRoomParticipantsByGroup($room, $groups); $this->addRoomParticipantsByGroup($room, $groups);
$this->addRoomParticipantsByCircle($room, $circles); } catch (InvalidArgumentException $e) {
} catch (Exception $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage())); $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return 1; return 1;
} }
@ -108,4 +87,25 @@ class Add extends Base {
$output->writeln('<info>Users successfully added to room.</info>'); $output->writeln('<info>Users successfully added to room.</info>');
return 0; return 0;
} }
public function completeOptionValues($optionName, CompletionContext $context) {
switch ($optionName) {
case 'user':
return $this->completeUserValues($context);
case 'group':
return $this->completeGroupValues($context);
}
return parent::completeOptionValues($optionName, $context);
}
public function completeArgumentValues($argumentName, CompletionContext $context) {
switch ($argumentName) {
case 'token':
return $this->completeTokenValues($context);
}
return parent::completeArgumentValues($argumentName, $context);
}
} }

Просмотреть файл

@ -25,10 +25,9 @@ declare(strict_types=1);
namespace OCA\Talk\Command\Room; namespace OCA\Talk\Command\Room;
use Exception; use InvalidArgumentException;
use OC\Core\Command\Base; use OC\Core\Command\Base;
use OCA\Talk\Manager; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use OCP\IUserManager;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@ -37,19 +36,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class Create extends Base { class Create extends Base {
use TRoomCommand; use TRoomCommand;
/** @var IUserManager */
public $userManager;
/** @var Manager */
public $manager;
public function __construct(IUserManager $userManager, Manager $manager) {
parent::__construct();
$this->userManager = $userManager;
$this->manager = $manager;
}
protected function configure(): void { protected function configure(): void {
$this $this
->setName('talk:room:create') ->setName('talk:room:create')
@ -68,11 +54,6 @@ class Create extends Base {
null, null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Invites all members of the given group to the room to create' 'Invites all members of the given group to the room to create'
)->addOption(
'circle',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Invites all members of the given circle to the room to create'
)->addOption( )->addOption(
'public', 'public',
null, null,
@ -105,7 +86,6 @@ class Create extends Base {
$name = $input->getArgument('name'); $name = $input->getArgument('name');
$users = $input->getOption('user'); $users = $input->getOption('user');
$groups = $input->getOption('group'); $groups = $input->getOption('group');
$circles = $input->getOption('circle');
$public = $input->getOption('public'); $public = $input->getOption('public');
$readonly = $input->getOption('readonly'); $readonly = $input->getOption('readonly');
$password = $input->getOption('password'); $password = $input->getOption('password');
@ -114,7 +94,7 @@ class Create extends Base {
$name = trim($name); $name = trim($name);
if (!$this->validateRoomName($name)) { if (!$this->validateRoomName($name)) {
$output->writeln("<error>Invalid room name.</error>"); $output->writeln('<error>Invalid room name.</error>');
return 1; return 1;
} }
@ -129,13 +109,12 @@ class Create extends Base {
$this->addRoomParticipants($room, $users); $this->addRoomParticipants($room, $users);
$this->addRoomParticipantsByGroup($room, $groups); $this->addRoomParticipantsByGroup($room, $groups);
$this->addRoomParticipantsByCircle($room, $circles);
$this->addRoomModerators($room, $moderators); $this->addRoomModerators($room, $moderators);
if ($owner !== null) { if ($owner !== null) {
$this->setRoomOwner($room, $owner); $this->setRoomOwner($room, $owner);
} }
} catch (Exception $e) { } catch (InvalidArgumentException $e) {
$room->deleteRoom(); $room->deleteRoom();
$output->writeln(sprintf('<error>%s</error>', $e->getMessage())); $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
@ -145,4 +124,20 @@ class Create extends Base {
$output->writeln('<info>Room successfully created.</info>'); $output->writeln('<info>Room successfully created.</info>');
return 0; return 0;
} }
public function completeOptionValues($optionName, CompletionContext $context) {
switch ($optionName) {
case 'user':
return $this->completeUserValues($context);
case 'group':
return $this->completeGroupValues($context);
case 'owner':
case 'moderator':
return $this->completeParticipantValues($context);
}
return parent::completeOptionValues($optionName, $context);
}
} }

Просмотреть файл

@ -27,21 +27,14 @@ namespace OCA\Talk\Command\Room;
use OC\Core\Command\Base; use OC\Core\Command\Base;
use OCA\Talk\Exceptions\RoomNotFoundException; use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Room; use OCA\Talk\Room;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
class Delete extends Base { class Delete extends Base {
/** @var Manager */ use TRoomCommand;
public $manager;
public function __construct(Manager $manager) {
parent::__construct();
$this->manager = $manager;
}
protected function configure(): void { protected function configure(): void {
$this $this
@ -74,4 +67,13 @@ class Delete extends Base {
$output->writeln('<info>Room successfully deleted.</info>'); $output->writeln('<info>Room successfully deleted.</info>');
return 0; return 0;
} }
public function completeArgumentValues($argumentName, CompletionContext $context) {
switch ($argumentName) {
case 'token':
return $this->completeTokenValues($context);
}
return parent::completeArgumentValues($argumentName, $context);
}
} }

Просмотреть файл

@ -25,12 +25,11 @@ declare(strict_types=1);
namespace OCA\Talk\Command\Room; namespace OCA\Talk\Command\Room;
use Exception; use InvalidArgumentException;
use OC\Core\Command\Base; use OC\Core\Command\Base;
use OCA\Talk\Exceptions\RoomNotFoundException; use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Room; use OCA\Talk\Room;
use OCP\IUserManager; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -38,19 +37,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class Demote extends Base { class Demote extends Base {
use TRoomCommand; use TRoomCommand;
/** @var IUserManager */
public $userManager;
/** @var Manager */
public $manager;
public function __construct(IUserManager $userManager, Manager $manager) {
parent::__construct();
$this->userManager = $userManager;
$this->manager = $manager;
}
protected function configure(): void { protected function configure(): void {
$this $this
->setName('talk:room:demote') ->setName('talk:room:demote')
@ -84,12 +70,24 @@ class Demote extends Base {
try { try {
$this->removeRoomModerators($room, $users); $this->removeRoomModerators($room, $users);
} catch (Exception $e) { } catch (InvalidArgumentException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage())); $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return 1; return 1;
} }
$output->writeln('<info>Users successfully remove from room.</info>'); $output->writeln('<info>Participants successfully demoted to regular users.</info>');
return 0; return 0;
} }
public function completeArgumentValues($argumentName, CompletionContext $context) {
switch ($argumentName) {
case 'token':
return $this->completeTokenValues($context);
case 'participant':
return $this->completeParticipantValues($context);
}
return parent::completeArgumentValues($argumentName, $context);
}
} }

Просмотреть файл

@ -25,12 +25,11 @@ declare(strict_types=1);
namespace OCA\Talk\Command\Room; namespace OCA\Talk\Command\Room;
use Exception; use InvalidArgumentException;
use OC\Core\Command\Base; use OC\Core\Command\Base;
use OCA\Talk\Exceptions\RoomNotFoundException; use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Room; use OCA\Talk\Room;
use OCP\IUserManager; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -38,19 +37,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class Promote extends Base { class Promote extends Base {
use TRoomCommand; use TRoomCommand;
/** @var IUserManager */
public $userManager;
/** @var Manager */
public $manager;
public function __construct(IUserManager $userManager, Manager $manager) {
parent::__construct();
$this->userManager = $userManager;
$this->manager = $manager;
}
protected function configure(): void { protected function configure(): void {
$this $this
->setName('talk:room:promote') ->setName('talk:room:promote')
@ -84,12 +70,24 @@ class Promote extends Base {
try { try {
$this->addRoomModerators($room, $users); $this->addRoomModerators($room, $users);
} catch (Exception $e) { } catch (InvalidArgumentException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage())); $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return 1; return 1;
} }
$output->writeln('<info>Users successfully added to room.</info>'); $output->writeln('<info>Participants successfully promoted to moderators.</info>');
return 0; return 0;
} }
public function completeArgumentValues($argumentName, CompletionContext $context) {
switch ($argumentName) {
case 'token':
return $this->completeTokenValues($context);
case 'participant':
return $this->completeParticipantValues($context);
}
return parent::completeArgumentValues($argumentName, $context);
}
} }

Просмотреть файл

@ -25,12 +25,11 @@ declare(strict_types=1);
namespace OCA\Talk\Command\Room; namespace OCA\Talk\Command\Room;
use Exception; use InvalidArgumentException;
use OC\Core\Command\Base; use OC\Core\Command\Base;
use OCA\Talk\Exceptions\RoomNotFoundException; use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Room; use OCA\Talk\Room;
use OCP\IUserManager; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -38,19 +37,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class Remove extends Base { class Remove extends Base {
use TRoomCommand; use TRoomCommand;
/** @var IUserManager */
public $userManager;
/** @var Manager */
public $manager;
public function __construct(IUserManager $userManager, Manager $manager) {
parent::__construct();
$this->userManager = $userManager;
$this->manager = $manager;
}
protected function configure(): void { protected function configure(): void {
$this $this
->setName('talk:room:remove') ->setName('talk:room:remove')
@ -60,15 +46,15 @@ class Remove extends Base {
InputArgument::REQUIRED, InputArgument::REQUIRED,
'Token of the room to remove users from' 'Token of the room to remove users from'
)->addArgument( )->addArgument(
'user', 'participant',
InputArgument::REQUIRED | InputArgument::IS_ARRAY, InputArgument::REQUIRED | InputArgument::IS_ARRAY,
'Removes the given users from the room' 'Removes the given participants from the room'
); );
} }
protected function execute(InputInterface $input, OutputInterface $output): ?int { protected function execute(InputInterface $input, OutputInterface $output): ?int {
$token = $input->getArgument('token'); $token = $input->getArgument('token');
$users = $input->getArgument('user'); $users = $input->getArgument('participant');
try { try {
$room = $this->manager->getRoomByToken($token); $room = $this->manager->getRoomByToken($token);
@ -84,12 +70,24 @@ class Remove extends Base {
try { try {
$this->removeRoomParticipants($room, $users); $this->removeRoomParticipants($room, $users);
} catch (Exception $e) { } catch (InvalidArgumentException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage())); $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return 1; return 1;
} }
$output->writeln('<info>Users successfully remove from room.</info>'); $output->writeln('<info>Users successfully removed from room.</info>');
return 0; return 0;
} }
public function completeArgumentValues($argumentName, CompletionContext $context) {
switch ($argumentName) {
case 'token':
return $this->completeTokenValues($context);
case 'participant':
return $this->completeParticipantValues($context);
}
return parent::completeArgumentValues($argumentName, $context);
}
} }

Просмотреть файл

@ -26,14 +26,44 @@ declare(strict_types=1);
namespace OCA\Talk\Command\Room; namespace OCA\Talk\Command\Room;
use InvalidArgumentException; use InvalidArgumentException;
use OCA\Circles\Api\v1\Circles;
use OCA\Circles\Model\Member;
use OCA\Talk\Exceptions\ParticipantNotFoundException; use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Participant; use OCA\Talk\Participant;
use OCA\Talk\Room; use OCA\Talk\Room;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUser; use OCP\IUser;
use OCP\IUserManager;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
trait TRoomCommand { trait TRoomCommand {
/** @var Manager */
protected $manager;
/** @var IUserManager */
protected $userManager;
/** @var IGroupManager */
protected $groupManager;
/**
* TRoomCommand constructor.
*
* @param Manager $manager
* @param IUserManager $userManager
* @param IGroupManager $groupManager
*/
public function __construct(Manager $manager, IUserManager $userManager, IGroupManager $groupManager) {
parent::__construct();
$this->manager = $manager;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
}
/** /**
* @param Room $room * @param Room $room
* @param string $name * @param string $name
@ -136,6 +166,8 @@ trait TRoomCommand {
throw new InvalidArgumentException(sprintf("User '%s' is no participant.", $userId)); throw new InvalidArgumentException(sprintf("User '%s' is no participant.", $userId));
} }
$this->unsetRoomOwner($room);
$room->setParticipantType($participant, Participant::OWNER); $room->setParticipantType($participant, Participant::OWNER);
} }
@ -163,11 +195,9 @@ trait TRoomCommand {
return; return;
} }
$groupManager = \OC::$server->getGroupManager();
$users = []; $users = [];
foreach ($groupIds as $groupId) { foreach ($groupIds as $groupId) {
$group = $groupManager->get($groupId); $group = $this->groupManager->get($groupId);
if ($group === null) { if ($group === null) {
throw new InvalidArgumentException(sprintf("Group '%s' not found.", $groupId)); throw new InvalidArgumentException(sprintf("Group '%s' not found.", $groupId));
} }
@ -182,43 +212,6 @@ trait TRoomCommand {
$this->addRoomParticipants($room, $users); $this->addRoomParticipants($room, $users);
} }
/**
* @param Room $room
* @param string[] $circleIds
*
* @throws InvalidArgumentException
*/
protected function addRoomParticipantsByCircle(Room $room, array $circleIds): void {
if (!$circleIds) {
return;
}
if (!\OC::$server->getAppManager()->isEnabledForUser('circles')) {
throw new InvalidArgumentException("App 'circles' is not enabled.");
}
$users = [];
foreach ($circleIds as $circleId) {
try {
$circle = Circles::detailsCircle($circleId);
} catch (\Exception $e) {
throw new InvalidArgumentException(sprintf("Circle '%s' not found.", $circleId));
}
$circleUsers = array_filter($circle->getMembers(), function (Member $member) {
if (($member->getType() !== Member::TYPE_USER) || ($member->getUserId() === '')) {
return false;
}
return in_array($member->getStatus(), [Member::STATUS_INVITED, Member::STATUS_MEMBER], true);
});
$users = array_merge($users, $circleUsers);
}
$this->addRoomParticipants($room, $users);
}
/** /**
* @param Room $room * @param Room $room
* @param string[] $userIds * @param string[] $userIds
@ -230,11 +223,9 @@ trait TRoomCommand {
return; return;
} }
$userManager = \OC::$server->getUserManager();
$participants = []; $participants = [];
foreach ($userIds as $userId) { foreach ($userIds as $userId) {
$user = $userManager->get($userId); $user = $this->userManager->get($userId);
if ($user === null) { if ($user === null) {
throw new InvalidArgumentException(sprintf("User '%s' not found.", $userId)); throw new InvalidArgumentException(sprintf("User '%s' not found.", $userId));
} }
@ -268,8 +259,6 @@ trait TRoomCommand {
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
protected function removeRoomParticipants(Room $room, array $userIds): void { protected function removeRoomParticipants(Room $room, array $userIds): void {
$userManager = \OC::$server->getUserManager();
$users = []; $users = [];
foreach ($userIds as $userId) { foreach ($userIds as $userId) {
try { try {
@ -278,7 +267,7 @@ trait TRoomCommand {
throw new InvalidArgumentException(sprintf("User '%s' is no participant.", $userId)); throw new InvalidArgumentException(sprintf("User '%s' is no participant.", $userId));
} }
$users[] = $userManager->get($userId); $users[] = $this->userManager->get($userId);
} }
foreach ($users as $user) { foreach ($users as $user) {
@ -335,4 +324,53 @@ trait TRoomCommand {
$room->setParticipantType($participant, Participant::USER); $room->setParticipantType($participant, Participant::USER);
} }
} }
protected function completeTokenValues(CompletionContext $context): array {
return array_map(function (Room $room) {
return $room->getToken();
}, $this->manager->searchRoomsByToken($context->getCurrentWord()));
}
protected function completeUserValues(CompletionContext $context): array {
return array_map(function (IUser $user) {
return $user->getUID();
}, $this->userManager->search($context->getCurrentWord()));
}
protected function completeGroupValues(CompletionContext $context): array {
return array_map(function (IGroup $group) {
return $group->getGID();
}, $this->groupManager->search($context->getCurrentWord()));
}
protected function completeParticipantValues(CompletionContext $context): array {
$definition = new InputDefinition();
if ($this->getApplication() !== null) {
$definition->addArguments($this->getApplication()->getDefinition()->getArguments());
$definition->addOptions($this->getApplication()->getDefinition()->getOptions());
}
$definition->addArguments($this->getDefinition()->getArguments());
$definition->addOptions($this->getDefinition()->getOptions());
$input = new ArgvInput($context->getWords(), $definition);
if ($input->hasArgument('token')) {
$token = $input->getArgument('token');
} elseif ($input->hasOption('token')) {
$token = $input->getOption('token');
} else {
return [];
}
try {
$room = $this->manager->getRoomByToken($token);
} catch (RoomNotFoundException $e) {
return [];
}
return array_map(function (Participant $participant) {
return $participant->getUser();
}, $room->searchParticipants($context->getCurrentWord()));
}
} }

Просмотреть файл

@ -25,12 +25,11 @@ declare(strict_types=1);
namespace OCA\Talk\Command\Room; namespace OCA\Talk\Command\Room;
use Exception; use InvalidArgumentException;
use OC\Core\Command\Base; use OC\Core\Command\Base;
use OCA\Talk\Exceptions\RoomNotFoundException; use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Room; use OCA\Talk\Room;
use OCP\IUserManager; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@ -39,19 +38,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class Update extends Base { class Update extends Base {
use TRoomCommand; use TRoomCommand;
/** @var IUserManager */
public $userManager;
/** @var Manager */
public $manager;
public function __construct(IUserManager $userManager, Manager $manager) {
parent::__construct();
$this->userManager = $userManager;
$this->manager = $manager;
}
protected function configure(): void { protected function configure(): void {
$this $this
->setName('talk:room:update') ->setName('talk:room:update')
@ -142,7 +128,7 @@ class Update extends Base {
$this->unsetRoomOwner($room); $this->unsetRoomOwner($room);
} }
} }
} catch (Exception $e) { } catch (InvalidArgumentException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage())); $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return 1; return 1;
} }
@ -150,4 +136,26 @@ class Update extends Base {
$output->writeln('<info>Room successfully updated.</info>'); $output->writeln('<info>Room successfully updated.</info>');
return 0; return 0;
} }
public function completeOptionValues($optionName, CompletionContext $context) {
switch ($optionName) {
case 'public':
case 'readonly':
return ['1', '0'];
case 'owner':
return $this->completeParticipantValues($context);
}
return parent::completeOptionValues($optionName, $context);
}
public function completeArgumentValues($argumentName, CompletionContext $context) {
switch ($argumentName) {
case 'token':
return $this->completeTokenValues($context);
}
return parent::completeArgumentValues($argumentName, $context);
}
} }

Просмотреть файл

@ -224,6 +224,43 @@ class Manager {
$result->closeCursor(); $result->closeCursor();
} }
/**
* @param string $searchToken
* @param int $limit
* @param int $offset
* @return Room[]
*/
public function searchRoomsByToken(string $searchToken = '', int $limit = null, int $offset = null): array {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from('talk_rooms')
->setMaxResults(1);
if ($searchToken !== '') {
$query->where($query->expr()->iLike('token', $query->createNamedParameter(
'%' . $this->db->escapeLikeParameter($searchToken) . '%'
)));
}
$query->setMaxResults($limit)
->setFirstResult($offset)
->orderBy('token', 'ASC');
$result = $query->execute();
$rooms = [];
while ($row = $result->fetch()) {
if ($row['token'] === null) {
// FIXME Temporary solution for the Talk6 release
continue;
}
$rooms[] = $this->createRoomObject($row);
}
$result->closeCursor();
return $rooms;
}
/** /**
* @param string $participant * @param string $participant
* @param bool $includeLastMessage * @param bool $includeLastMessage

Просмотреть файл

@ -1015,6 +1015,38 @@ class Room {
return $participants; return $participants;
} }
/**
* @param string $search
* @param int $limit
* @param int $offset
* @return Participant[]
*/
public function searchParticipants(string $search = '', int $limit = null, int $offset = null): array {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from('talk_participants')
->where($query->expr()->eq('room_id', $query->createNamedParameter($this->getId())));
if ($search !== '') {
$query->where($query->expr()->iLike('user_id', $query->createNamedParameter(
'%' . $this->db->escapeLikeParameter($search) . '%'
)));
}
$query->setMaxResults($limit)
->setFirstResult($offset)
->orderBy('user_id', 'ASC');
$result = $query->execute();
$participants = [];
while ($row = $result->fetch()) {
$participants[] = $this->manager->createParticipantObject($this, $row);
}
$result->closeCursor();
return $participants;
}
/** /**
* @return Participant[] * @return Participant[]
*/ */

Просмотреть файл

@ -0,0 +1,327 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCA\Talk\Command\Room\Add;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
class AddTest extends TestCase {
use TRoomCommandTest;
/** @var Add */
private $command;
/** @var Manager|MockObject */
private $manager;
/** @var RoomMockContainer */
private $roomMockContainer;
public function setUp(): void {
parent::setUp();
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->manager = $this->createMock(Manager::class);
$this->command = new Add($this->manager, $this->userManager, $this->groupManager);
$this->roomMockContainer = new RoomMockContainer($this);
$this->createTestUserMocks();
$this->createTestGroupMocks();
}
public function testMissingArguments(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "token").');
$tester = new CommandTester($this->command);
$tester->execute([]);
}
/**
* @dataProvider validProvider
*/
public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals("Users successfully added to room.\n", $tester->getDisplay());
$this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData());
}
public function validProvider(): array {
return [
[
[
'token' => '__test-room',
],
RoomMockContainer::prepareRoomData([]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--user' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--user' => ['user1', 'user2'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--user' => ['user2'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'--user' => ['user3'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user2', 'participantType' => Participant::USER],
['userId' => 'user3', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'--group' => ['group1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--group' => ['group1', 'group2'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
['userId' => 'user3', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--group' => ['group1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'--group' => ['group1', 'group2'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user4', 'participantType' => Participant::MODERATOR],
['userId' => 'user2', 'participantType' => Participant::USER],
['userId' => 'user3', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user4', 'participantType' => Participant::MODERATOR],
],
]),
],
[
[
'token' => '__test-room',
'--group' => ['group1'],
'--user' => ['user4'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user4', 'participantType' => Participant::USER],
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--group' => ['group1'],
'--user' => ['user4'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::MODERATOR],
['userId' => 'user3', 'participantType' => Participant::USER],
['userId' => 'user4', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::MODERATOR],
['userId' => 'user3', 'participantType' => Participant::USER],
],
]),
],
];
}
/**
* @dataProvider invalidProvider
*/
public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals($expectedOutput, $tester->getDisplay());
}
public function invalidProvider(): array {
return [
[
[
'token' => '__test-invalid',
],
"Room not found.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
],
"Room is no group call.\n",
RoomMockContainer::prepareRoomData([
'type' => Room::ONE_TO_ONE_CALL,
]),
],
[
[
'token' => '__test-room',
'--user' => ['user1','invalid']
],
"User 'invalid' not found.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--group' => ['group1','invalid']
],
"Group 'invalid' not found.\n",
RoomMockContainer::prepareRoomData([]),
],
];
}
}

Просмотреть файл

@ -0,0 +1,372 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCA\Talk\Command\Room\Create;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
class CreateTest extends TestCase {
use TRoomCommandTest;
/** @var Create */
private $command;
/** @var Manager|MockObject */
private $manager;
/** @var RoomMockContainer */
private $roomMockContainer;
public function setUp(): void {
parent::setUp();
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->manager = $this->createMock(Manager::class);
$this->command = new Create($this->manager, $this->userManager, $this->groupManager);
$this->roomMockContainer = new RoomMockContainer($this);
$this->createTestUserMocks();
$this->createTestGroupMocks();
}
public function testMissingArguments(): void {
$this->manager->expects($this->never())
->method('createGroupRoom');
$this->manager->expects($this->never())
->method('createPublicRoom');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "name").');
$tester = new CommandTester($this->command);
$tester->execute([]);
}
/**
* @dataProvider validProvider
*/
public function testValid(array $input, array $expectedRoomData): void {
$this->manager
->method('createGroupRoom')
->willReturnCallback(function (string $name = ''): Room {
return $this->roomMockContainer->create(['name' => $name, 'type' => Room::GROUP_CALL]);
});
$this->manager
->method('createPublicRoom')
->willReturnCallback(function (string $name = ''): Room {
return $this->roomMockContainer->create(['name' => $name, 'type' => Room::PUBLIC_CALL]);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals("Room successfully created.\n", $tester->getDisplay());
$this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData());
}
public function validProvider(): array {
return [
[
[
'name' => 'PHPUnit Test Room',
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--public' => true,
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'type' => Room::PUBLIC_CALL,
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--readonly' => true,
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'readOnly' => Room::READ_ONLY,
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--public' => true,
'--password' => 'my-secret-password',
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'type' => Room::PUBLIC_CALL,
'password' => 'my-secret-password',
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1', 'user2'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1', 'user2'],
'--moderator' => ['user2'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::MODERATOR],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1', 'user2', 'user3'],
'--moderator' => ['user2', 'user3'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::MODERATOR],
['userId' => 'user3', 'participantType' => Participant::MODERATOR],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1', 'user2'],
'--owner' => 'user2',
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::OWNER],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--group' => ['group1'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--group' => ['group1', 'group2'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
['userId' => 'user3', 'participantType' => Participant::USER],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--group' => ['group1'],
'--user' => ['user4'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user4', 'participantType' => Participant::USER],
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--group' => ['group1'],
'--moderator' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::MODERATOR],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'name' => 'PHPUnit Test Room',
'--group' => ['group1'],
'--owner' => 'user1',
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room',
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
];
}
/**
* @dataProvider invalidProvider
*/
public function testInvalid(array $input, string $expectedOutput): void {
$this->manager
->method('createGroupRoom')
->willReturnCallback(function (string $name = ''): Room {
return $this->roomMockContainer->create(['name' => $name, 'type' => Room::GROUP_CALL]);
});
$this->manager
->method('createPublicRoom')
->willReturnCallback(function (string $name = ''): Room {
return $this->roomMockContainer->create(['name' => $name, 'type' => Room::PUBLIC_CALL]);
});
$this->roomMockContainer->registerCallback(function (object $room) {
/** @var Room|MockObject $room */
$room->expects($this->once())
->method('deleteRoom');
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals($expectedOutput, $tester->getDisplay());
}
public function invalidProvider(): array {
return [
[
[
'name' => '',
],
"Invalid room name.\n",
],
[
[
'name' => ' ',
],
"Invalid room name.\n",
],
[
[
'name' => str_repeat('x', 256),
],
"Invalid room name.\n",
],
[
[
'name' => 'PHPUnit Test Room',
'--password' => 'my-secret-password',
],
"Unable to add password protection to private room.\n",
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1','invalid'],
],
"User 'invalid' not found.\n",
],
[
[
'name' => 'PHPUnit Test Room',
'--group' => ['group1','invalid'],
],
"Group 'invalid' not found.\n",
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1'],
'--moderator' => ['user2'],
],
"User 'user2' is no participant.\n",
],
[
[
'name' => 'PHPUnit Test Room',
'--user' => ['user1'],
'--owner' => 'user2',
],
"User 'user2' is no participant.\n",
],
];
}
}

Просмотреть файл

@ -0,0 +1,149 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCA\Talk\Command\Room\Delete;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Room;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
class DeleteTest extends TestCase {
use TRoomCommandTest;
/** @var Delete */
private $command;
/** @var Manager|MockObject */
private $manager;
/** @var RoomMockContainer */
private $roomMockContainer;
public function setUp(): void {
parent::setUp();
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->manager = $this->createMock(Manager::class);
$this->command = new Delete($this->manager, $this->userManager, $this->groupManager);
$this->roomMockContainer = new RoomMockContainer($this);
}
public function testMissingArguments(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "token").');
$tester = new CommandTester($this->command);
$tester->execute([]);
}
/**
* @dataProvider validProvider
*/
public function testValid(array $input, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$this->roomMockContainer->registerCallback(function (object $room) {
/** @var Room|MockObject $room */
$room->expects($this->once())
->method('deleteRoom');
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals("Room successfully deleted.\n", $tester->getDisplay());
}
public function validProvider(): array {
return [
[
[
'token' => '__test-room',
],
RoomMockContainer::prepareRoomData([]),
],
];
}
/**
* @dataProvider invalidProvider
*/
public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals($expectedOutput, $tester->getDisplay());
}
public function invalidProvider(): array {
return [
[
[
'token' => '__test-invalid',
],
"Room not found.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
],
"Room is no group call.\n",
RoomMockContainer::prepareRoomData([
'type' => Room::ONE_TO_ONE_CALL,
]),
],
];
}
}

Просмотреть файл

@ -0,0 +1,247 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCA\Talk\Command\Room\Demote;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
class DemoteTest extends TestCase {
use TRoomCommandTest;
/** @var Demote */
private $command;
/** @var Manager|MockObject */
private $manager;
/** @var RoomMockContainer */
private $roomMockContainer;
public function setUp(): void {
parent::setUp();
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->manager = $this->createMock(Manager::class);
$this->command = new Demote($this->manager, $this->userManager, $this->groupManager);
$this->roomMockContainer = new RoomMockContainer($this);
$this->createTestUserMocks();
$this->createTestGroupMocks();
}
public function testMissingArguments(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "token, participant").');
$tester = new CommandTester($this->command);
$tester->execute([]);
}
public function testMissingArgumentParticipant(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "participant").');
$tester = new CommandTester($this->command);
$tester->execute([
'token' => '__test-room',
]);
}
/**
* @dataProvider validProvider
*/
public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals("Participants successfully demoted to regular users.\n", $tester->getDisplay());
$this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData());
}
public function validProvider(): array {
return [
[
[
'token' => '__test-room',
'participant' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::MODERATOR],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1', 'user2'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::MODERATOR],
['userId' => 'user2', 'participantType' => Participant::MODERATOR],
],
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
],
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
],
]),
],
];
}
/**
* @dataProvider invalidProvider
*/
public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals($expectedOutput, $tester->getDisplay());
}
public function invalidProvider(): array {
return [
[
[
'token' => '__test-invalid',
'participant' => [''],
],
"Room not found.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'participant' => [''],
],
"Room is no group call.\n",
RoomMockContainer::prepareRoomData([
'type' => Room::ONE_TO_ONE_CALL,
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1','invalid']
],
"User 'user1' is no participant.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'participant' => ['user1','invalid']
],
"User 'invalid' is no participant.\n",
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
];
}
}

Просмотреть файл

@ -0,0 +1,231 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCA\Talk\Command\Room\Promote;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
class PromoteTest extends TestCase {
use TRoomCommandTest;
/** @var Promote */
private $command;
/** @var Manager|MockObject */
private $manager;
/** @var RoomMockContainer */
private $roomMockContainer;
public function setUp(): void {
parent::setUp();
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->manager = $this->createMock(Manager::class);
$this->command = new Promote($this->manager, $this->userManager, $this->groupManager);
$this->roomMockContainer = new RoomMockContainer($this);
$this->createTestUserMocks();
$this->createTestGroupMocks();
}
public function testMissingArguments(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "token, participant").');
$tester = new CommandTester($this->command);
$tester->execute([]);
}
public function testMissingArgumentParticipant(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "participant").');
$tester = new CommandTester($this->command);
$tester->execute([
'token' => '__test-room',
]);
}
/**
* @dataProvider validProvider
*/
public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals("Participants successfully promoted to moderators.\n", $tester->getDisplay());
$this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData());
}
public function validProvider(): array {
return [
[
[
'token' => '__test-room',
'participant' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::MODERATOR],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1', 'user2'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::MODERATOR],
['userId' => 'user2', 'participantType' => Participant::MODERATOR],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
],
]),
],
];
}
/**
* @dataProvider invalidProvider
*/
public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals($expectedOutput, $tester->getDisplay());
}
public function invalidProvider(): array {
return [
[
[
'token' => '__test-invalid',
'participant' => [''],
],
"Room not found.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'participant' => [''],
],
"Room is no group call.\n",
RoomMockContainer::prepareRoomData([
'type' => Room::ONE_TO_ONE_CALL,
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1','invalid']
],
"User 'user1' is no participant.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'participant' => ['user1','invalid']
],
"User 'invalid' is no participant.\n",
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
];
}
}

Просмотреть файл

@ -0,0 +1,214 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCA\Talk\Command\Room\Remove;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
class RemoveTest extends TestCase {
use TRoomCommandTest;
/** @var Remove */
private $command;
/** @var Manager|MockObject */
private $manager;
/** @var RoomMockContainer */
private $roomMockContainer;
public function setUp(): void {
parent::setUp();
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->manager = $this->createMock(Manager::class);
$this->command = new Remove($this->manager, $this->userManager, $this->groupManager);
$this->roomMockContainer = new RoomMockContainer($this);
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->createTestUserMocks();
$this->createTestGroupMocks();
}
public function testMissingArguments(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "token, participant").');
$tester = new CommandTester($this->command);
$tester->execute([]);
}
public function testMissingArgumentUser(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "participant").');
$tester = new CommandTester($this->command);
$tester->execute([
'token' => '__test-room',
]);
}
/**
* @dataProvider validProvider
*/
public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals("Users successfully removed from room.\n", $tester->getDisplay());
$this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData());
}
public function validProvider(): array {
return [
[
[
'token' => '__test-room',
'participant' => ['user1'],
],
RoomMockContainer::prepareRoomData([]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1', 'user2'],
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user3', 'participantType' => Participant::USER],
['userId' => 'user4', 'participantType' => Participant::MODERATOR],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
['userId' => 'user3', 'participantType' => Participant::USER],
['userId' => 'user4', 'participantType' => Participant::MODERATOR],
],
]),
],
];
}
/**
* @dataProvider invalidProvider
*/
public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals($expectedOutput, $tester->getDisplay());
}
public function invalidProvider(): array {
return [
[
[
'token' => '__test-invalid',
'participant' => [''],
],
"Room not found.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'participant' => [''],
],
"Room is no group call.\n",
RoomMockContainer::prepareRoomData([
'type' => Room::ONE_TO_ONE_CALL,
]),
],
[
[
'token' => '__test-room',
'participant' => ['user1','invalid']
],
"User 'user1' is no participant.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'participant' => ['user1','invalid']
],
"User 'invalid' is no participant.\n",
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
];
}
}

Просмотреть файл

@ -0,0 +1,221 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use InvalidArgumentException;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCP\IUser;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class RoomMockContainer {
/** @var TestCase */
private $testCase;
/** @var callable[] */
private $callbacks = [];
/** @var Room|null */
private $room;
/** @var array|null */
private $roomData;
/** @var Participant[] */
private $participants = [];
/** @var array[] */
private $participantData = [];
public function __construct(TestCase $testCase) {
$this->testCase = $testCase;
}
public function create(array $data = []): Room {
if ($this->room !== null) {
throw new InvalidArgumentException(__METHOD__ . ' must not be called multiple times.');
}
/** @var Room|MockObject $room */
$room = $this->createMock(Room::class);
$this->room = $room;
$this->roomData = self::prepareRoomData($data);
// simple getter
foreach (['token', 'name', 'type', 'readOnly'] as $key) {
$room->method('get' . ucfirst($key))
->willReturnCallback(function () use ($key) {
return $this->roomData[$key];
});
}
// simple setter
foreach (['name', 'type', 'readOnly', 'password'] as $key) {
$room->method('set' . ucfirst($key))
->willReturnCallback(function ($value) use ($key): bool {
$this->roomData[$key] = $value;
return true;
});
}
// password
$room->method('hasPassword')
->willReturnCallback(function (): bool {
return $this->roomData['password'] !== '';
});
$room->method('verifyPassword')
->willReturnCallback(function (string $password): array {
return [
'result' => in_array($this->roomData['password'], ['', $password], true),
'url' => '',
];
});
// participants
$room->method('getParticipants')
->willReturnCallback(function (): array {
return $this->participants;
});
$room->method('getParticipant')
->willReturnCallback(function (?string $userId): Participant {
if (in_array($userId, [null, ''], true)) {
throw new ParticipantNotFoundException('Not a user');
}
if (!isset($this->participants[$userId])) {
throw new ParticipantNotFoundException('User is not a participant');
}
return $this->participants[$userId];
});
$room->method('addUsers')
->willReturnCallback(function (array ...$participants): void {
foreach ($participants as $participant) {
$userId = $participant['userId'];
$participantType = $participant['participantType'] ?? Participant::USER;
$this->createParticipant($userId, ['participantType' => $participantType]);
}
});
$room->method('removeUser')
->willReturnCallback(function (IUser $user): void {
$this->removeParticipant($user->getUID());
});
$room->method('setParticipantType')
->willReturnCallback(function (Participant $participant, int $participantType): void {
$userId = $participant->getUser();
$this->updateParticipant($userId, ['participantType' => $participantType]);
});
// add participants
foreach ($this->roomData['participants'] as $participant) {
$userId = $participant['userId'];
$participantType = $participant['participantType'] ?? Participant::USER;
$this->createParticipant($userId, ['participantType' => $participantType]);
}
unset($this->roomData['participants']);
// execute callbacks
foreach ($this->callbacks as $callback) {
$callback($room);
}
return $room;
}
protected function createParticipant(string $userId, array $data): Participant {
/** @var Participant|MockObject $participant */
$participant = $this->createMock(Participant::class);
$this->participants[$userId] = $participant;
$this->participantData[$userId] = ['userId' => $userId] + $data;
$participant->method('getUser')
->willReturnCallback(function () use ($userId): string {
return $this->participantData[$userId]['userId'];
});
$participant->method('getParticipantType')
->willReturnCallback(function () use ($userId): int {
return $this->participantData[$userId]['participantType'];
});
return $participant;
}
protected function updateParticipant(string $userId, array $data): void {
$this->participantData[$userId] = array_merge($this->participantData[$userId], $data);
}
protected function removeParticipant(string $userId): void {
unset($this->participants[$userId], $this->participantData[$userId]);
}
public function registerCallback(callable $callback): void {
$this->callbacks[] = $callback;
}
protected function createMock(string $originalClassName): MockObject {
return $this->testCase->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->disableAutoReturnValueGeneration()
->getMock();
}
public function getRoom(): ?Room {
return $this->room;
}
public function getRoomData(): ?array {
$participants = array_values($this->participantData);
return $this->roomData + ['participants' => $participants];
}
public static function prepareRoomData(array $data): array {
$data += [
'token' => '__test-room',
'name' => 'PHPUnit Test Room',
'type' => Room::GROUP_CALL,
'readOnly' => Room::READ_WRITE,
'password' => '',
'participants' => [],
];
return $data;
}
}

Просмотреть файл

@ -0,0 +1,125 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
use PHPUnit\Framework\MockObject\MockObject;
trait TRoomCommandTest {
/** @var IUserManager|MockObject */
protected $userManager;
/** @var IGroupManager|MockObject */
protected $groupManager;
/** @var IUser[] */
private $userMocks;
/** @var IGroup[] */
private $groupMocks;
protected function registerUserManagerMock(): void {
$this->userManager = $this->createMock(IUserManager::class);
$this->userManager->method('get')
->willReturnCallback([$this, 'getUserMock']);
$this->overwriteService(IUserManager::class, $this->userManager);
}
protected function createTestUserMocks(): void {
$this->createUserMock('user1');
$this->createUserMock('user2');
$this->createUserMock('user3');
$this->createUserMock('user4');
$this->createUserMock('other');
}
public function getUserMock(string $uid): ?IUser {
return $this->userMocks[$uid] ?? null;
}
protected function createUserMock(string $uid): IUser {
/** @var IUser|MockObject $user */
$user = $this->createMock(IUser::class);
$this->userMocks[$uid] = $user;
$user->method('getUID')
->willReturn($uid);
return $user;
}
protected function registerGroupManagerMock(): void {
$this->groupManager = $this->createMock(IGroupManager::class);
$this->groupManager->method('get')
->willReturnCallback([$this, 'getGroupMock']);
$this->overwriteService(IGroupManager::class, $this->groupManager);
}
protected function createTestGroupMocks(): void {
$this->createGroupMock('group1', ['user1', 'user2']);
$this->createGroupMock('group2', ['user2', 'user3']);
$this->createGroupMock('other', ['other']);
}
public function getGroupMock(string $gid): ?IGroup {
return $this->groupMocks[$gid] ?? null;
}
protected function createGroupMock(string $gid, array $userIds): IGroup {
/** @var IGroup|MockObject $group */
$group = $this->createMock(IGroup::class);
$this->groupMocks[$gid] = $group;
$group->method('getGID')
->willReturn($gid);
$group->method('getUsers')
->willReturnCallback(function () use ($userIds) {
return array_map([$this, 'getUserMock'], $userIds);
});
return $group;
}
protected function createMock($originalClassName): MockObject {
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->disableAutoReturnValueGeneration()
->getMock();
}
}

Просмотреть файл

@ -0,0 +1,352 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Tests\php\Command\Room;
use OCA\Talk\Command\Room\Update;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
class UpdateTest extends TestCase {
use TRoomCommandTest;
/** @var Update */
private $command;
/** @var Manager|MockObject */
private $manager;
/** @var RoomMockContainer */
private $roomMockContainer;
public function setUp(): void {
parent::setUp();
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->manager = $this->createMock(Manager::class);
$this->command = new Update($this->manager, $this->userManager, $this->groupManager);
$this->roomMockContainer = new RoomMockContainer($this);
$this->registerUserManagerMock();
$this->registerGroupManagerMock();
$this->createTestUserMocks();
$this->createTestGroupMocks();
}
public function testMissingArguments(): void {
$this->manager->expects($this->never())
->method('getRoomByToken');
$this->expectException(ConsoleRuntimeException::class);
$this->expectExceptionMessage('Not enough arguments (missing: "token").');
$tester = new CommandTester($this->command);
$tester->execute([]);
}
/**
* @dataProvider validProvider
*/
public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals("Room successfully updated.\n", $tester->getDisplay());
$this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData());
}
public function validProvider(): array {
return [
[
[
'token' => '__test-room',
],
RoomMockContainer::prepareRoomData([]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--name' => 'PHPUnit Test Room 2'
],
RoomMockContainer::prepareRoomData([
'name' => 'PHPUnit Test Room 2',
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--public' => '1'
],
RoomMockContainer::prepareRoomData([
'type' => Room::PUBLIC_CALL,
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--public' => '0'
],
RoomMockContainer::prepareRoomData([]),
RoomMockContainer::prepareRoomData([
'type' => Room::PUBLIC_CALL,
]),
],
[
[
'token' => '__test-room',
'--readonly' => '1'
],
RoomMockContainer::prepareRoomData([
'readOnly' => Room::READ_ONLY,
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--readonly' => '0'
],
RoomMockContainer::prepareRoomData([]),
RoomMockContainer::prepareRoomData([
'readOnly' => Room::READ_ONLY,
]),
],
[
[
'token' => '__test-room',
'--readonly' => '1'
],
RoomMockContainer::prepareRoomData([
'readOnly' => Room::READ_ONLY,
]),
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--password' => 'my-secret-password'
],
RoomMockContainer::prepareRoomData([
'type' => Room::PUBLIC_CALL,
'password' => 'my-secret-password',
]),
RoomMockContainer::prepareRoomData([
'type' => Room::PUBLIC_CALL,
]),
],
[
[
'token' => '__test-room',
'--password' => ''
],
RoomMockContainer::prepareRoomData([
'type' => Room::PUBLIC_CALL,
]),
RoomMockContainer::prepareRoomData([
'type' => Room::PUBLIC_CALL,
'password' => 'my-secret-password',
]),
],
[
[
'token' => '__test-room',
'--owner' => 'user1'
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'--owner' => 'user2'
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::OWNER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
[
[
'token' => '__test-room',
'--owner' => ''
],
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::USER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
RoomMockContainer::prepareRoomData([
'participants' => [
['userId' => 'user1', 'participantType' => Participant::OWNER],
['userId' => 'user2', 'participantType' => Participant::USER],
],
]),
],
];
}
/**
* @dataProvider invalidProvider
*/
public function testInvalid(array $input, string $expectedOutput, array $initialRoomData = null): void {
if ($initialRoomData !== null) {
$this->manager->expects($this->once())
->method('getRoomByToken')
->willReturnCallback(function (string $token) use ($initialRoomData): Room {
if ($token !== $initialRoomData['token']) {
throw new RoomNotFoundException();
}
return $this->roomMockContainer->create($initialRoomData);
});
} else {
$this->manager->expects($this->never())
->method('getRoomByToken');
}
$tester = new CommandTester($this->command);
$tester->execute($input);
$this->assertEquals($expectedOutput, $tester->getDisplay());
}
public function invalidProvider(): array {
return [
[
[
'token' => '__test-room',
'--public' => '',
],
"Invalid value for option \"--public\" given.\n",
],
[
[
'token' => '__test-room',
'--readonly' => '',
],
"Invalid value for option \"--readonly\" given.\n",
],
[
[
'token' => '__test-invalid',
],
"Room not found.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
],
"Room is no group call.\n",
RoomMockContainer::prepareRoomData([
'type' => Room::ONE_TO_ONE_CALL,
]),
],
[
[
'token' => '__test-room',
'--name' => '',
],
"Invalid room name.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--name' => ' ',
],
"Invalid room name.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--name' => str_repeat('x', 256),
],
"Invalid room name.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--password' => 'my-secret-password',
],
"Unable to add password protection to private room.\n",
RoomMockContainer::prepareRoomData([]),
],
[
[
'token' => '__test-room',
'--owner' => 'invalid',
],
"User 'invalid' is no participant.\n",
RoomMockContainer::prepareRoomData([]),
],
];
}
}