Completed
Push — test-EZP-26707-issearchable-fu... ( fbd943...774d65 )
by
unknown
19:43
created

User::createSession()   C

Complexity

Conditions 9
Paths 69

Size

Total Lines 58
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 38
nc 69
nop 1
dl 0
loc 58
rs 6.9928
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * File containing the User controller 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
 * @version //autogentag//
10
 */
11
namespace eZ\Publish\Core\REST\Server\Controller;
12
13
use eZ\Publish\Core\REST\Common\Message;
14
use eZ\Publish\Core\REST\Server\Values;
15
use eZ\Publish\Core\REST\Server\Exceptions;
16
use eZ\Publish\Core\REST\Server\Controller as RestController;
17
use eZ\Publish\API\Repository\UserService;
18
use eZ\Publish\API\Repository\ContentService;
19
use eZ\Publish\API\Repository\ContentTypeService;
20
use eZ\Publish\API\Repository\RoleService;
21
use eZ\Publish\API\Repository\LocationService;
22
use eZ\Publish\API\Repository\SectionService;
23
use eZ\Publish\API\Repository\Repository;
24
use eZ\Publish\API\Repository\Values\User\UserRoleAssignment;
25
use eZ\Publish\API\Repository\Values\User\UserGroupRoleAssignment;
26
use eZ\Publish\API\Repository\Values\User\User as RepositoryUser;
27
use eZ\Publish\API\Repository\Exceptions as ApiExceptions;
28
use eZ\Publish\Core\REST\Common\Exceptions\NotFoundException as RestNotFoundException;
29
use eZ\Publish\Core\REST\Server\Exceptions\ForbiddenException;
30
use eZ\Publish\Core\REST\Common\Exceptions\NotFoundException;
31
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException;
32
use Symfony\Component\DependencyInjection\ContainerInterface;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
35
use Symfony\Component\Security\Core\Exception\AuthenticationException;
36
use Symfony\Component\Security\Csrf\CsrfToken;
37
38
/**
39
 * User controller.
40
 */
41
class User extends RestController
42
{
43
    /**
44
     * User service.
45
     *
46
     * @var \eZ\Publish\API\Repository\UserService
47
     */
48
    protected $userService;
49
50
    /**
51
     * Role service.
52
     *
53
     * @var \eZ\Publish\API\Repository\RoleService
54
     */
55
    protected $roleService;
56
57
    /**
58
     * Content service.
59
     *
60
     * @var \eZ\Publish\API\Repository\ContentService
61
     */
62
    protected $contentService;
63
64
    /**
65
     * Content service.
66
     *
67
     * @var \eZ\Publish\API\Repository\ContentTypeService
68
     */
69
    protected $contentTypeService;
70
71
    /**
72
     * Location service.
73
     *
74
     * @var \eZ\Publish\API\Repository\LocationService
75
     */
76
    protected $locationService;
77
78
    /**
79
     * Section service.
80
     *
81
     * @var \eZ\Publish\API\Repository\SectionService
82
     */
83
    protected $sectionService;
84
85
    /**
86
     * Repository.
87
     *
88
     * @var \eZ\Publish\API\Repository\Repository
89
     */
90
    protected $repository;
91
92
    /**
93
     * Construct controller.
94
     *
95
     * @param \eZ\Publish\API\Repository\UserService $userService
96
     * @param \eZ\Publish\API\Repository\RoleService $roleService
97
     * @param \eZ\Publish\API\Repository\ContentService $contentService
98
     * @param \eZ\Publish\API\Repository\LocationService $locationService
99
     * @param \eZ\Publish\API\Repository\SectionService $sectionService
100
     * @param \eZ\Publish\API\Repository\Repository $repository
101
     */
102
    public function __construct(
103
        UserService $userService,
104
        RoleService $roleService,
105
        ContentService $contentService,
106
        ContentTypeService $contentTypeService,
107
        LocationService $locationService,
108
        SectionService $sectionService,
109
        Repository $repository
110
    ) {
111
        $this->userService = $userService;
112
        $this->roleService = $roleService;
113
        $this->contentService = $contentService;
114
        $this->contentTypeService = $contentTypeService;
115
        $this->locationService = $locationService;
116
        $this->sectionService = $sectionService;
117
        $this->repository = $repository;
118
    }
119
120
    /**
121
     * Redirects to the root user group.
122
     *
123
     * @return \eZ\Publish\Core\REST\Server\Values\PermanentRedirect
124
     */
125
    public function loadRootUserGroup()
126
    {
127
        //@todo Replace hardcoded value with one loaded from settings
128
        return new Values\PermanentRedirect(
129
            $this->router->generate('ezpublish_rest_loadUserGroup', array('groupPath' => '/1/5'))
130
        );
131
    }
132
133
    /**
134
     * Loads a user group for the given path.
135
     *
136
     * @param $groupPath
137
     *
138
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserGroup
139
     */
140
    public function loadUserGroup($groupPath)
141
    {
142
        $userGroupLocation = $this->locationService->loadLocation(
143
            $this->extractLocationIdFromPath($groupPath)
144
        );
145
146
        if (trim($userGroupLocation->pathString, '/') != $groupPath) {
147
            throw new NotFoundException(
148
                "Could not find location with path string $groupPath"
149
            );
150
        }
151
152
        $userGroup = $this->userService->loadUserGroup(
153
            $userGroupLocation->contentId
154
        );
155
        $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo();
156
        $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId);
157
158
        return new Values\CachedValue(
159
            new Values\RestUserGroup(
160
                $userGroup,
161
                $contentType,
162
                $userGroupContentInfo,
163
                $userGroupLocation,
164
                $this->contentService->loadRelations($userGroup->getVersionInfo())
165
            ),
166
            array('locationId' => $userGroupLocation->id)
167
        );
168
    }
