Completed
Push — master ( 2bf901...7d3f30 )
by Christopher
24s queued 15s
created

ServiceConfiguration::getPrettyOutput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 2
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace POData\Configuration;
6
7
use InvalidArgumentException;
8
use POData\Common\InvalidOperationException;
9
use POData\Common\Messages;
10
use POData\Common\Version;
11
use POData\Providers\Metadata\IMetadataProvider;
12
use POData\Providers\Metadata\ResourceSet;
13
14
/**
15
 * Class ServiceConfiguration.
16
 * @package POData\Configuration
17
 */
18
class ServiceConfiguration implements IServiceConfiguration
19
{
20
    /**
21
     * Maximum number of segments to be expanded allowed in a request.
22
     */
23
    private $maxExpandCount;
24
25
    /**
26
     * Maximum number of segments in a single $expand path.
27
     */
28
    private $maxExpandDepth;
29
30
    /**
31
     * Maximum number of elements in each returned collection (top-level or expanded).
32
     */
33
    private $maxResultsPerCollection;
34
35
    /**
36
     * The provider for the web service.
37
     *
38
     * @var IMetadataProvider
39
     */
40
    private $provider;
41
42
    /**
43
     * Rights used for unspecified resource sets.
44
     *
45
     * @var EntitySetRights
46
     */
47
    private $defaultResourceSetRight;
48
49
    /**
50
     * Page size for unspecified resource sets.
51
     */
52
    private $defaultPageSize;
53
54
    /**
55
     * A mapping from entity set name to its right.
56
     *
57
     * @var EntitySetRights[]
58
     */
59
    private $resourceRights;
60
61
    /**
62
     * A mapping from entity sets to their page sizes.
63
     *
64
     * @var int[]
65
     */
66
    private $pageSizes = [];
67
68
    /**
69
     * Whether verbose errors should be returned by default.
70
     *
71
     * @var bool
72
     */
73
    private $useVerboseErrors;
74
75
    /**
76
     * Whether requests with the $count path segment or the $inlinecount
77
     * query options are accepted.
78
     */
79
    private $acceptCountRequest;
80
81
    /**
82
     * Whether projection requests ($select) should be accepted.
83
     */
84
    private $acceptProjectionRequest;
85
86
    /**
87
     * Maximum version of the response sent by server.
88
     *
89
     * @var ProtocolVersion
90
     */
91
    private $maxVersion;
92
93
    /**
94
     * Boolean value indicating whether to validate ETag header or not.
95
     */
96
    private $validateETagHeader;
97
98
    /**
99
     * @var string value to be used as line terminator
100
     */
101
    private $eol;
102
103
    /**
104
     * @var bool value to indicate if output should be printed human readable
105
     */
106
    private $prettyPrint;
107
108
    /**
109
     * Construct a new instance of ServiceConfiguration.
110
     *
111
     * @param IMetadataProvider|null $metadataProvider The metadata
112
     *                                                 provider for the OData service
113
     */
114
    public function __construct(?IMetadataProvider $metadataProvider)
115
    {
116
        $this->maxExpandCount          = PHP_INT_MAX;
117
        $this->maxExpandDepth          = PHP_INT_MAX;
118
        $this->maxResultsPerCollection = PHP_INT_MAX;
119
        $this->provider                = $metadataProvider;
120
        $this->defaultResourceSetRight = EntitySetRights::NONE();
121
        $this->defaultPageSize         = 0;
122
        $this->resourceRights          = [];
123
        $this->pageSizes               = [];
124
        $this->useVerboseErrors        = false;
125
        $this->acceptCountRequest      = false;
126
        $this->acceptProjectionRequest = false;
127
128
        $this->maxVersion = ProtocolVersion::V3(); //We default to the highest version
129
130
        $this->validateETagHeader = true;
131
        // basically display errors has a development value of on and a production value of off. so if not specified
132
        // use that
133
        $this->setPrettyOutput(in_array(strtolower(ini_get('display_errors')), array('1', 'on', 'true')));
134
        $this->setLineEndings(PHP_EOL);
135
    }
136
137
    /**
138
     * Gets maximum number of segments to be expanded allowed in a request.
139
     *
140
     * @return int
141
     */
142
    public function getMaxExpandCount(): int
143
    {
144
        return $this->maxExpandCount;
145
    }
146
147
    /**
148
     * Sets maximum number of segments to be expanded allowed in a request.
149
     *
150
     * @param int $maxExpandCount Maximum number of segments to be expanded
151
     */
152
    public function setMaxExpandCount(int $maxExpandCount): void
153
    {
154
        $this->maxExpandCount = $this->checkIntegerNonNegativeParameter(
155
            $maxExpandCount,
156
            'setMaxExpandCount'
157
        );
158
    }
159
160
    /**
161
     * Gets the maximum number of segments in a single $expand path.
162
     *
163
     * @return int
164
     */
165
    public function getMaxExpandDepth(): int
166
    {
167
        return $this->maxExpandDepth;
168
    }
169
170
    /**
171
     * Sets the maximum number of segments in a single $expand path.
172
     *
173
     * @param int $maxExpandDepth Maximum number of segments in a single $expand path
174
     */
175
    public function setMaxExpandDepth(int $maxExpandDepth): void
176
    {
177
        $this->maxExpandDepth = $this->checkIntegerNonNegativeParameter(
178
            $maxExpandDepth,
179
            'setMaxExpandDepth'
180
        );
181
    }
182
183
    /**
184
     * Gets maximum number of elements in each returned collection
185
     * (top-level or expanded).
186
     *
187
     * @return int
188
     */
189
    public function getMaxResultsPerCollection(): int
190
    {
191
        return $this->maxResultsPerCollection;
192
    }
193
194
    /**
195
     * Sets maximum number of elements in each returned collection
196
     * (top-level or expanded).
197
     *
198
     * @param int $maxResultPerCollection Maximum number of elements
199
     *                                    in returned collection
200
     *
201
     * @throws InvalidOperationException
202
     */
203
    public function setMaxResultsPerCollection(int $maxResultPerCollection): void
204
    {
205
        if ($this->isPageSizeDefined()) {
206
            throw new InvalidOperationException(
207
                Messages::configurationMaxResultAndPageSizeMutuallyExclusive()
208
            );
209
        }
210
211
        $this->maxResultsPerCollection = $this->checkIntegerNonNegativeParameter(
212
            $maxResultPerCollection,
213
            'setMaxResultsPerCollection'
214
        );
215
    }
216
217
    /**
218
     * Gets whether verbose errors should be used by default.
219
     *
220
     * @return bool
221
     */
222
    public function getUseVerboseErrors(): bool
223
    {
224
        return $this->useVerboseErrors;
225
    }
226
227
    /**
228
     * Sets whether verbose errors should be used by default.
229
     *
230
     * @param bool $useVerboseError true to enable verbose error else false
231
     */
232
    public function setUseVerboseErrors(bool $useVerboseError): void
233
    {
234
        $this->useVerboseErrors = $useVerboseError;
235
    }
236
237
    /**
238
     * gets the access rights on the specified resource set.
239
     *
240
     * @param ResourceSet $resourceSet The resource set for which get the access
241
     *                                 rights
242
     *
243
     * @return EntitySetRights
244
     */
245
    public function getEntitySetAccessRule(ResourceSet $resourceSet): EntitySetRights
246
    {
247
        if (!array_key_exists($resourceSet->getName(), $this->resourceRights)) {
248
            return $this->defaultResourceSetRight;
249
        }
250
251
        return $this->resourceRights[$resourceSet->getName()];
252
    }
253
254
    /**
255
     * sets the access rights on the specified resource set.
256
     *
257
     * @param string          $name   Name of resource set to set; '*' to indicate all
258
     * @param EntitySetRights $rights Rights to be granted to this resource
259
     *
260
     * @throws InvalidArgumentException when the entity set rights are not known or the resource set is not known
261
     */
262
    public function setEntitySetAccessRule(string $name, EntitySetRights $rights): void
263
    {
264
        if ($rights->getValue() < EntitySetRights::NONE || $rights->getValue() > EntitySetRights::ALL) {
265
            $msg = Messages::configurationRightsAreNotInRange('$rights', 'setEntitySetAccessRule');
266
            throw new InvalidArgumentException($msg);
267
        }
268
269
        if (strcmp($name, '*') === 0) {
270
            $this->defaultResourceSetRight = $rights;
271
        } else {
272
            if (!$this->provider->resolveResourceSet($name)) {
273
                throw new InvalidArgumentException(
274
                    Messages::configurationResourceSetNameNotFound($name)
275
                );
276
            }
277
278
            $this->resourceRights[$name] = $rights;
279
        }
280
    }
281
282
    /**
283
     * Gets the maximum page size for an entity set resource.
284
     *
285
     * @param ResourceSet $resourceSet Entity set for which to get the page size
286
     *
287
     * @return int
288
     */
289
    public function getEntitySetPageSize(ResourceSet $resourceSet): int
290
    {
291
        if (!array_key_exists($resourceSet->getName(), $this->pageSizes)) {
292
            return $this->defaultPageSize ?? 0; // TODO: defaultPageSize should never be null. it is inisalized in constructor. why is this requied?
293
        }
294
295
        return $this->pageSizes[$resourceSet->getName()];
296
    }
297
298
    /**
299
     * Sets the maximum page size for an entity set resource.
300
     *
301
     * @param string $name     Name of entity set resource for which to set the page size
302
     * @param int    $pageSize Page size for the entity set resource specified in name
303
     *
304
     * @throws InvalidOperationException
305
     * @throws InvalidArgumentException
306
     */
307
    public function setEntitySetPageSize(string $name, int $pageSize): void
308
    {
309
        $checkPageSize = $this->checkIntegerNonNegativeParameter(
310
            $pageSize,
311
            'setEntitySetPageSize'
312
        );
313
314
        if ($this->maxResultsPerCollection != PHP_INT_MAX) {
315
            throw new InvalidOperationException(
316
                Messages::configurationMaxResultAndPageSizeMutuallyExclusive()
317
            );
318
        }
319
320
        if ($checkPageSize == PHP_INT_MAX) {
321
            $checkPageSize = 0;
322
        }
323
324
        if (strcmp($name, '*') === 0) {
325
            $this->defaultPageSize = $checkPageSize;
326
        } else {
327
            if (!$this->provider->resolveResourceSet($name)) {
328
                throw new InvalidArgumentException(
329
                    Messages::configurationResourceSetNameNotFound($name)
330
                );
331
            }
332
            $this->pageSizes[$name] = $checkPageSize;
333
        }
334
    }
335
336
    /**
337
     * Gets whether requests with the $count path segment or the $inlinecount query
338
     * options are accepted.
339
     *
340
     * @return bool
341
     */
342
    public function getAcceptCountRequests(): bool
343
    {
344
        return $this->acceptCountRequest;
345
    }
346
347
    /**
348
     * Sets whether requests with the $count path segment or the $inlinecount
349
     * query options are accepted.
350
     *
351
     * @param bool $acceptCountRequest true to accept count request,
352
     *                                 false to not
353
     */
354
    public function setAcceptCountRequests(bool $acceptCountRequest): void
355
    {
356
        $this->acceptCountRequest = $acceptCountRequest;
357
    }
358
359
    /**
360
     * Gets whether projection requests ($select) should be accepted.
361
     *
362
     * @return bool
363
     */
364
    public function getAcceptProjectionRequests(): bool
365
    {
366
        return $this->acceptProjectionRequest;
367
    }
368
369
    /**
370
     * Sets whether projection requests ($select) should be accepted.
371
     *
372
     * @param bool $acceptProjectionRequest true to accept projection
373
     *                                      request, false to not
374
     */
375
    public function setAcceptProjectionRequests(bool $acceptProjectionRequest): void
376
    {
377
        $this->acceptProjectionRequest = $acceptProjectionRequest;
378
    }
379
380
    /**
381
     * Gets Maximum version of the response sent by server.
382
     *
383
     * @return Version
384
     */
385
    public function getMaxDataServiceVersion(): Version
386
    {
387
        switch ($this->maxVersion) {
388
            case ProtocolVersion::V1():
389
                return new Version(1, 0);
390
391
            case ProtocolVersion::V2():
392
                return new Version(2, 0);
393
394
            case ProtocolVersion::V3():
395
            default:
396
                return new Version(3, 0);
397
        }
398
    }
399
400
    /**
401
     * Sets Maximum version of the response sent by server.
402
     *
403
     * @param ProtocolVersion $version The version to set
404
     */
405
    public function setMaxDataServiceVersion(ProtocolVersion $version): void
406
    {
407
        $this->maxVersion = $version;
408
    }
409
410
    /**
411
     * Specify whether to validate the ETag or not.
412
     *
413
     * @param bool $validate True if ETag needs to validated, false otherwise
414
     */
415
    public function setValidateETagHeader(bool $validate): void
416
    {
417
        $this->validateETagHeader = $validate;
418
    }
419
420
    /**
421
     * Gets whether to validate the ETag or not.
422
     *
423
     * @return bool True if ETag needs to validated, false
424
     *              if its not to be validated, Note that in case
425
     *              of false library will not write the ETag header
426
     *              in the response even though the requested resource
427
     *              support ETag
428
     */
429
    public function getValidateETagHeader(): bool
430
    {
431
        return $this->validateETagHeader;
432
    }
433
434
    /**
435
     * Checks that the parameter to a function is numeric and is not negative.
436
     *
437
     * @param int    $value        The value of parameter to check
438
     * @param string $functionName The name of the function that receives above value
439
     *
440
     * @throws InvalidArgumentException
441
     *
442
     * @return int
443
     */
444
    private function checkIntegerNonNegativeParameter(int $value, string $functionName): int
445
    {
446
        if ($value < 0) {
447
            throw new InvalidArgumentException(
448
                Messages::commonArgumentShouldBeNonNegative($value, $functionName)
449
            );
450
        }
451
452
        return $value;
453
    }
454
455
    /**
456
     * Whether size of a page has been defined for any entity set.
457
     *
458
     * @return bool
459
     */
460
    private function isPageSizeDefined()
461
    {
462
        return count($this->pageSizes) > 0 || $this->defaultPageSize > 0;
463
    }
464
465
    /**
466
     * Gets the value to be used for line endings.
467
     *
468
     * @return string the value to append at the end of lines
469
     */
470
    public function getLineEndings(): string
471
    {
472
        return $this->eol;
473
    }
474
475
    /**
476
     * Gets whether to format the output as human readable or single line.
477
     *
478
     * @return bool true if output should be formatted for human readability
479
     */
480
    public function getPrettyOutput(): bool
481
    {
482
        return $this->prettyPrint;
483
    }
484
485
    /**
486
     * Sets the characters that represent line endings.
487
     *
488
     * @param string $eol the characters that should be used for line endings
489
     */
490
    public function setLineEndings(string $eol): void
491
    {
492
        $this->eol = $eol;
493
    }
494
495
    /**
496
     * Sets if output should be well formatted for human review.
497
     *
498
     * @param bool $on True if output should be well formatted
499
     */
500
    public function setPrettyOutput(bool $on): void
501
    {
502
        $this->prettyPrint = $on;
503
    }
504
}
505