Completed
Push — feature/EVO-7278-created-by-pr... ( a1521a )
by
unknown
66:28
created

DocumentModel   F

Complexity

Total Complexity 77

Size/Duplication

Total Lines 620
Duplicated Lines 1.61 %

Coupling/Cohesion

Components 2
Dependencies 22

Importance

Changes 10
Bugs 2 Features 1
Metric Value
wmc 77
lcom 2
cbo 22
dl 10
loc 620
rs 1.6414
c 10
b 2
f 1

23 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A getRepository() 0 4 1
A setRepository() 0 7 1
D findAll() 0 81 13
C buildSearchQuery() 0 51 13
B hasCustomSearchIndex() 0 17 5
B buildSearchTextQuery() 0 13 5
A getMongoDBVersion() 0 11 2
B insertRecord() 0 17 5
B find() 0 27 3
B updateRecord() 0 24 5
A deleteRecord() 0 21 4
A flush() 0 4 1
A deleteById() 0 9 1
A recordExists() 0 4 1
A selectSingleFields() 0 14 1
A getEntityClass() 0 8 2
A getConnectionName() 0 6 1
A doRqlQuery() 0 6 1
A checkIfOriginRecord() 0 15 4
A getDefaultLimit() 0 8 2
A setFilterByAuthUser() 0 5 2
A getSecurityUserUsername() 10 10 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DocumentModel often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DocumentModel, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Use doctrine odm as backend
4
 */
5
6
namespace Graviton\RestBundle\Model;
7
8
use Doctrine\ODM\MongoDB\DocumentManager;
9
use Doctrine\ODM\MongoDB\DocumentRepository;
10
use Graviton\CoreBundle\Document\BaseDocument;
11
use Graviton\Rql\Node\SearchNode;
12
use Graviton\SchemaBundle\Model\SchemaModel;
13
use Graviton\SecurityBundle\Entities\SecurityUser;
14
use Symfony\Bridge\Monolog\Logger;
15
use Symfony\Component\HttpFoundation\Request;
16
use Doctrine\ODM\MongoDB\Query\Builder;
17
use Graviton\Rql\Visitor\MongoOdm as Visitor;
18
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
19
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
20
use Symfony\Component\Security\Core\User\UserInterface;
21
use Xiag\Rql\Parser\Node\LimitNode;
22
use Xiag\Rql\Parser\Node\Query\AbstractLogicOperatorNode;
23
use Xiag\Rql\Parser\Query;
24
use Graviton\ExceptionBundle\Exception\RecordOriginModifiedException;
25
use Xiag\Rql\Parser\Exception\SyntaxErrorException as RqlSyntaxErrorException;
26
use Graviton\SchemaBundle\Document\Schema as SchemaDocument;
27
use Xiag\Rql\Parser\Query as XiagQuery;
28
use \Doctrine\ODM\MongoDB\Query\Builder as MongoBuilder;
29
30
/**
31
 * Use doctrine odm as backend
32
 *
33
 * @author  List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
34
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
35
 * @link    http://swisscom.ch
36
 */
