mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 07:23:13 +00:00
WIP
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
namespace Alchemy\Phrasea\Controller\Api;
|
||||
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Fractal\ArraySerializer;
|
||||
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||
use Alchemy\Phrasea\Search\SearchResultView;
|
||||
use Alchemy\Phrasea\Search\V2SearchTransformer;
|
||||
@@ -20,7 +21,6 @@ use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
|
@@ -32,6 +32,7 @@ use Alchemy\Phrasea\Core\Version;
|
||||
use Alchemy\Phrasea\Feed\Aggregate;
|
||||
use Alchemy\Phrasea\Feed\FeedInterface;
|
||||
use Alchemy\Phrasea\Form\Login\PhraseaRenewPasswordForm;
|
||||
use Alchemy\Phrasea\Fractal\ArraySerializer;
|
||||
use Alchemy\Phrasea\Model\Entities\ApiOauthToken;
|
||||
use Alchemy\Phrasea\Model\Entities\Basket;
|
||||
use Alchemy\Phrasea\Model\Entities\BasketElement;
|
||||
@@ -54,15 +55,24 @@ use Alchemy\Phrasea\Model\Repositories\FeedRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\LazaretFileRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\TaskRepository;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use Alchemy\Phrasea\Search\RecordTransformer;
|
||||
use Alchemy\Phrasea\Search\RecordView;
|
||||
use Alchemy\Phrasea\Search\SearchResultView;
|
||||
use Alchemy\Phrasea\Search\StoryTransformer;
|
||||
use Alchemy\Phrasea\Search\StoryView;
|
||||
use Alchemy\Phrasea\Search\SubdefTransformer;
|
||||
use Alchemy\Phrasea\Search\V1SearchCompositeResultTransformer;
|
||||
use Alchemy\Phrasea\Search\V1SearchRecordsResultTransformer;
|
||||
use Alchemy\Phrasea\Search\V1SearchResultTransformer;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineLogger;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineSuggestion;
|
||||
use Alchemy\Phrasea\Status\StatusStructure;
|
||||
use Alchemy\Phrasea\TaskManager\LiveInformation;
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -1035,24 +1045,18 @@ class V1Controller extends Controller
|
||||
*/
|
||||
public function searchAction(Request $request)
|
||||
{
|
||||
list($ret, $search_result) = $this->prepareSearchRequest($request);
|
||||
$fractal = new \League\Fractal\Manager();
|
||||
$fractal->setSerializer(new ArraySerializer());
|
||||
$fractal->parseIncludes($this->resolveSearchIncludes($request));
|
||||
|
||||
$records = [];
|
||||
$stories = [];
|
||||
$searchView = $this->buildSearchView($this->doSearch($request));
|
||||
|
||||
/** @var SearchEngineResult $search_result */
|
||||
foreach ($search_result->getResults() as $record) {
|
||||
if ($record->isStory()) {
|
||||
$stories[] = $record;
|
||||
} else {
|
||||
$records[] = $record;
|
||||
}
|
||||
}
|
||||
$recordTransformer = new RecordTransformer();
|
||||
$storyTransformer = new StoryTransformer(new SubdefTransformer(), $recordTransformer);
|
||||
$compositeTransformer = new V1SearchCompositeResultTransformer($recordTransformer, $storyTransformer);
|
||||
$searchTransformer = new V1SearchResultTransformer($compositeTransformer);
|
||||
|
||||
$ret['results'] = [
|
||||
'records' => $this->listRecords($request, $records),
|
||||
'stories' => $this->listStories($request, $stories),
|
||||
];
|
||||
$ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray();
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
@@ -1068,33 +1072,141 @@ class V1Controller extends Controller
|
||||
*/
|
||||
public function searchRecordsAction(Request $request)
|
||||
{
|
||||
list($ret, $search_result) = $this->prepareSearchRequest($request);
|
||||
$fractal = new \League\Fractal\Manager();
|
||||
$fractal->setSerializer(new ArraySerializer());
|
||||
$fractal->parseIncludes($this->resolveSearchRecordsIncludes($request));
|
||||
|
||||
/** @var SearchEngineResult $search_result */
|
||||
foreach ($search_result->getResults() as $es_record) {
|
||||
try {
|
||||
$record = new \record_adapter($this->app, $es_record->getDataboxId(), $es_record->getRecordId());
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
$searchView = $this->buildSearchRecordsView($this->doSearch($request));
|
||||
|
||||
$ret['results'][] = $this->listRecord($request, $record);
|
||||
}
|
||||
$searchTransformer = new V1SearchRecordsResultTransformer(new RecordTransformer());
|
||||
|
||||
$ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray();
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
|
||||
private function prepareSearchRequest(Request $request)
|
||||
/**
|
||||
* @param SearchEngineResult $result
|
||||
* @return SearchResultView
|
||||
*/
|
||||
private function buildSearchView(SearchEngineResult $result)
|
||||
{
|
||||
|
||||
$references = new RecordReferenceCollection($result->getResults());
|
||||
|
||||
$records = [];
|
||||
$stories = [];
|
||||
|
||||
foreach ($references->toRecords($this->getApplicationBox()) as $record) {
|
||||
if ($record->isStory()) {
|
||||
$stories[] = $record;
|
||||
} else {
|
||||
$records[] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
$resultView = new SearchResultView($result);
|
||||
|
||||
if ($stories) {
|
||||
$storyViews = [];
|
||||
|
||||
foreach ($stories as $story) {
|
||||
$storyViews[] = new StoryView($story);
|
||||
}
|
||||
|
||||
$resultView->setStories($storyViews);
|
||||
}
|
||||
|
||||
if ($records) {
|
||||
$recordViews = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
$recordViews[] = new RecordView($record);
|
||||
}
|
||||
|
||||
$resultView->setRecords($recordViews);
|
||||
}
|
||||
|
||||
return $resultView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SearchEngineResult $result
|
||||
* @return SearchResultView
|
||||
*/
|
||||
private function buildSearchRecordsView(SearchEngineResult $result)
|
||||
{
|
||||
$references = new RecordReferenceCollection($result->getResults());
|
||||
|
||||
$recordViews = [];
|
||||
|
||||
foreach ($references->toRecords($this->getApplicationBox()) as $record) {
|
||||
$recordViews[] = new RecordView($record);
|
||||
}
|
||||
|
||||
$resultView = new SearchResultView($result);
|
||||
$resultView->setRecords($recordViews);
|
||||
|
||||
return $resultView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns requested includes
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveSearchIncludes(Request $request)
|
||||
{
|
||||
if (!$request->attributes->get('_extended', false)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
'results.stories.records.subdefs',
|
||||
'results.stories.records.metadata',
|
||||
'results.stories.records.caption',
|
||||
'results.stories.records.status',
|
||||
'results.records.subdefs',
|
||||
'results.records.metadata',
|
||||
'results.records.caption',
|
||||
'results.records.status',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns requested includes
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveSearchRecordsIncludes(Request $request)
|
||||
{
|
||||
if (!$request->attributes->get('_extended', false)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
'results.subdefs',
|
||||
'results.metadata',
|
||||
'results.caption',
|
||||
'results.status',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
$options->setFirstResult((int) ($request->get('offset_start') ?: 0));
|
||||
$options->setMaxResults((int) $request->get('per_page') ?: 10);
|
||||
|
||||
$query = (string) $request->get('query');
|
||||
$this->getSearchEngine()->resetCache();
|
||||
|
||||
$search_result = $this->getSearchEngine()->query($query, $options);
|
||||
$search_result = $this->getSearchEngine()->query((string)$request->get('query'), $options);
|
||||
|
||||
$this->getUserManipulator()->logQuery($this->getAuthenticatedUser(), $search_result->getQuery());
|
||||
|
||||
@@ -1111,25 +1223,7 @@ class V1Controller extends Controller
|
||||
|
||||
$this->getSearchEngine()->clearCache();
|
||||
|
||||
$ret = [
|
||||
'offset_start' => $options->getFirstResult(),
|
||||
'per_page' => $options->getMaxResults(),
|
||||
'available_results' => $search_result->getAvailable(),
|
||||
'total_results' => $search_result->getTotal(),
|
||||
'error' => (string)$search_result->getError(),
|
||||
'warning' => (string)$search_result->getWarning(),
|
||||
'query_time' => $search_result->getDuration(),
|
||||
'search_indexes' => $search_result->getIndexes(),
|
||||
'suggestions' => array_map(
|
||||
function (SearchEngineSuggestion $suggestion) {
|
||||
return $suggestion->toArray();
|
||||
}, $search_result->getSuggestions()->toArray()),
|
||||
'facets' => $search_result->getFacets(),
|
||||
'results' => [],
|
||||
'query' => $search_result->getQuery(),
|
||||
];
|
||||
|
||||
return [$ret, $search_result];
|
||||
return $search_result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
49
lib/Alchemy/Phrasea/Fractal/ArraySerializer.php
Normal file
49
lib/Alchemy/Phrasea/Fractal/ArraySerializer.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Fractal;
|
||||
|
||||
use League\Fractal\Pagination\CursorInterface;
|
||||
use League\Fractal\Pagination\PaginatorInterface;
|
||||
use League\Fractal\Resource\ResourceInterface;
|
||||
use League\Fractal\Serializer\SerializerAbstract;
|
||||
|
||||
class ArraySerializer extends SerializerAbstract
|
||||
{
|
||||
public function collection($resourceKey, array $data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function item($resourceKey, array $data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function includedData(ResourceInterface $resource, array $data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function meta(array $meta)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function paginator(PaginatorInterface $paginator)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function cursor(CursorInterface $cursor)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
35
lib/Alchemy/Phrasea/Search/CaptionAware.php
Normal file
35
lib/Alchemy/Phrasea/Search/CaptionAware.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
trait CaptionAware
|
||||
{
|
||||
/**
|
||||
* @var CaptionView
|
||||
*/
|
||||
private $caption;
|
||||
|
||||
/**
|
||||
* @param CaptionView $caption
|
||||
*/
|
||||
public function setCaption(CaptionView $caption)
|
||||
{
|
||||
$this->caption = $caption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CaptionView
|
||||
*/
|
||||
public function getCaption()
|
||||
{
|
||||
return $this->caption;
|
||||
}
|
||||
}
|
32
lib/Alchemy/Phrasea/Search/CaptionView.php
Normal file
32
lib/Alchemy/Phrasea/Search/CaptionView.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
class CaptionView
|
||||
{
|
||||
/**
|
||||
* @var \caption_record
|
||||
*/
|
||||
private $caption;
|
||||
|
||||
public function __construct(\caption_record $caption)
|
||||
{
|
||||
$this->caption = $caption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \caption_record
|
||||
*/
|
||||
public function getCaption()
|
||||
{
|
||||
return $this->caption;
|
||||
}
|
||||
}
|
109
lib/Alchemy/Phrasea/Search/RecordTransformer.php
Normal file
109
lib/Alchemy/Phrasea/Search/RecordTransformer.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class RecordTransformer extends TransformerAbstract
|
||||
{
|
||||
protected $availableIncludes = ['thumbnail', 'technical_informations', 'subdefs', 'metadata', 'status', 'caption'];
|
||||
protected $defaultIncludes = ['thumbnail', 'technical_informations'];
|
||||
|
||||
/**
|
||||
* @var SubdefTransformer
|
||||
*/
|
||||
private $subdefTransformer;
|
||||
|
||||
/**
|
||||
* @var TechnicalDataTransformer
|
||||
*/
|
||||
private $technicalDataTransformer;
|
||||
|
||||
public function __construct(SubdefTransformer $subdefTransformer, TechnicalDataTransformer $technicalDataTransformer)
|
||||
{
|
||||
$this->subdefTransformer = $subdefTransformer;
|
||||
$this->technicalDataTransformer = $technicalDataTransformer;
|
||||
}
|
||||
|
||||
public function transform(RecordView $recordView)
|
||||
{
|
||||
$record = $recordView->getRecord();
|
||||
|
||||
return [
|
||||
'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(),
|
||||
'phrasea_type' => $record->getType(),
|
||||
'uuid' => $record->getUuid(),
|
||||
];
|
||||
}
|
||||
|
||||
public function includeThumbnail(RecordView $recordView)
|
||||
{
|
||||
return $this->item($recordView->getSubdef('thumbnail'), $this->subdefTransformer);
|
||||
}
|
||||
|
||||
public function includeTechnicalInformations(RecordView $recordView)
|
||||
{
|
||||
return $this->collection($recordView->getTechnicalDataView()->getDataSet(), $this->technicalDataTransformer);
|
||||
}
|
||||
|
||||
public function includeSubdefs(RecordView $recordView)
|
||||
{
|
||||
return $this->collection($recordView->getSubdefs(), $this->subdefTransformer);
|
||||
}
|
||||
|
||||
public function includeMetadata(RecordView $recordView)
|
||||
{
|
||||
$ret = [];
|
||||
|
||||
foreach ($recordView->getCaption()->getCaption()->get_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[] = array_replace($fieldData, $data);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->collection($recordView->getCaption(), )
|
||||
}
|
||||
|
||||
public function includeStatus(RecordView $recordView)
|
||||
{
|
||||
}
|
||||
|
||||
public function includeCaption(RecordView $recordView)
|
||||
{
|
||||
}
|
||||
}
|
53
lib/Alchemy/Phrasea/Search/RecordView.php
Normal file
53
lib/Alchemy/Phrasea/Search/RecordView.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
class RecordView
|
||||
{
|
||||
use SubdefsAware;
|
||||
use CaptionAware;
|
||||
|
||||
/**
|
||||
* @var \record_adapter
|
||||
*/
|
||||
private $record;
|
||||
|
||||
/**
|
||||
* @var TechnicalDataView
|
||||
*/
|
||||
private $technicalDataView;
|
||||
|
||||
public function __construct(\record_adapter $record)
|
||||
{
|
||||
$this->record = $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \record_adapter
|
||||
*/
|
||||
public function getRecord()
|
||||
{
|
||||
return $this->record;
|
||||
}
|
||||
|
||||
public function setTechnicalDataView(TechnicalDataView $technicalDataView)
|
||||
{
|
||||
$this->technicalDataView = $technicalDataView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TechnicalDataView
|
||||
*/
|
||||
public function getTechnicalDataView()
|
||||
{
|
||||
return $this->technicalDataView;
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
||||
use Assert\Assertion;
|
||||
|
||||
class SearchResultView
|
||||
{
|
||||
@@ -19,6 +20,16 @@ class SearchResultView
|
||||
*/
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* @var StoryView[]
|
||||
*/
|
||||
private $stories = [];
|
||||
|
||||
/**
|
||||
* @var RecordView[]
|
||||
*/
|
||||
private $records = [];
|
||||
|
||||
public function __construct(SearchEngineResult $result)
|
||||
{
|
||||
$this->result = $result;
|
||||
@@ -31,4 +42,42 @@ class SearchResultView
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StoryView[] $stories
|
||||
* @return void
|
||||
*/
|
||||
public function setStories($stories)
|
||||
{
|
||||
Assertion::allIsInstanceOf($this->stories, StoryView::class);
|
||||
|
||||
$this->stories = $stories instanceof \Traversable ? iterator_to_array($stories, false) : array_values($stories);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StoryView[]
|
||||
*/
|
||||
public function getStories()
|
||||
{
|
||||
return $this->stories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordView[] $records
|
||||
* @return void
|
||||
*/
|
||||
public function setRecords($records)
|
||||
{
|
||||
Assertion::allIsInstanceOf($records, RecordView::class);
|
||||
|
||||
$this->records = $records instanceof \Traversable ? iterator_to_array($records, false) : array_values($records);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecordView[]
|
||||
*/
|
||||
public function getRecords()
|
||||
{
|
||||
return $this->records;
|
||||
}
|
||||
}
|
||||
|
109
lib/Alchemy/Phrasea/Search/StoryTransformer.php
Normal file
109
lib/Alchemy/Phrasea/Search/StoryTransformer.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class StoryTransformer extends TransformerAbstract
|
||||
{
|
||||
protected $availableIncludes = ['thumbnail', 'metadatas', 'records'];
|
||||
protected $defaultIncludes = ['thumbnail', 'metadatas', 'records'];
|
||||
|
||||
/**
|
||||
* @var SubdefTransformer
|
||||
*/
|
||||
private $subdefTransformer;
|
||||
|
||||
/**
|
||||
* @var RecordTransformer
|
||||
*/
|
||||
private $recordTransformer;
|
||||
|
||||
/**
|
||||
* @param SubdefTransformer $subdefTransformer
|
||||
* @param RecordTransformer $recordTransformer
|
||||
*/
|
||||
public function __construct(SubdefTransformer $subdefTransformer, RecordTransformer $recordTransformer)
|
||||
{
|
||||
$this->subdefTransformer = $subdefTransformer;
|
||||
$this->recordTransformer = $recordTransformer;
|
||||
}
|
||||
|
||||
public function transform(StoryView $storyView)
|
||||
{
|
||||
$story = $storyView->getStory();
|
||||
|
||||
return [
|
||||
'@entity@' => 'http://api.phraseanet.com/api/objects/story',
|
||||
'databox_id' => $story->getDataboxId(),
|
||||
'story_id' => $story->getRecordId(),
|
||||
'updated_on' => NullableDateTime::format($story->getUpdated()),
|
||||
'created_on' => NullableDateTime::format($story->getUpdated()),
|
||||
'collection_id' => $story->getCollectionId(),
|
||||
'base_id' => $story->getBaseId(),
|
||||
'uuid' => $story->getUuid(),
|
||||
];
|
||||
}
|
||||
|
||||
public function includeThumbnail(StoryView $storyView)
|
||||
{
|
||||
return $this->item($storyView->getSubdef('thumbnail'), $this->subdefTransformer);
|
||||
}
|
||||
|
||||
public function includeMetadatas(StoryView $storyView)
|
||||
{
|
||||
return $this->item($storyView->getCaption(), $this->getCaptionTransformer());
|
||||
}
|
||||
|
||||
public function includeRecords(StoryView $storyView)
|
||||
{
|
||||
return $this->collection($storyView->getChildren(), $this->recordTransformer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Closure
|
||||
*/
|
||||
private function getCaptionTransformer()
|
||||
{
|
||||
/**
|
||||
* @param \caption_field[] $fields
|
||||
* @param string $dcField
|
||||
* @return string|null
|
||||
*/
|
||||
$format = function ($fields, $dcField) {
|
||||
return isset($fields[$dcField]) ? $fields[$dcField]->get_serialized_values() : null;
|
||||
};
|
||||
|
||||
return function (CaptionView $captionView) use ($format) {
|
||||
$caption = $captionView->getCaption()->getDCFields();
|
||||
|
||||
return [
|
||||
'@entity@' => 'http://api.phraseanet.com/api/objects/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),
|
||||
];
|
||||
};
|
||||
}
|
||||
}
|
63
lib/Alchemy/Phrasea/Search/StoryView.php
Normal file
63
lib/Alchemy/Phrasea/Search/StoryView.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use Assert\Assertion;
|
||||
|
||||
class StoryView
|
||||
{
|
||||
use SubdefsAware;
|
||||
use CaptionAware;
|
||||
|
||||
/**
|
||||
* @var \record_adapter
|
||||
*/
|
||||
private $story;
|
||||
/**
|
||||
* @var RecordView[]
|
||||
*/
|
||||
private $children = [];
|
||||
|
||||
/**
|
||||
* @param \record_adapter $story
|
||||
*/
|
||||
public function __construct(\record_adapter $story)
|
||||
{
|
||||
|
||||
$this->story = $story;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \record_adapter
|
||||
*/
|
||||
public function getStory()
|
||||
{
|
||||
return $this->story;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordView[] $children
|
||||
*/
|
||||
public function setChildren($children)
|
||||
{
|
||||
Assertion::allIsInstanceOf($children, RecordView::class);
|
||||
|
||||
$this->children = $children instanceof \Traversable ? iterator_to_array($children, false) : array_values($children);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecordView[]
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
}
|
21
lib/Alchemy/Phrasea/Search/SubdefTransformer.php
Normal file
21
lib/Alchemy/Phrasea/Search/SubdefTransformer.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class SubdefTransformer extends TransformerAbstract
|
||||
{
|
||||
public function transform(SubdefView $subdefView)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
32
lib/Alchemy/Phrasea/Search/SubdefView.php
Normal file
32
lib/Alchemy/Phrasea/Search/SubdefView.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
class SubdefView
|
||||
{
|
||||
/**
|
||||
* @var \media_subdef
|
||||
*/
|
||||
private $subdef;
|
||||
|
||||
public function __construct(\media_subdef $subdef)
|
||||
{
|
||||
$this->subdef = $subdef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \media_subdef
|
||||
*/
|
||||
public function getSubdef()
|
||||
{
|
||||
return $this->subdef;
|
||||
}
|
||||
}
|
52
lib/Alchemy/Phrasea/Search/SubdefsAware.php
Normal file
52
lib/Alchemy/Phrasea/Search/SubdefsAware.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use Assert\Assertion;
|
||||
|
||||
trait SubdefsAware
|
||||
{
|
||||
/**
|
||||
* @var SubdefView[]
|
||||
*/
|
||||
private $subdefs;
|
||||
|
||||
/**
|
||||
* @param SubdefView[] $subdefs
|
||||
*/
|
||||
public function setSubdefs($subdefs)
|
||||
{
|
||||
Assertion::allIsInstanceOf($subdefs, SubdefView::class);
|
||||
|
||||
$this->subdefs = [];
|
||||
|
||||
foreach ($subdefs as $subdef) {
|
||||
$this->subdefs[$subdef->getSubdef()->get_name()] = $subdef;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return SubdefView
|
||||
*/
|
||||
public function getSubdef($name)
|
||||
{
|
||||
return $this->subdefs[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubdefView
|
||||
*/
|
||||
public function getSubdefs()
|
||||
{
|
||||
return $this->subdefs;
|
||||
}
|
||||
}
|
25
lib/Alchemy/Phrasea/Search/TechnicalDataTransformer.php
Normal file
25
lib/Alchemy/Phrasea/Search/TechnicalDataTransformer.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use Alchemy\Phrasea\Media\TechnicalData;
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class TechnicalDataTransformer extends TransformerAbstract
|
||||
{
|
||||
public function transform(TechnicalData $technicalData)
|
||||
{
|
||||
return [
|
||||
'name' => $technicalData->getName(),
|
||||
'value' => $technicalData->getValue(),
|
||||
];
|
||||
}
|
||||
}
|
34
lib/Alchemy/Phrasea/Search/TechnicalDataView.php
Normal file
34
lib/Alchemy/Phrasea/Search/TechnicalDataView.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use Alchemy\Phrasea\Media\TechnicalDataSet;
|
||||
|
||||
class TechnicalDataView
|
||||
{
|
||||
/**
|
||||
* @var TechnicalDataSet
|
||||
*/
|
||||
private $dataSet;
|
||||
|
||||
public function __construct(TechnicalDataSet $dataSet)
|
||||
{
|
||||
$this->dataSet = $dataSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TechnicalDataSet
|
||||
*/
|
||||
public function getDataSet()
|
||||
{
|
||||
return $this->dataSet;
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class V1SearchCompositeResultTransformer extends TransformerAbstract
|
||||
{
|
||||
protected $availableIncludes = ['stories', 'records'];
|
||||
protected $defaultIncludes = ['stories', 'records'];
|
||||
|
||||
/**
|
||||
* @var RecordTransformer
|
||||
*/
|
||||
private $recordTransformer;
|
||||
/**
|
||||
* @var StoryTransformer
|
||||
*/
|
||||
private $storyTransformer;
|
||||
|
||||
public function __construct(RecordTransformer $recordTransformer, StoryTransformer $storyTransformer)
|
||||
{
|
||||
$this->recordTransformer = $recordTransformer;
|
||||
$this->storyTransformer = $storyTransformer;
|
||||
}
|
||||
|
||||
public function transform()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function includeRecords(SearchResultView $resultView)
|
||||
{
|
||||
return $this->collection($resultView->getRecords(), $this->recordTransformer);
|
||||
}
|
||||
|
||||
public function includeStories(SearchResultView $resultView)
|
||||
{
|
||||
return $this->collection($resultView->getStories(), $this->storyTransformer);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
class V1SearchRecordsResultTransformer extends V1SearchTransformer
|
||||
{
|
||||
/**
|
||||
* @var RecordTransformer
|
||||
*/
|
||||
private $recordTransformer;
|
||||
|
||||
public function __construct(RecordTransformer $recordTransformer)
|
||||
{
|
||||
$this->recordTransformer = $recordTransformer;
|
||||
}
|
||||
|
||||
public function includeResults(SearchResultView $resultView)
|
||||
{
|
||||
return $this->collection($resultView->getRecords(), $this->recordTransformer);
|
||||
}
|
||||
}
|
31
lib/Alchemy/Phrasea/Search/V1SearchResultTransformer.php
Normal file
31
lib/Alchemy/Phrasea/Search/V1SearchResultTransformer.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class V1SearchResultTransformer extends V1SearchTransformer
|
||||
{
|
||||
/**
|
||||
* @var TransformerAbstract
|
||||
*/
|
||||
private $transformer;
|
||||
|
||||
public function __construct(TransformerAbstract $transformer)
|
||||
{
|
||||
$this->transformer = $transformer;
|
||||
}
|
||||
|
||||
public function includeResults(SearchResultView $resultView)
|
||||
{
|
||||
return $this->item($resultView, $this->transformer);
|
||||
}
|
||||
}
|
44
lib/Alchemy/Phrasea/Search/V1SearchTransformer.php
Normal file
44
lib/Alchemy/Phrasea/Search/V1SearchTransformer.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Search;
|
||||
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineSuggestion;
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
abstract class V1SearchTransformer extends TransformerAbstract
|
||||
{
|
||||
protected $availableIncludes = ['results'];
|
||||
protected $defaultIncludes = ['results'];
|
||||
|
||||
public function transform(SearchResultView $resultView)
|
||||
{
|
||||
$result = $resultView->getResult();
|
||||
|
||||
return [
|
||||
'offset_start' => $result->getOptions()->getFirstResult(),
|
||||
'per_page' => $result->getOptions()->getMaxResults(),
|
||||
'available_results' => $result->getAvailable(),
|
||||
'total_results' => $result->getTotal(),
|
||||
'error' => (string)$result->getError(),
|
||||
'warning' => (string)$result->getWarning(),
|
||||
'query_time' => $result->getDuration(),
|
||||
'search_indexes' => $result->getIndexes(),
|
||||
'suggestions' => array_map(
|
||||
function (SearchEngineSuggestion $suggestion) {
|
||||
return $suggestion->toArray();
|
||||
}, $result->getSuggestions()->toArray()),
|
||||
'facets' => $result->getFacets(),
|
||||
'query' => $result->getQuery(),
|
||||
];
|
||||
}
|
||||
|
||||
abstract public function includeResults(SearchResultView $resultView);
|
||||
}
|
@@ -15,6 +15,9 @@ use League\Fractal\TransformerAbstract;
|
||||
|
||||
class V2SearchTransformer extends TransformerAbstract
|
||||
{
|
||||
protected $availableIncludes = ['results'];
|
||||
protected $defaultIncludes = ['results'];
|
||||
|
||||
public function transform(SearchResultView $searchView)
|
||||
{
|
||||
return [
|
||||
@@ -28,27 +31,18 @@ class V2SearchTransformer extends TransformerAbstract
|
||||
'search_indexes' => $searchView->getResult()->getIndexes(),
|
||||
'facets' => $searchView->getResult()->getFacets(),
|
||||
'search_type' => $searchView->getResult()->getOptions()->getSearchType(),
|
||||
'results' => $this->listResults($searchView->getResult()->getResults()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordInterface[] $results
|
||||
* @return array
|
||||
*/
|
||||
public function listResults($results)
|
||||
public function includeResults(SearchResultView $searchView)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($results as $record) {
|
||||
$data[] = [
|
||||
return $this->collection($searchView->getResult()->getResults(), function (RecordInterface $record) {
|
||||
return [
|
||||
'databox_id' => $record->getDataboxId(),
|
||||
'record_id' => $record->getRecordId(),
|
||||
'collection_id' => $record->getCollectionId(),
|
||||
'version' => $record->getUpdated()->getTimestamp(),
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user