Completed
Pull Request — develop (#453)
by Luca
21:47 queued 06:50
created

ArticleController::cgetAction()   F

Complexity

Conditions 27
Paths > 20000

Size

Total Lines 150

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 59
CRAP Score 28.6919

Importance

Changes 0
Metric Value
dl 0
loc 150
ccs 59
cts 68
cp 0.8676
rs 0
c 0
b 0
f 0
cc 27
nc 786432
nop 1
crap 28.6919

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of Sulu.
5
 *
6
 * (c) Sulu GmbH
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Sulu\Bundle\ArticleBundle\Controller;
13
14
use FOS\RestBundle\Context\Context;
15
use FOS\RestBundle\Controller\Annotations\Get;
16
use FOS\RestBundle\Controller\Annotations\Post;
17
use FOS\RestBundle\Routing\ClassResourceInterface;
18
use FOS\RestBundle\View\ViewHandlerInterface;
19
use ONGR\ElasticsearchBundle\Mapping\Caser;
20
use ONGR\ElasticsearchBundle\Service\Manager;
21
use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
22
use ONGR\ElasticsearchDSL\Query\FullText\MatchPhrasePrefixQuery;
23
use ONGR\ElasticsearchDSL\Query\FullText\MatchQuery;
24
use ONGR\ElasticsearchDSL\Query\MatchAllQuery;
25
use ONGR\ElasticsearchDSL\Query\TermLevel\IdsQuery;
26
use ONGR\ElasticsearchDSL\Query\TermLevel\RangeQuery;
27
use ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery;
28
use ONGR\ElasticsearchDSL\Sort\FieldSort;
29
use Sulu\Bundle\ArticleBundle\Admin\ArticleAdmin;
30
use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
31
use Sulu\Bundle\ArticleBundle\Document\Index\DocumentFactoryInterface;
32
use Sulu\Bundle\ArticleBundle\ListBuilder\ElasticSearchFieldDescriptor;
33
use Sulu\Bundle\ArticleBundle\Metadata\ArticleViewDocumentIdTrait;
34
use Sulu\Component\Content\Form\Exception\InvalidFormException;
35
use Sulu\Component\Content\Mapper\ContentMapperInterface;
36
use Sulu\Component\DocumentManager\DocumentManagerInterface;
37
use Sulu\Component\DocumentManager\MetadataFactoryInterface;
38
use Sulu\Component\Hash\RequestHashCheckerInterface;
39
use Sulu\Component\Rest\AbstractRestController;
40
use Sulu\Component\Rest\Exception\MissingParameterException;
41
use Sulu\Component\Rest\Exception\RestException;
42
use Sulu\Component\Rest\ListBuilder\FieldDescriptorInterface;
43
use Sulu\Component\Rest\ListBuilder\ListRepresentation;
44
use Sulu\Component\Rest\ListBuilder\ListRestHelperInterface;
45
use Sulu\Component\Rest\RequestParametersTrait;
46
use Sulu\Component\Security\Authorization\PermissionTypes;
47
use Sulu\Component\Security\Authorization\SecurityCheckerInterface;
48
use Sulu\Component\Security\Authorization\SecurityCondition;
49
use Sulu\Component\Security\SecuredControllerInterface;
50
use Symfony\Component\Form\FormFactoryInterface;
51
use Symfony\Component\HttpFoundation\Request;
52
use Symfony\Component\HttpFoundation\Response;
53
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
54
55
/**
56
 * Provides API for articles.
57
 */
58
class ArticleController extends AbstractRestController implements ClassResourceInterface, SecuredControllerInterface
59
{
60
    const DOCUMENT_TYPE = 'article';
61
62
    use RequestParametersTrait;
63
    use ArticleViewDocumentIdTrait;
64
65
    /**
66
     * @var DocumentManagerInterface
67
     */
68
    private $documentManager;
69
70
    /**
71
     * @var ContentMapperInterface
72
     */
73
    private $contentMapper;
74
75
    /**
76
     * @var MetadataFactoryInterface
77
     */
78
    private $metadataFactory;
79
80
    /**
81
     * @var ListRestHelperInterface
82
     */
83
    private $restHelper;
84
85
    /**
86
     * @var Manager
87
     */
88
    private $manager;
89
90
    /**
91
     * @var DocumentFactoryInterface
92
     */
93
    private $documentFactory;
94
95
    /**
96
     * @var FormFactoryInterface
97
     */
98 12
    private $formFactory;
99
100 12
    /**
101
     * @var RequestHashCheckerInterface
102 12
     */
103
    private $requestHashChecker;
104
105 12
    /**
106 12
     * @var SecurityCheckerInterface
107 12
     */
108
    private $securityChecker;
109 12
110 12
    /**
111
     * @var bool
112 12
     */
113 12
    private $displayTabAll;
114
115
    public function __construct(
116 12
        ViewHandlerInterface $viewHandler,
117 1
        DocumentManagerInterface $documentManager,
118 1
        ContentMapperInterface $contentMapper,
119
        MetadataFactoryInterface $metadataFactory,
120
        ListRestHelperInterface $restHelper,
121 12
        Manager $manager,
122 12
        DocumentFactoryInterface $documentFactory,
123
        FormFactoryInterface $formFactory,
124 2
        RequestHashCheckerInterface $requestHashChecker,
125
        SecurityCheckerInterface $securityChecker,
126
        bool $displayTabAll,
127 12
        ?TokenStorageInterface $tokenStorage = null
128 10
    ) {
129
        parent::__construct($viewHandler, $tokenStorage);
130
131 12
        $this->documentManager = $documentManager;
132 1
        $this->contentMapper = $contentMapper;
133 1
        $this->metadataFactory = $metadataFactory;
134 1
        $this->restHelper = $restHelper;
135 1
        $this->manager = $manager;
136 1
        $this->documentFactory = $documentFactory;
137
        $this->formFactory = $formFactory;
138
        $this->requestHashChecker = $requestHashChecker;
139 12
        $this->securityChecker = $securityChecker;
140 1
        $this->displayTabAll = $displayTabAll;
141
    }
142
143 12
    /**
144
     * Create field-descriptor array.
145
     *
146
     * @return ElasticSearchFieldDescriptor[]
147 12
     */
148
    protected function getFieldDescriptors()
149 12
    {
150 1
        return [
151 1
            'uuid' => ElasticSearchFieldDescriptor::create('id', 'public.id')
152
                ->setVisibility(FieldDescriptorInterface::VISIBILITY_NO)
153
                ->build(),
154
            'typeTranslation' => ElasticSearchFieldDescriptor::create('typeTranslation', 'sulu_article.list.type')
155 12
                ->setSortField('typeTranslation.raw')
156 12
                ->setVisibility(
157
                    $this->displayTabAll ?
158 12
                        FieldDescriptorInterface::VISIBILITY_YES :
159 12
                        FieldDescriptorInterface::VISIBILITY_NEVER
160 10
                )
161 1
                ->build(),
162
            'title' => ElasticSearchFieldDescriptor::create('title', 'public.title')
163 12
                ->setSortField('title.raw')
164
                ->build(),
165
            'creatorFullName' => ElasticSearchFieldDescriptor::create('creatorFullName', 'sulu_article.list.creator')
166
                ->setSortField('creatorFullName.raw')
167 12
                ->build(),
168 1
            'changerFullName' => ElasticSearchFieldDescriptor::create('changerFullName', 'sulu_article.list.changer')
169 1
                ->setSortField('changerFullName.raw')
170
                ->build(),
171
            'authorFullName' => ElasticSearchFieldDescriptor::create('authorFullName', 'sulu_article.author')
172 12
                ->setSortField('authorFullName.raw')
173 12
                ->build(),
174 12
            'created' => ElasticSearchFieldDescriptor::create('created', 'public.created')
175 12
                ->setSortField('authored')
176 12
                ->setType('datetime')
177 12
                ->setVisibility(FieldDescriptorInterface::VISIBILITY_NO)
178 12
                ->build(),
179 12
            'changed' => ElasticSearchFieldDescriptor::create('changed', 'public.changed')
180 12
                ->setSortField('authored')
181 12
                ->setType('datetime')
182
                ->setVisibility(FieldDescriptorInterface::VISIBILITY_NO)
183
                ->build(),
184
            'authored' => ElasticSearchFieldDescriptor::create('authored', 'sulu_article.authored')
185
                ->setSortField('authored')
186
                ->setType('datetime')
187
                ->build(),
188
            'localizationState' => ElasticSearchFieldDescriptor::create('localizationState')
189
                ->setVisibility(FieldDescriptorInterface::VISIBILITY_NO)
190
                ->build(),
191
            'published' => ElasticSearchFieldDescriptor::create('published')
192
                ->setVisibility(FieldDescriptorInterface::VISIBILITY_NO)
193
                ->build(),
194
            'publishedState' => ElasticSearchFieldDescriptor::create('publishedState')
195 9
                ->setVisibility(FieldDescriptorInterface::VISIBILITY_NO)
196
                ->build(),
197 9
            'routePath' => ElasticSearchFieldDescriptor::create('routePath')
198 9
                ->setVisibility(FieldDescriptorInterface::VISIBILITY_NO)
199 9
                ->build(),
200 9
        ];
201
    }
202 9
203
    /**
204
     * Returns list of articles.
205
     */
206
    public function cgetAction(Request $request): Response
207 9
    {
208 9
        $locale = $this->getRequestParameter($request, 'locale', true);
209 9
210 9
        $repository = $this->manager->getRepository($this->documentFactory->getClass('article'));
211 9
        $search = $repository->createSearch();
212
213
        $limit = (int) $this->restHelper->getLimit();
214
        $page = (int) $this->restHelper->getPage();
215
216
        if (null !== $locale) {
217
            $search->addQuery(new TermQuery('locale', $locale));
218
        }
219
220
        if (count($ids = array_filter(explode(',', $request->get('ids', ''))))) {
221
            $search->addQuery(new IdsQuery($this->getViewDocumentIds($ids, $locale)));
222
            $limit = count($ids);
223 51
        }
224
225 51
        $searchFields = $this->restHelper->getSearchFields();
226 51
        if (0 === count($searchFields)) {
227 51
            $searchFields = ['title'];
228 51
        }
229
230 51
        $searchPattern = $this->restHelper->getSearchPattern();
231 51
        if (!empty($searchPattern)) {
232 51
            $boolQuery = new BoolQuery();
233
            foreach ($searchFields as $searchField) {
234 51
                $boolQuery->add(new MatchPhrasePrefixQuery($searchField, $searchPattern), BoolQuery::SHOULD);
235 51
            }
236 51
            $search->addQuery($boolQuery);
237 51
        }
238 51
239
        if (null !== ($typeString = $request->get('types'))) {
240
            $types = explode(',', $typeString);
241
242
            if (count($types) > 1) {
243
                $query = new BoolQuery();
244
245
                foreach ($types as $type) {
246
                    $query->add(new TermQuery('type', $type));
247
                }
248
            } elseif ($types[0]) {
249
                $search->addQuery(new TermQuery('type', $types[0]));
250
            }
251 9
        }
252
253 9
        if ($contactId = $request->get('contactId')) {
254 9
            $boolQuery = new BoolQuery();
255 9
            $boolQuery->add(new MatchQuery('changer_contact_id', $contactId), BoolQuery::SHOULD);
256
            $boolQuery->add(new MatchQuery('creator_contact_id', $contactId), BoolQuery::SHOULD);
257 9
            $boolQuery->add(new MatchQuery('author_id', $contactId), BoolQuery::SHOULD);
258 9
            $search->addQuery($boolQuery);
259 9
        }
260
261 9
        if ($categoryId = $request->get('categoryId')) {
262
            $search->addQuery(new TermQuery('excerpt.categories.id', $categoryId), BoolQuery::MUST);
263
        }
264
265
        if ($tagId = $request->get('tagId')) {
266 9
            $search->addQuery(new TermQuery('excerpt.tags.id', $tagId), BoolQuery::MUST);
267
        }
268 9
269 9
        if ($pageId = $request->get('pageId')) {
270 9
            $search->addQuery(new TermQuery('parent_page_uuid', $pageId), BoolQuery::MUST);
271
        }
272 9
273 9
        if ($workflowStage = $request->get('workflowStage')) {
274 9
            $search->addQuery(new TermQuery('published_state', 'published' === $workflowStage), BoolQuery::MUST);
275 9
        }
276 9
277
        if ($this->getBooleanRequestParameter($request, 'exclude-shadows', false, false)) {
278
            $search->addQuery(new TermQuery('localization_state.state', 'shadow'), BoolQuery::MUST_NOT);
279
        }
280
281
        if ($this->getBooleanRequestParameter($request, 'exclude-ghosts', false, false)) {
282
            $search->addQuery(new TermQuery('localization_state.state', 'ghost'), BoolQuery::MUST_NOT);
283
        }
284
285
        $authoredFrom = $request->get('authoredFrom');
286
        $authoredTo = $request->get('authoredTo');
287
        if ($authoredFrom || $authoredTo) {
288 1
            $search->addQuery($this->getRangeQuery('authored', $authoredFrom, $authoredTo), BoolQuery::MUST);
289
        }
290 1
291
        if (null === $search->getQueries()) {
292 1
            $search->addQuery(new MatchAllQuery());
293 1
        }
294 1
295 1
        if (null !== $this->restHelper->getSortColumn() &&
296 1
            $sortField = $this->getSortFieldName($this->restHelper->getSortColumn())
297
        ) {
298
            $search->addSort(
299 1
                new FieldSort($sortField, $this->restHelper->getSortOrder())
300
            );
301
        }
302
303
        $fieldDescriptors = $this->getFieldDescriptors();
304
305
        if ($limit) {
306
            $search->setSize($limit);
307
            $search->setFrom(($page - 1) * $limit);
308
309 1
            $fields = array_merge(
310
                $this->restHelper->getFields() ?: [],
311 1
                ['id', 'localizationState', 'publishedState', 'published', 'title', 'routePath']
312 1
            );
313 1
            $fieldDescriptors = array_filter(
314 1
                $fieldDescriptors,
315
                function(FieldDescriptorInterface $fieldDescriptor) use ($fields) {
316 1
                    return in_array($fieldDescriptor->getName(), $fields);
317
                }
318
            );
319
        } else {
320
            $search->setSize(1000);
321
            $search->setScroll('1m');
322
        }
323
324
        $searchResult = $repository->findRaw($search);
325
        $result = [];
326
        foreach ($searchResult as $document) {
327
            $documentData = $this->normalize($document['_source'], $fieldDescriptors);
328
            if (false !== ($index = array_search($documentData['id'], $ids))) {
329 2
                $result[$index] = $documentData;
330
            } else {
331
                $result[] = $documentData;
332 2
            }
333 2
        }
334
335
        if (count($ids)) {
336 2
            ksort($result);
337 2
            $result = array_values($result);
338 2
        }
339
340
        $count = $searchResult->count();
341
342 2
        return $this->handleView(
343
            $this->view(
344
                new ListRepresentation(
345
                    $result,
346
                    'articles',
347
                    'get_articles',
348
                    $request->query->all(),
349 2
                    $page,
350
                    $limit,
351
                    $count
352
                )
353
            )
354 2
        );
355 1
    }
356 1
357
    /**
358 1
     * @param FieldDescriptorInterface[] $fieldDescriptors
359 1
     */
360 1
    private function normalize(array $document, array $fieldDescriptors)
361 1
    {
362 1
        $result = [];
363
        foreach ($fieldDescriptors as $fieldDescriptor) {
364
            $property = Caser::snake($fieldDescriptor->getName());
365
            if ('id' === $property) {
366 1
                $property = 'uuid';
367
            }
368 1
369 1
            $result[$fieldDescriptor->getName()] = array_key_exists($property, $document) ? $document[$property] : null;
370 1
        }
371
372
        return $result;
373
    }
374
375
    /**
376
     * Returns query to filter by given range.
377
     *
378 1
     * @param string $field
379 1
     * @param string $from
380 1
     * @param string $to
381 1
     *
382
     * @return RangeQuery
383 1
     */
384 1
    private function getRangeQuery($field, $from, $to)
385
    {
386
        return new RangeQuery($field, array_filter(['gte' => $from, 'lte' => $to]));
387
    }
388
389
    /**
390 2
     * Returns single article.
391 2
     *
392 2
     * @Get(defaults={"id" = ""})
393 2
     */
394 2
    public function getAction(Request $request, string $id): Response
395
    {
396
        $locale = $this->getRequestParameter($request, 'locale', true);
397
        $document = $this->documentManager->find(
398
            $id,
399
            $locale
400 2
        );
401
402
        $context = new Context();
403
        $context->setSerializeNull(true);
404
        $context->setGroups(['defaultPage', 'defaultArticle', 'smallArticlePage']);
405
406
        return $this->handleView(
407
            $this->view($document)->setContext($context)
408
        );
409 1
    }
410
411 1
    /**
412
     * Create article.
413 1
     */
414 1
    public function postAction(Request $request): Response
415 1
    {
416
        $action = $request->get('action');
417 1
        $document = $this->documentManager->create(self::DOCUMENT_TYPE);
418
        $locale = $this->getRequestParameter($request, 'locale', true);
419
        $data = $request->request->all();
420
421
        $this->persistDocument($data, $document, $locale);
422 52
        $this->handleActionParameter($action, $document, $locale);
423
        $this->documentManager->flush();
424 52
425
        $context = new Context();
426
        $context->setSerializeNull(true);
427
        $context->setGroups(['defaultPage', 'defaultArticle', 'smallArticlePage']);
428
429
        return $this->handleView(
430
            $this->view($document)->setContext($context)
431
        );
432
    }
433
434
    /**
435
     * Update articles.
436
     */
437 51
    public function putAction(Request $request, string $id): Response
438
    {
439 51
        $locale = $this->getRequestParameter($request, 'locale', true);
440 51
        $action = $request->get('action');
441 51
        $data = $request->request->all();
442
443
        $document = $this->documentManager->find(
444 51
            $id,
445
            $locale,
446
            [
447 51
                'load_ghost_content' => false,
448
                'load_shadow_content' => false,
449 51
            ]
450
        );
451
452
        $this->requestHashChecker->checkHash($request, $document, $document->getUuid());
453 51
454
        $this->persistDocument($data, $document, $locale);
455
        $this->handleActionParameter($action, $document, $locale);
456
        $this->documentManager->flush();
457 51
458 51
        $context = new Context();
459 51
        $context->setSerializeNull(true);
460
        $context->setGroups(['defaultPage', 'defaultArticle', 'smallArticlePage']);
461 51
462
        return $this->handleView(
463
            $this->view($document)->setContext($context)
464
        );
465 51
    }
466
467
    /**
468
     * Deletes multiple documents.
469
     */
470
    public function cdeleteAction(Request $request): Response
471
    {
472 51
        $ids = array_filter(explode(',', $request->get('ids', '')));
473
474 51
        $documentManager = $this->documentManager;
475
        foreach ($ids as $id) {
476
            $document = $documentManager->find($id);
477
            $documentManager->remove($document);
478
            $documentManager->flush();
479
        }
480 1
481
        return $this->handleView($this->view(null));
482 1
    }
483
484
    /**
485
     * Deletes multiple documents.
486
     */
487
    public function deleteAction(string $id): Response
488
    {
489
        $documentManager = $this->documentManager;
490
        $document = $documentManager->find($id);
491
        $documentManager->remove($document);
492 51
        $documentManager->flush();
493
494
        return $this->handleView($this->view(null));
495 51
    }
496 17
497 17
    /**
498
     * Trigger a action for given article specified over get-action parameter.
499 51
     *
500
     * @Post("/articles/{id}")
501
     */
502
    public function postTriggerAction(string $id, Request $request): Response
503
    {
504
        // extract parameter
505
        $action = $this->getRequestParameter($request, 'action', true);
506
        $locale = $this->getRequestParameter($request, 'locale', true);
507
508 1
        // prepare vars
509
        $view = null;
510 1
        $data = null;
511 1
        $userId = $this->getUser()->getId();
512 1
513 1
        try {
514
            switch ($action) {
515
                case 'unpublish':
516 1
                    $document = $this->documentManager->find($id, $locale);
517
                    $this->documentManager->unpublish($document, $locale);
518
                    $this->documentManager->flush();
519
520
                    $data = $this->documentManager->find($id, $locale);
521
522
                    break;
523
                case 'remove-draft':
524
                    $data = $this->documentManager->find($id, $locale);
525
                    $this->documentManager->removeDraft($data, $locale);
526
                    $this->documentManager->flush();
527
528
                    break;
529
                case 'copy-locale':
530
                    $destLocales = $this->getRequestParameter($request, 'dest', true);
531
                    $destLocales = explode(',', $destLocales);
532
533
                    foreach ($destLocales as $destLocale) {
534
                        $this->securityChecker->checkPermission(
535
                            new SecurityCondition($this->getSecurityContext(), $destLocale),
536
                            PermissionTypes::EDIT
537
                        );
538
                    }
539
540
                    $this->contentMapper->copyLanguage($id, $userId, null, $locale, $destLocales);
541
542
                    $data = $this->documentManager->find($id, $locale);
543
544
                    break;
545
                case 'copy':
546
                    /** @var ArticleDocument $document */
547
                    $document = $this->documentManager->find($id, $locale);
548
                    $copiedPath = $this->documentManager->copy($document, dirname($document->getPath()));
549
                    $this->documentManager->flush();
550
551
                    $data = $this->documentManager->find($copiedPath, $locale);
552
553
                    break;
554
                case 'order':
555
                    $this->orderPages($this->getRequestParameter($request, 'pages', true), $locale);
556
                    $this->documentManager->flush();
557
                    $this->documentManager->clear();
558
559
                    $data = $this->documentManager->find($id, $locale);
560
561
                    break;
562
                default:
563
                    throw new RestException('Unrecognized action: ' . $action);
564
            }
565
566
            // create context
567
            $context = new Context();
568
            $context->setSerializeNull(true);
569
            $context->setGroups(['defaultPage', 'defaultArticle', 'smallArticlePage']);
570
571
            // prepare view
572
            $view = $this->view($data);
573
            $view->setContext($context);
574
        } catch (RestException $exc) {
0 ignored issues
show
Bug introduced by
The class Sulu\Component\Rest\Exception\RestException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
575
            $view = $this->view($exc->toArray(), 400);
576
        }
577
578
        return $this->handleView($view);
579
    }
580
581
    /**
582
     * Ordering given pages.
583
     */
584
    private function orderPages(array $pages, string $locale): void
585
    {
586
        $documentManager = $this->documentManager;
587
588
        for ($i = 0; $i < count($pages); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
589
            $document = $documentManager->find($pages[$i], $locale);
590
            $documentManager->reorder($document, null);
591
        }
592
    }
593
594
    /**
595
     * {@inheritdoc}
596
     */
597
    public function getSecurityContext()
598
    {
599
        return ArticleAdmin::SECURITY_CONTEXT;
600
    }
601
602
    /**
603
     * Persists the document using the given Formation.
604
     *
605
     * @param object $document
606
     *
607
     * @throws InvalidFormException
608
     * @throws MissingParameterException
609
     */
610
    private function persistDocument(array $data, $document, string $locale): void
611
    {
612
        $formType = $this->metadataFactory->getMetadataForAlias('article')->getFormType();
613
        $form = $this->formFactory->create(
614
            $formType,
615
            $document,
616
            [
617
                // disable csrf protection, since we can't produce a token, because the form is cached on the client
618
                'csrf_protection' => false,
619
            ]
620
        );
621
        $form->submit($data, false);
622
623
        if (!$form->isValid()) {
624
            throw new InvalidFormException($form);
625
        }
626
627
        if (array_key_exists('author', $data) && null === $data['author']) {
628
            $document->setAuthor(null);
629
        }
630
631
        if (array_key_exists('additionalWebspaces', $data) && null === $data['additionalWebspaces']) {
632
            $document->setAdditionalWebspaces(null);
633
        }
634
635
        if (array_key_exists('customizeWebspaceSettings', $data) && false === $data['customizeWebspaceSettings']) {
636
            $document->setMainWebspace(null);
637
            $document->setAdditionalWebspaces(null);
638
        }
639
640
        $this->documentManager->persist(
641
            $document,
642
            $locale,
643
            [
644
                'user' => $this->getUser()->getId(),
645
                'clear_missing_content' => false,
646
            ]
647
        );
648
    }
649
650
    /**
651
     * Delegates actions by given actionParameter, which can be retrieved from the request.
652
     *
653
     * @param object $document
654
     */
655
    private function handleActionParameter(?string $actionParameter, $document, string $locale): void
656
    {
657
        switch ($actionParameter) {
658
            case 'publish':
659
                $this->documentManager->publish($document, $locale);
660
661
                break;
662
        }
663
    }
664
665
    private function getSortFieldName(string $sortBy): ?string
666
    {
667
        $sortBy = Caser::snake($sortBy);
668
        $fieldDescriptors = $this->getFieldDescriptors();
669
670
        if (array_key_exists($sortBy, $fieldDescriptors)) {
671
            return $fieldDescriptors[$sortBy]->getSortField();
672
        }
673
674
        return null;
675
    }
676
}
677