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.
Completed
Push — master ( 42c65a...a98f71 )
by
unknown
07:18
created

AbstractCmisObject   F

Complexity

Total Complexity 90

Size/Duplication

Total Lines 847
Duplicated Lines 1.3 %

Coupling/Cohesion

Components 1
Dependencies 23

Test Coverage

Coverage 4.36%

Importance

Changes 13
Bugs 6 Features 3
Metric Value
wmc 90
c 13
b 6
f 3
lcom 1
cbo 23
dl 11
loc 847
ccs 12
cts 275
cp 0.0436
rs 1.2394

48 Methods

Rating   Name   Duplication   Size   Complexity  
B initialize() 0 26 3
C initializeObjectData() 11 45 8
B initializeObjectDataProperties() 0 24 4
A initializeObjectDataPolicies() 0 11 3
A getMissingBaseProperties() 0 18 4
A getSession() 0 4 1
A getRepositoryId() 0 4 1
A getObjectType() 0 4 1
A getObjectFactory() 0 4 1
A getBinding() 0 4 1
A getCreationContext() 0 4 1
A getPropertyQueryName() 0 9 2
A delete() 0 4 1
B updateProperties() 0 44 5
A rename() 0 15 2
A getType() 0 4 1
A getBaseType() 0 9 2
A getBaseTypeId() 0 9 2
A getChangeToken() 0 4 1
A getCreatedBy() 0 4 1
A getCreationDate() 0 4 1
A getId() 0 4 1
A getLastModificationDate() 0 4 1
A getLastModifiedBy() 0 4 1
A getName() 0 4 1
A getDescription() 0 4 1
A getProperties() 0 4 1
A getProperty() 0 8 2
A getPropertyValue() 0 9 3
A getSecondaryTypes() 0 4 1
B findObjectType() 0 19 6
A getAllowableActions() 0 4 1
A hasAllowableAction() 0 9 3
A getRenditions() 0 4 1
A applyAcl() 0 8 1
A addAcl() 0 4 1
A removeAcl() 0 4 1
A setAcl() 0 8 1
A getAcl() 0 4 1
B getPermissionsForPrincipal() 0 22 6
A applyPolicies() 0 4 1
A getPolicies() 0 4 1
A removePolicy() 0 4 1
A getRelationships() 0 4 1
A getExtensions() 0 8 2
A getRefreshTimestamp() 0 4 1
A refresh() 0 23 1
A refreshIfOld() 0 6 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 AbstractCmisObject 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 AbstractCmisObject, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Dkd\PhpCmis\DataObjects;
3
4
/**
5
 * This file is part of php-cmis-lib.
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\CmisBindingInterface;
14
use Dkd\PhpCmis\CmisObject\CmisObjectInterface;
15
use Dkd\PhpCmis\Data\AceInterface;
16
use Dkd\PhpCmis\Data\AclInterface;
17
use Dkd\PhpCmis\Data\AllowableActionsInterface;
18
use Dkd\PhpCmis\Data\CmisExtensionElementInterface;
19
use Dkd\PhpCmis\Data\ObjectDataInterface;
20
use Dkd\PhpCmis\Data\ObjectIdInterface;
21
use Dkd\PhpCmis\Data\ObjectTypeInterface;
22
use Dkd\PhpCmis\Data\PolicyIdListInterface;
23
use Dkd\PhpCmis\Data\PolicyInterface;
24
use Dkd\PhpCmis\Data\PropertiesInterface;
25
use Dkd\PhpCmis\Data\PropertyInterface;
26
use Dkd\PhpCmis\Data\RelationshipInterface;
27
use Dkd\PhpCmis\Data\RenditionInterface;
28
use Dkd\PhpCmis\Data\SecondaryTypeInterface;
29
use Dkd\PhpCmis\Definitions\PropertyDefinitionInterface;
30
use Dkd\PhpCmis\Enum\AclPropagation;
31
use Dkd\PhpCmis\Enum\Action;
32
use Dkd\PhpCmis\Enum\BaseTypeId;
33
use Dkd\PhpCmis\Enum\ExtensionLevel;
34
use Dkd\PhpCmis\Enum\Updatability;
35
use Dkd\PhpCmis\Exception\CmisInvalidArgumentException;
36
use Dkd\PhpCmis\Exception\CmisObjectNotFoundException;
37
use Dkd\PhpCmis\Exception\IllegalStateException;
38
use Dkd\PhpCmis\ObjectFactoryInterface;
39
use Dkd\PhpCmis\OperationContextInterface;
40
use Dkd\PhpCmis\PropertyIds;
41
use Dkd\PhpCmis\SessionInterface;
42
43
abstract class AbstractCmisObject implements CmisObjectInterface
44
{
45
    /**
46
     * @var SessionInterface
47
     */
