GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

AbstractBrowserBindingService   F
last analyzed

Complexity

Total Complexity 97

Size/Duplication

Total Lines 718
Duplicated Lines 12.4 %

Coupling/Cohesion

Components 1
Dependencies 28

Test Coverage

Coverage 87.33%

Importance

Changes 0
Metric Value
wmc 97
lcom 1
cbo 28
dl 89
loc 718
ccs 255
cts 292
cp 0.8733
rs 1.882
c 0
b 0
f 0

31 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A setCmisBindingsHelper() 0 4 2
A getObjectUrl() 22 22 3
A getRepositoryUrlCache() 0 10 2
A getSession() 0 4 1
A setSession() 0 8 1
B getRepositoriesInternal() 0 55 9
A getServiceUrl() 0 4 1
A readJson() 0 4 1
A read() 0 21 3
A getHttpInvoker() 0 4 1
D convertStatusCode() 0 53 19
A getJsonConverter() 0 4 1
A getPathUrl() 22 22 3
A getSuccinct() 0 4 1
A postJson() 0 4 1
A post() 0 18 5
B convertQueryArrayToMultiPart() 0 27 7
A getTypeDefinitionInternal() 0 18 3
A getRepositoryUrl() 21 21 3
A convertPropertiesToQueryArray() 0 34 5
A convertPropertyValueToSimpleType() 0 12 4
B convertAclToQueryArray() 0 23 6
A convertPolicyIdArrayToQueryArray() 0 12 2
A getDateTimeFormat() 0 4 1
A setDateTimeFormat() 0 4 1
A appendPoliciesToUrl() 0 6 2
A appendAddAcesToUrl() 12 12 2
A appendRemoveAcesToUrl() 12 12 2
A loadContentLink() 0 5 2
A loadRenditionContentLink() 0 9 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like AbstractBrowserBindingService 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 AbstractBrowserBindingService, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Dkd\PhpCmis\Bindings\Browser;
3
4
/*
5
 * This file is part of php-cmis-client.
6
 *
7
 * (c) Sascha Egerer <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
use Dkd\PhpCmis\Bindings\BindingSessionInterface;
14
use Dkd\PhpCmis\Bindings\CmisBindingsHelper;
15
use Dkd\PhpCmis\Bindings\LinkAccessInterface;
16
use Dkd\PhpCmis\Constants;
17
use Dkd\PhpCmis\Data\AclInterface;
18
use Dkd\PhpCmis\Data\PropertiesInterface;
19
use Dkd\PhpCmis\DataObjects\RepositoryInfo;
20
use Dkd\PhpCmis\DataObjects\RepositoryInfoBrowserBinding;
21
use Dkd\PhpCmis\Definitions\TypeDefinitionInterface;
22
use Dkd\PhpCmis\Enum\DateTimeFormat;
23
use Dkd\PhpCmis\Exception\CmisBaseException;
24
use Dkd\PhpCmis\Exception\CmisConnectionException;
25
use Dkd\PhpCmis\Exception\CmisConstraintException;
26
use Dkd\PhpCmis\Exception\CmisInvalidArgumentException;
27
use Dkd\PhpCmis\Exception\CmisNotSupportedException;
28
use Dkd\PhpCmis\Exception\CmisObjectNotFoundException;
29
use Dkd\PhpCmis\Exception\CmisPermissionDeniedException;
30
use Dkd\PhpCmis\Exception\CmisProxyAuthenticationException;
31
use Dkd\PhpCmis\Exception\CmisRuntimeException;
32
use Dkd\PhpCmis\Exception\CmisUnauthorizedException;
33
use Dkd\PhpCmis\SessionParameter;
34
use GuzzleHttp\Client;
35
use GuzzleHttp\Exception\RequestException;
36
use GuzzleHttp\Psr7\Response;
37
use GuzzleHttp\Stream\StreamInterface;
38
use League\Url\Url;
39
use Psr\Http\Message\ResponseInterface;
40
use function basename;
41
use function is_array;
42
use function is_object;
43
use function is_resource;
44
use function json_decode;
45
46
/**
47
 * Base class for all Browser Binding client services.
48
 */