169
170
    /**
171
     * Loads a user for the given ID.
172
     *
173
     * @param $userId
174
     *
175
     * @return \eZ\Publish\Core\REST\Server\Values\RestUser
176
     */
177
    public function loadUser($userId)
178
    {
179
        $user = $this->userService->loadUser($userId);
180
181
        $userContentInfo = $user->getVersionInfo()->getContentInfo();
182
        $contentType = $this->contentTypeService->loadContentType($userContentInfo->contentTypeId);
183
184
        try {
185
            $userMainLocation = $this->locationService->loadLocation($userContentInfo->mainLocationId);
186
            $relations = $this->contentService->loadRelations($user->getVersionInfo());
187
        } catch (UnauthorizedException $e) {
188
            // TODO: Hack for special case to allow current logged in user to load him/here self (but not relations)
189
            if ($user->id == $this->repository->getCurrentUser()->id) {
190
                $userMainLocation = $this->repository->sudo(
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface eZ\Publish\API\Repository\Repository as the method sudo() does only exist in the following implementations of said interface: eZ\Publish\Core\Repository\Repository, eZ\Publish\Core\SignalSlot\Repository.

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...
191
                    function () use ($userContentInfo) {
192
                        return $this->locationService->loadLocation($userContentInfo->mainLocationId);
193
                    }
194
                );
195
                // user may not have permissions to read related content, for security reasons do not use sudo().
196
                $relations = array();
197
            } else {
198
                throw $e;
199
            }
200
        }
201
202
        return new Values\CachedValue(
203
            new Values\RestUser(
204
                $user,
205
                $contentType,
206
                $userContentInfo,
207
                $userMainLocation,
208
                $relations
209
            ),
210
            array('locationId' => $userContentInfo->mainLocationId)
211
        );
212
    }
213
214
    /**
215
     * Create a new user group under the given parent
216
     * To create a top level group use /user/groups/1/5/subgroups.
217
     *
218
     * @param $groupPath
219
     *
220
     * @throws \eZ\Publish\Core\REST\Server\Exceptions\BadRequestException
221
     *
222
     * @return \eZ\Publish\Core\REST\Server\Values\CreatedUserGroup
223
     */
224
    public function createUserGroup($groupPath, Request $request)
225
    {
226
        $userGroupLocation = $this->locationService->loadLocation(
227
            $this->extractLocationIdFromPath($groupPath)
228
        );
229
230
        $createdUserGroup = $this->userService->createUserGroup(
231
            $this->inputDispatcher->parse(
0 ignored issues
show
Compatibility introduced by
$this->inputDispatcher->...request->getContent())) of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...\UserGroupCreateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
232
                new Message(
233
                    array('Content-Type' => $request->headers->get('Content-Type')),
234
                    $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
235
                )
236
            ),
237
            $this->userService->loadUserGroup(
238
                $userGroupLocation->contentId
239
            )
240
        );
241
242
        $createdContentInfo = $createdUserGroup->getVersionInfo()->getContentInfo();
243
        $createdLocation = $this->locationService->loadLocation($createdContentInfo->mainLocationId);
244
        $contentType = $this->contentTypeService->loadContentType($createdContentInfo->contentTypeId);
245
246
        return new Values\CreatedUserGroup(
247
            array(
248
                'userGroup' => new Values\RestUserGroup(
249
                    $createdUserGroup,
250
                    $contentType,
251
                    $createdContentInfo,
252
                    $createdLocation,
253
                    $this->contentService->loadRelations($createdUserGroup->getVersionInfo())
254
                ),
255
            )
256
        );
257
    }
258
259
    /**
260
     * Create a new user group in the given group.
261
     *
262
     * @param $groupPath
263
     *
264
     * @throws \eZ\Publish\Core\REST\Server\Exceptions\ForbiddenException
265
     *
266
     * @return \eZ\Publish\Core\REST\Server\Values\CreatedUser
267
     */
268
    public function createUser($groupPath, Request $request)
269
    {
270
        $userGroupLocation = $this->locationService->loadLocation(
271
            $this->extractLocationIdFromPath($groupPath)
272
        );
273
        $userGroup = $this->userService->loadUserGroup($userGroupLocation->contentId);
274
275
        $userCreateStruct = $this->inputDispatcher->parse(
276
            new Message(
277
                array('Content-Type' => $request->headers->get('Content-Type')),
278
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
279
            )
280
        );
281
282
        try {
283
            $createdUser = $this->userService->createUser($userCreateStruct, array($userGroup));
0 ignored issues
show
Compatibility introduced by
$userCreateStruct of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...\User\UserCreateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
284
        } catch (ApiExceptions\InvalidArgumentException $e) {
285
            throw new ForbiddenException($e->getMessage());
286
        }
287
288
        $createdContentInfo = $createdUser->getVersionInfo()->getContentInfo();
289
        $createdLocation = $this->locationService->loadLocation($createdContentInfo->mainLocationId);
290
        $contentType = $this->contentTypeService->loadContentType($createdContentInfo->contentTypeId);
291
292
        return new Values\CreatedUser(
293
            array(
294
                'user' => new Values\RestUser(
295
                    $createdUser,
296
                    $contentType,
297
                    $createdContentInfo,
298
                    $createdLocation,
299
                    $this->contentService->loadRelations($createdUser->getVersionInfo())
300
                ),
301
            )
302
        );
303
    }
304
305
    /**
306
     * Updates a user group.
307
     *
308
     * @param $groupPath
309
     *
310
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserGroup
311
     */
312
    public function updateUserGroup($groupPath, Request $request)
313
    {
314
        $userGroupLocation = $this->locationService->loadLocation(
315
            $this->extractLocationIdFromPath($groupPath)
316
        );
317
318
        $userGroup = $this->userService->loadUserGroup(
319
            $userGroupLocation->contentId
320
        );
321
322
        $updateStruct = $this->inputDispatcher->parse(
323
            new Message(
324
                array(
325
                    'Content-Type' => $request->headers->get('Content-Type'),
326
                    // @todo Needs refactoring! Temporary solution so parser has access to URL
327
                    'Url' => $request->getPathInfo(),
328
                ),
329
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
330
            )
331
        );
332
333 View Code Duplication
        if ($updateStruct->sectionId !== null) {
0 ignored issues
show
Documentation introduced by
The property sectionId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
334
            $section = $this->sectionService->loadSection($updateStruct->sectionId);
0 ignored issues
show
Documentation introduced by
The property sectionId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
335
            $this->sectionService->assignSection(
336
                $userGroup->getVersionInfo()->getContentInfo(),
337
                $section
338
            );
339
        }
340
341
        $updatedGroup = $this->userService->updateUserGroup($userGroup, $updateStruct->userGroupUpdateStruct);
0 ignored issues
show
Documentation introduced by
The property userGroupUpdateStruct does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
342
        $contentType = $this->contentTypeService->loadContentType(
343
            $updatedGroup->getVersionInfo()->getContentInfo()->contentTypeId
344
        );
345
346
        return new Values\RestUserGroup(
347
            $updatedGroup,
348
            $contentType,
349
            $updatedGroup->getVersionInfo()->getContentInfo(),
350
            $userGroupLocation,
351
            $this->contentService->loadRelations($updatedGroup->getVersionInfo())
352
        );
353
    }
354
355
    /**
356
     * Updates a user.
357
     *
358
     * @param $userId
359
     *
360
     * @return \eZ\Publish\Core\REST\Server\Values\RestUser
361
     */
362
    public function updateUser($userId, Request $request)
363
    {
364
        $user = $this->userService->loadUser($userId);
365
366
        $updateStruct = $this->inputDispatcher->parse(
367
            new Message(
368
                array(
369
                    'Content-Type' => $request->headers->get('Content-Type'),
370
                    // @todo Needs refactoring! Temporary solution so parser has access to URL
371
                    'Url' => $request->getPathInfo(),
372
                ),
373
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
374
            )
375
        );
376
377 View Code Duplication
        if ($updateStruct->sectionId !== null) {
0 ignored issues
show
Documentation introduced by
The property sectionId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
378
            $section = $this->sectionService->loadSection($updateStruct->sectionId);
0 ignored issues
show
Documentation introduced by
The property sectionId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
379
            $this->sectionService->assignSection(
380
                $user->getVersionInfo()->getContentInfo(),
381
                $section
382
            );
383
        }
384
385
        $updatedUser = $this->userService->updateUser($user, $updateStruct->userUpdateStruct);
0 ignored issues
show
Documentation introduced by
The property userUpdateStruct does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
386
        $updatedContentInfo = $updatedUser->getVersionInfo()->getContentInfo();
387
        $mainLocation = $this->locationService->loadLocation($updatedContentInfo->mainLocationId);
388
        $contentType = $this->contentTypeService->loadContentType($updatedContentInfo->contentTypeId);
389
390
        return new Values\RestUser(
391
            $updatedUser,
392
            $contentType,
393
            $updatedContentInfo,
394
            $mainLocation,
395
            $this->contentService->loadRelations($updatedUser->getVersionInfo())
396
        );
397
    }
398
399
    /**
400
     * Given user group is deleted.
401
     *
402
     * @param $groupPath
403
     *
404
     * @throws \eZ\Publish\Core\REST\Server\Exceptions\ForbiddenException
405
     *
406
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
407
     */
