Completed
Push — master ( 2c86a7...690ed0 )
by
unknown
36:26 queued 28:50
created

getEntitiesAllowedQueryBuilder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 12
rs 9.4285
c 1
b 0
f 1
cc 1
eloc 4
nc 1
nop 2
1
<?php
2
3
namespace Victoire\Bundle\BusinessPageBundle\Helper;
4
5
use Doctrine\DBAL\Schema\View;
6
use Doctrine\ORM\EntityManager;
7
use Doctrine\ORM\QueryBuilder;
8
use Victoire\Bundle\BusinessEntityBundle\Converter\ParameterConverter;
9
use Victoire\Bundle\BusinessEntityBundle\Entity\BusinessEntity;
10
use Victoire\Bundle\BusinessEntityBundle\Entity\BusinessProperty;
11
use Victoire\Bundle\BusinessEntityBundle\Helper\BusinessEntityHelper;
12
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessTemplate;
13
use Victoire\Bundle\CoreBundle\Helper\UrlBuilder;
14
use Victoire\Bundle\QueryBundle\Helper\QueryHelper;
15
use Victoire\Bundle\ViewReferenceBundle\Connector\ViewReferenceRepository;
16
use Victoire\Bundle\ViewReferenceBundle\ViewReference\BusinessPageReference;
17
18
/**
19
 * The business entity page pattern helper
20
 * ref: victoire_business_page.business_page_helper.
21
 */
