| Total Complexity | 101 |
| Total Lines | 1190 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
Complex classes like RequestDescription 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.
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 RequestDescription, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 32 | class RequestDescription |
||
| 33 | { |
||
| 34 | /** |
||
| 35 | * Holds the value of HTTP 'DataServiceVersion' header in the request, |
||
| 36 | * DataServiceVersion header value states the version of the |
||
| 37 | * Open Data Protocol used by the client to generate the request. |
||
| 38 | * Refer http://www.odata.org/developers/protocols/overview#ProtocolVersioning |
||
| 39 | * |
||
| 40 | * @var Version |
||
| 41 | */ |
||
| 42 | private $requestVersion = null; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * Holds the value of HTTP 'MaxDataServiceVersion' header in the request, |
||
| 46 | * MaxDataServiceVersion header value specifies the maximum version number |
||
| 47 | * the client can accept in a response. |
||
| 48 | * Refer http://www.odata.org/developers/protocols/overview#ProtocolVersioning |
||
| 49 | * |
||
| 50 | * @var Version |
||
| 51 | */ |
||
| 52 | private $requestMaxVersion = null; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * This is the value of 'DataServiceVersion' header to be output in the response. this header |
||
| 56 | * value states the OData version the server used to generate the response. |
||
| 57 | * While processing the query and result set this value will be keeps on |
||
| 58 | * updating, after every update this is compared against the |
||
| 59 | * 'MaxDataServiceVersion' header in the client request to see whether the |
||
| 60 | * client can interpret the response or not. The client should use this |
||
| 61 | * value to determine whether it can correctly interpret the response or not. |
||
| 62 | * Refer http://www.odata.org/developers/protocols/overview#ProtocolVersioning |
||
| 63 | * |
||
| 64 | * @var Version |
||
| 65 | */ |
||
| 66 | private $requiredMinResponseVersion; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * The minimum client version requirement, This value keeps getting updated |
||
| 70 | * during processing of query, this is compared against the |
||
| 71 | * DataServiceVersion header in the client request and if the client request |
||
| 72 | * is less than this value then we fail the request (e.g. $count request |
||
| 73 | * was sent but client said it was Version 1.0). |
||
| 74 | * |
||
| 75 | * @var Version |
||
| 76 | */ |
||
| 77 | private $requiredMinRequestVersion; |
||
| 78 | |||
| 79 | /** @var Version */ |
||
| 80 | private $maxServiceVersion; |
||
| 81 | |||
| 82 | /** |
||
| 83 | * Collection of known data service versions. |
||
| 84 | * |
||
| 85 | * @var Version[] |
||
| 86 | */ |
||
| 87 | private static $_knownDataServiceVersions = null; |
||
| 88 | |||
| 89 | /** |
||
| 90 | * |
||
| 91 | * @var Url |
||
| 92 | */ |
||
| 93 | private $requestUrl; |
||
| 94 | |||
| 95 | /** |
||
| 96 | * Collection of SegmentDescriptor containing information about |
||
| 97 | * each segment in the resource path part of the request uri. |
||
| 98 | * |
||
| 99 | * @var SegmentDescriptor[] |
||
| 100 | */ |
||
| 101 | private $segments; |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Holds reference to the last segment descriptor. |
||
| 105 | * |
||
| 106 | * @var SegmentDescriptor |
||
| 107 | */ |
||
| 108 | private $lastSegment; |
||
| 109 | |||
| 110 | /** |
||
| 111 | * The name of the container for results |
||
| 112 | * |
||
| 113 | * @var string|null |
||
| 114 | */ |
||
| 115 | private $_containerName; |
||
| 116 | |||
| 117 | |||
| 118 | /** |
||
| 119 | * The count option specified in the request. |
||
| 120 | * |
||
| 121 | * @var string |
||
| 122 | */ |
||
| 123 | public $queryType; |
||
| 124 | |||
| 125 | /** |
||
| 126 | * Number of segments. |
||
| 127 | * |
||
| 128 | * @var int |
||
| 129 | */ |
||
| 130 | private $_segmentCount; |
||
| 131 | |||
| 132 | /** |
||
| 133 | * Holds the value of $skip query option, if no $skip option |
||
| 134 | * found then this parameter will be NULL. |
||
| 135 | * |
||
| 136 | * @var int|null |
||
| 137 | */ |
||
| 138 | private $_skipCount; |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Holds the value of take count, this value is depends on |
||
| 142 | * presence of $top option and configured page size. |
||
| 143 | * |
||
| 144 | * @var int|null |
||
| 145 | */ |
||
| 146 | private $_topCount; |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Holds the value of $top query option, if no $top option |
||
| 150 | * found then this parameter will be NULL. |
||
| 151 | * |
||
| 152 | * @var int|null |
||
| 153 | */ |
||
| 154 | private $_topOptionCount; |
||
| 155 | |||
| 156 | /** |
||
| 157 | * Holds the parsed details for sorting, this will |
||
| 158 | * be set in 3 cases |
||
| 159 | * (1) if $orderby option is specified in the request uri |
||
| 160 | * (2) if $skip or $top option is specified in the request uri |
||
| 161 | * (3) if server side paging is enabled for the resource |
||
| 162 | * targeted by the request uri. |
||
| 163 | * |
||
| 164 | * @var InternalOrderByInfo|null |
||
| 165 | */ |
||
| 166 | private $internalOrderByInfo; |
||
| 167 | |||
| 168 | /** |
||
| 169 | * Holds the parsed details for $skiptoken option, this will |
||
| 170 | * be NULL if $skiptoken option is absent. |
||
| 171 | * |
||
| 172 | * @var InternalSkipTokenInfo|null |
||
| 173 | */ |
||
| 174 | private $_internalSkipTokenInfo; |
||
| 175 | |||
| 176 | /** |
||
| 177 | * Holds the parsed details for $filter option, this will be NULL if $filter option is absent. |
||
| 178 | * |
||
| 179 | * @var FilterInfo|null |
||
| 180 | */ |
||
| 181 | private $_filterInfo; |
||
| 182 | |||
| 183 | /** |
||
| 184 | * Holds reference to the root of the tree describing expand |
||
| 185 | * and select information, this field will be NULL if no |
||
| 186 | * $expand or $select specified in the request uri. |
||
| 187 | * |
||
| 188 | * @var RootProjectionNode|null |
||
| 189 | */ |
||
| 190 | private $_rootProjectionNode; |
||
| 191 | |||
| 192 | /** |
||
| 193 | * Holds number of entities in the result set, if either $count or |
||
| 194 | * $inlinecount=allpages is specified, otherwise NULL |
||
| 195 | * |
||
| 196 | * |
||
| 197 | * @var int|null |
||
| 198 | */ |
||
| 199 | private $_countValue; |
||
| 200 | |||
| 201 | /** |
||
| 202 | * Data of request from request body |
||
| 203 | * |
||
| 204 | * @var array |
||
| 205 | */ |
||
| 206 | private $_data; |
||
| 207 | |||
| 208 | /** |
||
| 209 | * Flag indicating status of query execution. |
||
| 210 | * |
||
| 211 | * @var boolean |
||
| 212 | */ |
||
| 213 | private $_isExecuted; |
||
| 214 | |||
| 215 | /** |
||
| 216 | * Reference to Uri processor. |
||
| 217 | * |
||
| 218 | * @var UriProcessor |
||
| 219 | */ |
||
| 220 | private $_uriProcessor; |
||
| 221 | |||
| 222 | |||
| 223 | /** |
||
| 224 | * Reference to the service |
||
| 225 | * @var IService |
||
| 226 | */ |
||
| 227 | private $_service; |
||
| 228 | |||
| 229 | /** |
||
| 230 | * The parts of a multipart request |
||
| 231 | * @var array |
||
| 232 | */ |
||
| 233 | private $_parts; |
||
| 234 | |||
| 235 | /** |
||
| 236 | * The content of the Content-ID header of a request part |
||
| 237 | * @var string |
||
| 238 | */ |
||
| 239 | private $_contentId; |
||
| 240 | |||
| 241 | /** |
||
| 242 | * The HTTP request method of a request part |
||
| 243 | * @var string |
||
| 244 | */ |
||
| 245 | private $_requestMethod; |
||
| 246 | |||
| 247 | /** |
||
| 248 | * @param SegmentDescriptor[] $segmentDescriptors Description of segments in the resource path. |
||
| 249 | * @param Url $requestUri |
||
| 250 | * @param Version $serviceMaxVersion |
||
| 251 | * @param null|string $requestVersion |
||
| 252 | * @param null|string $maxRequestVersion |
||
| 253 | * @param string $dataType |
||
| 254 | */ |
||
| 255 | public function __construct($segmentDescriptors, Url $requestUri, Version $serviceMaxVersion, $requestVersion, $maxRequestVersion, $dataType = null, IService $service = null, $contentId = null, $requestMethod = null) |
||
| 256 | { |
||
| 257 | $this->segments = $segmentDescriptors; |
||
| 258 | $this->_segmentCount = count($this->segments); |
||
| 259 | $this->requestUrl = $requestUri; |
||
| 260 | $this->lastSegment = $segmentDescriptors[$this->_segmentCount - 1]; |
||
| 261 | $this->queryType = QueryType::ENTITIES; |
||
| 262 | $this->_service = $service; |
||
| 263 | $this->_parts = array(); |
||
| 264 | |||
| 265 | //we use this for validation checks down in validateVersions...but maybe we should check that outside of this object... |
||
| 266 | $this->maxServiceVersion = $serviceMaxVersion; |
||
| 267 | |||
| 268 | //Per OData 1 & 2 spec we must return the smallest size |
||
| 269 | //We start at 1.0 and move it up as features are requested |
||
| 270 | $this->requiredMinResponseVersion = clone Version::v1(); |
||
| 271 | $this->requiredMinRequestVersion = clone Version::v1(); |
||
| 272 | |||
| 273 | |||
| 274 | //see http://www.odata.org/documentation/odata-v2-documentation/overview/#ProtocolVersioning |
||
| 275 | //if requestVersion isn't there, use Service Max Version |
||
| 276 | $this->requestVersion = is_null($requestVersion) ? $serviceMaxVersion : self::parseVersionHeader($requestVersion, ODataConstants::ODATAVERSIONHEADER); |
||
| 277 | |||
| 278 | //if max version isn't there, use the request version |
||
| 279 | $this->requestMaxVersion = is_null($maxRequestVersion) ? $this->requestVersion : self::parseVersionHeader($maxRequestVersion, ODataConstants::ODATAMAXVERSIONHEADER); |
||
| 280 | |||
| 281 | //if it's OData v3..things change a bit |
||
| 282 | if ($this->maxServiceVersion == Version::v3()) { |
||
| 283 | if (is_null($maxRequestVersion)) |
||
| 284 | { |
||
| 285 | //if max request version isn't specified we use the service max version instead of the request version |
||
| 286 | //thus we favour newer versions |
||
| 287 | $this->requestMaxVersion = $this->maxServiceVersion; |
||
| 288 | } |
||
| 289 | |||
| 290 | //also we change min response version to be the max version, again favoring later things |
||
| 291 | //note that if the request max version is specified, it is still respected |
||
| 292 | $this->requiredMinResponseVersion = clone $this->requestMaxVersion; |
||
| 293 | } |
||
| 294 | |||
| 295 | |||
| 296 | |||
| 297 | $this->_containerName = null; |
||
| 298 | $this->_skipCount = null; |
||
| 299 | $this->_topCount = null; |
||
| 300 | $this->_topOptionCount = null; |
||
| 301 | $this->internalOrderByInfo = null; |
||
| 302 | $this->_internalSkipTokenInfo = null; |
||
| 303 | |||
| 304 | $this->_filterInfo = null; |
||
| 305 | $this->_countValue = null; |
||
| 306 | $this->_isExecuted = false; |
||
| 307 | $this->_contentId = $contentId; |
||
| 308 | $this->_requestMethod = $requestMethod; |
||
| 309 | |||
| 310 | // Define data from request body |
||
| 311 | if ($dataType) { |
||
| 312 | $this->_readData($dataType); |
||
| 313 | } |
||
| 314 | } |
||
| 315 | |||
| 316 | public function getParts() { |
||
| 317 | return $this->_parts; |
||
| 318 | } |
||
| 319 | |||
| 320 | public function getContentID() { |
||
| 321 | return $this->_contentId; |
||
| 322 | } |
||
| 323 | |||
| 324 | public function getRequestMethod() { |
||
| 325 | return $this->_requestMethod; |
||
| 326 | } |
||
| 327 | |||
| 328 | const STATE_PART_START = 'STATE_PART_START'; |
||
| 329 | const STATE_HTTP_STATUS = 'STATE_HTTP_STATUS'; |
||
| 330 | const STATE_HEADERS = 'STATE_HEADERS'; |
||
| 331 | const STATE_BODY = 'STATE_BODY'; |
||
| 332 | |||
| 333 | private function _processData($string, $dataType) |
||
| 334 | { |
||
| 335 | if ($dataType === MimeTypes::MIME_APPLICATION_XML) { |
||
| 336 | $data = Xml2Array::createArray($string); |
||
|
|
|||
| 337 | if (!empty($data['a:entry']['a:content']['m:properties'])) { |
||
| 338 | $clearData = $data['a:entry']['a:content']['m:properties']; |
||
| 339 | if (is_array($clearData)) { |
||
| 340 | foreach ($clearData as $key => $value) { |
||
| 341 | $this->_data[substr($key, 2)] = $value['@value']; |
||
| 342 | } |
||
| 343 | } |
||
| 344 | } |
||
| 345 | } elseif ($dataType === MimeTypes::MIME_APPLICATION_JSON) { |
||
| 346 | $data = json_decode($string, true); |
||
| 347 | $this->_data = $data; |
||
| 348 | } elseif (explode(';', $dataType)[0] === MimeTypes::MIME_MULTIPART_MIXED) { |
||
| 349 | preg_match('/boundary=(.*)$/', $dataType, $matches); |
||
| 350 | $boundary = $matches[1]; |
||
| 351 | |||
| 352 | // split content by boundary and get rid of last -- element |
||
| 353 | $a_blocks = preg_split("/-+$boundary/", $string); |
||
| 354 | array_pop($a_blocks); |
||
| 355 | |||
| 356 | // loop data blocks |
||
| 357 | foreach ($a_blocks as $id => $block) |
||
| 358 | { |
||
| 359 | if (empty($block)) { |
||
| 360 | continue; |
||
| 361 | } |
||
| 362 | |||
| 363 | $requestMethod = null; |
||
| 364 | $requestUrl = null; |
||
| 365 | |||
| 366 | $reader_state = RequestDescription::STATE_PART_START; |
||
| 367 | $body = null; |
||
| 368 | $headers = []; |
||
| 369 | $part_headers = []; |
||
| 370 | |||
| 371 | foreach (explode("\n", $block) as $line) { |
||
| 372 | if (empty($line)) { |
||
| 373 | if ($reader_state == RequestDescription::STATE_PART_START) { |
||
| 374 | $reader_state = RequestDescription::STATE_HTTP_STATUS; |
||
| 375 | } else if ($reader_state == RequestDescription::STATE_HEADERS) { |
||
| 376 | $reader_state = RequestDescription::STATE_BODY; |
||
| 377 | $body = ''; |
||
| 378 | } |
||
| 379 | continue; |
||
| 380 | } |
||
| 381 | $m = array(); |
||
| 382 | if (in_array($reader_state, [RequestDescription::STATE_HTTP_STATUS, RequestDescription::STATE_HEADERS]) && preg_match('/(?<key>[^:]+):\s*(?<value>.*?)\s*$/', $line, $m)) { |
||
| 383 | if ($reader_state == RequestDescription::STATE_HTTP_STATUS) { |
||
| 384 | $headers[$m['key']] = $m['value']; |
||
| 385 | } else if ($reader_state == RequestDescription::STATE_HEADERS) { |
||
| 386 | $part_headers[$m['key']] = $m['value']; |
||
| 387 | } |
||
| 388 | } else if (preg_match('/^(GET|PUT|POST|PATCH|DELETE)\s+(.*?)(\s+HTTP\/\d\.\d)?\s*$/', $line, $m)) { |
||
| 389 | $requestMethod = trim($m[1]); |
||
| 390 | $requestUrl = new Url(trim($m[2]), false); |
||
| 391 | $reader_state = RequestDescription::STATE_HEADERS; |
||
| 392 | } else if ($reader_state = RequestDescription::STATE_BODY) { |
||
| 393 | $body .= $line."\n"; |
||
| 394 | } |
||
| 395 | } |
||
| 396 | |||
| 397 | $host = $this->_service->getHost(); |
||
| 398 | $absoluteServiceUri = $host->getAbsoluteServiceUri(); |
||
| 399 | |||
| 400 | $requestUriSegments = array_slice( |
||
| 401 | $requestUrl->getSegments(), |
||
| 402 | $absoluteServiceUri->getSegmentCount() |
||
| 403 | ); |
||
| 404 | |||
| 405 | $segments = SegmentParser::parseRequestUriSegments( |
||
| 406 | $requestUriSegments, |
||
| 407 | $this->_service->getProvidersWrapper(), |
||
| 408 | true |
||
| 409 | ); |
||
| 410 | |||
| 411 | $contentType = $part_headers['Content-Type'] ?? null; |
||
| 412 | |||
| 413 | // you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char |
||
| 414 | $request = new RequestDescription( |
||
| 415 | $segments, |
||
| 416 | $requestUrl, |
||
| 417 | $this->maxServiceVersion, |
||
| 418 | null, // $this->requestVersion, |
||
| 419 | null, // $this->requestMaxVersion, |
||
| 420 | $contentType, |
||
| 421 | null, |
||
| 422 | $headers['Content-ID'], |
||
| 423 | $requestMethod |
||
| 424 | ); |
||
| 425 | |||
| 426 | $request->_setBody($body, $contentType); |
||
| 427 | |||
| 428 | $this->_parts[] = $request; |
||
| 429 | } |
||
| 430 | } |
||
| 431 | } |
||
| 432 | |||
| 433 | /** |
||
| 434 | * Define request data from body |
||
| 435 | * @param string $dataType |
||
| 436 | */ |
||
| 437 | private function _readData($dataType) { |
||
| 438 | $this->_data = null; |
||
| 439 | $string = file_get_contents('php://input'); |
||
| 440 | $this->_processData($string, $dataType); |
||
| 441 | } |
||
| 442 | |||
| 443 | /** |
||
| 444 | * Get request data from body |
||
| 445 | */ |
||
| 446 | private function _setBody($string, $dataType) { |
||
| 447 | $this->_data = null; |
||
| 448 | $this->_processData($string, $dataType); |
||
| 449 | } |
||
| 450 | /** |
||
| 451 | * Get request data from body |
||
| 452 | */ |
||
| 453 | public function getData() { |
||
| 454 | return $this->_data; |
||
| 455 | } |
||
| 456 | |||
| 457 | /** |
||
| 458 | * Raise the minimum client version requirement for this request and |
||
| 459 | * perform capability negotiation. |
||
| 460 | * |
||
| 461 | * @param int $major The major segment of the version |
||
| 462 | * @param int $minor The minor segment of the version |
||
| 463 | * |
||
| 464 | * @throws ODataException If capability negotiation fails. |
||
| 465 | */ |
||
| 466 | public function raiseMinVersionRequirement($major, $minor) { |
||
| 467 | if ($this->requiredMinRequestVersion->raiseVersion($major, $minor)) |
||
| 468 | { |
||
| 469 | $this->validateVersions(); |
||
| 470 | } |
||
| 471 | } |
||
| 472 | |||
| 473 | /** |
||
| 474 | * Raise the response version for this request and perform capability negotiation. |
||
| 475 | * |
||
| 476 | * |
||
| 477 | * @param int $major The major segment of the version |
||
| 478 | * @param int $minor The minor segment of the version |
||
| 479 | * |
||
| 480 | * @throws ODataException If capability negotiation fails. |
||
| 481 | */ |
||
| 482 | public function raiseResponseVersion($major, $minor) { |
||
| 483 | if ($this->requiredMinResponseVersion->raiseVersion($major, $minor)) { |
||
| 484 | $this->validateVersions(); |
||
| 485 | } |
||
| 486 | |||
| 487 | } |
||
| 488 | |||
| 489 | /** |
||
| 490 | * Gets collection of segment descriptors containing information about |
||
| 491 | * each segment in the resource path part of the request uri. |
||
| 492 | * |
||
| 493 | * @return SegmentDescriptor[] |
||
| 494 | */ |
||
| 495 | public function getSegments() |
||
| 496 | { |
||
| 497 | return $this->segments; |
||
| 498 | } |
||
| 499 | |||
| 500 | /** |
||
| 501 | * Gets reference to the descriptor of last segment. |
||
| 502 | * |
||
| 503 | * @return SegmentDescriptor |
||
| 504 | */ |
||
| 505 | public function getLastSegment() |
||
| 506 | { |
||
| 507 | return $this->lastSegment; |
||
| 508 | } |
||
| 509 | |||
| 510 | /** |
||
| 511 | * Gets kind of resource targeted by the resource path. |
||
| 512 | * |
||
| 513 | * @return int |
||
| 514 | */ |
||
| 515 | public function getTargetKind() |
||
| 516 | { |
||
| 517 | return $this->lastSegment->getTargetKind(); |
||
| 518 | } |
||
| 519 | |||
| 520 | /** |
||
| 521 | * Gets kind of 'source of data' targeted by the resource path. |
||
| 522 | * |
||
| 523 | * @return int |
||
| 524 | */ |
||
| 525 | public function getTargetSource() |
||
| 526 | { |
||
| 527 | /* |
||
| 528 | if (!empty($this->_parts)) { |
||
| 529 | $results = array(); |
||
| 530 | foreach ($this->_parts as &$part) { |
||
| 531 | $results[] = $part->lastSegment->getTargetSource(); |
||
| 532 | } |
||
| 533 | return $results; |
||
| 534 | } |
||
| 535 | */ |
||
| 536 | return $this->lastSegment->getTargetSource(); |
||
| 537 | } |
||
| 538 | |||
| 539 | /** |
||
| 540 | * Gets reference to the ResourceSetWrapper instance targeted by |
||
| 541 | * the resource path, ResourceSetWrapper will present in the |
||
| 542 | * following cases: |
||
| 543 | * if the last segment descriptor describes |
||
| 544 | * (a) resource set |
||
| 545 | * http://server/NW.svc/Customers |
||
| 546 | * http://server/NW.svc/Customers('ALFKI') |
||
| 547 | * http://server/NW.svc/Customers('ALFKI')/Orders |
||
| 548 | * http://server/NW.svc/Customers('ALFKI')/Orders(123) |
||
| 549 | * http://server/NW.svc/Customers('ALFKI')/$links/Orders |
||
| 550 | * (b) resource set reference |
||
| 551 | * http://server/NW.svc/Orders(123)/Customer |
||
| 552 | * http://server/NW.svc/Orders(123)/$links/Customer |
||
| 553 | * (c) $count |
||
| 554 | * http://server/NW.svc/Customers/$count |
||
| 555 | * ResourceSet wrapper will be absent (NULL) in the following cases: |
||
| 556 | * if the last segment descriptor describes |
||
| 557 | * (a) Primitive |
||
| 558 | * http://server/NW.svc/Customers('ALFKI')/Country |
||
| 559 | * (b) $value on primitive type |
||
| 560 | * http://server/NW.svc/Customers('ALFKI')/Country/$value |
||
| 561 | * (c) Complex |
||
| 562 | * http://server/NW.svc/Customers('ALFKI')/Address |
||
| 563 | * (d) Bag |
||
| 564 | * http://server/NW.svc/Employees(123)/Emails |
||
| 565 | * (e) MLE |
||
| 566 | * http://server/NW.svc/Employees(123)/$value |
||
| 567 | * (f) Named Stream |
||
| 568 | * http://server/NW.svc/Employees(123)/Thumnail48_48 |
||
| 569 | * (g) metadata |
||
| 570 | * http://server/NW.svc/$metadata |
||
| 571 | * (h) service directory |
||
| 572 | * http://server/NW.svc |
||
| 573 | * (i) $bath |
||
| 574 | * http://server/NW.svc/$batch |
||
| 575 | * |
||
| 576 | * @return ResourceSetWrapper|null |
||
| 577 | */ |
||
| 578 | public function getTargetResourceSetWrapper() |
||
| 579 | { |
||
| 580 | return $this->lastSegment->getTargetResourceSetWrapper(); |
||
| 581 | } |
||
| 582 | |||
| 583 | /** |
||
| 584 | * Gets reference to the ResourceType instance targeted by |
||
| 585 | * the resource path, ResourceType will present in the |
||
| 586 | * following cases: |
||
| 587 | * if the last segment descriptor describes |
||
| 588 | * (a) resource set |
||
| 589 | * http://server/NW.svc/Customers |
||
| 590 | * http://server/NW.svc/Customers('ALFKI') |
||
| 591 | * http://server/NW.svc/Customers('ALFKI')/Orders |
||
| 592 | * http://server/NW.svc/Customers('ALFKI')/Orders(123) |
||
| 593 | * http://server/NW.svc/Customers('ALFKI')/$links/Orders |
||
| 594 | * (b) resource set reference |
||
| 595 | * http://server/NW.svc/Orders(123)/Customer |
||
| 596 | * http://server/NW.svc/Orders(123)/$links/Customer |
||
| 597 | * (c) $count |
||
| 598 | * http://server/NW.svc/Customers/$count |
||
| 599 | * (d) Primitive |
||
| 600 | * http://server/NW.svc/Customers('ALFKI')/Country |
||
| 601 | * (e) $value on primitive type |
||
| 602 | * http://server/NW.svc/Customers('ALFKI')/Country/$value |
||
| 603 | * (f) Complex |
||
| 604 | * http://server/NW.svc/Customers('ALFKI')/Address |
||
| 605 | * (g) Bag |
||
| 606 | * http://server/NW.svc/Employees(123)/Emails |
||
| 607 | * (h) MLE |
||
| 608 | * http://server/NW.svc/Employees(123)/$value |
||
| 609 | * (i) Named Stream |
||
| 610 | * http://server/NW.svc/Employees(123)/Thumnail48_48 |
||
| 611 | * ResourceType will be absent (NULL) in the following cases: |
||
| 612 | * if the last segment descriptor describes |
||
| 613 | * (a) metadata |
||
| 614 | * http://server/NW.svc/$metadata |
||
| 615 | * (b) service directory |
||
| 616 | * http://server/NW.svc |
||
| 617 | * (c) $bath |
||
| 618 | * http://server/NW.svc/$batch |
||
| 619 | * |
||
| 620 | * @return ResourceType|null |
||
| 621 | */ |
||
| 622 | public function getTargetResourceType() |
||
| 623 | { |
||
| 624 | return $this->lastSegment->getTargetResourceType(); |
||
| 625 | } |
||
| 626 | |||
| 627 | /** |
||
| 628 | * Gets reference to the ResourceProperty instance targeted by |
||
| 629 | * the resource path, ResourceProperty will present in the |
||
| 630 | * following cases: |
||
| 631 | * if the last segment descriptor describes |
||
| 632 | * (a) resource set (after 1 level) |
||
| 633 | * http://server/NW.svc/Customers('ALFKI')/Orders |
||
| 634 | * http://server/NW.svc/Customers('ALFKI')/Orders(123) |
||
| 635 | * http://server/NW.svc/Customers('ALFKI')/$links/Orders |
||
| 636 | * (b) resource set reference |
||
| 637 | * http://server/NW.svc/Orders(123)/Customer |
||
| 638 | * http://server/NW.svc/Orders(123)/$links/Customer |
||
| 639 | * (c) $count |
||
| 640 | * http://server/NW.svc/Customers/$count |
||
| 641 | * (d) Primitive |
||
| 642 | * http://server/NW.svc/Customers('ALFKI')/Country |
||
| 643 | * (e) $value on primitive type |
||
| 644 | * http://server/NW.svc/Customers('ALFKI')/Country/$value |
||
| 645 | * (f) Complex |
||
| 646 | * http://server/NW.svc/Customers('ALFKI')/Address |
||
| 647 | * (g) Bag |
||
| 648 | * http://server/NW.svc/Employees(123)/Emails |
||
| 649 | * (h) MLE |
||
| 650 | * http://server/NW.svc/Employees(123)/$value |
||
| 651 | * |
||
| 652 | * ResourceType will be absent (NULL) in the following cases: |
||
| 653 | * if the last segment descriptor describes |
||
| 654 | * (a) If last segment is the only segment pointing to |
||
| 655 | * ResourceSet (single or multiple) |
||
| 656 | * http://server/NW.svc/Customers |
||
| 657 | * http://server/NW.svc/Customers('ALFKI') |
||
| 658 | * (b) Named Stream |
||
| 659 | * http://server/NW.svc/Employees(123)/Thumnail48_48 |
||
| 660 | * (c) metadata |
||
| 661 | * http://server/NW.svc/$metadata |
||
| 662 | * (d) service directory |
||
| 663 | * http://server/NW.svc |
||
| 664 | * (e) $bath |
||
| 665 | * http://server/NW.svc/$batch |
||
| 666 | * |
||
| 667 | * @return ResourceProperty|null |
||
| 668 | */ |
||
| 669 | public function getProjectedProperty() |
||
| 670 | { |
||
| 671 | return $this->lastSegment->getProjectedProperty(); |
||
| 672 | } |
||
| 673 | |||
| 674 | /** |
||
| 675 | * Gets the name of the container for results. |
||
| 676 | * |
||
| 677 | * @return string|null |
||
| 678 | */ |
||
| 679 | public function getContainerName() |
||
| 680 | { |
||
| 681 | return $this->_containerName; |
||
| 682 | } |
||
| 683 | |||
| 684 | /** |
||
| 685 | * Sets the name of the container for results. |
||
| 686 | * |
||
| 687 | * @param string $containerName The container name. |
||
| 688 | * |
||
| 689 | * @return void |
||
| 690 | */ |
||
| 691 | public function setContainerName($containerName) |
||
| 692 | { |
||
| 693 | $this->_containerName = $containerName; |
||
| 694 | } |
||
| 695 | |||
| 696 | /** |
||
| 697 | * Whether thr request targets a single result or not. |
||
| 698 | * |
||
| 699 | * @return boolean |
||
| 700 | */ |
||
| 701 | public function isSingleResult() |
||
| 702 | { |
||
| 703 | return $this->lastSegment->isSingleResult(); |
||
| 704 | } |
||
| 705 | |||
| 706 | /** |
||
| 707 | * Gets the identifier associated with the the resource path. |
||
| 708 | * |
||
| 709 | * @return string |
||
| 710 | */ |
||
| 711 | public function getIdentifier() |
||
| 712 | { |
||
| 713 | return $this->lastSegment->getIdentifier(); |
||
| 714 | } |
||
| 715 | |||
| 716 | /** |
||
| 717 | * Gets the request uri. |
||
| 718 | * |
||
| 719 | * @return Url |
||
| 720 | */ |
||
| 721 | public function getRequestUrl() |
||
| 722 | { |
||
| 723 | return $this->requestUrl; |
||
| 724 | } |
||
| 725 | |||
| 726 | /** |
||
| 727 | * Gets the value of $skip query option |
||
| 728 | * |
||
| 729 | * @return int|null The value of $skip query option, NULL if $skip is absent. |
||
| 730 | * |
||
| 731 | */ |
||
| 732 | public function getSkipCount() |
||
| 733 | { |
||
| 734 | return $this->_skipCount; |
||
| 735 | } |
||
| 736 | |||
| 737 | /** |
||
| 738 | * Sets skip value |
||
| 739 | * |
||
| 740 | * @param int $skipCount The value of $skip query option. |
||
| 741 | * |
||
| 742 | * @return void |
||
| 743 | */ |
||
| 744 | public function setSkipCount($skipCount) |
||
| 745 | { |
||
| 746 | $this->_skipCount = $skipCount; |
||
| 747 | } |
||
| 748 | |||
| 749 | /** |
||
| 750 | * Gets the value of take count |
||
| 751 | * |
||
| 752 | * @return int|null The value of take, NULL if no take to be applied. |
||
| 753 | * |
||
| 754 | */ |
||
| 755 | public function getTopCount() |
||
| 758 | } |
||
| 759 | |||
| 760 | /** |
||
| 761 | * Sets the value of take count |
||
| 762 | * |
||
| 763 | * @param int $topCount The value of take query option |
||
| 764 | * |
||
| 765 | * @return void |
||
| 766 | */ |
||
| 767 | public function setTopCount($topCount) |
||
| 768 | { |
||
| 769 | $this->_topCount = $topCount; |
||
| 770 | } |
||
| 771 | |||
| 772 | /** |
||
| 773 | * Gets the value of $top query option |
||
| 774 | * |
||
| 775 | * @return int|null The value of $top query option, NULL if $top is absent. |
||
| 776 | * |
||
| 777 | */ |
||
| 778 | public function getTopOptionCount() |
||
| 781 | } |
||
| 782 | |||
| 783 | /** |
||
| 784 | * Sets top value |
||
| 785 | * |
||
| 786 | * @param int $topOptionCount The value of $top query option |
||
| 787 | * |
||
| 788 | * @return void |
||
| 789 | */ |
||
| 790 | public function setTopOptionCount($topOptionCount) |
||
| 791 | { |
||
| 792 | $this->_topOptionCount = $topOptionCount; |
||
| 793 | } |
||
| 794 | |||
| 795 | /** |
||
| 796 | * Gets sorting (orderby) information, this function return |
||
| 797 | * sorting information in 3 cases: |
||
| 798 | * (1) if $orderby option is specified in the request uri |
||
| 799 | * (2) if $skip or $top option is specified in the request uri |
||
| 800 | * (3) if server side paging is enabled for the resource targeted |
||
| 801 | * by the request uri. |
||
| 802 | * |
||
| 803 | * @return InternalOrderByInfo|null |
||
| 804 | */ |
||
| 805 | public function getInternalOrderByInfo() |
||
| 806 | { |
||
| 807 | return $this->internalOrderByInfo; |
||
| 808 | } |
||
| 809 | |||
| 810 | /** |
||
| 811 | * Sets sorting (orderby) information. |
||
| 812 | * |
||
| 813 | * @param InternalOrderByInfo &$internalOrderByInfo The sorting information. |
||
| 814 | * |
||
| 815 | * @return void |
||
| 816 | */ |
||
| 817 | public function setInternalOrderByInfo(InternalOrderByInfo &$internalOrderByInfo) |
||
| 818 | { |
||
| 819 | $this->internalOrderByInfo = $internalOrderByInfo; |
||
| 820 | } |
||
| 821 | |||
| 822 | /** |
||
| 823 | * Gets the parsed details for $skiptoken option. |
||
| 824 | * |
||
| 825 | * @return InternalSkipTokenInfo|null Returns parsed details of $skiptoken option, NULL if $skiptoken is absent. |
||
| 826 | * |
||
| 827 | */ |
||
| 828 | public function getInternalSkipTokenInfo() |
||
| 829 | { |
||
| 830 | return $this->_internalSkipTokenInfo; |
||
| 831 | } |
||
| 832 | |||
| 833 | /** |
||
| 834 | * Sets $skiptoken information. |
||
| 835 | * |
||
| 836 | * @param InternalSkipTokenInfo &$internalSkipTokenInfo The paging information. |
||
| 837 | * |
||
| 838 | * @return void |
||
| 839 | */ |
||
| 840 | public function setInternalSkipTokenInfo( |
||
| 841 | InternalSkipTokenInfo &$internalSkipTokenInfo |
||
| 842 | ) { |
||
| 843 | $this->_internalSkipTokenInfo = $internalSkipTokenInfo; |
||
| 844 | } |
||
| 845 | |||
| 846 | /** |
||
| 847 | * |
||
| 848 | * @return FilterInfo|null Returns parsed details of $filter option, NULL if $filter is absent. |
||
| 849 | * |
||
| 850 | */ |
||
| 851 | public function getFilterInfo() |
||
| 852 | { |
||
| 853 | return $this->_filterInfo; |
||
| 854 | } |
||
| 855 | |||
| 856 | /** |
||
| 857 | * |
||
| 858 | * @param FilterInfo $filterInfo The filter information. |
||
| 859 | * |
||
| 860 | */ |
||
| 861 | public function setFilterInfo(FilterInfo $filterInfo) |
||
| 862 | { |
||
| 863 | $this->_filterInfo = $filterInfo; |
||
| 864 | } |
||
| 865 | |||
| 866 | /** |
||
| 867 | * Sets $expand and $select information. |
||
| 868 | * |
||
| 869 | * @param RootProjectionNode &$rootProjectionNode Root of the projection tree. |
||
| 870 | * |
||
| 871 | * @return void |
||
| 872 | */ |
||
| 873 | public function setRootProjectionNode(RootProjectionNode &$rootProjectionNode) |
||
| 874 | { |
||
| 875 | $this->_rootProjectionNode = $rootProjectionNode; |
||
| 876 | } |
||
| 877 | |||
| 878 | /** |
||
| 879 | * Gets the root of the tree describing expand and select options, |
||
| 880 | * |
||
| 881 | * @return RootProjectionNode|null Returns parsed details of $expand |
||
| 882 | * and $select options, NULL if |
||
| 883 | * $both options are absent. |
||
| 884 | */ |
||
| 885 | public function getRootProjectionNode() |
||
| 886 | { |
||
| 887 | return $this->_rootProjectionNode; |
||
| 888 | } |
||
| 889 | |||
| 890 | |||
| 891 | /** |
||
| 892 | * Gets the count of result set if $count or $inlinecount=allpages |
||
| 893 | * has been applied otherwise NULL |
||
| 894 | * |
||
| 895 | * @return int|null |
||
| 896 | */ |
||
| 897 | public function getCountValue() |
||
| 898 | { |
||
| 899 | return $this->_countValue; |
||
| 900 | } |
||
| 901 | |||
| 902 | /** |
||
| 903 | * Sets the count of result set. |
||
| 904 | * |
||
| 905 | * @param int $countValue The count value. |
||
| 906 | * |
||
| 907 | * @return void |
||
| 908 | */ |
||
| 909 | public function setCountValue($countValue) |
||
| 910 | { |
||
| 911 | $this->_countValue = $countValue; |
||
| 912 | } |
||
| 913 | |||
| 914 | /** |
||
| 915 | * To set the flag indicating the execution status as true. |
||
| 916 | * |
||
| 917 | * @return void |
||
| 918 | */ |
||
| 919 | public function setExecuted() |
||
| 920 | { |
||
| 921 | $this->_isExecuted = true; |
||
| 922 | } |
||
| 923 | |||
| 924 | /** |
||
| 925 | * To check whether to execute the query using IDSQP. |
||
| 926 | * |
||
| 927 | * @return boolean True if query need to be executed, False otherwise. |
||
| 928 | */ |
||
| 929 | public function needExecution() |
||
| 930 | { |
||
| 931 | return !$this->_isExecuted |
||
| 932 | && ($this->lastSegment->getTargetKind() != TargetKind::METADATA) |
||
| 933 | && ($this->lastSegment->getTargetKind() != TargetKind::SERVICE_DIRECTORY); |
||
| 934 | } |
||
| 935 | |||
| 936 | /** |
||
| 937 | * To check if the resource path is a request for link uri. |
||
| 938 | * |
||
| 939 | * @return boolean True if request is for link uri else false. |
||
| 940 | */ |
||
| 941 | public function isLinkUri() |
||
| 942 | { |
||
| 943 | return (($this->_segmentCount > 2) && ($this->segments[$this->_segmentCount - 2]->getTargetKind() == TargetKind::LINK)); |
||
| 944 | } |
||
| 945 | |||
| 946 | /** |
||
| 947 | * To check if the resource path is a request for meida resource |
||
| 948 | * |
||
| 949 | * @return boolean True if request is for media resource else false. |
||
| 950 | */ |
||
| 951 | public function isMediaResource() |
||
| 952 | { |
||
| 953 | return ($this->lastSegment->getTargetKind() == TargetKind::MEDIA_RESOURCE); |
||
| 954 | } |
||
| 955 | |||
| 956 | /** |
||
| 957 | * To check if the resource path is a request for named stream |
||
| 958 | * |
||
| 959 | * @return boolean True if request is for named stream else false. |
||
| 960 | */ |
||
| 961 | public function isNamedStream() |
||
| 962 | { |
||
| 963 | return $this->isMediaResource() && !($this->lastSegment->getIdentifier() === ODataConstants::URI_VALUE_SEGMENT); |
||
| 964 | } |
||
| 965 | |||
| 966 | /** |
||
| 967 | * Get ResourceStreamInfo for the media link entry or named stream request. |
||
| 968 | * |
||
| 969 | * @return ResourceStreamInfo|null Instance of ResourceStreamInfo if the |
||
| 970 | * current request targets named stream, NULL for MLE |
||
| 971 | */ |
||
| 972 | public function getResourceStreamInfo() |
||
| 973 | { |
||
| 974 | //assert($this->isMediaResource) |
||
| 975 | if ($this->isNamedStream()) { |
||
| 976 | return $this->getTargetResourceType() |
||
| 977 | ->tryResolveNamedStreamByName( |
||
| 978 | $this->lastSegment->getIdentifier() |
||
| 979 | ); |
||
| 980 | } |
||
| 981 | |||
| 982 | return null; |
||
| 983 | } |
||
| 984 | |||
| 985 | /** |
||
| 986 | * Gets the resource instance targeted by the request uri. |
||
| 987 | * Note: This value will be populated after query execution only. |
||
| 988 | * |
||
| 989 | * @return mixed |
||
| 990 | */ |
||
| 991 | public function getTargetResult() |
||
| 992 | { |
||
| 993 | if (!empty($this->_parts)) { |
||
| 994 | $results = array(); |
||
| 995 | foreach ($this->_parts as &$part) { |
||
| 996 | $results[] = $part->lastSegment->getResult(); |
||
| 997 | } |
||
| 998 | return $results; |
||
| 999 | } else { |
||
| 1000 | return $this->lastSegment->getResult(); |
||
| 1001 | } |
||
| 1002 | } |
||
| 1003 | |||
| 1004 | /** |
||
| 1005 | * Gets the OData version the server used to generate the response. |
||
| 1006 | * |
||
| 1007 | * @return Version |
||
| 1008 | */ |
||
| 1009 | public function getResponseVersion() |
||
| 1013 | } |
||
| 1014 | |||
| 1015 | /** |
||
| 1016 | * Checks whether etag headers are allowed for this request. |
||
| 1017 | * |
||
| 1018 | * @return boolean True if ETag header (If-Match or If-NoneMatch) |
||
| 1019 | * is allowed for the request, False otherwise. |
||
| 1020 | */ |
||
| 1021 | public function isETagHeaderAllowed() |
||
| 1022 | { |
||
| 1023 | return $this->lastSegment->isSingleResult() |
||
| 1024 | && ($this->queryType != QueryType::COUNT) |
||
| 1025 | && !$this->isLinkUri() |
||
| 1026 | && (is_null($this->_rootProjectionNode) |
||
| 1027 | || !($this->_rootProjectionNode->isExpansionSpecified()) |
||
| 1028 | ); |
||
| 1029 | } |
||
| 1030 | |||
| 1031 | /** |
||
| 1032 | * Gets collection of known data service versions, currently 1.0, 2.0 and 3.0. |
||
| 1033 | * |
||
| 1034 | * @return Version[] |
||
| 1035 | */ |
||
| 1036 | public static function getKnownDataServiceVersions() |
||
| 1037 | { |
||
| 1038 | if (is_null(self::$_knownDataServiceVersions)) { |
||
| 1039 | self::$_knownDataServiceVersions = array( |
||
| 1040 | new Version(1, 0), |
||
| 1041 | new Version(2, 0), |
||
| 1042 | new Version(3, 0) |
||
| 1043 | ); |
||
| 1044 | } |
||
| 1045 | |||
| 1046 | return self::$_knownDataServiceVersions; |
||
| 1047 | } |
||
| 1048 | |||
| 1049 | /** |
||
| 1050 | * This function is used to perform following checking (validation) |
||
| 1051 | * for capability negotiation. |
||
| 1052 | * (1) Check client request's 'DataServiceVersion' header value is |
||
| 1053 | * less than or equal to the minimum version required to intercept |
||
| 1054 | * the response |
||
| 1055 | * (2) Check client request's 'MaxDataServiceVersion' header value is |
||
| 1056 | * less than or equal to the version of protocol required to generate |
||
| 1057 | * the response |
||
| 1058 | * (3) Check the configured maximum protocol version is less than or equal |
||
| 1059 | * to the version of protocol required to generate the response |
||
| 1060 | * In addition to these checking, this function is also responsible for |
||
| 1061 | * initializing the properties representing 'DataServiceVersion' and |
||
| 1062 | * 'MaxDataServiceVersion'. |
||
| 1063 | * |
||
| 1064 | * |
||
| 1065 | * @throws ODataException If any of the above 3 check fails. |
||
| 1066 | */ |
||
| 1067 | public function validateVersions() { |
||
| 1068 | |||
| 1069 | //If the request version is below the minimum version required by supplied request arguments..throw an exception |
||
| 1070 | if ($this->requestVersion->compare($this->requiredMinRequestVersion) < 0) { |
||
| 1071 | throw ODataException::createBadRequestError( |
||
| 1072 | Messages::requestVersionTooLow( |
||
| 1073 | $this->requestVersion->toString(), |
||
| 1074 | $this->requiredMinRequestVersion->toString() |
||
| 1075 | ) |
||
| 1076 | ); |
||
| 1077 | } |
||
| 1078 | |||
| 1079 | //If the requested max version is below the version required to fulfill the response...throw an exception |
||
| 1080 | if ($this->requestMaxVersion->compare($this->requiredMinResponseVersion) < 0) { |
||
| 1081 | throw ODataException::createBadRequestError( |
||
| 1082 | Messages::requestVersionTooLow( |
||
| 1083 | $this->requestMaxVersion->toString(), |
||
| 1084 | $this->requiredMinResponseVersion->toString() |
||
| 1085 | ) |
||
| 1086 | ); |
||
| 1087 | } |
||
| 1088 | |||
| 1089 | //If the max version supported by the service is below the version required to fulfill the response..throw an exception |
||
| 1090 | if ($this->maxServiceVersion->compare($this->requiredMinResponseVersion) < 0) { |
||
| 1091 | throw ODataException::createBadRequestError( |
||
| 1092 | Messages::requestVersionIsBiggerThanProtocolVersion( |
||
| 1093 | $this->requiredMinResponseVersion->toString(), |
||
| 1094 | $this->maxServiceVersion->toString() |
||
| 1095 | ) |
||
| 1096 | ); |
||
| 1097 | } |
||
| 1098 | } |
||
| 1099 | |||
| 1100 | /** |
||
| 1101 | * Validates the given version in string format and returns the version as instance of Version |
||
| 1102 | * |
||
| 1103 | * @param string $versionHeader The DataServiceVersion or MaxDataServiceVersion header value |
||
| 1104 | * @param string $headerName The name of the header |
||
| 1105 | * |
||
| 1106 | * @return Version |
||
| 1107 | * |
||
| 1108 | * @throws ODataException If the version is malformed or not supported |
||
| 1109 | */ |
||
| 1110 | private static function parseVersionHeader($versionHeader, $headerName) |
||
| 1111 | { |
||
| 1112 | $libName = null; |
||
| 1113 | $versionHeader = trim($versionHeader); |
||
| 1114 | $libNameIndex = strpos($versionHeader, ';'); |
||
| 1115 | if ($libNameIndex !== false) { |
||
| 1116 | $libName = substr($versionHeader, $libNameIndex); |
||
| 1117 | } else { |
||
| 1118 | $libNameIndex = strlen($versionHeader); |
||
| 1119 | } |
||
| 1120 | |||
| 1121 | $dotIndex = -1; |
||
| 1122 | for ($i = 0; $i < $libNameIndex; $i++) { |
||
| 1123 | if ($versionHeader[$i] == '.') { |
||
| 1124 | |||
| 1125 | //Throw an exception if we find more than 1 dot |
||
| 1126 | if ($dotIndex != -1) { |
||
| 1127 | throw ODataException::createBadRequestError( |
||
| 1128 | Messages::requestDescriptionInvalidVersionHeader( |
||
| 1129 | $versionHeader, |
||
| 1130 | $headerName |
||
| 1131 | ) |
||
| 1132 | ); |
||
| 1133 | } |
||
| 1134 | |||
| 1135 | $dotIndex = $i; |
||
| 1136 | } else if ($versionHeader[$i] < '0' || $versionHeader[$i] > '9') { |
||
| 1137 | throw ODataException::createBadRequestError( |
||
| 1138 | Messages::requestDescriptionInvalidVersionHeader( |
||
| 1139 | $versionHeader, |
||
| 1140 | $headerName |
||
| 1141 | ) |
||
| 1142 | ); |
||
| 1143 | } |
||
| 1144 | } |
||
| 1145 | |||
| 1146 | |||
| 1147 | $major = intval(substr($versionHeader, 0, $dotIndex)); |
||
| 1148 | $minor = 0; |
||
| 1149 | |||
| 1150 | //Apparently the . is optional |
||
| 1151 | if ($dotIndex != -1) { |
||
| 1152 | if ($dotIndex == 0) { |
||
| 1153 | //If it starts with a ., throw an exception |
||
| 1154 | throw ODataException::createBadRequestError( |
||
| 1155 | Messages::requestDescriptionInvalidVersionHeader( |
||
| 1156 | $versionHeader, |
||
| 1157 | $headerName |
||
| 1158 | ) |
||
| 1159 | ); |
||
| 1160 | } |
||
| 1161 | $minor = intval(substr($versionHeader, $dotIndex + 1, $libNameIndex)); |
||
| 1162 | } |
||
| 1163 | |||
| 1164 | |||
| 1165 | $version = new Version($major, $minor); |
||
| 1166 | |||
| 1167 | //TODO: move this somewhere... |
||
| 1168 | /* |
||
| 1169 | $isSupportedVersion = false; |
||
| 1170 | foreach (self::getKnownDataServiceVersions() as $version1) { |
||
| 1171 | if ($version->compare($version1) == 0) { |
||
| 1172 | $isSupportedVersion = true; |
||
| 1173 | break; |
||
| 1174 | } |
||
| 1175 | } |
||
| 1176 | |||
| 1177 | if (!$isSupportedVersion) { |
||
| 1178 | $availableVersions = null; |
||
| 1179 | foreach (self::getKnownDataServiceVersions() as $version1) { |
||
| 1180 | $availableVersions .= $version1->toString() . ', '; |
||
| 1181 | } |
||
| 1182 | |||
| 1183 | $availableVersions = rtrim($availableVersions, ', '); |
||
| 1184 | throw ODataException::createBadRequestError( |
||
| 1185 | Messages::requestDescriptionUnSupportedVersion( |
||
| 1186 | $headerName, |
||
| 1187 | $versionHeader, |
||
| 1188 | $availableVersions |
||
| 1189 | ) |
||
| 1190 | ); |
||
| 1191 | } |
||
| 1192 | */ |
||
| 1193 | |||
| 1194 | return $version; |
||
| 1195 | } |
||
| 1196 | |||
| 1197 | /** |
||
| 1198 | * Gets reference to the UriProcessor instance. |
||
| 1199 | * |
||
| 1200 | * @return UriProcessor |
||
| 1201 | */ |
||
| 1202 | public function getUriProcessor() |
||
| 1203 | { |
||
| 1204 | return $this->_uriProcessor; |
||
| 1205 | } |
||
| 1206 | |||
| 1207 | /** |
||
| 1208 | * Set reference to UriProcessor instance. |
||
| 1209 | * |
||
| 1210 | * @param UriProcessor $uriProcessor Reference to the UriProcessor |
||
| 1211 | * |
||
| 1212 | * @return void |
||
| 1213 | */ |
||
| 1214 | public function setUriProcessor(UriProcessor $uriProcessor) |
||
| 1215 | { |
||
| 1216 | $this->_uriProcessor = $uriProcessor; |
||
| 1217 | } |
||
| 1218 | |||
| 1219 | public function getQueryStringItem(string $item) |
||
| 1222 | } |
||
| 1223 | } |
||
| 1224 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths