diff --git a/lib/Alchemy/Phrasea/Collection/CollectionRepository.php b/lib/Alchemy/Phrasea/Collection/CollectionRepository.php index aadf24148c..865ece521d 100644 --- a/lib/Alchemy/Phrasea/Collection/CollectionRepository.php +++ b/lib/Alchemy/Phrasea/Collection/CollectionRepository.php @@ -2,7 +2,7 @@ namespace Alchemy\Phrasea\Collection; -interface CollectionRepository +interface CollectionRepository { /** @@ -21,4 +21,10 @@ interface CollectionRepository * @return void */ public function save(Collection $collection); + + /** + * @param Collection $collection + * @return void + */ + public function delete(Collection $collection); } diff --git a/lib/Alchemy/Phrasea/Collection/CollectionRepositoryRegistry.php b/lib/Alchemy/Phrasea/Collection/CollectionRepositoryRegistry.php index 8aea2df32a..6acc5f0ee2 100644 --- a/lib/Alchemy/Phrasea/Collection/CollectionRepositoryRegistry.php +++ b/lib/Alchemy/Phrasea/Collection/CollectionRepositoryRegistry.php @@ -2,6 +2,7 @@ namespace Alchemy\Phrasea\Collection; +use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Collection\Reference\CollectionReferenceRepository; class CollectionRepositoryRegistry @@ -9,6 +10,11 @@ class CollectionRepositoryRegistry private $baseIdMap = null; + /** + * @var Application + */ + private $application; + /** * @var CollectionRepository[] */ @@ -25,13 +31,16 @@ class CollectionRepositoryRegistry private $repositoryFactory; /** + * @param Application $app * @param CollectionRepositoryFactory $collectionRepositoryFactory * @param CollectionReferenceRepository $referenceRepository */ public function __construct( + Application $app, CollectionRepositoryFactory $collectionRepositoryFactory, CollectionReferenceRepository $referenceRepository ) { + $this->application = $app; $this->repositoryFactory = $collectionRepositoryFactory; $this->referenceRepository = $referenceRepository; } @@ -70,6 +79,11 @@ class CollectionRepositoryRegistry public function purgeRegistry() { $this->baseIdMap = null; + + $appBox = $this->application->getApplicationBox(); + + \phrasea::reset_baseDatas($appBox); + \phrasea::reset_sbasDatas($appBox); } private function loadBaseIdMap() diff --git a/lib/Alchemy/Phrasea/Collection/CollectionService.php b/lib/Alchemy/Phrasea/Collection/CollectionService.php index 3707aa0157..6e75c87780 100644 --- a/lib/Alchemy/Phrasea/Collection/CollectionService.php +++ b/lib/Alchemy/Phrasea/Collection/CollectionService.php @@ -162,8 +162,6 @@ class CollectionService $stmt->execute([':base_id' => $reference->getBaseId()]); $stmt->closeCursor(); - $this->app['manipulator.registration']->deleteRegistrationsOnCollection($this); - return; } 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/CollectionReferenceRepository.php b/lib/Alchemy/Phrasea/Collection/Reference/CollectionReferenceRepository.php index b90b02e1de..48dbfc94f5 100644 --- a/lib/Alchemy/Phrasea/Collection/Reference/CollectionReferenceRepository.php +++ b/lib/Alchemy/Phrasea/Collection/Reference/CollectionReferenceRepository.php @@ -33,4 +33,10 @@ interface CollectionReferenceRepository * @return void */ public function save(CollectionReference $reference); + + /** + * @param CollectionReference $reference + * @return void + */ + public function delete(CollectionReference $reference); } diff --git a/lib/Alchemy/Phrasea/Collection/Reference/DbalCollectionReferenceRepository.php b/lib/Alchemy/Phrasea/Collection/Reference/DbalCollectionReferenceRepository.php index 63dd1eb06b..22ff361ed7 100644 --- a/lib/Alchemy/Phrasea/Collection/Reference/DbalCollectionReferenceRepository.php +++ b/lib/Alchemy/Phrasea/Collection/Reference/DbalCollectionReferenceRepository.php @@ -31,6 +31,8 @@ class DbalCollectionReferenceRepository implements CollectionReferenceRepository 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 */ @@ -126,6 +128,19 @@ class DbalCollectionReferenceRepository implements CollectionReferenceRepository } } + /** + * @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 diff --git a/lib/Alchemy/Phrasea/Collection/Repository/ArrayCacheCollectionRepository.php b/lib/Alchemy/Phrasea/Collection/Repository/ArrayCacheCollectionRepository.php index 45df2e1f6f..0373e02bf3 100644 --- a/lib/Alchemy/Phrasea/Collection/Repository/ArrayCacheCollectionRepository.php +++ b/lib/Alchemy/Phrasea/Collection/Repository/ArrayCacheCollectionRepository.php @@ -54,7 +54,16 @@ class ArrayCacheCollectionRepository implements CollectionRepository $this->collectionRepository->save($collection); if ($this->collectionCache !== null) { - $this->collectionCache = null; + $this->collectionCache[$collection->getCollectionId()] = $collection; + } + } + + 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 index 5dd84f7c53..a7a414aee4 100644 --- a/lib/Alchemy/Phrasea/Collection/Repository/CachedCollectionRepository.php +++ b/lib/Alchemy/Phrasea/Collection/Repository/CachedCollectionRepository.php @@ -96,6 +96,15 @@ final class CachedCollectionRepository implements CollectionRepository $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 index 0fe9827b06..860dcd1e5c 100644 --- a/lib/Alchemy/Phrasea/Collection/Repository/DbalCollectionRepository.php +++ b/lib/Alchemy/Phrasea/Collection/Repository/DbalCollectionRepository.php @@ -20,6 +20,8 @@ class DbalCollectionRepository implements CollectionRepository label_de = :labelDe, label_nl = :labelNl, prefs = :preferences, logo = :logo, majLogo = :logoTimestamp, pub_wm = :publicWatermark WHERE coll_id = :collectionId'; + private static $deleteQuery = 'DELETE FROM coll WHERE coll_id = :collectionId'; + /** * @var int */ @@ -150,4 +152,13 @@ class DbalCollectionRepository implements CollectionRepository $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/Core/Provider/RepositoriesServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php index 58bc0839a1..b8e3cffbd0 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php @@ -17,6 +17,7 @@ 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; @@ -150,7 +151,9 @@ class RepositoriesServiceProvider implements ServiceProviderInterface }); $app['repo.collection-references'] = $app->share(function (PhraseaApplication $app) { - return new DbalCollectionReferenceRepository($app->getApplicationBox()->get_connection()); + $repository = new DbalCollectionReferenceRepository($app->getApplicationBox()->get_connection()); + + return new ArrayCacheCollectionReferenceRepository($repository); }); $app['repo.collections-registry'] = $app->share(function (PhraseaApplication $app) { @@ -172,7 +175,7 @@ class RepositoriesServiceProvider implements ServiceProviderInterface $repositoryFactory = new ArrayCachedCollectionRepositoryFactory($repositoryFactory); - return new CollectionRepositoryRegistry($repositoryFactory, $app['repo.collection-references']); + return new CollectionRepositoryRegistry($app, $repositoryFactory, $app['repo.collection-references']); }); } diff --git a/lib/classes/collection.php b/lib/classes/collection.php index 9982b15bc0..269f8e79d1 100644 --- a/lib/classes/collection.php +++ b/lib/classes/collection.php @@ -302,6 +302,14 @@ class collection implements ThumbnailedElement ); } + /** + * @return CollectionVO + */ + public function getCollection() + { + return $this->collectionVO; + } + /** * @return CollectionReference */ @@ -642,6 +650,8 @@ class collection implements ThumbnailedElement $this->collectionService->delete($this->databox, $this->collectionVO, $this->reference); $this->getCollectionRepository()->delete($this->collectionVO); + + $this->app['manipulator.registration']->deleteRegistrationsOnCollection($this); $this->app['repo.collections-registry']->purgeRegistry(); } @@ -654,6 +664,8 @@ class collection implements ThumbnailedElement $this->collectionService->unmountCollection($this->reference); $this->getReferenceRepository()->delete($this->reference); + + $this->app['manipulator.registration']->deleteRegistrationsOnCollection($this); $this->app['repo.collections-registry']->purgeRegistry(); return $this; diff --git a/lib/classes/phrasea.php b/lib/classes/phrasea.php index 1b1f6faa83..c907c13ba6 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';