22
class BusinessPageHelper
23
{
24
    protected $queryHelper = null;
25
    protected $viewReferenceRepository = null;
26
    protected $businessEntityHelper = null;
27
    protected $parameterConverter = null;
28
    protected $urlBuilder = null;
29
30
    /**
31
     * @param QueryHelper             $queryHelper
32
     * @param ViewReferenceRepository $viewReferenceRepository
33
     * @param BusinessEntityHelper    $businessEntityHelper
34
     * @param ParameterConverter      $parameterConverter
35
     * @param UrlBuilder              $urlBuilder
36
     */
37 View Code Duplication
    public function __construct(QueryHelper $queryHelper, ViewReferenceRepository $viewReferenceRepository, BusinessEntityHelper $businessEntityHelper, ParameterConverter $parameterConverter, UrlBuilder $urlBuilder)
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...
38
    {
39
        $this->queryHelper = $queryHelper;
40
        $this->viewReferenceRepository = $viewReferenceRepository;
41
        $this->businessEntityHelper = $businessEntityHelper;
42
        $this->parameterConverter = $parameterConverter;
43
        $this->urlBuilder = $urlBuilder;
44
    }
45
46
    /**
47
     * Is the entity allowed for the business entity page.
48
     *
49
     * @param BusinessTemplate $businessTemplate
50
     * @param object|null      $entity
51
     * @param EntityManager    $em
52
     *
53
     * @throws \Exception
54
     *
55
     * @return bool
56
     */
57
    public function isEntityAllowed(BusinessTemplate $businessTemplate, $entity, EntityManager $em = null)
58
    {
59
        $allowed = true;
60
61
        //test that an entity is given
62
        if ($entity === null) {
63
            throw new \Exception('The entity is required.');
64
        }
65
66
        $queryHelper = $this->queryHelper;
67
68
        //the page id
69
        $entityId = $entity->getId();
70
71
        //the base of the query
72
        $baseQuery = $queryHelper->getQueryBuilder($businessTemplate, $em);
0 ignored issues
show
Bug introduced by
It seems like $em defined by parameter $em on line 57 can be null; however, Victoire\Bundle\QueryBun...lper::getQueryBuilder() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
73
74
        $baseQuery->andWhere('main_item.id = '.$entityId);
75
76
        //filter with the query of the page
77
        $items = $queryHelper->buildWithSubQuery($businessTemplate, $baseQuery, $em)
0 ignored issues
show
Bug introduced by
It seems like $em defined by parameter $em on line 57 can be null; however, Victoire\Bundle\QueryBun...er::buildWithSubQuery() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
78
            ->getQuery()->getResult();
79
80
        //only one page can be found because we filter on the
81
        if (count($items) > 1) {
82
            throw new \Exception('More than 1 item was found, there should not be more than 1 item with this query.');
83
        }
84
85
        if (count($items) === 0) {
86
            $allowed = false;
87
        }
88
89
        return $allowed;
90
    }
91
92
    /**
93
     * Get the list of entities allowed for the BusinessTemplate page.
94
     *
95
     * @param BusinessTemplate $businessTemplate
96
     * @param EntityManager    $em
97
     *
98
     * @return array
99
     */
100
    public function getEntitiesAllowed(BusinessTemplate $businessTemplate, EntityManager $em)
101
    {
102
        return $this->getEntitiesAllowedQueryBuilder($businessTemplate, $em)
103
            ->getQuery()
104
            ->getResult();
105
    }
106
107
    /**
108
     * Get the list of entities allowed for the BusinessTemplate page.
109
     *
110
     * @param BusinessTemplate $businessTemplate
111
     * @param EntityManager    $em
112
     *
113
     * @throws \Exception
114
     *
115
     * @return QueryBuilder
116
     */
117
    public function getEntitiesAllowedQueryBuilder(BusinessTemplate $businessTemplate, EntityManager $em)
118
    {
119
        //the base of the query
120
        $baseQuery = $this->queryHelper->getQueryBuilder($businessTemplate, $em);
121
122
        // add this fake condition to ensure that there is always a "where" clause.
123
        // In query mode, usage of "AND" will be always valid instead of "WHERE"
124
        $baseQuery->andWhere('1 = 1');
125
126
        //filter with the query of the page
127
        return $this->queryHelper->buildWithSubQuery($businessTemplate, $baseQuery, $em);
128
    }
129
130
    /**
131
     * Get the list of business properties usable for the url.
132
     *
133
     * @param BusinessEntity $businessEntity
134
     *
135
     * @return BusinessProperty[] The list of business properties
136
     */
137 View Code Duplication
    public function getBusinessProperties(BusinessEntity $businessEntity)
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...
138
    {
139
        //the business properties usable in a url
140
        $businessProperties = $businessEntity->getBusinessPropertiesByType('businessParameter');
141
142
        //the business properties usable in a url
143
        $seoBusinessProps = $businessEntity->getBusinessPropertiesByType('seoable');
144
145
        //the business properties are the identifier and the seoables properties
146
        $businessProperties = array_merge($businessProperties, $seoBusinessProps);
147
148
        return $businessProperties;
149
    }
150
151
    /**
152
     * Get the position of the identifier in the url of a business entity page pattern.
153
     *
154
     * @param BusinessTemplate $businessTemplate
155
     *
156
     * @return int The position
157
     */
158
    public function getIdentifierPositionInUrl(BusinessTemplate $businessTemplate)
159
    {
160
        $position = null;
161
162
        $url = $businessTemplate->getUrl();
0 ignored issues
show
Bug introduced by
The method getUrl() does not seem to exist on object<Victoire\Bundle\B...ntity\BusinessTemplate>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
163
164
        // split on the / character
165
        $keywords = preg_split("/\//", $url);
166
        // preg_match_all('/\{\%\s*([^\%\}]*)\s*\%\}|\{\{\s*([^\}\}]*)\s*\}\}/i', $url, $matches);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
167
168
        //the business property link to the page
169
        $businessEntityId = $businessTemplate->getBusinessEntityId();
170
171
        $businessEntity = $this->businessEntityHelper->findById($businessEntityId);
172
173
        //the business properties usable in a url
174
        $businessProperties = $businessEntity->getBusinessPropertiesByType('businessParameter');
175
176
        //we parse the words of the url
177
        foreach ($keywords as $index => $keyword) {
178
            foreach ($businessProperties as $businessProperty) {
179
                $entityProperty = $businessProperty->getEntityProperty();
180
                $searchWord = '{{item.'.$entityProperty.'}}';
181
182
                if ($searchWord === $keyword) {
183
                    //the array start at index 0 but we want the position to start at 1
184
                    $position = [
185
                        'position'         => $index + 1,
186
                        'businessProperty' => $businessProperty,
187
                    ];
188
                }
189
            }
190
        }
191
192
        return $position;
193
    }
194
195
    /**
196
     * Guess the best pattern to represent given reflectionClass.
197
     *
198
     * @param \ReflectionClass $refClass
199
     * @param int              $entityId
200
     * @param EntityManager    $em
201
     * @param string           $originalRefClassName When digging into parentClass, we do not have to forget originalClass to be able to get reference after all
202
     *
203
     * @throws \Exception
204
     *
205
     * @return View
206
     */
207
    public function guessBestPatternIdForEntity($refClass, $entityId, $em, $originalRefClassName = null)
208
    {
209
        $templateId = null;
210
        $refClassName = $em->getClassMetadata($refClass->name)->name;
211
212
        $viewReference = null;
213
        if (!$originalRefClassName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $originalRefClassName of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
214
            $originalRefClassName = $refClassName;
215
        }
216
217
        $businessEntity = $this->businessEntityHelper->findByEntityClassname($refClassName);
218
219
        if ($businessEntity) {
220
            $parameters = [
221
                'entityId'        => $entityId,
222
                'entityNamespace' => $originalRefClassName,
223
            ];
224
            $viewReference = $this->viewReferenceRepository->getOneReferenceByParameters($parameters);
225
        }
226
227
        if (!$viewReference) {
228
            $parentRefClass = $refClass->getParentClass();
229
            if ($parentRefClass) {
230
                $templateId = $this->guessBestPatternIdForEntity($parentRefClass, $entityId, $em, $originalRefClassName);
231
            } else {
232
                throw new \Exception(sprintf('Cannot find a BusinessTemplate that can display the requested BusinessEntity ("%s", "%s".)', $refClassName, $entityId));
233
            }
234
        } elseif ($viewReference instanceof BusinessPageReference) {
235
            $templateId = $viewReference->getTemplateId();
236
        }
237
238
        return $templateId;
239
    }
240
}
241