mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 07:23:13 +00:00
Extract view builder class to build view model
This commit is contained in:
@@ -20,10 +20,11 @@ use Alchemy\Phrasea\Model\Entities\Order;
|
||||
use Alchemy\Phrasea\Model\Entities\OrderElement;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Order\OrderElementTransformer;
|
||||
use Alchemy\Phrasea\Order\OrderElementViewModel;
|
||||
use Alchemy\Phrasea\Order\OrderElementView;
|
||||
use Alchemy\Phrasea\Order\OrderFiller;
|
||||
use Alchemy\Phrasea\Order\OrderTransformer;
|
||||
use Alchemy\Phrasea\Order\OrderViewModel;
|
||||
use Alchemy\Phrasea\Order\OrderView;
|
||||
use Alchemy\Phrasea\Order\OrderViewBuilder;
|
||||
use Alchemy\Phrasea\Record\RecordReference;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use Assert\Assertion;
|
||||
@@ -74,7 +75,7 @@ class ApiOrderController extends BaseOrderController
|
||||
{
|
||||
$page = max((int) $request->get('page', '1'), 1);
|
||||
$perPage = min(max((int)$request->get('per_page', '10'), 1), 100);
|
||||
$fractal = $this->parseIncludes($request->get('includes', []));
|
||||
$fractal = $this->buildFractalManager($request->get('includes', []));
|
||||
|
||||
$routeGenerator = function ($page) use ($perPage) {
|
||||
return $this->app->path('api_v2_orders_index', [
|
||||
@@ -95,8 +96,10 @@ class ApiOrderController extends BaseOrderController
|
||||
;
|
||||
}
|
||||
|
||||
$collection = $this->buildOrderViewModels($builder->getQuery()->getResult());
|
||||
$this->fillViewModels($collection, $fractal->getRequestedIncludes());
|
||||
$collection = $this->getViewBuilder()->buildViews(
|
||||
$builder->getQuery()->getResult(),
|
||||
$fractal->getRequestedIncludes()
|
||||
);
|
||||
|
||||
$resource = new Collection($collection, $this->getOrderTransformer());
|
||||
|
||||
@@ -118,15 +121,13 @@ class ApiOrderController extends BaseOrderController
|
||||
{
|
||||
$order = $this->findOr404($orderId);
|
||||
|
||||
$fractal = $this->parseIncludes($request->get('includes', []));
|
||||
$fractal = $this->buildFractalManager($request->get('includes', []));
|
||||
|
||||
if ($order->getUser()->getId() !== $this->getAuthenticatedUser()->getId()) {
|
||||
throw new AccessDeniedHttpException(sprintf('Cannot access order "%d"', $order->getId()));
|
||||
}
|
||||
|
||||
$model = $this->buildOrderViewModel($order);
|
||||
$this->fillViewModels([$model], $fractal->getRequestedIncludes());
|
||||
|
||||
$model = $this->getViewBuilder()->buildView($order, $fractal->getRequestedIncludes());
|
||||
$resource = new Item($model, $this->getOrderTransformer());
|
||||
|
||||
return $this->returnResourceResponse($request, $fractal, $resource);
|
||||
@@ -209,7 +210,7 @@ class ApiOrderController extends BaseOrderController
|
||||
* @param string|array $includes
|
||||
* @return Manager
|
||||
*/
|
||||
private function parseIncludes($includes)
|
||||
private function buildFractalManager($includes)
|
||||
{
|
||||
$fractal = new Manager();
|
||||
|
||||
@@ -226,7 +227,7 @@ class ApiOrderController extends BaseOrderController
|
||||
*/
|
||||
private function returnResourceResponse(Request $request, $includes, ResourceInterface $resource)
|
||||
{
|
||||
$fractal = $includes instanceof Manager ? $includes : $this->parseIncludes($includes);
|
||||
$fractal = $includes instanceof Manager ? $includes : $this->buildFractalManager($includes);
|
||||
|
||||
return Result::create($request, $fractal->createData($resource)->toArray())->createResponse();
|
||||
}
|
||||
@@ -248,162 +249,12 @@ class ApiOrderController extends BaseOrderController
|
||||
return $elementIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderViewModel[] $models
|
||||
* @param array $includes
|
||||
* @return void
|
||||
*/
|
||||
private function fillViewModels(array $models, array $includes)
|
||||
private function getViewBuilder()
|
||||
{
|
||||
if (!in_array('elements', $includes, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$elements = $this->gatherElements($models);
|
||||
|
||||
$allElements = $elements ? call_user_func_array('array_merge', $elements) : [];
|
||||
$allElements = array_combine(
|
||||
array_map(function (OrderElement $element) {
|
||||
return $element->getId();
|
||||
}, $allElements),
|
||||
$allElements
|
||||
return new OrderViewBuilder(
|
||||
$this->app,
|
||||
$this->getApplicationBox(),
|
||||
$this->app['service.media_subdef']
|
||||
);
|
||||
|
||||
if (!$allElements) {
|
||||
return;
|
||||
}
|
||||
|
||||
$collectionToDataboxMap = $this->mapBaseIdToDataboxId($allElements);
|
||||
|
||||
$records = RecordReferenceCollection::fromListExtractor(
|
||||
$allElements,
|
||||
function (OrderElement $element) use ($collectionToDataboxMap) {
|
||||
return isset($collectionToDataboxMap[$element->getBaseId()])
|
||||
? [$collectionToDataboxMap[$element->getBaseId()], $element->getRecordId()]
|
||||
: null;
|
||||
},
|
||||
function (array $data) {
|
||||
list ($databoxId, $recordId) = $data;
|
||||
|
||||
return RecordReference::createFromDataboxIdAndRecordId($databoxId, $recordId);
|
||||
}
|
||||
);
|
||||
|
||||
$this->createOrderElementViewModels($models, $elements, $records);
|
||||
|
||||
if (!in_array('elements.resource_links', $includes, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load all records
|
||||
$records->toRecords($this->getApplicationBox());
|
||||
|
||||
// Load all subdefs
|
||||
$subdefs = $this->app['service.media_subdef']->findSubdefsFromRecordReferenceCollection($records);
|
||||
\media_Permalink_Adapter::getMany($this->app, $subdefs);
|
||||
|
||||
$orderableSubdefs = [];
|
||||
|
||||
foreach ($subdefs as $subdef) {
|
||||
$databoxId = $subdef->get_sbas_id();
|
||||
$recordId = $subdef->get_record_id();
|
||||
|
||||
if (!isset($orderableSubdefs[$databoxId][$recordId])) {
|
||||
$orderableSubdefs[$databoxId][$recordId] = [];
|
||||
}
|
||||
|
||||
$orderableSubdefs[$databoxId][$recordId][] = $subdef;
|
||||
}
|
||||
|
||||
foreach ($models as $model) {
|
||||
foreach ($model->getElements() as $element) {
|
||||
$databoxId = $collectionToDataboxMap[$element->getElement()->getBaseId()];
|
||||
$recordId = $element->getElement()->getRecordId();
|
||||
|
||||
if (isset($orderableSubdefs[$databoxId][$recordId])) {
|
||||
$element->setOrderableMediaSubdefs($orderableSubdefs[$databoxId][$recordId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Order[] $orders
|
||||
* @return OrderViewModel[]
|
||||
*/
|
||||
private function buildOrderViewModels(array $orders)
|
||||
{
|
||||
Assertion::allIsInstanceOf($orders, Order::class);
|
||||
|
||||
return array_map(function (Order $order) {
|
||||
return new OrderViewModel($order);
|
||||
}, $orders);
|
||||
}
|
||||
|
||||
private function buildOrderViewModel(Order $order)
|
||||
{
|
||||
return new OrderViewModel($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderViewModel[] $models
|
||||
* @return OrderElement[][]
|
||||
*/
|
||||
private function gatherElements(array $models)
|
||||
{
|
||||
Assertion::allIsInstanceOf($models, OrderViewModel::class);
|
||||
|
||||
$elements = [];
|
||||
|
||||
foreach ($models as $index => $model) {
|
||||
$elements[$index] = $model->getOrder()->getElements()->toArray();
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderElement[] $elements
|
||||
* @return array
|
||||
*/
|
||||
private function mapBaseIdToDataboxId(array $elements)
|
||||
{
|
||||
$baseIds = array_keys(array_reduce($elements, function (array &$baseIds, OrderElement $element) {
|
||||
$baseIds[$element->getBaseId()] = true;
|
||||
|
||||
return $baseIds;
|
||||
}, []));
|
||||
|
||||
$collectionToDataboxMap = [];
|
||||
|
||||
foreach ($this->app['repo.collection-references']->findMany($baseIds) as $collectionReference) {
|
||||
$collectionToDataboxMap[$collectionReference->getBaseId()] = $collectionReference->getDataboxId();
|
||||
}
|
||||
|
||||
return $collectionToDataboxMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderViewModel[] $orderViewModels
|
||||
* @param OrderElement[][] $elements
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return void
|
||||
*/
|
||||
private function createOrderElementViewModels(array $orderViewModels, $elements, $records)
|
||||
{
|
||||
$user = $this->getAuthenticatedUser();
|
||||
|
||||
foreach ($orderViewModels as $index => $model) {
|
||||
$models = [];
|
||||
|
||||
/** @var OrderElement $element */
|
||||
foreach ($elements[$index] as $elementIndex => $element) {
|
||||
if (isset($records[$element->getId()])) {
|
||||
$models[$elementIndex] = new OrderElementViewModel($element, $records[$element->getId()], $user);
|
||||
}
|
||||
}
|
||||
|
||||
$model->setViewElements($models);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ class OrderElementTransformer extends TransformerAbstract
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
public function transform(OrderElementViewModel $model)
|
||||
public function transform(OrderElementView $model)
|
||||
{
|
||||
$element = $model->getElement();
|
||||
$record = $model->getRecordReference();
|
||||
@@ -54,7 +54,7 @@ class OrderElementTransformer extends TransformerAbstract
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function includeResourceLinks(OrderElementViewModel $model, ParamBag $params = null)
|
||||
public function includeResourceLinks(OrderElementView $model, ParamBag $params = null)
|
||||
{
|
||||
$ttl = null;
|
||||
|
||||
|
@@ -15,7 +15,7 @@ use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Assert\Assertion;
|
||||
|
||||
class OrderElementViewModel
|
||||
class OrderElementView
|
||||
{
|
||||
/**
|
||||
* @var OrderElement
|
||||
@@ -39,6 +39,7 @@ class OrderElementViewModel
|
||||
|
||||
/**
|
||||
* OrderElementViewModel constructor.
|
||||
*
|
||||
* @param OrderElement $element
|
||||
* @param RecordReferenceInterface $record
|
||||
* @param User $user
|
||||
@@ -50,16 +51,25 @@ class OrderElementViewModel
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OrderElement
|
||||
*/
|
||||
public function getElement()
|
||||
{
|
||||
return $this->element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecordReferenceInterface
|
||||
*/
|
||||
public function getRecordReference()
|
||||
{
|
||||
return $this->record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function getAuthenticatedUser()
|
||||
{
|
||||
return $this->user;
|
||||
@@ -75,6 +85,9 @@ class OrderElementViewModel
|
||||
$this->subdefs = $subdefs instanceof \Traversable ? iterator_to_array($subdefs) : $subdefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \media_subdef[]
|
||||
*/
|
||||
public function getOrderableMediaSubdefs()
|
||||
{
|
||||
return $this->subdefs;
|
@@ -28,7 +28,7 @@ class OrderTransformer extends TransformerAbstract
|
||||
$this->elementTransformer = $elementTransformer;
|
||||
}
|
||||
|
||||
public function transform(OrderViewModel $view)
|
||||
public function transform(OrderView $view)
|
||||
{
|
||||
$order = $view->getOrder();
|
||||
|
||||
@@ -47,7 +47,7 @@ class OrderTransformer extends TransformerAbstract
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function includeElements(OrderViewModel $order)
|
||||
public function includeElements(OrderView $order)
|
||||
{
|
||||
$elements = $order->getElements();
|
||||
|
||||
|
@@ -13,14 +13,15 @@ namespace Alchemy\Phrasea\Order;
|
||||
use Alchemy\Phrasea\Model\Entities\Order;
|
||||
use Assert\Assertion;
|
||||
|
||||
class OrderViewModel
|
||||
class OrderView
|
||||
{
|
||||
/**
|
||||
* @var Order
|
||||
*/
|
||||
private $order;
|
||||
|
||||
/**
|
||||
* @var OrderElementViewModel[]
|
||||
* @var OrderElementView[]
|
||||
*/
|
||||
private $viewElements = [];
|
||||
|
||||
@@ -33,11 +34,11 @@ class OrderViewModel
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $viewElements
|
||||
* @param OrderElementView[] $viewElements
|
||||
*/
|
||||
public function setViewElements($viewElements)
|
||||
{
|
||||
Assertion::allIsInstanceOf($viewElements, OrderElementViewModel::class);
|
||||
Assertion::allIsInstanceOf($viewElements, OrderElementView::class);
|
||||
|
||||
$this->viewElements = $viewElements instanceof \Traversable ? iterator_to_array($viewElements) : $viewElements;
|
||||
}
|
||||
@@ -51,7 +52,7 @@ class OrderViewModel
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OrderElementViewModel[]
|
||||
* @return OrderElementView[]
|
||||
*/
|
||||
public function getElements()
|
||||
{
|
222
lib/Alchemy/Phrasea/Order/OrderViewBuilder.php
Normal file
222
lib/Alchemy/Phrasea/Order/OrderViewBuilder.php
Normal file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of alchemy/pipeline-component.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Order;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Databox\Subdef\MediaSubdefService;
|
||||
use Alchemy\Phrasea\Model\Entities\Order;
|
||||
use Alchemy\Phrasea\Model\Entities\OrderElement;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Record\RecordReference;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use Assert\Assertion;
|
||||
|
||||
class OrderViewBuilder
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
|
||||
/**
|
||||
* @var \appbox
|
||||
*/
|
||||
private $applicationBox;
|
||||
|
||||
/**
|
||||
* @var MediaSubdefService
|
||||
*/
|
||||
private $mediaSubdefService;
|
||||
|
||||
/**
|
||||
* @param Application $application
|
||||
* @param \appbox $appbox
|
||||
* @param MediaSubdefService $subdefService
|
||||
*/
|
||||
public function __construct(Application $application, \appbox $appbox, MediaSubdefService $subdefService)
|
||||
{
|
||||
$this->application = $application;
|
||||
$this->applicationBox = $appbox;
|
||||
$this->mediaSubdefService = $subdefService;
|
||||
}
|
||||
|
||||
public function buildView(Order $order, array $includes)
|
||||
{
|
||||
$view = new OrderView($order);
|
||||
|
||||
$this->fillViews([$view], $includes);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Order[] $orders
|
||||
* @param string[] $includes
|
||||
* @return OrderView[]
|
||||
*/
|
||||
public function buildViews(array $orders, array $includes)
|
||||
{
|
||||
Assertion::allIsInstanceOf($orders, Order::class);
|
||||
|
||||
$views = array_map(function (Order $order) {
|
||||
return new OrderView($order);
|
||||
}, $orders);
|
||||
|
||||
$this->fillViews($views, $includes);
|
||||
|
||||
return $views;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderView[] $views
|
||||
* @param array $includes
|
||||
* @return void
|
||||
*/
|
||||
private function fillViews(array $views, array $includes)
|
||||
{
|
||||
if (!in_array('elements', $includes, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$elements = $this->gatherElements($views);
|
||||
|
||||
$allElements = $elements ? call_user_func_array('array_merge', $elements) : [];
|
||||
$allElements = array_combine(
|
||||
array_map(function (OrderElement $element) {
|
||||
return $element->getId();
|
||||
}, $allElements),
|
||||
$allElements
|
||||
);
|
||||
|
||||
if (!$allElements) {
|
||||
return;
|
||||
}
|
||||
|
||||
$collectionToDataboxMap = $this->mapBaseIdToDataboxId($allElements);
|
||||
|
||||
$records = RecordReferenceCollection::fromListExtractor(
|
||||
$allElements,
|
||||
function (OrderElement $element) use ($collectionToDataboxMap) {
|
||||
return isset($collectionToDataboxMap[$element->getBaseId()])
|
||||
? [$collectionToDataboxMap[$element->getBaseId()], $element->getRecordId()]
|
||||
: null;
|
||||
},
|
||||
function (array $data) {
|
||||
list ($databoxId, $recordId) = $data;
|
||||
|
||||
return RecordReference::createFromDataboxIdAndRecordId($databoxId, $recordId);
|
||||
}
|
||||
);
|
||||
|
||||
$this->createOrderElementViews($views, $elements, $records);
|
||||
|
||||
if (!in_array('elements.resource_links', $includes, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load all records
|
||||
$records->toRecords($this->applicationBox);
|
||||
|
||||
// Load all subdefs
|
||||
$subdefs = $this->mediaSubdefService->findSubdefsFromRecordReferenceCollection($records);
|
||||
\media_Permalink_Adapter::getMany($this->application, $subdefs);
|
||||
|
||||
$orderableSubdefs = [];
|
||||
|
||||
foreach ($subdefs as $subdef) {
|
||||
$databoxId = $subdef->get_sbas_id();
|
||||
$recordId = $subdef->get_record_id();
|
||||
|
||||
if (!isset($orderableSubdefs[$databoxId][$recordId])) {
|
||||
$orderableSubdefs[$databoxId][$recordId] = [];
|
||||
}
|
||||
|
||||
$orderableSubdefs[$databoxId][$recordId][] = $subdef;
|
||||
}
|
||||
|
||||
foreach ($views as $model) {
|
||||
foreach ($model->getElements() as $element) {
|
||||
$databoxId = $collectionToDataboxMap[$element->getElement()->getBaseId()];
|
||||
$recordId = $element->getElement()->getRecordId();
|
||||
|
||||
if (isset($orderableSubdefs[$databoxId][$recordId])) {
|
||||
$element->setOrderableMediaSubdefs($orderableSubdefs[$databoxId][$recordId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param OrderView[] $elements
|
||||
* @return OrderElement[][]
|
||||
*/
|
||||
private function gatherElements(array $elements)
|
||||
{
|
||||
Assertion::allIsInstanceOf($elements, OrderView::class);
|
||||
|
||||
$elements = [];
|
||||
|
||||
foreach ($elements as $index => $model) {
|
||||
$elements[$index] = $model->getOrder()->getElements()->toArray();
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderElement[] $elements
|
||||
* @return array
|
||||
*/
|
||||
private function mapBaseIdToDataboxId(array $elements)
|
||||
{
|
||||
$baseIds = array_keys(array_reduce($elements, function (array &$baseIds, OrderElement $element) {
|
||||
$baseIds[$element->getBaseId()] = true;
|
||||
|
||||
return $baseIds;
|
||||
}, []));
|
||||
|
||||
$collectionToDataboxMap = [];
|
||||
|
||||
foreach ($this->application['repo.collection-references']->findMany($baseIds) as $collectionReference) {
|
||||
$collectionToDataboxMap[$collectionReference->getBaseId()] = $collectionReference->getDataboxId();
|
||||
}
|
||||
|
||||
return $collectionToDataboxMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderView[] $orderViews
|
||||
* @param OrderElement[][] $elements
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return void
|
||||
*/
|
||||
private function createOrderElementViews(array $orderViews, $elements, $records)
|
||||
{
|
||||
$user = $this->application->getAuthenticatedUser();
|
||||
|
||||
foreach ($orderViews as $index => $model) {
|
||||
$models = [];
|
||||
|
||||
/** @var OrderElement $element */
|
||||
foreach ($elements[$index] as $elementIndex => $element) {
|
||||
if (isset($records[$element->getId()])) {
|
||||
$models[$elementIndex] = new OrderElementView($element, $records[$element->getId()], $user);
|
||||
}
|
||||
}
|
||||
|
||||
$model->setViewElements($models);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user