Completed
Push — ezp-30616 ( 9239a0...7bf8e8 )
by
unknown
57:53 queued 37:56
created

ContentService::updateContent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14

Duplication

Lines 14
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 14
loc 14
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * ContentService class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\SignalSlot;
10
11
use eZ\Publish\API\Repository\ContentService as ContentServiceInterface;
12
use eZ\Publish\API\Repository\Values\Content\ContentCreateStruct;
13
use eZ\Publish\API\Repository\Values\Content\ContentUpdateStruct;
14
use eZ\Publish\API\Repository\Values\Content\ContentMetadataUpdateStruct;
15
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
16
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
17
use eZ\Publish\API\Repository\Values\Content\VersionInfo;
18
use eZ\Publish\API\Repository\Values\Content\TranslationInfo;
19
use eZ\Publish\API\Repository\Values\Content\TranslationValues;
20
use eZ\Publish\API\Repository\Values\ContentType\ContentType;
21
use eZ\Publish\API\Repository\Values\User\User;
22
use eZ\Publish\Core\SignalSlot\Signal\ContentService\CreateContentSignal;
23
use eZ\Publish\Core\SignalSlot\Signal\ContentService\DeleteTranslationSignal;
24
use eZ\Publish\Core\SignalSlot\Signal\ContentService\HideContentSignal;
25
use eZ\Publish\Core\SignalSlot\Signal\ContentService\RemoveTranslationSignal;
26
use eZ\Publish\Core\SignalSlot\Signal\ContentService\RevealContentSignal;
27
use eZ\Publish\Core\SignalSlot\Signal\ContentService\UpdateContentMetadataSignal;
28
use eZ\Publish\Core\SignalSlot\Signal\ContentService\DeleteContentSignal;
29
use eZ\Publish\Core\SignalSlot\Signal\ContentService\CreateContentDraftSignal;
30
use eZ\Publish\Core\SignalSlot\Signal\ContentService\TranslateVersionSignal;
31
use eZ\Publish\Core\SignalSlot\Signal\ContentService\UpdateContentSignal;
32
use eZ\Publish\Core\SignalSlot\Signal\ContentService\PublishVersionSignal;
33
use eZ\Publish\Core\SignalSlot\Signal\ContentService\DeleteVersionSignal;
34
use eZ\Publish\Core\SignalSlot\Signal\ContentService\CopyContentSignal;
35
use eZ\Publish\Core\SignalSlot\Signal\ContentService\AddRelationSignal;
36
use eZ\Publish\Core\SignalSlot\Signal\ContentService\DeleteRelationSignal;
37
use eZ\Publish\Core\SignalSlot\Signal\ContentService\AddTranslationInfoSignal;
38
39
/**
40
 * ContentService class.
41
 */
