Completed
Push — master ( 6276d0...802252 )
by Christopher
06:08
created

LaravelQuery   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 302
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 9

Test Coverage

Coverage 43.14%

Importance

Changes 0
Metric Value
wmc 37
lcom 0
cbo 9
dl 0
loc 302
ccs 44
cts 102
cp 0.4314
rs 8.6
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getResourceFromResourceSet() 0 6 1
A __construct() 0 7 1
A handlesOrderedPaging() 0 4 1
A getExpressionProvider() 0 4 1
C getResourceSet() 0 61 18
C getResource() 0 27 8
B getRelatedResourceSet() 0 25 1
A getResourceFromRelatedResourceSet() 0 10 1
A getRelatedResourceReference() 0 9 1
A getSourceEntityInstance() 0 6 1
A updateResource() 0 3 1
A deleteResource() 0 6 1
A createResourceforResourceSet() 0 7 1
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
        $table = DB::table('dummy');
26 2
        $this->expression = new LaravelExpressionProvider($table); //PHPExpressionProvider('expression');
0 ignored issues
show
Unused Code introduced by
The call to LaravelExpressionProvider::__construct() has too many arguments starting with $table.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
27 2
        $this->queryProviderClassName = get_class($this);
28 2
    }
29
30
    /**
31
     * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
32
     * If the query provider can not handle ordered paging, it must return the entire result set and POData will
33
     * perform the ordering and paging
34
     *
35
     * @return Boolean True if the query provider can handle ordered paging, false if POData should perform the paging
36
     */
37
    public function handlesOrderedPaging()
38
    {
39
        return true;
40
    }
41
42
    /**
43
     * Gets the expression provider used by to compile OData expressions into expression used by this query provider.
44
     *
45
     * @return \POData\Providers\Expression\IExpressionProvider
46
     */
47
    public function getExpressionProvider()
48
    {
49
        return $this->expression;
50
    }
51
52
    /**
53
     * Gets collection of entities belongs to an entity set
54
     * IE: http://host/EntitySet
55
     *  http://host/EntitySet?$skip=10&$top=5&filter=Prop gt Value
56
     *
57
     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
58
     * @param ResourceSet $resourceSet The entity set containing the entities to fetch
59
     * @param FilterInfo $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
60
     * @param mixed $orderBy sorted order if we want to get the data in some specific order
61
     * @param int $top number of records which  need to be skip
62
     * @param String $skipToken value indicating what records to skip
63
     *
64
     * @return QueryResult
65
     */
66 3
    public function getResourceSet(
67
        QueryType $queryType,
68
        ResourceSet $resourceSet,
69
        $filterInfo = null,
70
        $orderBy = null,
71
        $top = null,
72
        $skipToken = null,
73
        $sourceEntityInstance = null
74
    ) {
75 3
        if ($resourceSet == null && $sourceEntityInstance == null) {
76
            throw new \Exception('Must supply at least one of a resource set and source entity');
77
        }
78 3
        if ($sourceEntityInstance == null) {
79 1
            $sourceEntityInstance = $this->getSourceEntityInstance($resourceSet);
80 1
        }
81
82 3
        $result          = new QueryResult();
83 3
        $result->results = null;
84 3
        $result->count   = null;
85
86 3
        if (isset($orderBy) && null != $orderBy) {
87
            foreach ($orderBy->getOrderByInfo()->getOrderByPathSegments() as $order) {
88
                foreach ($order->getSubPathSegments() as $subOrder) {
89
                    $sourceEntityInstance = $sourceEntityInstance->orderBy(
90
                        $subOrder->getName(),
91
                        $order->isAscending() ? 'asc' : 'desc'
92
                    );
93
                }
94
            }
95
        }
96 3
        if (isset($skipToken)) {
97 1
            $sourceEntityInstance = $sourceEntityInstance->skip($skipToken);
98 1
        }
99 3
        if (isset($top)) {
100 1
            $sourceEntityInstance = $sourceEntityInstance->take($top);
101 1
        }
102
103 3
        $resultSet = $sourceEntityInstance->get();
104
105 3
        if (isset($filterInfo)) {
106
            $method = "return ".$filterInfo->getExpressionAsString().";";
107
            $clln = "$".$resourceSet->getResourceType()->getName();
108
            $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...
109
            $resultSet = $resultSet->filter($isvalid);
110
        }
111
112
113 3
        if (QueryType::ENTITIES() == $queryType || QueryType::ENTITIES_WITH_COUNT() == $queryType) {
114 1
            $result->results = array();
115 1
            foreach ($resultSet as $res) {
116 1
                $result->results[] = $res;
117 1
            }
118 1
        }
119 3
        if (QueryType::COUNT() == $queryType || QueryType::ENTITIES_WITH_COUNT() == $queryType) {
120 3
            if (is_array($resultSet)) {
121
                $resultSet = collect($resultSet);
122
            }
123 3
            $result->count = $resultSet->count();
124 3
        }
125 3
        return $result;
126
    }
