mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
Merge pull request #3526 from alchemy-fr/PHRAS-3092_api-setmetadats-v3_master
PHRAS-3092 #comment merge api setmetadatas v3
This commit is contained in:
382
lib/Alchemy/Phrasea/Controller/Api/V3/V3MetadatasController.php
Normal file
382
lib/Alchemy/Phrasea/Controller/Api/V3/V3MetadatasController.php
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
<?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 caption_field;
|
||||||
|
use databox_field;
|
||||||
|
use Exception;
|
||||||
|
use record_adapter;
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
|
$debug = [
|
||||||
|
'metadatas_ops' => null,
|
||||||
|
'sb_ops' => null,
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
// do metadatas ops
|
||||||
|
if (is_array($b->metadatas)) {
|
||||||
|
$debug['metadatas_ops'] = $this->do_metadatas($struct, $record, $b->metadatas);
|
||||||
|
}
|
||||||
|
// do sb ops
|
||||||
|
if (is_array($b->status)) {
|
||||||
|
$debug['sb_ops'] = $this->do_status($struct, $record, $b->status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
return $this->app['controller.api.v1']->getBadRequestAction(
|
||||||
|
$request,
|
||||||
|
$e->getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo Move event dispatch inside record_adapter class (keeps things encapsulated)
|
||||||
|
$this->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
|
||||||
|
|
||||||
|
$ret = $this->getResultHelpers()->listRecord($request, $record, $this->getAclForUser());
|
||||||
|
|
||||||
|
return Result::create($request, $ret)->createResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
/// TODO : keep multi-values uniques !
|
||||||
|
/// it should be done in record_adapter
|
||||||
|
//////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param databox_field[] $struct
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param $metadatas
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function do_metadatas($struct, record_adapter $record, $metadatas)
|
||||||
|
{
|
||||||
|
$structByKey = [];
|
||||||
|
$nameToStrucId = [];
|
||||||
|
$allStructFields = [];
|
||||||
|
foreach ($struct as $f) {
|
||||||
|
$nameToStrucId[$f->get_name()] = $f->get_id();
|
||||||
|
$allStructFields[$f->get_id()] = $f;
|
||||||
|
$structByKey[$f->get_id()] = &$allStructFields[$f->get_id()];;
|
||||||
|
$structByKey[$f->get_name()] = &$allStructFields[$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
|
||||||
|
$field_keys = $_m->meta_struct_id ? $_m->meta_struct_id : $_m->field_name; // can be null if none defined (=match all)
|
||||||
|
if($field_keys !== null) {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no meta_struct_id, no field_name --> match all struct fields !
|
||||||
|
$struct_fields = $allStructFields;
|
||||||
|
}
|
||||||
|
$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) {
|
||||||
|
if(($v = trim((string)$v)) !== '') {
|
||||||
|
$values[] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(($v = trim((string)($_m->value))) !== '') {
|
||||||
|
$values[] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!($action = (string)($_m->action))) {
|
||||||
|
$action = 'set';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($_m->action) {
|
||||||
|
case 'set':
|
||||||
|
$ops = $this->metadata_set($struct_fields, $caption_fields, $meta_id, $values);
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
$ops = $this->metadata_add($struct_fields, $values);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
$ops = $this->metadata_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->metadata_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
$record->set_metadatas($metadatas_ops, true);
|
||||||
|
|
||||||
|
return $metadatas_ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $struct
|
||||||
|
* @param $record
|
||||||
|
* @param $statuses
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function do_status($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));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 metadata_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) {
|
||||||
|
foreach ($cf->get_values() as $field_value) {
|
||||||
|
if (is_null($meta_id) || $field_value->getId() === (int)$meta_id) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||||
|
'meta_id' => $field_value->getId(),
|
||||||
|
'value' => ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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 ($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()));
|
||||||
|
}
|
||||||
|
if( ($value = $values[0]) ) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $sf->get_id(),
|
||||||
|
'meta_id' => $meta_id, // probably null,
|
||||||
|
'value' => $value
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 metadata_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()));
|
||||||
|
}
|
||||||
|
foreach ($values as $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 metadata_replace($caption_fields, $meta_id, $match_method, $values, $replace_with)
|
||||||
|
{
|
||||||
|
$ops = [];
|
||||||
|
|
||||||
|
$replace_with = trim((string)$replace_with);
|
||||||
|
|
||||||
|
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' && $rw != '') {
|
||||||
|
$rw = preg_replace($value, $rw, $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()
|
||||||
|
{
|
||||||
|
return $this->app['controller.api.v3.resulthelpers'];
|
||||||
|
}
|
||||||
|
}
|
277
lib/Alchemy/Phrasea/Controller/Api/V3/V3ResultHelpers.php
Normal file
277
lib/Alchemy/Phrasea/Controller/Api/V3/V3ResultHelpers.php
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||||
|
|
||||||
|
|
||||||
|
use ACL;
|
||||||
|
use Alchemy\Phrasea\Authentication\Authenticator;
|
||||||
|
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||||
|
use Alchemy\Phrasea\Media\MediaSubDefinitionUrlGenerator;
|
||||||
|
use caption_field;
|
||||||
|
use databox_status;
|
||||||
|
use media_Permalink_Adapter;
|
||||||
|
use media_subdef;
|
||||||
|
use record_adapter;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
|
||||||
|
class V3ResultHelpers
|
||||||
|
{
|
||||||
|
/** @var PropertyAccess */
|
||||||
|
private $conf;
|
||||||
|
|
||||||
|
/** @var MediaSubDefinitionUrlGenerator */
|
||||||
|
private $urlgenerator;
|
||||||
|
|
||||||
|
/** @var Authenticator */
|
||||||
|
private $authenticator;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct($conf, $urlgenerator, Authenticator $authenticator)
|
||||||
|
{
|
||||||
|
$this->urlgenerator = $urlgenerator;
|
||||||
|
$this->conf = $conf;
|
||||||
|
$this->authenticator = $authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listEmbeddableMedia(Request $request, record_adapter $record, media_subdef $media, ACL $acl)
|
||||||
|
{
|
||||||
|
if (!$media->is_physically_present()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getAuthenticator()->isAuthenticated()) {
|
||||||
|
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->getAuthenticator()->getUser();
|
||||||
|
|
||||||
|
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->urlgenerator->generate($issuer, $media, $urlTTL),
|
||||||
|
'url_ttl' => $urlTTL,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param media_Permalink_Adapter $permalink
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @todo fix duplicated code
|
||||||
|
* @noinspection DuplicatedCode
|
||||||
|
*/
|
||||||
|
public 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(),
|
||||||
|
'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
|
||||||
|
* @param ACL $aclforuser
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function listRecord(Request $request, record_adapter $record, ACL $aclforuser)
|
||||||
|
{
|
||||||
|
$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(), $aclforuser),
|
||||||
|
'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, $aclforuser),
|
||||||
|
'metadata' => $this->listRecordMetadata($record, $aclforuser),
|
||||||
|
'status' => $this->listRecordStatus($record),
|
||||||
|
'caption' => $this->listRecordCaption($record, $aclforuser),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecordEmbeddableMedias(Request $request, record_adapter $record, ACL $acl)
|
||||||
|
{
|
||||||
|
$subdefs = [];
|
||||||
|
|
||||||
|
foreach ($record->get_embedable_medias([], []) as $name => $media) {
|
||||||
|
if (null !== $subdef = $this->listEmbeddableMedia($request, $record, $media, $acl)) {
|
||||||
|
$subdefs[] = $subdef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $subdefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all fields of given record
|
||||||
|
*
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param ACL $acl
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecordMetadata(record_adapter $record, ACL $acl)
|
||||||
|
{
|
||||||
|
$includeBusiness = $acl->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
|
||||||
|
* @param ACL $acl
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecordCaption(record_adapter $record, ACL $acl)
|
||||||
|
{
|
||||||
|
$includeBusiness = $acl->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
|
private function getAuthenticator()
|
||||||
|
{
|
||||||
|
return $this->authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getConf()
|
||||||
|
{
|
||||||
|
return $this->conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,8 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Alchemy\Phrasea\Controller\Api;
|
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\Collection\Reference\CollectionReference;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\Result;
|
||||||
use Alchemy\Phrasea\Controller\Controller;
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
use Alchemy\Phrasea\Databox\DataboxGroupable;
|
use Alchemy\Phrasea\Databox\DataboxGroupable;
|
||||||
use Alchemy\Phrasea\Fractal\CallbackTransformer;
|
use Alchemy\Phrasea\Fractal\CallbackTransformer;
|
||||||
@@ -31,34 +34,19 @@ use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
|
|||||||
use Alchemy\Phrasea\SearchEngine\SearchEngineLogger;
|
use Alchemy\Phrasea\SearchEngine\SearchEngineLogger;
|
||||||
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
||||||
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
||||||
|
use caption_record;
|
||||||
|
use League\Fractal\Manager as FractalManager;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
|
use media_Permalink_Adapter;
|
||||||
|
use media_subdef;
|
||||||
|
use record_adapter;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
||||||
|
|
||||||
class V3Controller extends Controller
|
class V3SearchController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
use JsonBodyAware;
|
||||||
* Return detailed information about one story
|
use DispatcherAware;
|
||||||
*
|
|
||||||
* @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, $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
|
* Search for results
|
||||||
@@ -101,7 +89,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
$includeResolver = new IncludeResolver($transformerResolver);
|
$includeResolver = new IncludeResolver($transformerResolver);
|
||||||
|
|
||||||
$fractal = new \League\Fractal\Manager();
|
$fractal = new FractalManager();
|
||||||
$fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher']));
|
$fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher']));
|
||||||
$fractal->parseIncludes($this->resolveSearchIncludes($request));
|
$fractal->parseIncludes($this->resolveSearchIncludes($request));
|
||||||
|
|
||||||
@@ -125,313 +113,6 @@ class V3Controller extends Controller
|
|||||||
return Result::create($request, $ret)->createResponse();
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
$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())),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
* Returns requested includes
|
||||||
*
|
*
|
||||||
@@ -660,7 +341,7 @@ class V3Controller extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RecordCollection|\record_adapter[] $references
|
* @param RecordCollection|record_adapter[] $references
|
||||||
* @return RecordView[]
|
* @return RecordView[]
|
||||||
*/
|
*/
|
||||||
private function buildRecordViews($references)
|
private function buildRecordViews($references)
|
||||||
@@ -693,7 +374,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
foreach ($subdefGroups as $index => $subdefGroup) {
|
foreach ($subdefGroups as $index => $subdefGroup) {
|
||||||
if (!isset($subdefGroup['thumbnail'])) {
|
if (!isset($subdefGroup['thumbnail'])) {
|
||||||
$fakeSubdef = new \media_subdef($this->app, $references[$index], 'thumbnail', true, []);
|
$fakeSubdef = new media_subdef($this->app, $references[$index], 'thumbnail', true, []);
|
||||||
$fakeSubdefs[spl_object_hash($fakeSubdef)] = $fakeSubdef;
|
$fakeSubdefs[spl_object_hash($fakeSubdef)] = $fakeSubdef;
|
||||||
|
|
||||||
$subdefGroups[$index]['thumbnail'] = $fakeSubdef;
|
$subdefGroups[$index]['thumbnail'] = $fakeSubdef;
|
||||||
@@ -701,9 +382,9 @@ class V3Controller extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$allSubdefs = $this->mergeGroupsIntoOneList($subdefGroups);
|
$allSubdefs = $this->mergeGroupsIntoOneList($subdefGroups);
|
||||||
$allPermalinks = \media_Permalink_Adapter::getMany(
|
$allPermalinks = media_Permalink_Adapter::getMany(
|
||||||
$this->app,
|
$this->app,
|
||||||
array_filter($allSubdefs, function (\media_subdef $subdef) use ($fakeSubdefs) {
|
array_filter($allSubdefs, function (media_subdef $subdef) use ($fakeSubdefs) {
|
||||||
return !isset($fakeSubdefs[spl_object_hash($subdef)]);
|
return !isset($fakeSubdefs[spl_object_hash($subdef)]);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -712,7 +393,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
$subdefViews = [];
|
$subdefViews = [];
|
||||||
|
|
||||||
/** @var \media_subdef $subdef */
|
/** @var media_subdef $subdef */
|
||||||
foreach ($allSubdefs as $index => $subdef) {
|
foreach ($allSubdefs as $index => $subdef) {
|
||||||
$subdefView = new SubdefView($subdef);
|
$subdefView = new SubdefView($subdef);
|
||||||
|
|
||||||
@@ -728,7 +409,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
$reorderedGroups = [];
|
$reorderedGroups = [];
|
||||||
|
|
||||||
/** @var \media_subdef[] $subdefGroup */
|
/** @var media_subdef[] $subdefGroup */
|
||||||
foreach ($subdefGroups as $index => $subdefGroup) {
|
foreach ($subdefGroups as $index => $subdefGroup) {
|
||||||
$reordered = [];
|
$reordered = [];
|
||||||
|
|
||||||
@@ -789,7 +470,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RecordView[] $recordViews
|
* @param RecordView[] $recordViews
|
||||||
* @param \caption_record[] $captions
|
* @param caption_record[] $captions
|
||||||
* @param bool[] $canSeeBusiness
|
* @param bool[] $canSeeBusiness
|
||||||
*/
|
*/
|
||||||
private function buildCaptionViews($recordViews, $captions, $canSeeBusiness)
|
private function buildCaptionViews($recordViews, $captions, $canSeeBusiness)
|
146
lib/Alchemy/Phrasea/Controller/Api/V3/V3StoriesController.php
Normal file
146
lib/Alchemy/Phrasea/Controller/Api/V3/V3StoriesController.php
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<?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\Api\V1Controller;
|
||||||
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
|
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||||
|
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||||
|
use caption_record;
|
||||||
|
use databox_Field_DCESAbstract;
|
||||||
|
use Exception;
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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->getResultHelpers()->listEmbeddableMedia($request, $story, $story->get_thumbnail(), $this->getAclForUser()),
|
||||||
|
'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->getResultHelpers()->listRecord($request, $record, $this->getAclForUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return V3ResultHelpers
|
||||||
|
*/
|
||||||
|
private function getResultHelpers()
|
||||||
|
{
|
||||||
|
return $this->app['controller.api.v3.resulthelpers'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -3,21 +3,41 @@
|
|||||||
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
||||||
|
|
||||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
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\V3ResultHelpers;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\V3\V3SearchController;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\V3\V3StoriesController;
|
||||||
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
||||||
use Silex\Application;
|
use Silex\Application;
|
||||||
use Silex\ControllerCollection;
|
use Silex\ControllerCollection;
|
||||||
use Silex\ControllerProviderInterface;
|
use Silex\ControllerProviderInterface;
|
||||||
use Silex\ServiceProviderInterface;
|
use Silex\ServiceProviderInterface;
|
||||||
|
|
||||||
|
|
||||||
class V3 extends Api implements ControllerProviderInterface, ServiceProviderInterface
|
class V3 extends Api implements ControllerProviderInterface, ServiceProviderInterface
|
||||||
{
|
{
|
||||||
const VERSION = '3.0.0';
|
const VERSION = '3.0.0';
|
||||||
|
|
||||||
public function register(Application $app)
|
public function register(Application $app)
|
||||||
{
|
{
|
||||||
$app['controller.api.v3'] = $app->share(function (PhraseaApplication $app) {
|
$app['controller.api.v3.resulthelpers'] = $app->share(function (PhraseaApplication $app) {
|
||||||
return (new V3Controller($app));
|
return (new V3ResultHelpers(
|
||||||
|
$app['conf'],
|
||||||
|
$app['media_accessor.subdef_url_generator'],
|
||||||
|
$app['authentication']
|
||||||
|
));
|
||||||
|
});
|
||||||
|
$app['controller.api.v3.metadatas'] = $app->share(function (PhraseaApplication $app) {
|
||||||
|
return (new V3MetadatasController($app))
|
||||||
|
->setJsonBodyHelper($app['json.body_helper'])
|
||||||
|
->setDispatcher($app['dispatcher'])
|
||||||
|
;
|
||||||
|
});
|
||||||
|
$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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,12 +56,32 @@ class V3 extends Api implements ControllerProviderInterface, ServiceProviderInte
|
|||||||
|
|
||||||
$controllers->before(new OAuthListener());
|
$controllers->before(new OAuthListener());
|
||||||
|
|
||||||
$controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3:getStoryAction')
|
/**
|
||||||
|
* @uses V3StoriesController::getStoryAction()
|
||||||
|
*/
|
||||||
|
$controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3.stories:getStoryAction')
|
||||||
->before('controller.api.v1:ensureCanAccessToRecord')
|
->before('controller.api.v1:ensureCanAccessToRecord')
|
||||||
->assert('databox_id', '\d+')
|
->assert('databox_id', '\d+')
|
||||||
->assert('record_id', '\d+');
|
->assert('record_id', '\d+');
|
||||||
|
|
||||||
$controllers->match('/search/', 'controller.api.v3:searchAction');
|
/**
|
||||||
|
* @uses V3SearchController::searchAction()
|
||||||
|
*/
|
||||||
|
$controllers->match('/search/', 'controller.api.v3.search:searchAction');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @uses V3MetadatasController::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+')
|
||||||
|
->assert('record_id', '\d+');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @uses \Alchemy\Phrasea\Controller\Api\V1Controller::getBadRequestAction()
|
||||||
|
*/
|
||||||
|
$controllers->match('/records/{any_id}/{anyother_id}/setmetadatas/', 'controller.api.v1:getBadRequestAction');
|
||||||
|
|
||||||
return $controllers;
|
return $controllers;
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,6 @@ class PermalinkTransformer extends TransformerAbstract
|
|||||||
'created_on' => $permalink->get_created_on()->format(DATE_ATOM),
|
'created_on' => $permalink->get_created_on()->format(DATE_ATOM),
|
||||||
'id' => $permalink->get_id(),
|
'id' => $permalink->get_id(),
|
||||||
'is_activated' => $permalink->get_is_activated(),
|
'is_activated' => $permalink->get_is_activated(),
|
||||||
/** @Ignore */
|
|
||||||
'label' => $permalink->get_label(),
|
'label' => $permalink->get_label(),
|
||||||
'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM),
|
'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM),
|
||||||
'page_url' => $permalink->get_page(),
|
'page_url' => $permalink->get_page(),
|
||||||
|
@@ -1054,10 +1054,13 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trim($params['meta_id']) !== '') {
|
|
||||||
$tmp_val = trim($params['value']);
|
$tmp_val = trim($params['value']);
|
||||||
|
|
||||||
$caption_field_value = $caption_field->get_value($params['meta_id']);
|
if (trim($params['meta_id']) !== '') {
|
||||||
|
|
||||||
|
if(is_null($caption_field_value = $caption_field->get_value($params['meta_id']))) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
if ($tmp_val === '') {
|
if ($tmp_val === '') {
|
||||||
$caption_field_value->delete();
|
$caption_field_value->delete();
|
||||||
@@ -1068,8 +1071,11 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
|||||||
$caption_field_value->setVocab($vocab, $vocab_id);
|
$caption_field_value->setVocab($vocab, $vocab_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
$caption_field_value = caption_Field_Value::create($this->app, $databox_field, $this, $params['value'], $vocab, $vocab_id);
|
else {
|
||||||
|
if($tmp_val !== '') {
|
||||||
|
caption_Field_Value::create($this->app, $databox_field, $this, $params['value'], $vocab, $vocab_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
Reference in New Issue
Block a user