48
    protected $session;
49
50
    /**
51
     * @var ObjectTypeInterface
52
     */
53
    protected $objectType;
54
55
    /**
56
     * @var null|SecondaryTypeInterface[]
57
     */
58
    protected $secondaryTypes;
59
60
    /**
61
     * @var PropertyInterface[]
62
     */
63
    protected $properties = array();
64
65
    /**
66
     * @var AllowableActionsInterface|null
67
     */
68
    protected $allowableActions;
69
70
    /**
71
     * @var RenditionInterface[]
72
     */
73
    protected $renditions = array();
74
75
    /**
76
     * @var AclInterface|null
77
     */
78
    protected $acl;
79
80
    /**
81
     * @var PolicyInterface[]
82
     */
83
    protected $policies = array();
84
85
    /**
86
     * @var RelationshipInterface[]
87
     */
88
    protected $relationships = array();
89
90
    /**
91
     * A list that contains a list of <code>CmisExtensionElementInterface</code> identified by
92
     * <code>ExtensionLevel</code>. The key is the string representation of <code>ExtensionLevel</code> and the value
93
     * the array of <code>CmisExtensionElementInterface</code>
94
     *
95
     * @see ExtensionLevel
96
     * @see CmisExtensionElementInterface
97
     * @var array[]
98
     */
99
    protected $extensions = array();
100
101
    /**
102
     * @var OperationContextInterface
103
     */
104
    protected $creationContext;
105
106
    /**
107
     * @var integer
108
     */
109
    protected $refreshTimestamp = 0;
110
111
    /**
112
     * Initialize the CMIS Object
113
     *
114
     * @param SessionInterface $session
115
     * @param ObjectTypeInterface $objectType
116
     * @param OperationContextInterface $context
117
     * @param ObjectDataInterface|null $objectData
118
     */
119
    public function initialize(
120
        SessionInterface $session,
121
        ObjectTypeInterface $objectType,
122
        OperationContextInterface $context,
123
        ObjectDataInterface $objectData = null
124
    ) {
125
        if (count($this->getMissingBaseProperties($objectType->getPropertyDefinitions())) !== 0) {
126
            throw new CmisInvalidArgumentException(
127
                sprintf(
128
                    'Object type must have at least the base property definitions! '
129
                    . 'These property definitions are missing: %s',
130
                    implode(', ', PropertyIds::getBasePropertyKeys())
131
                )
132
            );
133
        };
134
135
        $this->session = $session;
136
        $this->objectType = $objectType;
137
        $this->secondaryTypes = null;
138
        $this->creationContext = clone $context;
139
        $this->refreshTimestamp = (integer) round(microtime(true) * 1000);
140
141
        if ($objectData !== null) {
142
            $this->initializeObjectData($objectData);
143
        }
144
    }
145
146
    /**
147
     * Handle initialization for objectData
148
     *
149
     * @param ObjectDataInterface $objectData
150
     */
151
    private function initializeObjectData(ObjectDataInterface $objectData)
