From 1c0b1db9c7dffdc009c1b11ecc53c1ac1d4512ed Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 11 Dec 2019 11:48:23 +0400 Subject: [PATCH 1/3] exlu collection in quarantaine when upload --- .../Border/Checker/AbstractChecker.php | 14 ++++- .../Phrasea/Border/Checker/Filename.php | 14 ++++- lib/Alchemy/Phrasea/Border/Checker/Sha256.php | 12 +++- lib/Alchemy/Phrasea/Border/Checker/UUID.php | 12 +++- .../Provider/BorderManagerServiceProvider.php | 14 +++++ .../Databox/Record/LegacyRecordRepository.php | 61 +++++++++++++++++++ .../Databox/Record/RecordRepository.php | 14 +++++ lib/classes/record/adapter.php | 37 +++++++++++ 8 files changed, 172 insertions(+), 6 deletions(-) diff --git a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php index 8b4de0fb58..c929cf13bf 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php +++ b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php @@ -34,6 +34,11 @@ abstract class AbstractChecker implements CheckerInterface */ protected $collections = []; + /** + * @var \collection[] + */ + protected $ignoreCollections = []; + public function __construct(Application $app) { $this->app = $app; @@ -44,7 +49,7 @@ abstract class AbstractChecker implements CheckerInterface * Warning, you can not restrict on both databoxes and collections * * @param \databox[] $databoxes A databox or an array of databoxes - * @return bool + * @return \databox[] * * @throws \LogicException If already restricted to collections * @throws \InvalidArgumentException In case invalid databoxes are provided @@ -72,7 +77,7 @@ abstract class AbstractChecker implements CheckerInterface * Warning, you can not restrict on both databoxes and collections * * @param \collection[] $collections - * @return bool + * @return \collection[] * * @throws \LogicException If already restricted to databoxes * @throws \InvalidArgumentException In case invalid collections are provided @@ -95,6 +100,11 @@ abstract class AbstractChecker implements CheckerInterface return $this->collections; } + public function setIgnoreCollections($collections) + { + $this->ignoreCollections = $collections; + } + /** * Returns true if the checker should be executed against the current file * diff --git a/lib/Alchemy/Phrasea/Border/Checker/Filename.php b/lib/Alchemy/Phrasea/Border/Checker/Filename.php index ec4f0b0be4..0aa5661f95 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Filename.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Filename.php @@ -45,8 +45,18 @@ class Filename extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty(\record_adapter::get_records_by_originalname( - $file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1 + $excludedCollIds = []; + if (!empty($this->ignoreCollections)) { + foreach ($this->ignoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty(\record_adapter::getRecordsByOriginalnameWithExcludedCollIds( + $file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1, $excludedCollIds )); return new Response($boolean, $this); diff --git a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php index d17b28e5b9..7f994a55c2 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php @@ -34,7 +34,17 @@ class Sha256 extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256($file->getSha256())); + $excludedCollIds = []; + if (!empty($this->ignoreCollections)) { + foreach ($this->ignoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256WithExcludedCollIds($file->getSha256(), $excludedCollIds)); return new Response($boolean, $this); } diff --git a/lib/Alchemy/Phrasea/Border/Checker/UUID.php b/lib/Alchemy/Phrasea/Border/Checker/UUID.php index c3857fbe76..86960a045b 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/UUID.php +++ b/lib/Alchemy/Phrasea/Border/Checker/UUID.php @@ -33,7 +33,17 @@ class UUID extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuid($file->getUUID())); + $excludedCollIds = []; + if (!empty($this->ignoreCollections)) { + foreach ($this->ignoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuidWithExcludedCollIds($file->getUUID(), $excludedCollIds)); return new Response($boolean, $this); } diff --git a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php index 36f0ed0e7e..ff6d083077 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php @@ -78,6 +78,20 @@ class BorderManagerServiceProvider implements ServiceProviderInterface $checkerObj->restrictToCollections($collections); } + + if (isset($checker['compare-ignore-collections'])) { + $collections = []; + foreach ($checker['compare-ignore-collections'] as $base_id) { + try { + $collections[] = \collection::getByBaseId($app, $base_id); + } catch (\Exception $e) { + throw new \InvalidArgumentException('Invalid collection option'); + } + } + + $checkerObj->setIgnoreCollections($collections); + } + $registeredCheckers[] = $checkerObj; } catch (\InvalidArgumentException $e) { $app['monolog']->error( diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 522d49baae..eedeb9f042 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -82,6 +82,34 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } + public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = []) + { + static $sql; + + $params = []; + $types = []; + + if (!$sql) { + $qb = $this->createSelectBuilder() + ->where('sha256 = :sha256'); + + $params['sha256'] = $sha256; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + + $params['coll_id'] = $excludedCollIds; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + } + + $sql = $qb->getSQL(); + } + + $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + + return $this->mapRecordsFromResultSet($result); + } + /** * @param string $uuid * @return \record_adapter[] @@ -99,6 +127,39 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } + /** + * @param string $uuid + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = []) + { + static $sql; + + $params = ['uuid' => $uuid]; + $types = []; + + if (!$sql) { + $qb = $this->createSelectBuilder() + ->where('uuid = :uuid'); + + $params['uuid'] = $uuid; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + + $params['coll_id'] = $excludedCollIds; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + } + + $sql = $qb->getSQL(); + } + + $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + + return $this->mapRecordsFromResultSet($result); + } + public function findByRecordIds(array $recordIds) { static $sql; diff --git a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php index 0da49bb00f..8817610cef 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php @@ -26,12 +26,26 @@ interface RecordRepository */ public function findBySha256($sha256); + /** + * @param string $sha256 + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = []); + /** * @param string $uuid * @return \record_adapter[] */ public function findByUuid($uuid); + /** + * @param string $uuid + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = []); + /** * @param array $recordIds * @return \record_adapter[] diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index c4045d9fc5..ec7d997f1e 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1673,6 +1673,43 @@ class record_adapter implements RecordInterface, cache_cacheableInterface return $records; } + public static function getRecordsByOriginalnameWithExcludedCollIds(databox $databox, $original_name, $caseSensitive = false, $offset_start = 0, $how_many = 10, $excludedCollIds = []) + { + $offset_start = max(0, (int)$offset_start); + $how_many = max(1, (int)$how_many); + $collate = $caseSensitive ? 'utf8_bin' : 'utf8_unicode_ci'; + + $qb = $databox->get_connection()->createQueryBuilder() + ->select('record_id') + ->from('record') + ->where('originalname = :original_name COLLATE :collate') + ; + + $params = ['original_name' => $original_name, 'collate' => $collate]; + $types = []; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + + $params['coll_id'] = $excludedCollIds; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + } + + $sql = $qb->setFirstResult($offset_start) + ->setMaxResults($how_many) + ->getSQL() + ; + + $rs = $databox->get_connection()->fetchAll($sql, $params, $types); + + $records = []; + foreach ($rs as $row) { + $records[] = $databox->get_record($row['record_id']); + } + + return $records; + } + /** * @return set_selection|record_adapter[] * @throws Exception From 9ac196784a2257b36f476290aba5ae8982195348 Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 11 Dec 2019 12:41:43 +0400 Subject: [PATCH 2/3] change sql params form --- .../Databox/Record/LegacyRecordRepository.php | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index eedeb9f042..0e2cd7adea 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -86,26 +86,26 @@ class LegacyRecordRepository implements RecordRepository { static $sql; - $params = []; - $types = []; - if (!$sql) { $qb = $this->createSelectBuilder() ->where('sha256 = :sha256'); - $params['sha256'] = $sha256; - if (!empty($excludedCollIds)) { $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); - - $params['coll_id'] = $excludedCollIds; - $types[':coll_id'] = Connection::PARAM_INT_ARRAY; } $sql = $qb->getSQL(); } - $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + $result = $this->databox->get_connection()->fetchAll($sql, + [ + 'sha256' => $sha256, + 'coll_id' => $excludedCollIds + ], + [ + ':coll_id' => Connection::PARAM_INT_ARRAY + ] + ); return $this->mapRecordsFromResultSet($result); } @@ -136,26 +136,26 @@ class LegacyRecordRepository implements RecordRepository { static $sql; - $params = ['uuid' => $uuid]; - $types = []; - if (!$sql) { $qb = $this->createSelectBuilder() ->where('uuid = :uuid'); - $params['uuid'] = $uuid; - if (!empty($excludedCollIds)) { $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); - - $params['coll_id'] = $excludedCollIds; - $types[':coll_id'] = Connection::PARAM_INT_ARRAY; } $sql = $qb->getSQL(); } - $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + $result = $this->databox->get_connection()->fetchAll($sql, + [ + 'uuid' => $uuid, + 'coll_id' => $excludedCollIds + ], + [ + ':coll_id' => Connection::PARAM_INT_ARRAY + ] + ); return $this->mapRecordsFromResultSet($result); } From 8eb6ae5dfa76fa38ba5767654268a9e63fceabe5 Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 11 Dec 2019 18:18:30 +0400 Subject: [PATCH 3/3] change variable name --- lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php | 6 +++--- lib/Alchemy/Phrasea/Border/Checker/Filename.php | 4 ++-- lib/Alchemy/Phrasea/Border/Checker/Sha256.php | 4 ++-- lib/Alchemy/Phrasea/Border/Checker/UUID.php | 4 ++-- .../Phrasea/Core/Provider/BorderManagerServiceProvider.php | 2 +- .../Phrasea/Databox/Record/LegacyRecordRepository.php | 7 ++++--- lib/classes/record/adapter.php | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php index c929cf13bf..de6f4c25d6 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php +++ b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php @@ -37,7 +37,7 @@ abstract class AbstractChecker implements CheckerInterface /** * @var \collection[] */ - protected $ignoreCollections = []; + protected $compareIgnoreCollections = []; public function __construct(Application $app) { @@ -100,9 +100,9 @@ abstract class AbstractChecker implements CheckerInterface return $this->collections; } - public function setIgnoreCollections($collections) + public function setCompareIgnoreCollections($collections) { - $this->ignoreCollections = $collections; + $this->compareIgnoreCollections = $collections; } /** diff --git a/lib/Alchemy/Phrasea/Border/Checker/Filename.php b/lib/Alchemy/Phrasea/Border/Checker/Filename.php index 0aa5661f95..ea1c25a7a6 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Filename.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Filename.php @@ -46,8 +46,8 @@ class Filename extends AbstractChecker public function check(EntityManager $em, File $file) { $excludedCollIds = []; - if (!empty($this->ignoreCollections)) { - foreach ($this->ignoreCollections as $collection) { + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { // use only collection in the same databox and retrieve the coll_id if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { $excludedCollIds[] = $collection->get_coll_id(); diff --git a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php index 7f994a55c2..5116e35dfd 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php @@ -35,8 +35,8 @@ class Sha256 extends AbstractChecker public function check(EntityManager $em, File $file) { $excludedCollIds = []; - if (!empty($this->ignoreCollections)) { - foreach ($this->ignoreCollections as $collection) { + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { // use only collection in the same databox and retrieve the coll_id if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { $excludedCollIds[] = $collection->get_coll_id(); diff --git a/lib/Alchemy/Phrasea/Border/Checker/UUID.php b/lib/Alchemy/Phrasea/Border/Checker/UUID.php index 86960a045b..cdacf973a5 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/UUID.php +++ b/lib/Alchemy/Phrasea/Border/Checker/UUID.php @@ -34,8 +34,8 @@ class UUID extends AbstractChecker public function check(EntityManager $em, File $file) { $excludedCollIds = []; - if (!empty($this->ignoreCollections)) { - foreach ($this->ignoreCollections as $collection) { + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { // use only collection in the same databox and retrieve the coll_id if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { $excludedCollIds[] = $collection->get_coll_id(); diff --git a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php index ff6d083077..d7a0f636f9 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php @@ -89,7 +89,7 @@ class BorderManagerServiceProvider implements ServiceProviderInterface } } - $checkerObj->setIgnoreCollections($collections); + $checkerObj->setCompareIgnoreCollections($collections); } $registeredCheckers[] = $checkerObj; diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 0e2cd7adea..2d3c4564e4 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -138,7 +138,8 @@ class LegacyRecordRepository implements RecordRepository if (!$sql) { $qb = $this->createSelectBuilder() - ->where('uuid = :uuid'); + ->where('uuid = :uuid') + ; if (!empty($excludedCollIds)) { $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); @@ -149,8 +150,8 @@ class LegacyRecordRepository implements RecordRepository $result = $this->databox->get_connection()->fetchAll($sql, [ - 'uuid' => $uuid, - 'coll_id' => $excludedCollIds + 'uuid' => $uuid, + 'coll_id' => $excludedCollIds ], [ ':coll_id' => Connection::PARAM_INT_ARRAY diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index ec7d997f1e..e544dae308 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1692,7 +1692,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); $params['coll_id'] = $excludedCollIds; - $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; } $sql = $qb->setFirstResult($offset_start)