Completed
Push — master ( 6c3e1a...f2dfe9 )
by André
17:55
created

ContentService::translateVersion()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 1
nop 3
dl 0
loc 15
rs 9.7666
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\RemoveTranslationSignal;
25
use eZ\Publish\Core\SignalSlot\Signal\ContentService\UpdateContentMetadataSignal;
26
use eZ\Publish\Core\SignalSlot\Signal\ContentService\DeleteContentSignal;
27
use eZ\Publish\Core\SignalSlot\Signal\ContentService\CreateContentDraftSignal;
28
use eZ\Publish\Core\SignalSlot\Signal\ContentService\TranslateVersionSignal;
29
use eZ\Publish\Core\SignalSlot\Signal\ContentService\UpdateContentSignal;
30
use eZ\Publish\Core\SignalSlot\Signal\ContentService\PublishVersionSignal;
31
use eZ\Publish\Core\SignalSlot\Signal\ContentService\DeleteVersionSignal;
32
use eZ\Publish\Core\SignalSlot\Signal\ContentService\CopyContentSignal;
33
use eZ\Publish\Core\SignalSlot\Signal\ContentService\AddRelationSignal;
34
use eZ\Publish\Core\SignalSlot\Signal\ContentService\DeleteRelationSignal;
35
use eZ\Publish\Core\SignalSlot\Signal\ContentService\AddTranslationInfoSignal;
36
37
/**
38
 * ContentService class.
39
 */