408
    public function deleteUserGroup($groupPath)
409
    {
410
        $userGroupLocation = $this->locationService->loadLocation(
411
            $this->extractLocationIdFromPath($groupPath)
412
        );
413
414
        $userGroup = $this->userService->loadUserGroup(
415
            $userGroupLocation->contentId
416
        );
417
418
        // Load one user to see if user group is empty or not
419
        $users = $this->userService->loadUsersOfUserGroup($userGroup, 0, 1);
420
        if (!empty($users)) {
421
            throw new Exceptions\ForbiddenException('Non-empty user groups cannot be deleted');
422
        }
423
424
        $this->userService->deleteUserGroup($userGroup);
425
426
        return new Values\NoContent();
427
    }
428
429
    /**
430
     * Given user is deleted.
431
     *
432
     * @param $userId
433
     *
434
     * @throws \eZ\Publish\Core\REST\Server\Exceptions\ForbiddenException
435
     *
436
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
437
     */
438
    public function deleteUser($userId)
439
    {
440
        $user = $this->userService->loadUser($userId);
441
442
        if ($user->id == $this->repository->getCurrentUser()->id) {
443
            throw new Exceptions\ForbiddenException('Currently authenticated user cannot be deleted');
444
        }
445
446
        $this->userService->deleteUser($user);
447
448
        return new Values\NoContent();
449
    }
450
451
    /**
452
     * Loads users.
453
     *
454
     * @return \eZ\Publish\Core\REST\Server\Values\UserList|\eZ\Publish\Core\REST\Server\Values\UserRefList
455
     */
456
    public function loadUsers(Request $request)
457
    {
458
        $restUsers = array();
459
460
        try {
461
            if ($request->query->has('roleId')) {
462
                $restUsers = $this->loadUsersAssignedToRole(
463
                    $this->requestParser->parseHref($request->query->get('roleId'), 'roleId')
464
                );
465
            } elseif ($request->query->has('remoteId')) {
466
                $restUsers = array(
467
                    $this->buildRestUserObject(
468
                        $this->userService->loadUser(
469
                            $this->contentService->loadContentInfoByRemoteId($request->query->get('remoteId'))->id
470
                        )
471
                    ),
472
                );
473
            } elseif ($request->query->has('login')) {
474
                $restUsers = array(
475
                    $this->buildRestUserObject(
476
                        $this->userService->loadUserByLogin($request->query->get('login'))
477
                    ),
478
                );
479
            } elseif ($request->query->has('email')) {
480
                foreach ($this->userService->loadUsersByEmail($request->query->get('email')) as $user) {
481
                    $restUsers[] = $this->buildRestUserObject($user);
482
                }
483
            }
484
        } catch (ApiExceptions\UnauthorizedException $e) {
485
            $restUsers = [];
486
        }
487
488
        if (empty($restUsers)) {
489
            throw new NotFoundException('No users were found with the given filter');
490
        }
491
492
        if ($this->getMediaType($request) === 'application/vnd.ez.api.userlist') {
493
            return new Values\UserList($restUsers, $request->getPathInfo());
494
        }
495
496
        return new Values\UserRefList($restUsers, $request->getPathInfo());
497
    }
498
499
    public function verifyUsers(Request $request)
500
    {
501
        // We let the NotFoundException loadUsers throws if there are no results pass.
502
        $this->loadUsers($request)->users;
503
504
        return new Values\OK();
505
    }
506
507
    /**
508
     * Loads a list of users assigned to role.
509
     *
510
     * @param mixed $roleId
511
     *
512
     * @return \eZ\Publish\Core\REST\Server\Values\RestUser[]
513
     */
514
    public function loadUsersAssignedToRole($roleId)
515
    {
516
        $role = $this->roleService->loadRole($roleId);
517
        $roleAssignments = $this->roleService->getRoleAssignments($role);
518
519
        $restUsers = array();
520
521
        foreach ($roleAssignments as $roleAssignment) {
522
            if ($roleAssignment instanceof UserRoleAssignment) {
523
                $restUsers[] = $this->buildRestUserObject($roleAssignment->getUser());
524
            }
525
        }
526
527
        return $restUsers;
528
    }
529
530
    /**
531
     * @return Values\RestUser
532
     */
533
    private function buildRestUserObject(RepositoryUser $user)
534
    {
535
        return new Values\RestUser(
536
            $user,
537
            $this->contentTypeService->loadContentType($user->contentInfo->contentTypeId),
538
            $user->contentInfo,
539
            $this->locationService->loadLocation($user->contentInfo->mainLocationId),
540
            $this->contentService->loadRelations($user->getVersionInfo())
541
        );
542
    }
543
544
    /**
545
     * Loads user groups.
546
     *
547
     * @return \eZ\Publish\Core\REST\Server\Values\UserGroupList|\eZ\Publish\Core\REST\Server\Values\UserGroupRefList
548
     */
549
    public function loadUserGroups(Request $request)