127
    /**
128
     * Gets an entity instance from an entity set identified by a key
129
     * IE: http://host/EntitySet(1L)
130
     * http://host/EntitySet(KeyA=2L,KeyB='someValue')
131
     *
132
     * @param ResourceSet $resourceSet The entity set containing the entity to fetch
133
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
134
     *
135
     * @return object|null Returns entity instance if found else null
136
     */
137
    public function getResourceFromResourceSet(
138
        ResourceSet $resourceSet,
139
        KeyDescriptor $keyDescriptor = null
140
    ) {
141
        return $this->getResource($resourceSet, $keyDescriptor);
142
    }
143
144
    /**
145
     * Common method for getResourceFromRelatedResourceSet() and getResourceFromResourceSet()
146
     * @param ResourceSet|null $resourceSet
147
     * @param null|KeyDescriptor $keyDescriptor
148
     */
149
    protected function getResource(
150
        $resourceSet,
151
        $keyDescriptor,
152
        array $whereCondition = [],
153
        $sourceEntityInstance = null
154
    ) {
155
        if ($resourceSet == null && $sourceEntityInstance == null) {
156
            throw new \Exception('Must supply at least one of a resource set and source entity');
157
        }
158
        if ($sourceEntityInstance == null) {
159
            $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...
160
            $sourceEntityInstance = new $entityClassName();
161
        }
162
        if ($keyDescriptor) {
163
            foreach ($keyDescriptor->getValidatedNamedValues() as $key => $value) {
164
                $sourceEntityInstance = $sourceEntityInstance->where($key, $value[0]);
165
            }
166
        }
167
        foreach ($whereCondition as $fieldName => $fieldValue) {
168
            $sourceEntityInstance = $sourceEntityInstance->where($fieldName, $fieldValue);
169
        }
170
        $sourceEntityInstance = $sourceEntityInstance->get();
171
        if (0 == $sourceEntityInstance->count()) {
172
            return null;
173
        }
174
        return $sourceEntityInstance->first();
175
    }
176
177
    /**
178
     * Get related resource set for a resource
179
     * IE: http://host/EntitySet(1L)/NavigationPropertyToCollection
180
     * http://host/EntitySet?$expand=NavigationPropertyToCollection
181
     *
182
     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
183
     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
184
     * @param object $sourceEntityInstance The source entity instance.
185
     * @param ResourceSet $targetResourceSet The resource set of containing the target of the navigation property
186
     * @param ResourceProperty $targetProperty The navigation property to retrieve
187
     * @param FilterInfo $filter represents the $filter parameter of the OData query.  NULL if no $filter specified
188
     * @param mixed $orderBy sorted order if we want to get the data in some specific order
189
     * @param int $top number of records which  need to be skip
190
     * @param String $skip value indicating what records to skip
191
     *
192
     * @return QueryResult
193
     *
194
     */
195 3
    public function getRelatedResourceSet(
196
        QueryType $queryType,
197
        ResourceSet $sourceResourceSet,
198
        $sourceEntityInstance,
199
        ResourceSet $targetResourceSet,
200
        ResourceProperty $targetProperty,
201
        $filter = null,
202
        $orderBy = null,
203
        $top = null,
204
        $skip = null
205
    ) {
206 3
        $propertyName = $targetProperty->getName();
207 3
        $results = $sourceEntityInstance->$propertyName();
208
209 3
        return $this->getResourceSet(
210 3
            $queryType,
211 3
            $sourceResourceSet,
212 3
            $filter,
213 3
            $orderBy,
214 3
            $top,
215 3
            $skip,
216
            $results
217 3
        );
218
219
    }