49
abstract class AbstractBrowserBindingService implements LinkAccessInterface
50
{
51
    /**
52
     * @var BindingSessionInterface
53
     */
54
    protected $session;
55
56
    /**
57
     * @var boolean
58
     */
59
    protected $succinct;
60
61
    /**
62
     * @var CmisBindingsHelper
63
     */
64
    protected $cmisBindingsHelper;
65
66
    /**
67
     * @var DateTimeFormat
68
     */
69 168
    protected $dateTimeFormat;
70
71 168
    /**
72 168
     * @param BindingSessionInterface $session
73 168
     * @param CmisBindingsHelper|null $cmisBindingsHelper
74
     */
75
    public function __construct(BindingSessionInterface $session, $cmisBindingsHelper = null)
76
    {
77
        $this->setCmisBindingsHelper($cmisBindingsHelper);
78
        $this->setSession($session);
79
    }
80
81 168
    /**
82
     * Set cmis binding helper property
83 168
     *
84 168
     * @param CmisBindingsHelper|null $cmisBindingsHelper The cmis binding helper that should be defined.
85
     * If <code>null</code> is given a new instance of CmisBindingsHelper will be created.
86
     */
87
    protected function setCmisBindingsHelper($cmisBindingsHelper = null)
88
    {
89
        $this->cmisBindingsHelper = ($cmisBindingsHelper === null) ? new CmisBindingsHelper() : $cmisBindingsHelper;
90
    }
91
92
    /**
93
     * Get the url for an object
94
     *
95
     * @param string $repositoryId
96 2
     * @param string $objectId
97
     * @param string|null $selector
98 2
     * @throws CmisConnectionException
99
     * @throws CmisObjectNotFoundException
100 2
     * @return Url
101 1
     */
102 1 View Code Duplication
    protected function getObjectUrl($repositoryId, $objectId, $selector = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
103 1
    {
104
        $result = $this->getRepositoryUrlCache()->getObjectUrl($repositoryId, $objectId, $selector);
105 2
106 1
        if ($result === null) {
107 1
            $this->getRepositoriesInternal($repositoryId);
108 1
            $result = $this->getRepositoryUrlCache()->getObjectUrl($repositoryId, $objectId, $selector);
109 1
        }
110 1
111
        if ($result === null) {
112 1
            throw new CmisObjectNotFoundException(
113 1
                sprintf(
114
                    'Unknown Object! Repository: "%s" | Object: "%s" | Selector: "%s"',
115
                    $repositoryId,
116 1
                    $objectId,
117
                    $selector
118
                )
119
            );
120
        }
121
122
        return $result;
123
    }
124
125 2
    /**
126
     * Returns the repository URL cache or creates a new cache if it doesn't
127 2
     * exist.
128 2
     *
129 1
     * @return RepositoryUrlCache
130 1
     */
131 1
    protected function getRepositoryUrlCache()
132
    {
133 2
        $repositoryUrlCache = $this->getSession()->get(SessionParameter::REPOSITORY_URL_CACHE);
134
        if ($repositoryUrlCache === null) {
135
            $repositoryUrlCache = new RepositoryUrlCache();
136
            $this->getSession()->put(SessionParameter::REPOSITORY_URL_CACHE, $repositoryUrlCache);
137
        }
138
139
        return $repositoryUrlCache;
140
    }
141 66
142
    /**
143 66
     * Get current session
144
     *
145
     * @return BindingSessionInterface
146
     */
147
    public function getSession()
148
    {
149
        return $this->session;
150
    }
151 168
152
    /**
153 168
     * Sets the current session.
154 168
     *
155 168
     * @param BindingSessionInterface $session
156
     */
157 168
    protected function setSession(BindingSessionInterface $session)
158 168
    {
159
        $this->session = $session;
160
        $succinct = $session->get(SessionParameter::BROWSER_SUCCINCT);
161
        $this->succinct = $succinct ?? true;
162
163
        $this->dateTimeFormat = DateTimeFormat::cast($session->get(SessionParameter::BROWSER_DATETIME_FORMAT));
164
    }
165
166
    /**
167 8
     * Retrieves the the repository info objects.
168
     *
169 8
     * @param string|null $repositoryId
170
     * @throws CmisConnectionException
171 8
     * @return RepositoryInfo[] Returns ALL Repository Infos that are available and not just the one requested by id.
172
     */
173 6
    protected function getRepositoriesInternal($repositoryId = null)
174 6
    {
175
        $repositoryUrlCache = $this->getRepositoryUrlCache();
176 2
177 2
        if ($repositoryId === null) {
178
            // no repository id provided -> get all
179 1
            $url = $repositoryUrlCache->buildUrl($this->getServiceUrl());
180 1
        } else {
181
            // use URL of the specified repository
182
            $url = $repositoryUrlCache->getRepositoryUrl($repositoryId, Constants::SELECTOR_REPOSITORY_INFO) ??
183 8
                $repositoryUrlCache->buildUrl($this->getServiceUrl());
184 8
        }
185 8
186
        $repositoryInfos = [];
187 8
        $result = $this->readJson($url);
188 8
        if (!is_array($result)) {
189 1
            throw new CmisConnectionException(
190 1
                'Could not fetch repository info! Response is not a valid JSON.',
191
                1416343166
192 1
            );
193
        }
194 7
        foreach ($result as $item) {
195 7
            if (is_array($item)) {
196 6
                $repositoryInfo = $this->getJsonConverter()->convertRepositoryInfo($item);
197
198 6
                if ($repositoryInfo instanceof RepositoryInfoBrowserBinding) {
199 6
                    $id = $repositoryInfo->getId();
200 6
                    $repositoryUrl = $repositoryInfo->getRepositoryUrl();
201 6
                    $rootUrl = $repositoryInfo->getRootUrl();
202
203 6
                    if (empty($id) || empty($repositoryUrl) || empty($rootUrl)) {
204 3
                        throw new CmisConnectionException(
205 3
                            sprintf('Found invalid Repository Info! (id: %s)', $id),
206
                            1415187765
207 3
                        );
208
                    }
209
210 3
                    $this->getRepositoryUrlCache()->addRepository($id, $repositoryUrl, $rootUrl);
211
212 3
                    $repositoryInfos[] = $repositoryInfo;
213 3
                }
214 3
            } else {
215 1
                throw new CmisConnectionException(
216 1
                    sprintf(
217
                        'Found invalid repository info! Value of type "array" was expected'
218 1
                        . 'but value of type "%s" was given.',
219 1
                        gettype($item)
220 1
                    ),
221
                    1415187764
222 1
                );
223
            }
224 3
        }
225
226 3
        return $repositoryInfos;
227
    }
228
229
    /**
230
     * Returns the service URL of this session.
231
     *
232
     * @return string|null
233
     */
234 2
    protected function getServiceUrl()
235
    {
236 2
        return $this->getSession()->get(SessionParameter::BROWSER_URL);
237 2
    }
238 1
239
    /**
240
     * Wrapper to read URL response as JSON as is the general use case.
241 1
     *
242
     * @param Url $url
243
     * @return mixed
244
     */
245
    protected function readJson(Url $url)
246
    {
247
        return json_decode($this->read($url)->getBody(), true);
248
    }
249
250
    /**
251
     * Do a get request for the given url
252 3
     *
253
     * @param Url $url
254
     * @return Response
255
     * @throws CmisBaseException an more specific exception of this type could be thrown. For more details see
256 3
     * @see AbstractBrowserBindingService::convertStatusCode()
257 3
     */
258 2
    protected function read(Url $url)
259 2
    {
260 2
        /** @var Response $response */
261 2
        try {
262 2
            $response = $this->getHttpInvoker()->get((string) $url);
263 2
        } catch (RequestException $exception) {
264 2
            $code = 0;
265 2
            $message = null;
266 2
            if ($exception->getResponse()) {
267
                $code = $exception->getResponse()->getStatusCode();
268 2
                $message = $exception->getResponse()->getBody();
269
            }
270
            throw $this->convertStatusCode(
271 1
                $code,
272
                (string) $message,
273
                $exception
274
            );
275
        }
276
277
        return $response;
278
    }
279 4
280
    /**
281
     * Get a HTTP Invoker instance
282 4
     *
283
     * @return Client
284 4
     */
285
    protected function getHttpInvoker()
286
    {
287
        return $this->cmisBindingsHelper->getHttpInvoker($this->getSession());
288
    }
289
290
    /**
291
     * Converts an error message or a HTTP status code into an Exception.
292
     *
293
     * @see http://docs.oasis-open.org/cmis/CMIS/v1.1/os/CMIS-v1.1-os.html#x1-551021r549
294
     *
295
     * @param integer $code
296
     * @param string $message
297 26
     * @param null|\Exception $exception
298
     * @return CmisBaseException
299 26
     */
300
    protected function convertStatusCode($code, $message, \Exception $exception = null)
301 26
    {
302 13
        $messageData = json_decode($message, true);
303
304 13
        if (is_array($messageData) && !empty($messageData[JSONConstants::ERROR_EXCEPTION])) {
305 13
            $jsonError = $messageData[JSONConstants::ERROR_EXCEPTION];
306 13
307 13
            if (!empty($messageData[JSONConstants::ERROR_MESSAGE])
308 13
                && is_string($messageData[JSONConstants::ERROR_MESSAGE])
309
            ) {
310 13
                $message = $messageData[JSONConstants::ERROR_MESSAGE];
311
            }
312 13
313 12
            $exceptionName = '\\Dkd\\PhpCmis\\Exception\\Cmis' . ucfirst($jsonError) . 'Exception';
314
315 1
            if (class_exists($exceptionName)) {
316
                return new $exceptionName($message, null, $exception);
317 14
            }
318
        }
319
320
        if (empty($message) && $exception !== null) {
321
            $message = $exception->getMessage();
322
        }
323 14
324 14
        // fall back to status code
325 14
        switch ($code) {
326 14
            case 301:
327 4
            case 302:
328 4
            case 303:
329 4
            case 307:
330
                return new CmisConnectionException(
331 4
                    'Redirects are not supported (HTTP status code ' . $code . '): ' . $message,
332 10
                    null,
333 1
                    $exception
334 9
                );
335 1
            case 400:
336 8
                return new CmisInvalidArgumentException($message, null, $exception);
337 1
            case 401:
338 7
                return new CmisUnauthorizedException($message, null, $exception);
339 1
            case 403:
340 6
                return new CmisPermissionDeniedException($message, null, $exception);
341 1
            case 404:
342 5
                return new CmisObjectNotFoundException($message, null, $exception);
343 1
            case 405:
344 4
                return new CmisNotSupportedException($message, null, $exception);
345 1
            case 407:
346 3
                return new CmisProxyAuthenticationException($message, null, $exception);
347 3
            case 409:
348 3
                return new CmisConstraintException($message, null, $exception);
349
            default:
350
                return new CmisRuntimeException($message, null, $exception);
351
        }
352
    }
353
354
    // ---- helpers ----
355
356
    /**
357
     * Returns JSON Converter instance
358 65
     *
359
     * @return \Dkd\PhpCmis\Converter\JsonConverter
360 65
     */
361
    protected function getJsonConverter()
362
    {
363
        return $this->cmisBindingsHelper->getJsonConverter($this->getSession());
364
    }
365
366
    /**
367
     * Generate url for a given path of a given repository.
368
     *
369
     * @param string $repositoryId
370
     * @param string $path
371
     * @param string|null $selector
372
     * @throws CmisConnectionException
373 2
     * @throws CmisObjectNotFoundException
374
     * @return Url
375 2
     */
376 View Code Duplication
    protected function getPathUrl($repositoryId, $path, $selector = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
377 2
    {
378 1
        $result = $this->getRepositoryUrlCache()->getPathUrl($repositoryId, $path, $selector);
379 1
380 1
        if ($result === null) {
381
            $this->getRepositoriesInternal($repositoryId);
382 2
            $result = $this->getRepositoryUrlCache()->getPathUrl($repositoryId, $path, $selector);
383 1
        }
384 1
385 1
        if ($result === null) {
386 1
            throw new CmisObjectNotFoundException(
387 1
                sprintf(
388
                    'Unknown path! Repository: "%s" | Path: "%s" | Selector: "%s"',
389 1
                    $repositoryId,
390 1
                    $path,
391
                    $selector
392
                )
393 1
            );
394
        }
395
396
        return $result;
397
    }
398
399
// ---- URL ----
400
401
    /**
402
     * Get if succinct mode is used
403 46
     *
404
     * @return boolean
405 46
     */
406
    protected function getSuccinct()
407
    {
408
        return $this->succinct;
409
    }
410
411
    /**
412
     * Wrapper for calling post() and reading response as JSON, as is the general use case.
413
     *
414
     * @param Url $url
415
     * @param array $content
416
     * @param array $headers
417
     * @return mixed
418
     */
419 2
    protected function postJson(Url $url, $content = [], array $headers = [])
420
    {
421 2
        return \json_decode($this->post($url, $content, $headers)->getBody(), true);
422
    }
423
424
    /**
425 2
     * Performs a POST on an URL, checks the response code and returns the
426 2
     * result.
427 1
     *
428 1
     * @param Url $url Request url
429 1
     * @param resource|string|StreamInterface|array $content Entity body data or an array for POST fields and files
430
     * @param array $headers Additional header options
431 1
     * @return ResponseInterface
432
     * @throws CmisBaseException an more specific exception of this type could be thrown. For more details see
433
     * @see AbstractBrowserBindingService::convertStatusCode()
434 1
     */
435
    protected function post(Url $url, $content = [], array $headers = [])
436
    {
437
        if (is_resource($content) || is_object($content)) {
438
            $headers['body'] = $content;
439
        } elseif (is_array($content)) {
440
            $headers['multipart'] = $this->convertQueryArrayToMultiPart($content);
441
        }
442
443
        try {
444
            return $this->getHttpInvoker()->post((string) $url, $headers);
445 3
        } catch (RequestException $exception) {
446
            throw $this->convertStatusCode(
447 3
                $exception->getResponse()->getStatusCode(),
448 1
                (string) $exception->getResponse()->getBody(),
449
                $exception
450
            );
451 2
        }
452 1
    }
453
454
    /**
455
     * @param array $queryArray
456 1
     * @param null $prefix
457 1
     * @return array
458
     */
459 1
    protected function convertQueryArrayToMultiPart(array $queryArray, $prefix = null)
460 1
    {
461 1
        $multipart = [];
462
        foreach ($queryArray as $name => $value) {
463 1
            $prefixedName = $prefix ? $prefix . '[' . $name . ']' : $name;
464 1
            if (is_array($value)) {
465
                $multipart = array_merge($multipart, $this->convertQueryArrayToMultiPart($value, $prefixedName));
466
            } elseif ($value instanceof StreamInterface) {
467
                $streamPart = [
468
                    'name' => '',
469
                    'contents' => $value,
470
                    'filename' => basename( $value->getMetadata('uri'))
471
                ];
472
                $mimetype = $value->getMetadata('mimetype');
473
                if ($mimetype) {
474
                    $streamPart['headers'] = ['Content-type' => $mimetype];
475
                }
476 2
                $multipart[] = $streamPart;
477
            } else {
478 2
                $multipart[] = [
479
                    'name' => $prefix ? $prefixedName : $name,
480 2
                    'contents' => $value
481 1
                ];
482 1
            }
483 1
        }
484
        return $multipart;
485 2
    }
486 1
487 1
    /**
488 1
     * Retrieves a type definition.
489 1
     *
490
     * @param string $repositoryId
491 1
     * @param string $typeId
492 1
     * @return TypeDefinitionInterface|null
493
     * @throws CmisInvalidArgumentException if repository id or type id is <code>null</code>
494
     */
495 1
    protected function getTypeDefinitionInternal($repositoryId, $typeId)
496
    {
497
        if (empty($repositoryId)) {
498
            throw new CmisInvalidArgumentException('Repository id must not be empty!');
499
        }
500
501
        if (empty($typeId)) {
502
            throw new CmisInvalidArgumentException('Type id must not be empty!');
503
        }
504
505
        // build URL
506 13
        $url = $this->getRepositoryUrl($repositoryId, Constants::SELECTOR_TYPE_DEFINITION);
507
        $url->getQuery()->modify([Constants::PARAM_TYPE_ID => $typeId]);
508 13
509
        return $this->getJsonConverter()->convertTypeDefinition(
510 13
            (array) $this->readJson($url)
511 13
        );
512 13
    }
513 13
514 13
    /**
515
     * Get url for a repository
516 13
     *
517
     * @param string $repositoryId
518 13
     * @param string|null $selector
519 13
     * @throws CmisConnectionException
520 13
     * @throws CmisObjectNotFoundException
521 13
     * @return Url
522 13
     */
523 13 View Code Duplication
    protected function getRepositoryUrl($repositoryId, $selector = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
524 1
    {
525 1
        $result = $this->getRepositoryUrlCache()->getRepositoryUrl($repositoryId, $selector);
526 1
527 1
        if ($result === null) {
528 1
            $this->getRepositoriesInternal($repositoryId);
529
            $result = $this->getRepositoryUrlCache()->getRepositoryUrl($repositoryId, $selector);
530 1
        }
531 1
532 1
        if ($result === null) {
533 1
            throw new CmisObjectNotFoundException(
534
                sprintf(
535 13
                    'Unknown repository! Repository: "%s" | Selector: "%s"',
536 13
                    $repositoryId,
537
                    $selector
538 13
                )
539
            );
540
        }
541
542
        return $result;
543
    }
544
545
    /**
546
     * Converts a Properties list into an array that can be used for the CMIS request.
547 13
     *
548
     * @param PropertiesInterface $properties
549 13
     * @return array Example <code>
550
     * array('propertyId' => array(0 => 'myId'), 'propertyValue' => array(0 => 'valueOfMyId'))
551 1
     * </code>
552 13
     */
553
    protected function convertPropertiesToQueryArray(PropertiesInterface $properties)
554 1
    {
555 1
        $propertiesArray = [];
556
557 13
        $propertyCounter = 0;
558
        $propertiesArray[Constants::CONTROL_PROP_ID] = [];
559
        $propertiesArray[Constants::CONTROL_PROP_VALUE] = [];
560
        foreach ($properties->getProperties() as $property) {
561
            $propertiesArray[Constants::CONTROL_PROP_ID][$propertyCounter] = $property->getId();
562
563
            $propertyValues = $property->getValues();
564
565
            if (count($propertyValues) === 1) {
566
                $propertiesArray[Constants::CONTROL_PROP_VALUE][$propertyCounter] =
567
                    $this->convertPropertyValueToSimpleType(
568
                        $property->getFirstValue()
569
                    );
570
            } elseif (count($propertyValues) > 1) {
571
                $propertyValueCounter = 0;
572
                $propertiesArray[Constants::CONTROL_PROP_VALUE][$propertyCounter] = [];
573 7
                foreach ($propertyValues as $propertyValue) {
574
                    $propertiesArray[Constants::CONTROL_PROP_VALUE][$propertyCounter][$propertyValueCounter] =
575 7
                        $this->convertPropertyValueToSimpleType(
576 7
                            $propertyValue
577
                        );
578 7
                    $propertyValueCounter ++;
579 7
                }
580 7
            }
581 7
582 7
            $propertyCounter ++;
583 7
        }
584
585 7
        return $propertiesArray;
586 7
    }
587 7
588 7
    /**
589
     * Converts values to a format that can be used for the CMIS Browser binding request.
590 7
     *
591 7
     * @param mixed $value
592 7
     * @return mixed
593
     */
594 7
    protected function convertPropertyValueToSimpleType($value)
595
    {
596
        if ($value instanceof \DateTime) {
597
            // CMIS expects a timestamp in milliseconds
598
            $value = $value->getTimestamp() * 1000;
599
        } elseif (is_bool($value)) {
600
			// Booleans must be represented in string form since request will fail if cast to integer
601
			$value = $value ? 'true' : 'false';
602
		}
603 10
604
        return $value;
605 10
    }
606 10
607
    /**
608 10
     * Converts a Access Control list into an array that can be used for the CMIS request
609 6
     *
610 6
     * @param AclInterface $acl
611 10
     * @param string $principalControl one of principal ace constants
612
     * CONTROL_ADD_ACE_PRINCIPAL or CONTROL_REMOVE_ACE_PRINCIPAL
613 10
     * @param string $permissionControl one of permission ace constants
614
     * CONTROL_REMOVE_ACE_PRINCIPAL or CONTROL_REMOVE_ACE_PERMISSION
615
     * @return array Example <code>
616
     * array('addACEPrincipal' => array(0 => 'principalId'),
617
     *       'addACEPermission' => array(0 => array(0 => 'permissonValue')))
618
     * </code>
619
     */
620
    protected function convertAclToQueryArray(AclInterface $acl, $principalControl, $permissionControl)
621 32
    {
622
        $acesArray = [];
623 32
        $principalCounter = 0;
624
625
        foreach ($acl->getAces() as $ace) {
626
            $permissions = $ace->getPermissions();
627
            if ($ace->getPrincipal() !== null && $ace->getPrincipal()->getId() && !empty($permissions)) {
628
                $acesArray[$principalControl][$principalCounter] = $ace->getPrincipal()->getId();
629
                $permissionCounter = 0;
630
                $acesArray[$permissionControl][$principalCounter] = [];
631 1
632
                foreach ($permissions as $permission) {
633 1
                    $acesArray[$permissionControl][$principalCounter][$permissionCounter] = $permission;
634 1
                    $permissionCounter ++;
635
                }
636
637
                $principalCounter ++;
638
            }
639
        }
640
641
        return $acesArray;
642
    }
643
644
    /**
645
     * Converts a policies array into an array that can be used for the CMIS request
646
     *
647
     * @param string[] $policies A list of policy string representations
648
     * @return array
649
     */
650
    protected function convertPolicyIdArrayToQueryArray(array $policies)
651
    {
652
        $policiesArray = [];
653
        $policyCounter = 0;
654
655
        foreach ($policies as $policy) {
656
            $policiesArray[Constants::CONTROL_POLICY][$policyCounter] = (string) $policy;
657
            $policyCounter ++;
658
        }
659
660
        return $policiesArray;
661
    }
662
663
    /**
664
     * Returns the date time format
665
     *
666
     * @return DateTimeFormat
667
     */
668
    public function getDateTimeFormat()
669
    {
670
        return $this->dateTimeFormat;
671
    }
672
673
    /**
674
     * Sets the date time format
675
     *
676
     * @param DateTimeFormat $dateTimeFormat
677
     */
678
    public function setDateTimeFormat(DateTimeFormat $dateTimeFormat)
679
    {
680
        $this->dateTimeFormat = $dateTimeFormat;
681
    }
682
683
    /**
684
     * Appends policies parameters to url
685
     *
686
     * @param Url $url
687
     * @param string[] $policies A list of policy IDs that must be applied to the newly created document object
688
     */
689
    protected function appendPoliciesToUrl(Url $url, array $policies)
690
    {
691
        if (!empty($policies)) {
692
            $url->getQuery()->modify($this->convertPolicyIdArrayToQueryArray($policies));
693
        }
694
    }
695
696
    /**
697
     * Appends addAces parameters to url
698
     *
699
     * @param Url $url
700
     * @param AclInterface|null $addAces A list of ACEs
701
     */
702 View Code Duplication
    protected function appendAddAcesToUrl(Url $url, AclInterface $addAces = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
703
    {
704
        if ($addAces !== null) {
705
            $url->getQuery()->modify(
706
                $this->convertAclToQueryArray(
707
                    $addAces,
708
                    Constants::CONTROL_ADD_ACE_PRINCIPAL,
709
                    Constants::CONTROL_ADD_ACE_PERMISSION
710
                )
711
            );
712
        }
713
    }
714
715
    /**
716
     * Appends removeAces parameters to url
717
     *
718
     * @param Url $url
719
     * @param AclInterface|null $removeAces A list of ACEs
720
     */
721 View Code Duplication
    protected function appendRemoveAcesToUrl(Url $url, AclInterface $removeAces = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
722
    {
723
        if ($removeAces !== null) {
724
            $url->getQuery()->modify(
725
                $this->convertAclToQueryArray(
726
                    $removeAces,
727
                    Constants::CONTROL_REMOVE_ACE_PRINCIPAL,
728
                    Constants::CONTROL_REMOVE_ACE_PERMISSION
729
                )
730
            );
731
        }
732
    }
733
734
    /**
735
     * Gets the content link from the cache if it is there or loads it into the
736
     * cache if it is not there.
737
     *
738
     * @param string $repositoryId
739
     * @param string $documentId
740
     * @return string|null
741
     */
742
    public function loadContentLink($repositoryId, $documentId)
743
    {
744
        $result = $this->getRepositoryUrlCache()->getObjectUrl($repositoryId, $documentId, Constants::SELECTOR_CONTENT);
745
        return $result === null ? null : (string) $result;
746
    }
747
748
    /**
749
     * Gets a rendition content link from the cache if it is there or loads it
750
     * into the cache if it is not there.
751
     *
752
     * @param string $repositoryId
753
     * @param string $documentId
754
     * @param string $streamId
755
     * @return string|null
756
     */
757
    public function loadRenditionContentLink($repositoryId, $documentId, $streamId)
758
    {
759
        $result = $this->getRepositoryUrlCache()->getObjectUrl($repositoryId, $documentId, Constants::SELECTOR_CONTENT);
760
        if ($result !== null) {
761
            $result->getQuery()->modify([Constants::PARAM_STREAM_ID => $streamId]);
762
            $result = (string) $result;
763
        }
764
        return $result;
765
    }
766
}
767