From 00f5f3369ef9f5c629e7fc4e5f19d94fd8d12cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Burnichon?= Date: Thu, 2 Jul 2015 20:28:15 +0200 Subject: [PATCH] Add DataboxRepository --- .../ControllerProvider/Admin/Databox.php | 9 - .../Core/Configuration/AccessRestriction.php | 20 +++ .../Provider/RepositoriesServiceProvider.php | 5 + .../Phrasea/Databox/DataboxRepository.php | 75 +++++++++ .../Databox/DataboxRepositoryInterface.php | 24 +++ lib/classes/appbox.php | 66 +++----- lib/classes/databox.php | 154 ++++++------------ .../Phrasea/Controller/Admin/DataboxTest.php | 3 +- .../Phrasea/Databox/DataboxRepositoryTest.php | 39 +++++ 9 files changed, 239 insertions(+), 156 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Databox/DataboxRepository.php create mode 100644 lib/Alchemy/Phrasea/Databox/DataboxRepositoryInterface.php create mode 100644 tests/Alchemy/Tests/Phrasea/Databox/DataboxRepositoryTest.php diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php b/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php index 18925ea9f9..8e86565166 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php @@ -142,13 +142,4 @@ class Databox implements ControllerProviderInterface, ServiceProviderInterface { $this->getFirewall($app)->requireRightOnSbas($request->attributes->get('databox_id'), 'bas_modify_struct'); } - - /** - * @param Application $app - * @return Firewall - */ - private function getFirewall(Application $app) - { - return $app['firewall']; - } } diff --git a/lib/Alchemy/Phrasea/Core/Configuration/AccessRestriction.php b/lib/Alchemy/Phrasea/Core/Configuration/AccessRestriction.php index 39e8445b5d..da168831f7 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/AccessRestriction.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/AccessRestriction.php @@ -14,6 +14,7 @@ namespace Alchemy\Phrasea\Core\Configuration; use Alchemy\Phrasea\Cache\Cache; use Alchemy\Phrasea\Model\Entities\Collection; use Alchemy\Phrasea\Model\Entities\Databox; +use Assert\Assertion; use Psr\Log\LoggerInterface; class AccessRestriction @@ -59,6 +60,25 @@ class AccessRestriction return in_array($databox->get_sbas_id(), $this->cache->fetch('available_databoxes'), true); } + /** + * @param \databox[] $databoxes + * @return \databox[] + */ + public function filterDataboxAvailable(array $databoxes) + { + Assertion::allIsInstanceOf($databoxes, \databox::class); + + if (!$this->isRestricted()) { + return $databoxes; + } + + $available = array_flip($this->cache->fetch('available_databoxes')); + + return array_filter($databoxes, function (\databox $databox) use ($available) { + return isset($available[$databox->get_sbas_id()]); + }); + } + /** * Returns true if a collection is available given a configuration. * diff --git a/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php index 7904b1d56d..479452809d 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/RepositoriesServiceProvider.php @@ -12,6 +12,7 @@ namespace Alchemy\Phrasea\Core\Provider; use Alchemy\Phrasea\Application as PhraseaApplication; +use Alchemy\Phrasea\Databox\DataboxRepository; use Silex\Application; use Silex\ServiceProviderInterface; @@ -121,6 +122,10 @@ class RepositoriesServiceProvider implements ServiceProviderInterface $app['repo.webhook-delivery'] = $app->share(function (PhraseaApplication $app) { return $app['orm.em']->getRepository('Phraseanet:WebhookEventDelivery'); }); + + $app['repo.databoxes'] = $app->share(function (PhraseaApplication $app) { + return new DataboxRepository($app, $app['phraseanet.appbox']); + }); } public function boot(Application $app) diff --git a/lib/Alchemy/Phrasea/Databox/DataboxRepository.php b/lib/Alchemy/Phrasea/Databox/DataboxRepository.php new file mode 100644 index 0000000000..74da41010d --- /dev/null +++ b/lib/Alchemy/Phrasea/Databox/DataboxRepository.php @@ -0,0 +1,75 @@ +app = $app; + $this->appbox = $appbox; + } + + /** + * @param int $id + * @return \databox|null + */ + public function find($id) + { + try { + $databox = new \databox($this->app, (int)$id); + } catch (NotFoundHttpException $exception) { + $databox = null; + } + + return $databox; + } + + /** + * @return \databox[] + */ + public function findAll() + { + try { + $rows = $this->appbox->get_data_from_cache(\appbox::CACHE_LIST_BASES); + if (!is_array($rows)) { + throw new \UnexpectedValueException('Expects rows to be an array'); + } + } catch(\Exception $e) { + $connection = $this->appbox->get_connection(); + + $query = 'SELECT sbas_id, ord, viewname, label_en, label_fr, label_de, label_nl FROM sbas'; + $statement = $connection->prepare($query); + $statement->execute(); + $rows = $statement->fetchAll(\PDO::FETCH_ASSOC); + $statement->closeCursor(); + + $this->appbox->set_data_to_cache($rows, \appbox::CACHE_LIST_BASES); + } + + $databoxes = array(); + + foreach ($rows as $row) { + $databox = new \databox($this->app, (int)$row['sbas_id'], $row); + + $databoxes[$databox->get_sbas_id()] = $databox; + } + + return $databoxes; + } +} diff --git a/lib/Alchemy/Phrasea/Databox/DataboxRepositoryInterface.php b/lib/Alchemy/Phrasea/Databox/DataboxRepositoryInterface.php new file mode 100644 index 0000000000..9d39b4576a --- /dev/null +++ b/lib/Alchemy/Phrasea/Databox/DataboxRepositoryInterface.php @@ -0,0 +1,24 @@ +databoxes) { - return $this->databoxes; + if (!$this->databoxes) { + $this->databoxes = $this->getAccessRestriction() + ->filterDataboxAvailable($this->getDataboxRepository()->findAll()); } - $ret = []; - foreach ($this->retrieve_sbas_ids() as $sbas_id) { - try { - $databox = new \databox($this->app, $sbas_id); - if (!$this->app['conf.restrictions']->isDataboxAvailable($databox)) { - continue; - } - $ret[$sbas_id] = $databox; - } catch (NotFoundHttpException $e) { - $this->app['monolog']->error(sprintf('Databox %s is not reliable.', $sbas_id)); - } - } - - $this->databoxes = $ret; - return $this->databoxes; } - protected function retrieve_sbas_ids() - { - try { - $data = $this->get_data_from_cache(self::CACHE_SBAS_IDS); - if (is_array($data)) { - return $data; - } - } catch (\Exception $e) { - - } - $sql = 'SELECT sbas_id FROM sbas'; - - $ret = []; - - $stmt = $this->get_connection()->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - foreach ($rs as $row) { - $ret[] = (int) $row['sbas_id']; - } - - $this->set_data_to_cache($ret, self::CACHE_SBAS_IDS); - - return $ret; - } - public function get_databox($sbas_id) { $databoxes = $this->get_databoxes(); @@ -436,4 +396,20 @@ class appbox extends base parent::delete_data_from_cache($option); } + + /** + * @return AccessRestriction + */ + private function getAccessRestriction() + { + return $this->app['conf.restrictions']; + } + + /** + * @return DataboxRepositoryInterface + */ + private function getDataboxRepository() + { + return $this->app['repo.databoxes']; + } } diff --git a/lib/classes/databox.php b/lib/classes/databox.php index 7ebb2d1768..8ca80d8a47 100644 --- a/lib/classes/databox.php +++ b/lib/classes/databox.php @@ -23,76 +23,29 @@ use Alchemy\Phrasea\Core\PhraseaTokens; class databox extends base { - /** - * - * @var int - */ + /** @var int */ protected $id; - - /** - * - * @var string - */ + /** @var string */ protected $structure; - - /** - * - * @var Array - */ + /** @var array */ protected static $_xpath_thesaurus = []; - - /** - * - * @var Array - */ + /** @var array */ protected static $_dom_thesaurus = []; - - /** - * - * @var Array - */ + /** @var array */ protected static $_thesaurus = []; - - /** - * - * @var Array - */ + /** @var array */ protected $_xpath_structure; - - /** - * - * @var DOMDocument - */ + /** @var DOMDocument */ protected $_dom_structure; - - /** - * - * @var DOMDocument - */ + /** @var DOMDocument */ protected $_dom_cterms; - - /** - * - * @var SimpleXMLElement - */ + /** @var SimpleXMLElement */ protected $_sxml_structure; - - /** - * - * @var databox_descriptionStructure - */ + /** @var databox_descriptionStructure */ protected $meta_struct; - - /** - * - * @var databox_subdefsStructure - */ + /** @var databox_subdefsStructure */ protected $subdef_struct; - - /** - * - * @var SimpleXMLElement - */ + /** @var SimpleXMLElement */ protected static $_sxml_thesaurus = []; const BASE_TYPE = self::DATA_BOX; @@ -107,13 +60,13 @@ class databox extends base private $labels = []; private $ord; private $viewname; - private $loaded = false; /** * @param Application $app * @param int $sbas_id + * @param array $row */ - public function __construct(Application $app, $sbas_id) + public function __construct(Application $app, $sbas_id, array $row = null) { assert(is_int($sbas_id)); assert($sbas_id > 0); @@ -140,20 +93,23 @@ class databox extends base $this->user = $params['user']; $this->passwd = $params['password']; $this->dbname = $params['dbname']; + + if (empty($row)) { + $row = $this->loadRow(); + } + $this->loadFromRow($row); } - private function load() + private function loadRow() { - if ($this->loaded) { - return; - } - try { $row = $this->get_data_from_cache(static::CACHE_BASE_DATABOX); + if (!is_array($row)) { + throw new UnexpectedValueException('Expects row to be an array'); + } } catch (\Exception $e) { - $sql = 'SELECT ord, viewname, label_en, label_fr, label_de, label_nl - FROM sbas WHERE sbas_id = :sbas_id'; - $stmt = $this->app->getApplicationBox()->get_connection()->prepare($sql); + $sql = 'SELECT ord, viewname, label_en, label_fr, label_de, label_nl FROM sbas WHERE sbas_id = :sbas_id'; + $stmt = $this->get_appbox()->get_connection()->prepare($sql); $stmt->execute(['sbas_id' => $this->id]); $row = $stmt->fetch(\PDO::FETCH_ASSOC); $stmt->closeCursor(); @@ -165,35 +121,24 @@ class databox extends base throw new NotFoundHttpException(sprintf('databox %d not found', $this->id)); } - $this->ord = $row['ord']; - $this->viewname = $row['viewname']; - $this->labels['fr'] = $row['label_fr']; - $this->labels['en'] = $row['label_en']; - $this->labels['de'] = $row['label_de']; - $this->labels['nl'] = $row['label_nl']; - - $this->loaded = true; + return $row; } public function get_viewname() { - $this->load(); - return $this->viewname ? : $this->dbname; } public function set_viewname($viewname) { - $this->load(); - $sql = 'UPDATE sbas SET viewname = :viewname WHERE sbas_id = :sbas_id'; - $stmt = $this->app->getApplicationBox()->get_connection()->prepare($sql); + $stmt = $this->get_appbox()->get_connection()->prepare($sql); $stmt->execute([':viewname' => $viewname, ':sbas_id' => $this->id]); $stmt->closeCursor(); $this->delete_data_from_cache(static::CACHE_BASE_DATABOX); - $this->app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); + $this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); cache_databox::update($this->app, $this->id, 'structure'); $this->viewname = $viewname; @@ -203,8 +148,6 @@ class databox extends base public function get_ord() { - $this->load(); - return $this->ord; } @@ -213,7 +156,7 @@ class databox extends base */ public function get_appbox() { - return $this->app['phraseanet.appbox']; + return $this->app->getApplicationBox(); } /** @@ -264,7 +207,7 @@ class databox extends base } - $conn = $this->app->getApplicationBox()->get_connection(); + $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 @@ -299,8 +242,6 @@ class databox extends base public function get_label($code, $substitute = true) { - $this->load(); - if (!array_key_exists($code, $this->labels)) { throw new InvalidArgumentException(sprintf('Code %s is not defined', $code)); } @@ -314,15 +255,13 @@ class databox extends base public function set_label($code, $label) { - $this->load(); - if (!array_key_exists($code, $this->labels)) { throw new InvalidArgumentException(sprintf('Code %s is not defined', $code)); } $sql = "UPDATE sbas SET label_$code = :label WHERE sbas_id = :sbas_id"; - $stmt = $this->app->getApplicationBox()->get_connection()->prepare($sql); + $stmt = $this->get_appbox()->get_connection()->prepare($sql); $stmt->execute([':label' => $label, ':sbas_id' => $this->id]); $stmt->closeCursor(); @@ -533,17 +472,17 @@ class databox extends base $stmt->closeCursor(); $sql = "DELETE FROM sbas WHERE sbas_id = :sbas_id"; - $stmt = $this->app->getApplicationBox()->get_connection()->prepare($sql); + $stmt = $this->get_appbox()->get_connection()->prepare($sql); $stmt->execute([':sbas_id' => $this->id]); $stmt->closeCursor(); $sql = "DELETE FROM sbasusr WHERE sbas_id = :sbas_id"; - $stmt = $this->app->getApplicationBox()->get_connection()->prepare($sql); + $stmt = $this->get_appbox()->get_connection()->prepare($sql); $stmt->execute([':sbas_id' => $this->id]); $stmt->closeCursor(); - $this->app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); - $this->app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_SBAS_IDS); + $this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); + $this->get_appbox()->delete_data_from_cache(appbox::CACHE_SBAS_IDS); return; } @@ -798,7 +737,7 @@ class databox extends base $stmt->execute(); $stmt->closeCursor(); - $this->app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); + $this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); return; } @@ -845,7 +784,7 @@ class databox extends base public function get_mountable_colls() { /** @var Connection $conn */ - $conn = $this->app->getApplicationBox()->get_connection(); + $conn = $this->get_appbox()->get_connection(); $colls = []; $sql = 'SELECT server_coll_id FROM bas WHERE sbas_id = :sbas_id'; @@ -888,7 +827,7 @@ class databox extends base public function get_activable_colls() { /** @var Connection $conn */ - $conn = $this->app->getApplicationBox()->get_connection(); + $conn = $this->get_appbox()->get_connection(); $base_ids = []; $sql = 'SELECT base_id FROM bas WHERE sbas_id = :sbas_id AND active = "0"'; @@ -932,7 +871,7 @@ class databox extends base $this->meta_struct = null; - $this->app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); + $this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES); $this->delete_data_from_cache(self::CACHE_STRUCTURE); $this->delete_data_from_cache(self::CACHE_META_STRUCT); @@ -1062,7 +1001,7 @@ class databox extends base */ public function registerAdmin(User $user) { - $conn = $this->app->getApplicationBox()->get_connection(); + $conn = $this->get_appbox()->get_connection(); $this->app->getAclForUser($user) ->give_access_to_sbas([$this->id]) @@ -1575,4 +1514,17 @@ class databox extends base return false; } + + /** + * @param array $row + */ + private function loadFromRow(array $row) + { + $this->ord = $row['ord']; + $this->viewname = $row['viewname']; + $this->labels['fr'] = $row['label_fr']; + $this->labels['en'] = $row['label_en']; + $this->labels['de'] = $row['label_de']; + $this->labels['nl'] = $row['label_nl']; + } } diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php index 715d0cd6e9..d202006e2a 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Admin/DataboxTest.php @@ -111,7 +111,8 @@ class DataboxTest extends \PhraseanetAuthenticatedWebTestCase $this->setAdmin(true); - $collection = \collection::create(self::$DI['app'], $databox, self::$DI['app']['phraseanet.appbox'], 'TESTTODELETE'); + $app = $this->getApplication(); + $collection = \collection::create($app, $databox, $app['phraseanet.appbox'], 'TESTTODELETE'); $this->XMLHTTPRequest('POST', '/admin/databox/' . $databox->get_sbas_id() . '/collections/order/', [ 'order' => [ diff --git a/tests/Alchemy/Tests/Phrasea/Databox/DataboxRepositoryTest.php b/tests/Alchemy/Tests/Phrasea/Databox/DataboxRepositoryTest.php new file mode 100644 index 0000000000..4910e25d0f --- /dev/null +++ b/tests/Alchemy/Tests/Phrasea/Databox/DataboxRepositoryTest.php @@ -0,0 +1,39 @@ +app = $this->prophesize(Application::class); + $this->appbox = $this->prophesize(\appbox::class); + + $this->sut = new DataboxRepository($this->app->reveal(), $this->appbox->reveal()); + } + + public function testItImplementsDataboxRepositoryInterface() + { + $this->assertInstanceOf(DataboxRepositoryInterface::class, $this->sut); + } +}