diff --git a/lib/Alchemy/Phrasea/Collection/CachedCollectionRepository.php b/lib/Alchemy/Phrasea/Collection/CachedCollectionRepository.php new file mode 100644 index 0000000000..fd918a53cd --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/CachedCollectionRepository.php @@ -0,0 +1,87 @@ +repository = $repository; + $this->cache = $cache; + $this->cacheKey = $cacheKey; + } + + /** + * @param int $databoxId + * @return \collection[] + */ + public function findAllByDatabox($databoxId) + { + $cacheKey = hash('sha256', $this->cacheKey . '.findAll.' . $databoxId); + $collections = $this->cache->fetch($cacheKey); + + if ($collections === false) { + $collections = $this->repository->findAllByDatabox($databoxId); + $this->save($cacheKey, $collections); + } + + return $collections; + } + + /** + * @param int $baseId + * @return \collection|null + */ + public function find($baseId) + { + $cacheKey = hash('sha256', $this->cacheKey . '.find.' . $baseId); + $collection = $this->cache->fetch($cacheKey); + + if ($collection === false) { + $collection = $this->repository->find($baseId); + $this->save($cacheKey, $collection); + } + + return $collection; + } + + /** + * @param int $databoxId + * @param int $collectionId + * @return \collection|null + */ + public function findByCollectionId($databoxId, $collectionId) + { + $cacheKey = hash('sha256', $this->cacheKey . '.findByCollection.' . $databoxId . $collectionId); + $collection = $this->cache->fetch($cacheKey); + + if ($collection === false) { + $collection = $this->repository->findByCollectionId($databoxId, $collectionId); + $this->save($cacheKey, $collection); + } + + return $collection; + } + + private function save($key, $value) + { + $this->cache->save($key, $value); + } +} diff --git a/lib/Alchemy/Phrasea/Collection/CollectionFactory.php b/lib/Alchemy/Phrasea/Collection/CollectionFactory.php new file mode 100644 index 0000000000..bd3963fc76 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/CollectionFactory.php @@ -0,0 +1,55 @@ +app = $application; + } + + /** + * @param CollectionReference $reference + * @param array $row + * @return \collection + */ + public function create(CollectionReference $reference, array $row) + { + return new \collection($this->app, $reference->getBaseId(), $reference, $row); + } + + /** + * @param CollectionReference[] $collectionReferences + * @param array $rows + * @return array + */ + public function createMany($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($indexedReferences[$row['coll_id']], $row); + } + + return $collections; + } +} diff --git a/lib/Alchemy/Phrasea/Collection/CollectionReference.php b/lib/Alchemy/Phrasea/Collection/CollectionReference.php new file mode 100644 index 0000000000..c5f51af7d4 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/CollectionReference.php @@ -0,0 +1,144 @@ +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; + } + + /** + * @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/CollectionReferenceRepository.php b/lib/Alchemy/Phrasea/Collection/CollectionReferenceRepository.php new file mode 100644 index 0000000000..0d4f92f037 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/CollectionReferenceRepository.php @@ -0,0 +1,30 @@ +connection = $connection; + } + + /** + * @return CollectionReference[] + */ + public function findAll() + { + return $this->createManyReferences($this->connection->fetchAll(self::$query)); + } + + /** + * @param int $databoxId + * @return CollectionReference[] + */ + public function findAllByDatabox($databoxId) + { + $query = self::$query . ' 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::$query . ' 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::$query . ' 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; + } + + /** + * @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/DbalCollectionRepository.php b/lib/Alchemy/Phrasea/Collection/DbalCollectionRepository.php new file mode 100644 index 0000000000..826894dcd3 --- /dev/null +++ b/lib/Alchemy/Phrasea/Collection/DbalCollectionRepository.php @@ -0,0 +1,107 @@ +connectionProvider = $connectionProvider; + $this->referenceRepository = $referenceRepository; + $this->collectionFactory = $collectionFactory; + } + + /** + * @param int $databoxId + * @return \collection[] + */ + public function findAllByDatabox($databoxId) + { + $references = $this->referenceRepository->findAllByDatabox($databoxId); + $connection = $this->connectionProvider->getConnection($databoxId); + + $params = []; + + foreach ($references as $reference) { + $params[':id_' . $reference->getCollectionId()] = $reference->getCollectionId(); + } + + $query = self::$query . sprintf(' WHERE coll_id IN (%s)', implode(', ', array_keys($params))); + $rows = $connection->fetchAll($query, $params); + + return $this->collectionFactory->createMany($references, $rows); + } + + /** + * @param int $baseId + * @return \collection|null + */ + public function find($baseId) + { + $reference = $this->referenceRepository->find($baseId); + + if ($reference === null) { + return null; + } + + $connection = $this->connectionProvider->getConnection($reference->getDataboxId()); + + $query = self::$query . ' WHERE coll_id = :collectionId'; + $row = $connection->fetchAssoc($query, [ ':collectionId' => $reference->getCollectionId() ]); + + if ($row !== false) { + return $this->collectionFactory->create($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; + } + + $connection = $this->connectionProvider->getConnection($databoxId); + + $query = self::$query . ' WHERE coll_id = :collectionId'; + $row = $connection->fetchAssoc($query, [ ':collectionId' => $reference->getCollectionId() ]); + + if ($row !== false) { + return $this->collectionFactory->create($row['baseId'], $reference, $row); + } + + return null; + } +} diff --git a/lib/Alchemy/Phrasea/Command/RecordAdd.php b/lib/Alchemy/Phrasea/Command/RecordAdd.php index 11369e3126..fd4c05c857 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 b90f181a08..f2944e783e 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 59aa532f05..b1c55ac100 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,7 +468,7 @@ 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) { @@ -522,7 +522,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->unmount_collection($this->app); @@ -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 d1f6e8789b..21dd1a9bf0 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php @@ -639,7 +639,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; diff --git a/lib/Alchemy/Phrasea/Controller/Admin/FeedController.php b/lib/Alchemy/Phrasea/Controller/Admin/FeedController.php index 33becac80e..95752a53a3 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 6c34c876a9..501b385f57 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/UserController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/UserController.php @@ -454,7 +454,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); @@ -472,7 +472,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; @@ -494,7 +494,7 @@ class UserController extends Controller $acceptColl = $denyColl = []; foreach ($bases as $bas => $isok) { - $collection = \collection::get_from_base_id($this->app, $bas); + $collection = \collection::getByBaseId($this->app, $bas); if ($isok) { $acceptColl[] = $collection->get_label($this->app['locale']); diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index a283220cd2..7229b5832a 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -798,7 +798,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( @@ -896,7 +896,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->get_base_id(); - $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::create($request, 403, sprintf( 'You do not have access to collection %s', $collection->get_label($this->app['locale.I18n']) @@ -1572,7 +1572,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(); @@ -2064,7 +2064,7 @@ class V1Controller extends Controller $this->app->abort(400, 'Request body does not contains a valid "story" object'); } - $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 e5f4a94e8b..4b33e4ab91 100644 --- a/lib/Alchemy/Phrasea/Controller/PermalinkController.php +++ b/lib/Alchemy/Phrasea/Controller/PermalinkController.php @@ -157,7 +157,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 fee6e9d70e..b45aafa6d6 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/StoryController.php b/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php index bd1cceadc4..1d335b7312 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 479fab824b..feddfd1095 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 eba11c0376..0edafb2690 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/AccountController.php +++ b/lib/Alchemy/Phrasea/Controller/Root/AccountController.php @@ -312,7 +312,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/Controller/Root/LoginController.php b/lib/Alchemy/Phrasea/Controller/Root/LoginController.php index dc67e1d3f4..8e58803f1f 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/LoginController.php +++ b/lib/Alchemy/Phrasea/Controller/Root/LoginController.php @@ -302,7 +302,7 @@ class LoginController extends Controller return; } - $collection = \collection::get_from_base_id($this->app, $baseId); + $collection = \collection::getByBaseId($this->app, $baseId); $registrationManipulator->createRegistration($user, $collection); $registrationsOK[$baseId] = $collection; }); diff --git a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php index 0038727dc9..d659a664fb 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 d58db4bb8d..ba279d2867 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php @@ -12,7 +12,12 @@ namespace Alchemy\Phrasea\Core\Provider; use Alchemy\Phrasea\Application as PhraseaApplication; +use Alchemy\Phrasea\Collection\CollectionFactory; +use Alchemy\Phrasea\Collection\DbalCollectionReferenceRepository; +use Alchemy\Phrasea\Collection\DbalCollectionRepository; +use Alchemy\Phrasea\Collection\CachedCollectionRepository; 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; @@ -138,6 +143,23 @@ class RepositoriesServiceProvider implements ServiceProviderInterface $app['repo.fields.factory'] = $app->protect(function (\databox $databox) use ($app) { return new DbalDataboxFieldRepository($databox->get_connection(), new DataboxFieldFactory($app, $databox)); }); + + $app['repo.collection-references'] = $app->share(function (PhraseaApplication $app) { + return new DbalCollectionReferenceRepository($app->getApplicationBox()->get_connection()); + }); + + $app['repo.collections'] = $app->share(function (PhraseaApplication $app) { + $appbox = $app->getApplicationBox(); + $factory = new CollectionFactory($app); + $connectionProvider = new DataboxConnectionProvider($appbox); + $repository = new DbalCollectionRepository( + $connectionProvider, + $app['repo.collection-references'], + $factory + ); + + return new CachedCollectionRepository($repository, $app['cache'], 'collection_'); + }); } 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 770433e307..8e528148e9 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 d05bfeec7c..bd3af97f0c 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 1f69fb1076..f9a5e43408 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 50ec3f127b..2adaca141c 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php +++ b/lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php @@ -480,7 +480,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; } @@ -571,7 +571,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 29376a82b6..5b4ef9c861 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php @@ -867,7 +867,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 { @@ -1200,7 +1200,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 b788ad8b08..6f4ff51027 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->bas_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 13b79f4727..723bea85f3 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 fbd87f10ef..8c41a56fa7 100644 --- a/lib/classes/ACL.php +++ b/lib/classes/ACL.php @@ -717,7 +717,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) { } @@ -1655,7 +1655,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 5934bfab2e..6df141463b 100644 --- a/lib/classes/appbox.php +++ b/lib/classes/appbox.php @@ -16,7 +16,6 @@ use Alchemy\Phrasea\Core\Version\AppboxVersionRepository; 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; @@ -257,9 +256,13 @@ class appbox extends base return $this->databoxes; } + /** + * @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'); diff --git a/lib/classes/collection.php b/lib/classes/collection.php index d3c7516f10..cefde0d517 100644 --- a/lib/classes/collection.php +++ b/lib/classes/collection.php @@ -10,6 +10,8 @@ */ use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Collection\CollectionReference; +use Alchemy\Phrasea\Collection\CollectionRepository; use Alchemy\Phrasea\Core\Event\Collection\CollectionEvent; use Alchemy\Phrasea\Core\Event\Collection\CollectionEvents; use Alchemy\Phrasea\Core\Event\Collection\CreatedEvent; @@ -23,125 +25,279 @@ use Symfony\Component\HttpFoundation\File\File; class collection implements cache_cacheableInterface, ThumbnailedElement { - 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) + private static $_logos = []; + private static $_stamps = []; + private static $_watermarks = []; + private static $_presentations = []; + private static $_collections = []; + + private static function getNewOrder(Connection $conn, $sbas_id) { - $this->app = $app; - $this->databox = $databox; - $this->sbas_id = (int) $databox->get_sbas_id(); - $this->coll_id = (int) $coll_id; - $this->load(); - - return $this; - } - - private function dispatch($eventName, CollectionEvent $event) - { - $this->app['dispatcher']->dispatch($eventName, $event); - } - - protected function load() - { - 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); + $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(); - if ( ! $row) - throw new Exception('Unknown collection ' . $this->coll_id . ' on ' . $this->databox->get_dbname()); + 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 + + +EOT; + + $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::getByCollectionId($app, $databox, $new_id); + + if (null !== $user) { + $collection->set_admin($new_bas, $user); + } + + $app['dispatcher']->dispatch(CollectionEvents::CREATED, new CreatedEvent($collection)); + + return $collection; + } + + 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()); + + $coll = self::getByBaseId($app, $new_bas); + $coll->set_admin($new_bas, $user); + + 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 static function purge() + { + self::$_collections = []; + } + + /** + * @param Application $app + * @param int $base_id + * @return collection + */ + public static function getByBaseId(Application $app, $base_id) + { + /** @var CollectionRepository $repository */ + $repository = $app['repo.collections']; + $collection = $repository->find($base_id); + + 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('Collection `' . $collection->get_base_id() . '` is not available here.'); + } + + 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)); + + /** @var CollectionRepository $repository */ + $repository = $app['repo.collections']; + $collection = $repository->findByCollectionId($databox->get_sbas_id(), $coll_id); + + 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('Collection `' . $collection->get_base_id() . '` is not available here.'); + } + + return $collection; + } + + /** + * @var CollectionReference + */ + protected $reference; + + /** + * @var string + */ + protected $name; + + /** + * @var string + */ + protected $preferences; + + /** + * @var string + */ + protected $pub_wm; + + /** + * @var string[] + */ + protected $labels = []; + + /** + * @var databox + */ + protected $databox; + + /** + * @var int[]|string + */ + protected $binary_logo; + + /** + * @var Application + */ + protected $app; + + public function __construct(Application $app, $baseId, CollectionReference $reference, array $row) + { + $this->app = $app; + $this->databox = $app->getApplicationBox()->get_databox($reference->getDataboxId()); + + $this->reference = $reference; + + $this->name = $row['asciiname']; $this->available = true; $this->pub_wm = $row['pub_wm']; - $this->name = $row['asciiname']; - $this->prefs = $row['prefs']; + $this->preferences = $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; + private function dispatch($eventName, CollectionEvent $event) + { + $this->app['dispatcher']->dispatch($eventName, $event); } public function enable(appbox $appbox) @@ -162,7 +318,7 @@ class collection implements cache_cacheableInterface, ThumbnailedElement public function get_ord() { - return $this->ord; + return $this->reference->getDisplayIndex(); } public function set_ord($ord) @@ -171,6 +327,8 @@ class collection implements cache_cacheableInterface, ThumbnailedElement $this->delete_data_from_cache(); $this->app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); + $this->reference->setDisplayIndex($ord); + return $this; } @@ -186,6 +344,8 @@ class collection implements cache_cacheableInterface, ThumbnailedElement $this->databox->delete_data_from_cache(databox::CACHE_COLLECTIONS); cache_databox::update($this->app, $this->databox->get_sbas_id(), 'structure'); + $this->reference->disable(); + return $this; } @@ -211,9 +371,12 @@ class collection implements cache_cacheableInterface, ThumbnailedElement return $this; } + /** + * @return bool + */ public function is_active() { - return $this->is_active; + return $this->reference->isActive(); } /** @@ -225,16 +388,26 @@ class collection implements cache_cacheableInterface, ThumbnailedElement return $this->databox; } + /** + * @return \Doctrine\DBAL\Connection + */ public function get_connection() { return $this->databox->get_connection(); } + /** + * @return int + */ public function getRootIdentifier() { - return $this->base_id; + return $this->reference->getBaseId(); } + /** + * @param string $thumbnailType + * @param File $file + */ public function updateThumbnail($thumbnailType, File $file = null) { switch ($thumbnailType) { @@ -254,7 +427,6 @@ class collection implements cache_cacheableInterface, ThumbnailedElement } } - public function set_public_presentation($publi) { if (in_array($publi, ['none', 'wm', 'stamp'])) { @@ -344,7 +516,6 @@ class collection implements cache_cacheableInterface, ThumbnailedElement 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 @@ -386,7 +557,6 @@ class collection implements cache_cacheableInterface, ThumbnailedElement public function reset_watermark() { - $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"'; @@ -403,7 +573,6 @@ class collection implements cache_cacheableInterface, ThumbnailedElement public function reset_stamp($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")'; @@ -463,81 +632,38 @@ class collection implements cache_cacheableInterface, ThumbnailedElement return $this->binary_logo; } - /** - * - * @param Application $app - * @param int $base_id - * @return collection - */ - 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; + return $this->reference->getBaseId(); } public function get_sbas_id() { - return $this->sbas_id; + return $this->reference->getDataboxId(); } public function get_coll_id() { - return $this->coll_id; + return $this->reference->getCollectionId(); } public function get_prefs() { - return $this->prefs; + return $this->preferences; } public function set_prefs(DOMDocument $dom) { - $this->prefs = $dom->saveXML(); + $this->preferences = $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->execute([':prefs' => $this->preferences, ':coll_id' => $this->get_coll_id()]); $stmt->closeCursor(); $this->delete_data_from_cache(); - return $this->prefs; + return $this->preferences; } public function get_name() @@ -592,73 +718,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) { @@ -687,86 +746,6 @@ class collection implements cache_cacheableInterface, ThumbnailedElement 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()); - - $coll = self::get_from_base_id($app, $new_bas); - $coll->set_admin($new_bas, $user); - - 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 : ''); @@ -787,11 +766,6 @@ class collection implements cache_cacheableInterface, ThumbnailedElement 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. * diff --git a/lib/classes/databox.php b/lib/classes/databox.php index c8e20e22f0..485e8f21d1 100644 --- a/lib/classes/databox.php +++ b/lib/classes/databox.php @@ -10,6 +10,7 @@ */ use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Collection\CollectionRepository; use Alchemy\Phrasea\Core\Connection\ConnectionSettings; use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Core\Version\DataboxVersionRepository; @@ -151,69 +152,30 @@ class databox extends base implements \Alchemy\Phrasea\Core\Thumbnail\Thumbnaile */ 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 CollectionRepository $collectionsRepository */ + $collectionsRepository = $this->app['repo.collections']; + $collections = $collectionsRepository->findAllByDatabox($this->get_sbas_id()); } - return $ret; + return $collections; } public function get_collection_unique_ids() { - static $base_ids; + static $collectionsIds; - if (isset($base_ids)) { - return $base_ids; - } + 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; - } - - 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; } /** diff --git a/lib/classes/patch/370alpha7a.php b/lib/classes/patch/370alpha7a.php index f728e2132b..ebd5145426 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/record/adapter.php b/lib/classes/record/adapter.php index 37b0cd18df..d155ab7ce9 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -300,7 +300,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 f1a9d3e801..5ad9553753 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Admin/AdminCollectionTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Admin/AdminCollectionTest.php @@ -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); } @@ -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/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 da52f18e1e..16b81f8710 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()); }