152
    {
153
        // handle properties
154
        if ($objectData->getProperties() !== null) {
155
            $this->initializeObjectDataProperties($objectData->getProperties());
156
        }
157
158
        // handle allowable actions
159 View Code Duplication
        if ($objectData->getAllowableActions() !== null) {
160
            $this->allowableActions = $objectData->getAllowableActions();
161
            $this->extensions[(string) ExtensionLevel::cast(
162
                ExtensionLevel::ALLOWABLE_ACTIONS
163
            )] = $objectData->getAllowableActions()->getExtensions();
164
        }
165
166
        // handle renditions
167
        foreach ($objectData->getRenditions() as $rendition) {
168
            $this->renditions[] = $this->getObjectFactory()->convertRendition($this->getId(), $rendition);
169
        }
170
171
        // handle ACL
172 View Code Duplication
        if ($objectData->getAcl() !== null) {
173
            $this->acl = $objectData->getAcl();
174
            $this->extensions[(string) ExtensionLevel::cast(ExtensionLevel::ACL)] = $objectData->getAcl(
175
            )->getExtensions();
176
        }
177
178
        // handle policies
179
        if ($objectData->getPolicyIds() !== null) {
180
            $this->initializeObjectDataPolicies($objectData->getPolicyIds());
181
        }
182
183
        // handle relationships
184
        foreach ($objectData->getRelationships() as $relationshipData) {
185
            $relationship = $this->getObjectFactory()->convertObject(
186
                $relationshipData,
187
                $this->getCreationContext()
188
            );
189
            if ($relationship instanceof RelationshipInterface) {
190
                $this->relationships[] = $relationship;
191
            }
192
        }
193
194
        $this->extensions[(string) ExtensionLevel::OBJECT] = $objectData->getExtensions();
195
    }
196
197
    /**
198
     * Handle initialization of properties from the object data
199
     *
200
     * @param PropertiesInterface $properties
201
     */
202
    private function initializeObjectDataProperties(PropertiesInterface $properties)
203
    {
204
        // get secondary types
205
        $propertyList = $properties->getProperties();
206
        if (isset($propertyList[PropertyIds::SECONDARY_OBJECT_TYPE_IDS])) {
207
            $this->secondaryTypes = array();
208
            foreach ($propertyList[PropertyIds::SECONDARY_OBJECT_TYPE_IDS]->getValues() as $secondaryTypeId) {
209
                $type = $this->getSession()->getTypeDefinition($secondaryTypeId);
210
                if ($type instanceof SecondaryTypeInterface) {
211
                    $this->secondaryTypes[] = $type;
212
                }
213
            }
214
        }
215
216
        $this->properties = $this->getObjectFactory()->convertPropertiesDataToPropertyList(
217
            $this->getObjectType(),
218
            (array) $this->getSecondaryTypes(),
219
            $properties
220
        );
221
222
        $this->extensions[(string) ExtensionLevel::cast(
223
            ExtensionLevel::PROPERTIES
224
        )] = $properties->getExtensions();
225
    }
226
227
    /**
228
     * Handle initialization of policies from the object data
229
     *
230
     * @param PolicyIdListInterface $policies
231
     */
232
    private function initializeObjectDataPolicies(PolicyIdListInterface $policies)
233
    {
234
        foreach ($policies->getPolicyIds() as $policyId) {
235
            $policy = $this->getSession()->getObject($this->getSession()->createObjectId($policyId));
236
            if ($policy instanceof PolicyInterface) {
237
                $this->policies[] = $policy;
238
            }
239
        }
240
241
        $this->extensions[(string) ExtensionLevel::POLICIES] = $policies->getExtensions();
242
    }
243
244
245
    /**
246
     * Returns a list of missing property keys
247
     *
248
     * @param PropertyDefinitionInterface[]|null $properties
249
     * @return array
250
     */
251 4
    protected function getMissingBaseProperties(array $properties = null)
252
    {
253 4
        $basePropertyKeys = PropertyIds::getBasePropertyKeys();
254
255 4
        if ($properties === null) {
256 1
            return $basePropertyKeys;
257
        }
258
259 3
        foreach ($properties as $property) {
260 2
            $propertyId = $property->getId();
261 2
            $basePropertyKey = array_search($propertyId, $basePropertyKeys);
262 2
            if ($basePropertyKey !== false) {
263 2
                unset($basePropertyKeys[$basePropertyKey]);
264 2
            }
265 3
        }
266
267 3
        return $basePropertyKeys;
268
    }
269
270
    /**
271
     * Returns the session object
272
     *
273
     * @return SessionInterface
274
     */
275
    protected function getSession()
276
    {
277
        return $this->session;
278
    }
279
280
    /**
281
     * Returns the repository id
282
     *
283
     * @return string
284
     */
285
    protected function getRepositoryId()
286
    {
287
        return $this->getSession()->getRepositoryInfo()->getId();
288
    }
289
290
    /**
291
     * Returns the object type
292
     *
293
     * @return ObjectTypeInterface
294
     */
295
    protected function getObjectType()
296
    {
297
        return $this->objectType;
298
    }
299
300
    /**
301
     * Returns the object factory.
302
     *
303
     * @return ObjectFactoryInterface
304
     */
305
    protected function getObjectFactory()
306
    {
307
        return $this->getSession()->getObjectFactory();
308
    }
309
310
    /**
311
     * Get the binding object
312
     *
313
     * @return CmisBindingInterface
314
     */
315
    protected function getBinding()
316
    {
317
        return $this->getSession()->getBinding();
318
    }
319
320
    /**
321
     * Returns the OperationContext that was used to create this object.
322
     *
323
     * @return OperationContextInterface
324
     */
325
    protected function getCreationContext()
326
    {
327
        return $this->creationContext;
328
    }
329
330
    /**
331
     * Returns the query name of a property.
332
     *
333
     * @param string $propertyId
334
     * @return null|string
335
     */
336
    protected function getPropertyQueryName($propertyId)
337
    {
338
        $propertyDefinition = $this->getObjectType()->getPropertyDefinition($propertyId);
339
        if ($propertyDefinition === null) {
340
            return null;
341
        }
342
343
        return $propertyDefinition->getQueryName();
344
    }
345
346
    /**
347
     * Delete this object
348
     *
349
     * @param boolean $allVersions indicates if all versions of the object should be deleted
350
     */
351
    public function delete($allVersions = true)
352
    {
353
        $this->getSession()->delete($this, $allVersions);
354
    }
355
356
    /**
357
     * Updates the provided properties. If the repository created a new object, for example a new version,
358
     * the object ID of the new object is returned. Otherwise the object ID of the current object is returned.
359
     *
360
     * @param mixed[] $properties the properties to update
361
     * @param boolean $refresh <code>true</code> if this object should be refresh after the update,
362
     *      <code>false</code> if not
363
     * @return CmisObjectInterface|null the object ID of the updated object - can return <code>null</code> in case
364
     *      of a repository failure
365
     */
366
    public function updateProperties(array $properties, $refresh = true)
367
    {
368
        if (empty($properties)) {
369
            throw new CmisInvalidArgumentException('Properties must not be empty!');
370
        }
371
372
        $objectId = $this->getId();
373
        $changeToken = $this->getChangeToken();
374
375
        $updatability = array();
376
        $updatability[] = Updatability::cast(Updatability::READWRITE);
377
        if ((boolean) $this->getPropertyValue(PropertyIds::IS_VERSION_SERIES_CHECKED_OUT) === true) {
378
            $updatability[] = Updatability::cast(Updatability::WHENCHECKEDOUT);
379
        }
380
381
        $newObjectId = $objectId;
382
        $this->getBinding()->getObjectService()->updateProperties(
383
            $this->getRepositoryId(),
384
            $newObjectId,
385
            $this->getObjectFactory()->convertProperties(
386
                $properties,
387
                $this->getObjectType(),
388
                (array) $this->getSecondaryTypes(),
389
                $updatability
390
            ),
391
            $changeToken
392
        );
393
394
        // remove the object from the cache, it has been changed
395
        $this->getSession()->removeObjectFromCache($this->getSession()->createObjectId($objectId));
396
397
        if ($refresh === true) {
398
            $this->refresh();
399
        }
400
401
        if ($newObjectId === null) {
402
            return null;
403
        }
404
405
        return $this->getSession()->getObject(
406
            $this->getSession()->createObjectId($newObjectId),
407
            $this->getCreationContext()
408
        );
409
    }