550
    {
551
        $restUserGroups = array();
552
        if ($request->query->has('id')) {
553
            $userGroup = $this->userService->loadUserGroup($request->query->get('id'));
554
            $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo();
555
            $userGroupMainLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId);
556
            $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId);
557
558
            $restUserGroups = array(
559
                new Values\RestUserGroup(
560
                    $userGroup,
561
                    $contentType,
562
                    $userGroupContentInfo,
563
                    $userGroupMainLocation,
564
                    $this->contentService->loadRelations($userGroup->getVersionInfo())
565
                ),
566
            );
567
        } elseif ($request->query->has('roleId')) {
568
            $restUserGroups = $this->loadUserGroupsAssignedToRole($request->query->get('roleId'));
569
        } elseif ($request->query->has('remoteId')) {
570
            $restUserGroups = array(
571
                $this->loadUserGroupByRemoteId($request),
572
            );
573
        }
574
575
        if ($this->getMediaType($request) === 'application/vnd.ez.api.usergrouplist') {
576
            return new Values\UserGroupList($restUserGroups, $request->getPathInfo());
577
        }
578
579
        return new Values\UserGroupRefList($restUserGroups, $request->getPathInfo());
580
    }
581
582
    /**
583
     * Loads a user group by its remote ID.
584
     *
585
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserGroup
586
     */
587
    public function loadUserGroupByRemoteId(Request $request)
588
    {
589
        $contentInfo = $this->contentService->loadContentInfoByRemoteId($request->query->get('remoteId'));
590
        $userGroup = $this->userService->loadUserGroup($contentInfo->id);
591
        $userGroupLocation = $this->locationService->loadLocation($contentInfo->mainLocationId);
592
        $contentType = $this->contentTypeService->loadContentType($contentInfo->contentTypeId);
593
594
        return new Values\RestUserGroup(
595
            $userGroup,
596
            $contentType,
597
            $contentInfo,
598
            $userGroupLocation,
599
            $this->contentService->loadRelations($userGroup->getVersionInfo())
600
        );
601
    }
602
603
    /**
604
     * Loads a list of user groups assigned to role.
605
     *
606
     * @param mixed $roleId
607
     *
608
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserGroup[]
609
     */
610
    public function loadUserGroupsAssignedToRole($roleId)
611
    {
612
        $role = $this->roleService->loadRole($roleId);
613
        $roleAssignments = $this->roleService->getRoleAssignments($role);
614
615
        $restUserGroups = array();
616
617
        foreach ($roleAssignments as $roleAssignment) {
618
            if ($roleAssignment instanceof UserGroupRoleAssignment) {
619
                $userGroup = $roleAssignment->getUserGroup();
620
                $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo();
621
                $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId);
622
                $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId);
623
624
                $restUserGroups[] = new Values\RestUserGroup(
625
                    $userGroup,
626
                    $contentType,
627
                    $userGroupContentInfo,
628
                    $userGroupLocation,
629
                    $this->contentService->loadRelations($userGroup->getVersionInfo())
630
                );
631
            }
632
        }
633
634
        return $restUserGroups;
635
    }
636
637
    /**
638
     * Loads drafts assigned to user.
639
     *
640
     * @param $userId
641
     *
642
     * @return \eZ\Publish\Core\REST\Server\Values\VersionList
643
     */
644
    public function loadUserDrafts($userId, Request $request)
645
    {
646
        $contentDrafts = $this->contentService->loadContentDrafts(
647
            $this->userService->loadUser($userId)
648
        );
649
650
        return new Values\VersionList($contentDrafts, $request->getPathInfo());
651
    }
652
653
    /**
654
     * Moves the user group to another parent.
655
     *
656
     * @param $groupPath
657
     *
658
     * @throws \eZ\Publish\Core\REST\Server\Exceptions\ForbiddenException
659
     *
660
     * @return \eZ\Publish\Core\REST\Server\Values\ResourceCreated
661
     */
662
    public function moveUserGroup($groupPath, Request $request)
663
    {
664
        $userGroupLocation = $this->locationService->loadLocation(
665
            $this->extractLocationIdFromPath($groupPath)
666
        );
667
668
        $userGroup = $this->userService->loadUserGroup(
669
            $userGroupLocation->contentId
670
        );
671
672
        $locationPath = $this->requestParser->parseHref(
673
            $request->headers->get('Destination'),
674
            'groupPath'
675
        );
676
677
        try {
678
            $destinationGroupLocation = $this->locationService->loadLocation(
679
                $this->extractLocationIdFromPath($locationPath)
680
            );
681
        } catch (ApiExceptions\NotFoundException $e) {
682
            throw new Exceptions\ForbiddenException($e->getMessage());
683
        }
684
685
        try {
686
            $destinationGroup = $this->userService->loadUserGroup($destinationGroupLocation->contentId);
687
        } catch (ApiExceptions\NotFoundException $e) {
688
            throw new Exceptions\ForbiddenException($e->getMessage());
689
        }
690
691
        $this->userService->moveUserGroup($userGroup, $destinationGroup);
692
693
        return new Values\ResourceCreated(
694
            $this->router->generate(
695
                'ezpublish_rest_loadUserGroup',
696
                array(
697
                    'groupPath' => trim($destinationGroupLocation->pathString, '/') . '/' . $userGroupLocation->id,
698
                )
699
            )
700
        );
701
    }
