mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 09:53:15 +00:00
WIP
refacto : explode v3 controller, fix warnings
This commit is contained in:
371
lib/Alchemy/Phrasea/Controller/Api/V3/V3MetadatasController.php
Normal file
371
lib/Alchemy/Phrasea/Controller/Api/V3/V3MetadatasController.php
Normal file
@@ -0,0 +1,371 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Application\Helper\JsonBodyAware;
|
||||
use Alchemy\Phrasea\Controller\Api\Result;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Core\Event\RecordEdit;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use databox_field;
|
||||
use Exception;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
|
||||
class V3MetadatasController extends Controller
|
||||
{
|
||||
use JsonBodyAware;
|
||||
use DispatcherAware;
|
||||
|
||||
|
||||
/**
|
||||
* Return detailed information about one story
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $databox_id
|
||||
* @param int $record_id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function setmetadatasAction(Request $request, $databox_id, $record_id)
|
||||
{
|
||||
$struct = $this->findDataboxById($databox_id)->get_meta_structure();
|
||||
$record = $this->findDataboxById($databox_id)->get_record($record_id);
|
||||
|
||||
//$record->set_metadatas()
|
||||
|
||||
//setRecordStatusAction
|
||||
|
||||
try {
|
||||
$b = $this->decodeJsonBody($request);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return $this->app['controller.api.v1']->getBadRequestAction($request, 'Bad JSON');
|
||||
}
|
||||
|
||||
$ret = [
|
||||
'metadatas_ops' => null,
|
||||
'sb_ops' => null,
|
||||
];
|
||||
try {
|
||||
// do metadatas ops
|
||||
if (is_array($b->metadatas)) {
|
||||
$ret['metadatas_ops'] = $this->setmetadatasAction_meta($struct, $record, $b->metadatas);
|
||||
}
|
||||
// do sb ops
|
||||
if (is_array($b->status)) {
|
||||
$ret['sb_ops'] = $this->setmetadatasAction_sb($struct, $record, $b->status);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return $this->app['controller.api.v1']->getBadRequestAction(
|
||||
$request,
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $struct
|
||||
* @param $record
|
||||
* @param $metadatas
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function setmetadatasAction_meta($struct, $record, $metadatas)
|
||||
{
|
||||
$structByKey = [];
|
||||
$nameToStrucId = [];
|
||||
foreach ($struct as $f) {
|
||||
$nameToStrucId[$f->get_name()] = $f->get_id();
|
||||
$structByKey[$f->get_id()] = $f;
|
||||
$structByKey[$f->get_name()] = &$structByKey[$f->get_id()];
|
||||
}
|
||||
|
||||
$metadatas_ops = [];
|
||||
foreach ($metadatas as $_m) {
|
||||
// sanity
|
||||
if($_m->meta_struct_id && $_m->field_name) {
|
||||
throw new Exception("define meta_struct_id OR field_name, not both.");
|
||||
}
|
||||
// select fields that match meta_struct_id or field_name (can be arrays)
|
||||
$fields_list = null; // to filter caption_fields from record, default all
|
||||
$struct_fields = []; // struct fields that match meta_struct_id or field_name
|
||||
if(($field_keys = $_m->meta_struct_id ? $_m->meta_struct_id : $_m->field_name) !== null) { // can be null if none defined (=match all)
|
||||
if (!is_array($field_keys)) {
|
||||
$field_keys = [$field_keys];
|
||||
}
|
||||
$fields_list = [];
|
||||
foreach ($field_keys as $k) {
|
||||
if(array_key_exists($k, $structByKey)) {
|
||||
$fields_list[] = $structByKey[$k]->get_name();
|
||||
$struct_fields[$structByKey[$k]->get_id()] = $structByKey[$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
$caption_fields = $record->get_caption()->get_fields($fields_list, true);
|
||||
|
||||
$meta_id = is_null($_m->meta_id) ? null : (int)($_m->meta_id);
|
||||
|
||||
if(!($match_method = (string)($_m->match_method))) {
|
||||
$match_method = 'ignore_case';
|
||||
}
|
||||
if(!in_array($match_method, ['strict', 'ignore_case', 'regexp'])) {
|
||||
throw new Exception(sprintf("bad match_method (%s).", $match_method));
|
||||
}
|
||||
|
||||
$values = [];
|
||||
if(is_array($_m->value)) {
|
||||
foreach ($_m->value as $v) {
|
||||
$values[] = is_null($v) ? null : (string)$v;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$values = is_null($_m->value) ? [] : [(string)($_m->value)];
|
||||
}
|
||||
|
||||
if(!($action = (string)($_m->action))) {
|
||||
$action = 'set';
|
||||
}
|
||||
|
||||
switch ($_m->action) {
|
||||
case 'set':
|
||||
$ops = $this->setmetadatasAction_set($struct_fields, $caption_fields, $meta_id, $values);
|
||||
break;
|
||||
case 'add':
|
||||
$ops = $this->setmetadatasAction_add($struct_fields, $values);
|
||||
break;
|
||||
case 'delete':
|
||||
$ops = $this->setmetadatasAction_replace($caption_fields, $meta_id, $match_method, $values, null);
|
||||
break;
|
||||
case 'replace':
|
||||
if (!is_string($_m->replace_with) && !is_null($_m->replace_with)) {
|
||||
throw new Exception("bad \"replace_with\" for action \"replace\".");
|
||||
}
|
||||
$ops = $this->setmetadatasAction_replace($caption_fields, $meta_id, $match_method, $values, $_m->replace_with);
|
||||
break;
|
||||
default:
|
||||
throw new Exception(sprintf("bad action (%s).", $action));
|
||||
}
|
||||
|
||||
$metadatas_ops = array_merge($metadatas_ops, $ops);
|
||||
}
|
||||
|
||||
return $metadatas_ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $struct
|
||||
* @param $record
|
||||
* @param $statuses
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function setmetadatasAction_sb($struct, $record, $statuses)
|
||||
{
|
||||
$datas = strrev($record->getStatus());
|
||||
|
||||
foreach ($statuses as $status) {
|
||||
$n = (int)($status->bit);
|
||||
$value = (int)($status->state);
|
||||
if ($n > 31 || $n < 4) {
|
||||
throw new Exception(sprintf("Invalid status bit number (%s).", $n));
|
||||
}
|
||||
if ($value < 0 || $value > 1) {
|
||||
throw new Exception(sprintf("Invalid status bit state (%s) for bit (%s).", $value, $n));
|
||||
}
|
||||
|
||||
$datas = substr($datas, 0, ($n)) . $value . substr($datas, ($n + 1));
|
||||
}
|
||||
|
||||
// $record->setStatus(strrev($datas));
|
||||
|
||||
// @todo Move event dispatch inside record_adapter class (keeps things encapsulated)
|
||||
$this->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
|
||||
|
||||
return ["status" => $this->getResultHelpers()->listRecordStatus($record)];
|
||||
}
|
||||
|
||||
private function match($pattern, $method, $value)
|
||||
{
|
||||
switch ($method) {
|
||||
case 'strict':
|
||||
return $value === $pattern;
|
||||
case 'ignore_case':
|
||||
return strtolower($value) === strtolower($pattern);
|
||||
case 'regexp':
|
||||
return preg_match($pattern, $value) == 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
/// TODO : keep multi-values uniques !
|
||||
/// it should be done in record_adapter
|
||||
//////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param databox_field[] $struct_fields struct-fields (from struct) matching meta_struct_id or field_name
|
||||
* @param \caption_field[] $caption_fields caption-fields (from record) matching meta_struct_id or field_name (or all if not set)
|
||||
* @param int|null $meta_id
|
||||
* @param string[] $values
|
||||
*
|
||||
* @return array ops to execute
|
||||
* @throws Exception
|
||||
*/
|
||||
private function setmetadatasAction_set($struct_fields, $caption_fields, $meta_id, $values)
|
||||
{
|
||||
$ops = [];
|
||||
|
||||
// if one field was multi-valued and no meta_id was set, we must delete all values
|
||||
foreach ($caption_fields as $cf) {
|
||||
if ($cf->is_multi() && is_null($meta_id)) {
|
||||
foreach ($cf->get_values() as $field_value) {
|
||||
$ops[] = [
|
||||
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||
'meta_id' => $field_value->getId(),
|
||||
'value' => null
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
// now set values to matching struct_fields
|
||||
foreach ($struct_fields as $sf) {
|
||||
if($sf->is_multi()) {
|
||||
// add the non-null value(s)
|
||||
foreach ($values as $value) {
|
||||
if (!is_null($value)) {
|
||||
$ops[] = [
|
||||
'meta_struct_id' => $sf->get_id(),
|
||||
'meta_id' => $meta_id, // can be null
|
||||
'value' => $value
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// mono-valued
|
||||
if(count($values) > 1) {
|
||||
throw new Exception(sprintf("setting mono-valued (%s) requires only one value.", $sf->get_name()));
|
||||
}
|
||||
$ops[] = [
|
||||
'meta_struct_id' => $sf->get_id(),
|
||||
'meta_id' => $meta_id, // probably null,
|
||||
'value' => $values[0]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param databox_field[] $struct_fields struct-fields (from struct) matching meta_struct_id or field_name
|
||||
* @param string[] $values
|
||||
*
|
||||
* @return array ops to execute
|
||||
* @throws Exception
|
||||
*/
|
||||
private function setmetadatasAction_add($struct_fields, $values)
|
||||
{
|
||||
$ops = [];
|
||||
|
||||
// now set values to matching struct_fields
|
||||
foreach ($struct_fields as $sf) {
|
||||
if(!$sf->is_multi()) {
|
||||
throw new Exception(sprintf("can't \"add\" to mono-valued (%s).", $sf->get_name()));
|
||||
}
|
||||
// add the non-null value(s)
|
||||
foreach ($values as $value) {
|
||||
if (!is_null($value)) {
|
||||
$ops[] = [
|
||||
'meta_struct_id' => $sf->get_id(),
|
||||
'meta_id' => null,
|
||||
'value' => $value
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \caption_field[] $caption_fields caption-fields (from record) matching meta_struct_id or field_name (or all if not set)
|
||||
* @param int|null $meta_id
|
||||
* @param string $match_method "strict" | "ignore_case" | "regexp"
|
||||
* @param string[] $values
|
||||
* @param string|null $replace_with
|
||||
*
|
||||
* @return array ops to execute
|
||||
*/
|
||||
private function setmetadatasAction_replace($caption_fields, $meta_id, $match_method, $values, $replace_with)
|
||||
{
|
||||
$ops = [];
|
||||
|
||||
foreach ($caption_fields as $cf) {
|
||||
// match all ?
|
||||
if(is_null($meta_id) && count($values) == 0) {
|
||||
foreach ($cf->get_values() as $field_value) {
|
||||
$ops[] = [
|
||||
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||
'meta_id' => $field_value->getId(),
|
||||
'value' => $replace_with
|
||||
];
|
||||
}
|
||||
}
|
||||
// match by meta-id ?
|
||||
if (!is_null($meta_id)) {
|
||||
foreach ($cf->get_values() as $field_value) {
|
||||
if ($field_value->getId() === $meta_id) {
|
||||
$ops[] = [
|
||||
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||
'meta_id' => $field_value->getId(),
|
||||
'value' => $replace_with
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
// match by value(s) ?
|
||||
foreach ($values as $value) {
|
||||
foreach ($cf->get_values() as $field_value) {
|
||||
$rw = $replace_with;
|
||||
if($match_method=='regexp' && !is_null($replace_with)) {
|
||||
$rw = preg_replace($value, $replace_with, $field_value->getValue());
|
||||
}
|
||||
if ($this->match($value, $match_method, $field_value->getValue())) {
|
||||
$ops[] = [
|
||||
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||
'meta_id' => $field_value->getId(),
|
||||
'value' => $rw
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return V3ResultHelpers
|
||||
*/
|
||||
private function getResultHelpers()
|
||||
{
|
||||
static $rh = null;
|
||||
|
||||
if(is_null($rh)) {
|
||||
$rh = new V3ResultHelpers(
|
||||
$this,
|
||||
$this->getConf(),
|
||||
$this->app['media_accessor.subdef_url_generator']
|
||||
);
|
||||
}
|
||||
return $rh;
|
||||
}
|
||||
}
|
52
lib/Alchemy/Phrasea/Controller/Api/V3/V3ResultHelpers.php
Normal file
52
lib/Alchemy/Phrasea/Controller/Api/V3/V3ResultHelpers.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||
|
||||
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||
use Alchemy\Phrasea\Media\MediaSubDefinitionUrlGenerator;
|
||||
use databox_status;
|
||||
use record_adapter;
|
||||
|
||||
|
||||
class V3ResultHelpers
|
||||
{
|
||||
/** @var controller */
|
||||
private $controller;
|
||||
|
||||
/** @var MediaSubDefinitionUrlGenerator */
|
||||
private $urlgenerator;
|
||||
|
||||
/** @var PropertyAccess */
|
||||
private $conf;
|
||||
|
||||
|
||||
public function __construct($controller, $conf, $urlgenerator)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
$this->urlgenerator = $urlgenerator;
|
||||
$this->conf = $conf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve detailed information about one status
|
||||
*
|
||||
* @param record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
public function listRecordStatus(record_adapter $record)
|
||||
{
|
||||
$ret = [];
|
||||
foreach ($record->getStatusStructure() as $bit => $status) {
|
||||
$ret[] = [
|
||||
'bit' => $bit,
|
||||
'state' => databox_status::bitIsSet($record->getStatusBitField(), $bit),
|
||||
];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
488
lib/Alchemy/Phrasea/Controller/Api/V3/V3SearchController.php
Normal file
488
lib/Alchemy/Phrasea/Controller/Api/V3/V3SearchController.php
Normal file
@@ -0,0 +1,488 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Application\Helper\JsonBodyAware;
|
||||
use Alchemy\Phrasea\Collection\Reference\CollectionReference;
|
||||
use Alchemy\Phrasea\Controller\Api\Result;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Databox\DataboxGroupable;
|
||||
use Alchemy\Phrasea\Fractal\CallbackTransformer;
|
||||
use Alchemy\Phrasea\Fractal\IncludeResolver;
|
||||
use Alchemy\Phrasea\Fractal\SearchResultTransformerResolver;
|
||||
use Alchemy\Phrasea\Fractal\TraceableArraySerializer;
|
||||
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Record\RecordCollection;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use Alchemy\Phrasea\Search\CaptionView;
|
||||
use Alchemy\Phrasea\Search\PermalinkTransformer;
|
||||
use Alchemy\Phrasea\Search\PermalinkView;
|
||||
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\SubdefView;
|
||||
use Alchemy\Phrasea\Search\TechnicalDataTransformer;
|
||||
use Alchemy\Phrasea\Search\TechnicalDataView;
|
||||
use Alchemy\Phrasea\Search\V1SearchCompositeResultTransformer;
|
||||
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 caption_record;
|
||||
use League\Fractal\Manager as FractalManager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use media_Permalink_Adapter;
|
||||
use media_subdef;
|
||||
use record_adapter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class V3SearchController extends Controller
|
||||
{
|
||||
use JsonBodyAware;
|
||||
use DispatcherAware;
|
||||
|
||||
/**
|
||||
* 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 FractalManager();
|
||||
$fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher']));
|
||||
$fractal->parseIncludes($this->resolveSearchIncludes($request));
|
||||
|
||||
$result = $this->doSearch($request);
|
||||
|
||||
$story_max_records = null;
|
||||
// if search on story
|
||||
if ($request->get('search_type') == 1) {
|
||||
$story_max_records = (int)$request->get('story_max_records') ?: 10;
|
||||
}
|
||||
|
||||
$searchView = $this->buildSearchView(
|
||||
$result,
|
||||
$includeResolver->resolve($fractal),
|
||||
$this->resolveSubdefUrlTTL($request),
|
||||
$story_max_records
|
||||
);
|
||||
|
||||
$ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray();
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_records
|
||||
* @return SearchResultView
|
||||
*/
|
||||
private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_records = 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_records);
|
||||
$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<int, bool>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
359
lib/Alchemy/Phrasea/Controller/Api/V3/V3StoriesController.php
Normal file
359
lib/Alchemy/Phrasea/Controller/Api/V3/V3StoriesController.php
Normal file
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||
|
||||
use ACL;
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Application\Helper\JsonBodyAware;
|
||||
use Alchemy\Phrasea\Controller\Api\Result;
|
||||
use Alchemy\Phrasea\Controller\Api\V1Controller;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use caption_field;
|
||||
use caption_record;
|
||||
use databox_Field_DCESAbstract;
|
||||
use Exception;
|
||||
use media_Permalink_Adapter;
|
||||
use media_subdef;
|
||||
use record_adapter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
|
||||
class V3StoriesController extends Controller
|
||||
{
|
||||
use JsonBodyAware;
|
||||
use DispatcherAware;
|
||||
|
||||
/**
|
||||
* Return detailed information about one story
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $databox_id
|
||||
* @param int $record_id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getStoryAction(Request $request, $databox_id, $record_id)
|
||||
{
|
||||
try {
|
||||
$story = $this->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, 'Story Not Found')->createResponse();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return $this->app['controller.api.v1']->getBadRequestAction($request, 'An error occurred');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return V3ResultHelpers
|
||||
*/
|
||||
private function getResultHelpers()
|
||||
{
|
||||
static $rh = null;
|
||||
|
||||
if(is_null($rh)) {
|
||||
$rh = new V3ResultHelpers(
|
||||
$this,
|
||||
$this->getConf(),
|
||||
$this->app['media_accessor.subdef_url_generator']
|
||||
);
|
||||
}
|
||||
return $rh;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
$per_page = (int)$request->get('per_page')?:10;
|
||||
$page = (int)$request->get('page')?:1;
|
||||
$offset = ($per_page * ($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, $per_page)->get_elements())),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
public 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(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve detailed information about one record
|
||||
*
|
||||
* @param Request $request
|
||||
* @param record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
public 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->getResultHelpers()->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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -3,22 +3,39 @@
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
||||
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Api\V3Controller;
|
||||
use Alchemy\Phrasea\Controller\Api\V3\V3MetadatasController;
|
||||
use Alchemy\Phrasea\Controller\Api\V3\V3SearchController;
|
||||
use Alchemy\Phrasea\Controller\Api\V3\V3StoriesController;
|
||||
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerCollection;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
|
||||
class V3 extends Api implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
const VERSION = '3.0.0';
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
*
|
||||
* @uses V3MetadatasController::setmetadatasAction()
|
||||
* @uses V3SearchController::searchAction()
|
||||
* @uses V3StoriesController::getStoryAction()
|
||||
*/
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.api.v3'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new V3Controller($app))
|
||||
->setJsonBodyHelper($app['json.body_helper']);
|
||||
$app['controller.api.v3.metadatas'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new V3MetadatasController($app))
|
||||
->setJsonBodyHelper($app['json.body_helper'])
|
||||
;
|
||||
});
|
||||
$app['controller.api.v3.search'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new V3SearchController($app));
|
||||
});
|
||||
$app['controller.api.v3.stories'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new V3StoriesController($app));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,14 +54,14 @@ class V3 extends Api implements ControllerProviderInterface, ServiceProviderInte
|
||||
|
||||
$controllers->before(new OAuthListener());
|
||||
|
||||
$controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3:getStoryAction')
|
||||
$controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3.stories:getStoryAction')
|
||||
->before('controller.api.v1:ensureCanAccessToRecord')
|
||||
->assert('databox_id', '\d+')
|
||||
->assert('record_id', '\d+');
|
||||
|
||||
$controllers->match('/search/', 'controller.api.v3:searchAction');
|
||||
$controllers->match('/search/', 'controller.api.v3.search:searchAction');
|
||||
|
||||
$controllers->patch('/records/{databox_id}/{record_id}/setmetadatas/', 'controller.api.v3:setmetadatasAction')
|
||||
$controllers->patch('/records/{databox_id}/{record_id}/setmetadatas/', 'controller.api.v3.metadatas:setmetadatasAction')
|
||||
->before('controller.api.v1:ensureCanAccessToRecord')
|
||||
->before('controller.api.v1:ensureCanModifyRecord')
|
||||
->assert('databox_id', '\d+')
|
||||
|
Reference in New Issue
Block a user