410
411
    /**
412
     * Renames this object (changes the value of cmis:name).
413
     * If the repository created a new object, for example a new version, the object id of the
414
     * new object is returned. Otherwise the object id of the current object is returned.
415
     *
416
     * @param string $newName the new name, not <code>null</code> or empty
417
     * @param boolean $refresh <code>true</code> if this object should be refresh after the update,
418
     *     <code>false</code> if not
419
     * @return CmisObjectInterface|null the object ID of the updated object - can return <code>null</code> in case of
420
     *     a repository failure
421
     */
422
    public function rename($newName, $refresh = true)
423
    {
424
        if (empty($newName)) {
425
            throw new CmisInvalidArgumentException('New name must not be empty!');
426
        }
427
428
        $properties = array(
429
            PropertyIds::NAME,
430
            $newName
431
        );
432
433
        $object = $this->updateProperties($properties, $refresh);
434
435
        return $object;
436
    }
437
438
    /**
439
     * Returns the type of this CMIS object (object type identified by <code>cmis:objectTypeId</code>).
440
     *
441
     * @return ObjectTypeInterface the type of the object or <code>null</code> if the property
442
     *         <code>cmis:objectTypeId</code> hasn't been requested or hasn't been provided by the repository
443
     */
444
    public function getType()
445
    {
446
        return $this->getObjectType();
447
    }
448
449
    /**
450
     * Returns the base type of this CMIS object (object type identified by cmis:baseTypeId).
451
     *
452
     * @return ObjectTypeInterface the base type of the object or <code>null</code> if the property cmis:baseTypeId
453
     *         hasn't been requested or hasn't been provided by the repository
454
     */
455
    public function getBaseType()
456
    {
457
        $baseType = $this->getBaseTypeId();
458
        if ($baseType === null) {
459
            return null;
460
        }
461
462
        return $this->getSession()->getTypeDefinition((string) $baseType);
463
    }
464
465
    /**
466
     * Returns the base type of this CMIS object (object type identified by cmis:baseTypeId).
467
     *
468
     * @return BaseTypeId|null the base type of the object or <code>null</code> if the property
469
     *         cmis:baseTypeId hasn't been requested or hasn't been provided by the repository
470
     */
471
    public function getBaseTypeId()
472
    {
473
        $baseTypeProperty = $this->getProperty(PropertyIds::BASE_TYPE_ID);
474
        if ($baseTypeProperty === null) {
475
            return null;
476
        }
477
478
        return BaseTypeId::cast($baseTypeProperty->getFirstValue());
479
    }
480
481
    /**
482
     * Returns the change token (CMIS property cmis:changeToken).
483
     *
484
     * @return string the change token of the object or <code>null</code> if the property hasn't been requested or
485
     *         hasn't been provided or isn't supported by the repository
486
     */
487
    public function getChangeToken()
488
    {
489
        return $this->getPropertyValue(PropertyIds::CHANGE_TOKEN);
490
    }
491
492
    /**
493
     * Returns the user who created this CMIS object (CMIS property cmis:createdBy).
494
     *
495
     * @return string the creator of the object or <code>null</code> if the property hasn't been requested or hasn't
496
     *         been provided by the repository
497
     */
498
    public function getCreatedBy()
499
    {
500
        return $this->getPropertyValue(PropertyIds::CREATED_BY);
501
    }
502
503
    /**
504
     * Returns the timestamp when this CMIS object has been created (CMIS property cmis:creationDate).
505
     *
506
     * @return \DateTime|null the creation time of the object or <code>null</code> if the property hasn't been
507
     *         requested or hasn't been provided by the repository
508
     */
509
    public function getCreationDate()
510
    {
511
        return $this->getPropertyValue(PropertyIds::CREATION_DATE);
512
    }
