refacto common code
This commit is contained in:
jygaulier
2020-06-04 14:08:08 +02:00
parent 9272f3642f
commit cdadb3acc4
5 changed files with 295 additions and 258 deletions

View File

@@ -9,8 +9,10 @@ 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;
@@ -53,11 +55,11 @@ class V3MetadatasController extends Controller
try {
// do metadatas ops
if (is_array($b->metadatas)) {
$ret['metadatas_ops'] = $this->setmetadatasAction_meta($struct, $record, $b->metadatas);
$ret['metadatas_ops'] = $this->do_metadatas($struct, $record, $b->metadatas);
}
// do sb ops
if (is_array($b->status)) {
$ret['sb_ops'] = $this->setmetadatasAction_sb($struct, $record, $b->status);
$ret['sb_ops'] = $this->do_status($struct, $record, $b->status);
}
}
catch (Exception $e) {
@@ -67,17 +69,26 @@ class V3MetadatasController extends Controller
);
}
$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 $struct
* @param $record
* @param databox_field[] $struct
* @param record_adapter $record
* @param $metadatas
* @return array
* @throws Exception
*/
private function setmetadatasAction_meta($struct, $record, $metadatas)
private function do_metadatas($struct, record_adapter $record, $metadatas)
{
$structByKey = [];
$nameToStrucId = [];
@@ -135,19 +146,19 @@ class V3MetadatasController extends Controller
switch ($_m->action) {
case 'set':
$ops = $this->setmetadatasAction_set($struct_fields, $caption_fields, $meta_id, $values);
$ops = $this->metadata_set($struct_fields, $caption_fields, $meta_id, $values);
break;
case 'add':
$ops = $this->setmetadatasAction_add($struct_fields, $values);
$ops = $this->metadata_add($struct_fields, $values);
break;
case 'delete':
$ops = $this->setmetadatasAction_replace($caption_fields, $meta_id, $match_method, $values, null);
$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->setmetadatasAction_replace($caption_fields, $meta_id, $match_method, $values, $_m->replace_with);
$ops = $this->metadata_replace($caption_fields, $meta_id, $match_method, $values, $_m->replace_with);
break;
default:
throw new Exception(sprintf("bad action (%s).", $action));
@@ -156,6 +167,8 @@ class V3MetadatasController extends Controller
$metadatas_ops = array_merge($metadatas_ops, $ops);
}
// $record->set_metadatas($metadatas_ops, true);
return $metadatas_ops;
}
@@ -166,7 +179,7 @@ class V3MetadatasController extends Controller
* @return array
* @throws Exception
*/
private function setmetadatasAction_sb($struct, $record, $statuses)
private function do_status($struct, $record, $statuses)
{
$datas = strrev($record->getStatus());
@@ -183,7 +196,7 @@ class V3MetadatasController extends Controller
$datas = substr($datas, 0, ($n)) . $value . substr($datas, ($n + 1));
}
// $record->setStatus(strrev($datas));
$record->setStatus(strrev($datas));
// @todo Move event dispatch inside record_adapter class (keeps things encapsulated)
$this->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
@@ -204,21 +217,16 @@ class V3MetadatasController extends Controller
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 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)
private function metadata_set($struct_fields, $caption_fields, $meta_id, $values)
{
$ops = [];
@@ -271,7 +279,7 @@ class V3MetadatasController extends Controller
* @return array ops to execute
* @throws Exception
*/
private function setmetadatasAction_add($struct_fields, $values)
private function metadata_add($struct_fields, $values)
{
$ops = [];
@@ -296,7 +304,7 @@ class V3MetadatasController extends Controller
}
/**
* @param \caption_field[] $caption_fields caption-fields (from record) matching meta_struct_id or field_name (or all if not set)
* @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
@@ -304,7 +312,7 @@ class V3MetadatasController extends Controller
*
* @return array ops to execute
*/
private function setmetadatasAction_replace($caption_fields, $meta_id, $match_method, $values, $replace_with)
private function metadata_replace($caption_fields, $meta_id, $match_method, $values, $replace_with)
{
$ops = [];
@@ -357,15 +365,18 @@ class V3MetadatasController extends Controller
*/
private function getResultHelpers()
{
return $this->app['controller.api.v3.resulthelpers'];
/*
static $rh = null;
if(is_null($rh)) {
$rh = new V3ResultHelpers(
$this,
$this->getConf(),
$this->app['media_accessor.subdef_url_generator']
$this->app['media_accessor.subdef_url_generator'],
$this->getAuthenticator()
);
}
return $rh;
*/
}
}

View File

@@ -3,33 +3,37 @@
namespace Alchemy\Phrasea\Controller\Api\V3;
use Alchemy\Phrasea\Controller\Controller;
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 controller */
private $controller;
/** @var PropertyAccess */
private $conf;
/** @var MediaSubDefinitionUrlGenerator */
private $urlgenerator;
/** @var PropertyAccess */
private $conf;
/** @var Authenticator */
private $authenticator;
public function __construct($controller, $conf, $urlgenerator)
public function __construct($conf, $urlgenerator, Authenticator $authenticator)
{
$this->controller = $controller;
$this->urlgenerator = $urlgenerator;
$this->conf = $conf;
$this->authenticator = $authenticator;
}
/**
* Retrieve detailed information about one status
*
@@ -49,4 +53,225 @@ class V3ResultHelpers
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;
}
}

View File

@@ -2,7 +2,6 @@
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;
@@ -10,12 +9,9 @@ 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;
@@ -51,23 +47,6 @@ class V3StoriesController extends Controller
}
}
/**
* @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
*
@@ -107,7 +86,7 @@ class V3StoriesController extends Controller
'created_on' => $story->getCreated()->format(DATE_ATOM),
'collection_id' => $story->getCollectionId(),
'base_id' => $story->getBaseId(),
'thumbnail' => $this->listEmbeddableMedia($request, $story, $story->get_thumbnail()),
'thumbnail' => $this->getResultHelpers()->listEmbeddableMedia($request, $story, $story->get_thumbnail(), $this->getAclForUser()),
'uuid' => $story->getUuid(),
'metadatas' => [
'@entity@' => V1Controller::OBJECT_TYPE_STORY_METADATA_BAG,
@@ -149,211 +128,19 @@ class V3StoriesController extends Controller
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),
]);
$data[$index] = $this->getResultHelpers()->listRecord($request, $record, $this->getAclForUser());
}
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
* @return V3ResultHelpers
*/
private function listRecordMetadata(record_adapter $record)
private function getResultHelpers()
{
$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;
return $this->app['controller.api.v3.resulthelpers'];
}
}

View File

@@ -4,6 +4,7 @@ namespace Alchemy\Phrasea\ControllerProvider\Api;
use Alchemy\Phrasea\Application as PhraseaApplication;
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;
@@ -17,18 +18,19 @@ class V3 extends Api implements ControllerProviderInterface, ServiceProviderInte
{
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.resulthelpers'] = $app->share(function (PhraseaApplication $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) {
@@ -54,18 +56,31 @@ class V3 extends Api implements ControllerProviderInterface, ServiceProviderInte
$controllers->before(new OAuthListener());
/**
* @uses V3StoriesController::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+');
/**
* @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;

View File

@@ -25,7 +25,6 @@ class PermalinkTransformer extends TransformerAbstract
'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(),