Merge pull request #1760 from bburnichon/improvement/some-scrutinizers-fixups

Improvement/some scrutinizers fixups
This commit is contained in:
Benoît Burnichon
2016-03-15 13:52:46 +01:00
15 changed files with 277 additions and 264 deletions

View File

@@ -14,7 +14,6 @@ use Alchemy\Phrasea\Model\Entities\User;
trait AclAware
{
/** @var ACLProvider */
private $aclProvider;
/**
@@ -45,17 +44,20 @@ trait AclAware
return $this->aclProvider;
}
if (null === $this->aclProvider && $this instanceof \Pimple && $this->offsetExists('acl')) {
$this->aclProvider = function () {
$locator = $this->aclProvider;
if (null === $locator && $this instanceof \Pimple && $this->offsetExists('acl')) {
$locator = function () {
return $this['acl'];
};
}
if (null === $this->aclProvider) {
if (null === $locator) {
throw new \LogicException(ACLProvider::class . ' instance or locator was not set');
}
$instance = call_user_func($this->aclProvider);
$instance = $locator();
if (!$instance instanceof ACLProvider) {
throw new \LogicException(sprintf(
'Expects locator to return instance of "%s", got "%s"',

View File

@@ -13,24 +13,35 @@ namespace Alchemy\Phrasea\Authentication\Phrasea;
use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Authentication\Exception\RequireCaptchaException;
use Alchemy\Phrasea\Model\Repositories\AuthFailureRepository;
use Doctrine\ORM\EntityManager;
use Alchemy\Phrasea\Model\Entities\AuthFailure;
use Doctrine\ORM\EntityRepository;
use Neutron\ReCaptcha\ReCaptcha;
use Symfony\Component\HttpFoundation\Request;
class FailureManager
{
/** @var ReCaptcha */
/**
* @var ReCaptcha
*/
private $captcha;
/** @var EntityManager */
/**
* @var EntityManager
*/
private $em;
/** @var EntityRepository */
/**
* @var AuthFailureRepository
*/
private $repository;
/** @var integer */
/**
* @var int
*/
private $trials;
public function __construct(EntityRepository $repo, EntityManager $em, ReCaptcha $captcha, $trials)
public function __construct(AuthFailureRepository $repo, EntityManager $em, ReCaptcha $captcha, $trials)
{
$this->captcha = $captcha;
$this->em = $em;
@@ -40,9 +51,12 @@ class FailureManager
throw new InvalidArgumentException('Trials number must be a positive integer');
}
$this->trials = $trials;
$this->trials = (int)$trials;
}
/**
* @return int
*/
public function getTrials()
{
return $this->trials;
@@ -86,36 +100,38 @@ class FailureManager
$failures = $this->repository->findLockedFailuresMatching($username, $request->getClientIp());
if (0 === count($failures)) {
return;
return $this;
}
if ($this->trials < count($failures) && $this->captcha->isSetup()) {
$response = $this->captcha->bind($request);
if ($response->isValid()) {
foreach ($failures as $failure) {
$failure->setLocked(false);
}
$this->em->flush();
} else {
throw new RequireCaptchaException('Too much failure, require captcha');
if (!$response->isValid()) {
throw new RequireCaptchaException('Too many failures, require captcha');
}
foreach ($failures as $failure) {
$failure->setLocked(false);
}
$this->em->flush($failures);
}
return $this;
}
/**
* Removes failures older than 2 monthes
*/
private function removeOldFailures()
{
$failures = $this->repository->findOldFailures('-2 months');
if (0 < count($failures)) {
foreach ($failures as $failure) {
$this->em->remove($failure);
}
if (empty($failures)) {
return;
}
foreach ($failures as $failure) {
$this->em->remove($failure);
}
$this->em->flush($failures);
}
}

View File

@@ -15,13 +15,13 @@ use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
use Alchemy\Phrasea\Authentication\Provider\Token\Token;
use Alchemy\Phrasea\Authentication\Provider\Token\Identity;
use Alchemy\Phrasea\Model\Entities\User;
use Doctrine\Common\Persistence\ObjectRepository;
use Alchemy\Phrasea\Model\Repositories\UserRepository;
class SuggestionFinder
{
private $repository;
public function __construct(ObjectRepository $repository)
public function __construct(UserRepository $repository)
{
$this->repository = $repository;
}

View File

@@ -33,19 +33,16 @@ class Factory
*/
public static function getFileAttribute(Application $app, $name, $serialized)
{
switch ($name) {
switch ($name)
{
case AttributeInterface::NAME_METADATA:
return Metadata::loadFromString($app, $serialized);
break;
case AttributeInterface::NAME_STORY:
return Story::loadFromString($app, $serialized);
break;
case AttributeInterface::NAME_METAFIELD:
return MetaField::loadFromString($app, $serialized);
break;
case AttributeInterface::NAME_STATUS:
return Status::loadFromString($app, $serialized);
break;
}
throw new \InvalidArgumentException(sprintf('Unknown attribute %s', $name));

View File

@@ -12,7 +12,6 @@
namespace Alchemy\Phrasea\Border\Attribute;
use Alchemy\Phrasea\Application;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Phraseanet Border MetaField Attribute
@@ -23,13 +22,11 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class MetaField implements AttributeInterface
{
/**
*
* @var \databox_field
*/
protected $databox_field;
/**
*
* @var array
*/
protected $value;
@@ -46,14 +43,6 @@ class MetaField implements AttributeInterface
$this->value = $value;
}
/**
* Destructor
*/
public function __destruct()
{
$this->metadata = $this->databox_field = null;
}
/**
* {@inheritdoc}
*/
@@ -101,15 +90,18 @@ class MetaField implements AttributeInterface
*/
public static function loadFromString(Application $app, $string)
{
if (!$datas = @unserialize($string)) {
$data = @unserialize($string);
if (!is_array($data) || !isset($data['sbas_id']) || !isset($data['id']) || !isset($data['value'])) {
throw new \InvalidArgumentException('Unable to load metadata from string');
}
try {
return new static($app->findDataboxById($datas['sbas_id'])
->get_meta_structure()->get_element($datas['id']), $datas['value']);
} catch (NotFoundHttpException $e) {
throw new \InvalidArgumentException('Field does not exist anymore');
$field = $app->findDataboxById($data['sbas_id'])->get_meta_structure()->get_element($data['id']);
return new static($field, $data['value']);
} catch (\Exception $exception) {
throw new \InvalidArgumentException('Field does not exist anymore', 0, $exception);
}
}
}

View File

@@ -129,8 +129,6 @@ class Manager
$callable($element, $visa, $code);
}
$visa = null;
return $code;
}

View File

@@ -45,8 +45,6 @@ class CLI extends Application
{
parent::__construct($environment);
$app = $this;
$this['session.test'] = true;
$this['console'] = $this->share(function () use ($name, $version) {

View File

@@ -92,7 +92,7 @@ EOT;
}
/**
* @param $collectionId
* @param int $collectionId
*/
public function setCollectionId($collectionId)
{
@@ -126,7 +126,7 @@ EOT;
}
/**
* @return \string[]
* @return string[]
*/
public function getLabels()
{
@@ -134,7 +134,7 @@ EOT;
}
/**
* @param \string[] $labels
* @param string[] $labels
*/
public function setLabels($labels)
{
@@ -142,7 +142,7 @@ EOT;
}
/**
* @param $lang
* @param string $lang
* @param bool $substitute
* @return string
*/
@@ -154,14 +154,14 @@ EOT;
if ($substitute) {
return isset($this->labels[$lang]) ? $this->labels[$lang] : $this->name;
} else {
return $this->labels[$lang];
}
return $this->labels[$lang];
}
/**
* @param $lang
* @param $label
* @param string $lang
* @param string $label
*/
public function setLabel($lang, $label)
{
@@ -173,7 +173,7 @@ EOT;
}
/**
* @return \int[]|string|null
* @return int[]|string|null
*/
public function getLogo()
{
@@ -181,7 +181,7 @@ EOT;
}
/**
* @param \int[]|string $logo
* @param int[]|string $logo
*/
public function setLogo($logo)
{

View File

@@ -13,7 +13,7 @@ class ArrayCacheCollectionRepository implements CollectionRepository
private $collectionRepository;
/**
* @var \collection[]
* @var \collection[]|null
*/
private $collectionCache = null;

View File

@@ -18,16 +18,13 @@ use Symfony\Component\Console\Output\OutputInterface;
class BuildMissingSubdefs extends Command
{
/**
* Constructor
*/
private $generator;
public function __construct($name = null)
{
parent::__construct($name);
$this->setDescription('Builds subviews that previously failed to be generated / did not exist when records were added');
return $this;
}
/**
@@ -37,48 +34,61 @@ class BuildMissingSubdefs extends Command
{
$start = microtime(true);
$progressBar = new ProgressBar($output);
$n = 0;
/** @var SubdefGenerator $subdefGenerator */
$subdefGenerator = $this->container['subdef.generator'];
$generatedSubdefs = 0;
foreach ($this->container->getDataboxes() as $databox) {
$sql = 'SELECT record_id FROM record WHERE parent_record_id = 0';
$stmt = $databox->get_connection()->prepare($sql);
$stmt->execute();
$rs = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$stmt->closeCursor();
$progressBar->start(count($rs));
$result = $databox->get_connection()->executeQuery($sql)->fetchAll(\PDO::FETCH_ASSOC);
$progressBar->start(count($result));
foreach ($rs as $row) {
foreach ($result as $row) {
$record = $databox->get_record($row['record_id']);
$wanted_subdefs = $record->get_missing_subdefs();
$generatedSubdefs += $this->generateRecordMissingSubdefs($record);
if (count($wanted_subdefs) > 0) {
$subdefGenerator->generateSubdefs($record, $wanted_subdefs);
foreach ($wanted_subdefs as $subdef) {
$this->container['monolog']->addInfo("generate " . $subdef . " for record " . $record->get_record_id());
$n++;
}
}
unset($record);
$progressBar->advance();
}
$progressBar->finish();
}
$this->container['monolog']->addInfo($n . " subdefs done");
$this->container['monolog']->addInfo($generatedSubdefs . " subdefs done");
$stop = microtime(true);
$duration = $stop - $start;
$this->container['monolog']->addInfo(sprintf("process took %s, (%f sd/s.)", $this->getFormattedDuration($duration), round($n / $duration, 3)));
$this->container['monolog']->addInfo(sprintf("process took %s, (%f sd/s.)", $this->getFormattedDuration($duration), round($generatedSubdefs / $duration, 3)));
$progressBar->finish();
return;
}
/**
* Generate subdef generation and return number of subdef
* @param \record_adapter $record
* @return int
*/
protected function generateRecordMissingSubdefs(\record_adapter $record)
{
$wanted_subdefs = $record->get_missing_subdefs();
if (!empty($wanted_subdefs)) {
$this->getSubdefGenerator()->generateSubdefs($record, $wanted_subdefs);
foreach ($wanted_subdefs as $subdef) {
$this->container['monolog']->addInfo("generate " . $subdef . " for record " . $record->getRecordId());
}
}
return count($wanted_subdefs);
}
/**
* @return SubdefGenerator
*/
protected function getSubdefGenerator()
{
if (null === $this->generator) {
$this->generator = $this->container['subdef.generator'];
}
return $this->generator;
}
}

View File

@@ -1,9 +1,8 @@
<?php
/*
/**
* This file is part of Phraseanet
*
* (c) 2005-2014 Alchemy
* (c) 2005-2016 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,19 +13,15 @@ namespace Alchemy\Phrasea\Command;
use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Media\SubdefGenerator;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\SQLParserUtils;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\ProgressBar;
use media_subdef;
class BuildSubdefs extends Command
{
/**
* Constructor
*/
public function __construct($name = null)
{
parent::__construct($name);
@@ -39,8 +34,6 @@ class BuildSubdefs extends Command
$this->addOption('min_record', 'min', InputOption::VALUE_OPTIONAL, 'Min record id');
$this->addOption('with-substitution', 'wsubstit', InputOption::VALUE_NONE, 'Regenerate subdefs for substituted records as well');
$this->addOption('substitution-only', 'substito', InputOption::VALUE_NONE, 'Regenerate subdefs for substituted records only');
return $this;
}
/**
@@ -70,111 +63,46 @@ class BuildSubdefs extends Command
return;
}
$sqlCount = "SELECT COUNT(DISTINCT(r.record_id)) AS nb_records"
. " FROM record r LEFT JOIN subdef s ON (r.record_id = s.record_id AND s.name IN (?))"
. " WHERE r.type IN (?)";
$types = array(Connection::PARAM_STR_ARRAY, Connection::PARAM_STR_ARRAY);
$params = array($subdefsName, $recordsType);
if (null !== $min = $input->getOption('min_record')) {
$sqlCount .= " AND (r.record_id >= ?)";
$params[] = (int) $min;
$types[] = \PDO::PARAM_INT;
}
if (null !== $max = $input->getOption('max_record')) {
$sqlCount .= " AND (r.record_id <= ?)";
$params[] = (int) $max;
$types[] = \PDO::PARAM_INT;
}
$min = $input->getOption('min_record');
$max = $input->getOption('max_record');
$substitutionOnly = $input->getOption('substitution-only');
$withSubstitution = $input->getOption('with-substitution');
if (false === $withSubstitution) {
if (true === $substitutionOnly) {
$sqlCount .= " AND (ISNULL(s.substit) OR s.substit = 1)";
} else {
$sqlCount .= " AND (ISNULL(s.substit) OR s.substit = 0)";
}
} elseif ($substitutionOnly) {
if (false !== $withSubstitution && false !== $substitutionOnly) {
throw new InvalidArgumentException('Conflict, you can not ask for --substitution-only && --with-substitution parameters at the same time');
}
list($sqlCount, $stmtParams) = SQLParserUtils::expandListParameters($sqlCount, $params, $types);
list($sql, $params, $types) = $this->generateSQL($subdefsName, $recordsType, $min, $max, $withSubstitution, $substitutionOnly);
$databox = $this->container->findDataboxById($input->getArgument('databox'));
$output->writeln($sqlCount);
$connection = $databox->get_connection();
$stmt = $connection->prepare($sqlCount);
$stmt->execute($stmtParams);
$row = $stmt->fetch();
$totalRecords = $row['nb_records'];
$sqlCount = sprintf('SELECT COUNT(*) FROM (%s)', $sql);
$output->writeln($sqlCount);
$totalRecords = (int)$connection->executeQuery($sqlCount, $params, $types)->fetchColumn();
if ($totalRecords === 0) {
return;
}
/** @var HelperSet $helperSet */
$helperSet = $this->getHelperSet();
$progress = new ProgressBar($output, $totalRecords);
/** @var ProgressBar $progress */
$progress = $helperSet->get('progress');
$progress->start($output, $totalRecords);
$progress->start();
$progress->display();
$sql = "SELECT DISTINCT(r.record_id)"
. " FROM record r LEFT JOIN subdef s ON (r.record_id = s.record_id AND s.name IN (?))"
. " WHERE r.type IN (?)";
$types = array(Connection::PARAM_STR_ARRAY, Connection::PARAM_STR_ARRAY);
$params = array($subdefsName, $recordsType);
if ($min) {
$sql .= " AND (r.record_id >= ?)";
$params[] = (int) $min;
$types[] = \PDO::PARAM_INT;
}
if ($max) {
$sql .= " AND (r.record_id <= ?)";
$params[] = (int) $max;
$types[] = \PDO::PARAM_INT;
}
if (false === $withSubstitution) {
if (true === $substitutionOnly) {
$sql .= " AND (ISNULL(s.substit) OR s.substit = 1)";
} else {
$sql .= " AND (ISNULL(s.substit) OR s.substit = 0)";
}
}
list($sql, $stmtParams) = SQLParserUtils::expandListParameters($sql, $params, $types);
$connection = $databox->get_connection();
$stmt = $connection->prepare($sql);
$stmt->execute($stmtParams);
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$rows = $connection->executeQuery($sql, $params, $types)->fetchAll(\PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$output->write(sprintf(' (#%s)', $row['record_id']));
$record = new \record_adapter($this->container, $databox->get_sbas_id(), $row['record_id']);
$record = $databox->get_record($row['record_id']);
/** @var media_subdef[] $subdefs */
$subdefs = array_filter($record->get_subdefs(), function(media_subdef $subdef) use ($subdefsName) {
return in_array($subdef->get_name(), $subdefsName);
});
/** @var media_subdef $subdef */
foreach ($subdefs as $subdef) {
$subdef->remove_file();
if (($withSubstitution && $subdef->is_substituted()) || $substitutionOnly) {
@@ -186,13 +114,49 @@ class BuildSubdefs extends Command
$subdefGenerator = $this->container['subdef.generator'];
$subdefGenerator->generateSubdefs($record, $subdefsName);
$stmt->closeCursor();
$progress->advance();
}
unset($rows, $record, $stmt, $connection);
$progress->finish();
}
/**
* @param string[] $subdefNames
* @param string[] $recordTypes
* @param null|int $min
* @param null|int $max
* @param bool $withSubstitution
* @param bool $substitutionOnly
* @return array
*/
protected function generateSQL(array $subdefNames, array $recordTypes, $min, $max, $withSubstitution, $substitutionOnly)
{
$sql = "SELECT DISTINCT(r.record_id) AS record_id"
. " FROM record r LEFT JOIN subdef s ON (r.record_id = s.record_id AND s.name IN (?))"
. " WHERE r.type IN (?)";
$types = array(Connection::PARAM_STR_ARRAY, Connection::PARAM_STR_ARRAY);
$params = array($subdefNames, $recordTypes);
if (null !== $min) {
$sql .= " AND (r.record_id >= ?)";
$params[] = (int)$min;
$types[] = \PDO::PARAM_INT;
}
if (null !== $max) {
$sql .= " AND (r.record_id <= ?)";
$params[] = (int)$max;
$types[] = \PDO::PARAM_INT;
}
if (false === $withSubstitution) {
$sql .= " AND (ISNULL(s.substit) OR s.substit = ?)";
$params[] = $substitutionOnly ? 1 : 0;
$types[] = \PDO::PARAM_INT;
}
return array($sql, $params, $types);
}
}

View File

@@ -1,9 +1,8 @@
<?php
/*
/**
* This file is part of Phraseanet
*
* (c) 2005-2014 Alchemy
* (c) 2005-2016 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,16 +10,15 @@
namespace Alchemy\Phrasea\Model\Repositories;
use Alchemy\Phrasea\Model\Entities\AuthFailure;
use Doctrine\ORM\EntityRepository;
/**
* AuthFailureRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class AuthFailureRepository extends EntityRepository
{
/**
* @param string $limit
* @return AuthFailure[]
*/
public function findOldFailures($limit = '-2 months')
{
$date = new \DateTime($limit);
@@ -37,6 +35,11 @@ class AuthFailureRepository extends EntityRepository
return $query->getResult();
}
/**
* @param string $username
* @param string $ip
* @return AuthFailure[]
*/
public function findLockedFailuresMatching($username, $ip)
{
$dql = 'SELECT f
@@ -46,7 +49,7 @@ class AuthFailureRepository extends EntityRepository
$params = [
'username' => $username,
'ip' => $ip,
'ip' => $ip,
];
$query = $this->_em->createQuery($dql);

View File

@@ -4,6 +4,7 @@ namespace Alchemy\Tests\Phrasea\Authentication\Phrasea;
use Alchemy\Phrasea\Authentication\Phrasea\FailureManager;
use Alchemy\Phrasea\Model\Entities\AuthFailure;
use Alchemy\Phrasea\Model\Repositories\AuthFailureRepository;
use Gedmo\Timestampable\TimestampableListener;
use Symfony\Component\HttpFoundation\Request;
@@ -18,7 +19,7 @@ class FailureManagerTest extends \PhraseanetTestCase
*/
public function testSaveFailure()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$recaptcha = $this->getReCaptchaMock(null);
@@ -31,8 +32,8 @@ class FailureManagerTest extends \PhraseanetTestCase
->will($this->returnValue($ip));
$oldFailures = [
$this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure'),
$this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure')
$this->getMock(AuthFailure::class),
$this->getMock(AuthFailure::class)
];
$repo->expects($this->once())
@@ -41,12 +42,12 @@ class FailureManagerTest extends \PhraseanetTestCase
$em->expects($this->exactly(count($oldFailures)))
->method('remove')
->with($this->isInstanceOf('Alchemy\Phrasea\Model\Entities\AuthFailure'));
->with($this->isInstanceOf(AuthFailure::class));
$catchFailure = null;
$em->expects($this->once())
->method('persist')
->with($this->isInstanceOf('Alchemy\Phrasea\Model\Entities\AuthFailure'))
->with($this->isInstanceOf(AuthFailure::class))
->will($this->returnCallback(function ($failure) use (&$catchFailure) {
$catchFailure = $failure;
}));
@@ -54,6 +55,8 @@ class FailureManagerTest extends \PhraseanetTestCase
$manager = new FailureManager($repo, $em, $recaptcha, 9);
$manager->saveFailure($username, $request);
/** @var null|AuthFailure $catchFailure */
$this->assertInstanceOf(AuthFailure::class, $catchFailure);
$this->assertEquals($ip, $catchFailure->getIp());
$this->assertEquals(true, $catchFailure->getLocked());
$this->assertEquals($username, $catchFailure->getUsername());
@@ -64,7 +67,7 @@ class FailureManagerTest extends \PhraseanetTestCase
*/
public function testCheckFailures()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$recaptcha = $this->getReCaptchaMock(null);
$request = $this->getRequestMock();
@@ -86,7 +89,7 @@ class FailureManagerTest extends \PhraseanetTestCase
*/
public function testCheckFailuresLessThan9()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$recaptcha = $this->getReCaptchaMock(null);
$request = $this->getRequestMock();
@@ -94,7 +97,7 @@ class FailureManagerTest extends \PhraseanetTestCase
$username = 'romainneutron';
$oldFailures = $this->ArrayIze(function () {
return $this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure');
return $this->getMock(AuthFailure::class);
}, 8);
$repo->expects($this->once())
@@ -110,7 +113,7 @@ class FailureManagerTest extends \PhraseanetTestCase
*/
public function testCheckFailuresMoreThan9WithoutCaptcha()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$recaptcha = $this->getReCaptchaMock(false);
$request = $this->getRequestMock();
@@ -118,7 +121,7 @@ class FailureManagerTest extends \PhraseanetTestCase
$username = 'romainneutron';
$oldFailures = $this->ArrayIze(function () {
return $this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure');
return $this->getMock(AuthFailure::class);
}, 10);
$repo->expects($this->once())
@@ -134,7 +137,7 @@ class FailureManagerTest extends \PhraseanetTestCase
*/
public function testCheckFailuresMoreThan9WithCorrectCaptcha()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$request = $this->getRequestMock();
$recaptcha = $this->getReCaptchaMock(true, $request, true);
@@ -142,7 +145,7 @@ class FailureManagerTest extends \PhraseanetTestCase
$username = 'romainneutron';
$oldFailures = $this->ArrayIze(function () {
$failure = $this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure');
$failure = $this->getMock(AuthFailure::class);
$failure->expects($this->once())
->method('setLocked')
->with($this->equalTo(false));
@@ -164,7 +167,7 @@ class FailureManagerTest extends \PhraseanetTestCase
*/
public function testCheckFailuresMoreThan9WithIncorrectCaptcha()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$request = $this->getRequestMock();
$recaptcha = $this->getReCaptchaMock(true, $request, false);
@@ -172,7 +175,7 @@ class FailureManagerTest extends \PhraseanetTestCase
$username = 'romainneutron';
$oldFailures = $this->ArrayIze(function () {
return $this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure');
return $this->getMock(AuthFailure::class);
}, 10);
$repo->expects($this->once())
@@ -185,7 +188,7 @@ class FailureManagerTest extends \PhraseanetTestCase
public function testCheckFailuresTrialsIsConfigurableUnderThreshold()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$recaptcha = $this->getReCaptchaMock(null);
$request = $this->getRequestMock();
@@ -193,7 +196,7 @@ class FailureManagerTest extends \PhraseanetTestCase
$username = 'romainneutron';
$oldFailures = $this->ArrayIze(function () {
return $this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure');
return $this->getMock(AuthFailure::class);
}, 2);
$repo->expects($this->once())
@@ -207,10 +210,9 @@ class FailureManagerTest extends \PhraseanetTestCase
public function testTrialsIsConfigurable()
{
$em = $this->createEntityManagerMock();
$recaptcha = $this->getReCaptchaMock(null);
$manager = new FailureManager($this->createEntityRepositoryMock(), $em, $recaptcha, 2);
$manager = new FailureManager($this->createAuthFailureRepositoryMock(), $em, $recaptcha, 2);
$this->assertEquals(2, $manager->getTrials());
}
@@ -220,7 +222,7 @@ class FailureManagerTest extends \PhraseanetTestCase
*/
public function testCheckFailuresTrialsIsConfigurableOverThreshold()
{
$repo = $this->getRepo();
$repo = $this->createAuthFailureRepositoryMock();
$em = $this->createEntityManagerMock();
$request = $this->getRequestMock();
$recaptcha = $this->getReCaptchaMock(true, $request, false);
@@ -228,7 +230,7 @@ class FailureManagerTest extends \PhraseanetTestCase
$username = 'romainneutron';
$oldFailures = $this->ArrayIze(function () {
return $this->getMock('Alchemy\Phrasea\Model\Entities\AuthFailure');
return $this->getMock(AuthFailure::class);
}, 3);
$repo->expects($this->once())
@@ -311,14 +313,17 @@ class FailureManagerTest extends \PhraseanetTestCase
private function getRequestMock()
{
return $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
return $this->getMockBuilder(Request::class)
->disableOriginalConstructor()
->getMock();
}
private function getRepo()
/**
* @return AuthFailureRepository|\PHPUnit_Framework_MockObject_MockObject
*/
private function createAuthFailureRepositoryMock()
{
return $this->getMockBuilder('Alchemy\Phrasea\Model\Repositories\AuthFailureRepository')
return $this->getMockBuilder(AuthFailureRepository::class)
->disableOriginalConstructor()
->getMock();
}

View File

@@ -2,11 +2,26 @@
namespace Alchemy\Tests\Phrasea\Core\Provider;
use Alchemy\Phrasea\Authentication\AccountCreator;
use Alchemy\Phrasea\Authentication\Authenticator;
use Alchemy\Phrasea\Authentication\Manager as AuthenticationManager;
use Alchemy\Phrasea\Authentication\PersistentCookie\Manager as PersistentCookieManager;
use Alchemy\Phrasea\Authentication\Phrasea\FailureHandledNativeAuthentication;
use Alchemy\Phrasea\Authentication\Phrasea\FailureManager;
use Alchemy\Phrasea\Authentication\Phrasea\NativeAuthentication;
use Alchemy\Phrasea\Authentication\Phrasea\OldPasswordEncoder;
use Alchemy\Phrasea\Authentication\Phrasea\PasswordAuthenticationInterface;
use Alchemy\Phrasea\Authentication\Phrasea\PasswordEncoder;
use Alchemy\Phrasea\Authentication\Provider\Factory;
use Alchemy\Phrasea\Authentication\ProvidersCollection;
use Alchemy\Phrasea\Authentication\SuggestionFinder;
use Alchemy\Phrasea\Core\Provider\RepositoriesServiceProvider;
use Alchemy\Phrasea\Core\Provider\TokensServiceProvider;
use Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider;
use Alchemy\Phrasea\Core\Provider\ConfigurationServiceProvider;
use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Model\Repositories\AuthFailureRepository;
use Alchemy\Phrasea\Model\Repositories\UserRepository;
use Neutron\ReCaptcha\ReCaptcha;
/**
* @group functional
@@ -19,59 +34,59 @@ class AuthenticationManagerServiceProviderTest extends ServiceProviderTestCase
{
return [
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'authentication',
'Alchemy\\Phrasea\\Authentication\\Authenticator',
Authenticator::class,
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'authentication.persistent-manager',
'Alchemy\Phrasea\Authentication\PersistentCookie\Manager'
PersistentCookieManager::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'authentication.suggestion-finder',
'Alchemy\Phrasea\Authentication\SuggestionFinder'
SuggestionFinder::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'authentication.providers.factory',
'Alchemy\Phrasea\Authentication\Provider\Factory'
Factory::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'authentication.providers',
'Alchemy\Phrasea\Authentication\ProvidersCollection'
ProvidersCollection::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'authentication.manager',
'Alchemy\Phrasea\Authentication\Manager'
AuthenticationManager::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'auth.password-encoder',
'Alchemy\Phrasea\Authentication\Phrasea\PasswordEncoder'
PasswordEncoder::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'auth.old-password-encoder',
'Alchemy\Phrasea\Authentication\Phrasea\OldPasswordEncoder'
OldPasswordEncoder::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'auth.native.failure-manager',
'Alchemy\Phrasea\Authentication\Phrasea\FailureManager'
FailureManager::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'auth.native',
'Alchemy\Phrasea\Authentication\Phrasea\PasswordAuthenticationInterface'
PasswordAuthenticationInterface::class
],
[
'Alchemy\Phrasea\Core\Provider\AuthenticationManagerServiceProvider',
AuthenticationManagerServiceProvider::class,
'authentication.providers.account-creator',
'Alchemy\Phrasea\Authentication\AccountCreator'
AccountCreator::class
],
];
}
@@ -83,9 +98,7 @@ class AuthenticationManagerServiceProviderTest extends ServiceProviderTestCase
$app['conf']->set(['authentication', 'captcha', 'trials-before-display'], 42);
//$app['orm.em'] = $this->createEntityManagerMock();
$app['recaptcha'] = $this->getMockBuilder('Neutron\ReCaptcha\ReCaptcha')
->disableOriginalConstructor()
->getMock();
$app['recaptcha'] = $this->createReCaptchaMock();
$manager = $app['auth.native.failure-manager'];
$this->assertEquals(42, $manager->getTrials());
@@ -93,9 +106,10 @@ class AuthenticationManagerServiceProviderTest extends ServiceProviderTestCase
public function testFailureAccountCreator()
{
self::$DI['app']->register(new ConfigurationServiceProvider());
self::$DI['app']['conf']->set(['authentication', 'auto-create'], ['templates' => []]);
self::$DI['app']['authentication.providers.account-creator'];
$app = $this->getApplication();
$app->register(new ConfigurationServiceProvider());
$app['conf']->set(['authentication', 'auto-create'], ['templates' => []]);
$app['authentication.providers.account-creator'];
}
public function testAuthNativeWithCaptchaEnabled()
@@ -111,12 +125,12 @@ class AuthenticationManagerServiceProviderTest extends ServiceProviderTestCase
$app['orm.em'] = $this->createEntityManagerMock();
$app['repo.users'] = $this->createUserRepositoryMock();
$app['repo.auth-failures'] = $this->createEntityRepositoryMock();
$app['recaptcha'] = $this->getMockBuilder('Neutron\ReCaptcha\ReCaptcha')
$app['repo.auth-failures'] = $this->getMockBuilder(AuthFailureRepository::class)
->disableOriginalConstructor()
->getMock();
$app['recaptcha'] = $this->createReCaptchaMock();
$this->assertInstanceOf('Alchemy\Phrasea\Authentication\Phrasea\FailureHandledNativeAuthentication', $app['auth.native']);
$this->assertInstanceOf(FailureHandledNativeAuthentication::class, $app['auth.native']);
}
public function testAuthNativeWithCaptchaDisabled()
@@ -131,26 +145,25 @@ class AuthenticationManagerServiceProviderTest extends ServiceProviderTestCase
$app['orm.em'] = $this->createEntityManagerMock();
$app['repo.users'] = $this->createUserRepositoryMock();
$app['recaptcha'] = $this->getMockBuilder('Neutron\ReCaptcha\ReCaptcha')
->disableOriginalConstructor()
->getMock();
$app['recaptcha'] = $this->createReCaptchaMock();
$this->assertInstanceOf('Alchemy\Phrasea\Authentication\Phrasea\NativeAuthentication', $app['auth.native']);
$this->assertInstanceOf(NativeAuthentication::class, $app['auth.native']);
}
public function testAccountCreator()
{
$template1 = $user = self::$DI['app']['manipulator.user']->createTemplate('template1', self::$DI['user']);
$template2 = $user = self::$DI['app']['manipulator.user']->createTemplate('template2', self::$DI['user']);
$app = $this->getApplication();
$template1 = $user = $app['manipulator.user']->createTemplate('template1', self::$DI['user']);
$template2 = $user = $app['manipulator.user']->createTemplate('template2', self::$DI['user']);
self::$DI['app']['conf']->set(['authentication', 'auto-create'], ['templates' => [$template1->getId(), $template2->getId()]]);
$app['conf']->set(['authentication', 'auto-create'], ['templates' => [$template1->getId(), $template2->getId()]]);
$this->assertEquals([$template1->getLogin(), $template2->getLogin()], array_map(function ($u) {
return $u->getLogin();
}, self::$DI['app']['authentication.providers.account-creator']->getTemplates()));
$this->assertEquals([$template1->getLogin(), $template2->getLogin()], array_map(function (User $user) {
return $user->getLogin();
}, $app['authentication.providers.account-creator']->getTemplates()));
$this->removeUser(self::$DI['app'], $template1);
$this->removeUser(self::$DI['app'], $template2);
$this->removeUser($app, $template1);
$this->removeUser($app, $template2);
}
private function createUserRepositoryMock()
@@ -159,4 +172,14 @@ class AuthenticationManagerServiceProviderTest extends ServiceProviderTestCase
->disableOriginalConstructor()
->getMock();
}
/**
* @return ReCaptcha|\PHPUnit_Framework_MockObject_MockObject
*/
protected function createReCaptchaMock()
{
return $this->getMockBuilder(ReCaptcha::class)
->disableOriginalConstructor()
->getMock();
}
}

View File

@@ -336,6 +336,11 @@ abstract class PhraseanetTestCase extends WebTestCase
return $cli;
}
/**
* @param null|string $path
* @param string $environment
* @return Application
*/
protected function loadApp($path = null, $environment = Application::ENV_TEST)
{
if (null !== $path) {