Completed
Push — master ( 2077d1...b6c184 )
by Christopher
03:32
created

LaravelQuery::getRelatedResourceSet()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 11
cts 11
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 20
nc 1
nop 9
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace AlgoWeb\PODataLaravel\Query;
4
5
use POData\Providers\Metadata\ResourceProperty;
6
use POData\Providers\Metadata\ResourceSet;
7
use POData\UriProcessor\QueryProcessor\Expression\Parser\IExpressionProvider;
8
use POData\UriProcessor\QueryProcessor\ExpressionParser\FilterInfo;
9
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\KeyDescriptor;
10
use POData\Providers\Query\IQueryProvider;
11
use POData\Providers\Expression\MySQLExpressionProvider;
12
use POData\Providers\Query\QueryType;
13
use POData\Providers\Query\QueryResult;
14
use POData\Providers\Expression\PHPExpressionProvider;
15
use Illuminate\Support\Facades\DB;
16
17
class LaravelQuery implements IQueryProvider
18
{
19
    protected $expression;
20
    public $queryProviderClassName;
21
22 2
    public function __construct()
23
    {
24
        /* MySQLExpressionProvider();*/
25 2
        $this->expression = new LaravelExpressionProvider(); //PHPExpressionProvider('expression');
26 2
        $this->queryProviderClassName = get_class($this);
27 2
    }
28
29
    /**
30
     * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
31
     * If the query provider can not handle ordered paging, it must return the entire result set and POData will
32
     * perform the ordering and paging
33
     *
34
     * @return Boolean True if the query provider can handle ordered paging, false if POData should perform the paging
35
     */
36
    public function handlesOrderedPaging()
37
    {
38
        return true;
39
    }
40
41
    /**
42
     * Gets the expression provider used by to compile OData expressions into expression used by this query provider.
43
     *
44
     * @return \POData\Providers\Expression\IExpressionProvider
45
     */
46
    public function getExpressionProvider()
47
    {
48
        return $this->expression;
49
    }
50
51
    /**
52
     * Gets collection of entities belongs to an entity set
53
     * IE: http://host/EntitySet
54
     *  http://host/EntitySet?$skip=10&$top=5&filter=Prop gt Value
55
     *
56
     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
57
     * @param ResourceSet $resourceSet The entity set containing the entities to fetch
58
     * @param FilterInfo $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
59
     * @param mixed $orderBy sorted order if we want to get the data in some specific order
60
     * @param int $top number of records which  need to be skip
61
     * @param String $skipToken value indicating what records to skip
62
     *
63
     * @return QueryResult
64
     */
65 3
    public function getResourceSet(
66
        QueryType $queryType,
67
        ResourceSet $resourceSet,
68
        $filterInfo = null,
69
        $orderBy = null,
70
        $top = null,
71
        $skipToken = null,
72
        $sourceEntityInstance = null
73
    ) {
74 3
        if ($resourceSet == null && $sourceEntityInstance == null) {
75
            throw new \Exception('Must supply at least one of a resource set and source entity');
76
        }
77 3
        if ($sourceEntityInstance == null) {
78 1
            $sourceEntityInstance = $this->getSourceEntityInstance($resourceSet);
79 1
        }
80
81 3
        $result          = new QueryResult();
82 3
        $result->results = null;
83 3
        $result->count   = null;
84
85 3
        if (isset($orderBy) && null != $orderBy) {
86
            foreach ($orderBy->getOrderByInfo()->getOrderByPathSegments() as $order) {
87
                foreach ($order->getSubPathSegments() as $subOrder) {
88
                    $sourceEntityInstance = $sourceEntityInstance->orderBy(
89
                        $subOrder->getName(),
90
                        $order->isAscending() ? 'asc' : 'desc'
91
                    );
92
                }
93
            }
94
        }
95 3
        if (isset($skipToken)) {
96 1
            $sourceEntityInstance = $sourceEntityInstance->skip($skipToken);
97 1
        }
98 3
        if (isset($top)) {
99 1
            $sourceEntityInstance = $sourceEntityInstance->take($top);
100 1
        }
101
102 3
        $resultSet = $sourceEntityInstance->get();
103
104 3
        if (isset($filterInfo)) {
105
            $method = "return ".$filterInfo->getExpressionAsString().";";
106
            $clln = "$".$resourceSet->getResourceType()->getName();
107
            $isvalid = create_function($clln, $method);
0 ignored issues
show
Security Best Practice introduced by
The use of create_function is highly discouraged, better use a closure.

create_function can pose a great security vulnerability as it is similar to eval, and could be used for arbitrary code execution. We highly recommend to use a closure instead.

// Instead of
$function = create_function('$a, $b', 'return $a + $b');

// Better use
$function = function($a, $b) { return $a + $b; }
Loading history...
108
            $resultSet = $resultSet->filter($isvalid);
109
        }
110
111
112 3
        if (QueryType::ENTITIES() == $queryType || QueryType::ENTITIES_WITH_COUNT() == $queryType) {
113 1
            $result->results = array();
114 1
            foreach ($resultSet as $res) {
115 1
                $result->results[] = $res;
116 1
            }
117 1
        }
118 3
        if (QueryType::COUNT() == $queryType || QueryType::ENTITIES_WITH_COUNT() == $queryType) {
119 3
            if (is_array($resultSet)) {
120
                $resultSet = collect($resultSet);
121
            }
122 3
            $result->count = $resultSet->count();
123 3
        }
124 3
        return $result;
125
    }
126
    /**
127
     * Gets an entity instance from an entity set identified by a key
128
     * IE: http://host/EntitySet(1L)
129
     * http://host/EntitySet(KeyA=2L,KeyB='someValue')
130
     *
131
     * @param ResourceSet $resourceSet The entity set containing the entity to fetch
132
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
133
     *
134
     * @return object|null Returns entity instance if found else null
135
     */
136
    public function getResourceFromResourceSet(
137
        ResourceSet $resourceSet,
138
        KeyDescriptor $keyDescriptor = null
139
    ) {
140
        return $this->getResource($resourceSet, $keyDescriptor);
141
    }
142
143
    /**
144
     * Common method for getResourceFromRelatedResourceSet() and getResourceFromResourceSet()
145
     * @param ResourceSet|null $resourceSet
146
     * @param null|KeyDescriptor $keyDescriptor
147
     */
148
    protected function getResource(
149
        $resourceSet,
150
        $keyDescriptor,
151
        array $whereCondition = [],
152
        $sourceEntityInstance = null
153
    ) {
154
        if ($resourceSet == null && $sourceEntityInstance == null) {
155
            throw new \Exception('Must supply at least one of a resource set and source entity');
156
        }
157
        if ($sourceEntityInstance == null) {
158
            $entityClassName = $resourceSet->getResourceType()->getInstanceType()->name;
0 ignored issues
show
Bug introduced by
It seems like $resourceSet is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
159
            $sourceEntityInstance = new $entityClassName();
160
        }
161
        if ($keyDescriptor) {
162
            foreach ($keyDescriptor->getValidatedNamedValues() as $key => $value) {
163
                $sourceEntityInstance = $sourceEntityInstance->where($key, $value[0]);
164
            }
165
        }
166
        foreach ($whereCondition as $fieldName => $fieldValue) {
167
            $sourceEntityInstance = $sourceEntityInstance->where($fieldName, $fieldValue);
168
        }
169
        $sourceEntityInstance = $sourceEntityInstance->get();
170
        if (0 == $sourceEntityInstance->count()) {
171
            return null;
172
        }
173
        return $sourceEntityInstance->first();
174
    }
175
176
    /**
177
     * Get related resource set for a resource
178
     * IE: http://host/EntitySet(1L)/NavigationPropertyToCollection
179
     * http://host/EntitySet?$expand=NavigationPropertyToCollection
180
     *
181
     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
182
     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
183
     * @param object $sourceEntityInstance The source entity instance.
184
     * @param ResourceSet $targetResourceSet The resource set of containing the target of the navigation property
185
     * @param ResourceProperty $targetProperty The navigation property to retrieve
186
     * @param FilterInfo $filter represents the $filter parameter of the OData query.  NULL if no $filter specified
187
     * @param mixed $orderBy sorted order if we want to get the data in some specific order
188
     * @param int $top number of records which  need to be skip
189
     * @param String $skip value indicating what records to skip
190
     *
191
     * @return QueryResult
192
     *
193
     */
194 3
    public function getRelatedResourceSet(
195
        QueryType $queryType,
196
        ResourceSet $sourceResourceSet,
197
        $sourceEntityInstance,
198
        ResourceSet $targetResourceSet,
199
        ResourceProperty $targetProperty,
200
        $filter = null,
201
        $orderBy = null,
202
        $top = null,
203
        $skip = null
204
    ) {
205 3
        $propertyName = $targetProperty->getName();
206 3
        $results = $sourceEntityInstance->$propertyName();
207
208 3
        return $this->getResourceSet(
209 3
            $queryType,
210 3
            $sourceResourceSet,
211 3
            $filter,
212 3
            $orderBy,
213 3
            $top,
214 3
            $skip,
215
            $results
216 3
        );
217
218
    }
219
220
    /**
221
     * Gets a related entity instance from an entity set identified by a key
222
     * IE: http://host/EntitySet(1L)/NavigationPropertyToCollection(33)
223
     *
224
     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
225
     * @param object $sourceEntityInstance The source entity instance.
226
     * @param ResourceSet $targetResourceSet The entity set containing the entity to fetch
227
     * @param ResourceProperty $targetProperty The metadata of the target property.
228
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
229
     *
230
     * @return object|null Returns entity instance if found else null
231
     */
232
    public function getResourceFromRelatedResourceSet(
233
        ResourceSet $sourceResourceSet,
234
        $sourceEntityInstance,
235
        ResourceSet $targetResourceSet,
236
        ResourceProperty $targetProperty,
237
        KeyDescriptor $keyDescriptor
238
    ) {
239
        $propertyName = $targetProperty->getName();
240
        return $this->getResource(null, $keyDescriptor, [], $sourceEntityInstance->$propertyName);
241
    }
242
243
    /**
244
     * Get related resource for a resource
245
     * IE: http://host/EntitySet(1L)/NavigationPropertyToSingleEntity
246
     * http://host/EntitySet?$expand=NavigationPropertyToSingleEntity
247
     *
248
     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
249
     * @param object $sourceEntityInstance The source entity instance.
250
     * @param ResourceSet $targetResourceSet The entity set containing the entity pointed to by the navigation property
251
     * @param ResourceProperty $targetProperty The navigation property to fetch
252
     *
253
     * @return object|null The related resource if found else null
254
     */
255
    public function getRelatedResourceReference(
256
        ResourceSet $sourceResourceSet,
257
        $sourceEntityInstance,
258
        ResourceSet $targetResourceSet,
259
        ResourceProperty $targetProperty
260
    ) {
261
        $propertyName = $targetProperty->getName();
262
        return $sourceEntityInstance->$propertyName;
263
    }
264
265
    /**
266
     * @param ResourceSet $resourceSet
267
     * @return mixed
268
     */
269
    protected function getSourceEntityInstance(ResourceSet $resourceSet)
270
    {
271
        $entityClassName = $resourceSet->getResourceType()->getInstanceType()->name;
272
        $sourceEntityInstance = new $entityClassName();
273
        return $sourceEntityInstance = $sourceEntityInstance->newQuery();
0 ignored issues
show
Unused Code introduced by
$sourceEntityInstance is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
274
    }
275
    
276
    /**
277
     * Updates a resource 
278
     *
279
     * @param ResourceSet      $sourceResourceSet    The entity set containing the source entity
280
     * @param object           $sourceEntityInstance The source entity instance
281
     * @param KeyDescriptor    $keyDescriptor        The key identifying the entity to fetch
282
     * @param object           $data                 The New data for the entity instance.
283
     * @param bool             $shouldUpdate        Should undefined values be updated or reset to default
284
     *
285
     * @return object|null The new resource value if it is assignable or throw exception for null.
286
     */
287
    public function updateResource(ResourceSet $sourceResourceSet,$sourceEntityInstance, KeyDescriptor $keyDescriptor,$data, $shouldUpdate = false){
288
        throw new \POData\Common\NotImplementedException();
289
    }
290
    /**
291
     * Delete resource from a resource set.
292
     * @param ResourceSet|null $resourceSet
0 ignored issues
show
Documentation introduced by
There is no parameter named $resourceSet. Did you maybe mean $sourceResourceSet?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
293
     * @param object           $sourceEntityInstance
294
     *
295
     * return bool true if resources sucessfully deteled, otherwise false.
296
     */
297
    public function deleteResource(
298
        ResourceSet $sourceResourceSet,
299
        $sourceEntityInstance
300
    ){
301
        throw new \POData\Common\NotImplementedException();
302
    }
303
    /**
304
     * @param ResourceSet      $resourceSet   The entity set containing the entity to fetch
305
     * @param object           $sourceEntityInstance The source entity instance
306
     * @param object           $data                 The New data for the entity instance.
307
     * 
308
     * returns object|null returns the newly created model if sucessful or null if model creation failed.
309
     */
310
    public function createResourceforResourceSet(
311
        ResourceSet $resourceSet,
312
        $sourceEntityInstance,
313
        $data
314
    ){
315
        throw new \POData\Common\NotImplementedException();
316
    }
317
}
318