513
514
    /**
515
     * Returns the object ID
516
     *
517
     * @return string
518
     */
519
    public function getId()
520
    {
521
        return $this->getPropertyValue(PropertyIds::OBJECT_ID);
522
    }
523
524
    /**
525
     * Returns the timestamp when this CMIS object has been modified (CMIS property cmis:lastModificationDate).
526
     *
527
     * @return \DateTime|null the last modification date of the object or <code>null</code> if the property hasn't been
528
     *         requested or hasn't been provided by the repository
529
     */
530
    public function getLastModificationDate()
531
    {
532
        return $this->getPropertyValue(PropertyIds::LAST_MODIFICATION_DATE);
533
    }
534
535
    /**
536
     * Returns the user who modified this CMIS object (CMIS property cmis:lastModifiedBy).
537
     *
538
     * @return string|null the last modifier of the object or <code>null</code> if the property hasn't
539
     *         been requested or hasn't been provided by the repository
540
     */
541
    public function getLastModifiedBy()
542
    {
543
        return $this->getPropertyValue(PropertyIds::LAST_MODIFIED_BY);
544
    }
545
546
    /**
547
     * Returns the name of this CMIS object (CMIS property cmis:name).
548
     *
549
     * @return string|null the name of the object or <code>null</code> if the property hasn't been requested
550
     *         or hasn't been provided by the repository
551
     */
552
    public function getName()
553
    {
554
        return $this->getPropertyValue(PropertyIds::NAME);
555
    }
556
557
    /**
558
     * Returns the description of this CMIS object (CMIS property cmis:description).
559
     *
560
     * @return string|null the description of the object or <code>null</code> if the property hasn't been requested,
561
     *         hasn't been provided by the repository, or the property value isn't set
562
     */
563
    public function getDescription()
564
    {
565
        return $this->getPropertyValue(PropertyIds::DESCRIPTION);
566
    }
567
568
    /**
569
     * Returns a list of all available CMIS properties.
570
     *
571
     * @return PropertyInterface[] all available CMIS properties
572
     */
573
    public function getProperties()
574
    {
575
        return $this->properties;
576
    }
577
578
    /**
579
     * Returns a property.
580
     *
581
     * @param string $id the ID of the property
582
     * @return PropertyInterface|null the property or <code>null</code> if the property hasn't been requested or
583
     *         hasn't been provided by the repository
584
     */
585
    public function getProperty($id)
586
    {
587
        if (!isset($this->properties[$id])) {
588
            return null;
589
        }
590
591
        return $this->properties[$id];
592
    }
593
594
    /**
595
     * Returns the value of a property.
596
     *
597
     * @param string $id the ID of the property
598
     * @return mixed the property value or <code>null</code> if the property hasn't been requested,
599
     *         hasn't been provided by the repository, or the property value isn't set
600
     */
601
    public function getPropertyValue($id)
602
    {
603
        $property = $this->getProperty($id);
604
        if ($property === null) {
605
            return null;
606
        }
607
608
        return $property->isMultiValued() ? $property->getValues() : $property->getFirstValue();
609
    }
610
611
    /**
612
     * Returns the secondary types of this CMIS object (object types identified by cmis:secondaryObjectTypeIds).
613
     *
614
     * @return SecondaryTypeInterface[]|null the secondary types of the object or <code>null</code> if the property
615
     *         cmis:secondaryObjectTypeIds hasn't been requested or hasn't been provided by the repository
616
     */
617
    public function getSecondaryTypes()
618
    {
619
        return $this->secondaryTypes;
620
    }
621
622
    /**
623
     * Returns a list of primary and secondary object types that define the given property.
624
     *
625
     * @param string $id the ID of the property
626
     * @return ObjectTypeInterface[]|null a list of object types that define the given property or <code>null</code>
627
     *         if the property could not be found in the object types that are attached to this object
628
     */
629
    public function findObjectType($id)