40
class ContentService implements ContentServiceInterface
41
{
42
    /**
43
     * Aggregated service.
44
     *
45
     * @var \eZ\Publish\API\Repository\ContentService
46
     */
47
    protected $service;
48
49
    /**
50
     * SignalDispatcher.
51
     *
52
     * @var \eZ\Publish\Core\SignalSlot\SignalDispatcher
53
     */
54
    protected $signalDispatcher;
55
56
    /**
57
     * Constructor.
58
     *
59
     * Construct service object from aggregated service and signal
60
     * dispatcher
61
     *
62
     * @param \eZ\Publish\API\Repository\ContentService $service
63
     * @param \eZ\Publish\Core\SignalSlot\SignalDispatcher $signalDispatcher
64
     */
65
    public function __construct(ContentServiceInterface $service, SignalDispatcher $signalDispatcher)
66
    {
67
        $this->service = $service;
68
        $this->signalDispatcher = $signalDispatcher;
69
    }
70
71
    /**
72
     * Loads a content info object.
73
     *
74
     * To load fields use loadContent
75
     *
76
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content
77
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the content with the given id does not exist
78
     *
79
     * @param int $contentId
80
     *
81
     * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo
82
     */
83
    public function loadContentInfo($contentId)
84
    {
85
        return $this->service->loadContentInfo($contentId);
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function loadContentInfoList(array $contentIds): iterable
92
    {
93
        return $this->service->loadContentInfoList($contentIds);
94
    }
95
96
    /**
97
     * Loads a content info object for the given remoteId.
98
     *
99
     * To load fields use loadContent
100
     *
101
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content
102
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the content with the given remote id does not exist
103
     *
104
     * @param string $remoteId
105
     *
106
     * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo
107
     */
108
    public function loadContentInfoByRemoteId($remoteId)
109
    {
110
        return $this->service->loadContentInfoByRemoteId($remoteId);
111
    }
112
113
    /**
114
     * Loads a version info of the given content object.
115
     *
116
     * If no version number is given, the method returns the current version
117
     *
118
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the version with the given number does not exist
119
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
120
     *
121
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
122
     * @param int $versionNo the version number. If not given the current version is returned.
123
     *
124
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo
125
     */
126
    public function loadVersionInfo(ContentInfo $contentInfo, $versionNo = null)
127
    {
128
        return $this->service->loadVersionInfo($contentInfo, $versionNo);
129
    }
130
131
    /**
132
     * Loads a version info of the given content object id.
133
     *
134
     * If no version number is given, the method returns the current version
135
     *
136
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the version with the given number does not exist
137
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
138
     *
139
     * @param mixed $contentId
140
     * @param int $versionNo the version number. If not given the current version is returned.
141
     *
142
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo
143
     */
144
    public function loadVersionInfoById($contentId, $versionNo = null)
145
    {
146
        return $this->service->loadVersionInfoById($contentId, $versionNo);
147
    }
148
149
    /**
150
     * Loads content in a version for the given content info object.
151
     *
152
     * If no version number is given, the method returns the current version
153
     *
154
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if version with the given number does not exist
155
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
156
     *
157
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
158
     * @param array $languages A language filter for fields. If not given all languages are returned
159
     * @param int $versionNo the version number. If not given the current version is returned
160
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
161
     *
162
     * @return \eZ\Publish\API\Repository\Values\Content\Content
163
     */
164
    public function loadContentByContentInfo(ContentInfo $contentInfo, array $languages = null, $versionNo = null, $useAlwaysAvailable = true)
165
    {
166
        return $this->service->loadContentByContentInfo($contentInfo, $languages, $versionNo, $useAlwaysAvailable);
167
    }
168
169
    /**
170
     * Loads content in the version given by version info.
171
     *
172
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
173
     *
174
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
175
     * @param array $languages A language filter for fields. If not given all languages are returned
176
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
177
     *
178
     * @return \eZ\Publish\API\Repository\Values\Content\Content
179
     */
180
    public function loadContentByVersionInfo(VersionInfo $versionInfo, array $languages = null, $useAlwaysAvailable = true)
181
    {
182
        return $this->service->loadContentByVersionInfo($versionInfo, $languages, $useAlwaysAvailable);
183
    }
184
185
    /**
186
     * Loads content in a version of the given content object.
187
     *
188
     * If no version number is given, the method returns the current version
189
     *
190
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content or version with the given id and languages does not exist
191
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
192
     *
193
     * @param int $contentId
194
     * @param array $languages A language filter for fields. If not given all languages are returned
195
     * @param int $versionNo the version number. If not given the current version is returned
196
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
197
     *
198
     * @return \eZ\Publish\API\Repository\Values\Content\Content
199
     */
200
    public function loadContent($contentId, array $languages = null, $versionNo = null, $useAlwaysAvailable = true)
201
    {
202
        return $this->service->loadContent($contentId, $languages, $versionNo, $useAlwaysAvailable);
203
    }
204
205
    /**
206
     * Loads content in a version for the content object reference by the given remote id.
207
     *
208
     * If no version is given, the method returns the current version
209
     *
210
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException - if the content or version with the given remote id does not exist
211
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version
212
     *
213
     * @param string $remoteId
214
     * @param array $languages A language filter for fields. If not given all languages are returned
215
     * @param int $versionNo the version number. If not given the current version is returned
216
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true
217
     *
218
     * @return \eZ\Publish\API\Repository\Values\Content\Content
219
     */
220
    public function loadContentByRemoteId($remoteId, array $languages = null, $versionNo = null, $useAlwaysAvailable = true)
221
    {
222
        return $this->service->loadContentByRemoteId($remoteId, $languages, $versionNo, $useAlwaysAvailable);
223
    }
224
225
    /**
226
     * Creates a new content draft assigned to the authenticated user.
227
     *
228
     * If a different userId is given in $contentCreateStruct it is assigned to the given user
229
     * but this required special rights for the authenticated user
230
     * (this is useful for content staging where the transfer process does not
231
     * have to authenticate with the user which created the content object in the source server).
232
     * The user has to publish the draft if it should be visible.
233
     * In 4.x at least one location has to be provided in the location creation array.
234
     *
235
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to create the content in the given location
236
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if there is a provided remoteId which exists in the system
237
     *                                                                        or there is no location provided (4.x) or multiple locations
238
     *                                                                        are under the same parent or if the a field value is not accepted by the field type
239
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $contentCreateStruct is not valid
240
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is missing or is set to an empty value
241
     *
242
     * @param \eZ\Publish\API\Repository\Values\Content\ContentCreateStruct $contentCreateStruct
243
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct[] $locationCreateStructs For each location parent under which a location should be created for the content
244
     *
245
     * @return \eZ\Publish\API\Repository\Values\Content\Content - the newly created content draft
246
     */
247
    public function createContent(ContentCreateStruct $contentCreateStruct, array $locationCreateStructs = array())
248
    {
249
        $returnValue = $this->service->createContent($contentCreateStruct, $locationCreateStructs);
250
        $this->signalDispatcher->emit(
251
            new CreateContentSignal(
252
                array(
253
                    'contentId' => $returnValue->getVersionInfo()->getContentInfo()->id,
254
                    'versionNo' => $returnValue->getVersionInfo()->versionNo,
255
                )
256
            )
257
        );
258
259
        return $returnValue;
260
    }
261
262
    /**
263
     * Updates the metadata.
264
     *
265
     * (see {@link ContentMetadataUpdateStruct}) of a content object - to update fields use updateContent
266
     *
267
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to update the content meta data
268
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the remoteId in $contentMetadataUpdateStruct is set but already exists
269
     *
270
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
271
     * @param \eZ\Publish\API\Repository\Values\Content\ContentMetadataUpdateStruct $contentMetadataUpdateStruct
272
     *
273
     * @return \eZ\Publish\API\Repository\Values\Content\Content the content with the updated attributes
274
     */
275
    public function updateContentMetadata(ContentInfo $contentInfo, ContentMetadataUpdateStruct $contentMetadataUpdateStruct)
276
    {
277
        $returnValue = $this->service->updateContentMetadata($contentInfo, $contentMetadataUpdateStruct);
278
        $this->signalDispatcher->emit(
279
            new UpdateContentMetadataSignal(
280
                array(
281
                    'contentId' => $contentInfo->id,
282
                )
283
            )
284
        );
285
286
        return $returnValue;
287
    }
288
289
    /**
290
     * Deletes a content object including all its versions and locations including their subtrees.
291
     *
292
     * @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)
293
     *
294
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
295
     *
296
     * @return mixed[] Affected Location Id's
297
     */
298
    public function deleteContent(ContentInfo $contentInfo)
299
    {
300
        $returnValue = $this->service->deleteContent($contentInfo);
301
        $this->signalDispatcher->emit(
302
            new DeleteContentSignal(
303
                array(
304
                    'contentId' => $contentInfo->id,
305
                    'affectedLocationIds' => $returnValue,
306
                )
307
            )
308
        );
309
310
        return $returnValue;
311
    }
312
313
    /**
314
     * Creates a draft from a published or archived version.
315
     *
316
     * If no version is given, the current published version is used.
317
     * 4.x: The draft is created with the initialLanguage code of the source version or if not present with the main language.
318
     * It can be changed on updating the version.
319
     *
320
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to create the draft
321
     *
322
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
323
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
324
     * @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
325
     *
326
     * @return \eZ\Publish\API\Repository\Values\Content\Content - the newly created content draft
327
     */
328
    public function createContentDraft(ContentInfo $contentInfo, VersionInfo $versionInfo = null, User $user = null)
329
    {
330
        $returnValue = $this->service->createContentDraft($contentInfo, $versionInfo, $user);
331
        $this->signalDispatcher->emit(
332
            new CreateContentDraftSignal(
333
                array(
334
                    'contentId' => $contentInfo->id,
335
                    'versionNo' => ($versionInfo !== null ? $versionInfo->versionNo : null),
336
                    'newVersionNo' => $returnValue->getVersionInfo()->versionNo,
337
                    'userId' => ($user !== null ? $user->id : null),
338
                )
339
            )
340
        );
341
342
        return $returnValue;
343
    }
344
345
    /**
346
     * Loads drafts for a user.
347
     *
348
     * If no user is given the drafts for the authenticated user a returned
349
     *
350
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to load the draft list
351
     *
352
     * @param \eZ\Publish\API\Repository\Values\User\User $user
353
     *
354
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo[] the drafts ({@link VersionInfo}) owned by the given user
355
     */
356
    public function loadContentDrafts(User $user = null)
357
    {
358
        return $this->service->loadContentDrafts($user);
359
    }
360
361
    /**
362
     * Translate a version.
363
     *
364
     * updates the destination version given in $translationInfo with the provided translated fields in $translationValues
365
     *
366
     * @example Examples/translation_5x.php
367
     *
368
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to update this version
369
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the given destination version is not a draft
370
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is set to an empty value
371
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $translationValues is not valid
372
     *
373
     * @param \eZ\Publish\API\Repository\Values\Content\TranslationInfo $translationInfo
374
     * @param \eZ\Publish\API\Repository\Values\Content\TranslationValues $translationValues
375
     * @param \eZ\Publish\API\Repository\Values\User\User $user If set, this user is taken as modifier of the version
376
     *
377
     * @return \eZ\Publish\API\Repository\Values\Content\Content the content draft with the translated fields
378
     *
379
     * @since 5.0
380
     */
381
    public function translateVersion(TranslationInfo $translationInfo, TranslationValues $translationValues, User $user = null)
382
    {
383
        $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...
384
        $this->signalDispatcher->emit(
385
            new TranslateVersionSignal(
386
                array(
387
                    'contentId' => $translationInfo->srcVersionInfo->contentInfo->id,
388
                    'versionNo' => $translationInfo->srcVersionInfo->versionNo,
389
                    'userId' => ($user !== null ? $user->id : null),
390
                )
391
            )
392
        );
393
394
        return $returnValue;
395
    }
396
397
    /**
398
     * Updates the fields of a draft.
399
     *
400
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to update this version
401
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
402
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $contentUpdateStruct is not valid
403
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is set to an empty value
404
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if a field value is not accepted by the field type
405
     *
406
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
407
     * @param \eZ\Publish\API\Repository\Values\Content\ContentUpdateStruct $contentUpdateStruct
408
     *
409
     * @return \eZ\Publish\API\Repository\Values\Content\Content the content draft with the updated fields
410
     */
411 View Code Duplication
    public function updateContent(VersionInfo $versionInfo, ContentUpdateStruct $contentUpdateStruct)
412
    {
413
        $returnValue = $this->service->updateContent($versionInfo, $contentUpdateStruct);
414
        $this->signalDispatcher->emit(
415
            new UpdateContentSignal(
416
                array(
417
                    'contentId' => $versionInfo->getContentInfo()->id,
418
                    'versionNo' => $versionInfo->versionNo,
419
                )
420
            )
421
        );
422
423
        return $returnValue;
424
    }
425
426
    /**
427
     * Publishes a content version.
428
     *
429
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to publish this version
430
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
431
     *
432
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
433
     *
434
     * @return \eZ\Publish\API\Repository\Values\Content\Content
435
     */
436 View Code Duplication
    public function publishVersion(VersionInfo $versionInfo)
437
    {
438
        $returnValue = $this->service->publishVersion($versionInfo);
439
        $this->signalDispatcher->emit(
440
            new PublishVersionSignal(
441
                array(
442
                    'contentId' => $versionInfo->getContentInfo()->id,
443
                    'versionNo' => $versionInfo->versionNo,
444
                )
445
            )
446
        );
447
448
        return $returnValue;
449
    }
450
451
    /**
452
     * Removes the given version.
453
     *
454
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is in
455
     *         published state or is the last version of the Content
456
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to remove this version
457
     *
458
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
459
     */
460 View Code Duplication
    public function deleteVersion(VersionInfo $versionInfo)
461
    {
462
        $returnValue = $this->service->deleteVersion($versionInfo);
463
        $this->signalDispatcher->emit(
464
            new DeleteVersionSignal(
465
                array(
466
                    'contentId' => $versionInfo->contentInfo->id,
467
                    'versionNo' => $versionInfo->versionNo,
468
                )
469
            )
470
        );
471
472
        return $returnValue;
473
    }
474
475
    /**
476
     * Loads all versions for the given content.
477
     *
478
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to list versions
479
     *
480
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
481
     *
482
     * @return \eZ\Publish\API\Repository\Values\Content\VersionInfo[] Sorted by creation date
483
     */
484
    public function loadVersions(ContentInfo $contentInfo)
485
    {
486
        return $this->service->loadVersions($contentInfo);
487
    }
488
489
    /**
490
     * Copies the content to a new location. If no version is given,
491
     * all versions are copied, otherwise only the given version.
492
     *
493
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to copy the content to the given location
494
     *
495
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
496
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $destinationLocationCreateStruct the target location where the content is copied to
497
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
498
     *
499
     * @return \eZ\Publish\API\Repository\Values\Content\Content
500
     */
501
    public function copyContent(ContentInfo $contentInfo, LocationCreateStruct $destinationLocationCreateStruct, VersionInfo $versionInfo = null)
502
    {
503
        $returnValue = $this->service->copyContent($contentInfo, $destinationLocationCreateStruct, $versionInfo);
504
        $this->signalDispatcher->emit(
505
            new CopyContentSignal(
506
                array(
507
                    'srcContentId' => $contentInfo->id,
508
                    'srcVersionNo' => ($versionInfo !== null ? $versionInfo->versionNo : null),
509
                    'dstContentId' => $returnValue->getVersionInfo()->getContentInfo()->id,
510
                    'dstVersionNo' => $returnValue->getVersionInfo()->versionNo,
511
                    'dstParentLocationId' => $destinationLocationCreateStruct->parentLocationId,
512
                )
513
            )
514
        );
515
516
        return $returnValue;
517
    }
518
519
    /**
520
     * Loads all outgoing relations for the given version.
521
     *
522
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read this version
523
     *
524
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
525
     *
526
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
527
     */
528
    public function loadRelations(VersionInfo $versionInfo)
529
    {
530
        return $this->service->loadRelations($versionInfo);
531
    }
532
533
    /**
534
     * Loads all incoming relations for a content object.
535
     *
536
     * The relations come only from published versions of the source content objects
537
     *
538
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to read this version
539
     *
540
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
541
     *
542
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
543
     */
544
    public function loadReverseRelations(ContentInfo $contentInfo)
545
    {
546
        return $this->service->loadReverseRelations($contentInfo);
547
    }
548
549
    /**
550
     * Adds a relation of type common.
551
     *
552
     * The source of the relation is the content and version
553
     * referenced by $versionInfo.
554
     *
555
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to edit this version
556
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
557
     *
558
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $sourceVersion
559
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContent the destination of the relation
560
     *
561
     * @return \eZ\Publish\API\Repository\Values\Content\Relation the newly created relation
562
     */
563 View Code Duplication
    public function addRelation(VersionInfo $sourceVersion, ContentInfo $destinationContent)
564
    {
565
        $returnValue = $this->service->addRelation($sourceVersion, $destinationContent);
566
        $this->signalDispatcher->emit(
567
            new AddRelationSignal(
568
                array(
569
                    'srcContentId' => $sourceVersion->contentInfo->id,
570
                    'srcVersionNo' => $sourceVersion->versionNo,
571
                    'dstContentId' => $destinationContent->id,
572
                )
573
            )
574
        );
575
576
        return $returnValue;
577
    }
578
579
    /**
580
     * Removes a relation of type COMMON from a draft.
581
     *
582
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed edit this version
583
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
584
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if there is no relation of type COMMON for the given destination
585
     *
586
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $sourceVersion
587
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContent
588
     */
589 View Code Duplication
    public function deleteRelation(VersionInfo $sourceVersion, ContentInfo $destinationContent)
590
    {
591
        $returnValue = $this->service->deleteRelation($sourceVersion, $destinationContent);
592
        $this->signalDispatcher->emit(
593
            new DeleteRelationSignal(
594
                array(
595
                    'srcContentId' => $sourceVersion->contentInfo->id,
596
                    'srcVersionNo' => $sourceVersion->versionNo,
597
                    'dstContentId' => $destinationContent->id,
598
                )
599
            )
600
        );
601
602
        return $returnValue;
603
    }
604
605
    /**
606
     * Adds translation information to the content object.
607
     *
608
     * @example Examples/translation_5x.php
609
     *
610
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed add a translation info
611
     *
612
     * @param \eZ\Publish\API\Repository\Values\Content\TranslationInfo $translationInfo
613
     *
614
     * @since 5.0
615
     */
616
    public function addTranslationInfo(TranslationInfo $translationInfo)
617
    {
618
        $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...
619
        $this->signalDispatcher->emit(
620
            new AddTranslationInfoSignal(array())
621
        );
622
623
        return $returnValue;
624
    }
625
626
    /**
627
     * lists the translations done on this content object.
628
     *
629
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed read translation infos
630
     *
631
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
632
     * @param array $filter
633
     *
634
     * @todo TBD - filter by source version, destination version and languages
635
     *
636
     * @return \eZ\Publish\API\Repository\Values\Content\TranslationInfo[]
637
     *
638
     * @since 5.0
639
     */
640
    public function loadTranslationInfos(ContentInfo $contentInfo, array $filter = array())
641
    {
642
        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...
643
    }
644
645
    /**
646
     * {@inheritdoc}
647
     */
648
    public function removeTranslation(ContentInfo $contentInfo, $languageCode)
649
    {
650
        @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...
651
            __METHOD__ . ' is deprecated, use deleteTranslation instead',
652
            E_USER_DEPRECATED
653
        );
654
        $this->deleteTranslation($contentInfo, $languageCode);
655
    }
656
657
    /**
658
     * Delete Content item Translation from all Versions (including archived ones) of a Content Object.
659
     *
660
     * NOTE: this operation is risky and permanent, so user interface should provide a warning before performing it.
661
     *
662
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the specified Translation
663
     *         is the Main Translation of a Content Item.
664
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed
665
     *         to delete the content (in one of the locations of the given Content Item).
666
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if languageCode argument
667
     *         is invalid for the given content.
668
     *
669
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
670
     * @param string $languageCode
671
     *
672
     * @since 6.13
673
     */
674
    public function deleteTranslation(ContentInfo $contentInfo, $languageCode)
675
    {
676
        $this->service->deleteTranslation($contentInfo, $languageCode);
677
        $this->signalDispatcher->emit(
678
            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...
679
        );
680
        $this->signalDispatcher->emit(
681
            new DeleteTranslationSignal(['contentId' => $contentInfo->id, 'languageCode' => $languageCode])
682
        );
683
    }
684
685
    /**
686
     * Delete specified Translation from a Content Draft.
687
     *
688
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the specified Translation
689
     *         is the only one the Content Draft has or it is the main Translation of a Content Object.
690
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed
691
     *         to edit the Content (in one of the locations of the given Content Object).
692
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if languageCode argument
693
     *         is invalid for the given Draft.
694
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if specified Version was not found
695
     *
696
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo Content Version Draft
697
     * @param string $languageCode Language code of the Translation to be removed
698
     *
699
     * @return \eZ\Publish\API\Repository\Values\Content\Content Content Draft w/o the specified Translation
700
     *
701
     * @since 6.12
702
     */
703
    public function deleteTranslationFromDraft(VersionInfo $versionInfo, $languageCode)
704
    {
705
        return $this->service->deleteTranslationFromDraft($versionInfo, $languageCode);
706
    }
707
708
    /**
709
     * Bulk-load Content items by the list of ContentInfo Value Objects.
710
     *
711
     * Note: it does not throw exceptions on load, just ignores erroneous Content item.
712
     * Moreover, since the method works on pre-loaded ContentInfo list, it is assumed that user is
713
     * allowed to access every Content on the list.
714
     *
715
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo[] $contentInfoList
716
     * @param string[] $languages A language priority, filters returned fields and is used as prioritized language code on
717
     *                            returned value object. If not given all languages are returned.
718
     * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true,
719
     *                                 unless all languages have been asked for.
720
     *
721
     * @return \eZ\Publish\API\Repository\Values\Content\Content[] list of Content items with Content Ids as keys
722
     */
723
    public function loadContentListByContentInfo(
724
        array $contentInfoList,
725
        array $languages = [],
726
        $useAlwaysAvailable = true
727
    ) {
728
        return $this->service->loadContentListByContentInfo(
729
            $contentInfoList,
730
            $languages,
731
            $useAlwaysAvailable
732
        );
733
    }
734
735
    /**
736
     * Instantiates a new content create struct object.
737
     *
738
     * alwaysAvailable is set to the ContentType's defaultAlwaysAvailable
739
     *
740
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType
741
     * @param string $mainLanguageCode
742
     *
743
     * @return \eZ\Publish\API\Repository\Values\Content\ContentCreateStruct
744
     */
745
    public function newContentCreateStruct(ContentType $contentType, $mainLanguageCode)
746
    {
747
        return $this->service->newContentCreateStruct($contentType, $mainLanguageCode);
748
    }
749
750
    /**
751
     * Instantiates a new content meta data update struct.
752
     *
753
     * @return \eZ\Publish\API\Repository\Values\Content\ContentMetadataUpdateStruct
754
     */
755
    public function newContentMetadataUpdateStruct()
756
    {
757
        return $this->service->newContentMetadataUpdateStruct();
758
    }
759
760
    /**
761
     * Instantiates a new content update struct.
762
     *
763
     * @return \eZ\Publish\API\Repository\Values\Content\ContentUpdateStruct
764
     */
765
    public function newContentUpdateStruct()
766
    {
767
        return $this->service->newContentUpdateStruct();
768
    }
769
}
770