42
class ContentService implements ContentServiceInterface
43
{
44
    /**
45
     * Aggregated service.
46
     *
47
     * @var \eZ\Publish\API\Repository\ContentService
48
     */
49
    protected $service;
50
51
    /**
52
     * SignalDispatcher.
53
     *
54
     * @var \eZ\Publish\Core\SignalSlot\SignalDispatcher
55
     */
56
    protected $signalDispatcher;
57
58
    /**
59
     * Constructor.
60
     *
61
     * Construct service object from aggregated service and signal
62
     * dispatcher
63
     *
64
     * @param \eZ\Publish\API\Repository\ContentService $service
65
     * @param \eZ\Publish\Core\SignalSlot\SignalDispatcher $signalDispatcher
66
     */
67
    public function __construct(ContentServiceInterface $service, SignalDispatcher $signalDispatcher)
68
    {
69
        $this->service = $service;
70
        $this->signalDispatcher = $signalDispatcher;
71
    }
72
73
    /**
74
     * Loads a content info object.
75
     *
76
     * To load fields use loadContent
77
     *
78
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content
79
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the content with the given id does not exist
80
     *
81
     * @param int $contentId
82
     *
83
     * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo
84
     */
85
    public function loadContentInfo($contentId)
86
    {
87
        return $this->service->loadContentInfo($contentId);
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function loadContentInfoList(array $contentIds): iterable
94
    {
95
        return $this->service->loadContentInfoList($contentIds);
96
    }
97
98
    /**
99
     * Loads a content info object for the given remoteId.
100
     *
101
     * To load fields use loadContent
102
     *
103
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content
104
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the content with the given remote id does not exist
105
     *
106
     * @param string $remoteId
107
     *
108
     * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo
109
     */
110
    public function loadContentInfoByRemoteId($remoteId)
111
    {
112
        return $this->service->loadContentInfoByRemoteId($remoteId);
113
    }
114
115
    /**
116
     * Loads a version info of the given content object.
117
     *
118
     * If no version number is given, the method returns the current version
119
     *
120
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the version with the given number does not exist
121
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
122
     *
123
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
124
     * @param int $versionNo the version number. If not given the current version is returned.
125
     *
126
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo
127
     */
128
    public function loadVersionInfo(ContentInfo $contentInfo, $versionNo = null)
129
    {
130
        return $this->service->loadVersionInfo($contentInfo, $versionNo);
131
    }
132
133
    /**
134
     * Loads a version info of the given content object id.
135
     *
136
     * If no version number is given, the method returns the current version
137
     *
138
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the version with the given number does not exist
139
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
140
     *
141
     * @param mixed $contentId
142
     * @param int $versionNo the version number. If not given the current version is returned.
143
     *
144
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo
145
     */
146
    public function loadVersionInfoById($contentId, $versionNo = null)
147
    {
148
        return $this->service->loadVersionInfoById($contentId, $versionNo);
149
    }
150
151
    /**
152
     * Loads content in a version for the given content info object.
153
     *
154
     * If no version number is given, the method returns the current version
155
     *
156
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if version with the given number does not exist
157
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
158
     *
159
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
160
     * @param array $languages A language filter for fields. If not given all languages are returned
161
     * @param int $versionNo the version number. If not given the current version is returned
162
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
163
     *
164
     * @return \eZ\Publish\API\Repository\Values\Content\Content
165
     */
166
    public function loadContentByContentInfo(ContentInfo $contentInfo, array $languages = null, $versionNo = null, $useAlwaysAvailable = true)
167
    {
168
        return $this->service->loadContentByContentInfo($contentInfo, $languages, $versionNo, $useAlwaysAvailable);
169
    }
170
171
    /**
172
     * Loads content in the version given by version info.
173
     *
174
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
175
     *
176
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
177
     * @param array $languages A language filter for fields. If not given all languages are returned
178
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
179
     *
180
     * @return \eZ\Publish\API\Repository\Values\Content\Content
181
     */
182
    public function loadContentByVersionInfo(VersionInfo $versionInfo, array $languages = null, $useAlwaysAvailable = true)
183
    {
184
        return $this->service->loadContentByVersionInfo($versionInfo, $languages, $useAlwaysAvailable);
185
    }
186
187
    /**
188
     * Loads content in a version of the given content object.
189
     *
190
     * If no version number is given, the method returns the current version
191
     *
192
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content or version with the given id and languages does not exist
193
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
194
     *
195
     * @param int $contentId
196
     * @param array $languages A language filter for fields. If not given all languages are returned
197
     * @param int $versionNo the version number. If not given the current version is returned
198
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
199
     *
200
     * @return \eZ\Publish\API\Repository\Values\Content\Content
201
     */
202
    public function loadContent($contentId, array $languages = null, $versionNo = null, $useAlwaysAvailable = true)
203
    {
204
        return $this->service->loadContent($contentId, $languages, $versionNo, $useAlwaysAvailable);
205
    }
206
207
    /**
208
     * Loads content in a version for the content object reference by the given remote id.
209
     *
210
     * If no version is given, the method returns the current version
211
     *
212
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the content or version with the given remote id does not exist
213
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
214
     *
215
     * @param string $remoteId
216
     * @param array $languages A language filter for fields. If not given all languages are returned
217
     * @param int $versionNo the version number. If not given the current version is returned
218
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
219
     *
220
     * @return \eZ\Publish\API\Repository\Values\Content\Content
221
     */
222
    public function loadContentByRemoteId($remoteId, array $languages = null, $versionNo = null, $useAlwaysAvailable = true)
223
    {
224
        return $this->service->loadContentByRemoteId($remoteId, $languages, $versionNo, $useAlwaysAvailable);
225
    }
226
227
    /**
228
     * Creates a new content draft assigned to the authenticated user.
229
     *
230
     * If a different userId is given in $contentCreateStruct it is assigned to the given user
231
     * but this required special rights for the authenticated user
232
     * (this is useful for content staging where the transfer process does not
233
     * have to authenticate with the user which created the content object in the source server).
234
     * The user has to publish the draft if it should be visible.
235
     * In 4.x at least one location has to be provided in the location creation array.
236
     *
237
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to create the content in the given location
238
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if there is a provided remoteId which exists in the system
239
     *                                                                        or there is no location provided (4.x) or multiple locations
240
     *                                                                        are under the same parent or if the a field value is not accepted by the field type
241
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $contentCreateStruct is not valid
242
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is missing or is set to an empty value
243
     *
244
     * @param \eZ\Publish\API\Repository\Values\Content\ContentCreateStruct $contentCreateStruct
245
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct[] $locationCreateStructs For each location parent under which a location should be created for the content
246
     *
247
     * @return \eZ\Publish\API\Repository\Values\Content\Content - the newly created content draft
248
     */
249
    public function createContent(ContentCreateStruct $contentCreateStruct, array $locationCreateStructs = array())
250
    {
251
        $returnValue = $this->service->createContent($contentCreateStruct, $locationCreateStructs);
252
        $this->signalDispatcher->emit(
253
            new CreateContentSignal(
254
                array(
255
                    'contentId' => $returnValue->getVersionInfo()->getContentInfo()->id,
256
                    'versionNo' => $returnValue->getVersionInfo()->versionNo,
257
                )
258
            )
259
        );
260
261
        return $returnValue;
262
    }
263
264
    /**
265
     * Updates the metadata.
266
     *
267
     * (see {@link ContentMetadataUpdateStruct}) of a content object - to update fields use updateContent
268
     *
269
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to update the content meta data
270
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the remoteId in $contentMetadataUpdateStruct is set but already exists
271
     *
272
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
273
     * @param \eZ\Publish\API\Repository\Values\Content\ContentMetadataUpdateStruct $contentMetadataUpdateStruct
274
     *
275
     * @return \eZ\Publish\API\Repository\Values\Content\Content the content with the updated attributes
276
     */
277
    public function updateContentMetadata(ContentInfo $contentInfo, ContentMetadataUpdateStruct $contentMetadataUpdateStruct)
278
    {
279
        $returnValue = $this->service->updateContentMetadata($contentInfo, $contentMetadataUpdateStruct);
280
        $this->signalDispatcher->emit(
281
            new UpdateContentMetadataSignal(
282
                array(
283
                    'contentId' => $contentInfo->id,
284
                )
285
            )
286
        );
287
288
        return $returnValue;
289
    }
290
291
    /**
292
     * Deletes a content object including all its versions and locations including their subtrees.
293
     *
294
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to delete the content (in one of the locations of the given content object)
295
     *
296
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
297
     *
298
     * @return mixed[] Affected Location Id's
299
     */
300
    public function deleteContent(ContentInfo $contentInfo)
301
    {
302
        $returnValue = $this->service->deleteContent($contentInfo);
303
        $this->signalDispatcher->emit(
304
            new DeleteContentSignal(
305
                array(
306
                    'contentId' => $contentInfo->id,
307
                    'affectedLocationIds' => $returnValue,
308
                )
309
            )
310
        );
311
312
        return $returnValue;
313
    }
314
315
    /**
316
     * Creates a draft from a published or archived version.
317
     *
318
     * If no version is given, the current published version is used.
319
     * 4.x: The draft is created with the initialLanguage code of the source version or if not present with the main language.
320
     * It can be changed on updating the version.
321
     *
322
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to create the draft
323
     *
324
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
325
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
326
     * @param \eZ\Publish\API\Repository\Values\User\User $user if set given user is used to create the draft - otherwise the current user is used
327
     *
328
     * @return \eZ\Publish\API\Repository\Values\Content\Content - the newly created content draft
329
     */
330
    public function createContentDraft(ContentInfo $contentInfo, VersionInfo $versionInfo = null, User $user = null)
331
    {
332
        $returnValue = $this->service->createContentDraft($contentInfo, $versionInfo, $user);
333
        $this->signalDispatcher->emit(
334
            new CreateContentDraftSignal(
335
                array(
336
                    'contentId' => $contentInfo->id,
337
                    'versionNo' => ($versionInfo !== null ? $versionInfo->versionNo : null),
338
                    'newVersionNo' => $returnValue->getVersionInfo()->versionNo,
339
                    'userId' => ($user !== null ? $user->id : null),
340
                )
341
            )
342
        );
343
344
        return $returnValue;
345
    }
346
347
    /**
348
     * Loads drafts for a user.
349
     *
350
     * If no user is given the drafts for the authenticated user a returned
351
     *
352
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load the draft list
353
     *
354
     * @param \eZ\Publish\API\Repository\Values\User\User $user
355
     *
356
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo[] the drafts ({@link VersionInfo}) owned by the given user
357
     */
358
    public function loadContentDrafts(User $user = null)
359
    {
360
        return $this->service->loadContentDrafts($user);
361
    }
362
363
    /**
364
     * Translate a version.
365
     *
366
     * updates the destination version given in $translationInfo with the provided translated fields in $translationValues
367
     *
368
     * @example Examples/translation_5x.php
369
     *
370
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to update this version
371
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the given destination version is not a draft
372
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is set to an empty value
373
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $translationValues is not valid
374
     *
375
     * @param \eZ\Publish\API\Repository\Values\Content\TranslationInfo $translationInfo
376
     * @param \eZ\Publish\API\Repository\Values\Content\TranslationValues $translationValues
377
     * @param \eZ\Publish\API\Repository\Values\User\User $user If set, this user is taken as modifier of the version
378
     *
379
     * @return \eZ\Publish\API\Repository\Values\Content\Content the content draft with the translated fields
380
     *
381
     * @since 5.0
382
     */
383
    public function translateVersion(TranslationInfo $translationInfo, TranslationValues $translationValues, User $user = null)
384
    {
385
        $returnValue = $this->service->translateVersion($translationInfo, $translationValues, $user);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface eZ\Publish\API\Repository\ContentService as the method translateVersion() does only exist in the following implementations of said interface: eZ\Publish\Core\SignalSlot\ContentService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
386
        $this->signalDispatcher->emit(
387
            new TranslateVersionSignal(
388
                array(
389
                    'contentId' => $translationInfo->srcVersionInfo->contentInfo->id,
390
                    'versionNo' => $translationInfo->srcVersionInfo->versionNo,
391
                    'userId' => ($user !== null ? $user->id : null),
392
                )
393
            )
394
        );
395
396
        return $returnValue;
397
    }
398
399
    /**
400
     * Updates the fields of a draft.
401
     *
402
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to update this version
403
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
404
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $contentUpdateStruct is not valid
405
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is set to an empty value
406
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if a field value is not accepted by the field type
407
     *
408
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
409
     * @param \eZ\Publish\API\Repository\Values\Content\ContentUpdateStruct $contentUpdateStruct
410
     *
411
     * @return \eZ\Publish\API\Repository\Values\Content\Content the content draft with the updated fields
412
     */
413 View Code Duplication
    public function updateContent(VersionInfo $versionInfo, ContentUpdateStruct $contentUpdateStruct)
414
    {
415
        $returnValue = $this->service->updateContent($versionInfo, $contentUpdateStruct);
416
        $this->signalDispatcher->emit(
417
            new UpdateContentSignal(
418
                array(
419
                    'contentId' => $versionInfo->getContentInfo()->id,
420
                    'versionNo' => $versionInfo->versionNo,
421
                )
422
            )
423
        );
424
425
        return $returnValue;
426
    }
427
428
    /**
429
     * Publishes a content version.
430
     *
431
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to publish this version
432
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
433
     *
434
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
435
     *
436
     * @return \eZ\Publish\API\Repository\Values\Content\Content
437
     */
438 View Code Duplication
    public function publishVersion(VersionInfo $versionInfo)
439
    {
440
        $returnValue = $this->service->publishVersion($versionInfo);
441
        $this->signalDispatcher->emit(
442
            new PublishVersionSignal(
443
                array(
444
                    'contentId' => $versionInfo->getContentInfo()->id,
445
                    'versionNo' => $versionInfo->versionNo,
446
                )
447
            )
448
        );
449
450
        return $returnValue;
451
    }
452
453
    /**
454
     * Removes the given version.
455
     *
456
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is in
457
     *         published state or is the last version of the Content
458
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to remove this version
459
     *
460
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
461
     */
462 View Code Duplication
    public function deleteVersion(VersionInfo $versionInfo)
463
    {
464
        $returnValue = $this->service->deleteVersion($versionInfo);
465
        $this->signalDispatcher->emit(
466
            new DeleteVersionSignal(
467
                array(
468
                    'contentId' => $versionInfo->contentInfo->id,
469
                    'versionNo' => $versionInfo->versionNo,
470
                )
471
            )
472
        );
473
474
        return $returnValue;
475
    }
476
477
    /**
478
     * Loads all versions for the given content.
479
     *
480
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to list versions
481
     *
482
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
483
     *
484
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo[] Sorted by creation date
485
     */
486
    public function loadVersions(ContentInfo $contentInfo)
487
    {
488
        return $this->service->loadVersions($contentInfo);
489
    }
490
491
    /**
492
     * Copies the content to a new location. If no version is given,
493
     * all versions are copied, otherwise only the given version.
494
     *
495
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to copy the content to the given location
496
     *
497
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
498
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $destinationLocationCreateStruct the target location where the content is copied to
499
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
500
     *
501
     * @return \eZ\Publish\API\Repository\Values\Content\Content
502
     */
503
    public function copyContent(ContentInfo $contentInfo, LocationCreateStruct $destinationLocationCreateStruct, VersionInfo $versionInfo = null)
504
    {
505
        $returnValue = $this->service->copyContent($contentInfo, $destinationLocationCreateStruct, $versionInfo);
506
        $this->signalDispatcher->emit(
507
            new CopyContentSignal(
508
                array(
509
                    'srcContentId' => $contentInfo->id,
510
                    'srcVersionNo' => ($versionInfo !== null ? $versionInfo->versionNo : null),
511
                    'dstContentId' => $returnValue->getVersionInfo()->getContentInfo()->id,
512
                    'dstVersionNo' => $returnValue->getVersionInfo()->versionNo,
513
                    'dstParentLocationId' => $destinationLocationCreateStruct->parentLocationId,
514
                )
515
            )
516
        );
517
518
        return $returnValue;
519
    }
520
521
    /**
522
     * Loads all outgoing relations for the given version.
523
     *
524
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read this version
525
     *
526
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
527
     *
528
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
529
     */
530
    public function loadRelations(VersionInfo $versionInfo)
531
    {
532
        return $this->service->loadRelations($versionInfo);
533
    }
534
535
    /**
536
     * Loads all incoming relations for a content object.
537
     *
538
     * The relations come only from published versions of the source content objects
539
     *
540
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read this version
541
     *
542
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
543
     *
544
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
545
     */
546
    public function loadReverseRelations(ContentInfo $contentInfo)
547
    {
548
        return $this->service->loadReverseRelations($contentInfo);
549
    }
550
551
    /**
552
     * Adds a relation of type common.
553
     *
554
     * The source of the relation is the content and version
555
     * referenced by $versionInfo.
556
     *
557
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to edit this version
558
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
559
     *
560
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $sourceVersion
561
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContent the destination of the relation
562
     *
563
     * @return \eZ\Publish\API\Repository\Values\Content\Relation the newly created relation
564
     */
565 View Code Duplication
    public function addRelation(VersionInfo $sourceVersion, ContentInfo $destinationContent)
566
    {
567
        $returnValue = $this->service->addRelation($sourceVersion, $destinationContent);
568
        $this->signalDispatcher->emit(
569
            new AddRelationSignal(
570
                array(
571
                    'srcContentId' => $sourceVersion->contentInfo->id,
572
                    'srcVersionNo' => $sourceVersion->versionNo,
573
                    'dstContentId' => $destinationContent->id,
574
                )
575
            )
576
        );
577
578
        return $returnValue;
579
    }
580
581
    /**
582
     * Removes a relation of type COMMON from a draft.
583
     *
584
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed edit this version
585
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
586
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if there is no relation of type COMMON for the given destination
587
     *
588
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $sourceVersion
589
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContent
590
     */
591 View Code Duplication
    public function deleteRelation(VersionInfo $sourceVersion, ContentInfo $destinationContent)
592
    {
593
        $returnValue = $this->service->deleteRelation($sourceVersion, $destinationContent);
594
        $this->signalDispatcher->emit(
595
            new DeleteRelationSignal(
596
                array(
597
                    'srcContentId' => $sourceVersion->contentInfo->id,
598
                    'srcVersionNo' => $sourceVersion->versionNo,
599
                    'dstContentId' => $destinationContent->id,
600
                )
601
            )
602
        );
603
604
        return $returnValue;
605
    }
606
607
    /**
608
     * Adds translation information to the content object.
609
     *
610
     * @example Examples/translation_5x.php
611
     *
612
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed add a translation info
613
     *
614
     * @param \eZ\Publish\API\Repository\Values\Content\TranslationInfo $translationInfo
615
     *
616
     * @since 5.0
617
     */
618
    public function addTranslationInfo(TranslationInfo $translationInfo)
619
    {
620
        $returnValue = $this->service->addTranslationInfo($translationInfo);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface eZ\Publish\API\Repository\ContentService as the method addTranslationInfo() does only exist in the following implementations of said interface: eZ\Publish\Core\SignalSlot\ContentService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
621
        $this->signalDispatcher->emit(
622
            new AddTranslationInfoSignal(array())
623
        );
624
625
        return $returnValue;
626
    }
627
628
    /**
629
     * lists the translations done on this content object.
630
     *
631
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed read translation infos
632
     *
633
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
634
     * @param array $filter
635
     *
636
     * @todo TBD - filter by source version, destination version and languages
637
     *
638
     * @return \eZ\Publish\API\Repository\Values\Content\TranslationInfo[]
639
     *
640
     * @since 5.0
641
     */
642
    public function loadTranslationInfos(ContentInfo $contentInfo, array $filter = array())
643
    {
644
        return $this->service->loadTranslationInfos($contentInfo, $filter);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface eZ\Publish\API\Repository\ContentService as the method loadTranslationInfos() does only exist in the following implementations of said interface: eZ\Publish\Core\SignalSlot\ContentService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
645
    }
646
647
    /**
648
     * {@inheritdoc}
649
     */
650
    public function removeTranslation(ContentInfo $contentInfo, $languageCode)
651
    {
652
        @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
653
            __METHOD__ . ' is deprecated, use deleteTranslation instead',
654
            E_USER_DEPRECATED
655
        );
656
        $this->deleteTranslation($contentInfo, $languageCode);
657
    }
658
659
    /**
660
     * Delete Content item Translation from all Versions (including archived ones) of a Content Object.
661
     *
662
     * NOTE: this operation is risky and permanent, so user interface should provide a warning before performing it.
663
     *
664
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the specified Translation
665
     *         is the Main Translation of a Content Item.
666
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed
667
     *         to delete the content (in one of the locations of the given Content Item).
668
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if languageCode argument
669
     *         is invalid for the given content.
670
     *
671
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
672
     * @param string $languageCode
673
     *
674
     * @since 6.13
675
     */
676
    public function deleteTranslation(ContentInfo $contentInfo, $languageCode)
677
    {
678
        $this->service->deleteTranslation($contentInfo, $languageCode);
679
        $this->signalDispatcher->emit(
680
            new RemoveTranslationSignal(['contentId' => $contentInfo->id, 'languageCode' => $languageCode])
0 ignored issues
show
Deprecated Code introduced by
The class eZ\Publish\Core\SignalSl...RemoveTranslationSignal has been deprecated with message: since 6.13, use DeleteTranslationSignal

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
681
        );
682
        $this->signalDispatcher->emit(
683
            new DeleteTranslationSignal(['contentId' => $contentInfo->id, 'languageCode' => $languageCode])
684
        );
685
    }
686
687
    /**
688
     * Delete specified Translation from a Content Draft.
689
     *
690
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the specified Translation
691
     *         is the only one the Content Draft has or it is the main Translation of a Content Object.
692
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed
693
     *         to edit the Content (in one of the locations of the given Content Object).
694
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if languageCode argument
695
     *         is invalid for the given Draft.
696
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if specified Version was not found
697
     *
698
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo Content Version Draft
699
     * @param string $languageCode Language code of the Translation to be removed
700
     *
701
     * @return \eZ\Publish\API\Repository\Values\Content\Content Content Draft w/o the specified Translation
702
     *
703
     * @since 6.12
704
     */
705
    public function deleteTranslationFromDraft(VersionInfo $versionInfo, $languageCode)
706
    {
707
        return $this->service->deleteTranslationFromDraft($versionInfo, $languageCode);
708
    }
709
710
    /**
711
     * Bulk-load Content items by the list of ContentInfo Value Objects.
712
     *
713
     * Note: it does not throw exceptions on load, just ignores erroneous Content item.
714
     * Moreover, since the method works on pre-loaded ContentInfo list, it is assumed that user is
715
     * allowed to access every Content on the list.
716
     *
717
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo[] $contentInfoList
718
     * @param string[] $languages A language priority, filters returned fields and is used as prioritized language code on
719
     *                            returned value object. If not given all languages are returned.
720
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true,
721
     *                                 unless all languages have been asked for.
722
     *
723
     * @return \eZ\Publish\API\Repository\Values\Content\Content[] list of Content items with Content Ids as keys
724
     */
725
    public function loadContentListByContentInfo(
726
        array $contentInfoList,
727
        array $languages = [],
728
        $useAlwaysAvailable = true
729
    ) {
730
        return $this->service->loadContentListByContentInfo(
731
            $contentInfoList,
732
            $languages,
733
            $useAlwaysAvailable
734
        );
735
    }
736
737
    /**
738
     * Hides Content by making all the Locations appear hidden.
739
     * It does not persist hidden state on Location object itself.
740
     *
741
     * Content hidden by this API can be revealed by revealContent API.
742
     *
743
     * @see revealContent
744
     *
745
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
746
     */
747
    public function hideContent(ContentInfo $contentInfo): void
748
    {
749
        $this->service->hideContent($contentInfo);
750
        $this->signalDispatcher->emit(
751
            new HideContentSignal([
752
                'contentId' => $contentInfo->id,
753
            ])
754
        );
755
    }
756
757
    /**
758
     * Reveals Content hidden by hideContent API.
759
     * Locations which were hidden before hiding Content will remain hidden.
760
     *
761
     * @see hideContent
762
     *
763
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
764
     */
765
    public function revealContent(ContentInfo $contentInfo): void
766
    {
767
        $this->service->revealContent($contentInfo);
768
        $this->signalDispatcher->emit(
769
            new RevealContentSignal([
770
                'contentId' => $contentInfo->id,
771
            ])
772
        );
773
    }
774
775
    /**
776
     * Instantiates a new content create struct object.
777
     *
778
     * alwaysAvailable is set to the ContentType's defaultAlwaysAvailable
779
     *
780
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType
781
     * @param string $mainLanguageCode
782
     *
783
     * @return \eZ\Publish\API\Repository\Values\Content\ContentCreateStruct
784
     */
785
    public function newContentCreateStruct(ContentType $contentType, $mainLanguageCode)
786
    {
787
        return $this->service->newContentCreateStruct($contentType, $mainLanguageCode);
788
    }
789
790
    /**
791
     * Instantiates a new content meta data update struct.
792
     *
793
     * @return \eZ\Publish\API\Repository\Values\Content\ContentMetadataUpdateStruct
794
     */
795
    public function newContentMetadataUpdateStruct()
796
    {
797
        return $this->service->newContentMetadataUpdateStruct();
798
    }
799
800
    /**
801
     * Instantiates a new content update struct.
802
     *
803
     * @return \eZ\Publish\API\Repository\Values\Content\ContentUpdateStruct
804
     */
805
    public function newContentUpdateStruct()
806
    {
807
        return $this->service->newContentUpdateStruct();
808
    }
809
}
810