630
    {
631
        $result = array();
632
633
        if ($this->getObjectType()->getPropertyDefinition($id) !== null) {
634
            $result[] = $this->getObjectType();
635
        }
636
637
        $secondaryTypes = $this->getSecondaryTypes();
638
        if ($secondaryTypes !== null) {
639
            foreach ($secondaryTypes as $secondaryType) {
640
                if ($secondaryType->getPropertyDefinition($id) !== null) {
641
                    $result[] = $secondaryType;
642
                }
643
            }
644
        }
645
646
        return empty($result) ? null : $result;
647
    }
648
649
    /**
650
     * Returns the allowable actions if they have been fetched for this object.
651
     *
652
     * @return AllowableActionsInterface|null
653
     */
654
    public function getAllowableActions()
655
    {
656
        return $this->allowableActions;
657
    }
658
659
    /**
660
     * Checks if the given action is an allowed action for the object
661
     *
662
     * @param Action $action
663
     * @return boolean
664
     */
665
    public function hasAllowableAction(Action $action)
666
    {
667
        $currentAllowableActions = $this->getAllowableActions();
668
        if ($currentAllowableActions === null || count($currentAllowableActions->getAllowableActions()) === 0) {
669
            throw new IllegalStateException('Allowable Actions are not available!');
670
        }
671
672
        return in_array($action, $currentAllowableActions->getAllowableActions(), false);
673
    }
674
675
    /**
676
     * Returns the renditions if they have been fetched for this object.
677
     *
678
     * @return RenditionInterface[]
679
     */
680
    public function getRenditions()
681
    {
682
        return $this->renditions;
683
    }
684
685
    /**
686
     * Adds and removes ACEs to the object and refreshes this object afterwards.
687
     *
688
     * @param AceInterface[] $addAces
689
     * @param AceInterface[] $removeAces
690
     * @param AclPropagation $aclPropagation
691
     * @return AclInterface the new ACL of this object
692
     */
693
    public function applyAcl(array $addAces, array $removeAces, AclPropagation $aclPropagation)
694
    {
695
        $result = $this->getSession()->applyAcl($this, $addAces, $removeAces, $aclPropagation);
696
697
        $this->refresh();
698
699
        return $result;
700
    }
701
702
    /**
703
     * Adds ACEs to the object and refreshes this object afterwards.
704
     *
705
     * @param AceInterface[] $addAces
706
     * @param AclPropagation $aclPropagation
707
     * @return AclInterface the new ACL of this object
708
     */
709
    public function addAcl(array $addAces, AclPropagation $aclPropagation)
710
    {
711
        return $this->applyAcl($addAces, array(), $aclPropagation);
712
    }
713
714
    /**
715
     * Removes ACEs to the object and refreshes this object afterwards.
716
     *
717
     * @param array $removeAces
718
     * @param AclPropagation $aclPropagation
719
     * @return AclInterface the new ACL of this object
720
     */
721
    public function removeAcl(array $removeAces, AclPropagation $aclPropagation)
722
    {
723
        return $this->applyAcl(array(), $removeAces, $aclPropagation);
724
    }
725
726
    /**
727
     * Removes the direct ACE of this object, sets the provided ACEs to the object and refreshes this object afterwards.
728
     *
729
     * @param AceInterface[] $aces
730
     * @return AclInterface
731
     */
732
    public function setAcl(array $aces)
733
    {
734
        $result = $this->getSession()->setAcl($this, $aces);
735
736
        $this->refresh();
737
738
        return $result;
739
    }
740
741
    /**
742
     * Returns the ACL if it has been fetched for this object.
743
     *
744
     * @return AclInterface|null
745
     */
746
    public function getAcl()
747
    {
748
        return $this->acl;
749
    }
750
751
    /**
752
     * Returns all permissions for the given principal from the ACL.
753
     *
754
     * @param string $principalId the principal ID
755
     * @return string[] the set of permissions for this user, or an empty set if principal is not in the ACL
756
     * @throws IllegalStateException if the ACL hasn't been fetched or provided by the repository
757
     */
758
    public function getPermissionsForPrincipal($principalId)