702
703
    /**
704
     * Returns a list of the sub groups.
705
     *
706
     * @param $groupPath
707
     *
708
     * @return \eZ\Publish\Core\REST\Server\Values\UserGroupList|\eZ\Publish\Core\REST\Server\Values\UserGroupRefList
709
     */
710 View Code Duplication
    public function loadSubUserGroups($groupPath, Request $request)
711
    {
712
        $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0;
713
        $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : 25;
714
715
        $userGroupLocation = $this->locationService->loadLocation(
716
            $this->extractLocationIdFromPath($groupPath)
717
        );
718
719
        $userGroup = $this->userService->loadUserGroup(
720
            $userGroupLocation->contentId
721
        );
722
723
        $subGroups = $this->userService->loadSubUserGroups(
724
            $userGroup,
725
            $offset >= 0 ? $offset : 0,
726
            $limit >= 0 ? $limit : 25
727
        );
728
729
        $restUserGroups = array();
730
        foreach ($subGroups as $subGroup) {
731
            $subGroupContentInfo = $subGroup->getVersionInfo()->getContentInfo();
732
            $subGroupLocation = $this->locationService->loadLocation($subGroupContentInfo->mainLocationId);
733
            $contentType = $this->contentTypeService->loadContentType($subGroupContentInfo->contentTypeId);
734
735
            $restUserGroups[] = new Values\RestUserGroup(
736
                $subGroup,
737
                $contentType,
738
                $subGroupContentInfo,
739
                $subGroupLocation,
740
                $this->contentService->loadRelations($subGroup->getVersionInfo())
741
            );
742
        }
743
744
        if ($this->getMediaType($request) === 'application/vnd.ez.api.usergrouplist') {
745
            return new Values\CachedValue(
746
                new Values\UserGroupList($restUserGroups, $request->getPathInfo()),
747
                array('locationId' => $userGroupLocation->id)
748
            );
749
        }
750
751
        return new Values\CachedValue(
752
            new Values\UserGroupRefList($restUserGroups, $request->getPathInfo()),
753
            array('locationId' => $userGroupLocation->id)
754
        );
755
    }
756
757
    /**
758
     * Returns a list of user groups the user belongs to.
759
     * The returned list includes the resources for unassigning
760
     * a user group if the user is in multiple groups.
761
     *
762
     * @param $userId
763
     *
764
     * @return \eZ\Publish\Core\REST\Server\Values\UserGroupRefList
765
     */
766
    public function loadUserGroupsOfUser($userId, Request $request)
767
    {
768
        $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0;
769
        $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : 25;
770
771
        $user = $this->userService->loadUser($userId);
772
        $userGroups = $this->userService->loadUserGroupsOfUser(
773
            $user,
774
            $offset >= 0 ? $offset : 0,
775
            $limit >= 0 ? $limit : 25
776
        );
777
778
        $restUserGroups = array();
779
        foreach ($userGroups as $userGroup) {
780
            $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo();
781
            $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId);
782
            $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId);
783
784
            $restUserGroups[] = new Values\RestUserGroup(
785
                $userGroup,
786
                $contentType,
787
                $userGroupContentInfo,
788
                $userGroupLocation,
789
                $this->contentService->loadRelations($userGroup->getVersionInfo())
790
            );
791
        }
792
793
        return new Values\CachedValue(
794
            new Values\UserGroupRefList($restUserGroups, $request->getPathInfo(), $userId),
795
            array('locationId' => $user->contentInfo->mainLocationId)
796
        );
797
    }
798
799
    /**
800
     * Loads the users of the group with the given path.
801
     *
802
     * @param $groupPath
803
     *
804
     * @return \eZ\Publish\Core\REST\Server\Values\UserList|\eZ\Publish\Core\REST\Server\Values\UserRefList
805
     */
806 View Code Duplication
    public function loadUsersFromGroup($groupPath, Request $request)
807
    {
808
        $userGroupLocation = $this->locationService->loadLocation(
809
            $this->extractLocationIdFromPath($groupPath)
810
        );
811
812
        $userGroup = $this->userService->loadUserGroup(
813
            $userGroupLocation->contentId
814
        );
815
816
        $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0;
817
        $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : 25;
818
819
        $users = $this->userService->loadUsersOfUserGroup(
820
            $userGroup,
821
            $offset >= 0 ? $offset : 0,
822
            $limit >= 0 ? $limit : 25
823
        );
824
825
        $restUsers = array();
826
        foreach ($users as $user) {
827
            $userContentInfo = $user->getVersionInfo()->getContentInfo();
828
            $userLocation = $this->locationService->loadLocation($userContentInfo->mainLocationId);
829
            $contentType = $this->contentTypeService->loadContentType($userContentInfo->contentTypeId);
830
831
            $restUsers[] = new Values\RestUser(
832
                $user,
833
                $contentType,
834
                $userContentInfo,
835
                $userLocation,
836
                $this->contentService->loadRelations($user->getVersionInfo())
837
            );
838
        }
839
840
        if ($this->getMediaType($request) === 'application/vnd.ez.api.userlist') {
841
            return new Values\CachedValue(
842
                new Values\UserList($restUsers, $request->getPathInfo()),
843
                array('locationId' => $userGroupLocation->id)
844
            );
845
        }
846
847
        return new Values\CachedValue(
848
            new Values\UserRefList($restUsers, $request->getPathInfo()),
849
            array('locationId' => $userGroupLocation->id)
850
        );
851
    }
