1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace POData\UriProcessor; |
4
|
|
|
|
5
|
|
|
use JMS\Serializer\SerializerBuilder; |
6
|
|
|
use POData\Common\Messages; |
7
|
|
|
use POData\Common\MimeTypes; |
8
|
|
|
use POData\Common\ODataConstants; |
9
|
|
|
use POData\Common\ODataException; |
10
|
|
|
use POData\Common\Url; |
11
|
|
|
use POData\Common\Version; |
12
|
|
|
use POData\ObjectModel\ODataEntry; |
13
|
|
|
use POData\OperationContext\IHTTPRequest; |
14
|
|
|
use POData\Providers\Metadata\ResourceProperty; |
15
|
|
|
use POData\Providers\Metadata\ResourceSetWrapper; |
16
|
|
|
use POData\Providers\Metadata\ResourceStreamInfo; |
17
|
|
|
use POData\Providers\Metadata\ResourceType; |
18
|
|
|
use POData\Providers\Query\QueryType; |
19
|
|
|
use POData\UriProcessor\Interfaces\IUriProcessor; |
20
|
|
|
use POData\UriProcessor\QueryProcessor\ExpandProjectionParser\RootProjectionNode; |
21
|
|
|
use POData\UriProcessor\QueryProcessor\ExpressionParser\FilterInfo; |
22
|
|
|
use POData\UriProcessor\QueryProcessor\OrderByParser\InternalOrderByInfo; |
23
|
|
|
use POData\UriProcessor\QueryProcessor\SkipTokenParser\InternalSkipTokenInfo; |
24
|
|
|
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\SegmentDescriptor; |
25
|
|
|
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\TargetKind; |
26
|
|
|
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\TargetSource; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Class RequestDescription. |
30
|
|
|
*/ |
31
|
|
|
class RequestDescription |
32
|
|
|
{ |
33
|
|
|
/** |
34
|
|
|
* Holds the value of HTTP 'DataServiceVersion' header in the request, |
35
|
|
|
* DataServiceVersion header value states the version of the |
36
|
|
|
* Open Data Protocol used by the client to generate the request. |
37
|
|
|
* Refer http://www.odata.org/developers/protocols/overview#ProtocolVersioning. |
38
|
|
|
* |
39
|
|
|
* @var Version |
40
|
|
|
*/ |
41
|
|
|
private $requestVersion = null; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Holds the value of HTTP 'MaxDataServiceVersion' header in the request, |
45
|
|
|
* MaxDataServiceVersion header value specifies the maximum version number |
46
|
|
|
* the client can accept in a response. |
47
|
|
|
* Refer http://www.odata.org/developers/protocols/overview#ProtocolVersioning. |
48
|
|
|
* |
49
|
|
|
* @var Version |
50
|
|
|
*/ |
51
|
|
|
private $requestMaxVersion = null; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* This is the value of 'DataServiceVersion' header to be output in the response. this header |
55
|
|
|
* value states the OData version the server used to generate the response. |
56
|
|
|
* While processing the query and result set this value will be keeps on |
57
|
|
|
* updating, after every update this is compared against the |
58
|
|
|
* 'MaxDataServiceVersion' header in the client request to see whether the |
59
|
|
|
* client can interpret the response or not. The client should use this |
60
|
|
|
* value to determine whether it can correctly interpret the response or not. |
61
|
|
|
* Refer http://www.odata.org/developers/protocols/overview#ProtocolVersioning. |
62
|
|
|
* |
63
|
|
|
* @var Version |
64
|
|
|
*/ |
65
|
|
|
private $requiredMinResponseVersion; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* The minimum client version requirement, This value keeps getting updated |
69
|
|
|
* during processing of query, this is compared against the |
70
|
|
|
* DataServiceVersion header in the client request and if the client request |
71
|
|
|
* is less than this value then we fail the request (e.g. $count request |
72
|
|
|
* was sent but client said it was Version 1.0). |
73
|
|
|
* |
74
|
|
|
* @var Version |
75
|
|
|
*/ |
76
|
|
|
private $requiredMinRequestVersion; |
77
|
|
|
|
78
|
|
|
/** @var Version */ |
79
|
|
|
private $maxServiceVersion; |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Collection of known data service versions. |
83
|
|
|
* |
84
|
|
|
* @var Version[] |
85
|
|
|
*/ |
86
|
|
|
private static $knownDataServiceVersions = null; |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @var Url |
90
|
|
|
*/ |
91
|
|
|
private $requestUrl; |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Collection of SegmentDescriptor containing information about |
95
|
|
|
* each segment in the resource path part of the request uri. |
96
|
|
|
* |
97
|
|
|
* @var SegmentDescriptor[] |
98
|
|
|
*/ |
99
|
|
|
private $segments; |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Holds reference to the last segment descriptor. |
103
|
|
|
* |
104
|
|
|
* @var SegmentDescriptor |
105
|
|
|
*/ |
106
|
|
|
private $lastSegment; |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* The name of the container for results. |
110
|
|
|
* |
111
|
|
|
* @var string|null |
112
|
|
|
*/ |
113
|
|
|
private $containerName; |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* The count option specified in the request. |
117
|
|
|
* |
118
|
|
|
* @var QueryType |
119
|
|
|
*/ |
120
|
|
|
public $queryType; |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Number of segments. |
124
|
|
|
* |
125
|
|
|
* @var int |
126
|
|
|
*/ |
127
|
|
|
private $segmentCount; |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Holds the value of $skip query option, if no $skip option |
131
|
|
|
* found then this parameter will be NULL. |
132
|
|
|
* |
133
|
|
|
* @var int|null |
134
|
|
|
*/ |
135
|
|
|
private $skipCount; |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Holds the value of take count, this value is depends on |
139
|
|
|
* presence of $top option and configured page size. |
140
|
|
|
* |
141
|
|
|
* @var int|null |
142
|
|
|
*/ |
143
|
|
|
private $topCount; |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Holds the value of $top query option, if no $top option |
147
|
|
|
* found then this parameter will be NULL. |
148
|
|
|
* |
149
|
|
|
* @var int|null |
150
|
|
|
*/ |
151
|
|
|
private $topOptionCount; |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Holds the parsed details for sorting, this will |
155
|
|
|
* be set in 3 cases |
156
|
|
|
* (1) if $orderby option is specified in the request uri |
157
|
|
|
* (2) if $skip or $top option is specified in the request uri |
158
|
|
|
* (3) if server side paging is enabled for the resource |
159
|
|
|
* targeted by the request uri. |
160
|
|
|
* |
161
|
|
|
* @var InternalOrderByInfo|null |
162
|
|
|
*/ |
163
|
|
|
private $internalOrderByInfo; |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Holds the parsed details for $skiptoken option, this will |
167
|
|
|
* be NULL if $skiptoken option is absent. |
168
|
|
|
* |
169
|
|
|
* @var InternalSkipTokenInfo|null |
170
|
|
|
*/ |
171
|
|
|
private $internalSkipTokenInfo; |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Holds the parsed details for $filter option, this will be NULL if $filter option is absent. |
175
|
|
|
* |
176
|
|
|
* @var FilterInfo|null |
177
|
|
|
*/ |
178
|
|
|
private $filterInfo; |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Holds reference to the root of the tree describing expand |
182
|
|
|
* and select information, this field will be NULL if no |
183
|
|
|
* $expand or $select specified in the request uri. |
184
|
|
|
* |
185
|
|
|
* @var RootProjectionNode|null |
186
|
|
|
*/ |
187
|
|
|
private $rootProjectionNode; |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Holds number of entities in the result set, if either $count or |
191
|
|
|
* $inlinecount=allpages is specified, otherwise NULL. |
192
|
|
|
* |
193
|
|
|
* |
194
|
|
|
* @var int|null |
195
|
|
|
*/ |
196
|
|
|
private $countValue; |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Data of request from request body. |
200
|
|
|
* |
201
|
|
|
* @var array|null |
202
|
|
|
*/ |
203
|
|
|
private $data; |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Flag indicating status of query execution. |
207
|
|
|
* |
208
|
|
|
* @var bool |
209
|
|
|
*/ |
210
|
|
|
private $isExecuted; |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Reference to Uri processor. |
214
|
|
|
* |
215
|
|
|
* @var IUriProcessor |
216
|
|
|
*/ |
217
|
|
|
private $uriProcessor; |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* @param SegmentDescriptor[] $segmentDescriptors Description of segments in the resource path |
221
|
|
|
* @param Url $requestUri |
222
|
|
|
* @param Version $serviceMaxVersion |
223
|
|
|
* @param string|null $requestVersion |
224
|
|
|
* @param string|null $maxRequestVersion |
225
|
|
|
* @param string|null $dataType |
226
|
|
|
* @param IHTTPRequest|null $payload |
227
|
|
|
*/ |
228
|
|
|
public function __construct( |
229
|
|
|
array $segmentDescriptors, |
230
|
|
|
Url $requestUri, |
231
|
|
|
Version $serviceMaxVersion, |
232
|
|
|
$requestVersion, |
233
|
|
|
$maxRequestVersion, |
234
|
|
|
$dataType = null, |
235
|
|
|
IHTTPRequest $payload = null |
236
|
|
|
) { |
237
|
|
|
$this->segments = $segmentDescriptors; |
238
|
|
|
$this->segmentCount = count($this->segments); |
239
|
|
|
$this->requestUrl = $requestUri; |
240
|
|
|
$this->lastSegment = $segmentDescriptors[$this->segmentCount - 1]; |
241
|
|
|
$this->queryType = QueryType::ENTITIES(); |
242
|
|
|
//we use this for validation checks down in validateVersions... |
243
|
|
|
//but maybe we should check that outside of this object... |
244
|
|
|
$this->maxServiceVersion = $serviceMaxVersion; |
245
|
|
|
|
246
|
|
|
//Per OData 1 & 2 spec we must return the smallest size |
247
|
|
|
//We start at 1.0 and move it up as features are requested |
248
|
|
|
$this->requiredMinResponseVersion = clone Version::v1(); |
249
|
|
|
$this->requiredMinRequestVersion = clone Version::v1(); |
250
|
|
|
|
251
|
|
|
//see http://www.odata.org/documentation/odata-v2-documentation/overview/#ProtocolVersioning |
252
|
|
|
//if requestVersion isn't there, use Service Max Version |
253
|
|
|
$this->requestVersion = null === $requestVersion |
254
|
|
|
? $serviceMaxVersion |
255
|
|
|
: self::parseVersionHeader($requestVersion, ODataConstants::ODATAVERSIONHEADER); |
256
|
|
|
|
257
|
|
|
//if max version isn't there, use the request version |
258
|
|
|
$this->requestMaxVersion = null === $maxRequestVersion |
259
|
|
|
? $this->requestVersion |
260
|
|
|
: self::parseVersionHeader($maxRequestVersion, ODataConstants::ODATAMAXVERSIONHEADER); |
261
|
|
|
|
262
|
|
|
//if it's OData v3..things change a bit |
263
|
|
|
if ($this->maxServiceVersion == Version::v3()) { |
264
|
|
|
if (null === $maxRequestVersion) { |
265
|
|
|
//if max request version isn't specified we use the service max version instead of the request version |
266
|
|
|
//thus we favour newer versions |
267
|
|
|
$this->requestMaxVersion = $this->maxServiceVersion; |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
//also we change min response version to be the max version, again favoring later things |
271
|
|
|
//note that if the request max version is specified, it is still respected |
272
|
|
|
$this->requiredMinResponseVersion = clone $this->requestMaxVersion; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
$this->containerName = null; |
276
|
|
|
$this->skipCount = null; |
277
|
|
|
$this->topCount = null; |
278
|
|
|
$this->topOptionCount = null; |
279
|
|
|
$this->internalOrderByInfo = null; |
280
|
|
|
$this->internalSkipTokenInfo = null; |
281
|
|
|
|
282
|
|
|
$this->filterInfo = null; |
283
|
|
|
$this->countValue = null; |
284
|
|
|
$this->isExecuted = false; |
285
|
|
|
$this->data = isset($payload) ? $payload->getAllInput() : null; |
286
|
|
|
|
287
|
|
|
// Define data from request body |
288
|
|
|
if (null !== $dataType) { |
289
|
|
|
$this->readData($dataType); |
290
|
|
|
} |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* Define request data from body. |
295
|
|
|
* |
296
|
|
|
* @param string $dataType |
297
|
|
|
*/ |
298
|
|
|
private function readData($dataType) |
299
|
|
|
{ |
300
|
|
|
$string = $this->data; |
301
|
|
|
if (MimeTypes::MIME_APPLICATION_ATOM === $dataType || MimeTypes::MIME_APPLICATION_XML === $dataType) { |
302
|
|
|
if (is_array($string) && 1 == count($string)) { |
303
|
|
|
$string = $string[0]; |
304
|
|
|
} |
305
|
|
|
if (0 == strlen(trim($string))) { |
306
|
|
|
return; |
307
|
|
|
} |
308
|
|
|
$ymlDir = dirname(dirname(dirname(__DIR__))) . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . |
309
|
|
|
'POData' . DIRECTORY_SEPARATOR . 'Writers' . DIRECTORY_SEPARATOR . 'YML'; |
310
|
|
|
$serialize = |
311
|
|
|
SerializerBuilder::create() |
312
|
|
|
->addMetadataDir($ymlDir) |
313
|
|
|
->build(); |
314
|
|
|
$objectType = strpos($this->requestUrl->getUrlAsString(), '$links') !== false |
315
|
|
|
? 'POData\ObjectModel\ODataURL' : 'POData\ObjectModel\ODataEntry'; |
316
|
|
|
$this->data = $serialize->deserialize($string, $objectType, 'xml'); |
317
|
|
|
$msg = null; |
318
|
|
|
assert($this->data instanceof $objectType); |
319
|
|
|
assert($this->data->isOk($msg), $msg); |
320
|
|
|
} elseif ($dataType === MimeTypes::MIME_APPLICATION_JSON) { |
321
|
|
|
$data = !is_array($string) ? json_decode($string, true) : $string; |
322
|
|
|
$this->data = $data; |
323
|
|
|
} |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Get request data from body. |
328
|
|
|
*/ |
329
|
|
|
public function getData() |
330
|
|
|
{ |
331
|
|
|
return $this->data; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Raise the minimum client version requirement for this request and |
336
|
|
|
* perform capability negotiation. |
337
|
|
|
* |
338
|
|
|
* @param int $major The major segment of the version |
339
|
|
|
* @param int $minor The minor segment of the version |
340
|
|
|
* |
341
|
|
|
* @throws ODataException If capability negotiation fails |
342
|
|
|
*/ |
343
|
|
|
public function raiseMinVersionRequirement($major, $minor) |
344
|
|
|
{ |
345
|
|
|
if ($this->requiredMinRequestVersion->raiseVersion($major, $minor)) { |
346
|
|
|
$this->validateVersions(); |
347
|
|
|
} |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Raise the response version for this request and perform capability negotiation. |
352
|
|
|
* |
353
|
|
|
* |
354
|
|
|
* @param int $major The major segment of the version |
355
|
|
|
* @param int $minor The minor segment of the version |
356
|
|
|
* |
357
|
|
|
* @throws ODataException If capability negotiation fails |
358
|
|
|
*/ |
359
|
|
|
public function raiseResponseVersion($major, $minor) |
360
|
|
|
{ |
361
|
|
|
if ($this->requiredMinResponseVersion->raiseVersion($major, $minor)) { |
362
|
|
|
$this->validateVersions(); |
363
|
|
|
} |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* Gets collection of segment descriptors containing information about |
368
|
|
|
* each segment in the resource path part of the request uri. |
369
|
|
|
* |
370
|
|
|
* @return SegmentDescriptor[] |
371
|
|
|
*/ |
372
|
|
|
public function getSegments() |
373
|
|
|
{ |
374
|
|
|
return $this->segments; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* Gets reference to the descriptor of last segment. |
379
|
|
|
* |
380
|
|
|
* @return SegmentDescriptor |
381
|
|
|
*/ |
382
|
|
|
public function getLastSegment() |
383
|
|
|
{ |
384
|
|
|
return $this->lastSegment; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* Gets kind of resource targeted by the resource path. |
389
|
|
|
* |
390
|
|
|
* @return TargetKind |
391
|
|
|
*/ |
392
|
|
|
public function getTargetKind() |
393
|
|
|
{ |
394
|
|
|
return $this->lastSegment->getTargetKind(); |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* Gets kind of 'source of data' targeted by the resource path. |
399
|
|
|
* |
400
|
|
|
* @return TargetSource |
401
|
|
|
*/ |
402
|
|
|
public function getTargetSource() |
403
|
|
|
{ |
404
|
|
|
return $this->lastSegment->getTargetSource(); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Gets reference to the ResourceSetWrapper instance targeted by |
409
|
|
|
* the resource path, ResourceSetWrapper will present in the |
410
|
|
|
* following cases: |
411
|
|
|
* if the last segment descriptor describes |
412
|
|
|
* (a) resource set |
413
|
|
|
* http://server/NW.svc/Customers |
414
|
|
|
* http://server/NW.svc/Customers('ALFKI') |
415
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Orders |
416
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Orders(123) |
417
|
|
|
* http://server/NW.svc/Customers('ALFKI')/$links/Orders |
418
|
|
|
* (b) resource set reference |
419
|
|
|
* http://server/NW.svc/Orders(123)/Customer |
420
|
|
|
* http://server/NW.svc/Orders(123)/$links/Customer |
421
|
|
|
* (c) $count |
422
|
|
|
* http://server/NW.svc/Customers/$count |
423
|
|
|
* ResourceSet wrapper will be absent (NULL) in the following cases: |
424
|
|
|
* if the last segment descriptor describes |
425
|
|
|
* (a) Primitive |
426
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Country |
427
|
|
|
* (b) $value on primitive type |
428
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Country/$value |
429
|
|
|
* (c) Complex |
430
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Address |
431
|
|
|
* (d) Bag |
432
|
|
|
* http://server/NW.svc/Employees(123)/Emails |
433
|
|
|
* (e) MLE |
434
|
|
|
* http://server/NW.svc/Employees(123)/$value |
435
|
|
|
* (f) Named Stream |
436
|
|
|
* http://server/NW.svc/Employees(123)/Thumbnail48_48 |
437
|
|
|
* (g) metadata |
438
|
|
|
* http://server/NW.svc/$metadata |
439
|
|
|
* (h) service directory |
440
|
|
|
* http://server/NW.svc |
441
|
|
|
* (i) $bath |
442
|
|
|
* http://server/NW.svc/$batch. |
443
|
|
|
* |
444
|
|
|
* @return ResourceSetWrapper|null |
445
|
|
|
*/ |
446
|
|
|
public function getTargetResourceSetWrapper() |
447
|
|
|
{ |
448
|
|
|
return $this->lastSegment->getTargetResourceSetWrapper(); |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
/** |
452
|
|
|
* Gets reference to the ResourceType instance targeted by |
453
|
|
|
* the resource path, ResourceType will present in the |
454
|
|
|
* following cases: |
455
|
|
|
* if the last segment descriptor describes |
456
|
|
|
* (a) resource set |
457
|
|
|
* http://server/NW.svc/Customers |
458
|
|
|
* http://server/NW.svc/Customers('ALFKI') |
459
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Orders |
460
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Orders(123) |
461
|
|
|
* http://server/NW.svc/Customers('ALFKI')/$links/Orders |
462
|
|
|
* (b) resource set reference |
463
|
|
|
* http://server/NW.svc/Orders(123)/Customer |
464
|
|
|
* http://server/NW.svc/Orders(123)/$links/Customer |
465
|
|
|
* (c) $count |
466
|
|
|
* http://server/NW.svc/Customers/$count |
467
|
|
|
* (d) Primitive |
468
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Country |
469
|
|
|
* (e) $value on primitive type |
470
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Country/$value |
471
|
|
|
* (f) Complex |
472
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Address |
473
|
|
|
* (g) Bag |
474
|
|
|
* http://server/NW.svc/Employees(123)/Emails |
475
|
|
|
* (h) MLE |
476
|
|
|
* http://server/NW.svc/Employees(123)/$value |
477
|
|
|
* (i) Named Stream |
478
|
|
|
* http://server/NW.svc/Employees(123)/Thumbnail48_48 |
479
|
|
|
* ResourceType will be absent (NULL) in the following cases: |
480
|
|
|
* if the last segment descriptor describes |
481
|
|
|
* (a) metadata |
482
|
|
|
* http://server/NW.svc/$metadata |
483
|
|
|
* (b) service directory |
484
|
|
|
* http://server/NW.svc |
485
|
|
|
* (c) $bath |
486
|
|
|
* http://server/NW.svc/$batch. |
487
|
|
|
* |
488
|
|
|
* @return ResourceType|null |
489
|
|
|
*/ |
490
|
|
|
public function getTargetResourceType() |
491
|
|
|
{ |
492
|
|
|
return $this->lastSegment->getTargetResourceType(); |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* Gets reference to the ResourceProperty instance targeted by |
497
|
|
|
* the resource path, ResourceProperty will present in the |
498
|
|
|
* following cases: |
499
|
|
|
* if the last segment descriptor describes |
500
|
|
|
* (a) resource set (after 1 level) |
501
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Orders |
502
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Orders(123) |
503
|
|
|
* http://server/NW.svc/Customers('ALFKI')/$links/Orders |
504
|
|
|
* (b) resource set reference |
505
|
|
|
* http://server/NW.svc/Orders(123)/Customer |
506
|
|
|
* http://server/NW.svc/Orders(123)/$links/Customer |
507
|
|
|
* (c) $count |
508
|
|
|
* http://server/NW.svc/Customers/$count |
509
|
|
|
* (d) Primitive |
510
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Country |
511
|
|
|
* (e) $value on primitive type |
512
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Country/$value |
513
|
|
|
* (f) Complex |
514
|
|
|
* http://server/NW.svc/Customers('ALFKI')/Address |
515
|
|
|
* (g) Bag |
516
|
|
|
* http://server/NW.svc/Employees(123)/Emails |
517
|
|
|
* (h) MLE |
518
|
|
|
* http://server/NW.svc/Employees(123)/$value. |
519
|
|
|
* |
520
|
|
|
* ResourceType will be absent (NULL) in the following cases: |
521
|
|
|
* if the last segment descriptor describes |
522
|
|
|
* (a) If last segment is the only segment pointing to |
523
|
|
|
* ResourceSet (single or multiple) |
524
|
|
|
* http://server/NW.svc/Customers |
525
|
|
|
* http://server/NW.svc/Customers('ALFKI') |
526
|
|
|
* (b) Named Stream |
527
|
|
|
* http://server/NW.svc/Employees(123)/Thumbnail48_48 |
528
|
|
|
* (c) metadata |
529
|
|
|
* http://server/NW.svc/$metadata |
530
|
|
|
* (d) service directory |
531
|
|
|
* http://server/NW.svc |
532
|
|
|
* (e) $bath |
533
|
|
|
* http://server/NW.svc/$batch |
534
|
|
|
* |
535
|
|
|
* @return ResourceProperty|null |
536
|
|
|
*/ |
537
|
|
|
public function getProjectedProperty() |
538
|
|
|
{ |
539
|
|
|
return $this->lastSegment->getProjectedProperty(); |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
/** |
543
|
|
|
* Gets the name of the container for results. |
544
|
|
|
* |
545
|
|
|
* @return string|null |
546
|
|
|
*/ |
547
|
|
|
public function getContainerName() |
548
|
|
|
{ |
549
|
|
|
return $this->containerName; |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
/** |
553
|
|
|
* Sets the name of the container for results. |
554
|
|
|
* |
555
|
|
|
* @param string $containerName The container name |
556
|
|
|
*/ |
557
|
|
|
public function setContainerName($containerName) |
558
|
|
|
{ |
559
|
|
|
$this->containerName = $containerName; |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
/** |
563
|
|
|
* Whether thr request targets a single result or not. |
564
|
|
|
* |
565
|
|
|
* @return bool |
566
|
|
|
*/ |
567
|
|
|
public function isSingleResult() |
568
|
|
|
{ |
569
|
|
|
return $this->lastSegment->isSingleResult(); |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
/** |
573
|
|
|
* Gets the identifier associated with the the resource path. |
574
|
|
|
* |
575
|
|
|
* @return string |
576
|
|
|
*/ |
577
|
|
|
public function getIdentifier() |
578
|
|
|
{ |
579
|
|
|
return $this->lastSegment->getIdentifier(); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
/** |
583
|
|
|
* Gets the request uri. |
584
|
|
|
* |
585
|
|
|
* @return Url |
586
|
|
|
*/ |
587
|
|
|
public function getRequestUrl() |
588
|
|
|
{ |
589
|
|
|
return $this->requestUrl; |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
/** |
593
|
|
|
* Gets the value of $skip query option. |
594
|
|
|
* |
595
|
|
|
* @return int|null The value of $skip query option, NULL if $skip is absent |
596
|
|
|
*/ |
597
|
|
|
public function getSkipCount() |
598
|
|
|
{ |
599
|
|
|
return $this->skipCount; |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
/** |
603
|
|
|
* Sets skip value. |
604
|
|
|
* |
605
|
|
|
* @param int $skipCount The value of $skip query option |
606
|
|
|
*/ |
607
|
|
|
public function setSkipCount($skipCount) |
608
|
|
|
{ |
609
|
|
|
$this->skipCount = $skipCount; |
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
/** |
613
|
|
|
* Gets the value of take count. |
614
|
|
|
* |
615
|
|
|
* @return int|null The value of take, NULL if no take to be applied |
616
|
|
|
*/ |
617
|
|
|
public function getTopCount() |
618
|
|
|
{ |
619
|
|
|
return $this->topCount; |
620
|
|
|
} |
621
|
|
|
|
622
|
|
|
/** |
623
|
|
|
* Sets the value of take count. |
624
|
|
|
* |
625
|
|
|
* @param int $topCount The value of take query option |
626
|
|
|
*/ |
627
|
|
|
public function setTopCount($topCount) |
628
|
|
|
{ |
629
|
|
|
$this->topCount = $topCount; |
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
/** |
633
|
|
|
* Gets the value of $top query option. |
634
|
|
|
* |
635
|
|
|
* @return int|null The value of $top query option, NULL if $top is absent |
636
|
|
|
*/ |
637
|
|
|
public function getTopOptionCount() |
638
|
|
|
{ |
639
|
|
|
return $this->topOptionCount; |
640
|
|
|
} |
641
|
|
|
|
642
|
|
|
/** |
643
|
|
|
* Sets top value. |
644
|
|
|
* |
645
|
|
|
* @param int $topOptionCount The value of $top query option |
646
|
|
|
*/ |
647
|
|
|
public function setTopOptionCount($topOptionCount) |
648
|
|
|
{ |
649
|
|
|
$this->topOptionCount = $topOptionCount; |
650
|
|
|
} |
651
|
|
|
|
652
|
|
|
/** |
653
|
|
|
* Gets sorting (orderby) information, this function return |
654
|
|
|
* sorting information in 3 cases: |
655
|
|
|
* (1) if $orderby option is specified in the request uri |
656
|
|
|
* (2) if $skip or $top option is specified in the request uri |
657
|
|
|
* (3) if server side paging is enabled for the resource targeted |
658
|
|
|
* by the request uri. |
659
|
|
|
* |
660
|
|
|
* @return InternalOrderByInfo|null |
661
|
|
|
*/ |
662
|
|
|
public function getInternalOrderByInfo() |
663
|
|
|
{ |
664
|
|
|
return $this->internalOrderByInfo; |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
/** |
668
|
|
|
* Sets sorting (orderby) information. |
669
|
|
|
* |
670
|
|
|
* @param InternalOrderByInfo &$internalOrderByInfo The sorting information |
671
|
|
|
*/ |
672
|
|
|
public function setInternalOrderByInfo(InternalOrderByInfo &$internalOrderByInfo) |
673
|
|
|
{ |
674
|
|
|
$this->internalOrderByInfo = $internalOrderByInfo; |
675
|
|
|
} |
676
|
|
|
|
677
|
|
|
/** |
678
|
|
|
* Gets the parsed details for $skiptoken option. |
679
|
|
|
* |
680
|
|
|
* @return InternalSkipTokenInfo|null Returns parsed details of $skiptoken option, NULL if $skiptoken is absent |
681
|
|
|
*/ |
682
|
|
|
public function getInternalSkipTokenInfo() |
683
|
|
|
{ |
684
|
|
|
return $this->internalSkipTokenInfo; |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
/** |
688
|
|
|
* Sets $skiptoken information. |
689
|
|
|
* |
690
|
|
|
* @param InternalSkipTokenInfo &$internalSkipTokenInfo The paging information |
691
|
|
|
*/ |
692
|
|
|
public function setInternalSkipTokenInfo( |
693
|
|
|
InternalSkipTokenInfo &$internalSkipTokenInfo |
694
|
|
|
) { |
695
|
|
|
$this->internalSkipTokenInfo = $internalSkipTokenInfo; |
696
|
|
|
} |
697
|
|
|
|
698
|
|
|
/** |
699
|
|
|
* @return FilterInfo|null Returns parsed details of $filter option, NULL if $filter is absent |
700
|
|
|
*/ |
701
|
|
|
public function getFilterInfo() |
702
|
|
|
{ |
703
|
|
|
return $this->filterInfo; |
704
|
|
|
} |
705
|
|
|
|
706
|
|
|
/** |
707
|
|
|
* @param FilterInfo $filterInfo The filter information |
708
|
|
|
*/ |
709
|
|
|
public function setFilterInfo(FilterInfo $filterInfo) |
710
|
|
|
{ |
711
|
|
|
$this->filterInfo = $filterInfo; |
712
|
|
|
} |
713
|
|
|
|
714
|
|
|
/** |
715
|
|
|
* Sets $expand and $select information. |
716
|
|
|
* |
717
|
|
|
* @param RootProjectionNode &$rootProjectionNode Root of the projection tree |
718
|
|
|
*/ |
719
|
|
|
public function setRootProjectionNode(RootProjectionNode &$rootProjectionNode) |
720
|
|
|
{ |
721
|
|
|
$this->rootProjectionNode = $rootProjectionNode; |
722
|
|
|
} |
723
|
|
|
|
724
|
|
|
/** |
725
|
|
|
* Gets the root of the tree describing expand and select options,. |
726
|
|
|
* |
727
|
|
|
* @return RootProjectionNode|null Returns parsed details of $expand |
728
|
|
|
* and $select options, NULL if |
729
|
|
|
* $both options are absent |
730
|
|
|
*/ |
731
|
|
|
public function getRootProjectionNode() |
732
|
|
|
{ |
733
|
|
|
return $this->rootProjectionNode; |
734
|
|
|
} |
735
|
|
|
|
736
|
|
|
/** |
737
|
|
|
* Gets the count of result set if $count or $inlinecount=allpages |
738
|
|
|
* has been applied otherwise NULL. |
739
|
|
|
* |
740
|
|
|
* @return int|null |
741
|
|
|
*/ |
742
|
|
|
public function getCountValue() |
743
|
|
|
{ |
744
|
|
|
return $this->countValue; |
745
|
|
|
} |
746
|
|
|
|
747
|
|
|
/** |
748
|
|
|
* Sets the count of result set. |
749
|
|
|
* |
750
|
|
|
* @param int $countValue The count value |
751
|
|
|
*/ |
752
|
|
|
public function setCountValue($countValue) |
753
|
|
|
{ |
754
|
|
|
$this->countValue = $countValue; |
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
/** |
758
|
|
|
* To set the flag indicating the execution status as true. |
759
|
|
|
*/ |
760
|
|
|
public function setExecuted() |
761
|
|
|
{ |
762
|
|
|
$this->isExecuted = true; |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
/** |
766
|
|
|
* To check whether to execute the query using IDSQP. |
767
|
|
|
* |
768
|
|
|
* @return bool True if query need to be executed, False otherwise |
769
|
|
|
*/ |
770
|
|
|
public function needExecution() |
|
|
|
|
771
|
|
|
{ |
772
|
|
|
return !$this->isExecuted |
773
|
|
|
&& ($this->lastSegment->getTargetKind() != TargetKind::METADATA()) |
774
|
|
|
&& ($this->lastSegment->getTargetKind() != TargetKind::SERVICE_DIRECTORY()); |
775
|
|
|
} |
776
|
|
|
|
777
|
|
|
/** |
778
|
|
|
* To check if the resource path is a request for link uri. |
779
|
|
|
* |
780
|
|
|
* @return bool True if request is for link uri else false |
781
|
|
|
*/ |
782
|
|
|
public function isLinkUri() |
783
|
|
|
{ |
784
|
|
|
return ($this->segmentCount > 2) |
785
|
|
|
&& ($this->segments[$this->segmentCount - 2]->getTargetKind() == TargetKind::LINK()); |
786
|
|
|
} |
787
|
|
|
|
788
|
|
|
/** |
789
|
|
|
* To check if the resource path is a request for media resource. |
790
|
|
|
* |
791
|
|
|
* @return bool True if request is for media resource else false |
792
|
|
|
*/ |
793
|
|
|
public function isMediaResource() |
794
|
|
|
{ |
795
|
|
|
return $this->lastSegment->getTargetKind() == TargetKind::MEDIA_RESOURCE(); |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
/** |
799
|
|
|
* To check if the resource path is a request for named stream. |
800
|
|
|
* |
801
|
|
|
* @return bool True if request is for named stream else false |
802
|
|
|
*/ |
803
|
|
|
public function isNamedStream() |
804
|
|
|
{ |
805
|
|
|
return $this->isMediaResource() && !($this->lastSegment->getIdentifier() === ODataConstants::URI_VALUE_SEGMENT); |
806
|
|
|
} |
807
|
|
|
|
808
|
|
|
/** |
809
|
|
|
* Get ResourceStreamInfo for the media link entry or named stream request. |
810
|
|
|
* |
811
|
|
|
* @return ResourceStreamInfo|null Instance of ResourceStreamInfo if the |
812
|
|
|
* current request targets named stream, NULL for MLE |
813
|
|
|
*/ |
814
|
|
|
public function getResourceStreamInfo() |
815
|
|
|
{ |
816
|
|
|
//assert($this->isMediaResource) |
|
|
|
|
817
|
|
|
if ($this->isNamedStream()) { |
818
|
|
|
return $this->getTargetResourceType() |
819
|
|
|
->tryResolveNamedStreamByName( |
820
|
|
|
$this->lastSegment->getIdentifier() |
821
|
|
|
); |
822
|
|
|
} |
823
|
|
|
return null; |
824
|
|
|
} |
825
|
|
|
|
826
|
|
|
/** |
827
|
|
|
* Gets the resource instance targeted by the request uri. |
828
|
|
|
* Note: This value will be populated after query execution only. |
829
|
|
|
* |
830
|
|
|
* @return mixed |
831
|
|
|
*/ |
832
|
|
|
public function getTargetResult() |
833
|
|
|
{ |
834
|
|
|
return $this->lastSegment->getResult(); |
835
|
|
|
} |
836
|
|
|
|
837
|
|
|
/** |
838
|
|
|
* Gets the OData version the server used to generate the response. |
839
|
|
|
* |
840
|
|
|
* @return Version |
841
|
|
|
*/ |
842
|
|
|
public function getResponseVersion() |
843
|
|
|
{ |
844
|
|
|
return $this->requiredMinResponseVersion; |
845
|
|
|
} |
846
|
|
|
|
847
|
|
|
/** |
848
|
|
|
* Checks whether etag headers are allowed for this request. |
849
|
|
|
* |
850
|
|
|
* @return bool True if ETag header (If-Match or If-NoneMatch) |
851
|
|
|
* is allowed for the request, False otherwise |
852
|
|
|
*/ |
853
|
|
|
public function isETagHeaderAllowed() |
854
|
|
|
{ |
855
|
|
|
return $this->lastSegment->isSingleResult() |
856
|
|
|
&& ($this->queryType != QueryType::COUNT()) |
857
|
|
|
&& !$this->isLinkUri() |
858
|
|
|
&& (null === $this->rootProjectionNode |
859
|
|
|
|| !($this->rootProjectionNode->isExpansionSpecified()) |
860
|
|
|
); |
861
|
|
|
} |
862
|
|
|
|
863
|
|
|
/** |
864
|
|
|
* Gets collection of known data service versions, currently 1.0, 2.0 and 3.0. |
865
|
|
|
* |
866
|
|
|
* @return Version[] |
867
|
|
|
*/ |
868
|
|
|
public static function getKnownDataServiceVersions() |
869
|
|
|
{ |
870
|
|
|
if (null === self::$knownDataServiceVersions) { |
871
|
|
|
self::$knownDataServiceVersions = [ |
872
|
|
|
new Version(1, 0), |
873
|
|
|
new Version(2, 0), |
874
|
|
|
new Version(3, 0), |
875
|
|
|
]; |
876
|
|
|
} |
877
|
|
|
|
878
|
|
|
return self::$knownDataServiceVersions; |
879
|
|
|
} |
880
|
|
|
|
881
|
|
|
/** |
882
|
|
|
* This function is used to perform following checking (validation) |
883
|
|
|
* for capability negotiation. |
884
|
|
|
* (1) Check client request's 'DataServiceVersion' header value is |
885
|
|
|
* less than or equal to the minimum version required to intercept |
886
|
|
|
* the response |
887
|
|
|
* (2) Check client request's 'MaxDataServiceVersion' header value is |
888
|
|
|
* less than or equal to the version of protocol required to generate |
889
|
|
|
* the response |
890
|
|
|
* (3) Check the configured maximum protocol version is less than or equal |
891
|
|
|
* to the version of protocol required to generate the response |
892
|
|
|
* In addition to these checking, this function is also responsible for |
893
|
|
|
* initializing the properties representing 'DataServiceVersion' and |
894
|
|
|
* 'MaxDataServiceVersion'. |
895
|
|
|
* |
896
|
|
|
* |
897
|
|
|
* @throws ODataException If any of the above 3 check fails |
898
|
|
|
*/ |
899
|
|
|
public function validateVersions() |
900
|
|
|
{ |
901
|
|
|
|
902
|
|
|
//If the request version is below the minimum version required by supplied request arguments..throw an exception |
903
|
|
|
if ($this->requestVersion->compare($this->requiredMinRequestVersion) < 0) { |
904
|
|
|
throw ODataException::createBadRequestError( |
905
|
|
|
Messages::requestVersionTooLow( |
906
|
|
|
$this->requestVersion->toString(), |
907
|
|
|
$this->requiredMinRequestVersion->toString() |
908
|
|
|
) |
909
|
|
|
); |
910
|
|
|
} |
911
|
|
|
|
912
|
|
|
//If the requested max version is below the version required to fulfill the response...throw an exception |
913
|
|
|
if ($this->requestMaxVersion->compare($this->requiredMinResponseVersion) < 0) { |
914
|
|
|
throw ODataException::createBadRequestError( |
915
|
|
|
Messages::requestVersionTooLow( |
916
|
|
|
$this->requestMaxVersion->toString(), |
917
|
|
|
$this->requiredMinResponseVersion->toString() |
918
|
|
|
) |
919
|
|
|
); |
920
|
|
|
} |
921
|
|
|
|
922
|
|
|
//If the max version supported by the service is below the version required to fulfill the response.. |
923
|
|
|
//throw an exception |
924
|
|
|
if ($this->maxServiceVersion->compare($this->requiredMinResponseVersion) < 0) { |
925
|
|
|
throw ODataException::createBadRequestError( |
926
|
|
|
Messages::requestVersionIsBiggerThanProtocolVersion( |
927
|
|
|
$this->requiredMinResponseVersion->toString(), |
928
|
|
|
$this->maxServiceVersion->toString() |
929
|
|
|
) |
930
|
|
|
); |
931
|
|
|
} |
932
|
|
|
} |
933
|
|
|
|
934
|
|
|
/** |
935
|
|
|
* Validates the given version in string format and returns the version as instance of Version. |
936
|
|
|
* |
937
|
|
|
* @param string $versionHeader The DataServiceVersion or MaxDataServiceVersion header value |
938
|
|
|
* @param string $headerName The name of the header |
939
|
|
|
* |
940
|
|
|
* @throws ODataException If the version is malformed or not supported |
941
|
|
|
* |
942
|
|
|
* @return Version |
943
|
|
|
*/ |
944
|
|
|
private static function parseVersionHeader($versionHeader, $headerName) |
945
|
|
|
{ |
946
|
|
|
$versionHeader = trim($versionHeader); |
|
|
|
|
947
|
|
|
$libNameIndex = strpos($versionHeader, ';'); |
948
|
|
|
if (false === $libNameIndex) { |
949
|
|
|
$libNameIndex = strlen($versionHeader); |
950
|
|
|
} |
951
|
|
|
|
952
|
|
|
$dotIndex = -1; |
953
|
|
|
$badVersionMsg = Messages::requestDescriptionInvalidVersionHeader( |
954
|
|
|
$versionHeader, |
955
|
|
|
$headerName |
956
|
|
|
); |
957
|
|
|
for ($i = 0; $i < $libNameIndex; ++$i) { |
958
|
|
|
if ($versionHeader[$i] == '.') { |
959
|
|
|
//Throw an exception if we find more than 1 dot |
960
|
|
|
if ($dotIndex != -1) { |
961
|
|
|
throw ODataException::createBadRequestError($badVersionMsg); |
962
|
|
|
} |
963
|
|
|
|
964
|
|
|
$dotIndex = $i; |
965
|
|
|
} elseif ($versionHeader[$i] < '0' || $versionHeader[$i] > '9') { |
966
|
|
|
throw ODataException::createBadRequestError($badVersionMsg); |
967
|
|
|
} |
968
|
|
|
} |
969
|
|
|
|
970
|
|
|
$major = intval(substr($versionHeader, 0, $dotIndex)); |
971
|
|
|
$minor = 0; |
972
|
|
|
|
973
|
|
|
//Apparently the . is optional |
974
|
|
|
if ($dotIndex != -1) { |
975
|
|
|
if ($dotIndex == 0) { |
976
|
|
|
//If it starts with a ., throw an exception |
977
|
|
|
throw ODataException::createBadRequestError($badVersionMsg); |
978
|
|
|
} |
979
|
|
|
$minor = intval(substr($versionHeader, $dotIndex + 1, $libNameIndex)); |
980
|
|
|
} |
981
|
|
|
|
982
|
|
|
$version = new Version($major, $minor); |
983
|
|
|
|
984
|
|
|
//TODO: move this somewhere... |
|
|
|
|
985
|
|
|
//$this->validateVersions(); |
|
|
|
|
986
|
|
|
$isSupportedVersion = false; |
987
|
|
|
foreach (self::getKnownDataServiceVersions() as $version1) { |
988
|
|
|
if ($version->compare($version1) == 0) { |
989
|
|
|
$isSupportedVersion = true; |
990
|
|
|
break; |
991
|
|
|
} |
992
|
|
|
} |
993
|
|
|
|
994
|
|
|
if (!$isSupportedVersion) { |
995
|
|
|
$availableVersions = null; |
996
|
|
|
foreach (self::getKnownDataServiceVersions() as $version1) { |
997
|
|
|
$availableVersions .= $version1->toString() . ', '; |
998
|
|
|
} |
999
|
|
|
|
1000
|
|
|
$availableVersions = rtrim($availableVersions, ', '); |
1001
|
|
|
throw ODataException::createBadRequestError( |
1002
|
|
|
Messages::requestDescriptionUnSupportedVersion( |
1003
|
|
|
$headerName, |
1004
|
|
|
$versionHeader, |
1005
|
|
|
$availableVersions |
1006
|
|
|
) |
1007
|
|
|
); |
1008
|
|
|
} |
1009
|
|
|
|
1010
|
|
|
return $version; |
1011
|
|
|
} |
1012
|
|
|
|
1013
|
|
|
/** |
1014
|
|
|
* Gets reference to the IUriProcessor instance. |
1015
|
|
|
* |
1016
|
|
|
* @return IUriProcessor |
1017
|
|
|
*/ |
1018
|
|
|
public function getUriProcessor() |
1019
|
|
|
{ |
1020
|
|
|
return $this->uriProcessor; |
1021
|
|
|
} |
1022
|
|
|
|
1023
|
|
|
/** |
1024
|
|
|
* Set reference to IUriProcessor instance. |
1025
|
|
|
* |
1026
|
|
|
* @param IUriProcessor $uriProcessor Reference to the UriProcessor |
1027
|
|
|
*/ |
1028
|
|
|
public function setUriProcessor(IUriProcessor $uriProcessor) |
1029
|
|
|
{ |
1030
|
|
|
$this->uriProcessor = $uriProcessor; |
1031
|
|
|
} |
1032
|
|
|
} |
1033
|
|
|
|
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.