220
221
    /**
222
     * Gets a related entity instance from an entity set identified by a key
223
     * IE: http://host/EntitySet(1L)/NavigationPropertyToCollection(33)
224
     *
225
     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
226
     * @param object $sourceEntityInstance The source entity instance.
227
     * @param ResourceSet $targetResourceSet The entity set containing the entity to fetch
228
     * @param ResourceProperty $targetProperty The metadata of the target property.
229
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
230
     *
231
     * @return object|null Returns entity instance if found else null
232
     */
233
    public function getResourceFromRelatedResourceSet(
234
        ResourceSet $sourceResourceSet,
235
        $sourceEntityInstance,
236
        ResourceSet $targetResourceSet,
237
        ResourceProperty $targetProperty,
238
        KeyDescriptor $keyDescriptor
239
    ) {
240
        $propertyName = $targetProperty->getName();
241
        return $this->getResource(null, $keyDescriptor, [], $sourceEntityInstance->$propertyName);
242
    }
243
244
    /**
245
     * Get related resource for a resource
246
     * IE: http://host/EntitySet(1L)/NavigationPropertyToSingleEntity
247
     * http://host/EntitySet?$expand=NavigationPropertyToSingleEntity
248
     *
249
     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
250
     * @param object $sourceEntityInstance The source entity instance.
251
     * @param ResourceSet $targetResourceSet The entity set containing the entity pointed to by the navigation property
252
     * @param ResourceProperty $targetProperty The navigation property to fetch
253
     *
254
     * @return object|null The related resource if found else null
255
     */
256
    public function getRelatedResourceReference(
257
        ResourceSet $sourceResourceSet,
258
        $sourceEntityInstance,
259
        ResourceSet $targetResourceSet,
260
        ResourceProperty $targetProperty
261
    ) {
262
        $propertyName = $targetProperty->getName();
263
        return $sourceEntityInstance->$propertyName;
264
    }
265
266
    /**
267
     * @param ResourceSet $resourceSet
268
     * @return mixed
269
     */
270
    protected function getSourceEntityInstance(ResourceSet $resourceSet)
271
    {
272
        $entityClassName = $resourceSet->getResourceType()->getInstanceType()->name;
273
        $sourceEntityInstance = new $entityClassName();
274
        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...
275
    }
276
    
277
    /**
278
     * Updates a resource 
279
     *
280
     * @param ResourceSet      $sourceResourceSet    The entity set containing the source entity
281
     * @param object           $sourceEntityInstance The source entity instance
282
     * @param KeyDescriptor    $keyDescriptor        The key identifying the entity to fetch
283
     * @param object           $data                 The New data for the entity instance.
284
     * @param bool             $shouldUpdate        Should undefined values be updated or reset to default
285
     *
286
     * @return object|null The new resource value if it is assignable or throw exception for null.
287
     */
288
    public function updateResource(ResourceSet $sourceResourceSet,$sourceEntityInstance, KeyDescriptor $keyDescriptor,$data, $shouldUpdate = false){
0 ignored issues
show
Unused Code introduced by
The parameter $sourceResourceSet is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $sourceEntityInstance is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $keyDescriptor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $shouldUpdate is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
289
        throw new \POData\Common\NotImplementedException();
290
    }
291
    /**
292
     * Delete resource from a resource set.
293
     * @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...
294
     * @param object           $sourceEntityInstance
295
     *
296
     * return bool true if resources sucessfully deteled, otherwise false.
297
     */
298
    public function deleteResource(
299
        ResourceSet $sourceResourceSet,
0 ignored issues
show
Unused Code introduced by
The parameter $sourceResourceSet is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
300
        $sourceEntityInstance
0 ignored issues
show
Unused Code introduced by
The parameter $sourceEntityInstance is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
301
    ){
302
        throw new \POData\Common\NotImplementedException();
303
    }
304
    /**
305
     * @param ResourceSet      $resourceSet   The entity set containing the entity to fetch
306
     * @param object           $sourceEntityInstance The source entity instance
307
     * @param object           $data                 The New data for the entity instance.
308
     * 
309
     * returns object|null returns the newly created model if sucessful or null if model creation failed.
310
     */
311
    public function createResourceforResourceSet(
312
        ResourceSet $resourceSet,
0 ignored issues
show
Unused Code introduced by
The parameter $resourceSet is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
313
        $sourceEntityInstance,
0 ignored issues
show
Unused Code introduced by
The parameter $sourceEntityInstance is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
314
        $data
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
315
    ){
316
        throw new \POData\Common\NotImplementedException();
317
    }
318
}
319