852
853
    /**
854
     * Unassigns the user from a user group.
855
     *
856
     * @param $userId
857
     * @param $groupPath
858
     *
859
     * @throws \eZ\Publish\Core\REST\Server\Exceptions\ForbiddenException
860
     *
861
     * @return \eZ\Publish\Core\REST\Server\Values\UserGroupRefList
862
     */
863
    public function unassignUserFromUserGroup($userId, $groupPath)
864
    {
865
        $user = $this->userService->loadUser($userId);
866
        $userGroupLocation = $this->locationService->loadLocation(trim($groupPath, '/'));
867
868
        $userGroup = $this->userService->loadUserGroup(
869
            $userGroupLocation->contentId
870
        );
871
872
        try {
873
            $this->userService->unAssignUserFromUserGroup($user, $userGroup);
874
        } catch (ApiExceptions\InvalidArgumentException $e) {
875
            // User is not in the group
876
            throw new Exceptions\ForbiddenException($e->getMessage());
877
        }
878
879
        $userGroups = $this->userService->loadUserGroupsOfUser($user);
880
        $restUserGroups = array();
881
        foreach ($userGroups as $userGroup) {
882
            $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo();
883
            $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId);
884
            $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId);
885
886
            $restUserGroups[] = new Values\RestUserGroup(
887
                $userGroup,
888
                $contentType,
889
                $userGroupContentInfo,
890
                $userGroupLocation,
891
                $this->contentService->loadRelations($userGroup->getVersionInfo())
892
            );
893
        }
894
895
        return new Values\UserGroupRefList(
896
            $restUserGroups,
897
            $this->router->generate(
898
                'ezpublish_rest_loadUserGroupsOfUser',
899
                array('userId' => $userId)
900
            ),
901
            $userId
902
        );
903
    }
904
905
    /**
906
     * Assigns the user to a user group.
907
     *
908
     * @param $userId
909
     *
910
     * @throws \eZ\Publish\Core\REST\Server\Exceptions\ForbiddenException
911
     *
912
     * @return \eZ\Publish\Core\REST\Server\Values\UserGroupRefList
913
     */
914
    public function assignUserToUserGroup($userId, Request $request)
915
    {
916
        $user = $this->userService->loadUser($userId);
917
918
        try {
919
            $userGroupLocation = $this->locationService->loadLocation(
920
                $this->extractLocationIdFromPath($request->query->get('group'))
921
            );
922
        } catch (ApiExceptions\NotFoundException $e) {
923
            throw new Exceptions\ForbiddenException($e->getMessage());
924
        }
925
926
        try {
927
            $userGroup = $this->userService->loadUserGroup(
928
                $userGroupLocation->contentId
929
            );
930
        } catch (ApiExceptions\NotFoundException $e) {
931
            throw new Exceptions\ForbiddenException($e->getMessage());
932
        }
933
934
        try {
935
            $this->userService->assignUserToUserGroup($user, $userGroup);
936
        } catch (ApiExceptions\NotFoundException $e) {
937
            throw new Exceptions\ForbiddenException($e->getMessage());
938
        }
939
940
        $userGroups = $this->userService->loadUserGroupsOfUser($user);
941
        $restUserGroups = array();
942
        foreach ($userGroups as $userGroup) {
943
            $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo();
944
            $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId);
945
            $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId);
946
947
            $restUserGroups[] = new Values\RestUserGroup(
948
                $userGroup,
949
                $contentType,
950
                $userGroupContentInfo,
951
                $userGroupLocation,
952
                $this->contentService->loadRelations($userGroup->getVersionInfo())
953
            );
954
        }
955
956
        return new Values\UserGroupRefList(
957
            $restUserGroups,
958
            $this->router->generate(
959
                'ezpublish_rest_loadUserGroupsOfUser',
960
                array('userId' => $userId)
961
            ),
962
            $userId
963
        );
964
    }
965
966
    /**
967
     * Creates a new session based on the credentials provided as POST parameters.
968
     *
969
     * @throws \eZ\Publish\Core\Base\Exceptions\UnauthorizedException If the login or password are incorrect or invalid CSRF
970
     *
971
     * @return Values\UserSession|Values\Conflict
972
     */
973
    public function createSession(Request $request)
