From 5a8d68844304d50ec26598fee29cc3e2551a40d3 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Tue, 11 Sep 2018 17:49:24 +0400 Subject: [PATCH 01/40] add max_item and page in api route search and stories --- .../Phrasea/Controller/Api/V1Controller.php | 26 ++++++++++++++++--- .../Databox/Record/LegacyRecordRepository.php | 8 +++++- .../Databox/Record/RecordRepository.php | 4 ++- lib/classes/record/adapter.php | 7 +++-- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index ff8764b0d9..00564fae53 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -29,6 +29,7 @@ use Alchemy\Phrasea\Border\Visa; use Alchemy\Phrasea\Cache\Cache; use Alchemy\Phrasea\Collection\Reference\CollectionReference; use Alchemy\Phrasea\Controller\Controller; +use Alchemy\Phrasea\ControllerProvider\Api\V1; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\Version; @@ -1178,7 +1179,8 @@ class V1Controller extends Controller $searchView = $this->buildSearchView( $result, $includeResolver->resolve($fractal), - $this->resolveSubdefUrlTTL($request) + $this->resolveSubdefUrlTTL($request), + $request ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1233,9 +1235,10 @@ class V1Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL + * @param Request $request * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, Request $request) { $references = new RecordReferenceCollection($result->getResults()); @@ -1253,6 +1256,12 @@ class V1Controller extends Controller $resultView = new SearchResultView($result); if ($stories->count() > 0) { + $storie_max_items = null; + + if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ + $storie_max_items = (int)$request->get('storie_max_items')?:10; + } + $user = $this->getAuthenticatedUser(); $children = []; @@ -1261,7 +1270,7 @@ class V1Controller extends Controller $selections = $this->findDataboxById($databoxId) ->getRecordRepository() - ->findChildren($storyIds, $user); + ->findChildren($storyIds, $user,0, $storie_max_items); $children[$databoxId] = array_combine($storyIds, $selections); } @@ -1631,6 +1640,15 @@ class V1Controller extends Controller return Result::createError($request, 404, 'Story not found')->createResponse(); } + $offset = 0; + $max_items = null; + if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ + $max_items = (int)$request->get('max_items')?:10; + $page = (int)$request->get('page')?:1; + + $offset = $max_items * ($page - 1); + } + $caption = $story->get_caption(); $format = function (\caption_record $caption, $dcField) { @@ -1672,7 +1690,7 @@ class V1Controller extends Controller 'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title), 'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type), ], - 'records' => $this->listRecords($request, array_values($story->getChildren()->get_elements())), + 'records' => $this->listRecords($request, array_values($story->getChildren($offset, $max_items)->get_elements())), ]; } diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 522d49baae..933cdbd6af 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -120,7 +120,7 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } - public function findChildren(array $storyIds, $user = null) + public function findChildren(array $storyIds, $user = null, $offset = 0, $max_items = null) { if (!$storyIds) { return []; @@ -147,6 +147,12 @@ class LegacyRecordRepository implements RecordRepository $this->addUserFilter($builder, $user); } + if($max_items){ + $builder->addOrderBy('s.ord', 'ASC') + ->setFirstResult($offset) + ->setMaxResults($max_items); + } + $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); $records = $this->mapRecordsFromResultSet($data); diff --git a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php index 0da49bb00f..fb91e05f1f 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php @@ -43,9 +43,11 @@ interface RecordRepository * * @param int[] $storyIds * @param null|int|User $user + * @param int $offset + * @param null|int $max_items * @return \set_selection[] */ - public function findChildren(array $storyIds, $user = null); + public function findChildren(array $storyIds, $user = null, $offset = 0, $max_items = null); /** diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index b647927717..33a9c7989e 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1677,17 +1677,20 @@ class record_adapter implements RecordInterface, cache_cacheableInterface } /** + * @param int $offset + * @param null|int $max_items + * * @return set_selection|record_adapter[] * @throws Exception * @throws \Doctrine\DBAL\DBALException */ - public function getChildren() + public function getChildren($offset = 0, $max_items = null) { if (!$this->isStory()) { throw new Exception('This record is not a grouping'); } - $selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()]); + $selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()], null, $offset, $max_items); return reset($selections); } From 5f72af4d4edd7e7e7523cdab3b55d27f358982ac Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Thu, 13 Sep 2018 10:37:35 +0400 Subject: [PATCH 02/40] update V1Controller --- .../Phrasea/Controller/Api/V1Controller.php | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 00564fae53..8508931781 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1180,7 +1180,7 @@ class V1Controller extends Controller $result, $includeResolver->resolve($fractal), $this->resolveSubdefUrlTTL($request), - $request + $this->getStorieMaxItems($request) ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1235,10 +1235,10 @@ class V1Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL - * @param Request $request + * @param int|null $storie_max_items * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, Request $request) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $storie_max_items = null) { $references = new RecordReferenceCollection($result->getResults()); @@ -1256,12 +1256,6 @@ class V1Controller extends Controller $resultView = new SearchResultView($result); if ($stories->count() > 0) { - $storie_max_items = null; - - if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ - $storie_max_items = (int)$request->get('storie_max_items')?:10; - } - $user = $this->getAuthenticatedUser(); $children = []; @@ -1360,6 +1354,21 @@ class V1Controller extends Controller return $resultView; } + /** + * @param Request $request + * @return int|null + */ + private function getStorieMaxItems(Request $request) + { + $storie_max_items = null; + + if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ + $storie_max_items = (int)$request->get('storie_max_items')?:10; + } + + return $storie_max_items; + } + /** * @param SearchEngineResult $result * @param string[] $includes From 5215e963552538804cb8fc490b4d74b9eb26c023 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Thu, 13 Sep 2018 17:21:34 +0400 Subject: [PATCH 03/40] change param name --- lib/Alchemy/Phrasea/Controller/Api/V1Controller.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 8508931781..e79a277d6e 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1235,10 +1235,10 @@ class V1Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL - * @param int|null $storie_max_items + * @param int|null $story_max_items * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $storie_max_items = null) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_items = null) { $references = new RecordReferenceCollection($result->getResults()); @@ -1264,7 +1264,7 @@ class V1Controller extends Controller $selections = $this->findDataboxById($databoxId) ->getRecordRepository() - ->findChildren($storyIds, $user,0, $storie_max_items); + ->findChildren($storyIds, $user,0, $story_max_items); $children[$databoxId] = array_combine($storyIds, $selections); } @@ -1360,13 +1360,13 @@ class V1Controller extends Controller */ private function getStorieMaxItems(Request $request) { - $storie_max_items = null; + $story_max_items = null; if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ - $storie_max_items = (int)$request->get('storie_max_items')?:10; + $story_max_items = (int)$request->get('story_max_items')?:10; } - return $storie_max_items; + return $story_max_items; } /** From e9beafef854c0ba12d7261615c41d2ebe00ce2e5 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Tue, 11 Sep 2018 17:49:24 +0400 Subject: [PATCH 04/40] add max_item and page in api route search and stories --- .../Phrasea/Controller/Api/V1Controller.php | 26 ++++++++++++++++--- .../Databox/Record/LegacyRecordRepository.php | 8 +++++- .../Databox/Record/RecordRepository.php | 4 ++- lib/classes/record/adapter.php | 7 +++-- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index ff8764b0d9..00564fae53 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -29,6 +29,7 @@ use Alchemy\Phrasea\Border\Visa; use Alchemy\Phrasea\Cache\Cache; use Alchemy\Phrasea\Collection\Reference\CollectionReference; use Alchemy\Phrasea\Controller\Controller; +use Alchemy\Phrasea\ControllerProvider\Api\V1; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\Version; @@ -1178,7 +1179,8 @@ class V1Controller extends Controller $searchView = $this->buildSearchView( $result, $includeResolver->resolve($fractal), - $this->resolveSubdefUrlTTL($request) + $this->resolveSubdefUrlTTL($request), + $request ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1233,9 +1235,10 @@ class V1Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL + * @param Request $request * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, Request $request) { $references = new RecordReferenceCollection($result->getResults()); @@ -1253,6 +1256,12 @@ class V1Controller extends Controller $resultView = new SearchResultView($result); if ($stories->count() > 0) { + $storie_max_items = null; + + if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ + $storie_max_items = (int)$request->get('storie_max_items')?:10; + } + $user = $this->getAuthenticatedUser(); $children = []; @@ -1261,7 +1270,7 @@ class V1Controller extends Controller $selections = $this->findDataboxById($databoxId) ->getRecordRepository() - ->findChildren($storyIds, $user); + ->findChildren($storyIds, $user,0, $storie_max_items); $children[$databoxId] = array_combine($storyIds, $selections); } @@ -1631,6 +1640,15 @@ class V1Controller extends Controller return Result::createError($request, 404, 'Story not found')->createResponse(); } + $offset = 0; + $max_items = null; + if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ + $max_items = (int)$request->get('max_items')?:10; + $page = (int)$request->get('page')?:1; + + $offset = $max_items * ($page - 1); + } + $caption = $story->get_caption(); $format = function (\caption_record $caption, $dcField) { @@ -1672,7 +1690,7 @@ class V1Controller extends Controller 'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title), 'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type), ], - 'records' => $this->listRecords($request, array_values($story->getChildren()->get_elements())), + 'records' => $this->listRecords($request, array_values($story->getChildren($offset, $max_items)->get_elements())), ]; } diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 522d49baae..933cdbd6af 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -120,7 +120,7 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } - public function findChildren(array $storyIds, $user = null) + public function findChildren(array $storyIds, $user = null, $offset = 0, $max_items = null) { if (!$storyIds) { return []; @@ -147,6 +147,12 @@ class LegacyRecordRepository implements RecordRepository $this->addUserFilter($builder, $user); } + if($max_items){ + $builder->addOrderBy('s.ord', 'ASC') + ->setFirstResult($offset) + ->setMaxResults($max_items); + } + $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); $records = $this->mapRecordsFromResultSet($data); diff --git a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php index 0da49bb00f..fb91e05f1f 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php @@ -43,9 +43,11 @@ interface RecordRepository * * @param int[] $storyIds * @param null|int|User $user + * @param int $offset + * @param null|int $max_items * @return \set_selection[] */ - public function findChildren(array $storyIds, $user = null); + public function findChildren(array $storyIds, $user = null, $offset = 0, $max_items = null); /** diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index b647927717..33a9c7989e 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1677,17 +1677,20 @@ class record_adapter implements RecordInterface, cache_cacheableInterface } /** + * @param int $offset + * @param null|int $max_items + * * @return set_selection|record_adapter[] * @throws Exception * @throws \Doctrine\DBAL\DBALException */ - public function getChildren() + public function getChildren($offset = 0, $max_items = null) { if (!$this->isStory()) { throw new Exception('This record is not a grouping'); } - $selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()]); + $selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()], null, $offset, $max_items); return reset($selections); } From a76c971ab1f5fe583bc8e054723b21ecd767a070 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Thu, 13 Sep 2018 10:37:35 +0400 Subject: [PATCH 05/40] update V1Controller --- .../Phrasea/Controller/Api/V1Controller.php | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 00564fae53..8508931781 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1180,7 +1180,7 @@ class V1Controller extends Controller $result, $includeResolver->resolve($fractal), $this->resolveSubdefUrlTTL($request), - $request + $this->getStorieMaxItems($request) ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1235,10 +1235,10 @@ class V1Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL - * @param Request $request + * @param int|null $storie_max_items * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, Request $request) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $storie_max_items = null) { $references = new RecordReferenceCollection($result->getResults()); @@ -1256,12 +1256,6 @@ class V1Controller extends Controller $resultView = new SearchResultView($result); if ($stories->count() > 0) { - $storie_max_items = null; - - if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ - $storie_max_items = (int)$request->get('storie_max_items')?:10; - } - $user = $this->getAuthenticatedUser(); $children = []; @@ -1360,6 +1354,21 @@ class V1Controller extends Controller return $resultView; } + /** + * @param Request $request + * @return int|null + */ + private function getStorieMaxItems(Request $request) + { + $storie_max_items = null; + + if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ + $storie_max_items = (int)$request->get('storie_max_items')?:10; + } + + return $storie_max_items; + } + /** * @param SearchEngineResult $result * @param string[] $includes From 9c5947701717f9de73bbce9f8cd42ebd6df0a5f3 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Thu, 13 Sep 2018 17:21:34 +0400 Subject: [PATCH 06/40] change param name --- lib/Alchemy/Phrasea/Controller/Api/V1Controller.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 8508931781..e79a277d6e 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1235,10 +1235,10 @@ class V1Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL - * @param int|null $storie_max_items + * @param int|null $story_max_items * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $storie_max_items = null) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_items = null) { $references = new RecordReferenceCollection($result->getResults()); @@ -1264,7 +1264,7 @@ class V1Controller extends Controller $selections = $this->findDataboxById($databoxId) ->getRecordRepository() - ->findChildren($storyIds, $user,0, $storie_max_items); + ->findChildren($storyIds, $user,0, $story_max_items); $children[$databoxId] = array_combine($storyIds, $selections); } @@ -1360,13 +1360,13 @@ class V1Controller extends Controller */ private function getStorieMaxItems(Request $request) { - $storie_max_items = null; + $story_max_items = null; if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ - $storie_max_items = (int)$request->get('storie_max_items')?:10; + $story_max_items = (int)$request->get('story_max_items')?:10; } - return $storie_max_items; + return $story_max_items; } /** From 5281bafe9589479853c751c4c02e619065d55c25 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Tue, 23 Oct 2018 18:11:21 +0400 Subject: [PATCH 07/40] fix api search pagination story --- .../Databox/Record/LegacyRecordRepository.php | 75 ++++++++++++++----- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 933cdbd6af..7b560a84a6 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -131,29 +131,66 @@ class LegacyRecordRepository implements RecordRepository $selects = $this->getRecordSelects(); array_unshift($selects, 's.rid_parent as story_id'); - $builder = $connection->createQueryBuilder(); - $builder - ->select($selects) - ->from('regroup', 's') - ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') - ->where( - 's.rid_parent IN (:storyIds)', - 'r.parent_record_id = 0' - ) - ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) - ; - - if (null !== $user) { - $this->addUserFilter($builder, $user); - } + $sql = null; + $params = []; + $types = []; if($max_items){ - $builder->addOrderBy('s.ord', 'ASC') - ->setFirstResult($offset) - ->setMaxResults($max_items); + + foreach($storyIds as $key => $storyId){ + $builder = $connection->createQueryBuilder(); + $builder + ->select($selects) + ->from('regroup', 's') + ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') + ->where( + 's.rid_parent = :storyId'.$key, + 'r.parent_record_id = 0' + ) + ->setParameter('storyId'.$key, $storyId) + ; + + if (null !== $user) { + $this->addUserFilter($builder, $user); + } + + $builder->addOrderBy('s.ord', 'ASC') + ->setFirstResult($offset) + ->setMaxResults($max_items); + + if(is_null($sql)){ + $sql = '('. $builder->getSQL() .')'; + }else{ + $sql = $sql. ' UNION ' . '('. $builder->getSQL(). ')'; + } + + $params = array_merge($params, $builder->getParameters()); + $types = array_merge($types, $builder->getParameterTypes()); + + } + + $data = $connection->fetchAll($sql, $params, $types); + + }else{ + $builder = $connection->createQueryBuilder(); + $builder + ->select($selects) + ->from('regroup', 's') + ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') + ->where( + 's.rid_parent IN (:storyIds)', + 'r.parent_record_id = 0' + ) + ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) + ; + + if (null !== $user) { + $this->addUserFilter($builder, $user); + } + + $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); } - $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); $records = $this->mapRecordsFromResultSet($data); $selections = array_map( From 103b8f7265a76fdd473baa35ac1eaeaf486d6ed3 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Wed, 24 Oct 2018 15:36:06 +0400 Subject: [PATCH 08/40] fix requete pagination --- .../Databox/Record/LegacyRecordRepository.php | 77 +++++-------------- 1 file changed, 20 insertions(+), 57 deletions(-) diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 7b560a84a6..1c90e9843f 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -129,68 +129,31 @@ class LegacyRecordRepository implements RecordRepository $connection = $this->databox->get_connection(); $selects = $this->getRecordSelects(); - array_unshift($selects, 's.rid_parent as story_id'); + array_unshift($selects, 's.rid_parent as story_id', 's.ord'); - $sql = null; - $params = []; - $types = []; + $builder = $connection->createQueryBuilder(); + $builder + ->select($selects) + ->from('regroup', 's') + ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') + ->where( + 's.rid_parent IN (:storyIds)', + 'r.parent_record_id = 0' + ) + ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) + ; + + if (null !== $user) { + $this->addUserFilter($builder, $user); + } if($max_items){ - - foreach($storyIds as $key => $storyId){ - $builder = $connection->createQueryBuilder(); - $builder - ->select($selects) - ->from('regroup', 's') - ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') - ->where( - 's.rid_parent = :storyId'.$key, - 'r.parent_record_id = 0' - ) - ->setParameter('storyId'.$key, $storyId) - ; - - if (null !== $user) { - $this->addUserFilter($builder, $user); - } - - $builder->addOrderBy('s.ord', 'ASC') - ->setFirstResult($offset) - ->setMaxResults($max_items); - - if(is_null($sql)){ - $sql = '('. $builder->getSQL() .')'; - }else{ - $sql = $sql. ' UNION ' . '('. $builder->getSQL(). ')'; - } - - $params = array_merge($params, $builder->getParameters()); - $types = array_merge($types, $builder->getParameterTypes()); - - } - - $data = $connection->fetchAll($sql, $params, $types); - - }else{ - $builder = $connection->createQueryBuilder(); - $builder - ->select($selects) - ->from('regroup', 's') - ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') - ->where( - 's.rid_parent IN (:storyIds)', - 'r.parent_record_id = 0' - ) - ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) - ; - - if (null !== $user) { - $this->addUserFilter($builder, $user); - } - - $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); + $builder->having('s.ord >= '. $offset .' and ord < '. ($offset + $max_items)) + ->addOrderBy('s.ord', 'ASC'); } + $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); + $records = $this->mapRecordsFromResultSet($data); $selections = array_map( From 415b0fcc275b26519b12c312408567a9e43c340c Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Wed, 24 Oct 2018 16:12:56 +0400 Subject: [PATCH 09/40] update --- lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 1c90e9843f..f480be4f8a 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -148,7 +148,7 @@ class LegacyRecordRepository implements RecordRepository } if($max_items){ - $builder->having('s.ord >= '. $offset .' and ord < '. ($offset + $max_items)) + $builder->having('s.ord >= '. $offset .' and s.ord < '. ($offset + $max_items)) ->addOrderBy('s.ord', 'ASC'); } From b407a17bdfbcc705f032a421aa2aa78e96705f80 Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Fri, 26 Oct 2018 18:01:31 +0400 Subject: [PATCH 10/40] change query --- .../Phrasea/Controller/Api/V1Controller.php | 4 +- .../Databox/Record/LegacyRecordRepository.php | 85 ++++++++++++++----- 2 files changed, 65 insertions(+), 24 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index e79a277d6e..a8edb45ab0 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1264,7 +1264,7 @@ class V1Controller extends Controller $selections = $this->findDataboxById($databoxId) ->getRecordRepository() - ->findChildren($storyIds, $user,0, $story_max_items); + ->findChildren($storyIds, $user,1, $story_max_items); $children[$databoxId] = array_combine($storyIds, $selections); } @@ -1655,7 +1655,7 @@ class V1Controller extends Controller $max_items = (int)$request->get('max_items')?:10; $page = (int)$request->get('page')?:1; - $offset = $max_items * ($page - 1); + $offset = $max_items * ($page - 1) + 1; } $caption = $story->get_caption(); diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index f480be4f8a..fedb07d965 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -120,7 +120,7 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } - public function findChildren(array $storyIds, $user = null, $offset = 0, $max_items = null) + public function findChildren(array $storyIds, $user = null, $offset = 1, $max_items = null) { if (!$storyIds) { return []; @@ -129,30 +129,71 @@ class LegacyRecordRepository implements RecordRepository $connection = $this->databox->get_connection(); $selects = $this->getRecordSelects(); - array_unshift($selects, 's.rid_parent as story_id', 's.ord'); - - $builder = $connection->createQueryBuilder(); - $builder - ->select($selects) - ->from('regroup', 's') - ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') - ->where( - 's.rid_parent IN (:storyIds)', - 'r.parent_record_id = 0' - ) - ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) - ; - - if (null !== $user) { - $this->addUserFilter($builder, $user); - } if($max_items){ - $builder->having('s.ord >= '. $offset .' and s.ord < '. ($offset + $max_items)) - ->addOrderBy('s.ord', 'ASC'); - } + array_unshift($selects, 'sr.rid_parent as story_id'); - $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); + $subBuilder = $connection->createQueryBuilder(); + + $subBuilder + ->select('s.*, + IF(@old_rid_parent != s.rid_parent, @cpt := 1, @cpt := @cpt+1) AS CPT') + ->addSelect("IF(@old_rid_parent != s.rid_parent, IF(@old_rid_parent:=s.rid_parent,'NEW PARENT',0), '----------') AS Y") + ->from('regroup', 's') + ->where('s.rid_parent IN (:storyIds)') + ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) + ->orderBy('s.rid_parent, s.ord') + ; + + $builder = $subBuilder->getConnection()->createQueryBuilder(); + + $builder->select($selects) + ->from(sprintf('( %s )', $subBuilder->getSQL()), 'sr') + ->innerJoin('sr', 'record', 'r', 'r.record_id = sr.rid_child') + ->where('sr.CPT BETWEEN :offset AND :maxresult') + ->andWhere('r.parent_record_id = 0') + ->setParameter('offset', $offset) + ->setParameter('maxresult', ($offset + $max_items -1)) + ->orderBy('story_id, sr.CPT') + ; + + if (null !== $user) { + $this->addUserFilter($builder, $user); + } + + $connection->executeQuery('SET @cpt = 1'); + + $connection->executeQuery('SET @old_rid_parent = -1'); + + + $data = $connection->fetchAll( + $builder->getSQL(), + array_merge($subBuilder->getParameters(), $builder->getParameters()), + array_merge($subBuilder->getParameterTypes(), $builder->getParameterTypes()) + ); + + }else{ + array_unshift($selects, 's.rid_parent as story_id'); + + $builder = $connection->createQueryBuilder(); + + $builder + ->select($selects) + ->from('regroup', 's') + ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') + ->where( + 's.rid_parent IN (:storyIds)', + 'r.parent_record_id = 0' + ) + ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) + ; + + if (null !== $user) { + $this->addUserFilter($builder, $user); + } + + $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); + } $records = $this->mapRecordsFromResultSet($data); From 17800bc33c3f2ed1ddf3d2e31bde42295b73cefb Mon Sep 17 00:00:00 2001 From: aina-esokia Date: Fri, 26 Oct 2018 18:12:07 +0400 Subject: [PATCH 11/40] do the pagination for all accept header --- .../Phrasea/Controller/Api/V1Controller.php | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index a8edb45ab0..954e8df6d1 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1180,7 +1180,7 @@ class V1Controller extends Controller $result, $includeResolver->resolve($fractal), $this->resolveSubdefUrlTTL($request), - $this->getStorieMaxItems($request) + (int)$request->get('story_max_items')?:10 ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1354,21 +1354,6 @@ class V1Controller extends Controller return $resultView; } - /** - * @param Request $request - * @return int|null - */ - private function getStorieMaxItems(Request $request) - { - $story_max_items = null; - - if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ - $story_max_items = (int)$request->get('story_max_items')?:10; - } - - return $story_max_items; - } - /** * @param SearchEngineResult $result * @param string[] $includes @@ -1649,14 +1634,10 @@ class V1Controller extends Controller return Result::createError($request, 404, 'Story not found')->createResponse(); } - $offset = 0; - $max_items = null; - if($request->getAcceptableContentTypes() == V1::$extendedContentTypes['json']){ - $max_items = (int)$request->get('max_items')?:10; - $page = (int)$request->get('page')?:1; + $max_items = (int)$request->get('max_items')?:10; + $page = (int)$request->get('page')?:1; - $offset = $max_items * ($page - 1) + 1; - } + $offset = $max_items * ($page - 1) + 1; $caption = $story->get_caption(); From c9356ec206641f3362b9ec0981c2a68f3b4489b5 Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 28 Nov 2019 18:15:55 +0400 Subject: [PATCH 12/40] max_items depends on header application/vnd.phraseanet.story-paginate --- .../Application/ApiApplicationLoader.php | 3 ++- .../Phrasea/Controller/Api/V1Controller.php | 19 ++++++++++++++----- .../Phrasea/ControllerProvider/Api/V1.php | 2 ++ .../Databox/Record/RecordRepository.php | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php index 490554c95e..c2f1a4da3b 100644 --- a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php +++ b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php @@ -51,7 +51,8 @@ class ApiApplicationLoader extends BaseApplicationLoader ['application/json', 'application/yaml', 'text/yaml', 'text/javascript', 'application/javascript'], V1::$extendedContentTypes['json'], V1::$extendedContentTypes['jsonp'], - V1::$extendedContentTypes['yaml'] + V1::$extendedContentTypes['yaml'], + [V1::HEADER_ACCEPT_STORY_PAGINATE] ); $app['phraseanet.content-negotiation.custom_formats'] = [ diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 7b41bf7f64..dacb48f539 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1217,12 +1217,18 @@ class V1Controller extends Controller $fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher'])); $fractal->parseIncludes($this->resolveSearchIncludes($request)); + $story_max_items = null; + // if the header accept story paginate, take account story_max_items parameter + if (in_array(V1::HEADER_ACCEPT_STORY_PAGINATE, $request->getAcceptableContentTypes())) { + $story_max_items = (int)$request->get('story_max_items') ?: 10; + } + $result = $this->doSearch($request); $searchView = $this->buildSearchView( $result, $includeResolver->resolve($fractal), $this->resolveSubdefUrlTTL($request), - (int)$request->get('story_max_items')?:10 + $story_max_items ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1676,10 +1682,13 @@ class V1Controller extends Controller return Result::createError($request, 404, 'Story not found')->createResponse(); } - $max_items = (int)$request->get('max_items')?:10; - $page = (int)$request->get('page')?:1; - - $offset = $max_items * ($page - 1) + 1; + $offset = 1; + $max_items = null; + if (in_array(V1::HEADER_ACCEPT_STORY_PAGINATE, $request->getAcceptableContentTypes())) { + $max_items = (int)$request->get('max_items')?:10; + $page = (int)$request->get('page')?:1; + $offset = ($max_items * ($page - 1)) + 1; + } $caption = $story->get_caption(); diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php b/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php index d64689eca2..597e34aec7 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php @@ -25,6 +25,8 @@ class V1 extends Api implements ControllerProviderInterface, ServiceProviderInte { const VERSION = '2.0.0'; + const HEADER_ACCEPT_STORY_PAGINATE = 'application/vnd.phraseanet.story-paginate'; + public static $extendedContentTypes = [ 'json' => ['application/vnd.phraseanet.record-extended+json'], 'yaml' => ['application/vnd.phraseanet.record-extended+yaml'], diff --git a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php index fb91e05f1f..870339a238 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php @@ -47,7 +47,7 @@ interface RecordRepository * @param null|int $max_items * @return \set_selection[] */ - public function findChildren(array $storyIds, $user = null, $offset = 0, $max_items = null); + public function findChildren(array $storyIds, $user = null, $offset = 1, $max_items = null); /** From cac34cc3a4856dcc0ab6587a98f7fd9f3e1e17e5 Mon Sep 17 00:00:00 2001 From: aynsix Date: Mon, 2 Dec 2019 16:34:49 +0400 Subject: [PATCH 13/40] add libfdk_aac and change presets name --- .../Controller/Admin/SubdefsController.php | 48 +++++++++---------- lib/Alchemy/Phrasea/Media/Subdef/Video.php | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php index e30aa03946..02039f0860 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php @@ -354,7 +354,7 @@ class SubdefsController extends Controller Subdef::TYPE_VIDEO => [ "definitions" => [ "video codec H264" => null, - "144P H264 128 kbps ACC 128kbps" => [ + "144P H264 128 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "128", @@ -362,10 +362,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "256", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "240P H264 256 kbps ACC 128kbps" => [ + "240P H264 256 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "256", @@ -373,10 +373,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "426", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "360P H264 576 kbps ACC 128kbps" => [ + "360P H264 576 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "576", @@ -384,10 +384,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "480", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libtheora", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "480P H264 750 kbps ACC 128kbps" => [ + "480P H264 750 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "750", @@ -395,10 +395,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "854", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "720P H264 1492 kbps ACC 128kbps" => [ + "720P H264 1492 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "1492", @@ -406,10 +406,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1280", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "1080P H264 2420 kbps ACC 128kbps" => [ + "1080P H264 2420 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "2420", @@ -417,11 +417,11 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1920", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], "video codec libvpx" => null, - "144P webm 128 kbps ACC 128kbps" => [ + "144P webm 128 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "128", @@ -429,10 +429,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "256", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "240P webm 256 kbps ACC 128kbps" => [ + "240P webm 256 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "256", @@ -440,10 +440,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "426", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "360P webm 576 kbps ACC 128kbps" => [ + "360P webm 576 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "576", @@ -451,10 +451,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "480", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "480P webm 750 kbps ACC 128kbps" => [ + "480P webm 750 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "750", @@ -462,10 +462,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "854", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "720P webm 1492 kbps ACC 128kbps" => [ + "720P webm 1492 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "1492", @@ -473,10 +473,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1280", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "1080P webm 2420 kbps ACC 128kbps" => [ + "1080P webm 2420 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "2420", @@ -484,7 +484,7 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1920", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], ], diff --git a/lib/Alchemy/Phrasea/Media/Subdef/Video.php b/lib/Alchemy/Phrasea/Media/Subdef/Video.php index ef0a113564..1b0ce097b0 100644 --- a/lib/Alchemy/Phrasea/Media/Subdef/Video.php +++ b/lib/Alchemy/Phrasea/Media/Subdef/Video.php @@ -33,7 +33,7 @@ class Video extends Audio $this->registerOption(new OptionType\Range($this->translator->trans('Frame Rate'), self::OPTION_FRAMERATE, 1, 200, 20)); $this->registerOption(new OptionType\Enum($this->translator->trans('Video Codec'), self::OPTION_VCODEC, ['libx264', 'libvpx', 'libtheora'], 'libx264')); $this->unregisterOption(self::OPTION_ACODEC); - $this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis'], 'libfaac')); + $this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis', 'libfdk_aac'], 'libfdk_aac')); } public function getType() From c691be541cf0fbec0d29b61087982a77f86ec7bc Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Tue, 3 Dec 2019 18:05:01 +0400 Subject: [PATCH 14/40] PHRAS-2848 #comment Lightbox mobile design refacto #time 8h --- .../jquery-mobile/_jquery-validator.scss | 194 ++++++++++++++---- templates/mobile/common/menubar.html.twig | 8 +- templates/mobile/lightbox/index.html.twig | 26 ++- 3 files changed, 171 insertions(+), 57 deletions(-) diff --git a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss index 7f49c0af1c..a64f197f32 100644 --- a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss +++ b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss @@ -1,30 +1,34 @@ $iconsPath: '../../../assets/common/images/icons/'; - -ul.image_set{ - padding:0; - margin:0; - border:none; - width:100%; - border:none; +$feedbackColor : #8bc34a; +$basketColor : #2196f3 ; +ul.image_set { + padding: 0; + margin: 0; + border: none; + width: 100%; + border: none; list-style-type: none; display: flex; flex-wrap: wrap; } -li.image_box a img{ - position:relative; - border:none; - width: auto!important; - height: 100% !important; + +li.image_box a img { + position: relative; + border: none; + width: auto !important; + height: 100% !important; top: 0 !important; object-fit: contain; } -li.image_box a{ - padding:0; - text-shadow:0; - margin:0; + +li.image_box a { + padding: 0; + text-shadow: 0; + margin: 0; width: 100%; } -li.image_box{ + +li.image_box { width: 18%; position: relative; margin: 0 2.5% 15px 0; @@ -38,19 +42,20 @@ li.image_box{ } .thumb_wrapper { background: #ededed; - width: 100%!important; - height: 160px!important; + width: 100% !important; + height: 160px !important; @media screen and (max-width: 767px) { - height: 130px !important; + height: 130px !important; } } } + @media screen and (max-width: 767px) { - li.image_box{ + li.image_box { width: 32%; margin: 0 2% 15px 0; &:nth-child(5n) { - margin-right: 2% ; + margin-right: 2%; } &:nth-child(3n) { margin-right: 0; @@ -58,35 +63,37 @@ li.image_box{ } } -a.no.active_choice{ - background-color:red; +a.no.active_choice { + background-color: red; color: #fff; } -a.active_choice{ + +a.active_choice { background-color: #53b401; color: #fff; } -.valid_choice{ - position:absolute; - bottom:0; - right:0; - width:16px; - height:16px; - z-index:2; +.valid_choice { + position: absolute; + bottom: 0; + right: 0; + width: 16px; + height: 16px; + z-index: 2; } -.valid_choice.agree{ +.valid_choice.agree { background: #7ed321; border-top-left-radius: 100px; } -.valid_choice.disagree{ + +.valid_choice.disagree { background: #d0021b; border-top-left-radius: 100px; } .thumb_wrapper { - text-align:center; + text-align: center; } @media screen and (orientation: landscape) { @@ -109,21 +116,120 @@ a.active_choice{ font-size: 18px; } - -.ui-listview .ui-li-has-thumb .ui-li-thumb, .ui-listview .ui-li-has-thumb>.ui-btn>img:first-child, .ui-listview .ui-li-has-thumb>img:first-child { +.ui-listview .ui-li-has-thumb .ui-li-thumb, .ui-listview .ui-li-has-thumb > .ui-btn > img:first-child, .ui-listview .ui-li-has-thumb > img:first-child { top: 50%; transform: translateY(-50%); } /*user status*/ .menu-bar-item { - background: #000; - padding: 12px; - text-align: center; - a { - color: #fff!important; - text-decoration: none!important; - font-weight: normal; + background: #f0f0f0; + padding: 12px 15px; + text-align: left; + position: relative; + .icomoon { + font-size: 17px; + position: absolute; + left: 23px; + top: 50%; + transform: translateY(-50%); + } + .ui-link { + color: #4f4f4f !important; + text-decoration: none !important; + .text { + padding-left: 31px; + color: #4f4f4f !important; + text-decoration: none !important; + font-weight: 700; + font-size: 13px; + } } } +/*new design of lightbox*/ +/*main nav */ +#lightbox-menu { + li { + margin-bottom: 30px; + .ui-li-count { + border-radius: 3px !important; + border-top-left-radius: 0 !important; + border-bottom-left-radius: 0 !important; + border: 0; + color: #fff; + text-shadow: none; + padding: 18px 23px; + top: 0; + right: 0; + margin: 0; + font-size: 22px; + min-width: 25px; + background: $feedbackColor; + } + &.ui-first-child { + margin-top: 15px; + } + &.ui-last-child { + a { + &:before { + background: $basketColor; + } + &:hover, &:active, &:focus { + color: $basketColor; + } + } + .ui-li-count { + background: $basketColor; + } + } + + } + a { + padding: 22px 25px; + font-size: 20px; + border-radius: 3px !important; + box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.19); + background-color: #eeeeee; + &:hover, &:active, &:focus { + color: $feedbackColor; + } + &:after { + content: none !important; + } + &:before { + content: ""; + position: absolute; + display: block; + width: 100%; + height: 4px; + bottom: 0; + background: $feedbackColor; + left: 0; + border-radius: 3px; + } + } +} + +.lightbox-bottom-btn { + margin-top: 50px; + .ui-btn { + font-size: 15px; + } +} +#validation, #basket { + .ui-content { + padding-left: 0; + padding-right: 0; + } +} +.basket-title { + background: $feedbackColor; + padding: 12px 30px; + font-size: 17px; + margin: 0; + text-shadow: none; + color: #fff; + font-weight: 700; +} + diff --git a/templates/mobile/common/menubar.html.twig b/templates/mobile/common/menubar.html.twig index 03a41053f7..d8190dd5fa 100644 --- a/templates/mobile/common/menubar.html.twig +++ b/templates/mobile/common/menubar.html.twig @@ -3,13 +3,13 @@ {% if app.getAuthenticator().isAuthenticated() %} diff --git a/templates/mobile/lightbox/index.html.twig b/templates/mobile/lightbox/index.html.twig index a270116c9c..418df10caa 100644 --- a/templates/mobile/lightbox/index.html.twig +++ b/templates/mobile/lightbox/index.html.twig @@ -44,17 +44,17 @@ {% include 'common/menubar.html.twig' %}
-
    -
  • + - @@ -89,15 +89,19 @@
    {{ 'Back' | trans }} -

    {{ 'Validations' | trans }}

    +

    {{ module_name }}

    -

    - {{ 'Voici vos validations en cours' | trans }} -

    +

    + {{ 'Validations' | trans }} + {{_self.valid_baskets_length(baskets_collection)}} +

    +

    + {{ 'Voici vos validations en cours' | trans }} +

      {% for basket in baskets_collection | sort | reverse%} {% if basket.getValidation() %} @@ -122,12 +126,16 @@
      {{ 'Back' | trans }} -

      {{ 'Paniers' | trans }}

      +

      {{module_name}}

      +

      + {{ 'Paniers' | trans }} + {{_self.baskets_length(baskets_collection)}} +

      {{ 'Voici vos paniers' | trans }}

      From 530397db007f3e03f4d994dcd2800087355b9fc9 Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 4 Dec 2019 10:17:59 +0400 Subject: [PATCH 15/40] do no use header application/vnd.phraseanet.story-paginate --- .../Application/ApiApplicationLoader.php | 3 +-- .../Phrasea/Controller/Api/V1Controller.php | 18 ++++-------------- .../Phrasea/ControllerProvider/Api/V1.php | 2 -- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php index c2f1a4da3b..490554c95e 100644 --- a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php +++ b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php @@ -51,8 +51,7 @@ class ApiApplicationLoader extends BaseApplicationLoader ['application/json', 'application/yaml', 'text/yaml', 'text/javascript', 'application/javascript'], V1::$extendedContentTypes['json'], V1::$extendedContentTypes['jsonp'], - V1::$extendedContentTypes['yaml'], - [V1::HEADER_ACCEPT_STORY_PAGINATE] + V1::$extendedContentTypes['yaml'] ); $app['phraseanet.content-negotiation.custom_formats'] = [ diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index dacb48f539..cb2523e1ae 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1217,18 +1217,12 @@ class V1Controller extends Controller $fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher'])); $fractal->parseIncludes($this->resolveSearchIncludes($request)); - $story_max_items = null; - // if the header accept story paginate, take account story_max_items parameter - if (in_array(V1::HEADER_ACCEPT_STORY_PAGINATE, $request->getAcceptableContentTypes())) { - $story_max_items = (int)$request->get('story_max_items') ?: 10; - } - $result = $this->doSearch($request); $searchView = $this->buildSearchView( $result, $includeResolver->resolve($fractal), $this->resolveSubdefUrlTTL($request), - $story_max_items + (int)$request->get('story_max_items') ?: 10 ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1682,13 +1676,9 @@ class V1Controller extends Controller return Result::createError($request, 404, 'Story not found')->createResponse(); } - $offset = 1; - $max_items = null; - if (in_array(V1::HEADER_ACCEPT_STORY_PAGINATE, $request->getAcceptableContentTypes())) { - $max_items = (int)$request->get('max_items')?:10; - $page = (int)$request->get('page')?:1; - $offset = ($max_items * ($page - 1)) + 1; - } + $max_items = (int)$request->get('max_items')?:10; + $page = (int)$request->get('page')?:1; + $offset = ($max_items * ($page - 1)) + 1; $caption = $story->get_caption(); diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php b/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php index 597e34aec7..d64689eca2 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Api/V1.php @@ -25,8 +25,6 @@ class V1 extends Api implements ControllerProviderInterface, ServiceProviderInte { const VERSION = '2.0.0'; - const HEADER_ACCEPT_STORY_PAGINATE = 'application/vnd.phraseanet.story-paginate'; - public static $extendedContentTypes = [ 'json' => ['application/vnd.phraseanet.record-extended+json'], 'yaml' => ['application/vnd.phraseanet.record-extended+yaml'], From 2960ba8d848ac8c4258fe0aea0b3d0393c042d4c Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Wed, 4 Dec 2019 10:46:46 +0400 Subject: [PATCH 16/40] PHRAS-2375 #comment fix prod Roll over PDF #time 1h --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 31a385774f..e909dbb2ab 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "normalize-css": "^2.1.0", "npm": "^6.0.0", "npm-modernizr": "^2.8.3", - "phraseanet-production-client": "0.34.82-d", + "phraseanet-production-client": "0.34.84-d", "requirejs": "^2.3.5", "tinymce": "^4.0.28", "underscore": "^1.8.3", diff --git a/yarn.lock b/yarn.lock index e393792080..4d9806aeaa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7565,10 +7565,10 @@ phantomjs-prebuilt@^2.1.3: request-progress "^2.0.1" which "^1.2.10" -phraseanet-common@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/phraseanet-common/-/phraseanet-common-0.4.2.tgz#740de9bf254116adc506c9703015ab1533f89864" - integrity sha512-uyKULVCV9df161A970mWnZtdxAb/ZWCuUdnSTn0T9AGvwsWvKf2p6+pgEVtBQ81LIGn1m5UlhiF7dUlc6nT7iQ== +phraseanet-common@^0.4.5-d: + version "0.4.5-d" + resolved "https://registry.yarnpkg.com/phraseanet-common/-/phraseanet-common-0.4.5-d.tgz#193da1ab062f98e99729b7f98a7bbe32c495c7f3" + integrity sha512-7mmPDg0pFnFYyY1eazmUcDa18SGXp90zEBYTNzVan6goPPBjUmA0YwzBiuvDnxlcwMX8x0kDIrOouOBfWG5E1w== dependencies: es6-promise "^4.1.1" humane-js "^3.2.2" @@ -7577,10 +7577,10 @@ phraseanet-common@^0.4.1: js-cookie "^2.1.0" pym.js "^1.3.1" -phraseanet-production-client@0.34.82-d: - version "0.34.82-d" - resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.82-d.tgz#904f649ae4164c38b8f3a36be0bf33d98b99f739" - integrity sha512-pofcyCNGbR/esbTxMkUGyn1M70PSsgcon/ZHRB6iHgFtgQKa4XUpDceGEtQqjMFPwB85d4sO8m9hgkLlC0pdIQ== +phraseanet-production-client@0.34.84-d: + version "0.34.84-d" + resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.84-d.tgz#ccf091b51209c6d42fd3dc1e4f05f6bbefe44ea5" + integrity sha512-ZZZOIR7a+4AVwkx0s3e3P23sobQjWVFXrX3FnB6BhEC3qpR0b44bH1Dc7n53ciL5UQMmTNUNYoVTMpMfHpNrFA== dependencies: "@mapbox/mapbox-gl-language" "^0.9.2" "@turf/turf" "^5.1.6" @@ -7611,7 +7611,7 @@ phraseanet-production-client@0.34.82-d: mapbox-gl-circle "^1.6.5" mapbox.js "^2.4.0" nouislider "^9.2.0" - phraseanet-common "^0.4.1" + phraseanet-common "^0.4.5-d" pym.js "^1.3.1" rx "^4.1.0" sprintf-js "^1.1.1" From 3b8edf8e671fcef3c21d3b5a4db1231c6f13b918 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Wed, 4 Dec 2019 17:24:12 +0400 Subject: [PATCH 17/40] PHRAS-2848 --- .../jquery-mobile/_jquery-validator.scss | 82 ++++++++++++++++++- templates/mobile/lightbox/index.html.twig | 72 ++++++++-------- 2 files changed, 121 insertions(+), 33 deletions(-) diff --git a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss index a64f197f32..4edfa60d29 100644 --- a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss +++ b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss @@ -217,7 +217,7 @@ a.active_choice { font-size: 15px; } } -#validation, #basket { +#validation, #baskets { .ui-content { padding-left: 0; padding-right: 0; @@ -231,5 +231,85 @@ a.active_choice { text-shadow: none; color: #fff; font-weight: 700; + #baskets & { + background: $basketColor; + } + span { + float: right; + } } +.feed-list { + li { + height: 71px; + padding-left: 109px!important; + padding-right: 80px!important; + border-color: #d4d4d4!important; + } + .lightbox-img { + width: 90px; + height: 90px; + background-color: #ededed; + position: absolute; + left: 0; + top: 0; + display: flex; + flex-wrap: wrap; + img { + display: flex; + align-items: center; + max-width: 100%; + max-height: 100%; + object-fit: contain; + } + } + h3 { + display: flex!important; + align-items: center; + height: 71px; + margin: 0!important; + font-size: 15px; + font-weight: bold!important; + a { + position: relative; + color: #313131!important; + width: 100%; + &:after { + content: "\e96c"; + font-family: icomoon; + position: absolute; + right: 0; + font-size: 20px; + line-height: 1; + top: 50%; + transform: translateY(-50%); + } + } + + } + span { + font-size: 17px; + color: #fff!important; + display: inline-block; + text-shadow: none!important; + top: 0; + width: 52px; + right: 0; + line-height: 25px; + padding: 31px 0px; + margin: 0; + border-radius: 0; + &.validation { + background: $feedbackColor!important; + } + &.baskets { + background: $basketColor!important; + } + } + +} +.lightbox-msg { + font-size: 14px; + color: #313131; + padding: 6px 0 6px 30px; +} diff --git a/templates/mobile/lightbox/index.html.twig b/templates/mobile/lightbox/index.html.twig index 418df10caa..5fb65f9f58 100644 --- a/templates/mobile/lightbox/index.html.twig +++ b/templates/mobile/lightbox/index.html.twig @@ -99,24 +99,28 @@ {{ 'Validations' | trans }} {{_self.valid_baskets_length(baskets_collection)}}

      -

      +

      -
        - {% for basket in baskets_collection | sort | reverse%} - {% if basket.getValidation() %} - {% set basket_length = basket.getElements().count() %} -
      • - {% if basket.getElements().first() %} - - {% endif %} -

        {{basket.getName()}}

        -

        {{ basket.getDescription() }}

        - {{ basket_length }} -
      • - {% endif %} - {% endfor %} -
      +
      +
        + {% for basket in baskets_collection | sort | reverse%} + {% if basket.getValidation() %} + {% set basket_length = basket.getElements().count() %} +
      • + {% if basket.getElements().first() %} + + {% endif %} +

        {{basket.getName()}}

        +

        {{ basket.getDescription() }}

        + {{ basket_length }} +
      • + {% endif %} + {% endfor %} +
      +
      @@ -136,24 +140,28 @@ {{ 'Paniers' | trans }} {{_self.baskets_length(baskets_collection)}}

      -

      +

      -
        - {% for basket in baskets_collection %} - {% if basket.getValidation() is empty %} - {% set basket_length = basket.getElements().count() %} -
      • - {% if basket.getElements().first() %} - - {% endif %} -

        {{ basket.getName() }}

        -

        {{ basket.getDescription() }}

        - {{basket_length}} -
      • - {% endif %} - {% endfor %} -
      +
      +
        + {% for basket in baskets_collection %} + {% if basket.getValidation() is empty %} + {% set basket_length = basket.getElements().count() %} +
      • + {% if basket.getElements().first() %} + + {% endif %} +

        {{ basket.getName() }}

        +

        {{ basket.getDescription() }}

        + {{basket_length}} +
      • + {% endif %} + {% endfor %} +
      +
      From e4b29d70c56da7a662b9b2c15d470be746c40bbc Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 5 Dec 2019 12:30:23 +0400 Subject: [PATCH 18/40] route search and storie on api/v3 --- .../Application/ApiApplicationLoader.php | 13 + .../Phrasea/Controller/Api/V1Controller.php | 11 +- .../Phrasea/Controller/Api/V3Controller.php | 807 ++++++++++++++++++ .../Phrasea/ControllerProvider/Api/V3.php | 48 ++ lib/classes/record/adapter.php | 2 +- 5 files changed, 872 insertions(+), 9 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Controller/Api/V3Controller.php create mode 100644 lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php diff --git a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php index 490554c95e..ca47f16baa 100644 --- a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php +++ b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php @@ -15,6 +15,7 @@ use Alchemy\Phrasea\Controller\Api\Result; use Alchemy\Phrasea\ControllerProvider\Api\OAuth2; use Alchemy\Phrasea\ControllerProvider\Api\V1; use Alchemy\Phrasea\ControllerProvider\Api\V2; +use Alchemy\Phrasea\ControllerProvider\Api\V3; use Alchemy\Phrasea\ControllerProvider\Datafiles; use Alchemy\Phrasea\ControllerProvider\MediaAccessor; use Alchemy\Phrasea\ControllerProvider\Minifier; @@ -36,6 +37,7 @@ class ApiApplicationLoader extends BaseApplicationLoader $app->register(new OAuth2()); $app->register(new V1()); $app->register(new V2()); + $app->register(new V3()); $app->register(new ApiReportControllerProvider()); $app->register(new JsonSchemaServiceProvider()); } @@ -119,6 +121,16 @@ class ApiApplicationLoader extends BaseApplicationLoader 'access_token' => '/api/oauthv2/token' ], ], + '3' => [ + 'number' => V3::VERSION, + 'uri' => '/api/v3/', + 'authenticationProtocol' => 'OAuth2', + 'authenticationVersion' => 'draft#v9', + 'authenticationEndPoints' => [ + 'authorization_token' => '/api/oauthv2/authorize', + 'access_token' => '/api/oauthv2/token' + ] + ], ] ])->createResponse(); }); @@ -135,6 +147,7 @@ class ApiApplicationLoader extends BaseApplicationLoader $app->mount('/datafiles/', new Datafiles()); $app->mount('/api/v1', new V1()); $app->mount('/api/v2', new V2()); + $app->mount('/api/v3', new V3()); $app->mount('/api/report', new ApiReportControllerProvider()); $app->mount('/permalink/', new Permalink()); $app->mount($app['controller.media_accessor.route_prefix'], new MediaAccessor()); diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index cb2523e1ae..1260b90ee3 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1221,8 +1221,7 @@ class V1Controller extends Controller $searchView = $this->buildSearchView( $result, $includeResolver->resolve($fractal), - $this->resolveSubdefUrlTTL($request), - (int)$request->get('story_max_items') ?: 10 + $this->resolveSubdefUrlTTL($request) ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -1280,7 +1279,7 @@ class V1Controller extends Controller * @param int|null $story_max_items * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_items = null) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL) { $references = new RecordReferenceCollection($result->getResults()); @@ -1676,10 +1675,6 @@ class V1Controller extends Controller return Result::createError($request, 404, 'Story not found')->createResponse(); } - $max_items = (int)$request->get('max_items')?:10; - $page = (int)$request->get('page')?:1; - $offset = ($max_items * ($page - 1)) + 1; - $caption = $story->get_caption(); $format = function (\caption_record $caption, $dcField) { @@ -1721,7 +1716,7 @@ class V1Controller extends Controller 'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title), 'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type), ], - 'records' => $this->listRecords($request, array_values($story->getChildren($offset, $max_items)->get_elements())), + 'records' => $this->listRecords($request, array_values($story->getChildren()->get_elements())), ]; } diff --git a/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php new file mode 100644 index 0000000000..f7672058a9 --- /dev/null +++ b/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php @@ -0,0 +1,807 @@ +findDataboxById($databox_id)->get_record($record_id); + + return Result::create($request, ['story' => $this->listStory($request, $story)])->createResponse(); + } catch (NotFoundHttpException $e) { + return Result::createError($request, 404, $this->app->trans('Story Not Found'))->createResponse(); + } catch (\Exception $e) { + return $this->app['controller.api.v1']->getBadRequestAction($request, $this->app->trans('An error occurred')); + } + } + + /** + * Search for results + * + * @param Request $request + * + * @return Response + */ + public function searchAction(Request $request) + { + $subdefTransformer = new SubdefTransformer($this->app['acl'], $this->getAuthenticatedUser(), new PermalinkTransformer()); + $technicalDataTransformer = new TechnicalDataTransformer(); + $recordTransformer = new RecordTransformer($subdefTransformer, $technicalDataTransformer); + $storyTransformer = new StoryTransformer($subdefTransformer, $recordTransformer); + $compositeTransformer = new V1SearchCompositeResultTransformer($recordTransformer, $storyTransformer); + $searchTransformer = new V1SearchResultTransformer($compositeTransformer); + + $transformerResolver = new SearchResultTransformerResolver([ + '' => $searchTransformer, + 'results' => $compositeTransformer, + 'results.stories' => $storyTransformer, + 'results.stories.thumbnail' => $subdefTransformer, + 'results.stories.metadatas' => new CallbackTransformer(), + 'results.stories.caption' => new CallbackTransformer(), + 'results.stories.records' => $recordTransformer, + 'results.stories.records.thumbnail' => $subdefTransformer, + 'results.stories.records.technical_informations' => $technicalDataTransformer, + 'results.stories.records.subdefs' => $subdefTransformer, + 'results.stories.records.metadata' => new CallbackTransformer(), + 'results.stories.records.status' => new CallbackTransformer(), + 'results.stories.records.caption' => new CallbackTransformer(), + 'results.records' => $recordTransformer, + 'results.records.thumbnail' => $subdefTransformer, + 'results.records.technical_informations' => $technicalDataTransformer, + 'results.records.subdefs' => $subdefTransformer, + 'results.records.metadata' => new CallbackTransformer(), + 'results.records.status' => new CallbackTransformer(), + 'results.records.caption' => new CallbackTransformer(), + ]); + + $includeResolver = new IncludeResolver($transformerResolver); + + $fractal = new \League\Fractal\Manager(); + $fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher'])); + $fractal->parseIncludes($this->resolveSearchIncludes($request)); + + $result = $this->doSearch($request); + + $story_max_items = null; + // if search on story + if ($request->get('search_type') == 1) { + $story_max_items = (int)$request->get('story_max_items') ?: 10; + } + + $searchView = $this->buildSearchView( + $result, + $includeResolver->resolve($fractal), + $this->resolveSubdefUrlTTL($request), + $story_max_items + ); + + $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); + + return Result::create($request, $ret)->createResponse(); + } + + /** + * Retrieve detailed information about one story + * + * @param Request $request + * @param \record_adapter $story + * @return array + * @throws \Exception + */ + private function listStory(Request $request, \record_adapter $story) + { + if (!$story->isStory()) { + return Result::createError($request, 404, 'Story not found')->createResponse(); + } + + $max_items = (int)$request->get('max_items')?:10; + $page = (int)$request->get('page')?:1; + $offset = ($max_items * ($page - 1)) + 1; + + $caption = $story->get_caption(); + + $format = function (\caption_record $caption, $dcField) { + + $field = $caption->get_dc_field($dcField); + + if (!$field) { + return null; + } + + return $field->get_serialized_values(); + }; + + return [ + '@entity@' => V1Controller::OBJECT_TYPE_STORY, + 'databox_id' => $story->getDataboxId(), + 'story_id' => $story->getRecordId(), + 'updated_on' => $story->getUpdated()->format(DATE_ATOM), + 'created_on' => $story->getCreated()->format(DATE_ATOM), + 'collection_id' => $story->getCollectionId(), + 'base_id' => $story->getBaseId(), + 'thumbnail' => $this->listEmbeddableMedia($request, $story, $story->get_thumbnail()), + 'uuid' => $story->getUuid(), + 'metadatas' => [ + '@entity@' => V1Controller::OBJECT_TYPE_STORY_METADATA_BAG, + 'dc:contributor' => $format($caption, \databox_Field_DCESAbstract::Contributor), + 'dc:coverage' => $format($caption, \databox_Field_DCESAbstract::Coverage), + 'dc:creator' => $format($caption, \databox_Field_DCESAbstract::Creator), + 'dc:date' => $format($caption, \databox_Field_DCESAbstract::Date), + 'dc:description' => $format($caption, \databox_Field_DCESAbstract::Description), + 'dc:format' => $format($caption, \databox_Field_DCESAbstract::Format), + 'dc:identifier' => $format($caption, \databox_Field_DCESAbstract::Identifier), + 'dc:language' => $format($caption, \databox_Field_DCESAbstract::Language), + 'dc:publisher' => $format($caption, \databox_Field_DCESAbstract::Publisher), + 'dc:relation' => $format($caption, \databox_Field_DCESAbstract::Relation), + 'dc:rights' => $format($caption, \databox_Field_DCESAbstract::Rights), + 'dc:source' => $format($caption, \databox_Field_DCESAbstract::Source), + 'dc:subject' => $format($caption, \databox_Field_DCESAbstract::Subject), + 'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title), + 'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type), + ], + 'records' => $this->listRecords($request, array_values($story->getChildren($offset, $max_items)->get_elements())), + ]; + } + + private function listEmbeddableMedia(Request $request, \record_adapter $record, \media_subdef $media) + { + if (!$media->is_physically_present()) { + return null; + } + + if ($this->getAuthenticator()->isAuthenticated()) { + $acl = $this->getAclForUser(); + if ($media->get_name() !== 'document' + && false === $acl->has_access_to_subdef($record, $media->get_name()) + ) { + return null; + } + if ($media->get_name() === 'document' + && !$acl->has_right_on_base($record->getBaseId(), \ACL::CANDWNLDHD) + && !$acl->has_hd_grant($record) + ) { + return null; + } + } + + if ($media->get_permalink() instanceof \media_Permalink_Adapter) { + $permalink = $this->listPermalink($media->get_permalink()); + } else { + $permalink = null; + } + + $urlTTL = (int) $request->get( + 'subdef_url_ttl', + $this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl']) + ); + if ($urlTTL < 0) { + $urlTTL = -1; + } + $issuer = $this->getAuthenticatedUser(); + + return [ + 'name' => $media->get_name(), + 'permalink' => $permalink, + 'height' => $media->get_height(), + 'width' => $media->get_width(), + 'filesize' => $media->get_size(), + 'devices' => $media->getDevices(), + 'player_type' => $media->get_type(), + 'mime_type' => $media->get_mime(), + 'substituted' => $media->is_substituted(), + 'created_on' => $media->get_creation_date()->format(DATE_ATOM), + 'updated_on' => $media->get_modification_date()->format(DATE_ATOM), + 'url' => $this->app['media_accessor.subdef_url_generator']->generate($issuer, $media, $urlTTL), + 'url_ttl' => $urlTTL, + ]; + } + + private function listPermalink(\media_Permalink_Adapter $permalink) + { + $downloadUrl = $permalink->get_url(); + $downloadUrl->getQuery()->set('download', '1'); + + return [ + 'created_on' => $permalink->get_created_on()->format(DATE_ATOM), + 'id' => $permalink->get_id(), + 'is_activated' => $permalink->get_is_activated(), + /** @Ignore */ + 'label' => $permalink->get_label(), + 'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM), + 'page_url' => $permalink->get_page(), + 'download_url' => (string)$downloadUrl, + 'url' => (string)$permalink->get_url(), + ]; + } + + /** + * @param Request $request + * @param RecordReferenceInterface[]|RecordReferenceCollection $records + * @return array + */ + private function listRecords(Request $request, $records) + { + if (!$records instanceof RecordReferenceCollection) { + $records = new RecordReferenceCollection($records); + } + + $technicalData = $this->app['service.technical_data']->fetchRecordsTechnicalData($records); + + $data = []; + + foreach ($records->toRecords($this->getApplicationBox()) as $index => $record) { + $record->setTechnicalDataSet($technicalData[$index]); + + $data[$index] = $this->listRecord($request, $record); + } + + return $data; + } + + /** + * Retrieve detailed information about one record + * + * @param Request $request + * @param \record_adapter $record + * @return array + */ + private function listRecord(Request $request, \record_adapter $record) + { + $technicalInformation = []; + foreach ($record->get_technical_infos()->getValues() as $name => $value) { + $technicalInformation[] = ['name' => $name, 'value' => $value]; + } + + $data = [ + 'databox_id' => $record->getDataboxId(), + 'record_id' => $record->getRecordId(), + 'mime_type' => $record->getMimeType(), + 'title' => $record->get_title(), + 'original_name' => $record->get_original_name(), + 'updated_on' => $record->getUpdated()->format(DATE_ATOM), + 'created_on' => $record->getCreated()->format(DATE_ATOM), + 'collection_id' => $record->getCollectionId(), + 'base_id' => $record->getBaseId(), + 'sha256' => $record->getSha256(), + 'thumbnail' => $this->listEmbeddableMedia($request, $record, $record->get_thumbnail()), + 'technical_informations' => $technicalInformation, + 'phrasea_type' => $record->getType(), + 'uuid' => $record->getUuid(), + ]; + + if ($request->attributes->get('_extended', false)) { + $data = array_merge($data, [ + 'subdefs' => $this->listRecordEmbeddableMedias($request, $record), + 'metadata' => $this->listRecordMetadata($record), + 'status' => $this->listRecordStatus($record), + 'caption' => $this->listRecordCaption($record), + ]); + } + + return $data; + } + + /** + * @param Request $request + * @param \record_adapter $record + * @return array + */ + private function listRecordEmbeddableMedias(Request $request, \record_adapter $record) + { + $subdefs = []; + + foreach ($record->get_embedable_medias([], []) as $name => $media) { + if (null !== $subdef = $this->listEmbeddableMedia($request, $record, $media)) { + $subdefs[] = $subdef; + } + } + + return $subdefs; + } + + /** + * List all fields of given record + * + * @param \record_adapter $record + * @return array + */ + private function listRecordMetadata(\record_adapter $record) + { + $includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox()); + + return $this->listRecordCaptionFields($record->get_caption()->get_fields(null, $includeBusiness)); + } + + /** + * @param \caption_field[] $fields + * @return array + */ + private function listRecordCaptionFields($fields) + { + $ret = []; + + foreach ($fields as $field) { + $databox_field = $field->get_databox_field(); + + $fieldData = [ + 'meta_structure_id' => $field->get_meta_struct_id(), + 'name' => $field->get_name(), + 'labels' => [ + 'fr' => $databox_field->get_label('fr'), + 'en' => $databox_field->get_label('en'), + 'de' => $databox_field->get_label('de'), + 'nl' => $databox_field->get_label('nl'), + ], + ]; + + foreach ($field->get_values() as $value) { + $data = [ + 'meta_id' => $value->getId(), + 'value' => $value->getValue(), + ]; + + $ret[] = $fieldData + $data; + } + } + + return $ret; + } + + /** + * Retrieve detailed information about one status + * + * @param \record_adapter $record + * @return array + */ + private function listRecordStatus(\record_adapter $record) + { + $ret = []; + foreach ($record->getStatusStructure() as $bit => $status) { + $ret[] = [ + 'bit' => $bit, + 'state' => \databox_status::bitIsSet($record->getStatusBitField(), $bit), + ]; + } + + return $ret; + } + + /** + * @param \record_adapter $record + * @return array + */ + private function listRecordCaption(\record_adapter $record) + { + $includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox()); + + $caption = []; + + foreach ($record->get_caption()->get_fields(null, $includeBusiness) as $field) { + $caption[] = [ + 'meta_structure_id' => $field->get_meta_struct_id(), + 'name' => $field->get_name(), + 'value' => $field->get_serialized_values(';'), + ]; + } + + return $caption; + } + + /** + * Returns requested includes + * + * @param Request $request + * @return string[] + */ + private function resolveSearchIncludes(Request $request) + { + $includes = [ + 'results.stories.records' + ]; + + if ($request->attributes->get('_extended', false)) { + if ($request->get('search_type') != SearchEngineOptions::RECORD_STORY) { + $includes = array_merge($includes, [ + 'results.stories.records.subdefs', + 'results.stories.records.metadata', + 'results.stories.records.caption', + 'results.stories.records.status' + ]); + } + else { + $includes = [ 'results.stories.caption' ]; + } + + $includes = array_merge($includes, [ + 'results.records.subdefs', + 'results.records.metadata', + 'results.records.caption', + 'results.records.status' + ]); + } + + return $includes; + } + + /** + * @param SearchEngineResult $result + * @param string[] $includes + * @param int $urlTTL + * @param int|null $story_max_items + * @return SearchResultView + */ + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_items = null) + { + $references = new RecordReferenceCollection($result->getResults()); + + $records = new RecordCollection(); + $stories = new RecordCollection(); + + foreach ($references->toRecords($this->getApplicationBox()) as $record) { + if ($record->isStory()) { + $stories[$record->getId()] = $record; + } else { + $records[$record->getId()] = $record; + } + } + + $resultView = new SearchResultView($result); + + if ($stories->count() > 0) { + $user = $this->getAuthenticatedUser(); + $children = []; + + foreach ($stories->getDataboxIds() as $databoxId) { + $storyIds = $stories->getDataboxRecordIds($databoxId); + + $selections = $this->findDataboxById($databoxId) + ->getRecordRepository() + ->findChildren($storyIds, $user,1, $story_max_items); + $children[$databoxId] = array_combine($storyIds, $selections); + } + + /** @var StoryView[] $storyViews */ + $storyViews = []; + /** @var RecordView[] $childrenViews */ + $childrenViews = []; + + foreach ($stories as $index => $story) { + $storyView = new StoryView($story); + + $selection = $children[$story->getDataboxId()][$story->getRecordId()]; + + $childrenView = $this->buildRecordViews($selection); + + foreach ($childrenView as $view) { + $childrenViews[spl_object_hash($view)] = $view; + } + + $storyView->setChildren($childrenView); + + $storyViews[$index] = $storyView; + } + + if (in_array('results.stories.thumbnail', $includes, true)) { + $subdefViews = $this->buildSubdefsViews($stories, ['thumbnail'], $urlTTL); + + foreach ($storyViews as $index => $storyView) { + $storyView->setSubdefs($subdefViews[$index]); + } + } + + if (in_array('results.stories.metadatas', $includes, true) || + in_array('results.stories.caption', $includes, true)) { + $captions = $this->app['service.caption']->findByReferenceCollection($stories); + $canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($stories); + + $this->buildCaptionViews($storyViews, $captions, $canSeeBusiness); + } + + $allChildren = new RecordCollection(); + foreach ($childrenViews as $index => $childrenView) { + $allChildren[$index] = $childrenView->getRecord(); + } + + $names = in_array('results.stories.records.subdefs', $includes, true) ? null : ['thumbnail']; + $subdefViews = $this->buildSubdefsViews($allChildren, $names, $urlTTL); + $technicalDatasets = $this->app['service.technical_data']->fetchRecordsTechnicalData($allChildren); + + foreach ($childrenViews as $index => $recordView) { + $recordView->setSubdefs($subdefViews[$index]); + $recordView->setTechnicalDataView(new TechnicalDataView($technicalDatasets[$index])); + } + + if (array_intersect($includes, ['results.stories.records.metadata', 'results.stories.records.caption'])) { + $captions = $this->app['service.caption']->findByReferenceCollection($allChildren); + $canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($allChildren); + + $this->buildCaptionViews($childrenViews, $captions, $canSeeBusiness); + } + + $resultView->setStories($storyViews); + } + + if ($records->count() > 0) { + $names = in_array('results.records.subdefs', $includes, true) ? null : ['thumbnail']; + $recordViews = $this->buildRecordViews($records); + $subdefViews = $this->buildSubdefsViews($records, $names, $urlTTL); + + $technicalDatasets = $this->app['service.technical_data']->fetchRecordsTechnicalData($records); + + foreach ($recordViews as $index => $recordView) { + $recordView->setSubdefs($subdefViews[$index]); + $recordView->setTechnicalDataView(new TechnicalDataView($technicalDatasets[$index])); + } + + if (array_intersect($includes, ['results.records.metadata', 'results.records.caption'])) { + $captions = $this->app['service.caption']->findByReferenceCollection($records); + $canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($records); + + $this->buildCaptionViews($recordViews, $captions, $canSeeBusiness); + } + + $resultView->setRecords($recordViews); + } + + return $resultView; + } + + /** + * @param Request $request + * @return SearchEngineResult + */ + private function doSearch(Request $request) + { + $options = SearchEngineOptions::fromRequest($this->app, $request); + $options->setFirstResult((int)($request->get('offset_start') ?: 0)); + $options->setMaxResults((int)$request->get('per_page') ?: 10); + + $this->getSearchEngine()->resetCache(); + + $search_result = $this->getSearchEngine()->query((string)$request->get('query'), $options); + + $this->getUserManipulator()->logQuery($this->getAuthenticatedUser(), $search_result->getQueryText()); + + // log array of collectionIds (from $options) for each databox + $collectionsReferencesByDatabox = $options->getCollectionsReferencesByDatabox(); + foreach ($collectionsReferencesByDatabox as $sbid => $references) { + $databox = $this->findDataboxById($sbid); + $collectionsIds = array_map(function(CollectionReference $ref){return $ref->getCollectionId();}, $references); + $this->getSearchEngineLogger()->log($databox, $search_result->getQueryText(), $search_result->getTotal(), $collectionsIds); + } + + $this->getSearchEngine()->clearCache(); + + return $search_result; + } + + /** + * @return SearchEngineInterface + */ + private function getSearchEngine() + { + return $this->app['phraseanet.SE']; + } + + /** + * @return UserManipulator + */ + private function getUserManipulator() + { + return $this->app['manipulator.user']; + } + + /** + * @return SearchEngineLogger + */ + private function getSearchEngineLogger() + { + return $this->app['phraseanet.SE.logger']; + } + + /** + * @param Request $request + * @return int + */ + private function resolveSubdefUrlTTL(Request $request) + { + $urlTTL = $request->query->get('subdef_url_ttl'); + + if (null !== $urlTTL) { + return (int)$urlTTL; + } + + return $this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl']); + } + + /** + * @param RecordCollection|\record_adapter[] $references + * @return RecordView[] + */ + private function buildRecordViews($references) + { + if (!$references instanceof RecordCollection) { + $references = new RecordCollection($references); + } + + $recordViews = []; + + foreach ($references as $index => $record) { + $recordViews[$index] = new RecordView($record); + } + + return $recordViews; + } + + /** + * @param RecordReferenceInterface[]|RecordReferenceCollection|DataboxGroupable $references + * @param array|null $names + * @param int $urlTTL + * @return SubdefView[][] + */ + private function buildSubdefsViews($references, array $names = null, $urlTTL) + { + $subdefGroups = $this->app['service.media_subdef'] + ->findSubdefsByRecordReferenceFromCollection($references, $names); + + $fakeSubdefs = []; + + foreach ($subdefGroups as $index => $subdefGroup) { + if (!isset($subdefGroup['thumbnail'])) { + $fakeSubdef = new \media_subdef($this->app, $references[$index], 'thumbnail', true, []); + $fakeSubdefs[spl_object_hash($fakeSubdef)] = $fakeSubdef; + + $subdefGroups[$index]['thumbnail'] = $fakeSubdef; + } + } + + $allSubdefs = $this->mergeGroupsIntoOneList($subdefGroups); + $allPermalinks = \media_Permalink_Adapter::getMany( + $this->app, + array_filter($allSubdefs, function (\media_subdef $subdef) use ($fakeSubdefs) { + return !isset($fakeSubdefs[spl_object_hash($subdef)]); + }) + ); + $urls = $this->app['media_accessor.subdef_url_generator'] + ->generateMany($this->getAuthenticatedUser(), $allSubdefs, $urlTTL); + + $subdefViews = []; + + /** @var \media_subdef $subdef */ + foreach ($allSubdefs as $index => $subdef) { + $subdefView = new SubdefView($subdef); + + if (isset($allPermalinks[$index])) { + $subdefView->setPermalinkView(new PermalinkView($allPermalinks[$index])); + } + + $subdefView->setUrl($urls[$index]); + $subdefView->setUrlTTL($urlTTL); + + $subdefViews[spl_object_hash($subdef)] = $subdefView; + } + + $reorderedGroups = []; + + /** @var \media_subdef[] $subdefGroup */ + foreach ($subdefGroups as $index => $subdefGroup) { + $reordered = []; + + foreach ($subdefGroup as $subdef) { + $reordered[] = $subdefViews[spl_object_hash($subdef)]; + } + + $reorderedGroups[$index] = $reordered; + } + + return $reorderedGroups; + } + + /** + * @param array $groups + * @return array|mixed + */ + private function mergeGroupsIntoOneList(array $groups) + { + // Strips keys from the internal array + array_walk($groups, function (array &$group) { + $group = array_values($group); + }); + + if ($groups) { + return call_user_func_array('array_merge', $groups); + } + + return []; + } + + /** + * @param RecordReferenceInterface[]|DataboxGroupable $references + * @return array + */ + private function retrieveSeeBusinessPerDatabox($references) + { + if (!$references instanceof DataboxGroupable) { + $references = new RecordReferenceCollection($references); + } + + $acl = $this->getAclForUser(); + + $canSeeBusiness = []; + + foreach ($references->getDataboxIds() as $databoxId) { + $canSeeBusiness[$databoxId] = $acl->can_see_business_fields($this->findDataboxById($databoxId)); + } + + $rights = []; + + foreach ($references as $index => $reference) { + $rights[$index] = $canSeeBusiness[$reference->getDataboxId()]; + } + + return $rights; + } + + /** + * @param RecordView[] $recordViews + * @param \caption_record[] $captions + * @param bool[] $canSeeBusiness + */ + private function buildCaptionViews($recordViews, $captions, $canSeeBusiness) + { + foreach ($recordViews as $index => $recordView) { + $caption = $captions[$index]; + + $captionView = new CaptionView($caption); + + $captionView->setFields($caption->get_fields(null, isset($canSeeBusiness[$index]) && (bool)$canSeeBusiness[$index])); + + $recordView->setCaption($captionView); + } + } +} diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php b/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php new file mode 100644 index 0000000000..d5add594b2 --- /dev/null +++ b/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php @@ -0,0 +1,48 @@ +share(function (PhraseaApplication $app) { + return (new V3Controller($app)); + }); + } + + public function boot(Application $app) + { + } + + public function connect(Application $app) + { + if (! $this->isApiEnabled($app)) { + return $app['controllers_factory']; + } + + /** @var ControllerCollection $controllers */ + $controllers = $app['controllers_factory']; + + $controllers->before(new OAuthListener()); + + $controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3:getStoryAction') + ->before('controller.api.v1:ensureCanAccessToRecord') + ->assert('databox_id', '\d+') + ->assert('record_id', '\d+'); + + $controllers->match('/search/', 'controller.api.v3:searchAction'); + + return $controllers; + } +} diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index 37839b792d..103a2b4cb0 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1692,7 +1692,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface * @throws Exception * @throws \Doctrine\DBAL\DBALException */ - public function getChildren($offset = 0, $max_items = null) + public function getChildren($offset = 1, $max_items = null) { if (!$this->isStory()) { throw new Exception('This record is not a grouping'); From 4fd9f49ec20ba3823a061bf386a2ff52ba8a9a86 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Thu, 5 Dec 2019 13:25:19 +0400 Subject: [PATCH 19/40] PHRAS-2848 #comment some --- .../lightbox/styles/jquery-mobile/_jquery-validator.scss | 6 ++++++ templates/mobile/lightbox/index.html.twig | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss index 4edfa60d29..013a7ae0a7 100644 --- a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss +++ b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss @@ -245,6 +245,8 @@ a.active_choice { padding-left: 109px!important; padding-right: 80px!important; border-color: #d4d4d4!important; + text-overflow: inherit!important; + white-space: inherit!important; } .lightbox-img { width: 90px; @@ -258,6 +260,7 @@ a.active_choice { img { display: flex; align-items: center; + width: 90px; max-width: 100%; max-height: 100%; object-fit: contain; @@ -270,10 +273,13 @@ a.active_choice { margin: 0!important; font-size: 15px; font-weight: bold!important; + text-overflow: inherit!important; + white-space: inherit!important; a { position: relative; color: #313131!important; width: 100%; + padding-right: 18px; &:after { content: "\e96c"; font-family: icomoon; diff --git a/templates/mobile/lightbox/index.html.twig b/templates/mobile/lightbox/index.html.twig index 5fb65f9f58..188a514e86 100644 --- a/templates/mobile/lightbox/index.html.twig +++ b/templates/mobile/lightbox/index.html.twig @@ -145,7 +145,7 @@

        - {% for basket in baskets_collection %} + {% for basket in baskets_collection | sort | reverse %} {% if basket.getValidation() is empty %} {% set basket_length = basket.getElements().count() %}
      • From 1313d8ff829a052ff798171fe267411f1282ee66 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Thu, 5 Dec 2019 14:13:23 +0400 Subject: [PATCH 20/40] PHRAS-2850 #comment fix error icomoon #time 2h --- .../common/styles/fonts/PhraseanetIcomoon/style.css | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css b/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css index 566f9d5786..bef5e9c08c 100644 --- a/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css +++ b/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css @@ -1,13 +1,3 @@ -@font-face { - font-family: 'icomoon'; - src: url('fonts/icomoon.eot?81kpnc'); - src: url('fonts/icomoon.eot?81kpnc#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?81kpnc') format('truetype'), - url('fonts/icomoon.woff?81kpnc') format('woff'), - url('fonts/icomoon.svg?81kpnc#icomoon') format('svg'); - font-weight: normal; - font-style: normal; -} [class^="icon-"], [class*=" icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ From 3d6d2e4e64b3a08b9ad01210690aca1c8a9b09fd Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 5 Dec 2019 14:30:17 +0400 Subject: [PATCH 21/40] fix V1Controller --- lib/Alchemy/Phrasea/Controller/Api/V1Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 1260b90ee3..932b383036 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -1305,7 +1305,7 @@ class V1Controller extends Controller $selections = $this->findDataboxById($databoxId) ->getRecordRepository() - ->findChildren($storyIds, $user,1, $story_max_items); + ->findChildren($storyIds, $user); $children[$databoxId] = array_combine($storyIds, $selections); } From 276d5a8ce65cf237be4e4ca151de197ea3686cce Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 5 Dec 2019 14:42:15 +0400 Subject: [PATCH 22/40] remove unused comment --- lib/Alchemy/Phrasea/Controller/Api/V1Controller.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 932b383036..9b8f4ed04d 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -29,7 +29,6 @@ use Alchemy\Phrasea\Border\Visa; use Alchemy\Phrasea\Cache\Cache; use Alchemy\Phrasea\Collection\Reference\CollectionReference; use Alchemy\Phrasea\Controller\Controller; -use Alchemy\Phrasea\ControllerProvider\Api\V1; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\Version; @@ -1276,7 +1275,6 @@ class V1Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL - * @param int|null $story_max_items * @return SearchResultView */ private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL) From 960c40233c99b72ec380eff7db8ff5930b94716e Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 5 Dec 2019 14:55:56 +0400 Subject: [PATCH 23/40] add presets and libmp3lame to default --- .../Controller/Admin/SubdefsController.php | 66 +++++++++++++++++++ lib/Alchemy/Phrasea/Media/Subdef/Video.php | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php index 02039f0860..6ebdf524d7 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php @@ -420,6 +420,72 @@ class SubdefsController extends Controller Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], + "144P H264 128 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "128", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "256", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "240P H264 256 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "256", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "426", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "360P H264 576 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "576", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "480", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libtheora", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "480P H264 750 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "750", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "854", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "720P H264 1492 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "1492", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1280", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "1080P H264 2420 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "2420", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1920", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], "video codec libvpx" => null, "144P webm 128 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", diff --git a/lib/Alchemy/Phrasea/Media/Subdef/Video.php b/lib/Alchemy/Phrasea/Media/Subdef/Video.php index 1b0ce097b0..be673b937a 100644 --- a/lib/Alchemy/Phrasea/Media/Subdef/Video.php +++ b/lib/Alchemy/Phrasea/Media/Subdef/Video.php @@ -33,7 +33,7 @@ class Video extends Audio $this->registerOption(new OptionType\Range($this->translator->trans('Frame Rate'), self::OPTION_FRAMERATE, 1, 200, 20)); $this->registerOption(new OptionType\Enum($this->translator->trans('Video Codec'), self::OPTION_VCODEC, ['libx264', 'libvpx', 'libtheora'], 'libx264')); $this->unregisterOption(self::OPTION_ACODEC); - $this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis', 'libfdk_aac'], 'libfdk_aac')); + $this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis', 'libfdk_aac'], 'libmp3lame')); } public function getType() From d95014831ee888f6c54c7eb233802847cf84332e Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 5 Dec 2019 15:23:59 +0400 Subject: [PATCH 24/40] update presets webm --- .../Controller/Admin/SubdefsController.php | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php index 6ebdf524d7..106a60b1d8 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php @@ -553,6 +553,72 @@ class SubdefsController extends Controller Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], + "144P webm 128 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "128", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "256", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "240P webm 256 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "256", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "426", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "360P webm 576 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "576", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "480", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "480P webm 750 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "750", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "854", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "720P webm 1492 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "1492", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1280", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "1080P webm 2420 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "2420", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1920", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], ], "form" => [ Video::OPTION_AUDIOBITRATE => "slide", From 0967f3c8104781e96ec0ed6bdd48f1118f78f610 Mon Sep 17 00:00:00 2001 From: Jean-Yves Gaulier Date: Thu, 5 Dec 2019 14:52:46 +0100 Subject: [PATCH 25/40] PHRAS-2631_feedback-icon fix : 2 new icons for feedback baskets; no more display of 2 icons. fix : tooltip on "about" icon of feedback baskets --- .../Phrasea/Controller/Prod/PushController.php | 2 +- .../common/images/icons/basket_feedback_read.png | Bin 0 -> 1372 bytes .../images/icons/basket_feedback_unread.png | Bin 0 -> 1502 bytes templates/web/prod/WorkZone/Macros.html.twig | 13 ++++++------- 4 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 resources/www/common/images/icons/basket_feedback_read.png create mode 100644 resources/www/common/images/icons/basket_feedback_unread.png diff --git a/lib/Alchemy/Phrasea/Controller/Prod/PushController.php b/lib/Alchemy/Phrasea/Controller/Prod/PushController.php index f9ce528e41..6e650aefaa 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/PushController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/PushController.php @@ -193,7 +193,7 @@ class PushController extends Controller 'Validation from %user%', [ '%user%' => $this->getAuthenticatedUser()->getDisplayName(), ])); - $validation_description = $request->request->get('validation_description'); + $validation_description = $request->request->get('message'); $participants = $request->request->get('participants'); diff --git a/resources/www/common/images/icons/basket_feedback_read.png b/resources/www/common/images/icons/basket_feedback_read.png new file mode 100644 index 0000000000000000000000000000000000000000..129170a64832e4607a8bd55d1950fa22e34e0b84 GIT binary patch literal 1372 zcmV-i1*7_jP)Px)7D+@wR7eeVReelVWf*_Xx#w^{Py{bJEzuEBf27NnGtIRnh;pSlW7eiE`J)fF zvdp;_MAQg3KxnSEWCij^&e<2)$C3+H5Lp9lrDba&Mll&q^lBJfF8AJZ`u$!wcYx#B ze)oOf^L)L}*Lz(8s%k6PK0kfIMedXANiuM-tG+1^+vax>t?v86n_Q))BVdQ4!{BbR zrTlo_yOqIw3f-oWeV{X7#l|g($1KrZx!a401LPd+;pz1WoL`|OjBS?B?q@aK;YxbnkH7< zK3JL;dd*eRO=2eLQnEhiVT?(>RI}c;Y?VR^e$`Ve zb*BmwIG=gJ;Q|e*g0gt1r<*6wKE)pOmuZTwG@&KZe_dT4?{2ZD_rR3iRRz z=I%bUrYPg?w0dUJiNUh${#Wu^9|ZqjV3Z0ZN0FUj0$llx*@;dfj#U*Et72-8?p^C% z^+;-yOVb~Qhr!sG^?K>X;78z7k(B5H9sO3T8`|Ef*I`O&s^Q5NPj9dCq!e5gU*>J| zq$GX7Oei2@>{couSOuh%aYlJhH#&2Sf-gVRLbucCjT8A|B1_@n@#4y&_M^;@$)d6j zQ>p&+;}WwX5=E!cSaO=X9DFqTL`D+xa^&nD=?!&Bj{gBMbhp?Lo=ov#M}gN;MdJFz z%D1GY=S|s=^&F3)AqK`08H=~6Gk)e(wHKU&)-t-!O1)p^c^1hJ7d}zJvWFN$U2$hd zXdrx*SBjRd53bd8O^r$4@M-z^^5^26V~EFRDB+PC(FO>QKsL_nu(CcN1><=N^Sjh( z3tpxF{Pkzw+1=F)KA(aJ6`a61!c=6wT>#U@wg>|p=?I|afl360=#8KeDsW<{#Fgza zt(S0~=qarF{+9f$X0lNYOLvelIe^?wCr$o}j>Jk{4V?T83}qCnQ`AK7C2oZttX4fp zsmbCiXt*@J0ujo zBsmLL3!fA|gVeEYEwi|C)nVEMTpV;&EYs8jmP!MJ5CL8aux_OjJ$3TOP=`FWyh`SK zmneZ4o+h@C=Hi6HGHijt2j6mD5*=`rhLeG_Z68!2B`=t8On+m=K-*`{!VnnjrPAum-?T|9=M{ zrCu@i0Yf1?FE*~*x;Q7L!6`D=IP(f*q^^*^uc8O05RK_HiUK=D9=tHT>+M}X9)}o< zJWdC!0VAOkx7RD)eMfW4=lb1G(*a4fr>c)SCVo_VGGbU6zB=A`aOby`;jl712BC2v zMhAq`O^zcKRmuXlcW1@D1?kI@^F3~3xn}4KAuD#wx-u4togeBO`T9u3FD=7E5p`Rz zXjB=-%72B#=wqLlVn*adMTgE=6^()*hQ=Jz2*JT3oHO|Px)m`OxIR7eeNRS9fVWe}cs?a_s8YoXz=U^!Zi5HOMgX^cVxw1|iZh$LdfC}?O( zgNalSEJ|8v0;mX)azqG`M2i76lpBf_Q?O70uObzsfE2c{+dbayJDl$?Zz;q{X6OIk z+}FPfF;wg?d|5x!){3*sW;lQLtgZ6Jt~gXkwvF#ZQdM11C{&QwNGp#P*`a8_{{6)~ zTkdF&Z(MuqC3>``p|1q7Rdq#{5w|F=8}!cVkkG}C7ixe@?M-$p7PCM2uD})=U@~Sf zx)>vjw;YCCRX6dsgkd%ouV~Mi^T*YE#HCdpDb)3-LE&J0FeJC;_KC<<$BNFw@#69O zC^Nk;{o^OzD1Qq^s6Q&vzbxQRr9 z0)YUZC*PBXFrzCaP1|5wHkk%I6Mg?@6|Fh(Jo){8>e#V|%4R6E>{T~)JJgVikUS6P zWMmXq=UqVv3EiZn6A#ehnz1A?S5YNWTnZ@)U0O2!z%VGli<`0g{Pm-zW<8$10qJvV z_!DPq*_Yod*!L74kxT>%07p@DfbXFAh8Pof(PS!`%2Y6=>7}FHBVI_`qDb;2%d)OT z0`cYZKE3@&cS(IWY@3ythfl476=9v{tx8sOnH`33YQ>Sl zCO-5}@GK2X8%e32UR2-wHA!qvbIGJ~r&r9}pA`+zO?XI@jj0_i$umS6)lUf)gL zZYp_w8o4|wMT15)3x`?Oga?f=h0$MeXu=P&BKLE~0?A)K*Z%fr^M9&gJ{DVt0=yu3 ztS}TYS6CjD4Py~y#7d)s78D$W5WE3l1PW*ylt3|8_stUDlgjc(d&f=Dd}<|I8vuq= zc7$uQs-Ov*X6y(>dtWsX-F?85dVKo1OGQpJ4pn#tE5!`5xYK-LoPT&VgmH|U!Mis5 z%P{q7>s-?NtlzyDHZ?hGqU2A`^-Nxv-NZ>`!!V3a8(L0-dgLW_F_NZflCJAwG~K&P zn0GPBfAC=1wu0J;T0UEny@k7!-MP$MK#sDj@vh1j11D+g&-3WQg10C#FsCakdA`lh zZccsE3}hf2XqsGPp}s)Q0OfcPFebGZ*3hrlkI-{NmQsdm0Cg-{PD}R8 zY#59H@iYLPyU3aENrnGA! {% if not basket.isRead() %} - + + {% else %} + {% endif %} - {{basket.getName()|e}} @@ -26,11 +27,9 @@
        - + From 5309794f338bd2886876b744488e2da6a989a0ba Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Fri, 6 Dec 2019 12:16:47 +0400 Subject: [PATCH 26/40] PHRAS-2848 remove basket description --- templates/mobile/lightbox/index.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/mobile/lightbox/index.html.twig b/templates/mobile/lightbox/index.html.twig index 188a514e86..67f698664f 100644 --- a/templates/mobile/lightbox/index.html.twig +++ b/templates/mobile/lightbox/index.html.twig @@ -114,7 +114,7 @@ {% endif %}

        {{basket.getName()}}

        -

        {{ basket.getDescription() }}

        + {#

        {{ basket.getDescription() }}

        #} {{ basket_length }} {% endif %} @@ -155,7 +155,7 @@ {% endif %}

        {{ basket.getName() }}

        -

        {{ basket.getDescription() }}

        + {#

        {{ basket.getDescription() }}

        #} {{basket_length}} {% endif %} From f475a5c925b9775fe3267ac49a95c57ff7968dcf Mon Sep 17 00:00:00 2001 From: aynsix Date: Fri, 6 Dec 2019 14:24:03 +0400 Subject: [PATCH 27/40] fix api/v3 api_version --- lib/Alchemy/Phrasea/Controller/Api/Result.php | 9 ++++++--- lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php | 2 +- .../Phrasea/Core/Event/Listener/OAuthListener.php | 9 ++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/Result.php b/lib/Alchemy/Phrasea/Controller/Api/Result.php index 15624e1f6e..c7c45b4d0f 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/Result.php +++ b/lib/Alchemy/Phrasea/Controller/Api/Result.php @@ -12,6 +12,7 @@ namespace Alchemy\Phrasea\Controller\Api; use Alchemy\Phrasea\ControllerProvider\Api\V1; +use Alchemy\Phrasea\ControllerProvider\Api\V3; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -268,11 +269,13 @@ class Result public function getVersion() { if (null === $this->version) { - if($this->request->attributes->get('api_version')){ + if ($this->request->attributes->get('api_version')) { $this->version = $this->request->attributes->get('api_version'); - }elseif(mb_strpos($this->request->getPathInfo(), '/api/v1') !== FALSE){ + } elseif (mb_strpos($this->request->getPathInfo(), '/api/v1') !== FALSE) { $this->version = V1::VERSION; - }else{ + } elseif (mb_strpos($this->request->getPathInfo(), '/api/v3') !== FALSE) { + $this->version = V3::VERSION; + } else { $this->version = self::$defaultVersion; } } diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php b/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php index d5add594b2..5925c74921 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php @@ -12,7 +12,7 @@ use Silex\ServiceProviderInterface; class V3 extends Api implements ControllerProviderInterface, ServiceProviderInterface { - const VERSION = '2.0.0'; + const VERSION = '3.0.0'; public function register(Application $app) { diff --git a/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php b/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php index 34c4685149..0dd4984306 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php +++ b/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php @@ -15,6 +15,7 @@ use Alchemy\Phrasea\Authentication\Context; use Alchemy\Phrasea\Controller\Api\Result; use Alchemy\Phrasea\ControllerProvider\Api\V1; use Alchemy\Phrasea\ControllerProvider\Api\V2; +use Alchemy\Phrasea\ControllerProvider\Api\V3; use Alchemy\Phrasea\Core\Configuration\PropertyAccess; use Alchemy\Phrasea\Core\Event\ApiOAuth2EndEvent; use Alchemy\Phrasea\Core\Event\ApiOAuth2StartEvent; @@ -76,11 +77,13 @@ class OAuthListener // Sets the Api Version $CalledController = $request->attributes->get('_controller'); - if(mb_strpos($CalledController, 'controller.api.v1') !== FALSE){ + if (mb_strpos($CalledController, 'controller.api.v1') !== FALSE) { $request->attributes->set('api_version', V1::VERSION); - }elseif(mb_strpos($CalledController, 'controller.api.v2') !== FALSE){ + } elseif(mb_strpos($CalledController, 'controller.api.v2') !== FALSE) { $request->attributes->set('api_version', V2::VERSION); - }else{ + } elseif(mb_strpos($CalledController, 'controller.api.v3') !== FALSE) { + $request->attributes->set('api_version', V3::VERSION); + } else { $request->attributes->set('api_version', $oAuth2Account->getApiVersion()); } From 775e4bd05af6ab89242b8db69684cbd4e31fb473 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Fri, 6 Dec 2019 17:03:23 +0400 Subject: [PATCH 28/40] PHRAS-2848 #comment fix error on firefox --- templates/mobile/lightbox/basket_element.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/mobile/lightbox/basket_element.html.twig b/templates/mobile/lightbox/basket_element.html.twig index 06e6d590a1..db4756347e 100644 --- a/templates/mobile/lightbox/basket_element.html.twig +++ b/templates/mobile/lightbox/basket_element.html.twig @@ -69,10 +69,10 @@ {% if basket_element.getBasket().getValidation() %} {% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanAgree() %}
        - + - +
        From b76e503c0cc3ea963326f8a3733f96c82a5da506 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Fri, 6 Dec 2019 17:08:41 +0400 Subject: [PATCH 29/40] PHRAS-2848 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e909dbb2ab..fe943aebfb 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "normalize-css": "^2.1.0", "npm": "^6.0.0", "npm-modernizr": "^2.8.3", - "phraseanet-production-client": "0.34.84-d", + "phraseanet-production-client": "0.34.85-d", "requirejs": "^2.3.5", "tinymce": "^4.0.28", "underscore": "^1.8.3", diff --git a/yarn.lock b/yarn.lock index 4d9806aeaa..f97d972cc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7577,10 +7577,10 @@ phraseanet-common@^0.4.5-d: js-cookie "^2.1.0" pym.js "^1.3.1" -phraseanet-production-client@0.34.84-d: - version "0.34.84-d" - resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.84-d.tgz#ccf091b51209c6d42fd3dc1e4f05f6bbefe44ea5" - integrity sha512-ZZZOIR7a+4AVwkx0s3e3P23sobQjWVFXrX3FnB6BhEC3qpR0b44bH1Dc7n53ciL5UQMmTNUNYoVTMpMfHpNrFA== +phraseanet-production-client@0.34.85-d: + version "0.34.85-d" + resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.85-d.tgz#e62f42f3464b664a56c2f0af3d7f5e7f3fcff802" + integrity sha512-V1tlEq24RMoGWnH7wHV5N/hCUxNfCiDgNaobcwfQMi/Hhdi0Xm3a1qX135w4B5xWZKilSfKNMIateiFI46xadw== dependencies: "@mapbox/mapbox-gl-language" "^0.9.2" "@turf/turf" "^5.1.6" From 1c0b1db9c7dffdc009c1b11ecc53c1ac1d4512ed Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 11 Dec 2019 11:48:23 +0400 Subject: [PATCH 30/40] exlu collection in quarantaine when upload --- .../Border/Checker/AbstractChecker.php | 14 ++++- .../Phrasea/Border/Checker/Filename.php | 14 ++++- lib/Alchemy/Phrasea/Border/Checker/Sha256.php | 12 +++- lib/Alchemy/Phrasea/Border/Checker/UUID.php | 12 +++- .../Provider/BorderManagerServiceProvider.php | 14 +++++ .../Databox/Record/LegacyRecordRepository.php | 61 +++++++++++++++++++ .../Databox/Record/RecordRepository.php | 14 +++++ lib/classes/record/adapter.php | 37 +++++++++++ 8 files changed, 172 insertions(+), 6 deletions(-) diff --git a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php index 8b4de0fb58..c929cf13bf 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php +++ b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php @@ -34,6 +34,11 @@ abstract class AbstractChecker implements CheckerInterface */ protected $collections = []; + /** + * @var \collection[] + */ + protected $ignoreCollections = []; + public function __construct(Application $app) { $this->app = $app; @@ -44,7 +49,7 @@ abstract class AbstractChecker implements CheckerInterface * Warning, you can not restrict on both databoxes and collections * * @param \databox[] $databoxes A databox or an array of databoxes - * @return bool + * @return \databox[] * * @throws \LogicException If already restricted to collections * @throws \InvalidArgumentException In case invalid databoxes are provided @@ -72,7 +77,7 @@ abstract class AbstractChecker implements CheckerInterface * Warning, you can not restrict on both databoxes and collections * * @param \collection[] $collections - * @return bool + * @return \collection[] * * @throws \LogicException If already restricted to databoxes * @throws \InvalidArgumentException In case invalid collections are provided @@ -95,6 +100,11 @@ abstract class AbstractChecker implements CheckerInterface return $this->collections; } + public function setIgnoreCollections($collections) + { + $this->ignoreCollections = $collections; + } + /** * Returns true if the checker should be executed against the current file * diff --git a/lib/Alchemy/Phrasea/Border/Checker/Filename.php b/lib/Alchemy/Phrasea/Border/Checker/Filename.php index ec4f0b0be4..0aa5661f95 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Filename.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Filename.php @@ -45,8 +45,18 @@ class Filename extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty(\record_adapter::get_records_by_originalname( - $file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1 + $excludedCollIds = []; + if (!empty($this->ignoreCollections)) { + foreach ($this->ignoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty(\record_adapter::getRecordsByOriginalnameWithExcludedCollIds( + $file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1, $excludedCollIds )); return new Response($boolean, $this); diff --git a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php index d17b28e5b9..7f994a55c2 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php @@ -34,7 +34,17 @@ class Sha256 extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256($file->getSha256())); + $excludedCollIds = []; + if (!empty($this->ignoreCollections)) { + foreach ($this->ignoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256WithExcludedCollIds($file->getSha256(), $excludedCollIds)); return new Response($boolean, $this); } diff --git a/lib/Alchemy/Phrasea/Border/Checker/UUID.php b/lib/Alchemy/Phrasea/Border/Checker/UUID.php index c3857fbe76..86960a045b 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/UUID.php +++ b/lib/Alchemy/Phrasea/Border/Checker/UUID.php @@ -33,7 +33,17 @@ class UUID extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuid($file->getUUID())); + $excludedCollIds = []; + if (!empty($this->ignoreCollections)) { + foreach ($this->ignoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuidWithExcludedCollIds($file->getUUID(), $excludedCollIds)); return new Response($boolean, $this); } diff --git a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php index 36f0ed0e7e..ff6d083077 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php @@ -78,6 +78,20 @@ class BorderManagerServiceProvider implements ServiceProviderInterface $checkerObj->restrictToCollections($collections); } + + if (isset($checker['compare-ignore-collections'])) { + $collections = []; + foreach ($checker['compare-ignore-collections'] as $base_id) { + try { + $collections[] = \collection::getByBaseId($app, $base_id); + } catch (\Exception $e) { + throw new \InvalidArgumentException('Invalid collection option'); + } + } + + $checkerObj->setIgnoreCollections($collections); + } + $registeredCheckers[] = $checkerObj; } catch (\InvalidArgumentException $e) { $app['monolog']->error( diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 522d49baae..eedeb9f042 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -82,6 +82,34 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } + public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = []) + { + static $sql; + + $params = []; + $types = []; + + if (!$sql) { + $qb = $this->createSelectBuilder() + ->where('sha256 = :sha256'); + + $params['sha256'] = $sha256; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + + $params['coll_id'] = $excludedCollIds; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + } + + $sql = $qb->getSQL(); + } + + $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + + return $this->mapRecordsFromResultSet($result); + } + /** * @param string $uuid * @return \record_adapter[] @@ -99,6 +127,39 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } + /** + * @param string $uuid + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = []) + { + static $sql; + + $params = ['uuid' => $uuid]; + $types = []; + + if (!$sql) { + $qb = $this->createSelectBuilder() + ->where('uuid = :uuid'); + + $params['uuid'] = $uuid; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + + $params['coll_id'] = $excludedCollIds; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + } + + $sql = $qb->getSQL(); + } + + $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + + return $this->mapRecordsFromResultSet($result); + } + public function findByRecordIds(array $recordIds) { static $sql; diff --git a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php index 0da49bb00f..8817610cef 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php @@ -26,12 +26,26 @@ interface RecordRepository */ public function findBySha256($sha256); + /** + * @param string $sha256 + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = []); + /** * @param string $uuid * @return \record_adapter[] */ public function findByUuid($uuid); + /** + * @param string $uuid + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = []); + /** * @param array $recordIds * @return \record_adapter[] diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index c4045d9fc5..ec7d997f1e 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1673,6 +1673,43 @@ class record_adapter implements RecordInterface, cache_cacheableInterface return $records; } + public static function getRecordsByOriginalnameWithExcludedCollIds(databox $databox, $original_name, $caseSensitive = false, $offset_start = 0, $how_many = 10, $excludedCollIds = []) + { + $offset_start = max(0, (int)$offset_start); + $how_many = max(1, (int)$how_many); + $collate = $caseSensitive ? 'utf8_bin' : 'utf8_unicode_ci'; + + $qb = $databox->get_connection()->createQueryBuilder() + ->select('record_id') + ->from('record') + ->where('originalname = :original_name COLLATE :collate') + ; + + $params = ['original_name' => $original_name, 'collate' => $collate]; + $types = []; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + + $params['coll_id'] = $excludedCollIds; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + } + + $sql = $qb->setFirstResult($offset_start) + ->setMaxResults($how_many) + ->getSQL() + ; + + $rs = $databox->get_connection()->fetchAll($sql, $params, $types); + + $records = []; + foreach ($rs as $row) { + $records[] = $databox->get_record($row['record_id']); + } + + return $records; + } + /** * @return set_selection|record_adapter[] * @throws Exception From 9ac196784a2257b36f476290aba5ae8982195348 Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 11 Dec 2019 12:41:43 +0400 Subject: [PATCH 31/40] change sql params form --- .../Databox/Record/LegacyRecordRepository.php | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index eedeb9f042..0e2cd7adea 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -86,26 +86,26 @@ class LegacyRecordRepository implements RecordRepository { static $sql; - $params = []; - $types = []; - if (!$sql) { $qb = $this->createSelectBuilder() ->where('sha256 = :sha256'); - $params['sha256'] = $sha256; - if (!empty($excludedCollIds)) { $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); - - $params['coll_id'] = $excludedCollIds; - $types[':coll_id'] = Connection::PARAM_INT_ARRAY; } $sql = $qb->getSQL(); } - $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + $result = $this->databox->get_connection()->fetchAll($sql, + [ + 'sha256' => $sha256, + 'coll_id' => $excludedCollIds + ], + [ + ':coll_id' => Connection::PARAM_INT_ARRAY + ] + ); return $this->mapRecordsFromResultSet($result); } @@ -136,26 +136,26 @@ class LegacyRecordRepository implements RecordRepository { static $sql; - $params = ['uuid' => $uuid]; - $types = []; - if (!$sql) { $qb = $this->createSelectBuilder() ->where('uuid = :uuid'); - $params['uuid'] = $uuid; - if (!empty($excludedCollIds)) { $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); - - $params['coll_id'] = $excludedCollIds; - $types[':coll_id'] = Connection::PARAM_INT_ARRAY; } $sql = $qb->getSQL(); } - $result = $this->databox->get_connection()->fetchAll($sql, $params, $types); + $result = $this->databox->get_connection()->fetchAll($sql, + [ + 'uuid' => $uuid, + 'coll_id' => $excludedCollIds + ], + [ + ':coll_id' => Connection::PARAM_INT_ARRAY + ] + ); return $this->mapRecordsFromResultSet($result); } From 8eb6ae5dfa76fa38ba5767654268a9e63fceabe5 Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 11 Dec 2019 18:18:30 +0400 Subject: [PATCH 32/40] change variable name --- lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php | 6 +++--- lib/Alchemy/Phrasea/Border/Checker/Filename.php | 4 ++-- lib/Alchemy/Phrasea/Border/Checker/Sha256.php | 4 ++-- lib/Alchemy/Phrasea/Border/Checker/UUID.php | 4 ++-- .../Phrasea/Core/Provider/BorderManagerServiceProvider.php | 2 +- .../Phrasea/Databox/Record/LegacyRecordRepository.php | 7 ++++--- lib/classes/record/adapter.php | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php index c929cf13bf..de6f4c25d6 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php +++ b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php @@ -37,7 +37,7 @@ abstract class AbstractChecker implements CheckerInterface /** * @var \collection[] */ - protected $ignoreCollections = []; + protected $compareIgnoreCollections = []; public function __construct(Application $app) { @@ -100,9 +100,9 @@ abstract class AbstractChecker implements CheckerInterface return $this->collections; } - public function setIgnoreCollections($collections) + public function setCompareIgnoreCollections($collections) { - $this->ignoreCollections = $collections; + $this->compareIgnoreCollections = $collections; } /** diff --git a/lib/Alchemy/Phrasea/Border/Checker/Filename.php b/lib/Alchemy/Phrasea/Border/Checker/Filename.php index 0aa5661f95..ea1c25a7a6 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Filename.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Filename.php @@ -46,8 +46,8 @@ class Filename extends AbstractChecker public function check(EntityManager $em, File $file) { $excludedCollIds = []; - if (!empty($this->ignoreCollections)) { - foreach ($this->ignoreCollections as $collection) { + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { // use only collection in the same databox and retrieve the coll_id if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { $excludedCollIds[] = $collection->get_coll_id(); diff --git a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php index 7f994a55c2..5116e35dfd 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php @@ -35,8 +35,8 @@ class Sha256 extends AbstractChecker public function check(EntityManager $em, File $file) { $excludedCollIds = []; - if (!empty($this->ignoreCollections)) { - foreach ($this->ignoreCollections as $collection) { + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { // use only collection in the same databox and retrieve the coll_id if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { $excludedCollIds[] = $collection->get_coll_id(); diff --git a/lib/Alchemy/Phrasea/Border/Checker/UUID.php b/lib/Alchemy/Phrasea/Border/Checker/UUID.php index 86960a045b..cdacf973a5 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/UUID.php +++ b/lib/Alchemy/Phrasea/Border/Checker/UUID.php @@ -34,8 +34,8 @@ class UUID extends AbstractChecker public function check(EntityManager $em, File $file) { $excludedCollIds = []; - if (!empty($this->ignoreCollections)) { - foreach ($this->ignoreCollections as $collection) { + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { // use only collection in the same databox and retrieve the coll_id if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { $excludedCollIds[] = $collection->get_coll_id(); diff --git a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php index ff6d083077..d7a0f636f9 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php @@ -89,7 +89,7 @@ class BorderManagerServiceProvider implements ServiceProviderInterface } } - $checkerObj->setIgnoreCollections($collections); + $checkerObj->setCompareIgnoreCollections($collections); } $registeredCheckers[] = $checkerObj; diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 0e2cd7adea..2d3c4564e4 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -138,7 +138,8 @@ class LegacyRecordRepository implements RecordRepository if (!$sql) { $qb = $this->createSelectBuilder() - ->where('uuid = :uuid'); + ->where('uuid = :uuid') + ; if (!empty($excludedCollIds)) { $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); @@ -149,8 +150,8 @@ class LegacyRecordRepository implements RecordRepository $result = $this->databox->get_connection()->fetchAll($sql, [ - 'uuid' => $uuid, - 'coll_id' => $excludedCollIds + 'uuid' => $uuid, + 'coll_id' => $excludedCollIds ], [ ':coll_id' => Connection::PARAM_INT_ARRAY diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index ec7d997f1e..e544dae308 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1692,7 +1692,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); $params['coll_id'] = $excludedCollIds; - $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; } $sql = $qb->setFirstResult($offset_start) From 713108078843350d3a89c352252edb7908a42127 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Wed, 11 Dec 2019 18:26:44 +0400 Subject: [PATCH 33/40] PHRAS-2856 #comment Fix prod Basket and story : Set records order --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fe943aebfb..7525421e67 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "normalize-css": "^2.1.0", "npm": "^6.0.0", "npm-modernizr": "^2.8.3", - "phraseanet-production-client": "0.34.85-d", + "phraseanet-production-client": "^0.34.86-d", "requirejs": "^2.3.5", "tinymce": "^4.0.28", "underscore": "^1.8.3", diff --git a/yarn.lock b/yarn.lock index f97d972cc3..a7d490caab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7577,10 +7577,10 @@ phraseanet-common@^0.4.5-d: js-cookie "^2.1.0" pym.js "^1.3.1" -phraseanet-production-client@0.34.85-d: - version "0.34.85-d" - resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.85-d.tgz#e62f42f3464b664a56c2f0af3d7f5e7f3fcff802" - integrity sha512-V1tlEq24RMoGWnH7wHV5N/hCUxNfCiDgNaobcwfQMi/Hhdi0Xm3a1qX135w4B5xWZKilSfKNMIateiFI46xadw== +phraseanet-production-client@^0.34.86-d: + version "0.34.86-d" + resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.86-d.tgz#51e6c6fb17fcd2695cee90fb3d972c781057fd78" + integrity sha512-12o7pcRZAJ/5Ote4DbkaRxLz2GIZBUcZf53FB+GHVFxhds5ia6UNDCPhYP5vX4hhHtO/Y6Mj/BOlOjnoyi+k1g== dependencies: "@mapbox/mapbox-gl-language" "^0.9.2" "@turf/turf" "^5.1.6" From 5a703f207ae9dab9f1b0d6d70b20d86744d5c020 Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 12 Dec 2019 12:13:56 +0400 Subject: [PATCH 34/40] fix record order in story --- lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 522d49baae..9924b8be94 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -140,6 +140,7 @@ class LegacyRecordRepository implements RecordRepository 's.rid_parent IN (:storyIds)', 'r.parent_record_id = 0' ) + ->orderBy('s.ord', 'ASC') ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) ; From 86752ad714ebf0e360428a870552022af84831eb Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Thu, 12 Dec 2019 15:04:58 +0400 Subject: [PATCH 35/40] PHRAS-2848 Fix lightbox mobile --- resources/www/lightbox/styles/main-mobile.scss | 9 ++++++++- templates/mobile/lightbox/basket_element.html.twig | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/resources/www/lightbox/styles/main-mobile.scss b/resources/www/lightbox/styles/main-mobile.scss index e5c9e1e93e..28f50fd064 100644 --- a/resources/www/lightbox/styles/main-mobile.scss +++ b/resources/www/lightbox/styles/main-mobile.scss @@ -650,8 +650,12 @@ button.confirm_report { min-height: 26px; padding: 10px 0; } - +.ui-controlgroup, fieldset.ui-controlgroup { + margin: 10px 0!important; +} .ui-listview.lightbox-list-view { + margin-top: 0; + margin-bottom: 0; & > .ui-li-static { padding: .7em 1em; text-overflow: inherit; @@ -687,6 +691,9 @@ button.confirm_report { .center-image { text-align: center; + iframe { + min-height: 240px; + } } /*validate page*/ diff --git a/templates/mobile/lightbox/basket_element.html.twig b/templates/mobile/lightbox/basket_element.html.twig index db4756347e..54736a3fb2 100644 --- a/templates/mobile/lightbox/basket_element.html.twig +++ b/templates/mobile/lightbox/basket_element.html.twig @@ -77,8 +77,8 @@ for="radio-view-no_{{ basket_element.getId() }}">{{ 'validation:: NON' | trans }} {% endif %} -
        - + From e037e15e950d52728dc5bdabd8e16f23e0356147 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Thu, 12 Dec 2019 15:14:19 +0400 Subject: [PATCH 36/40] PHRAS-2848 Fix video display --- resources/www/lightbox/styles/main-mobile.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/www/lightbox/styles/main-mobile.scss b/resources/www/lightbox/styles/main-mobile.scss index 28f50fd064..7f53448267 100644 --- a/resources/www/lightbox/styles/main-mobile.scss +++ b/resources/www/lightbox/styles/main-mobile.scss @@ -693,6 +693,7 @@ button.confirm_report { text-align: center; iframe { min-height: 240px; + width: auto; } } From 2b5902a1b68bdd3689862b86edc106bd795b5d74 Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 12 Dec 2019 16:47:44 +0400 Subject: [PATCH 37/40] php-unoconv 0.3.1 and media-alchemyst 0.5.5 --- composer.json | 2 +- composer.lock | 337 +++++++++++++++++++++++++------------------------- 2 files changed, 169 insertions(+), 170 deletions(-) diff --git a/composer.json b/composer.json index 47635b0e47..7497b86823 100644 --- a/composer.json +++ b/composer.json @@ -84,7 +84,7 @@ "league/flysystem": "^1.0", "league/flysystem-aws-s3-v2": "^1.0", "league/fractal": "dev-webgalleries#af1acc0275438571bc8c1d08a05a4b5af92c9f97 as 0.13.0", - "media-alchemyst/media-alchemyst": "^0.5", + "media-alchemyst/media-alchemyst": "^0.5.5", "monolog/monolog": "~1.3", "mrclay/minify": "~2.1.6", "neutron/process-manager": "2.0.x-dev@dev", diff --git a/composer.lock b/composer.lock index 482cce9daf..7c347581f1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "e5bed7b0b8cb8b45ffffc4965a7689db", - "content-hash": "f3b1fc0a30bf14b05e57ce673550d9c0", + "content-hash": "d0c8742d02e8d51c702c26ecb5502b30", "packages": [ { "name": "alchemy-fr/tcpdf-clone", @@ -71,7 +70,7 @@ "source": "https://github.com/alchemy-fr/tcpdf-clone/tree/6.0.039", "issues": "https://github.com/alchemy-fr/tcpdf-clone/issues" }, - "time": "2013-10-13 16:11:17" + "time": "2013-10-13T16:11:17+00:00" }, { "name": "alchemy/binary-driver", @@ -128,7 +127,7 @@ "binary", "driver" ], - "time": "2016-03-02 13:49:15" + "time": "2016-03-02T13:49:15+00:00" }, { "name": "alchemy/embed-bundle", @@ -172,7 +171,7 @@ } ], "description": "Embed resources bundle", - "time": "2019-10-09 14:34:23" + "time": "2019-10-09T14:34:23+00:00" }, { "name": "alchemy/geonames-api-consumer", @@ -210,7 +209,7 @@ "keywords": [ "geonames" ], - "time": "2014-02-05 15:29:39" + "time": "2014-02-05T15:29:39+00:00" }, { "name": "alchemy/ghostscript", @@ -262,7 +261,7 @@ "ghostscript", "pdf" ], - "time": "2013-06-25 09:12:58" + "time": "2013-06-25T09:12:58+00:00" }, { "name": "alchemy/mediavorus", @@ -324,7 +323,7 @@ "keywords": [ "metadata" ], - "time": "2019-01-22 11:23:34" + "time": "2019-01-22T11:23:34+00:00" }, { "name": "alchemy/oauth2php", @@ -347,7 +346,7 @@ ] }, "notification-url": "https://packagist.org/downloads/", - "time": "2019-01-17 14:34:10" + "time": "2019-01-17T14:34:10+00:00" }, { "name": "alchemy/phlickr", @@ -370,7 +369,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "time": "2014-12-15 14:27:57" + "time": "2014-12-15T14:27:57+00:00" }, { "name": "alchemy/phpexiftool", @@ -443,7 +442,7 @@ "exiftool", "metadata" ], - "time": "2019-02-13 13:06:43" + "time": "2019-02-13T13:06:43+00:00" }, { "name": "alchemy/queue-bundle", @@ -491,7 +490,7 @@ } ], "description": "Symfony bundle for alchemy/queue-component", - "time": "2016-10-04 14:19:39" + "time": "2016-10-04T14:19:39+00:00" }, { "name": "alchemy/queue-component", @@ -536,7 +535,7 @@ "MIT" ], "description": "Message queue component", - "time": "2016-10-05 10:41:36" + "time": "2016-10-05T10:41:36+00:00" }, { "name": "alchemy/rest-bundle", @@ -588,7 +587,7 @@ } ], "description": "Simple REST utility bundle", - "time": "2016-05-16 09:37:34" + "time": "2016-05-16T09:37:34+00:00" }, { "name": "alchemy/symfony-cors", @@ -635,7 +634,7 @@ } ], "description": "A library that adds CORS services to Silex/Symfony Applications", - "time": "2015-12-17 15:34:43" + "time": "2015-12-17T15:34:43+00:00" }, { "name": "alchemy/task-manager", @@ -698,7 +697,7 @@ "parallel", "process" ], - "time": "2016-11-30 13:34:30" + "time": "2016-11-30T13:34:30+00:00" }, { "name": "alchemy/worker-bundle", @@ -747,7 +746,7 @@ } ], "description": "Symfony bundle for alchemy/worker-component", - "time": "2016-12-06 10:39:58" + "time": "2016-12-06T10:39:58+00:00" }, { "name": "alchemy/worker-component", @@ -793,7 +792,7 @@ "MIT" ], "description": "Message queue worker component", - "time": "2016-11-14 16:41:16" + "time": "2016-11-14T16:41:16+00:00" }, { "name": "alchemy/zippy", @@ -855,7 +854,7 @@ "tar", "zip" ], - "time": "2016-02-15 22:46:40" + "time": "2016-02-15T22:46:40+00:00" }, { "name": "aws/aws-sdk-php", @@ -918,7 +917,7 @@ "s3", "sdk" ], - "time": "2016-07-25 18:03:20" + "time": "2016-07-25T18:03:20+00:00" }, { "name": "beberlei/assert", @@ -973,7 +972,7 @@ "assertion", "validation" ], - "time": "2017-01-24 15:14:39" + "time": "2017-01-24T15:14:39+00:00" }, { "name": "behat/transliterator", @@ -1013,7 +1012,7 @@ "slug", "transliterator" ], - "time": "2015-09-28 16:26:35" + "time": "2015-09-28T16:26:35+00:00" }, { "name": "box/spout", @@ -1081,7 +1080,7 @@ "write", "xlsx" ], - "time": "2017-09-25 19:44:35" + "time": "2017-09-25T19:44:35+00:00" }, { "name": "cocur/slugify", @@ -1145,7 +1144,7 @@ "slug", "slugify" ], - "time": "2016-08-09 20:10:17" + "time": "2016-08-09T20:10:17+00:00" }, { "name": "czproject/git-php", @@ -1187,7 +1186,7 @@ "keywords": [ "git" ], - "time": "2019-02-09 13:11:36" + "time": "2019-02-09T13:11:36+00:00" }, { "name": "dailymotion/sdk", @@ -1220,7 +1219,7 @@ "dailymotion", "sdk" ], - "time": "2015-11-20 11:18:32" + "time": "2015-11-20T11:18:32+00:00" }, { "name": "data-uri/data-uri", @@ -1265,7 +1264,7 @@ "data-uri", "uri" ], - "time": "2014-08-22 15:01:57" + "time": "2014-08-22T15:01:57+00:00" }, { "name": "dflydev/doctrine-orm-service-provider", @@ -1327,7 +1326,7 @@ "pimple", "silex" ], - "time": "2015-09-07 12:16:54" + "time": "2015-09-07T12:16:54+00:00" }, { "name": "doctrine/annotations", @@ -1395,7 +1394,7 @@ "docblock", "parser" ], - "time": "2015-08-31 12:32:49" + "time": "2015-08-31T12:32:49+00:00" }, { "name": "doctrine/cache", @@ -1407,7 +1406,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", + "url": "https://api.github.com/repos/doctrine/cache/zipball/b6f544a20f4807e81f7044d31e679ccbb1866dc3", "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3", "shasum": "" }, @@ -1465,7 +1464,7 @@ "cache", "caching" ], - "time": "2016-10-29 11:16:17" + "time": "2016-10-29T11:16:17+00:00" }, { "name": "doctrine/collections", @@ -1531,7 +1530,7 @@ "collections", "iterator" ], - "time": "2015-04-14 22:21:58" + "time": "2015-04-14T22:21:58+00:00" }, { "name": "doctrine/common", @@ -1604,7 +1603,7 @@ "persistence", "spl" ], - "time": "2016-11-30 16:50:46" + "time": "2016-11-30T16:50:46+00:00" }, { "name": "doctrine/dbal", @@ -1675,7 +1674,7 @@ "persistence", "queryobject" ], - "time": "2017-01-23 23:17:10" + "time": "2017-01-23T23:17:10+00:00" }, { "name": "doctrine/inflector", @@ -1742,7 +1741,7 @@ "singularize", "string" ], - "time": "2015-11-06 14:35:42" + "time": "2015-11-06T14:35:42+00:00" }, { "name": "doctrine/instantiator", @@ -1796,7 +1795,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "doctrine/lexer", @@ -1850,7 +1849,7 @@ "lexer", "parser" ], - "time": "2014-09-09 13:34:57" + "time": "2014-09-09T13:34:57+00:00" }, { "name": "doctrine/migrations", @@ -1924,7 +1923,7 @@ "database", "migrations" ], - "time": "2016-12-25 22:54:00" + "time": "2016-12-25T22:54:00+00:00" }, { "name": "doctrine/orm", @@ -2000,7 +1999,7 @@ "database", "orm" ], - "time": "2016-12-18 15:42:34" + "time": "2016-12-18T15:42:34+00:00" }, { "name": "elasticsearch/elasticsearch", @@ -2054,7 +2053,7 @@ "elasticsearch", "search" ], - "time": "2016-11-30 17:15:05" + "time": "2016-11-30T17:15:05+00:00" }, { "name": "evenement/evenement", @@ -2094,7 +2093,7 @@ "keywords": [ "event-dispatcher" ], - "time": "2012-05-30 15:01:08" + "time": "2012-05-30T15:01:08+00:00" }, { "name": "facebook/graph-sdk", @@ -2152,7 +2151,7 @@ "facebook", "sdk" ], - "time": "2017-08-16 17:28:07" + "time": "2017-08-16T17:28:07+00:00" }, { "name": "firebase/php-jwt", @@ -2195,7 +2194,7 @@ ], "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", "homepage": "https://github.com/firebase/php-jwt", - "time": "2015-07-22 18:31:08" + "time": "2015-07-22T18:31:08+00:00" }, { "name": "gedmo/doctrine-extensions", @@ -2273,7 +2272,7 @@ "tree", "uploadable" ], - "time": "2015-02-24 21:41:37" + "time": "2015-02-24T21:41:37+00:00" }, { "name": "goodby/csv", @@ -2330,7 +2329,7 @@ "export", "import" ], - "time": "2015-06-29 10:28:19" + "time": "2015-06-29T10:28:19+00:00" }, { "name": "google/apiclient", @@ -2389,7 +2388,7 @@ "keywords": [ "google" ], - "time": "2017-11-03 01:19:53" + "time": "2017-11-03T01:19:53+00:00" }, { "name": "google/apiclient-services", @@ -2426,7 +2425,7 @@ "keywords": [ "google" ], - "time": "2017-11-25 00:23:12" + "time": "2017-11-25T00:23:12+00:00" }, { "name": "google/auth", @@ -2471,7 +2470,7 @@ "google", "oauth2" ], - "time": "2017-10-10 17:01:45" + "time": "2017-10-10T17:01:45+00:00" }, { "name": "google/recaptcha", @@ -2516,7 +2515,7 @@ "recaptcha", "spam" ], - "time": "2017-03-09 18:44:34" + "time": "2017-03-09T18:44:34+00:00" }, { "name": "guzzle/guzzle", @@ -2612,7 +2611,7 @@ "web service" ], "abandoned": "guzzlehttp/guzzle", - "time": "2015-03-18 18:23:50" + "time": "2015-03-18T18:23:50+00:00" }, { "name": "guzzlehttp/guzzle", @@ -2677,7 +2676,7 @@ "rest", "web service" ], - "time": "2017-06-22 18:50:49" + "time": "2017-06-22T18:50:49+00:00" }, { "name": "guzzlehttp/promises", @@ -2728,7 +2727,7 @@ "keywords": [ "promise" ], - "time": "2016-12-20 10:07:11" + "time": "2016-12-20T10:07:11+00:00" }, { "name": "guzzlehttp/psr7", @@ -2793,7 +2792,7 @@ "uri", "url" ], - "time": "2017-03-20 17:10:46" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "guzzlehttp/ringphp", @@ -2844,7 +2843,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" + "time": "2015-05-20T03:37:09+00:00" }, { "name": "guzzlehttp/streams", @@ -2894,7 +2893,7 @@ "Guzzle", "stream" ], - "time": "2014-10-12 19:18:40" + "time": "2014-10-12T19:18:40+00:00" }, { "name": "hoa/compiler", @@ -2974,7 +2973,7 @@ "trace", "uniform" ], - "time": "2015-10-29 21:35:12" + "time": "2015-10-29T21:35:12+00:00" }, { "name": "hoa/console", @@ -3046,7 +3045,7 @@ "tput", "window" ], - "time": "2015-07-27 07:52:10" + "time": "2015-07-27T07:52:10+00:00" }, { "name": "hoa/core", @@ -3114,7 +3113,7 @@ "protocol" ], "abandoned": "hoa/consistency", - "time": "2015-11-09 06:51:06" + "time": "2015-11-09T06:51:06+00:00" }, { "name": "hoa/dispatcher", @@ -3174,7 +3173,7 @@ "kit", "library" ], - "time": "2015-11-09 06:52:08" + "time": "2015-11-09T06:52:08+00:00" }, { "name": "hoa/file", @@ -3234,7 +3233,7 @@ "link", "temporary" ], - "time": "2015-11-09 06:55:20" + "time": "2015-11-09T06:55:20+00:00" }, { "name": "hoa/iterator", @@ -3287,7 +3286,7 @@ "iterator", "library" ], - "time": "2015-10-29 21:37:16" + "time": "2015-10-29T21:37:16+00:00" }, { "name": "hoa/math", @@ -3349,7 +3348,7 @@ "sampler", "set" ], - "time": "2015-10-26 15:22:52" + "time": "2015-10-26T15:22:52+00:00" }, { "name": "hoa/regex", @@ -3403,7 +3402,7 @@ "library", "regex" ], - "time": "2015-08-13 06:48:47" + "time": "2015-08-13T06:48:47+00:00" }, { "name": "hoa/router", @@ -3455,7 +3454,7 @@ "library", "router" ], - "time": "2015-10-21 14:12:51" + "time": "2015-10-21T14:12:51+00:00" }, { "name": "hoa/stream", @@ -3513,7 +3512,7 @@ "stream", "wrapper" ], - "time": "2015-10-26 12:21:43" + "time": "2015-10-26T12:21:43+00:00" }, { "name": "hoa/ustring", @@ -3572,7 +3571,7 @@ "string", "unicode" ], - "time": "2015-11-09 06:44:33" + "time": "2015-11-09T06:44:33+00:00" }, { "name": "hoa/visitor", @@ -3627,7 +3626,7 @@ "visit", "visitor" ], - "time": "2015-08-17 06:30:58" + "time": "2015-08-17T06:30:58+00:00" }, { "name": "igorw/get-in", @@ -3672,7 +3671,7 @@ "assoc-array", "hash-map" ], - "time": "2014-12-15 23:03:51" + "time": "2014-12-15T23:03:51+00:00" }, { "name": "imagine/imagine", @@ -3731,7 +3730,7 @@ "support": { "source": "https://github.com/alchemy-fr/Imagine/tree/alchemy-0.6.2" }, - "time": "2015-01-13 18:12:26" + "time": "2015-01-13T18:12:26+00:00" }, { "name": "ircmaxell/password-compat", @@ -3773,7 +3772,7 @@ "hashing", "password" ], - "time": "2014-11-20 16:49:30" + "time": "2014-11-20T16:49:30+00:00" }, { "name": "ircmaxell/security-lib", @@ -3819,7 +3818,7 @@ ], "description": "A Base Security Library", "homepage": "https://github.com/ircmaxell/SecurityLib", - "time": "2015-03-20 14:31:23" + "time": "2015-03-20T14:31:23+00:00" }, { "name": "jms/metadata", @@ -3870,7 +3869,7 @@ "xml", "yaml" ], - "time": "2016-12-05 10:18:33" + "time": "2016-12-05T10:18:33+00:00" }, { "name": "jms/parser-lib", @@ -3905,7 +3904,7 @@ "Apache2" ], "description": "A library for easily creating recursive-descent parsers.", - "time": "2012-11-18 18:08:43" + "time": "2012-11-18T18:08:43+00:00" }, { "name": "jms/serializer", @@ -3975,7 +3974,7 @@ "serialization", "xml" ], - "time": "2014-03-18 08:39:00" + "time": "2014-03-18T08:39:00+00:00" }, { "name": "jms/translation-bundle", @@ -4051,7 +4050,7 @@ "support": { "source": "https://github.com/alchemy-fr/JMSTranslationBundle/tree/rebase-2015-10-20" }, - "time": "2015-11-04 15:09:44" + "time": "2015-11-04T15:09:44+00:00" }, { "name": "justinrainbow/json-schema", @@ -4117,7 +4116,7 @@ "json", "schema" ], - "time": "2016-05-10 20:38:51" + "time": "2016-05-10T20:38:51+00:00" }, { "name": "league/flysystem", @@ -4200,7 +4199,7 @@ "sftp", "storage" ], - "time": "2017-01-30 17:41:17" + "time": "2017-01-30T17:41:17+00:00" }, { "name": "league/flysystem-aws-s3-v2", @@ -4247,7 +4246,7 @@ } ], "description": "Flysystem adapter for AWS S3 SDK v2", - "time": "2015-10-15 15:55:48" + "time": "2015-10-15T15:55:48+00:00" }, { "name": "league/fractal", @@ -4308,20 +4307,20 @@ "league", "rest" ], - "time": "2016-12-02 14:55:48" + "time": "2016-12-02T14:55:48+00:00" }, { "name": "media-alchemyst/media-alchemyst", - "version": "0.5.2", + "version": "0.5.5", "source": { "type": "git", "url": "https://github.com/alchemy-fr/Media-Alchemyst.git", - "reference": "5d2fe6dd95215804202ecf0466fd9cfaeedd0140" + "reference": "3bd3204b69882f495adfb617383a077face92ed0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/Media-Alchemyst/zipball/5d2fe6dd95215804202ecf0466fd9cfaeedd0140", - "reference": "5d2fe6dd95215804202ecf0466fd9cfaeedd0140", + "url": "https://api.github.com/repos/alchemy-fr/Media-Alchemyst/zipball/3bd3204b69882f495adfb617383a077face92ed0", + "reference": "3bd3204b69882f495adfb617383a077face92ed0", "shasum": "" }, "require": { @@ -4333,7 +4332,7 @@ "php": ">=5.3.3", "php-ffmpeg/php-ffmpeg": ">=0.4.2,<0.6", "php-mp4box/php-mp4box": "~0.3.0", - "php-unoconv/php-unoconv": "~0.3.0", + "php-unoconv/php-unoconv": "~0.3.1", "pimple/pimple": "~1.0", "swftools/swftools": "~0.3.0", "symfony/console": "^2.1|^3.0", @@ -4382,7 +4381,7 @@ "video", "video processing" ], - "time": "2019-01-25 12:09:11" + "time": "2019-12-11T07:20:45+00:00" }, { "name": "monolog/monolog", @@ -4460,7 +4459,7 @@ "logging", "psr-3" ], - "time": "2016-11-26 00:15:39" + "time": "2016-11-26T00:15:39+00:00" }, { "name": "mrclay/minify", @@ -4500,7 +4499,7 @@ ], "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", "homepage": "http://code.google.com/p/minify/", - "time": "2013-07-23 19:58:28" + "time": "2013-07-23T19:58:28+00:00" }, { "name": "neutron/process-manager", @@ -4539,7 +4538,7 @@ "homepage": "http://www.lickmychip.com/" } ], - "time": "2014-02-13 20:27:33" + "time": "2014-02-13T20:27:33+00:00" }, { "name": "neutron/recaptcha", @@ -4583,7 +4582,7 @@ } ], "description": "ReCaptcha Client", - "time": "2013-02-14 13:42:00" + "time": "2013-02-14T13:42:00+00:00" }, { "name": "neutron/signal-handler", @@ -4626,7 +4625,7 @@ "keywords": [ "signal" ], - "time": "2014-01-15 17:24:13" + "time": "2014-01-15T17:24:13+00:00" }, { "name": "neutron/silex-filesystem-provider", @@ -4670,7 +4669,7 @@ "silex", "temporary-filesystem" ], - "time": "2012-11-08 21:07:08" + "time": "2012-11-08T21:07:08+00:00" }, { "name": "neutron/silex-imagine-provider", @@ -4717,7 +4716,7 @@ "imagine", "silex" ], - "time": "2013-05-03 18:48:51" + "time": "2013-05-03T18:48:51+00:00" }, { "name": "neutron/temporary-filesystem", @@ -4757,7 +4756,7 @@ } ], "description": "Symfony filesystem extension to handle temporary files", - "time": "2016-03-05 10:22:50" + "time": "2016-03-05T10:22:50+00:00" }, { "name": "nikic/php-parser", @@ -4802,7 +4801,7 @@ "parser", "php" ], - "time": "2015-09-19 14:15:08" + "time": "2015-09-19T14:15:08+00:00" }, { "name": "ocramius/proxy-manager", @@ -4865,7 +4864,7 @@ "proxy pattern", "service proxies" ], - "time": "2015-08-09 04:28:19" + "time": "2015-08-09T04:28:19+00:00" }, { "name": "pagerfanta/pagerfanta", @@ -4932,7 +4931,7 @@ "paginator", "paging" ], - "time": "2016-11-28 09:17:04" + "time": "2016-11-28T09:17:04+00:00" }, { "name": "paragonie/random-lib", @@ -4994,7 +4993,7 @@ "random-numbers", "random-strings" ], - "time": "2017-10-06 23:34:21" + "time": "2017-10-06T23:34:21+00:00" }, { "name": "paragonie/random_compat", @@ -5042,7 +5041,7 @@ "pseudorandom", "random" ], - "time": "2016-11-07 23:38:38" + "time": "2016-11-07T23:38:38+00:00" }, { "name": "paragonie/sodium_compat", @@ -5124,7 +5123,7 @@ "secret-key cryptography", "side-channel resistant" ], - "time": "2019-03-20 17:19:05" + "time": "2019-03-20T17:19:05+00:00" }, { "name": "php-ffmpeg/php-ffmpeg", @@ -5193,7 +5192,7 @@ "video", "video processing" ], - "time": "2014-08-26 08:46:56" + "time": "2014-08-26T08:46:56+00:00" }, { "name": "php-mp4box/php-mp4box", @@ -5244,20 +5243,20 @@ "gpac", "mp4box" ], - "time": "2013-06-25 10:13:06" + "time": "2013-06-25T10:13:06+00:00" }, { "name": "php-unoconv/php-unoconv", - "version": "0.3.0", + "version": "0.3.1", "source": { "type": "git", "url": "https://github.com/alchemy-fr/PHP-Unoconv.git", - "reference": "6d1e14a7467b5d637741396549529dc4d5f9f355" + "reference": "8fa666972f6c13fe9703dfe894cd311a61f89f33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/PHP-Unoconv/zipball/6d1e14a7467b5d637741396549529dc4d5f9f355", - "reference": "6d1e14a7467b5d637741396549529dc4d5f9f355", + "url": "https://api.github.com/repos/alchemy-fr/PHP-Unoconv/zipball/8fa666972f6c13fe9703dfe894cd311a61f89f33", + "reference": "8fa666972f6c13fe9703dfe894cd311a61f89f33", "shasum": "" }, "require": { @@ -5294,7 +5293,7 @@ "keywords": [ "unoconv" ], - "time": "2013-06-25 10:09:59" + "time": "2019-09-16T09:54:30+00:00" }, { "name": "php-xpdf/php-xpdf", @@ -5346,7 +5345,7 @@ "pdf", "xpdf" ], - "time": "2016-07-04 07:30:16" + "time": "2016-07-04T07:30:16+00:00" }, { "name": "phpcollection/phpcollection", @@ -5394,7 +5393,7 @@ "sequence", "set" ], - "time": "2015-05-17 12:39:23" + "time": "2015-05-17T12:39:23+00:00" }, { "name": "phpexiftool/exiftool", @@ -5427,7 +5426,7 @@ "exiftool", "metadatas" ], - "time": "2016-01-25 11:10:14" + "time": "2016-01-25T11:10:14+00:00" }, { "name": "phpoption/phpoption", @@ -5477,7 +5476,7 @@ "php", "type" ], - "time": "2015-07-25 16:39:46" + "time": "2015-07-25T16:39:46+00:00" }, { "name": "phpseclib/phpseclib", @@ -5569,7 +5568,7 @@ "x.509", "x509" ], - "time": "2017-10-23 05:04:54" + "time": "2017-10-23T05:04:54+00:00" }, { "name": "pimple/pimple", @@ -5615,7 +5614,7 @@ "container", "dependency injection" ], - "time": "2013-11-22 08:30:29" + "time": "2013-11-22T08:30:29+00:00" }, { "name": "psr/cache", @@ -5661,7 +5660,7 @@ "psr", "psr-6" ], - "time": "2016-08-06 20:24:11" + "time": "2016-08-06T20:24:11+00:00" }, { "name": "psr/http-message", @@ -5711,7 +5710,7 @@ "request", "response" ], - "time": "2016-08-06 14:39:51" + "time": "2016-08-06T14:39:51+00:00" }, { "name": "psr/log", @@ -5758,7 +5757,7 @@ "psr", "psr-3" ], - "time": "2016-10-10 12:19:37" + "time": "2016-10-10T12:19:37+00:00" }, { "name": "ramsey/uuid", @@ -5840,7 +5839,7 @@ "identifier", "uuid" ], - "time": "2016-11-22 19:21:44" + "time": "2016-11-22T19:21:44+00:00" }, { "name": "react/promise", @@ -5883,7 +5882,7 @@ "promise", "promises" ], - "time": "2016-12-22 14:09:01" + "time": "2016-12-22T14:09:01+00:00" }, { "name": "roave/security-advisories", @@ -6008,7 +6007,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2017-01-24 18:32:04" + "time": "2017-01-24T18:32:04+00:00" }, { "name": "seld/jsonlint", @@ -6054,7 +6053,7 @@ "parser", "validator" ], - "time": "2016-11-14 17:59:58" + "time": "2016-11-14T17:59:58+00:00" }, { "name": "silex/silex", @@ -6132,7 +6131,7 @@ "microframework" ], "abandoned": "symfony/flex", - "time": "2016-01-06 14:59:35" + "time": "2016-01-06T14:59:35+00:00" }, { "name": "silex/web-profiler", @@ -6178,7 +6177,7 @@ "description": "A WebProfiler for Silex", "homepage": "http://silex.sensiolabs.org/", "abandoned": true, - "time": "2016-01-10 11:39:13" + "time": "2016-01-10T11:39:13+00:00" }, { "name": "simple-bus/doctrine-orm-bridge", @@ -6232,7 +6231,7 @@ "doctrine", "event bus" ], - "time": "2015-04-29 12:27:27" + "time": "2015-04-29T12:27:27+00:00" }, { "name": "simple-bus/jms-serializer-bridge", @@ -6281,7 +6280,7 @@ "message", "serialization" ], - "time": "2015-07-29 07:48:42" + "time": "2015-07-29T07:48:42+00:00" }, { "name": "simple-bus/message-bus", @@ -6331,7 +6330,7 @@ "message", "message bus" ], - "time": "2016-02-12 08:35:53" + "time": "2016-02-12T08:35:53+00:00" }, { "name": "simple-bus/serialization", @@ -6379,7 +6378,7 @@ "messages", "serialization" ], - "time": "2015-05-08 13:34:17" + "time": "2015-05-08T13:34:17+00:00" }, { "name": "sorien/silex-dbal-profiler", @@ -6427,7 +6426,7 @@ "profiler", "silex" ], - "time": "2016-10-26 11:08:02" + "time": "2016-10-26T11:08:02+00:00" }, { "name": "sorien/silex-pimple-dumper", @@ -6469,7 +6468,7 @@ "plugin", "silex" ], - "time": "2015-11-11 07:16:28" + "time": "2015-11-11T07:16:28+00:00" }, { "name": "swftools/swftools", @@ -6523,7 +6522,7 @@ "flash", "swf" ], - "time": "2013-07-03 13:11:36" + "time": "2013-07-03T13:11:36+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -6577,7 +6576,7 @@ "mail", "mailer" ], - "time": "2016-12-29 10:02:40" + "time": "2016-12-29T10:02:40+00:00" }, { "name": "symfony/polyfill-apcu", @@ -6630,7 +6629,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-intl-icu", @@ -6688,7 +6687,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -6747,7 +6746,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php54", @@ -6805,7 +6804,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php55", @@ -6861,7 +6860,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php56", @@ -6917,7 +6916,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php70", @@ -6976,7 +6975,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-util", @@ -7028,7 +7027,7 @@ "polyfill", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/security-acl", @@ -7089,7 +7088,7 @@ ], "description": "Symfony Security Component - ACL (Access Control List)", "homepage": "https://symfony.com", - "time": "2015-12-28 09:39:46" + "time": "2015-12-28T09:39:46+00:00" }, { "name": "symfony/symfony", @@ -7224,7 +7223,7 @@ "keywords": [ "framework" ], - "time": "2017-01-12 20:27:46" + "time": "2017-01-12T20:27:46+00:00" }, { "name": "themattharris/tmhoauth", @@ -7266,7 +7265,7 @@ "oauth", "twitter" ], - "time": "2014-08-06 22:29:35" + "time": "2014-08-06T22:29:35+00:00" }, { "name": "twig/extensions", @@ -7318,7 +7317,7 @@ "i18n", "text" ], - "time": "2016-10-25 17:34:14" + "time": "2016-10-25T17:34:14+00:00" }, { "name": "twig/twig", @@ -7379,7 +7378,7 @@ "keywords": [ "templating" ], - "time": "2017-01-11 19:36:15" + "time": "2017-01-11T19:36:15+00:00" }, { "name": "vierbergenlars/php-semver", @@ -7427,7 +7426,7 @@ "semver", "versioning" ], - "time": "2013-09-20 10:41:27" + "time": "2013-09-20T10:41:27+00:00" }, { "name": "webmozart/assert", @@ -7477,7 +7476,7 @@ "check", "validate" ], - "time": "2016-11-23 20:04:58" + "time": "2016-11-23T20:04:58+00:00" }, { "name": "webmozart/json", @@ -7526,7 +7525,7 @@ } ], "description": "A robust JSON decoder/encoder with support for schema validation.", - "time": "2016-01-14 12:11:46" + "time": "2016-01-14T12:11:46+00:00" }, { "name": "webmozart/path-util", @@ -7572,7 +7571,7 @@ } ], "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "time": "2015-12-17 08:42:14" + "time": "2015-12-17T08:42:14+00:00" }, { "name": "willdurand/negotiation", @@ -7624,7 +7623,7 @@ "header", "negotiation" ], - "time": "2016-10-14 09:17:47" + "time": "2016-10-14T09:17:47+00:00" }, { "name": "zend/gdata", @@ -7665,7 +7664,7 @@ "gdata", "zend" ], - "time": "2013-01-30 15:31:21" + "time": "2013-01-30T15:31:21+00:00" }, { "name": "zendframework/zend-code", @@ -7717,7 +7716,7 @@ "code", "zf2" ], - "time": "2016-04-20 17:26:42" + "time": "2016-04-20T17:26:42+00:00" }, { "name": "zendframework/zend-eventmanager", @@ -7771,7 +7770,7 @@ "events", "zf2" ], - "time": "2016-02-18 20:53:00" + "time": "2016-02-18T20:53:00+00:00" } ], "packages-dev": [ @@ -7819,7 +7818,7 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2016-07-18 14:02:57" + "time": "2016-07-18T14:02:57+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -7873,7 +7872,7 @@ "reflection", "static analysis" ], - "time": "2015-12-27 11:43:31" + "time": "2015-12-27T11:43:31+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -7918,7 +7917,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" + "time": "2016-09-30T07:12:33+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -7965,7 +7964,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-11-25 06:54:22" + "time": "2016-11-25T06:54:22+00:00" }, { "name": "phpspec/prophecy", @@ -8028,7 +8027,7 @@ "spy", "stub" ], - "time": "2016-11-21 14:58:47" + "time": "2016-11-21T14:58:47+00:00" }, { "name": "phpunit/php-code-coverage", @@ -8090,7 +8089,7 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", @@ -8137,7 +8136,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2016-10-03T07:40:28+00:00" }, { "name": "phpunit/php-text-template", @@ -8178,7 +8177,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -8222,7 +8221,7 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2016-05-12T18:03:57+00:00" }, { "name": "phpunit/php-token-stream", @@ -8271,7 +8270,7 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15 14:06:22" + "time": "2016-11-15T14:06:22+00:00" }, { "name": "phpunit/phpunit", @@ -8343,7 +8342,7 @@ "testing", "xunit" ], - "time": "2017-01-26 16:15:36" + "time": "2017-01-26T16:15:36+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -8400,7 +8399,7 @@ "xunit" ], "abandoned": true, - "time": "2015-10-02 06:51:40" + "time": "2015-10-02T06:51:40+00:00" }, { "name": "sebastian/comparator", @@ -8464,7 +8463,7 @@ "compare", "equality" ], - "time": "2017-01-29 09:50:25" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", @@ -8516,7 +8515,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08 07:14:41" + "time": "2015-12-08T07:14:41+00:00" }, { "name": "sebastian/environment", @@ -8566,7 +8565,7 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", @@ -8633,7 +8632,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", @@ -8684,7 +8683,7 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/recursion-context", @@ -8737,7 +8736,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2015-11-11T19:50:13+00:00" }, { "name": "sebastian/version", @@ -8772,7 +8771,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2015-06-21T13:59:46+00:00" } ], "aliases": [ From afc5a85edf59dd760a1003f97a59601910b5946f Mon Sep 17 00:00:00 2001 From: aynsix Date: Fri, 13 Dec 2019 15:28:02 +0400 Subject: [PATCH 38/40] change param name --- .../Phrasea/Controller/Api/V3Controller.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php index f7672058a9..4dcab291fe 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php @@ -107,17 +107,17 @@ class V3Controller extends Controller $result = $this->doSearch($request); - $story_max_items = null; + $story_max_records = null; // if search on story if ($request->get('search_type') == 1) { - $story_max_items = (int)$request->get('story_max_items') ?: 10; + $story_max_records = (int)$request->get('story_max_records') ?: 10; } $searchView = $this->buildSearchView( $result, $includeResolver->resolve($fractal), $this->resolveSubdefUrlTTL($request), - $story_max_items + $story_max_records ); $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); @@ -139,9 +139,9 @@ class V3Controller extends Controller return Result::createError($request, 404, 'Story not found')->createResponse(); } - $max_items = (int)$request->get('max_items')?:10; + $per_page = (int)$request->get('per_page')?:10; $page = (int)$request->get('page')?:1; - $offset = ($max_items * ($page - 1)) + 1; + $offset = ($per_page * ($page - 1)) + 1; $caption = $story->get_caption(); @@ -184,7 +184,7 @@ class V3Controller extends Controller 'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title), 'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type), ], - 'records' => $this->listRecords($request, array_values($story->getChildren($offset, $max_items)->get_elements())), + 'records' => $this->listRecords($request, array_values($story->getChildren($offset, $per_page)->get_elements())), ]; } @@ -472,10 +472,10 @@ class V3Controller extends Controller * @param SearchEngineResult $result * @param string[] $includes * @param int $urlTTL - * @param int|null $story_max_items + * @param int|null $story_max_records * @return SearchResultView */ - private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_items = null) + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_records = null) { $references = new RecordReferenceCollection($result->getResults()); @@ -501,7 +501,7 @@ class V3Controller extends Controller $selections = $this->findDataboxById($databoxId) ->getRecordRepository() - ->findChildren($storyIds, $user,1, $story_max_items); + ->findChildren($storyIds, $user,1, $story_max_records); $children[$databoxId] = array_combine($storyIds, $selections); } From 2969fa7e9cf76e6ed0c62d5e8ca64bc681c782ef Mon Sep 17 00:00:00 2001 From: Jean-Yves Gaulier Date: Mon, 16 Dec 2019 16:13:08 +0100 Subject: [PATCH 39/40] PHRAS-2814_missing-es-options-for-tests to complete https://github.com/alchemy-fr/Phraseanet/pull/3222/commits : add options to bootstrap for tests --- tests/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bootstrap.sh b/tests/bootstrap.sh index 658fec4bab..0f951a22ac 100755 --- a/tests/bootstrap.sh +++ b/tests/bootstrap.sh @@ -34,7 +34,7 @@ then mv config/configuration.yml{,.backup} rm -f config/configuration-compiled.php fi -./bin/setup system:install --email=test@phraseanet.com --password=test --db-user=root --db-template=en-simple --db-password=toor --databox=db_test --appbox=ab_test --server-name=http://127.0.0.1 -y $VERBOSITY +./bin/setup system:install --email=test@phraseanet.com --password=test --db-user=root --db-template=en-simple --db-password=toor --databox=db_test --appbox=ab_test --server-name=http://127.0.0.1 --es-host=localhost --es-port=9200 --es-index=phrasea_test -y $VERBOSITY case "$INSTALL_MODE" in update) ./bin/developer ini:reset --email=test@phraseanet.com --password=test --run-patches --no-setup-dbs $VERBOSITY From c119627e84106ea7e98acedfe11b25df852b2ad1 Mon Sep 17 00:00:00 2001 From: Jean-Yves Gaulier Date: Mon, 16 Dec 2019 17:40:15 +0100 Subject: [PATCH 40/40] PHRAS-2814_missing-es-options-for-tests add options to a testfile that changes conf. todo : fix the test to backup/restore file after test --- .../Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php b/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php index 0e3c477b5c..f05831d94b 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php @@ -78,9 +78,12 @@ class InstallTest extends \PhraseanetTestCase case 'db-password': return $infoDb['database']['password']; break; - case 'yes': - return true; - break; + case 'es-host': + return 'localhost'; + case 'es-port': + return 9200; + case 'es-index': + return 'phrasea_test'; default: return ''; }