diff --git a/circle.yml b/circle.yml index 23fa3b36f8..22517ac9d1 100644 --- a/circle.yml +++ b/circle.yml @@ -36,12 +36,12 @@ database: override: - mysql -u ubuntu -e 'CREATE DATABASE update39_test;CREATE DATABASE ab_test;CREATE DATABASE db_test;SET @@global.sql_mode=STRICT_ALL_TABLES;SET @@global.max_allowed_packet=33554432;SET @@global.wait_timeout=999999;'; post: - - "./bin/developer system:uninstall" - - "./bin/setup system:install --email=test@phraseanet.com --password=test --db-host=127.0.0.1 --db-user=ubuntu --db-template=fr --db-password= --databox=db_test --appbox=ab_test --server-name=http://127.0.0.1 -y;" - - "./bin/developer ini:setup-tests-dbs" - - "./bin/console searchengine:index:create" - - "./bin/developer phraseanet:regenerate-sqlite" - - "./bin/developer phraseanet:generate-js-fixtures" + - "./bin/developer system:uninstall -v" + - "./bin/setup system:install -v --email=test@phraseanet.com --password=test --db-host=127.0.0.1 --db-user=ubuntu --db-template=fr --db-password= --databox=db_test --appbox=ab_test --server-name=http://127.0.0.1 -y;" + - "./bin/developer ini:setup-tests-dbs -v" + - "./bin/console searchengine:index:create -v" + - "./bin/developer phraseanet:regenerate-sqlite -v" + - "./bin/developer phraseanet:generate-js-fixtures -v" test: override: diff --git a/lib/Alchemy/Phrasea/Application/Helper/ApplicationBoxAware.php b/lib/Alchemy/Phrasea/Application/Helper/ApplicationBoxAware.php index 4d75a46705..50c917ae8d 100644 --- a/lib/Alchemy/Phrasea/Application/Helper/ApplicationBoxAware.php +++ b/lib/Alchemy/Phrasea/Application/Helper/ApplicationBoxAware.php @@ -9,6 +9,8 @@ */ namespace Alchemy\Phrasea\Application\Helper; +use Alchemy\Phrasea\Collection\CollectionService; + trait ApplicationBoxAware { /** @var \appbox|callable */ @@ -61,6 +63,14 @@ trait ApplicationBoxAware return $this->applicationBox; } + /** + * @return CollectionService + */ + public function getCollectionService() + { + return $this['services.collection']; + } + /** * Find a registered Databoxes. * diff --git a/lib/Alchemy/Phrasea/Collection/Collection.php b/lib/Alchemy/Phrasea/Collection/Collection.php new file mode 100644 index 0000000000..adce9e1705 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Collection.php @@ -0,0 +1,250 @@ +databoxId = (int) $databoxId; + $this->collectionId = (int) $collectionId; + $this->name = (string) $name; + $this->preferences = << + + 0 + + +EOT; + $this->logo = ''; + $this->labels = array( + 'en' => '', + 'fr' => '', + 'de' => '', + 'nl' => '' + ); + $this->publicWatermark = ''; + } + + /** + * @return int + */ + public function getDataboxId() + { + return $this->databoxId; + } + + /** + * @return int + */ + public function getCollectionId() + { + return $this->collectionId; + } + + /** + * @param $collectionId + */ + public function setCollectionId($collectionId) + { + if ($this->collectionId > 0) { + throw new LogicException('Cannot change the ID of an existing collection.'); + } + + $this->collectionId = (int) $collectionId; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName($name) + { + $name = trim(strip_tags($name)); + + if ($name === '') { + throw new \InvalidArgumentException(); + } + + $this->name = $name; + } + + /** + * @return \string[] + */ + public function getLabels() + { + return $this->labels; + } + + /** + * @param \string[] $labels + */ + public function setLabels($labels) + { + $this->labels = $labels; + } + + /** + * @param $lang + * @param bool $substitute + * @return string + */ + public function getLabel($lang, $substitute = true) + { + if (!array_key_exists($lang, $this->labels)) { + throw new \InvalidArgumentException(sprintf('Code %s is not defined', $lang)); + } + + if ($substitute) { + return isset($this->labels[$lang]) ? $this->labels[$lang] : $this->name; + } else { + return $this->labels[$lang]; + } + } + + /** + * @param $lang + * @param $label + */ + public function setLabel($lang, $label) + { + if (!array_key_exists($lang, $this->labels)) { + throw new \InvalidArgumentException(sprintf("Language '%s' is not defined.", $lang)); + } + + $this->labels[$lang] = $label; + } + + /** + * @return \int[]|string|null + */ + public function getLogo() + { + return $this->logo; + } + + /** + * @param \int[]|string $logo + */ + public function setLogo($logo) + { + $this->logo = $logo; + } + + /** + * @return \DateTimeInterface + */ + public function getLogoUpdatedAt() + { + return $this->logoUpdatedAt; + } + + /** + * @return string + */ + public function getPublicWatermark() + { + return $this->publicWatermark; + } + + /** + * @param string $publicWatermark + */ + public function setPublicWatermark($publicWatermark) + { + if (! in_array($publicWatermark, ['none', 'wm', 'stamp'])) { + return; + } + + $this->publicWatermark = $publicWatermark; + } + + /** + * @return string + */ + public function getPreferences() + { + return $this->preferences; + } + + /** + * @param string $preferences + */ + public function setPreferences($preferences) + { + $this->preferences = $preferences; + } + + /** + * @return CollectionReference + */ + public function getCollectionReference() + { + return $this->collectionReference; + } + + /** + * @param CollectionReference $collectionReference + */ + public function setCollectionReference($collectionReference) + { + $this->collectionReference = $collectionReference; + } +} diff --git a/lib/Alchemy/Phrasea/Collection/CollectionFactory.php b/lib/Alchemy/Phrasea/Collection/CollectionFactory.php new file mode 100644 index 0000000000..34c99c19b0 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/CollectionFactory.php @@ -0,0 +1,72 @@ +app = $application; + } + + /** + * @param int $databoxId + * @param CollectionReference $reference + * @param array $row + * @return \collection + */ + public function create($databoxId, CollectionReference $reference, array $row) + { + if ($databoxId != $reference->getDataboxId()) { + throw new \InvalidArgumentException('Reference does not belong to given databoxId.'); + } + + $collection = new Collection($databoxId, $row['coll_id'], $row['asciiname']); + + $collection->setLabel('en', $row['label_en']); + $collection->setLabel('fr', $row['label_fr']); + $collection->setLabel('de', $row['label_de']); + $collection->setLabel('nl', $row['label_nl']); + $collection->setLogo($row['logo']); + $collection->setPreferences($row['prefs']); + $collection->setPublicWatermark($row['pub_wm']); + + return new \collection($this->app, $collection, $reference, $row); + } + + /** + * @param int $databoxId + * @param CollectionReference[] $collectionReferences + * @param array $rows + * @return array + */ + public function createMany($databoxId, $collectionReferences, array $rows) + { + Assertion::allIsInstanceOf($collectionReferences, CollectionReference::class); + + $collections = []; + $indexedReferences = []; + + foreach ($collectionReferences as $reference) { + $indexedReferences[$reference->getCollectionId()] = $reference; + } + + foreach ($rows as $row) { + $collections[$row['coll_id']] = $this->create($databoxId, $indexedReferences[$row['coll_id']], $row); + } + + return $collections; + } +} diff --git a/lib/Alchemy/Phrasea/Collection/CollectionRepository.php b/lib/Alchemy/Phrasea/Collection/CollectionRepository.php new file mode 100644 index 0000000000..865ece521d --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/CollectionRepository.php @@ -0,0 +1,30 @@ +application = $app; + $this->repositoryFactory = $collectionRepositoryFactory; + $this->referenceRepository = $referenceRepository; + } + + /** + * @param $databoxId + * @return CollectionRepository + */ + public function getRepositoryByDatabox($databoxId) + { + if (!isset($this->repositories[$databoxId])) { + $this->repositories[$databoxId] = $this->repositoryFactory->createRepositoryForDatabox($databoxId); + } + + return $this->repositories[$databoxId]; + } + + /** + * @param int $baseId + * @return CollectionRepository + * @throws \OutOfBoundsException if no repository was found for the given baseId. + */ + public function getRepositoryByBase($baseId) + { + if ($this->baseIdMap === null) { + $this->loadBaseIdMap(); + } + + if (isset($this->baseIdMap[$baseId])) { + return $this->getRepositoryByDatabox($this->baseIdMap[$baseId]); + } + + throw new \OutOfBoundsException('No repository available for given base [baseId: ' . $baseId . ' ].'); + } + + public function purgeRegistry() + { + $this->baseIdMap = null; + + $appBox = $this->application->getApplicationBox(); + + \phrasea::reset_baseDatas($appBox); + \phrasea::reset_sbasDatas($appBox); + } + + private function loadBaseIdMap() + { + $references = $this->referenceRepository->findAll(); + + $this->baseIdMap = []; + + foreach ($references as $reference) { + $this->baseIdMap[$reference->getBaseId()] = $reference->getDataboxId(); + } + } +} diff --git a/lib/Alchemy/Phrasea/Collection/CollectionService.php b/lib/Alchemy/Phrasea/Collection/CollectionService.php new file mode 100644 index 0000000000..0cb33fc4fe --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/CollectionService.php @@ -0,0 +1,266 @@ +app = $application; + $this->connection = $connection; + $this->connectionProvider = $connectionProvider; + } + + /** + * @param Collection $collection + * @return int|null + * @throws \Doctrine\DBAL\DBALException + */ + public function getRecordCount(Collection $collection) + { + $connection = $this->connectionProvider->getConnection($collection->getDataboxId()); + + $sql = "SELECT COALESCE(COUNT(record_id), 0) AS recordCount FROM record WHERE coll_id = :coll_id"; + $stmt = $connection->prepare($sql); + $stmt->execute([':coll_id' => $collection->getCollectionId()]); + $rowbas = $stmt->fetch(\PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + $amount = $rowbas ? (int) $rowbas["recordCount"] : null; + + return $amount; + } + + /** + * @param Collection $collection + * @return array + */ + public function getRecordDetails(Collection $collection) + { + $sql = "SELECT record.coll_id,name,COALESCE(asciiname, CONCAT('_',record.coll_id)) AS asciiname, + SUM(1) AS n, SUM(size) AS size + FROM record NATURAL JOIN subdef + INNER JOIN coll ON record.coll_id=coll.coll_id AND coll.coll_id = :coll_id + GROUP BY record.coll_id, subdef.name"; + + $connection = $this->connectionProvider->getConnection($collection->getDataboxId()); + + $stmt = $connection->prepare($sql); + $stmt->execute([':coll_id' => $collection->getCollectionId()]); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + $ret = []; + foreach ($rs as $row) { + $ret[] = [ + "coll_id" => (int) $row["coll_id"], + "name" => $row["name"], + "amount" => (int) $row["n"], + "size" => (int) $row["size"]]; + } + + return $ret; + } + + /** + * @param Collection $collection + * @return $this + * @throws \Doctrine\DBAL\DBALException + */ + public function resetWatermark(Collection $collection) + { + $sql = 'SELECT path, file FROM record r INNER JOIN subdef s USING(record_id) + WHERE r.coll_id = :coll_id AND r.type="image" AND s.name="preview"'; + + $connection = $this->connectionProvider->getConnection($collection->getDataboxId()); + + $stmt = $connection->prepare($sql); + $stmt->execute([':coll_id' => $collection->getCollectionId()]); + + while ($row2 = $stmt->fetch(\PDO::FETCH_ASSOC)) { + @unlink(\p4string::addEndSlash($row2['path']) . 'watermark_' . $row2['file']); + } + $stmt->closeCursor(); + + return $this; + } + + /** + * @param Collection $collection + * @param int|null $record_id + * @return $this + * @throws \Doctrine\DBAL\DBALException + */ + public function resetStamp(Collection $collection, $record_id = null) + { + $sql = 'SELECT path, file FROM record r INNER JOIN subdef s USING(record_id) + WHERE r.coll_id = :coll_id + AND r.type="image" AND s.name IN ("preview", "document")'; + + + $params = [':coll_id' => $collection->getCollectionId()]; + + if ($record_id) { + $sql .= ' AND record_id = :record_id'; + $params[':record_id'] = $record_id; + } + + $connection = $this->connectionProvider->getConnection($collection->getDataboxId()); + + $stmt = $connection->prepare($sql); + $stmt->execute($params); + + while ($row2 = $stmt->fetch(\PDO::FETCH_ASSOC)) { + @unlink(\p4string::addEndSlash($row2['path']) . 'stamp_' . $row2['file']); + } + $stmt->closeCursor(); + + return $this; + } + + /** + * @param \databox $databox + * @param Collection $collection + * @param CollectionReference $reference + * @throws \Doctrine\DBAL\DBALException + */ + public function delete(\databox $databox, Collection $collection, CollectionReference $reference) + { + while ($this->getRecordCount($collection) > 0) { + $this->emptyCollection($databox, $collection); + } + + $connection = $this->connectionProvider->getConnection($collection->getDataboxId()); + + $sql = "DELETE FROM coll WHERE coll_id = :coll_id"; + $stmt = $connection->prepare($sql); + $stmt->execute([':coll_id' => $collection->getCollectionId()]); + $stmt->closeCursor(); + + $sql = "DELETE FROM bas WHERE base_id = :base_id"; + $stmt = $this->connection->prepare($sql); + $stmt->execute([':base_id' => $reference->getBaseId()]); + $stmt->closeCursor(); + + $sql = "DELETE FROM basusr WHERE base_id = :base_id"; + $stmt = $this->connection->prepare($sql); + $stmt->execute([':base_id' => $reference->getBaseId()]); + $stmt->closeCursor(); + + return; + } + + /** + * @param \databox $databox + * @param Collection $collection + * @param int $pass_quantity + * @return $this + * @throws \Doctrine\DBAL\DBALException + */ + public function emptyCollection(\databox $databox, Collection $collection, $pass_quantity = 100) + { + $pass_quantity = (int) $pass_quantity > 200 ? 200 : (int) $pass_quantity; + $pass_quantity = (int) $pass_quantity < 10 ? 10 : (int) $pass_quantity; + + $sql = "SELECT record_id FROM record WHERE coll_id = :coll_id + ORDER BY record_id DESC LIMIT 0, " . $pass_quantity; + + $connection = $this->connectionProvider->getConnection($collection->getDataboxId()); + + $stmt = $connection->prepare($sql); + $stmt->execute([':coll_id' => $collection->getCollectionId()]); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + foreach ($rs as $row) { + $record = $databox->get_record($row['record_id']); + $record->delete(); + unset($record); + } + + return $this; + } + + /** + * @param CollectionReference $reference + * @return $this + * @throws \Doctrine\DBAL\DBALException + */ + public function unmountCollection(CollectionReference $reference) + { + $params = [':base_id' => $reference->getBaseId()]; + + $query = $this->app['phraseanet.user-query']; + $total = $query->on_base_ids([$reference->getBaseId()]) + ->include_phantoms(false) + ->include_special_users(true) + ->include_invite(true) + ->include_templates(true)->get_total(); + $n = 0; + + while ($n < $total) { + $results = $query->limit($n, 50)->execute()->get_results(); + + foreach ($results as $user) { + $this->app->getAclForUser($user)->delete_data_from_cache(\ACL::CACHE_RIGHTS_SBAS); + $this->app->getAclForUser($user)->delete_data_from_cache(\ACL::CACHE_RIGHTS_BAS); + } + + $n+=50; + } + + $sql = "DELETE FROM basusr WHERE base_id = :base_id"; + $stmt = $this->connection->prepare($sql); + $stmt->execute($params); + $stmt->closeCursor(); + + $sql = "DELETE FROM bas WHERE base_id = :base_id"; + $stmt = $this->connection->prepare($sql); + $stmt->execute($params); + $stmt->closeCursor(); + } + + /** + * @param CollectionReference $reference + * @param User $user + */ + public function grantAdminRights(CollectionReference $reference, User $user) + { + $rights = [ + "canputinalbum" => "1", + "candwnldhd" => "1", + "nowatermark" => "1", + "candwnldpreview" => "1", + "cancmd" => "1", + "canadmin" => "1", + "actif" => "1", + "canreport" => "1", + "canpush" => "1", + "basusr_infousr" => "", + "canaddrecord" => "1", + "canmodifrecord" => "1", + "candeleterecord" => "1", + "chgstatus" => "1", + "imgtools" => "1", + "manage" => "1", + "modify_struct" => "1" + ]; + + $this->app->getAclForUser($user)->update_rights_to_base($reference->getBaseId(), $rights); + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Factory/ArrayCachedCollectionRepositoryFactory.php b/lib/Alchemy/Phrasea/Collection/Factory/ArrayCachedCollectionRepositoryFactory.php new file mode 100644 index 0000000000..bec14d37e9 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Factory/ArrayCachedCollectionRepositoryFactory.php @@ -0,0 +1,34 @@ +collectionRepositoryFactory = $collectionRepositoryFactory; + } + + /** + * @param int $databoxId + * @return CollectionRepository + */ + public function createRepositoryForDatabox($databoxId) + { + $repository = $this->collectionRepositoryFactory->createRepositoryForDatabox($databoxId); + + return new ArrayCacheCollectionRepository($repository); + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Factory/CachedCollectionRepositoryFactory.php b/lib/Alchemy/Phrasea/Collection/Factory/CachedCollectionRepositoryFactory.php new file mode 100644 index 0000000000..601bd9671b --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Factory/CachedCollectionRepositoryFactory.php @@ -0,0 +1,66 @@ +application = $application; + $this->collectionRepositoryFactory = $collectionRepositoryFactory; + $this->cache = $cache; + $this->baseCacheKey = (string)$baseCacheKey; + } + + /** + * @param int $databoxId + * @return CollectionRepository + */ + public function createRepositoryForDatabox($databoxId) + { + $repository = $this->collectionRepositoryFactory->createRepositoryForDatabox($databoxId); + + return new CachedCollectionRepository( + $this->application, + $repository, + $this->cache, + $this->baseCacheKey . '.' . $databoxId + ); + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Factory/DbalCollectionRepositoryFactory.php b/lib/Alchemy/Phrasea/Collection/Factory/DbalCollectionRepositoryFactory.php new file mode 100644 index 0000000000..c26ea68872 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Factory/DbalCollectionRepositoryFactory.php @@ -0,0 +1,60 @@ +databoxConnectionProvider = $connectionProvider; + $this->collectionFactory = $collectionFactory; + $this->collectionReferenceRepository = $referenceRepository; + } + + /** + * @param int $databoxId + * @return CollectionRepository + */ + public function createRepositoryForDatabox($databoxId) + { + $connection = $this->databoxConnectionProvider->getConnection($databoxId); + + return new DbalCollectionRepository( + $databoxId, + $connection, + $this->collectionReferenceRepository, + $this->collectionFactory + ); + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Reference/ArrayCacheCollectionReferenceRepository.php b/lib/Alchemy/Phrasea/Collection/Reference/ArrayCacheCollectionReferenceRepository.php new file mode 100644 index 0000000000..373eeab202 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Reference/ArrayCacheCollectionReferenceRepository.php @@ -0,0 +1,110 @@ +repository = $referenceRepository; + } + + /** + * @return CollectionReference[] + */ + public function findAll() + { + if ($this->referenceCache === null) { + $this->referenceCache = $this->repository->findAll(); + } + + return $this->referenceCache; + } + + /** + * @param int $databoxId + * @return CollectionReference[] + */ + public function findAllByDatabox($databoxId) + { + $references = $this->findAll(); + $found = array(); + + foreach ($references as $reference) { + if ($reference->getDataboxId() == $databoxId) { + $found[$reference->getBaseId()] = $reference; + } + } + + return $found; + } + + /** + * @param int $baseId + * @return CollectionReference|null + */ + public function find($baseId) + { + $references = $this->findAll(); + + if (isset($references[$baseId])) { + return $references[$baseId]; + } + + return null; + } + + /** + * @param int $databoxId + * @param int $collectionId + * @return CollectionReference|null + */ + public function findByCollectionId($databoxId, $collectionId) + { + $references = $this->findAll(); + + foreach ($references as $reference) { + if ($reference->getCollectionId() == $collectionId) { + return $reference; + } + } + + return null; + } + + /** + * @param CollectionReference $reference + * @return void + */ + public function save(CollectionReference $reference) + { + $this->repository->save($reference); + + if ($this->referenceCache !== null) { + $this->referenceCache[$reference->getBaseId()] = $reference; + } + } + + /** + * @param CollectionReference $reference + * @return void + */ + public function delete(CollectionReference $reference) + { + $this->repository->delete($reference); + + if ($this->referenceCache !== null) { + unset($this->referenceCache[$reference->getBaseId()]); + } + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Reference/CollectionReference.php b/lib/Alchemy/Phrasea/Collection/Reference/CollectionReference.php new file mode 100644 index 0000000000..5f0f74b3c8 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Reference/CollectionReference.php @@ -0,0 +1,156 @@ +baseId = (int) $baseId; + $this->databoxId = (int) $databoxId; + $this->collectionId = (int) $collectionId; + $this->displayIndex = (int) $displayIndex; + $this->isActive = (bool) $isActive; + $this->alias = (string) $alias; + } + + /** + * @return int + */ + public function getDataboxId() + { + return $this->databoxId; + } + + /** + * @return int + */ + public function getBaseId() + { + return $this->baseId; + } + + /** + * @param int $baseId + */ + public function setBaseId($baseId) + { + if ($this->baseId > 0) { + throw new \LogicException('Cannot change the baseId of an existing collection reference.'); + } + + $this->baseId = $baseId; + } + + /** + * @return int + */ + public function getCollectionId() + { + return $this->collectionId; + } + + /** + * @return int + */ + public function getDisplayIndex() + { + return $this->displayIndex; + } + + /** + * @param int $index + * @return $this + */ + public function setDisplayIndex($index) + { + $this->displayIndex = (int) $index; + + return $this; + } + + /** + * @return boolean + */ + public function isActive() + { + return $this->isActive; + } + + /** + * @return $this + */ + public function disable() + { + $this->isActive = false; + + return $this; + } + + /** + * @return $this + */ + public function enable() + { + $this->isActive = true; + + return $this; + } + + /** + * @return string + */ + public function getAlias() + { + return $this->alias; + } + + /** + * @param string $alias + * @return $this + */ + public function setAlias($alias) + { + $this->alias = (string) $alias; + + return $this; + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Reference/CollectionReferenceRepository.php b/lib/Alchemy/Phrasea/Collection/Reference/CollectionReferenceRepository.php new file mode 100644 index 0000000000..48dbfc94f5 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Reference/CollectionReferenceRepository.php @@ -0,0 +1,42 @@ + 'baseId', + 'sbas_id' => 'databoxId', + 'server_coll_id' => 'collectionId', + 'ord' => 'displayIndex', + 'active' => 'isActive', + 'aliases' => 'alias' + ]; + + private static $selectQuery = 'SELECT base_id AS baseId, sbas_id AS databoxId, server_coll_id AS collectionId, + ord AS displayIndex, active AS isActive, aliases AS alias + FROM bas'; + + private static $insertQuery = 'INSERT INTO bas (sbas_id, server_coll_id, ord, active, aliases) + VALUES (:databoxId, :collectionId, + (SELECT COALESCE(MAX(b.ord), 0) + 1 AS ord FROM bas b WHERE b.sbas_id = :databoxId), + :isActive, :alias)'; + + private static $updateQuery = 'UPDATE bas SET ord = :displayIndex, active = :isActive, aliases = :alias + WHERE base_id = :baseId'; + + private static $deleteQuery = 'DELETE FROM bas WHERE base_id = :baseId'; + + /** + * @var Connection + */ + private $connection; + + /** + * @param Connection $connection + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * @return CollectionReference[] + */ + public function findAll() + { + return $this->createManyReferences($this->connection->fetchAll(self::$selectQuery)); + } + + /** + * @param int $databoxId + * @return CollectionReference[] + */ + public function findAllByDatabox($databoxId) + { + $query = self::$selectQuery . ' WHERE sbas_id = :databoxId'; + $rows = $this->connection->fetchAll($query, [ ':databoxId' => $databoxId ]); + + return $this->createManyReferences($rows); + } + + /** + * @param int $baseId + * @return CollectionReference|null + */ + public function find($baseId) + { + $query = self::$selectQuery . ' WHERE base_id = :baseId'; + $row = $this->connection->fetchAssoc($query, [ ':baseId' => $baseId ]); + + if ($row !== false) { + return $this->createReference($row); + } + + return null; + } + + /** + * @param int $databoxId + * @param int $collectionId + * @return CollectionReference|null + */ + public function findByCollectionId($databoxId, $collectionId) + { + $query = self::$selectQuery . ' WHERE sbas_id = :databoxId AND server_coll_id = :collectionId'; + $row = $this->connection->fetchAssoc($query, [ ':databoxId' => $databoxId, ':collectionId' => $collectionId ]); + + if ($row !== false) { + return $this->createReference($row); + } + + return null; + } + + public function save(CollectionReference $collectionReference) + { + $query = self::$insertQuery; + $isInsert = true; + + $parameters = [ + 'isActive' => $collectionReference->isActive(), + 'alias' => $collectionReference->getAlias() + ]; + + if ($collectionReference->getBaseId() > 0) { + $query = self::$updateQuery; + $isInsert = false; + + $parameters['baseId'] = $collectionReference->getBaseId(); + $parameters['displayIndex'] = $collectionReference->getDisplayIndex(); + } + else { + $parameters['databoxId'] = $collectionReference->getDataboxId(); + $parameters['collectionId'] = $collectionReference->getCollectionId(); + } + + $this->connection->executeQuery($query, $parameters); + + if ($isInsert) { + $collectionReference->setBaseId($this->connection->lastInsertId()); + } + } + + /** + * @param CollectionReference $collectionReference + * @throws \Doctrine\DBAL\DBALException + */ + public function delete(CollectionReference $collectionReference) + { + $parameters = [ + 'baseId' => $collectionReference->getBaseId() + ]; + + $this->connection->executeQuery(self::$deleteQuery, $parameters); + } + + /** + * @param array $row + * @return CollectionReference + */ + private function createReference(array $row) + { + return new CollectionReference( + $row['baseId'], + $row['databoxId'], + $row['collectionId'], + $row['displayIndex'], + $row['isActive'], + $row['alias'] + ); + } + + /** + * @param $rows + * @return array + */ + private function createManyReferences($rows) + { + $references = []; + + foreach ($rows as $row) { + $references[$row['baseId']] = $this->createReference($row); + } + + return $references; + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Repository/ArrayCacheCollectionRepository.php b/lib/Alchemy/Phrasea/Collection/Repository/ArrayCacheCollectionRepository.php new file mode 100644 index 0000000000..3a5bc69951 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Repository/ArrayCacheCollectionRepository.php @@ -0,0 +1,69 @@ +collectionRepository = $collectionRepository; + } + + /** + * @return \collection[] + */ + public function findAll() + { + if ($this->collectionCache === null) { + $this->collectionCache = $this->collectionRepository->findAll(); + } + + return $this->collectionCache; + } + + /** + * @param int $collectionId + * @return \collection|null + */ + public function find($collectionId) + { + $collections = $this->findAll(); + + if (isset($collections[$collectionId])) { + return $collections[$collectionId]; + } + + return null; + } + + public function save(Collection $collection) + { + $this->collectionRepository->save($collection); + + if ($this->collectionCache !== null) { + $this->collectionCache = null; + } + } + + public function delete(Collection $collection) + { + $this->collectionRepository->delete($collection); + + if (isset($this->collectionCache[$collection->getCollectionId()])) { + unset($this->collectionCache[$collection->getCollectionId()]); + } + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Repository/CachedCollectionRepository.php b/lib/Alchemy/Phrasea/Collection/Repository/CachedCollectionRepository.php new file mode 100644 index 0000000000..a7a414aee4 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Repository/CachedCollectionRepository.php @@ -0,0 +1,112 @@ +app = $application; + $this->repository = $repository; + $this->cache = $cache; + $this->cacheKey = $cacheKey; + } + + /** + * @return \collection[] + */ + public function findAll() + { + $cacheKey = hash('sha256', $this->cacheKey); + /** @var \collection[] $collections */ + $collections = $this->cache->fetch($cacheKey); + + if ($collections === false) { + $collections = $this->repository->findAll(); + $this->putInCache($cacheKey, $collections); + } else { + foreach ($collections as $collection) { + $collection->hydrate($this->app); + } + } + + return $collections; + } + + /** + * @param int $collectionId + * @return \collection|null + */ + public function find($collectionId) + { + $collections = $this->findAll(); + + if (isset($collections[$collectionId])) { + return $collections[$collectionId]; + } + + return null; + } + + public function save(Collection $collection) + { + $this->repository->save($collection); + + $cacheKey = hash('sha256', $this->cacheKey); + + $this->cache->delete($cacheKey); + } + + public function delete(Collection $collection) + { + $this->repository->delete($collection); + + $cacheKey = hash('sha256', $this->cacheKey); + + $this->cache->delete($cacheKey); + } + + private function putInCache($key, $value) + { + $this->cache->save($key, $value); + } +} diff --git a/lib/Alchemy/Phrasea/Collection/Repository/DbalCollectionRepository.php b/lib/Alchemy/Phrasea/Collection/Repository/DbalCollectionRepository.php new file mode 100644 index 0000000000..860dcd1e5c --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/Repository/DbalCollectionRepository.php @@ -0,0 +1,164 @@ +databoxId = (int) $databoxId; + $this->connection = $connection; + $this->referenceRepository = $referenceRepository; + $this->collectionFactory = $collectionFactory; + } + + /** + * @return \collection[] + */ + public function findAll() + { + $references = $this->referenceRepository->findAllByDatabox($this->databoxId); + $params = []; + + foreach ($references as $reference) { + $params[':id_' . $reference->getCollectionId()] = $reference->getCollectionId(); + } + + $query = self::$selectQuery . sprintf(' WHERE coll_id IN (%s)', implode(', ', array_keys($params))); + $rows = $this->connection->fetchAll($query, $params); + + return $this->collectionFactory->createMany($this->databoxId, $references, $rows); + } + + /** + * @param int $baseId + * @return \collection|null + */ + public function find($baseId) + { + $reference = $this->referenceRepository->find($baseId); + + if ($reference === null) { + return null; + } + + $query = self::$selectQuery . ' WHERE coll_id = :collectionId'; + $row = $this->connection->fetchAssoc($query, [ ':collectionId' => $reference->getCollectionId() ]); + + if ($row !== false) { + return $this->collectionFactory->create($this->databoxId, $reference, $row); + } + + return null; + } + + /** + * @param int $databoxId + * @param int $collectionId + * @return \collection|null + */ + public function findByCollectionId($databoxId, $collectionId) + { + $reference = $this->referenceRepository->findByCollectionId($databoxId, $collectionId); + + if ($reference === null) { + return null; + } + + $query = self::$selectQuery . ' WHERE coll_id = :collectionId'; + $row = $this->connection->fetchAssoc($query, [ ':collectionId' => $reference->getCollectionId() ]); + + if ($row !== false) { + return $this->collectionFactory->create($this->databoxId, $reference, $row); + } + + return null; + } + + public function save(Collection $collection) + { + $isInsert = true; + $query = self::$insertQuery; + $parameters = array( + 'name' => $collection->getName(), + 'preferences' => $collection->getPreferences(), + 'logo' => $collection->getLogo() + ); + + if ($collection->getCollectionId() > 0) { + $parameters['collectionId'] = $collection->getCollectionId(); + $parameters['labelEn'] = $collection->getLabel('en', false); + $parameters['labelFr'] = $collection->getLabel('fr', false); + $parameters['labelDe'] = $collection->getLabel('de', false); + $parameters['labelNl'] = $collection->getLabel('nl', false); + $parameters['logoTimestamp'] = $collection->getLogoUpdatedAt(); + $parameters['publicWatermark'] = $collection->getPublicWatermark(); + + $query = self::$updateQuery; + $isInsert = false; + } + + $this->connection->executeQuery($query, $parameters); + + if ($isInsert) { + $collection->setCollectionId($this->connection->lastInsertId()); + } + } + + public function delete(Collection $collection) + { + $parameters = [ + 'collectionId' => $collection->getCollectionId() + ]; + + $this->connection->executeQuery(self::$deleteQuery, $parameters); + } +} diff --git a/lib/Alchemy/Phrasea/Command/RecordAdd.php b/lib/Alchemy/Phrasea/Command/RecordAdd.php index e42a79ee77..e40514ac4c 100644 --- a/lib/Alchemy/Phrasea/Command/RecordAdd.php +++ b/lib/Alchemy/Phrasea/Command/RecordAdd.php @@ -43,7 +43,7 @@ class RecordAdd extends Command protected function doExecute(InputInterface $input, OutputInterface $output) { try { - $collection = \collection::get_from_base_id($this->container, $input->getArgument('base_id')); + $collection = \collection::getByBaseId($this->container, $input->getArgument('base_id')); } catch (\Exception $e) { throw new \InvalidArgumentException(sprintf('Collection %s is invalid', $input->getArgument('base_id'))); } diff --git a/lib/Alchemy/Phrasea/Command/Upgrade/Step31.php b/lib/Alchemy/Phrasea/Command/Upgrade/Step31.php index 32ea0f775e..a7f42db231 100644 --- a/lib/Alchemy/Phrasea/Command/Upgrade/Step31.php +++ b/lib/Alchemy/Phrasea/Command/Upgrade/Step31.php @@ -125,7 +125,7 @@ class Step31 implements DatasUpgraderInterface $uuid = Uuid::uuid4(); try { $media = $this->app->getMediaFromUri($pathfile); - $collection = \collection::get_from_coll_id($this->$app, $databox, (int) $record['coll_id']); + $collection = \collection::getByCollectionId($this->$app, $databox, (int) $record['coll_id']); $file = new File($this->app, $media, $collection); $uuid = $file->getUUID(true, true); diff --git a/lib/Alchemy/Phrasea/Controller/Admin/CollectionController.php b/lib/Alchemy/Phrasea/Controller/Admin/CollectionController.php index a8254560fb..ac082bb3ca 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/CollectionController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/CollectionController.php @@ -33,7 +33,7 @@ class CollectionController extends Controller */ public function getCollection(Request $request, $bas_id) { - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); $admins = []; @@ -144,7 +144,7 @@ class CollectionController extends Controller $success = false; $msg = $this->app->trans('An error occurred'); - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { if ($collection->get_record_amount() <= 500) { $collection->empty_collection(500); @@ -184,7 +184,7 @@ class CollectionController extends Controller { $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $this->app->getApplicationBox()->write_collection_pic( @@ -224,7 +224,7 @@ class CollectionController extends Controller { $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $this->app->getApplicationBox()->write_collection_pic( @@ -264,7 +264,7 @@ class CollectionController extends Controller { $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $collection->update_logo(null); @@ -323,7 +323,7 @@ class CollectionController extends Controller ]); } - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $this->app->getApplicationBox()->write_collection_pic( @@ -378,7 +378,7 @@ class CollectionController extends Controller ]); } - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $this->app->getApplicationBox()->write_collection_pic( @@ -432,7 +432,7 @@ class CollectionController extends Controller ]); } - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $this->app->getApplicationBox()->write_collection_pic( @@ -468,13 +468,13 @@ class CollectionController extends Controller $success = false; $msg = $this->app->trans('An error occured'); - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { if ($collection->get_record_amount() > 0) { $msg = $this->app->trans('Empty the collection before removing'); } else { - $collection->unmount_collection($this->app); + $collection->unmount(); $collection->delete(); $success = true; $msg = $this->app->trans('Successful removal'); @@ -522,10 +522,10 @@ class CollectionController extends Controller { $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { - $collection->unmount_collection($this->app); + $collection->unmount(); $success = true; } catch (\Exception $e) { @@ -562,7 +562,7 @@ class CollectionController extends Controller $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $collection->set_name($name); @@ -594,7 +594,7 @@ class CollectionController extends Controller $this->app->abort(400, $this->app->trans('Invalid labels parameter')); } - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); $success = true; try { @@ -638,7 +638,7 @@ class CollectionController extends Controller $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $collection->set_public_presentation($watermark); @@ -671,7 +671,7 @@ class CollectionController extends Controller { $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $collection->enable($this->app->getApplicationBox()); @@ -704,7 +704,7 @@ class CollectionController extends Controller { $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); try { $collection->disable($this->app->getApplicationBox()); @@ -736,7 +736,7 @@ class CollectionController extends Controller { /** @var \databox $databox */ $databox = $this->app->findDataboxById(\phrasea::sbasFromBas($this->app, $bas_id)); - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); $structFields = $suggestedValues = $basePrefs = []; /** @var \databox_field $meta */ @@ -806,7 +806,7 @@ class CollectionController extends Controller { $success = false; - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); $prefs = $request->request->get('str'); try { @@ -843,7 +843,7 @@ class CollectionController extends Controller */ public function getDetails($bas_id) { - $collection = \collection::get_from_base_id($this->app, $bas_id); + $collection = \collection::getByBaseId($this->app, $bas_id); $out = ['total' => ['totobj' => 0, 'totsiz' => 0, 'mega' => '0', 'giga' => '0'], 'result' => []]; diff --git a/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php b/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php index 0cc7529682..f1e8e5e6a0 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php @@ -633,7 +633,7 @@ class DataboxController extends Controller { try { foreach ($request->request->get('order', []) as $data) { - $collection = \collection::get_from_base_id($this->app, $data['id']); + $collection = \collection::getByBaseId($this->app, $data['id']); $collection->set_ord($data['offset']); } $success = true; @@ -712,7 +712,7 @@ class DataboxController extends Controller } catch (\Exception $e) { return $this->app->redirectPath('admin_database_submit_collection', [ 'databox_id' => $databox_id, - 'error' => 'error', + 'error' => $e->getMessage(), ]); } } diff --git a/lib/Alchemy/Phrasea/Controller/Admin/FeedController.php b/lib/Alchemy/Phrasea/Controller/Admin/FeedController.php index 59ce41c97b..4180cb1d84 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/FeedController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/FeedController.php @@ -56,7 +56,7 @@ class FeedController extends Controller if ($request->request->get('public') == '1') { $feed->setIsPublic(true); } elseif ($request->request->get('base_id')) { - $feed->setCollection(\collection::get_from_base_id($this->app, $request->request->get('base_id'))); + $feed->setCollection(\collection::getByBaseId($this->app, $request->request->get('base_id'))); } $publisher->setFeed($feed); @@ -106,7 +106,7 @@ class FeedController extends Controller } try { - $collection = \collection::get_from_base_id($this->app, $request->request->get('base_id')); + $collection = \collection::getByBaseId($this->app, $request->request->get('base_id')); } catch (\Exception $e) { $collection = null; } diff --git a/lib/Alchemy/Phrasea/Controller/Admin/UserController.php b/lib/Alchemy/Phrasea/Controller/Admin/UserController.php index eabcbc9a6f..07d8bc8674 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/UserController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/UserController.php @@ -455,7 +455,7 @@ class UserController extends Controller $registrationRepository->getUserRegistrations( $user, array_map(function ($baseId) { - return \collection::get_from_base_id($this->app, $baseId); + return \collection::getByBaseId($this->app, $baseId); }, $bases) ) as $registration) { $registrationManipulator->rejectRegistration($registration); @@ -473,7 +473,7 @@ class UserController extends Controller foreach ($registrationRepository->getUserRegistrations( $user, array_map(function ($baseId) { - return \collection::get_from_base_id($this->app, $baseId); + return \collection::getByBaseId($this->app, $baseId); }, $bases) ) as $registration) { $done[$usr][$registration->getBaseId()] = true; @@ -503,7 +503,7 @@ class UserController extends Controller ]; foreach ($bases as $bas => $isok) { - $collection = \collection::get_from_base_id($this->app, $bas); + $collection = \collection::getByBaseId($this->app, $bas); $label = $collection->get_label($this->app['locale']); if ($isok) { diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 778e0c1df5..b697b1e64c 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -837,7 +837,7 @@ class V1Controller extends Controller return $this->getBadRequestAction($request, 'Missing base_id parameter'); } - $collection = \collection::get_from_base_id($this->app, $request->get('base_id')); + $collection = \collection::getByBaseId($this->app, $request->get('base_id')); if (!$this->getAclForUser()->has_right_on_base($request->get('base_id'), 'canaddrecord')) { return Result::createError($request, 403, sprintf( @@ -935,7 +935,7 @@ class V1Controller extends Controller $media = $this->app->getMediaFromUri($file->getPathname()); $record = $this->findDataboxById($request->get('databox_id'))->get_record($request->get('record_id')); $base_id = $record->getBaseId(); - $collection = \collection::get_from_base_id($this->app, $base_id); + $collection = \collection::getByBaseId($this->app, $base_id); if (!$this->getAclForUser()->has_right_on_base($base_id, 'canaddrecord')) { return Result::createError($request, 403, sprintf( 'You do not have access to collection %s', $collection->get_label($this->app['locale.I18n']) @@ -1611,7 +1611,7 @@ class V1Controller extends Controller $record = $databox->get_record($record_id); try { - $collection = \collection::get_from_base_id($this->app, $request->get('base_id')); + $collection = \collection::getByBaseId($this->app, $request->get('base_id')); $record->move_to_collection($collection, $this->getApplicationBox()); return Result::create($request, ["record" => $this->listRecord($request, $record)])->createResponse(); @@ -2067,7 +2067,7 @@ class V1Controller extends Controller */ protected function createStory($data) { - $collection = \collection::get_from_base_id($this->app, $data->{'base_id'}); + $collection = \collection::getByBaseId($this->app, $data->{'base_id'}); if (!$this->getAclForUser()->has_right_on_base($collection->get_base_id(), 'canaddrecord')) { $this->app->abort(403, sprintf('You can not create a story on this collection %s', $collection->get_base_id())); diff --git a/lib/Alchemy/Phrasea/Controller/PermalinkController.php b/lib/Alchemy/Phrasea/Controller/PermalinkController.php index 12379c9be7..a590e86fec 100644 --- a/lib/Alchemy/Phrasea/Controller/PermalinkController.php +++ b/lib/Alchemy/Phrasea/Controller/PermalinkController.php @@ -132,7 +132,7 @@ class PermalinkController extends AbstractDelivery return $this->deliverContentWithCaptionLink($request, $record, $subdef, $watermark, $stamp, $token); } - $collection = \collection::get_from_base_id($this->app, $record->get_base_id()); + $collection = \collection::getByBaseId($this->app, $record->get_base_id()); switch ($collection->get_pub_wm()) { default: case 'none': diff --git a/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php b/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php index c6daefa300..74c8378e84 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php @@ -58,7 +58,7 @@ class MoveCollectionController extends Controller } try { - $collection = \collection::get_from_base_id($this->app, $request->request->get('base_id')); + $collection = \collection::getByBaseId($this->app, $request->request->get('base_id')); } catch (\Exception_Databox_CollectionNotFound $e) { $datas['message'] = $this->app->trans('Invalid target collection'); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/PropertyController.php b/lib/Alchemy/Phrasea/Controller/Prod/PropertyController.php index e4e832521c..5d2b670f9f 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/PropertyController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/PropertyController.php @@ -36,7 +36,7 @@ class PropertyController extends Controller ])); } - $databox = current($records->databoxes()); + $databox = reset($records->databoxes()); $statusStructure = $databox->getStatusStructure(); $recordsStatuses = []; diff --git a/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php b/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php index c74b6ddce4..e8efc59e47 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php @@ -33,7 +33,7 @@ class StoryController extends Controller public function postCreateFormAction(Request $request) { - $collection = \collection::get_from_base_id($this->app, $request->request->get('base_id')); + $collection = \collection::getByBaseId($this->app, $request->request->get('base_id')); if (!$this->getAclForUser()->has_right_on_base($collection->get_base_id(), 'canaddrecord')) { throw new AccessDeniedHttpException('You can not create a story on this collection'); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php b/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php index 9ca3c5f9d9..1c04bfd251 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php @@ -133,7 +133,7 @@ class UploadController extends Controller $this->getFilesystem()->rename($uploadedFilename, $renamedFilename); $media = $this->app->getMediaFromUri($renamedFilename); - $collection = \collection::get_from_base_id($this->app, $base_id); + $collection = \collection::getByBaseId($this->app, $base_id); $lazaretSession = new LazaretSession(); $lazaretSession->setUser($this->getAuthenticatedUser()); diff --git a/lib/Alchemy/Phrasea/Controller/Root/AccountController.php b/lib/Alchemy/Phrasea/Controller/Root/AccountController.php index 7acbc0d5d8..87bcbdc721 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/AccountController.php +++ b/lib/Alchemy/Phrasea/Controller/Root/AccountController.php @@ -316,7 +316,7 @@ class AccountController extends Controller if (0 !== count($registrations)) { foreach ($registrations as $baseId) { $this->getRegistrationManipulator() - ->createRegistration($user, \collection::get_from_base_id($this->app, $baseId)); + ->createRegistration($user, \collection::getByBaseId($this->app, $baseId)); } $this->app->addFlash('success', $this->app->trans('Your registration requests have been taken into account.')); } diff --git a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php index 496c56fde5..36f0ed0e7e 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php @@ -70,7 +70,7 @@ class BorderManagerServiceProvider implements ServiceProviderInterface $collections = []; foreach ($checker['collections'] as $base_id) { try { - $collections[] = \collection::get_from_base_id($app, $base_id); + $collections[] = \collection::getByBaseId($app, $base_id); } catch (\Exception $e) { throw new \InvalidArgumentException('Invalid collection option'); } diff --git a/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php index fe40727b0c..1bbfc20c4b 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php @@ -12,7 +12,18 @@ namespace Alchemy\Phrasea\Core\Provider; use Alchemy\Phrasea\Application as PhraseaApplication; +use Alchemy\Phrasea\Collection\CollectionFactory; +use Alchemy\Phrasea\Collection\CollectionRepositoryRegistry; +use Alchemy\Phrasea\Collection\Factory\ArrayCachedCollectionRepositoryFactory; +use Alchemy\Phrasea\Collection\Factory\CachedCollectionRepositoryFactory; +use Alchemy\Phrasea\Collection\Factory\DbalCollectionRepositoryFactory; +use Alchemy\Phrasea\Collection\Reference\ArrayCacheCollectionReferenceRepository; +use Alchemy\Phrasea\Collection\Reference\DbalCollectionReferenceRepository; +use Alchemy\Phrasea\Collection\Repository\ArrayCacheCollectionRepository; +use Alchemy\Phrasea\Collection\Repository\CachedCollectionRepository; +use Alchemy\Phrasea\Collection\Repository\DbalCollectionRepository; use Alchemy\Phrasea\Databox\CachingDataboxRepositoryDecorator; +use Alchemy\Phrasea\Databox\DataboxConnectionProvider; use Alchemy\Phrasea\Databox\DataboxFactory; use Alchemy\Phrasea\Databox\DbalDataboxRepository; use Alchemy\Phrasea\Databox\Field\DataboxFieldFactory; @@ -147,6 +158,33 @@ class RepositoriesServiceProvider implements ServiceProviderInterface $app['repo.records.factory'] = $app->protect(function (\databox $databox) use ($app) { return new LegacyRecordRepository($app, $databox); }); + + $app['repo.collection-references'] = $app->share(function (PhraseaApplication $app) { + $repository = new DbalCollectionReferenceRepository($app->getApplicationBox()->get_connection()); + + return new ArrayCacheCollectionReferenceRepository($repository); + }); + $app['repo.collections-registry'] = $app->share(function (PhraseaApplication $app) { + $factory = new CollectionFactory($app); + $connectionProvider = new DataboxConnectionProvider($app->getApplicationBox()); + + $repositoryFactory = new DbalCollectionRepositoryFactory( + $connectionProvider, + $factory, + $app['repo.collection-references'] + ); + + $repositoryFactory = new CachedCollectionRepositoryFactory( + $app, + $repositoryFactory, + $app['cache'], + 'phrasea.collections' + ); + + $repositoryFactory = new ArrayCachedCollectionRepositoryFactory($repositoryFactory); + + return new CollectionRepositoryRegistry($app, $repositoryFactory, $app['repo.collection-references']); + }); } public function boot(Application $app) diff --git a/lib/Alchemy/Phrasea/Databox/DataboxConnectionProvider.php b/lib/Alchemy/Phrasea/Databox/DataboxConnectionProvider.php new file mode 100644 index 0000000000..a1601dd00d --- /dev/null +++ b/lib/Alchemy/Phrasea/Databox/DataboxConnectionProvider.php @@ -0,0 +1,23 @@ +applicationBox = $applicationBox; + } + + /** + * @param $databoxId + * @return \Doctrine\DBAL\Connection + */ + public function getConnection($databoxId) + { + return $this->applicationBox->get_databox($databoxId)->get_connection(); + } +} diff --git a/lib/Alchemy/Phrasea/Helper/User/Edit.php b/lib/Alchemy/Phrasea/Helper/User/Edit.php index 95b0973e44..e8d0381dd2 100644 --- a/lib/Alchemy/Phrasea/Helper/User/Edit.php +++ b/lib/Alchemy/Phrasea/Helper/User/Edit.php @@ -227,7 +227,7 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper 'users' => $this->users, 'users_serial' => implode(';', $this->users), 'base_id' => $this->base_id, - 'collection' => \collection::get_from_base_id($this->app, $this->base_id), + 'collection' => \collection::getByBaseId($this->app, $this->base_id), ]; } @@ -331,7 +331,7 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper 'users' => $this->users, 'users_serial' => implode(';', $this->users), 'base_id' => $this->base_id, - 'collection' => \collection::get_from_base_id($this->app, $this->base_id), + 'collection' => \collection::getByBaseId($this->app, $this->base_id), ]; } @@ -391,7 +391,7 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper 'users' => $this->users, 'users_serial' => implode(';', $this->users), 'base_id' => $this->base_id, - 'collection' => \collection::get_from_base_id($this->app, $this->base_id), + 'collection' => \collection::getByBaseId($this->app, $this->base_id), ]; } diff --git a/lib/Alchemy/Phrasea/Model/Entities/Feed.php b/lib/Alchemy/Phrasea/Model/Entities/Feed.php index 6f1c5a8a93..55a2156128 100644 --- a/lib/Alchemy/Phrasea/Model/Entities/Feed.php +++ b/lib/Alchemy/Phrasea/Model/Entities/Feed.php @@ -302,7 +302,7 @@ class Feed implements FeedInterface public function getCollection(Application $app) { if ($this->getBaseId() !== null) { - return \collection::get_from_base_id($app, $this->getBaseId()); + return \collection::getByBaseId($app, $this->getBaseId()); } } diff --git a/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php b/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php index 1eabdf1fd7..c9a43ec845 100644 --- a/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php +++ b/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php @@ -211,7 +211,7 @@ class LazaretFile */ public function getCollection(Application $app) { - return \collection::get_from_base_id($app, $this->getBaseId()); + return \collection::getByBaseId($app, $this->getBaseId()); } /** diff --git a/lib/Alchemy/Phrasea/Model/Entities/Registration.php b/lib/Alchemy/Phrasea/Model/Entities/Registration.php index e00b82455f..6d7e08052f 100644 --- a/lib/Alchemy/Phrasea/Model/Entities/Registration.php +++ b/lib/Alchemy/Phrasea/Model/Entities/Registration.php @@ -141,7 +141,7 @@ class Registration */ public function getCollection(Application $app) { - return \collection::get_from_base_id($app, $this->baseId); + return \collection::getByBaseId($app, $this->baseId); } /** diff --git a/lib/Alchemy/Phrasea/Out/Module/PDF.php b/lib/Alchemy/Phrasea/Out/Module/PDF.php index a7ef976057..3519f95729 100644 --- a/lib/Alchemy/Phrasea/Out/Module/PDF.php +++ b/lib/Alchemy/Phrasea/Out/Module/PDF.php @@ -350,7 +350,7 @@ class PDF } } - $collection = \collection::get_from_base_id($this->app, $rec->get_base_id()); + $collection = \collection::getByBaseId($this->app, $rec->get_base_id()); $vn = ""; if (false !== $str = simplexml_load_string($collection->get_prefs())) { diff --git a/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php b/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php index 6bd3bcf00f..0b1dad1798 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php +++ b/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php @@ -481,7 +481,7 @@ class SearchEngineOptions break; case in_array($key, ['collections', 'business_fields']): $value = array_map(function ($base_id) use ($app) { - return \collection::get_from_base_id($app, $base_id); + return \collection::getByBaseId($app, $base_id); }, $value); break; } @@ -572,7 +572,7 @@ class SearchEngineOptions $bas = []; foreach ($selected_bases as $bas_id) { try { - $bas[$bas_id] = \collection::get_from_base_id($app, $bas_id); + $bas[$bas_id] = \collection::getByBaseId($app, $bas_id); } catch (\Exception_Databox_CollectionNotFound $e) { // Ignore } diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php index ce80c5f814..8372a6f3b1 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php @@ -868,7 +868,7 @@ class ArchiveJob extends AbstractJob } try { - $collection = \collection::get_from_coll_id($app, $databox, (int) $cid); + $collection = \collection::getByCollectionId($app, $databox, (int) $cid); if ($captionFileName === null) { $story = $this->createStory($app, $collection, $path . '/' . $representationFileName, null, $stat0, $stat1); } else { @@ -1203,7 +1203,7 @@ class ArchiveJob extends AbstractJob } try { - $collection = \collection::get_from_coll_id($app, $databox, (int) $cid); + $collection = \collection::getByCollectionId($app, $databox, (int) $cid); if ($captionFileName === null) { $this->createRecord($app, $collection, $path . '/' . $file, null, $grp_rid, null, $stat0, $stat1); diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/EmptyCollectionJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/EmptyCollectionJob.php index a3756c3161..3e361ba549 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/EmptyCollectionJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/EmptyCollectionJob.php @@ -61,7 +61,7 @@ class EmptyCollectionJob extends AbstractJob $baseId = (string) $settings->base_id; - $collection = \collection::get_from_base_id($app, $baseId); + $collection = \collection::getByBaseId($app, $baseId); $collection->empty_collection(200); if (0 === $collection->get_record_amount()) { diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/RecordMoverJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/RecordMoverJob.php index 71922028ba..8ac3f3064a 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/RecordMoverJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/RecordMoverJob.php @@ -82,7 +82,7 @@ class RecordMoverJob extends AbstractJob case 'UPDATE': // change collection ? if (array_key_exists('coll', $row)) { - $coll = \collection::get_from_coll_id($app, $databox, $row['coll']); + $coll = \collection::getByCollectionId($app, $databox, $row['coll']); $rec->move_to_collection($coll, $app['phraseanet.appbox']); if ($logsql) { $this->log('debug', sprintf("on sbas %s move rid %s to coll %s \n", $row['sbas_id'], $row['record_id'], $coll->get_coll_id())); diff --git a/lib/classes/ACL.php b/lib/classes/ACL.php index 65b805daff..ae3534f7ec 100644 --- a/lib/classes/ACL.php +++ b/lib/classes/ACL.php @@ -731,7 +731,7 @@ class ACL implements cache_cacheableInterface } try { - $ret[$base_id] = collection::get_from_base_id($this->app, $base_id); + $ret[$base_id] = collection::getByBaseId($this->app, $base_id); } catch (\Exception $e) { } @@ -1780,7 +1780,7 @@ class ACL implements cache_cacheableInterface $collections = []; foreach ($rs as $row) { - $collections[] = \collection::get_from_base_id($this->app, $row['base_id']); + $collections[] = \collection::getByBaseId($this->app, $row['base_id']); } return $collections; diff --git a/lib/classes/appbox.php b/lib/classes/appbox.php index 8d01767ed8..17cf7ac793 100644 --- a/lib/classes/appbox.php +++ b/lib/classes/appbox.php @@ -10,13 +10,14 @@ */ use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Collection\CollectionService; use Alchemy\Phrasea\Core\Configuration\AccessRestriction; use Alchemy\Phrasea\Core\Connection\ConnectionSettings; use Alchemy\Phrasea\Core\Version\AppboxVersionRepository; +use Alchemy\Phrasea\Databox\DataboxConnectionProvider; use Alchemy\Phrasea\Databox\DataboxRepository; use Doctrine\ORM\Tools\SchemaTool; use MediaAlchemyst\Alchemyst; -use MediaAlchemyst\Specification\Image as ImageSpecification; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\File\File as SymfoFile; use Symfony\Component\Finder\Finder; @@ -42,6 +43,10 @@ class appbox extends base * @var \databox[] */ protected $databoxes; + /** + * @var CollectionService + */ + protected $collectionService; public function __construct(Application $app) { @@ -258,12 +263,12 @@ class appbox extends base } /** - * @param $sbas_id + * @param int $sbas_id * @return databox */ public function get_databox($sbas_id) { - $databoxes = $this->get_databoxes(); + $databoxes = $this->getDataboxRepository()->findAll(); if (!isset($databoxes[$sbas_id]) && !array_key_exists($sbas_id, $databoxes)) { throw new NotFoundHttpException('Databox `' . $sbas_id . '` not found'); @@ -314,6 +319,19 @@ class appbox extends base parent::delete_data_from_cache($option); } + public function getCollectionService() + { + if ($this->collectionService === null) { + $this->collectionService = new CollectionService( + $this->app, + $this->connection, + new DataboxConnectionProvider($this) + ); + } + + return $this->collectionService; + } + /** * @return AccessRestriction */ diff --git a/lib/classes/collection.php b/lib/classes/collection.php index c37e5de801..95d13b4b31 100644 --- a/lib/classes/collection.php +++ b/lib/classes/collection.php @@ -10,11 +10,15 @@ */ use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Collection\Collection as CollectionVO; +use Alchemy\Phrasea\Collection\CollectionRepository; +use Alchemy\Phrasea\Collection\CollectionRepositoryRegistry; +use Alchemy\Phrasea\Collection\CollectionService; +use Alchemy\Phrasea\Collection\Reference\CollectionReference; +use Alchemy\Phrasea\Collection\Reference\CollectionReferenceRepository; use Alchemy\Phrasea\Core\Thumbnail\ThumbnailedElement; use Alchemy\Phrasea\Core\Thumbnail\ThumbnailManager; -use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Model\Entities\User; -use Doctrine\DBAL\Driver\Connection; use Symfony\Component\HttpFoundation\File\File; use Alchemy\Phrasea\Core\Event\Collection\CollectionEvent; @@ -29,205 +33,318 @@ use Alchemy\Phrasea\Core\Event\Collection\UnmountedEvent; use Alchemy\Phrasea\Core\Event\Collection\SettingsChangedEvent; use Alchemy\Phrasea\Core\Event\Collection\LabelChangedEvent; -class collection implements cache_cacheableInterface, ThumbnailedElement +class collection implements ThumbnailedElement, cache_cacheableInterface { - protected $base_id; - protected $sbas_id; - protected $coll_id; - protected $available = false; - protected $name; - protected $prefs; - protected $pub_wm; - protected $labels = []; - private static $_logos = []; - private static $_stamps = []; - private static $_watermarks = []; - private static $_presentations = []; - private static $_collections = []; - protected $databox; - protected $is_active; - protected $binary_logo; - protected $ord; - protected $app; const PIC_LOGO = 'minilogos'; const PIC_WM = 'wm'; const PIC_STAMP = 'stamp'; const PIC_PRESENTATION = 'presentation'; - protected function __construct(Application $app, $coll_id, databox $databox) - { - $this->app = $app; - $this->databox = $databox; - $this->sbas_id = (int) $databox->get_sbas_id(); - $this->coll_id = (int) $coll_id; - $this->load(); + private static $_logos = []; + private static $_stamps = []; + private static $_watermarks = []; + private static $_presentations = []; + private static $_collections = []; - return $this; + + + /** + * @param Application $app + * @param $databoxId + * @return CollectionRepository + */ + private static function getRepository(Application $app, $databoxId) + { + /** @var CollectionRepositoryRegistry $registry */ + $registry = $app['repo.collections-registry']; + + return $registry->getRepositoryByDatabox($databoxId); } + public static function create(Application $app, databox $databox, appbox $appbox, $name, User $user = null) + { + $databoxId = $databox->get_sbas_id(); + + $repository = self::getRepository($app, $databoxId); + $collection = new CollectionVO($databoxId, 0, $name); + + $repository->save($collection); + + $repository = $app['repo.collection-references']; + $collectionReference = new CollectionReference(0, $databoxId, $collection->getCollectionId(), 0, true, ''); + + $repository->save($collectionReference); + + $app['repo.collections-registry']->purgeRegistry(); + + $collection = new self($app, $collection, $collectionReference); + + if (null !== $user) { + $collection->collectionService->grantAdminRights($collectionReference, $user); + } + + $app['dispatcher']->dispatch( + CollectionEvents::CREATED, + new CreatedEvent( + $collection + ) + ); + + return $collection; + } + + public static function mount_collection(Application $app, databox $databox, $coll_id, User $user) + { + $reference = new CollectionReference(0, $databox->get_sbas_id(), $coll_id, 0, true, ''); + + $app['repo.collection-references']->save($reference); + $app['repo.collections-registry']->purgeRegistry(); + + $collection = self::getByBaseId($app, $reference->getBaseId()); + $collection->collectionService->grantAdminRights($collection->reference, $user); + + $app['dispatcher']->dispatch( + CollectionEvents::MOUNTED, + new MountedEvent( + $collection + ) + ); + return $reference->getBaseId(); + } + + public static function getLogo($base_id, Application $app, $printname = false) + { + $base_id_key = $base_id . '_' . ($printname ? '1' : '0'); + + if (!isset(self::$_logos[$base_id_key])) { + + if (is_file($app['root.path'] . '/config/minilogos/' . $base_id)) { + $name = phrasea::bas_labels($base_id, $app); + self::$_logos[$base_id_key] = ''; + } elseif ($printname) { + self::$_logos[$base_id_key] = phrasea::bas_labels($base_id, $app); + } + } + + return isset(self::$_logos[$base_id_key]) ? self::$_logos[$base_id_key] : ''; + } + + public static function getWatermark($base_id) + { + if (!isset(self::$_watermarks['base_id'])) { + + if (is_file(__DIR__ . '/../../config/wm/' . $base_id)) { + self::$_watermarks['base_id'] = ''; + } + } + + return isset(self::$_watermarks['base_id']) ? self::$_watermarks['base_id'] : ''; + } + + public static function getPresentation($base_id) + { + if (!isset(self::$_presentations['base_id'])) { + + if (is_file(__DIR__ . '/../../config/presentation/' . $base_id)) { + self::$_presentations['base_id'] = ''; + } + } + + return isset(self::$_presentations['base_id']) ? self::$_presentations['base_id'] : ''; + } + + public static function getStamp($base_id) + { + if (!isset(self::$_stamps['base_id'])) { + + if (is_file(__DIR__ . '/../../config/stamp/' . $base_id)) { + self::$_stamps['base_id'] = ''; + } + } + + return isset(self::$_stamps['base_id']) ? self::$_stamps['base_id'] : ''; + } + + public static function purge() + { + self::$_collections = []; + } + + /** + * @param Application $app + * @param int $base_id + * @return collection + */ + public static function getByBaseId(Application $app, $base_id) + { + /** @var CollectionReferenceRepository $referenceRepository */ + $referenceRepository = $app['repo.collection-references']; + $reference = $referenceRepository->find($base_id); + + if (!$reference) { + throw new Exception_Databox_CollectionNotFound(sprintf( + "Collection with base_id %s could not be found", + $base_id + )); + } + + $repository = self::getRepository($app, $reference->getDataboxId()); + $collection = $repository->find($reference->getCollectionId()); + + if (!$collection) { + throw new Exception_Databox_CollectionNotFound(sprintf( + "Collection with base_id %s could not be found", + $base_id + )); + } + + if (!$app['conf.restrictions']->isCollectionAvailable($collection)) { + throw new Exception_Databox_CollectionNotFound(sprintf( + 'Collection `%d` is not available here.', + $collection->get_base_id() + )); + } + + return $collection; + } + + /** + * @param Application $app + * @param databox $databox + * @param int $coll_id + * @return collection + */ + public static function getByCollectionId(Application $app, databox $databox, $coll_id) + { + assert(is_int($coll_id)); + + $repository = self::getRepository($app, $databox->get_sbas_id()); + $collection = $repository->find($coll_id); + + if (!$collection) { + throw new Exception_Databox_CollectionNotFound(sprintf( + "Collection with collection ID %d could not be found", + $coll_id + )); + } + + if (!$app['conf.restrictions']->isCollectionAvailable($collection)) { + throw new Exception_Databox_CollectionNotFound(sprintf( + 'Collection `%d` is not available here.', + $collection->get_base_id() + )); + } + + return $collection; + } + + /** + * @var Application + */ + protected $app; + + /** + * @var CollectionService + */ + protected $collectionService; + + /** + * @var databox + */ + protected $databox; + + /** + * @var CollectionVO + */ + protected $collectionVO; + + /** + * @var CollectionReference + */ + protected $reference; + + + /** + * @param Application $app + * @param CollectionVO $collection + * @param CollectionReference $reference + * @internal param $baseId + * @internal param array $row + */ + public function __construct(Application $app, CollectionVO $collection, CollectionReference $reference) + { + $this->app = $app; + $this->databox = $app->getApplicationBox()->get_databox($reference->getDataboxId()); + $this->collectionService = $app->getApplicationBox()->getCollectionService(); + + $this->collectionVO = $collection; + $this->reference = $reference; + } + + /** + * @param $eventName + * @param CollectionEvent $event + */ private function dispatch($eventName, CollectionEvent $event) { $this->app['dispatcher']->dispatch($eventName, $event); } - protected function load() + /** + * @return CollectionRepository + */ + private function getCollectionRepository() { - try { - $datas = $this->get_data_from_cache(); - if (!is_array($datas)) { - throw new \Exception('Collection could not be retrieved from cache'); - } - $this->is_active = $datas['is_active']; - $this->base_id = $datas['base_id']; - $this->available = $datas['available']; - $this->pub_wm = $datas['pub_wm']; - $this->name = $datas['name']; - $this->ord = $datas['ord']; - $this->prefs = $datas['prefs']; - $this->labels = $datas['labels']; - - return $this; - } catch (\Exception $e) { - - } - - $connbas = $this->databox->get_connection(); - $sql = 'SELECT - asciiname, prefs, pub_wm, coll_id, - label_en, label_fr, label_de, label_nl - FROM coll WHERE coll_id = :coll_id'; - $stmt = $connbas->prepare($sql); - $stmt->execute([':coll_id' => $this->coll_id]); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - if ( ! $row) - throw new Exception('Unknown collection ' . $this->coll_id . ' on ' . $this->databox->get_dbname()); - - $this->available = true; - $this->pub_wm = $row['pub_wm']; - $this->name = $row['asciiname']; - $this->prefs = $row['prefs']; - $this->labels = [ - 'fr' => $row['label_fr'], - 'en' => $row['label_en'], - 'de' => $row['label_de'], - 'nl' => $row['label_nl'], - ]; - - $conn = $this->app->getApplicationBox()->get_connection(); - - $sql = 'SELECT server_coll_id, sbas_id, base_id, active, ord FROM bas - WHERE server_coll_id = :coll_id AND sbas_id = :sbas_id'; - - $stmt = $conn->prepare($sql); - $stmt->execute([':coll_id' => $this->coll_id, ':sbas_id' => $this->databox->get_sbas_id()]); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $this->is_active = false; - - if ($row) { - $this->is_active = ! ! $row['active']; - $this->base_id = (int) $row['base_id']; - $this->ord = (int) $row['ord']; - } - - $stmt->closeCursor(); - - $datas = [ - 'is_active' => $this->is_active - , 'base_id' => $this->base_id - , 'available' => $this->available - , 'pub_wm' => $this->pub_wm - , 'name' => $this->name - , 'ord' => $this->ord - , 'prefs' => $this->prefs - , 'labels' => $this->labels - ]; - - $this->set_data_to_cache($datas); - - return $this; + return self::getRepository($this->app, $this->reference->getDataboxId()); } - public function enable(appbox $appbox) + /** + * @return CollectionReferenceRepository + */ + private function getReferenceRepository() { - $sql = 'UPDATE bas SET active = "1" WHERE base_id = :base_id'; - $stmt = $appbox->get_connection()->prepare($sql); - $stmt->execute([':base_id' => $this->get_base_id()]); - $stmt->closeCursor(); - - $this->is_active = true; - $this->delete_data_from_cache(); - $appbox->delete_data_from_cache(appbox::CACHE_LIST_BASES); - $this->databox->delete_data_from_cache(databox::CACHE_COLLECTIONS); - cache_databox::update($this->app, $this->databox->get_sbas_id(), 'structure'); - - $this->dispatch(CollectionEvents::ENABLED, new EnabledEvent($this)); - - return $this; + return $this->app['repo.collection-references']; } - public function get_ord() + public function hydrate(Application $app) { - return $this->ord; + $this->app = $app; + $this->databox = $app->getApplicationBox()->get_databox($this->reference->getDataboxId()); + $this->collectionService = $app->getApplicationBox()->getCollectionService(); } - public function set_ord($ord) + public function __sleep() { - $this->app->getApplicationBox()->set_collection_order($this, $ord); - $this->delete_data_from_cache(); - $this->app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); - - return $this; + return array( + 'collectionVO', + 'reference' + ); } - public function disable(appbox $appbox) + /** + * @return CollectionVO + */ + public function getCollection() { - $sql = 'UPDATE bas SET active=0 WHERE base_id = :base_id'; - $stmt = $appbox->get_connection()->prepare($sql); - $stmt->execute([':base_id' => $this->get_base_id()]); - $stmt->closeCursor(); - $this->is_active = false; - $this->delete_data_from_cache(); - $appbox->delete_data_from_cache(appbox::CACHE_LIST_BASES); - $this->databox->delete_data_from_cache(databox::CACHE_COLLECTIONS); - cache_databox::update($this->app, $this->databox->get_sbas_id(), 'structure'); - - $this->dispatch(CollectionEvents::DISABLED, new DisabledEvent($this)); - - return $this; + return $this->collectionVO; } - public function empty_collection($pass_quantity = 100) + /** + * @return CollectionReference + */ + public function getReference() { - $pass_quantity = (int) $pass_quantity > 200 ? 200 : (int) $pass_quantity; - $pass_quantity = (int) $pass_quantity < 10 ? 10 : (int) $pass_quantity; - - $sql = "SELECT record_id FROM record WHERE coll_id = :coll_id - ORDER BY record_id DESC LIMIT 0, " . $pass_quantity; - - $stmt = $this->databox->get_connection()->prepare($sql); - $stmt->execute([':coll_id' => $this->get_coll_id()]); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - foreach ($rs as $row) { - $record = $this->databox->get_record($row['record_id']); - $record->delete(); - unset($record); - } - - $this->dispatch(CollectionEvents::EMPTIED, new EmptiedEvent($this)); - - return $this; + return $this->reference; } + /** + * @return bool + */ public function is_active() { - return $this->is_active; + return $this->reference->isActive(); } /** @@ -239,16 +356,257 @@ class collection implements cache_cacheableInterface, ThumbnailedElement return $this->databox; } + /** + * @return \Doctrine\DBAL\Connection + */ public function get_connection() { return $this->databox->get_connection(); } - public function getRootIdentifier() + /** + * @param $publi + * @return $this + */ + public function set_public_presentation($publi) { - return $this->base_id; + $this->collectionVO->setPublicWatermark($publi); + $this->getCollectionRepository()->save($this->collectionVO); + $this->app['repo.collections-registry']->purgeRegistry(); + + return $this; } + /** + * @param $name + * @return $this + * @throws Exception_InvalidArgument + */ + public function set_name($name) + { + $old_name = $this->get_name(); + + try { + $this->collectionVO->setName($name); + } catch (\InvalidArgumentException $e) { + throw new Exception_InvalidArgument(); + } + + $this->getCollectionRepository()->save($this->collectionVO); + $this->app['repo.collections-registry']->purgeRegistry(); + + $this->dispatch(CollectionEvents::NAME_CHANGED, + new NameChangedEvent( + $this, + array("name_before"=>$old_name) + ) + ); + + return $this; + } + + /** + * @param $code + * @param $label + * @return $this + */ + public function set_label($code, $label) + { + $old_label = $this->collectionVO->getLabel($code); + + $this->collectionVO->setLabel($code, $label); + + $this->getCollectionRepository()->save($this->collectionVO); + $this->app['repo.collections-registry']->purgeRegistry(); + + $this->dispatch(CollectionEvents::LABEL_CHANGED, new LabelChangedEvent($this, array( + "lng"=>$code, + "label_before"=>$old_label, + ))); + + return $this; + } + + /** + * @param $code + * @param bool $substitute + * @return string + */ + public function get_label($code, $substitute = true) + { + return $this->collectionVO->getLabel($code, $substitute); + } + + /** + * @return int + */ + public function get_ord() + { + return $this->reference->getDisplayIndex(); + } + + /** + * @param $ord + * @return $this + */ + public function set_ord($ord) + { + $this->reference->setDisplayIndex($ord); + + $this->getReferenceRepository()->save($this->reference); + $this->app['repo.collections-registry']->purgeRegistry(); + + return $this; + } + + /** + * @return int[]|null|string + */ + public function get_binary_minilogos() + { + return $this->collectionVO->getLogo(); + } + + /** + * @return int + */ + public function get_base_id() + { + return $this->reference->getBaseId(); + } + + /** + * @return int + */ + public function get_sbas_id() + { + return $this->reference->getDataboxId(); + } + + /** + * @return int + */ + public function get_coll_id() + { + return $this->reference->getCollectionId(); + } + + /** + * @return string + */ + public function get_prefs() + { + return $this->collectionVO->getPreferences(); + } + + /** + * @param DOMDocument $dom + * @return string + */ + public function set_prefs(DOMDocument $dom) + { + $oldPreferences = $this->collectionVO->getPreferences(); + + $this->collectionVO->setPreferences($dom->saveXML()); + $this->getCollectionRepository()->save($this->collectionVO); + + $this->app['repo.collections-registry']->purgeRegistry(); + + $this->dispatch( + CollectionEvents::SETTINGS_CHANGED, + new SettingsChangedEvent( + $this, + array( + 'settings_before' => $oldPreferences + ) + ) + ); + + return $this->collectionVO->getPreferences(); + } + + /** + * @return string + */ + public function get_name() + { + return $this->collectionVO->getName(); + } + + /** + * @return string + */ + public function get_pub_wm() + { + return $this->collectionVO->getName(); + } + + /** + * @return bool + */ + public function is_available() + { + return true; + } + + /** + * @return int + */ + public function getRootIdentifier() + { + return $this->reference->getBaseId(); + } + + /** + * @return $this + */ + public function disable() + { + $this->reference->disable(); + + $this->getReferenceRepository()->save($this->reference); + $this->app['repo.collections-registry']->purgeRegistry(); + + cache_databox::update($this->app, $this->databox->get_sbas_id(), 'structure'); + + $this->dispatch(CollectionEvents::DISABLED, new DisabledEvent($this)); + + return $this; + } + + /** + * @return $this + */ + public function enable() + { + $this->reference->enable(); + + $this->getReferenceRepository()->save($this->reference); + $this->app['repo.collections-registry']->purgeRegistry(); + + cache_databox::update($this->app, $this->databox->get_sbas_id(), 'structure'); + + $this->dispatch(CollectionEvents::ENABLED, new EnabledEvent($this)); + + return $this; + } + + /** + * @param int $pass_quantity + * @return $this + * @throws \Doctrine\DBAL\DBALException + */ + public function empty_collection($pass_quantity = 100) + { + $this->collectionService->emptyCollection($this->databox, $this->collectionVO, $pass_quantity); + $this->dispatch(CollectionEvents::EMPTIED, new EmptiedEvent($this)); + return $this; + } + + /** + * @param string $thumbnailType + * @param File $file + */ public function updateThumbnail($thumbnailType, File $file = null) { switch ($thumbnailType) { @@ -268,378 +626,109 @@ class collection implements cache_cacheableInterface, ThumbnailedElement } } - - public function set_public_presentation($publi) - { - if (in_array($publi, ['none', 'wm', 'stamp'])) { - $sql = 'UPDATE coll SET pub_wm = :pub_wm WHERE coll_id = :coll_id'; - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':pub_wm' => $publi, ':coll_id' => $this->get_coll_id()]); - $stmt->closeCursor(); - - $this->pub_wm = $publi; - - $this->delete_data_from_cache(); - } - - return $this; - } - - public function set_name($name) - { - $old_name = $this->get_name(); - - $name = trim(strip_tags($name)); - - if ($name === '') - throw new Exception_InvalidArgument (); - - $sql = "UPDATE coll SET asciiname = :asciiname - WHERE coll_id = :coll_id"; - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':asciiname' => $name, ':coll_id' => $this->get_coll_id()]); - $stmt->closeCursor(); - - $this->name = $name; - - $this->delete_data_from_cache(); - - phrasea::reset_baseDatas($this->databox->get_appbox()); - - $this->dispatch( - CollectionEvents::NAME_CHANGED, - new NameChangedEvent( - $this, - array("name_before"=>$old_name) - ) - ); - - return $this; - } - - public function set_label($code, $label) - { - if (!array_key_exists($code, $this->labels)) { - throw new InvalidArgumentException(sprintf('Code %s is not defined', $code)); - } - - $old_label = $this->labels[$code]; - - $sql = "UPDATE coll SET label_$code = :label - WHERE coll_id = :coll_id"; - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':label' => $label, ':coll_id' => $this->get_coll_id()]); - $stmt->closeCursor(); - - $this->labels[$code] = $label; - - $this->delete_data_from_cache(); - - phrasea::reset_baseDatas($this->databox->get_appbox()); - - $this->dispatch(CollectionEvents::LABEL_CHANGED, new LabelChangedEvent($this, array( - "lng"=>$code, - "label_before"=>$old_label, - ))); - - return $this; - } - - public function get_label($code, $substitute = true) - { - if (!array_key_exists($code, $this->labels)) { - throw new InvalidArgumentException(sprintf('Code %s is not defined', $code)); - } - - if ($substitute) { - return isset($this->labels[$code]) ? $this->labels[$code] : $this->name; - } else { - return $this->labels[$code]; - } - } - + /** + * @return int|null + * @throws \Doctrine\DBAL\DBALException + */ public function get_record_amount() { - $sql = "SELECT COUNT(record_id) AS n FROM record WHERE coll_id = :coll_id"; - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':coll_id' => $this->get_coll_id()]); - $rowbas = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $amount = $rowbas ? (int) $rowbas["n"] : null; - - return $amount; + return $this->collectionService->getRecordCount($this->collectionVO); } + /** + * @return array + * @throws \Doctrine\DBAL\DBALException + */ public function get_record_details() { - - $sql = "SELECT record.coll_id,name,COALESCE(asciiname, CONCAT('_',record.coll_id)) AS asciiname, - SUM(1) AS n, SUM(size) AS size - FROM record NATURAL JOIN subdef - INNER JOIN coll ON record.coll_id=coll.coll_id AND coll.coll_id = :coll_id - GROUP BY record.coll_id, subdef.name"; - - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':coll_id' => $this->get_coll_id()]); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $ret = []; - foreach ($rs as $row) { - $ret[] = [ - "coll_id" => (int) $row["coll_id"], - "name" => $row["name"], - "amount" => (int) $row["n"], - "size" => (int) $row["size"]]; - } - - return $ret; + return $this->collectionService->getRecordDetails($this->collectionVO); } + /** + * @param SplFileInfo $pathfile + * @return $this + */ public function update_logo(\SplFileInfo $pathfile = null) { - if (is_null($pathfile)) { - $this->binary_logo = null; - } else { - $this->binary_logo = file_get_contents($pathfile->getPathname()); + $fileContents = null; + + if (!is_null($pathfile)) { + $fileContents = file_get_contents($pathfile->getPathname()); } - $sql = "UPDATE coll SET logo = :logo, majLogo=NOW() WHERE coll_id = :coll_id"; - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':logo' => $this->binary_logo, ':coll_id' => $this->get_coll_id()]); - $stmt->closeCursor(); + $this->collectionVO->setLogo($fileContents); + + $this->getCollectionRepository()->save($this->collectionVO); + $this->app['repo.collections-registry']->purgeRegistry(); return $this; } + /** + * @return $this + * @throws \Doctrine\DBAL\DBALException + */ public function reset_watermark() { + $this->collectionService->resetWatermark($this->collectionVO); - $sql = 'SELECT path, file FROM record r INNER JOIN subdef s USING(record_id) - WHERE r.coll_id = :coll_id AND r.type="image" AND s.name="preview"'; - - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':coll_id' => $this->get_coll_id()]); - - while ($row2 = $stmt->fetch(PDO::FETCH_ASSOC)) { - @unlink(p4string::addEndSlash($row2['path']) . 'watermark_' . $row2['file']); - } - $stmt->closeCursor(); + $this->getCollectionRepository()->save($this->collectionVO); + $this->app['repo.collections-registry']->purgeRegistry(); return $this; } + /** + * @param null $record_id + * @return $this + * @throws \Doctrine\DBAL\DBALException + */ public function reset_stamp($record_id = null) { + $this->collectionService->resetStamp($this->collectionVO, $record_id); - $sql = 'SELECT path, file FROM record r INNER JOIN subdef s USING(record_id) - WHERE r.coll_id = :coll_id - AND r.type="image" AND s.name IN ("preview", "document")'; - - $params = [':coll_id' => $this->get_coll_id()]; - - if ($record_id) { - $sql .= ' AND record_id = :record_id'; - $params[':record_id'] = $record_id; - } - - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute($params); - - while ($row2 = $stmt->fetch(PDO::FETCH_ASSOC)) { - @unlink(p4string::addEndSlash($row2['path']) . 'stamp_' . $row2['file']); - } - $stmt->closeCursor(); + $this->getCollectionRepository()->save($this->collectionVO); + $this->app['repo.collections-registry']->purgeRegistry(); return $this; } + /** + * @throws \Doctrine\DBAL\DBALException + */ public function delete() { - while ($this->get_record_amount() > 0) { - $this->empty_collection(); - } + $this->collectionService->delete($this->databox, $this->collectionVO, $this->reference); - $sql = "DELETE FROM coll WHERE coll_id = :coll_id"; - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':coll_id' => $this->get_coll_id()]); - $stmt->closeCursor(); - - $appbox = $this->databox->get_appbox(); - - $sql = "DELETE FROM bas WHERE base_id = :base_id"; - $stmt = $appbox->get_connection()->prepare($sql); - $stmt->execute([':base_id' => $this->get_base_id()]); - $stmt->closeCursor(); - - $sql = "DELETE FROM basusr WHERE base_id = :base_id"; - $stmt = $appbox->get_connection()->prepare($sql); - $stmt->execute([':base_id' => $this->get_base_id()]); - $stmt->closeCursor(); + $this->getCollectionRepository()->delete($this->collectionVO); $this->app['manipulator.registration']->deleteRegistrationsOnCollection($this); - - $this->get_databox()->delete_data_from_cache(databox::CACHE_COLLECTIONS); - $appbox->delete_data_from_cache(appbox::CACHE_LIST_BASES); - phrasea::reset_baseDatas($appbox); - - return; - } - - public function get_binary_minilogos() - { - return $this->binary_logo; + $this->app['repo.collections-registry']->purgeRegistry(); } /** - * - * @param Application $app - * @param int $base_id - * @return collection + * @return $this + * @throws \Doctrine\DBAL\DBALException */ - public static function get_from_base_id(Application $app, $base_id) - { - $coll_id = phrasea::collFromBas($app, $base_id); - $sbas_id = phrasea::sbasFromBas($app, $base_id); - if (! $sbas_id || ! $coll_id) { - throw new Exception_Databox_CollectionNotFound(sprintf("Collection with base_id %s could not be found", $base_id)); - } - $databox = $app->findDataboxById($sbas_id); - - return self::get_from_coll_id($app, $databox, $coll_id); - } - - /** - * - * @param Application $app - * @param databox $databox - * @param int $coll_id - * @return collection - */ - public static function get_from_coll_id(Application $app, databox $databox, $coll_id) - { - assert(is_int($coll_id)); - - $key = sprintf('%d_%d', $databox->get_sbas_id(), $coll_id); - if (!isset(self::$_collections[$key])) { - $collection = new self($app, $coll_id, $databox); - - if (!$app['conf.restrictions']->isCollectionAvailable($collection)) { - throw new Exception_Databox_CollectionNotFound('Collection `' . $collection->get_base_id() . '` is not available here.'); - } - - self::$_collections[$key] = $collection; - } - - return self::$_collections[$key]; - } - - public function get_base_id() - { - return $this->base_id; - } - - public function get_sbas_id() - { - return $this->sbas_id; - } - - public function get_coll_id() - { - return $this->coll_id; - } - - public function get_prefs() - { - return $this->prefs; - } - - public function set_prefs(DOMDocument $dom) - { - $old_prefs = $this->get_prefs(); - - $this->prefs = $dom->saveXML(); - - $sql = "UPDATE coll SET prefs = :prefs WHERE coll_id = :coll_id"; - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute([':prefs' => $this->prefs, ':coll_id' => $this->get_coll_id()]); - $stmt->closeCursor(); - - $this->delete_data_from_cache(); - - $this->dispatch( - CollectionEvents::SETTINGS_CHANGED, - new SettingsChangedEvent( - $this, - array( - 'settings_before'=>$old_prefs - ) - ) - ); - - return $this->prefs; - } - - public function get_name() - { - return $this->name; - } - - public function get_pub_wm() - { - return $this->pub_wm; - } - - public function is_available() - { - return $this->available; - } - - public function unmount_collection(Application $app) + public function unmount() { $old_coll_id = $this->get_coll_id(); $old_name = $this->get_name(); - $params = [':base_id' => $this->get_base_id()]; + $this->collectionService->unmountCollection($this->reference); - $query = $app['phraseanet.user-query']; - $total = $query->on_base_ids([$this->get_base_id()]) - ->include_phantoms(false) - ->include_special_users(true) - ->include_invite(true) - ->include_templates(true)->get_total(); - $n = 0; - while ($n < $total) { - $results = $query->limit($n, 50)->execute()->get_results(); - foreach ($results as $user) { - $app->getAclForUser($user)->delete_data_from_cache(ACL::CACHE_RIGHTS_SBAS); - $app->getAclForUser($user)->delete_data_from_cache(ACL::CACHE_RIGHTS_BAS); - } - $n+=50; - } - - $sql = "DELETE FROM basusr WHERE base_id = :base_id"; - $stmt = $app->getApplicationBox()->get_connection()->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - - $sql = "DELETE FROM bas WHERE base_id = :base_id"; - $stmt = $app->getApplicationBox()->get_connection()->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); + $this->getReferenceRepository()->delete($this->reference); $this->app['manipulator.registration']->deleteRegistrationsOnCollection($this); + $this->app['repo.collections-registry']->purgeRegistry(); - phrasea::reset_baseDatas($app['phraseanet.appbox']); - - $app['dispatcher']->dispatch( + $this->dispatch( CollectionEvents::UNMOUNTED, new UnmountedEvent( null, // the coll is not available anymore array( - 'coll_id'=>$old_coll_id, - 'coll_name'=>$old_name + 'coll_id' => $old_coll_id, + 'coll_name' => $old_name ) ) ); @@ -647,218 +736,6 @@ class collection implements cache_cacheableInterface, ThumbnailedElement return $this; } - private static function getNewOrder(Connection $conn, $sbas_id) - { - $sql = "SELECT GREATEST(0, MAX(ord)) + 1 AS ord FROM bas WHERE sbas_id = :sbas_id"; - $stmt = $conn->prepare($sql); - $stmt->execute([':sbas_id' => $sbas_id]); - $ord = $stmt->fetch(\PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - return $ord['ord'] ?: 1; - } - - public static function create(Application $app, databox $databox, appbox $appbox, $name, User $user = null) - { - $sbas_id = $databox->get_sbas_id(); - $connbas = $databox->get_connection(); - $conn = $appbox->get_connection(); - $new_bas = false; - - $prefs = ' - - 0 - - - '; - - $sql = "INSERT INTO coll (coll_id, asciiname, prefs, logo) - VALUES (null, :name, :prefs, '')"; - - $params = [ - ':name' => $name, - 'prefs' => $prefs, - ]; - - $stmt = $connbas->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - - $new_id = (int) $connbas->lastInsertId(); - - $sql = "INSERT INTO bas (base_id, active, ord, server_coll_id, sbas_id, aliases) - VALUES - (null, 1, :ord, :server_coll_id, :sbas_id, '')"; - $stmt = $conn->prepare($sql); - $stmt->execute([ - ':server_coll_id' => $new_id, - ':sbas_id' => $sbas_id, - ':ord' => self::getNewOrder($conn, $sbas_id), - ]); - $stmt->closeCursor(); - - $new_bas = $conn->lastInsertId(); - $databox->delete_data_from_cache(databox::CACHE_COLLECTIONS); - $appbox->delete_data_from_cache(appbox::CACHE_LIST_BASES); - - phrasea::reset_baseDatas($appbox); - - $collection = self::get_from_coll_id($app, $databox, $new_id); - - if (null !== $user) { - $collection->set_admin($new_bas, $user); - } - - $app['dispatcher']->dispatch( - CollectionEvents::CREATED, - new CreatedEvent( - $collection - ) - ); - - return $collection; - } - - public function set_admin($base_id, User $user) - { - - $rights = [ - "canputinalbum" => "1", - "candwnldhd" => "1", - "nowatermark" => "1", - "candwnldpreview" => "1", - "cancmd" => "1", - "canadmin" => "1", - "actif" => "1", - "canreport" => "1", - "canpush" => "1", - "basusr_infousr" => "", - "canaddrecord" => "1", - "canmodifrecord" => "1", - "candeleterecord" => "1", - "chgstatus" => "1", - "imgtools" => "1", - "manage" => "1", - "modify_struct" => "1" - ]; - - $this->app->getAclForUser($user)->update_rights_to_base($base_id, $rights); - - return true; - } - - public static function mount_collection(Application $app, databox $databox, $coll_id, User $user) - { - - $sql = "INSERT INTO bas (base_id, active, server_coll_id, sbas_id, aliases, ord) - VALUES - (null, 1, :server_coll_id, :sbas_id, '', :ord)"; - $stmt = $databox->get_appbox()->get_connection()->prepare($sql); - $stmt->execute([ - ':server_coll_id' => $coll_id, - ':sbas_id' => $databox->get_sbas_id(), - ':ord' => self::getNewOrder($databox->get_appbox()->get_connection(), $databox->get_sbas_id()), - ]); - $stmt->closeCursor(); - - $new_bas = $databox->get_appbox()->get_connection()->lastInsertId(); - $databox->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); - - $databox->delete_data_from_cache(databox::CACHE_COLLECTIONS); - - cache_databox::update($app, $databox->get_sbas_id(), 'structure'); - - phrasea::reset_baseDatas($databox->get_appbox()); - - $collection = self::get_from_base_id($app, $new_bas); - $collection->set_admin($new_bas, $user); - - $app['dispatcher']->dispatch( - CollectionEvents::MOUNTED, - new MountedEvent( - $collection - ) - ); - - return $new_bas; - } - - public static function getLogo($base_id, Application $app, $printname = false) - { - $base_id_key = $base_id . '_' . ($printname ? '1' : '0'); - - if ( ! isset(self::$_logos[$base_id_key])) { - - if (is_file($app['root.path'] . '/config/minilogos/' . $base_id)) { - $name = phrasea::bas_labels($base_id, $app); - self::$_logos[$base_id_key] = ''; - } elseif ($printname) { - self::$_logos[$base_id_key] = phrasea::bas_labels($base_id, $app); - } - } - - return isset(self::$_logos[$base_id_key]) ? self::$_logos[$base_id_key] : ''; - } - - public static function getWatermark($base_id) - { - if ( ! isset(self::$_watermarks['base_id'])) { - - if (is_file(__DIR__ . '/../../config/wm/' . $base_id)) - self::$_watermarks['base_id'] = ''; - } - - return isset(self::$_watermarks['base_id']) ? self::$_watermarks['base_id'] : ''; - } - - public static function getPresentation($base_id) - { - if ( ! isset(self::$_presentations['base_id'])) { - - if (is_file(__DIR__ . '/../../config/presentation/' . $base_id)) - self::$_presentations['base_id'] = ''; - } - - return isset(self::$_presentations['base_id']) ? self::$_presentations['base_id'] : ''; - } - - public static function getStamp($base_id) - { - if ( ! isset(self::$_stamps['base_id'])) { - - if (is_file(__DIR__ . '/../../config/stamp/' . $base_id)) - self::$_stamps['base_id'] = ''; - } - - return isset(self::$_stamps['base_id']) ? self::$_stamps['base_id'] : ''; - } - - public function get_cache_key($option = null) - { - return 'collection_' . $this->coll_id . ($option ? '_' . $option : ''); - } - - public function get_data_from_cache($option = null) - { - return $this->databox->get_data_from_cache($this->get_cache_key($option)); - } - - public function set_data_to_cache($value, $option = null, $duration = 0) - { - return $this->databox->set_data_to_cache($value, $this->get_cache_key($option), $duration); - } - - public function delete_data_from_cache($option = null) - { - return $this->databox->delete_data_from_cache($this->get_cache_key($option)); - } - - public static function purge() - { - self::$_collections = []; - } - /** * Tells whether registration is activated for provided collection or not. * @@ -877,7 +754,7 @@ class collection implements cache_cacheableInterface, ThumbnailedElement } foreach ($element as $caninscript) { - if (false !== (Boolean) (string) $caninscript) { + if (false !== (bool)(string)$caninscript) { return true; } } @@ -888,18 +765,36 @@ class collection implements cache_cacheableInterface, ThumbnailedElement /** * Gets terms of use. * - * @param \collection $collection - * * @return null|string */ public function getTermsOfUse() { if (false === $xml = simplexml_load_string($this->get_prefs())) { - return; + return null; } foreach ($xml->xpath('/baseprefs/cgu') as $sbpcgu) { return $sbpcgu->saveXML(); } } + + public function get_cache_key($option = null) + { + return 'collection_' . $this->collectionVO->getCollectionId() . ($option ? '_' . $option : ''); + } + + public function get_data_from_cache($option = null) + { + return $this->databox->get_data_from_cache($this->get_cache_key($option)); + } + + public function set_data_to_cache($value, $option = null, $duration = 0) + { + return $this->databox->set_data_to_cache($value, $this->get_cache_key($option), $duration); + } + + public function delete_data_from_cache($option = null) + { + $this->databox->delete_data_from_cache($this->get_cache_key($option)); + } } diff --git a/lib/classes/databox.php b/lib/classes/databox.php index ecf510463d..d829ae813b 100644 --- a/lib/classes/databox.php +++ b/lib/classes/databox.php @@ -10,6 +10,7 @@ */ use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Collection\CollectionRepositoryRegistry; use Alchemy\Phrasea\Core\Connection\ConnectionSettings; use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Core\Thumbnail\ThumbnailedElement; @@ -177,69 +178,35 @@ class databox extends base implements ThumbnailedElement */ public function get_collections() { - $ret = []; + static $collections; - foreach ($this->get_available_collections() as $coll_id) { - $ret[] = collection::get_from_coll_id($this->app, $this, $coll_id); + if ($collections === null) { + /** @var CollectionRepositoryRegistry $repositoryRegistry */ + $repositoryRegistry = $this->app['repo.collections-registry']; + $repository = $repositoryRegistry->getRepositoryByDatabox($this->get_sbas_id()); + + $collections = $repository->findAll(); } - return $ret; + return $collections; } + /** + * @return int[] + */ public function get_collection_unique_ids() { - static $base_ids_cache = []; + static $collectionsIds; - if (isset($base_ids_cache[$this->id])) { - return $base_ids_cache[$this->id]; - } + if ($collectionsIds === null) { + $collectionsIds = []; - $conn = $this->get_appbox()->get_connection(); - $sql = "SELECT b.base_id FROM bas b WHERE b.sbas_id = :sbas_id AND b.active = '1' ORDER BY b.ord ASC"; - $stmt = $conn->prepare($sql); - $stmt->execute([':sbas_id' => $this->id]); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $base_ids = []; - foreach ($rs as $row) { - $base_ids[] = (int) $row['base_id']; - } - - return $base_ids_cache[$this->id] = $base_ids; - } - - protected function get_available_collections() - { - try { - $data = $this->get_data_from_cache(self::CACHE_COLLECTIONS); - if (is_array($data)) { - return $data; + foreach ($this->get_collections() as $collection) { + $collectionsIds[] = $collection->get_base_id(); } - } catch (\Exception $e) { - } - $conn = $this->get_appbox()->get_connection(); - - $sql = "SELECT b.server_coll_id FROM sbas s, bas b - WHERE s.sbas_id = b.sbas_id AND b.sbas_id = :sbas_id - AND b.active = '1' - ORDER BY s.ord ASC, b.ord,b.base_id ASC"; - $stmt = $conn->prepare($sql); - $stmt->execute([':sbas_id' => $this->id]); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $ret = []; - - foreach ($rs as $row) { - $ret[] = (int) $row['server_coll_id']; - } - - $this->set_data_to_cache($ret, self::CACHE_COLLECTIONS); - - return $ret; + return $collectionsIds; } /** @@ -415,7 +382,7 @@ class databox extends base implements ThumbnailedElement $old_dbname = $this->get_dbname(); foreach ($this->get_collections() as $collection) { - $collection->unmount_collection($this->app); + $collection->unmount(); } $query = $this->app['phraseanet.user-query']; diff --git a/lib/classes/patch/370alpha7a.php b/lib/classes/patch/370alpha7a.php index d6c7fb0be0..ea48b90430 100644 --- a/lib/classes/patch/370alpha7a.php +++ b/lib/classes/patch/370alpha7a.php @@ -110,7 +110,7 @@ class patch_370alpha7a extends patchAbstract $media = $app->getMediaFromUri($filePath); - $collection = \collection::get_from_base_id($app, $row['base_id']); + $collection = \collection::getByBaseId($app, $row['base_id']); $borderFile = new \Alchemy\Phrasea\Border\File($app, $media, $collection); diff --git a/lib/classes/patch/390alpha13a.php b/lib/classes/patch/390alpha13a.php index d0b7ca7118..3b96e50b46 100644 --- a/lib/classes/patch/390alpha13a.php +++ b/lib/classes/patch/390alpha13a.php @@ -91,7 +91,7 @@ class patch_390alpha13a implements patchInterface } try { - $collection = \collection::get_from_base_id($app, $row['base_id']); + $collection = \collection::getByBaseId($app, $row['base_id']); } catch (\Exception $e) { $app['monolog']->addInfo(sprintf( 'Patch %s : Registration for user (%s) could not be turn into doctrine entity as base with id (%s) could not be found.', diff --git a/lib/classes/phrasea.php b/lib/classes/phrasea.php index 93c732243a..22731fa404 100644 --- a/lib/classes/phrasea.php +++ b/lib/classes/phrasea.php @@ -10,6 +10,8 @@ */ use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Collection\CollectionRepositoryRegistry; +use Alchemy\Phrasea\Collection\Reference\CollectionReferenceRepository; use Symfony\Component\Translation\TranslatorInterface; class phrasea @@ -98,49 +100,28 @@ class phrasea public static function sbasFromBas(Application $app, $base_id) { - if (!self::$_bas2sbas) { - try { - $data = $app->getApplicationBox()->get_data_from_cache(self::CACHE_SBAS_FROM_BAS); - if (!$data) { - throw new \Exception('Could not get sbas from cache'); - } - self::$_bas2sbas = $data; - } catch (\Exception $e) { - $sql = 'SELECT base_id, sbas_id FROM bas'; - $stmt = $app->getApplicationBox()->get_connection()->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); + /** @var CollectionReferenceRepository $repository */ + $repository = $app['repo.collection-references']; + $reference = $repository->find($base_id); - foreach ($rs as $row) { - self::$_bas2sbas[$row['base_id']] = (int) $row['sbas_id']; - } - - $app->getApplicationBox()->set_data_to_cache(self::$_bas2sbas, self::CACHE_SBAS_FROM_BAS); - } + if ($reference) { + return $reference->getDataboxId(); } - return isset(self::$_bas2sbas[$base_id]) ? self::$_bas2sbas[$base_id] : false; + return false; } public static function baseFromColl($sbas_id, $coll_id, Application $app) { - if (!self::$_coll2bas) { - $conn = $app->getApplicationBox()->get_connection(); - $sql = 'SELECT base_id, server_coll_id, sbas_id FROM bas'; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); + /** @var CollectionReferenceRepository $repository */ + $repository = $app['repo.collection-references']; + $reference = $repository->findByCollectionId($sbas_id, $coll_id); - foreach ($rs as $row) { - if (!isset(self::$_coll2bas[$row['sbas_id']])) - self::$_coll2bas[$row['sbas_id']] = []; - self::$_coll2bas[$row['sbas_id']][$row['server_coll_id']] = (int) $row['base_id']; - } + if ($reference) { + return $reference->getBaseId(); } - return isset(self::$_coll2bas[$sbas_id][$coll_id]) ? self::$_coll2bas[$sbas_id][$coll_id] : false; + return false; } public static function reset_baseDatas(appbox $appbox) @@ -175,20 +156,15 @@ class phrasea public static function collFromBas(Application $app, $base_id) { - if (!self::$_bas2coll) { - $conn = $app->getApplicationBox()->get_connection(); - $sql = 'SELECT base_id, server_coll_id FROM bas'; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); + /** @var CollectionReferenceRepository $repository */ + $repository = $app['repo.collection-references']; + $reference = $repository->find($base_id); - foreach ($rs as $row) { - self::$_bas2coll[$row['base_id']] = (int) $row['server_coll_id']; - } + if ($reference) { + return $reference->getCollectionId(); } - return isset(self::$_bas2coll[$base_id]) ? self::$_bas2coll[$base_id] : false; + return false; } public static function sbas_names($sbas_id, Application $app) @@ -234,27 +210,28 @@ class phrasea public static function bas_labels($base_id, Application $app) { - if (!self::$_bas_labels) { - try { - self::$_bas_labels = $app->getApplicationBox()->get_data_from_cache(self::CACHE_BAS_LABELS); - } catch (\Exception $e) { - foreach ($app->getDataboxes() as $databox) { - foreach ($databox->get_collections() as $collection) { - self::$_bas_labels[$collection->get_base_id()] = [ - 'fr' => $collection->get_label('fr'), - 'en' => $collection->get_label('en'), - 'de' => $collection->get_label('de'), - 'nl' => $collection->get_label('nl'), - ]; - } - } + /** @var CollectionReferenceRepository $repository */ + $referenceRepository = $app['repo.collection-references']; + $reference = $referenceRepository->find($base_id); - $app->getApplicationBox()->set_data_to_cache(self::$_bas_labels, self::CACHE_BAS_LABELS); - } + if (! $reference) { + return 'Unknown collection'; } - if (isset(self::$_bas_labels[$base_id]) && isset(self::$_bas_labels[$base_id][$app['locale']])) { - return self::$_bas_labels[$base_id][$app['locale']]; + /** @var CollectionRepositoryRegistry $collectionRepositoryRegistry */ + $collectionRepositoryRegistry = $app['repo.collections-registry']; + $collectionRepository = $collectionRepositoryRegistry->getRepositoryByDatabox($reference->getDataboxId()); + + $collection = $collectionRepository->find($reference->getCollectionId()); + + if (! $collection) { + throw new \RuntimeException('Missing collection ' . $base_id . '.'); + } + + $labels = $collection->getCollection()->getLabels(); + + if (isset($labels[$app['locale']])) { + return $labels[$app['locale']]; } return 'Unknown collection'; diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index de7335a83f..0ad429446b 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -346,7 +346,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface */ public function get_collection() { - return \collection::get_from_coll_id($this->app, $this->databox, $this->collection_id); + return \collection::getByCollectionId($this->app, $this->databox, $this->collection_id); } /** diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Admin/AdminCollectionTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Admin/AdminCollectionTest.php index 6699d41982..2522acced4 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Admin/AdminCollectionTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Admin/AdminCollectionTest.php @@ -30,7 +30,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase self::$DI['app']['acl'] = new ACLProvider(self::$DI['app']); foreach (self::$createdCollections as $collection) { try { - $collection->unmount_collection(self::$DI['app']); + $collection->unmount(); } catch (\Exception $e) { } @@ -154,7 +154,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $json = $this->getJson(self::$DI['client']->getResponse()); $this->assertTrue($json->success); - $collection = $collection = \collection::get_from_base_id(self::$DI['app'], self::$DI['collection']->get_base_id()); + $collection = $collection = \collection::getByBaseId(self::$DI['app'], self::$DI['collection']->get_base_id()); $this->assertTrue( ! ! strrpos($collection->get_prefs(), 'my_new_value')); unset($collection); } @@ -212,7 +212,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $json = $this->getJson(self::$DI['client']->getResponse()); $this->assertTrue($json->success); - $collection = \collection::get_from_base_id(self::$DI['app'], self::$DI['collection']->get_base_id()); + $collection = \collection::getByBaseId(self::$DI['app'], self::$DI['collection']->get_base_id()); $this->assertTrue($collection->is_active()); unset($collection); } @@ -252,7 +252,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $json = $this->getJson(self::$DI['client']->getResponse()); $this->assertTrue($json->success); - $collection = \collection::get_from_base_id(self::$DI['app'], self::$DI['collection']->get_base_id()); + $collection = \collection::getByBaseId(self::$DI['app'], self::$DI['collection']->get_base_id()); $this->assertFalse($collection->is_active()); unset($collection); } @@ -335,7 +335,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $json = $this->getJson(self::$DI['client']->getResponse()); $this->assertTrue($json->success); - $collection = \collection::get_from_base_id(self::$DI['app'], self::$DI['collection']->get_base_id()); + $collection = \collection::getByBaseId(self::$DI['app'], self::$DI['collection']->get_base_id()); $this->assertNotNull($collection->get_pub_wm()); unset($collection); } @@ -440,7 +440,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $json = $this->getJson(self::$DI['client']->getResponse()); $this->assertTrue($json->success); $this->assertEquals($collection->get_name(), 'test_rename_coll'); - $collection->unmount_collection(self::$DI['app']); + $collection->unmount(); $collection->delete(); } @@ -469,7 +469,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $this->assertEquals($collection->get_label('nl'), 'netherlands label'); $this->assertEquals($collection->get_label('fr'), 'label français'); $this->assertEquals($collection->get_label('en'), 'label à l\'anglaise'); - $collection->unmount_collection(self::$DI['app']); + $collection->unmount(); $collection->delete(); } @@ -832,7 +832,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $json = $this->getJson(self::$DI['client']->getResponse()); $this->assertTrue($json->success); try { - \collection::get_from_base_id(self::$DI['app'], $collection->get_base_id()); + \collection::getByBaseId(self::$DI['app'], $collection->get_base_id()); $this->fail('Collection not deleted'); } catch (\Exception $e) { @@ -902,7 +902,7 @@ class AdminCollectionTest extends \PhraseanetAuthenticatedWebTestCase $this->assertTrue($json->success); try { - \collection::get_from_base_id(self::$DI['app'], $collection->get_base_id()); + \collection::getByBaseId(self::$DI['app'], $collection->get_base_id()); $this->fail('Collection not unmounted'); } catch (\Exception_Databox_CollectionNotFound $e) { diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php index 74c1086fcc..e136521eed 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php @@ -34,7 +34,7 @@ class DataboxTest extends \PhraseanetAuthenticatedWebTestCase foreach (self::$createdCollections as $collection) { try { - $collection->unmount_collection(self::$DI['app']); + $collection->unmount(); } catch (\Exception $e) { } @@ -513,7 +513,7 @@ class DataboxTest extends \PhraseanetAuthenticatedWebTestCase $this->setAdmin(true); $collection = $this->createOneCollection(); - $collection->unmount_collection(self::$DI['app']); + $collection->unmount(); self::$DI['client']->request('POST', '/admin/databox/' . $collection->get_sbas_id() . '/collection/' . $collection->get_coll_id() . '/mount/', [ 'othcollsel' => self::$DI['collection']->get_base_id() diff --git a/tests/classes/ACLTest.php b/tests/classes/ACLTest.php index f73248c905..e259569347 100644 --- a/tests/classes/ACLTest.php +++ b/tests/classes/ACLTest.php @@ -494,7 +494,7 @@ class ACLTest extends \PhraseanetTestCase foreach ($bases as $base_id) { try { - $collection = collection::get_from_base_id(self::$DI['app'], $base_id); + $collection = collection::getByBaseId(self::$DI['app'], $base_id); $this->assertTrue($collection instanceof collection); $this->assertEquals($base_id, $collection->get_base_id()); unset($collection); diff --git a/tests/classes/PhraseanetTestCase.php b/tests/classes/PhraseanetTestCase.php index 94c5d78d90..5d65ae64c1 100644 --- a/tests/classes/PhraseanetTestCase.php +++ b/tests/classes/PhraseanetTestCase.php @@ -196,15 +196,15 @@ abstract class PhraseanetTestCase extends WebTestCase }); self::$DI['collection'] = self::$DI->share(function ($DI) { - return collection::get_from_base_id($DI['app'], self::$fixtureIds['collection']['coll']); + return collection::getByBaseId($DI['app'], self::$fixtureIds['collection']['coll']); }); self::$DI['collection_no_access'] = self::$DI->share(function ($DI) { - return collection::get_from_base_id($DI['app'], self::$fixtureIds['collection']['coll_no_access']); + return collection::getByBaseId($DI['app'], self::$fixtureIds['collection']['coll_no_access']); }); self::$DI['collection_no_access_by_status'] = self::$DI->share(function ($DI) { - return collection::get_from_base_id($DI['app'], self::$fixtureIds['collection']['coll_no_status']); + return collection::getByBaseId($DI['app'], self::$fixtureIds['collection']['coll_no_status']); }); self::$DI['lazaret_1'] = self::$DI->share(function ($DI) { diff --git a/tests/classes/collectionTest.php b/tests/classes/collectionTest.php index 97709f5741..7bc607cd76 100644 --- a/tests/classes/collectionTest.php +++ b/tests/classes/collectionTest.php @@ -175,7 +175,7 @@ class collectionTest extends \PhraseanetTestCase public function testGet_from_coll_id() { - $temp_coll = collection::get_from_coll_id(self::$DI['app'], self::$object->get_databox(), self::$object->get_coll_id()); + $temp_coll = collection::getByCollectionId(self::$DI['app'], self::$object->get_databox(), self::$object->get_coll_id()); $this->assertEquals(self::$object->get_coll_id(), $temp_coll->get_coll_id()); $this->assertEquals(self::$object->get_base_id(), $temp_coll->get_base_id()); }