974
    {
975
        /** @var $sessionInput \eZ\Publish\Core\REST\Server\Values\SessionInput */
976
        $sessionInput = $this->inputDispatcher->parse(
977
            new Message(
978
                array('Content-Type' => $request->headers->get('Content-Type')),
979
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
980
            )
981
        );
982
        $request->attributes->set('username', $sessionInput->login);
983
        $request->attributes->set('password', $sessionInput->password);
984
985
        try {
986
            $csrfToken = '';
987
            $csrfTokenManager = $this->container->get('security.csrf.token_manager', ContainerInterface::NULL_ON_INVALID_REFERENCE);
988
            $session = $request->getSession();
989
            if ($session->isStarted()) {
990
                if ($csrfTokenManager) {
991
                    $csrfToken = $request->headers->get('X-CSRF-Token');
992
                    if (
993
                        !$csrfTokenManager->isTokenValid(
994
                            new CsrfToken(
995
                                $this->container->getParameter('ezpublish_rest.csrf_token_intention'),
996
                                $csrfToken
0 ignored issues
show
Bug introduced by
It seems like $csrfToken defined by $request->headers->get('X-CSRF-Token') on line 991 can also be of type array; however, Symfony\Component\Securi...srfToken::__construct() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
997
                            )
998
                        )
999
                    ) {
1000
                        throw new UnauthorizedException('Missing or invalid CSRF token', $csrfToken);
0 ignored issues
show
Bug introduced by
It seems like $csrfToken defined by $request->headers->get('X-CSRF-Token') on line 991 can also be of type array; however, eZ\Publish\Core\Base\Exc...xception::__construct() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1001
                    }
1002
                }
1003
            }
1004
1005
            $authenticator = $this->container->get('ezpublish_rest.session_authenticator');
1006
            $token = $authenticator->authenticate($request);
1007
            // If CSRF token has not been generated yet (i.e. session not started), we generate it now.
1008
            // This will seamlessly start the session.
1009
            if ($csrfTokenManager && !$csrfToken) {
1010
                $csrfToken = $csrfTokenManager->getToken(
1011
                    $this->container->getParameter('ezpublish_rest.csrf_token_intention')
1012
                )->getValue();
1013
            }
1014
1015
            return new Values\UserSession(
1016
                $token->getUser()->getAPIUser(),
1017
                $session->getName(),
1018
                $session->getId(),
1019
                $csrfToken,
1020
                !$token->hasAttribute('isFromSession')
1021
            );
1022
        } catch (Exceptions\UserConflictException $e) {
1023
            // Already logged in with another user, this will be converted to HTTP status 409
1024
            return new Values\Conflict();
1025
        } catch (AuthenticationException $e) {
1026
            throw new UnauthorizedException('Invalid login or password', $request->getPathInfo());
1027
        } catch (AccessDeniedException $e) {
1028
            throw new UnauthorizedException($e->getMessage(), $request->getPathInfo());
1029
        }
1030
    }
1031
1032
    /**
1033
     * Refresh given session.
1034
     *
1035
     * @param string $sessionId
1036
     *
1037
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
1038
     *
1039
     * @return \eZ\Publish\Core\REST\Server\Values\UserSession
1040
     */
1041
    public function refreshSession($sessionId, Request $request)
1042
    {
1043
        /** @var $session \Symfony\Component\HttpFoundation\Session\Session */
1044
        $session = $request->getSession();
1045
        $inputCsrf = $request->headers->get('X-CSRF-Token');
1046
        if ($session === null || !$session->isStarted() || $session->getId() != $sessionId) {
1047
            throw new RestNotFoundException('Session not valid');
1048
        }
1049
1050
        return new Values\UserSession(
1051
            $this->repository->getCurrentUser(),
1052
            $session->getName(),
1053
            $session->getId(),
1054
            $inputCsrf,
0 ignored issues
show
Bug introduced by
It seems like $inputCsrf defined by $request->headers->get('X-CSRF-Token') on line 1045 can also be of type array; however, eZ\Publish\Core\REST\Ser...rSession::__construct() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1055
            false
1056
        );
1057
    }
1058
1059
    /**
1060
     * Deletes given session.
1061
     *
1062
     * @param string $sessionId
1063
     *
1064
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
1065
     *
1066
     * @throws RestNotFoundException
1067
     */
1068
    public function deleteSession($sessionId, Request $request)
1069
    {
1070
        /** @var $session \Symfony\Component\HttpFoundation\Session\Session */
1071
        $session = $this->container->get('session');
1072
        if (!$session->isStarted() || $session->getId() != $sessionId) {
1073
            throw new RestNotFoundException("Session not found: '{$sessionId}'.");
1074
        }
1075
1076
        return new Values\DeletedUserSession(
1077
            $this->container->get('ezpublish_rest.session_authenticator')->logout($request)
1078
        );
1079
    }
1080
1081
    /**
1082
     * Extracts and returns an item id from a path, e.g. /1/2/58 => 58.
1083
     *
1084
     * @param string $path
1085
     *
1086
     * @return mixed
1087
     */
1088
    private function extractLocationIdFromPath($path)
1089
    {
1090
        $pathParts = explode('/', $path);
1091
1092
        return array_pop($pathParts);
1093
    }
1094
}
1095