37
class DocumentModel extends SchemaModel implements ModelInterface
38
{
39
    /**
40
     * @var string
41
     */
42
    protected $description;
43
    /**
44
     * @var string[]
45
     */
46
    protected $fieldTitles;
47
    /**
48
     * @var string[]
49
     */
50
    protected $fieldDescriptions;
51
    /**
52
     * @var string[]
53
     */
54
    protected $requiredFields = array();
55
    /**
56
     * @var string[]
57
     */
58
    protected $searchableFields = array();
59
    /**
60
     * @var string[]
61
     */
62
    protected $textIndexes = array();
63
    /**
64
     * @var DocumentRepository
65
     */
66
    private $repository;
67
    /**
68
     * @var Visitor
69
     */
70
    private $visitor;
71
    /**
72
     * @var array
73
     */
74
    protected $notModifiableOriginRecords;
75
    /**
76
     * @var  integer
77
     */
78
    private $paginationDefaultLimit;
79
80
    /**
81
     * @var boolean
82
     */
83
    protected $filterByAuthUser;
84
85
    /**
86
     * @var string
87
     */
88
    protected $filterByAuthField;
89
90
    /**
91
     * @var DocumentManager
92
     */
93
    protected $manager;
94
95
    /**
96
     * @var TokenStorage
97
     */
98
    protected $tokenStorage;
99
100
    /**
101
     * @param Visitor      $visitor                    rql query visitor
102
     * @param TokenStorage $tokenStorage               Sf Security Token Storage
103
     * @param array        $notModifiableOriginRecords strings with not modifiable recordOrigin values
104
     * @param integer      $paginationDefaultLimit     amount of data records to be returned when in pagination context
105
     */
106
    public function __construct(
107
        Visitor $visitor,
108
        TokenStorage $tokenStorage,
109
        $notModifiableOriginRecords,
110
        $paginationDefaultLimit
111
    ) {
112
        parent::__construct();
113
        $this->visitor = $visitor;
114
        $this->tokenStorage = $tokenStorage;
115
        $this->notModifiableOriginRecords = $notModifiableOriginRecords;
116
        $this->paginationDefaultLimit = (int) $paginationDefaultLimit;
117
    }
118
119
    /**
120
     * get repository instance
121
     *
122
     * @return DocumentRepository
123
     */
124
    public function getRepository()
125
    {
126
        return $this->repository;
127
    }
128
129
    /**
130
     * create new app model
131
     *
132
     * @param DocumentRepository $repository Repository of countries
133
     *
134
     * @return \Graviton\RestBundle\Model\DocumentModel
135
     */
136
    public function setRepository(DocumentRepository $repository)
137
    {
138
        $this->repository = $repository;
139
        $this->manager = $repository->getDocumentManager();
140
141
        return $this;
142
    }
143
144
    /**
145
     * {@inheritDoc}
146
     *
147
     * @param Request      $request The request object
148
     * @param SecurityUser $user    SecurityUser Object
0 ignored issues
show
Documentation introduced by
Should the type for parameter $user not be null|SecurityUser?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
149
     *
150
     * @return array
151
     */
152
    public function findAll(Request $request, SecurityUser $user = null)
153
    {
154
        $pageNumber = $request->query->get('page', 1);
155
        $numberPerPage = (int) $request->query->get('perPage', $this->getDefaultLimit());
156
        $startAt = ($pageNumber - 1) * $numberPerPage;
157
158
        /** @var XiagQuery $xiagQuery */
159
        $xiagQuery = $request->attributes->get('rqlQuery');
160
161
        /** @var MongoBuilder $queryBuilder */
162
        $queryBuilder = $this->repository
163
            ->createQueryBuilder();
164
165
        // Setting RQL Query
166
        if ($xiagQuery) {
167
            // Clean up Search rql param and set it as Doctrine query
168
            if ($xiagQuery->getQuery() && $this->hasCustomSearchIndex() && (float) $this->getMongoDBVersion() >= 2.6) {
169
                $searchQueries = $this->buildSearchQuery($xiagQuery, $queryBuilder);
170
                $xiagQuery = $searchQueries['xiagQuery'];
171
                $queryBuilder = $searchQueries['queryBuilder'];
172
            }
173
            $queryBuilder = $this->doRqlQuery(
174
                $queryBuilder,
175
                $xiagQuery
176
            );
177
        } else {
178
            // @todo [lapistano]: seems the offset is missing for this query.
179
            /** @var \Doctrine\ODM\MongoDB\Query\Builder $qb */
180
            $queryBuilder->find($this->repository->getDocumentName());
181
        }
182
183
        /** @var LimitNode $rqlLimit */
184
        $rqlLimit = $xiagQuery instanceof XiagQuery ? $xiagQuery->getLimit() : false;
185
186
        // define offset and limit
187
        if (!$rqlLimit || !$rqlLimit->getOffset()) {
188
            $queryBuilder->skip($startAt);
0 ignored issues
show
Bug introduced by
The method skip does only exist in Doctrine\ODM\MongoDB\Query\Builder, but not in Doctrine\ODM\MongoDB\Query\Expr.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
189
        } else {
190
            $startAt = (int) $rqlLimit->getOffset();
191
            $queryBuilder->skip($startAt);
192
        }
193
194
        if (!$rqlLimit || is_null($rqlLimit->getLimit())) {
195
            $queryBuilder->limit($numberPerPage);
0 ignored issues
show
Bug introduced by
The method limit does only exist in Doctrine\ODM\MongoDB\Query\Builder, but not in Doctrine\ODM\MongoDB\Query\Expr.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
196
        } else {
197
            $numberPerPage = (int) $rqlLimit->getLimit();
198
            $queryBuilder->limit($numberPerPage);
199
        }
200
201
        // Limit can not be negative nor null.
202
        if ($numberPerPage < 1) {
203
            throw new RqlSyntaxErrorException('negative or null limit in rql');
204
        }
205
206
        /**
207
         * add a default sort on id if none was specified earlier
208
         *
209
         * not specifying something to sort on leads to very weird cases when fetching references.
210
         */
211
        if (!array_key_exists('sort', $queryBuilder->getQuery()->getQuery())) {
212
            $queryBuilder->sort('_id');
213
        }
214
215
        // run query
216
        $query = $queryBuilder->getQuery();
217
        $records = array_values($query->execute()->toArray());
218
219
        $totalCount = $query->count();
220
        $numPages = (int) ceil($totalCount / $numberPerPage);
221
        $page = (int) ceil($startAt / $numberPerPage) + 1;
222
        if ($numPages > 1) {
223
            $request->attributes->set('paging', true);
224
            $request->attributes->set('page', $page);
225
            $request->attributes->set('numPages', $numPages);
226
            $request->attributes->set('startAt', $startAt);
227
            $request->attributes->set('perPage', $numberPerPage);
228
            $request->attributes->set('totalCount', $totalCount);
229
        }
230
231
        return $records;
232
    }
233
234
    /**
235
     * @param XiagQuery    $xiagQuery    Xiag Builder
236
     * @param MongoBuilder $queryBuilder Mongo Doctrine query builder
237
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,Query|Builder>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
238
     */
239
    private function buildSearchQuery(XiagQuery $xiagQuery, MongoBuilder $queryBuilder)
240
    {
241
        $innerQuery = $xiagQuery->getQuery();
242
        $hasSearch = false;
243
        $nodes = [];
244
        if ($innerQuery instanceof AbstractLogicOperatorNode) {
245
            foreach ($innerQuery->getQueries() as $key => $innerRql) {
246
                if ($innerRql instanceof SearchNode) {
247
                    if (!$hasSearch) {
248
                        $queryBuilder = $this->buildSearchTextQuery($queryBuilder, $innerRql);
249
                        $hasSearch = true;
250
                    }
251
                } else {
252
                    $nodes[] = $innerRql;
253
                }
254
            }
255
        } elseif ($innerQuery instanceof SearchNode) {
256
            $queryBuilder = $this->repository->createQueryBuilder();
257
            $queryBuilder = $this->buildSearchTextQuery($queryBuilder, $innerQuery);
258
            $hasSearch = true;
259
        }
260
        // Remove the Search from RQL xiag
261
        if ($hasSearch && $nodes) {
262
            $newXiagQuery = new XiagQuery();
263
            if ($xiagQuery->getLimit()) {
264
                $newXiagQuery->setLimit($xiagQuery->getLimit());
265
            }
266
            if ($xiagQuery->getSelect()) {
267
                $newXiagQuery->setSelect($xiagQuery->getSelect());
268
            }
269
            if ($xiagQuery->getSort()) {
270
                $newXiagQuery->setSort($xiagQuery->getSort());
271
            }
272
            $binderClass = get_class($innerQuery);
273
            /** @var AbstractLogicOperatorNode $newBinder */
274
            $newBinder = new $binderClass();
275
            foreach ($nodes as $node) {
276
                $newBinder->addQuery($node);
277
            }
278
            $newXiagQuery->setQuery($newBinder);
279
            // Reset original query, so that there is no Search param
280
            $xiagQuery = $newXiagQuery;
281
        }
282
        if ($hasSearch) {
283
            $queryBuilder->sortMeta('score', 'textScore');
284
        }
285
        return [
286
            'xiagQuery'     => $xiagQuery,
287
            'queryBuilder'  => $queryBuilder
288
        ];
289
    }
290
291
    /**
292
     * Check if collection has search indexes in DB
293
     *
294
     * @param string $prefix the prefix for custom text search indexes
295
     * @return bool
296
     */
297
    private function hasCustomSearchIndex($prefix = 'search')
298
    {
299
        $metadata = $this->repository->getClassMetadata();
300
        $indexes = $metadata->getIndexes();
301
        if (count($indexes) < 1) {
302
            return false;
303
        }
304
        $collectionsName = substr($metadata->getName(), strrpos($metadata->getName(), '\\') + 1);
305
        $searchIndexName = $prefix.$collectionsName.'Index';
306
        // We reverse as normally the search index is the last.
307
        foreach (array_reverse($indexes) as $index) {
308
            if (array_key_exists('keys', $index) && array_key_exists($searchIndexName, $index['keys'])) {
309
                return true;
310
            }
311
        }
312
        return false;
313
    }
314
315
    /**
316
     * Build Search text index
317
     *
318
     * @param MongoBuilder $queryBuilder Doctrine mongo query builder object
319
     * @param SearchNode   $searchNode   Graviton Search node
320
     * @return MongoBuilder
321
     */
322
    private function buildSearchTextQuery(MongoBuilder $queryBuilder, SearchNode $searchNode)
323
    {
324
        $searchArr = [];
325
        foreach ($searchNode->getSearchTerms() as $string) {
326
            if (!empty(trim($string))) {
327
                $searchArr[] = (strpos($string, '.') !== false) ? "\"{$string}\"" : $string;
328
            }
329
        }
330
        if (!empty($searchArr)) {
331
            $queryBuilder->addAnd($queryBuilder->expr()->text(implode(' ', $searchArr)));
332
        }
333
        return $queryBuilder;
334
    }
335
336
    /**
337
     * @return string the version of the MongoDB as a string
338
     */
339
    private function getMongoDBVersion()
340
    {
341
        $buildInfo = $this->repository->getDocumentManager()->getDocumentDatabase(
342
            $this->repository->getClassName()
343
        )->command(['buildinfo'=>1]);
344
        if (isset($buildInfo['version'])) {
345
            return $buildInfo['version'];
346
        } else {
347
            return "unkown";
348
        }
349
    }
350
351
    /**
352
     * @param object $entity       entity to insert
353
     * @param bool   $returnEntity true to return entity
354
     * @param bool   $doFlush      if we should flush or not after insert
355
     *
356
     * @return Object|null
357
     */
358
    public function insertRecord($entity, $returnEntity = true, $doFlush = true)
359
    {
360
        if ($entity instanceof BaseDocument) {
361
            $entity->setCreatedAt(new \DateTime());
362
            if ($name = $this->getSecurityUserUsername()) {
363
                $entity->setCreatedBy($name);
364
            }
365
        }
366
        $this->manager->persist($entity);
367
368
        if ($doFlush) {
369
            $this->manager->flush($entity);
370
        }
371
        if ($returnEntity) {
372
            return $this->find($entity->getId());
373
        }
374
    }
375
376
    /**
377
     * @param string  $documentId id of entity to find
378
     * @param Request $request    request
0 ignored issues
show
Documentation introduced by
Should the type for parameter $request not be null|Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
379
     *
380
     * @return Object
381
     */
382
    public function find($documentId, Request $request = null)
383
    {
384
        if ($request instanceof Request) {
385
            // if we are provided a Request, we apply RQL
386
387
            /** @var MongoBuilder $queryBuilder */
388
            $queryBuilder = $this->repository
389
                ->createQueryBuilder();
390
391
            /** @var XiagQuery $query */
392
            $query = $request->attributes->get('rqlQuery');
393
394
            if ($query instanceof XiagQuery) {
395
                $queryBuilder = $this->doRqlQuery(
396
                    $queryBuilder,
397
                    $query
398
                );
399
            }
400
401
            $queryBuilder->field('id')->equals($documentId);
402
403
            $query = $queryBuilder->getQuery();
404
            return $query->getSingleResult();
405
        }
406
407
        return $this->repository->find($documentId);
408
    }
409
410
    /**
411
     * {@inheritDoc}
412
     *
413
     * @param string $documentId   id of entity to update
414
     * @param Object $entity       new entity
415
     * @param bool   $returnEntity true to return entity
416
     *
417
     * @return Object|null
418
     */
419
    public function updateRecord($documentId, $entity, $returnEntity = true)
420
    {
421
        if (!is_null($documentId)) {
422
            $this->deleteById($documentId);
423
            // detach so odm knows it's gone
424
            $this->manager->detach($entity);
425
            $this->manager->clear();
426
        }
427
428
        $entity = $this->manager->merge($entity);
429
430
        if ($entity instanceof BaseDocument) {
431
            $entity->setUpdatedAt(new \DateTime());
432
            if ($name = $this->getSecurityUserUsername()) {
433
                $entity->setUpdatedBy($name);
434
            }
435
        }
436
        $this->manager->persist($entity);
437
        $this->manager->flush($entity);
438
439
        if ($returnEntity) {
440
            return $entity;
441
        }
442
    }
443
444
    /**
445
     * {@inheritDoc}
446
     *
447
     * @param string|object $id id of entity to delete or entity instance
448
     *
449
     * @return null|Object
450
     */
451
    public function deleteRecord($id)
452
    {
453
        if (is_object($id)) {
454
            $entity = $id;
455
        } else {
456
            $entity = $this->find($id);
457
        }
458
459
        $this->checkIfOriginRecord($entity);
460
        $return = $entity;
461
462
        if (is_callable([$entity, 'getId']) && $entity->getId() != null) {
463
            $this->deleteById($entity->getId());
464
            // detach so odm knows it's gone
465
            $this->manager->detach($entity);
466
            $this->manager->clear();
467
            $return = null;
468
        }
469
470
        return $return;
471
    }
472
473
    /**
474
     * Triggers a flush on the DocumentManager
475
     *
476
     * @param null $document optional document
477
     *
478
     * @return void
479
     */
480
    public function flush($document = null)
481
    {
482
        $this->manager->flush($document);
483
    }
484
485
    /**
486
     * A low level delete without any checks
487
     *
488
     * @param mixed $id record id
489
     *
490
     * @return void
491
     */
492
    private function deleteById($id)
493
    {
494
        $builder = $this->repository->createQueryBuilder();
495
        $builder
496
            ->remove()
497
            ->field('id')->equals($id)
498
            ->getQuery()
499
            ->execute();
500
    }
501
502
    /**
503
     * Checks in a performant way if a certain record id exists in the database
504
     *
505
     * @param mixed $id record id
506
     *
507
     * @return bool true if it exists, false otherwise
508
     */
509
    public function recordExists($id)
0 ignored issues
show
Coding Style introduced by
function recordExists() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
510
    {
511
        return is_array($this->selectSingleFields($id, ['id'], false));
512
    }
513
514
    /**
515
     * Returns a set of fields from an existing resource in a performant manner.
516
     * If you need to check certain fields on an object (and don't need everything), this
517
     * is a better way to get what you need.
518
     * If the record is not present, you will receive null. If you don't need an hydrated
519
     * instance, make sure to pass false there.
520
     *
521
     * @param mixed $id      record id
522
     * @param array $fields  list of fields you need.
523
     * @param bool  $hydrate whether to hydrate object or not
524
     *
525
     * @return array|null|object
526
     */
527
    public function selectSingleFields($id, array $fields, $hydrate = true)
528
    {
529
        $builder = $this->repository->createQueryBuilder();
530
        $idField = $this->repository->getClassMetadata()->getIdentifier()[0];
531
532
        $record = $builder
533
            ->field($idField)->equals($id)
534
            ->select($fields)
535
            ->hydrate($hydrate)
536
            ->getQuery()
537
            ->getSingleResult();
538
539
        return $record;
540
    }
541
542
    /**
543
     * get classname of entity
544
     *
545
     * @return string|null
546
     */
547
    public function getEntityClass()
548
    {
549
        if ($this->repository instanceof DocumentRepository) {
550
            return $this->repository->getDocumentName();
551
        }
552
553
        return null;
554
    }
555
556
    /**
557
     * {@inheritDoc}
558
     *
559
     * Currently this is being used to build the route id used for redirecting
560
     * to newly made documents. It might benefit from having a different name
561
     * for those purposes.
562
     *
563
     * We might use a convention based mapping here:
564
     * Graviton\CoreBundle\Document\App -> mongodb://graviton_core
565
     * Graviton\CoreBundle\Entity\Table -> mysql://graviton_core
566
     *
567
     * @todo implement this in a more convention based manner
568
     *
569
     * @return string
570
     */
571
    public function getConnectionName()
572
    {
573
        $bundle = strtolower(substr(explode('\\', get_class($this))[1], 0, -6));
574
575
        return 'graviton.' . $bundle;
576
    }
577
578
    /**
579
     * Does the actual query using the RQL Bundle.
580
     *
581
     * @param Builder $queryBuilder Doctrine ODM QueryBuilder
582
     * @param Query   $query        query from parser
583
     *
584
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be Builder|\Doctrine\ODM\MongoDB\Query\Expr?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
585
     */
586
    protected function doRqlQuery($queryBuilder, Query $query)
587
    {
588
        $this->visitor->setBuilder($queryBuilder);
589
590
        return $this->visitor->visit($query);
591
    }
592
593
    /**
594
     * Checks the recordOrigin attribute of a record and will throw an exception if value is not allowed
595
     *
596
     * @param Object $record record
597
     *
598
     * @return void
599
     */
600
    protected function checkIfOriginRecord($record)
601
    {
602
        if ($record instanceof RecordOriginInterface
603
            && !$record->isRecordOriginModifiable()
604
        ) {
605
            $values = $this->notModifiableOriginRecords;
606
            $originValue = strtolower(trim($record->getRecordOrigin()));
607
608
            if (in_array($originValue, $values)) {
609
                $msg = sprintf("Must not be one of the following keywords: %s", implode(', ', $values));
610
611
                throw new RecordOriginModifiedException($msg);
612
            }
613
        }
614
    }
615
616
    /**
617
     * Determines the configured amount fo data records to be returned in pagination context.
618
     *
619
     * @return int
620
     */
621
    private function getDefaultLimit()
622
    {
623
        if (0 < $this->paginationDefaultLimit) {
624
            return $this->paginationDefaultLimit;
625
        }
626
627
        return 10;
628
    }
629
630
    /**
631
     * @param Boolean $active active
632
     * @param String  $field  field
633
     * @return void
634
     */
635
    public function setFilterByAuthUser($active, $field)
636
    {
637
        $this->filterByAuthUser = is_bool($active) ? $active : false;
638
        $this->filterByAuthField = $field;
639
    }
640
641
    /**
642
     * Security needs to be enabled to get Object.
643
     *
644
     * @return String|bool Username if available
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string|false.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
645
     */
646 View Code Duplication
    public function getSecurityUserUsername()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
647
    {
648
        /** @var PreAuthenticatedToken $token */
649
        if (($token = $this->tokenStorage->getToken())
650
            && ($user = $token->getUser()) instanceof UserInterface ) {
651
            /** @var SecurityUser $user */
652
            return $user->getUsername();
653
        }
654
        return false;
655
    }
656
}
657