759
    {
760
        if (empty($principalId)) {
761
            throw new IllegalStateException('Principal ID must be set!');
762
        }
763
764
        $currentAcl = $this->getAcl();
765
766
        if ($currentAcl === null) {
767
            throw new IllegalStateException('ACLs are not available');
768
        }
769
770
        $result = array();
771
772
        foreach ($currentAcl->getAces() as $ace) {
773
            if ($principalId === $ace->getPrincipalId() && count($ace->getPermissions()) > 0) {
774
                $result = array_merge($result, $ace->getPermissions());
775
            }
776
        }
777
778
        return $result;
779
    }
780
781
    /**
782
     * Applies the provided policies and refreshes this object afterwards.
783
     *
784
     * @param ObjectIdInterface[] $policyIds
785
     */
786
    public function applyPolicies(array $policyIds)
787
    {
788
        $this->getSession()->applyPolicies($this, $policyIds);
789
    }
790
791
    /**
792
     * Returns the applied policies if they have been fetched for this object.
793
     *
794
     * @return PolicyInterface[]
795
     */
796
    public function getPolicies()
797
    {
798
        $this->policies;
799
    }
800
801
    /**
802
     * Removes the provided policies and refreshes this object afterwards.
803
     *
804
     * @param ObjectIdInterface[] $policyIds
805
     */
806
    public function removePolicy(array $policyIds)
807
    {
808
        $this->getSession()->removePolicy($this, $policyIds);
809
    }
810
811
    /**
812
     * Returns the relationships if they have been fetched for this object.
813
     *
814
     * @return RelationshipInterface[]
815
     */
816
    public function getRelationships()
817
    {
818
        return $this->relationships;
819
    }
820
821
    /**
822
     * Returns the extensions for the given level.
823
     *
824
     * @param ExtensionLevel $level the level
825
     * @return array[]|null A list of <code>CmisExtensionElementInterface</code> at the requested level or
826
     *      <code>null</code> if there are no extensions for the requested level
827
     * @see CmisExtensionElementInterface
828
     */
829
    public function getExtensions(ExtensionLevel $level)
830
    {
831
        if (!isset($this->extensions[(string) $level])) {
832
            return null;
833
        }
834
835
        return $this->extensions[(string) $level];
836
    }
837
838
    /**
839
     * Returns the timestamp of the last refresh.
840
     *
841
     * @return integer returns the Java-style milliseconds UNIX timestamp of last refresh
842
     */
843
    public function getRefreshTimestamp()
844
    {
845
        return $this->refreshTimestamp;
846
    }
847
848
    /**
849
     * Reloads this object from the repository.
850
     *
851
     * @throws CmisObjectNotFoundException - if the object doesn't exist anymore in the repository
852
     */
853
    public function refresh()
854
    {
855
        $operationContext = $this->getCreationContext();
856
857
        $objectData = $this->getSession()->getBinding()->getObjectService()->getObject(
858
            $this->getRepositoryId(),
859
            $this->getId(),
860
            $operationContext->getQueryFilterString(),
861
            $operationContext->isIncludeAllowableActions(),
862
            $operationContext->getIncludeRelationships(),
863
            $operationContext->getRenditionFilterString(),
864
            $operationContext->isIncludePolicies(),
865
            $operationContext->isIncludeAcls(),
866
            null
867
        );
868
869
        $this->initialize(
870
            $this->getSession(),
871
            $this->getSession()->getTypeDefinition($this->getObjectType()->getId()),
872
            $this->creationContext,
873
            $objectData
874
        );
875
    }
876
877
    /**
878
     * Reloads the data from the repository if the last refresh did not occur within durationInMillis.
879
     *
880
     * @param integer $durationInMillis
881
     * @throws CmisObjectNotFoundException - if the object doesn't exist anymore in the repository
882
     */
883
    public function refreshIfOld($durationInMillis = 0)
884
    {
885
        if ($this->getRefreshTimestamp() < ((round(microtime(true) * 1000)) - (integer) $durationInMillis)) {
886
            $this->refresh();
887
        }
888
    }
889
}
890