From 0572305c36d653f03bcb41d5d761489080943990 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Tue, 17 Sep 2024 16:03:32 +0200 Subject: [PATCH] delete old controllers which methods were split --- src/lib/Server/Controller/Content.php | 2429 ---------------- src/lib/Server/Controller/ContentType.php | 2483 ----------------- src/lib/Server/Controller/Language.php | 129 - src/lib/Server/Controller/Location.php | 852 ------ src/lib/Server/Controller/ObjectState.php | 1023 ------- src/lib/Server/Controller/Role.php | 1990 ------------- src/lib/Server/Controller/Section.php | 488 ---- .../Server/Controller/SessionController.php | 499 ---- src/lib/Server/Controller/Trash.php | 409 --- src/lib/Server/Controller/URLAlias.php | 386 --- src/lib/Server/Controller/URLWildcard.php | 322 --- src/lib/Server/Controller/User.php | 2416 ---------------- 12 files changed, 13426 deletions(-) delete mode 100644 src/lib/Server/Controller/Content.php delete mode 100644 src/lib/Server/Controller/ContentType.php delete mode 100644 src/lib/Server/Controller/Language.php delete mode 100644 src/lib/Server/Controller/Location.php delete mode 100644 src/lib/Server/Controller/ObjectState.php delete mode 100644 src/lib/Server/Controller/Role.php delete mode 100644 src/lib/Server/Controller/Section.php delete mode 100644 src/lib/Server/Controller/SessionController.php delete mode 100644 src/lib/Server/Controller/Trash.php delete mode 100644 src/lib/Server/Controller/URLAlias.php delete mode 100644 src/lib/Server/Controller/URLWildcard.php delete mode 100644 src/lib/Server/Controller/User.php diff --git a/src/lib/Server/Controller/Content.php b/src/lib/Server/Controller/Content.php deleted file mode 100644 index b2bf9f0b..00000000 --- a/src/lib/Server/Controller/Content.php +++ /dev/null @@ -1,2429 +0,0 @@ - false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'Executes a query and returns View including the results. The View input reflects the criteria model of the public PHP API. Deprecated as of eZ Platform 1.0 and will respond 301, use POST /views instead.', - tags: [ - 'Views', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'The View in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The View input in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_MOVED_PERMANENTLY => [ - 'description' => 'Moved permanently.', - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objects', - name: 'Create content item', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a draft assigned to the authenticated user. If a different user ID is given in the input, the draft is assigned to the given user but this action requires special permissions for the authenticated user (this is useful for content staging where the transfer process does not have to authenticate with the user who created the content item in the source server). The user needs to publish the content item if it should be visible.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'Content - If set, all information for the content item including the embedded current version is returned in XML or JSON format. ContentInfo - If set, all information for the content item (excluding the current version) is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The ContentCreate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/POST/ContentCreate.xml.example', - ], - 'application/vnd.ibexa.api.ContentCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/POST/ContentCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.Content+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Content', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/GET/Content.xml.example', - ], - 'application/vnd.ibexa.api.Content+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/GET/Content.json.example', - ], - 'application/vnd.ibexa.api.ContentInfo+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentInfoWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/PATCH/ContentInfo.xml.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition or the validation on a field fails.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create this Object in this Location.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the parent Location specified in the request body does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects', - name: 'Load content by remote ID', - openapi: new Model\Operation( - summary: 'Loads content item for a given remote ID.', - tags: [ - 'Objects', - ], - parameters: [ - ], - responses: [ - Response::HTTP_TEMPORARY_REDIRECT => [ - 'description' => 'Temporary redirect.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content with the given remote ID does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}', - name: 'Load content', - openapi: new Model\Operation( - summary: 'Loads the content item for the given ID. Depending on the Accept header the current version is embedded (i.e. the current published version or if it does not exist, the draft of the authenticated user).', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'Content - If set, all information for the content item including the embedded current version is returned in XML or JSON format. ContentInfo - If set, all information for the content item (excluding the current version) is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'If the provided ETag matches the current ETag then a "304 Not Modified" is returned. The ETag changes if the meta data has changed, this happens also if there is a new published version.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Content+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Content', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/GET/Content.xml.example', - ], - 'application/vnd.ibexa.api.Content+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/GET/Content.json.example', - ], - 'application/vnd.ibexa.api.ContentInfo+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentInfo', - ], - ], - 'application/vnd.ibexa.api.ContentInfo+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentInfoWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/PATCH/ContentInfo.xml.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this object. This could also happen if there is no published version yet and another user owns a draft of this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the ID is not found.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/objects/{contentId}', - name: 'Update content', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'This method updates the content metadata which is independent from a version. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, all information for the content item (excluding the current version) is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-match', - in: 'header', - required: true, - description: 'Causes to patch only if the specified ETag is the current one. Otherwise a 412 is returned.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The ContentUpdate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentInfo', - ], - ], - 'application/vnd.ibexa.api.ContentUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentInfoWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/PATCH/ContentInfo.xml.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.ContentInfo+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentInfo', - ], - ], - 'application/vnd.ibexa.api.ContentInfo+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentInfoWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/PATCH/ContentInfo.xml.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update this object.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content ID does not exist.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - the current ETag does not match with the one provided in the If-Match header.', - ], - Response::HTTP_UNSUPPORTED_MEDIA_TYPE => [ - 'description' => 'Error - the media-type is not one of those specified in headers.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/objects/{contentId}', - name: 'Delete Content', - openapi: new Model\Operation( - summary: 'Deletes content item. If content item has multiple Locations, all of them will be deleted via delete a subtree.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'The content item is deleted.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - content item was not found.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this content item.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/objects/{contentId}/translations/{languageCode}', - name: 'Delete translation (permanently)', - openapi: new Model\Operation( - summary: 'Permanently deletes a translation from all versions of a content item.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'languageCode', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete content item (content/remove policy).', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item was not found.', - ], - Response::HTTP_NOT_ACCEPTABLE => [ - 'description' => 'Error - the given translation does not exist for the content item.', - ], - Response::HTTP_CONFLICT => [ - 'description' => 'Error - the specified translation is the only one any version has or is the main translation.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/currentversion', - name: 'Get current version', - openapi: new Model\Operation( - summary: 'Redirects to the current version of the content item.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Version+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Version', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.xml.example', - ], - 'application/vnd.ibexa.api.Version+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.json.example', - ], - ], - ], - Response::HTTP_TEMPORARY_REDIRECT => [ - 'description' => 'Temporary redirect.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the resource does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objects/{contentId}/currentversion', - name: 'Create a draft from current version', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'The system creates a new draft as a copy of the current version. COPY or POST with header X-HTTP-Method-Override COPY.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated version is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Created', - 'content' => [ - 'application/vnd.ibexa.api.Version+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Version', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.xml.example', - ], - 'application/vnd.ibexa.api.Version+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update this content item.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the current version is already a draft.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item was not found.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/versions', - name: 'List versions', - openapi: new Model\Operation( - summary: 'Returns a list of all versions of the content item. This method does not include fields and relations in the version elements of the response.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the version list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.VersionList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/GET/VersionList.xml.example', - ], - 'application/vnd.ibexa.api.VersionList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/GET/VersionList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read the versions.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}', - name: 'Load version', - openapi: new Model\Operation( - summary: 'Loads a specific version of a content item. This method returns Fields and relations.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'Only return the version if the given ETag is the not current one, otherwise a 304 is returned.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the version list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Version+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Version', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.xml.example', - ], - 'application/vnd.ibexa.api.Version+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.json.example', - ], - ], - ], - Response::HTTP_NOT_MODIFIED => [ - 'description' => 'Error - the ETag does not match the current one.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the ID or version is not found.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}', - name: 'Update version', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'A specific draft is updated. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated version is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-match', - in: 'header', - required: true, - description: 'Performs the patch only if the specified ETag is the current one.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The VersionUpdate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.VersionUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/PATCH/VersionUpdate.xml.example', - ], - 'application/vnd.ibexa.api.VersionUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionUpdateWrapper', - ], - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Version+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Version', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.xml.example', - ], - 'application/vnd.ibexa.api.Version+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update this version.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the version is not allowed to change - i.e. version is not a DRAFT.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content ID or version ID does not exist.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - the current ETag does not match with the one provided in the If-Match header.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}', - name: 'Create a draft from a version', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'The system creates a new draft as a copy of the given version. COPY or POST with header X-HTTP-Method-Override COPY.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated version is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Created.', - 'content' => [ - 'application/vnd.ibexa.api.Version+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Version', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.xml.example', - ], - 'application/vnd.ibexa.api.Version+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/GET/Version.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item was not found.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}', - name: 'Delete content version', - openapi: new Model\Operation( - summary: 'Deletes the content version.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - the version is deleted.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item or version were not found.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this version.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the version is in published state.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}/translations/{languageCode}', - name: 'Delete translation from version draft', - openapi: new Model\Operation( - summary: 'Removes a translation from a version draft.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'languageCode', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - removes a translation from a version draft.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this translation.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the version is not in draft state.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item or version number were not found.', - ], - Response::HTTP_NOT_ACCEPTABLE => [ - 'description' => 'Error - the given translation does not exist for the version.', - ], - Response::HTTP_CONFLICT => [ - 'description' => 'Error - the specified translation is the only one the version has or is the main translation.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}/relations', - name: 'Load Relations of content item version', - openapi: new Model\Operation( - summary: 'Loads the Relations of the given version.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Relation is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.RelationList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RelationList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/GET/RelationList.xml.example', - ], - 'application/vnd.ibexa.api.RelationList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RelationListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/GET/RelationList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item was not found.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}/relations', - name: 'Create new Relation', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new Relation of type COMMON for the given draft.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated version is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The RelationCreate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.RelationCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RelationCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/POST/RelationCreate.xml.example', - ], - 'application/vnd.ibexa.api.RelationCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RelationCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/POST/RelationCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.Relation+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Relation', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/relation_id/GET/Relation.xml.example', - ], - 'application/vnd.ibexa.api.Relation+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RelationWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/POST/Relation.json.example', - ], - ], - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}/relations/{relationId}', - name: 'Load Relation', - openapi: new Model\Operation( - summary: 'Loads a Relation for the given content item.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Relation is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'relationId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - loads a Relation for the given content item.', - 'content' => [ - 'application/vnd.ibexa.api.Relation+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Relation', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/relation_id/GET/Relation.xml.example', - ], - 'application/vnd.ibexa.api.Relation+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RelationWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/versions/version_no/relations/POST/Relation.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item with the given ID or the Relation does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/objects/{contentId}/versions/{versionNo}/relations/{relationId}', - name: 'Delete Relation', - openapi: new Model\Operation( - summary: 'Deletes a Relation of the given draft.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'versionNo', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'relationId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - deleted a Relation of the given draft.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this Relation.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the Relation is not of type COMMON or the given version is not a draft.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - content item or the Relation were not found in the given version.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/relations', - name: 'Load Relations of content item', - openapi: new Model\Operation( - summary: 'Redirects to the Relations of the current version.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_TEMPORARY_REDIRECT => [ - 'description' => 'Temporary redirect.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item was not found.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objects/{contentId}/locations', - name: 'Create new Location for content item', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new Location for the given content item.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new Location is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The LocationCreate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.LocationCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/LocationCreate.xml.example', - ], - 'application/vnd.ibexa.api.LocationCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/LocationCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.Location+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Location', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.xml.example', - ], - 'application/vnd.ibexa.api.Location+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create this Location.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - a Location under the given parent ID already exists.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/locations', - name: 'Get Locations for content item', - openapi: new Model\Operation( - summary: 'Loads all Locations for the given content item.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Location list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.LocationList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/GET/LocationList.xml.example', - ], - 'application/vnd.ibexa.api.LocationList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/GET/LocationList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item with the given ID does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objects/{contentId}/objectstates', - name: 'Get Object states of content item', - openapi: new Model\Operation( - summary: 'Returns the Object states of a content item', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Object states are returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the Object state.', - 'content' => [ - 'application/vnd.ibexa.api.ContentObjectStates+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentObjectStates', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/objectstates/PATCH/ContentObjectStates.response.xml.example', - ], - 'application/vnd.ibexa.api.ContentObjectStates+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentObjectStatesWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/objectstates/GET/ContentObjectStates.json.example', - ], - ], - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content item does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/objects/{contentId}/objectstates', - name: 'Set Object states of content item', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates Object states of a content item. An Object state in the input overrides the state of the Object state group. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Object state is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The content item Object states input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentObjectStates+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentObjectStates', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/objectstates/PATCH/ContentObjectStates.response.xml.example', - ], - 'application/vnd.ibexa.api.ContentObjectStates+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentObjectStatesWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/objectstates/GET/ContentObjectStates.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'OK - Object state updated.', - 'content' => [ - 'application/vnd.ibexa.api.ContentObjectStates+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentObjectStates', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/objectstates/PATCH/ContentObjectStates.response.xml.example', - ], - 'application/vnd.ibexa.api.ContentObjectStates+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentObjectStatesWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/objectstates/GET/ContentObjectStates.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to set an Object state.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - The input contains multiple Object states of the same Object state group.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - The current ETag does not match the one provided in the If-Match header.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objects/{contentId}/hide', - name: 'Hide content item', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'Makes or keep the content item invisible', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'OK - Object item is hidden.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to change Object item visibility.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content item was not found.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objects/{contentId}/reveal', - name: 'Reveal content item', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'Makes or keep the content item visible', - tags: [ - 'Objects', - ], - parameters: [ - new Model\Parameter( - name: 'contentId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'OK - Object item is revealed.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to change Object item visibility.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content item was not found.', - ], - ], - ), -)] -/** - * Content controller. - */ -class Content extends RestController -{ - /** - * Loads a content info by remote ID. - * - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException - * - * @return \Ibexa\Rest\Server\Values\TemporaryRedirect - */ - public function redirectContent(Request $request) - { - if (!$request->query->has('remoteId')) { - throw new BadRequestException("'remoteId' parameter is required."); - } - - $contentInfo = $this->repository->getContentService()->loadContentInfoByRemoteId( - $request->query->get('remoteId') - ); - - return new Values\TemporaryRedirect( - $this->router->generate( - 'ibexa.rest.load_content', - [ - 'contentId' => $contentInfo->id, - ] - ) - ); - } - - /** - * Loads a content info, potentially with the current version embedded. - * - * @param mixed $contentId - * @param \Symfony\Component\HttpFoundation\Request $request - * - * @return \Ibexa\Rest\Server\Values\RestContent - */ - public function loadContent($contentId, Request $request) - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - - $mainLocation = null; - if (!empty($contentInfo->mainLocationId)) { - $mainLocation = $this->repository->getLocationService()->loadLocation($contentInfo->mainLocationId); - } - - $contentType = $this->repository->getContentTypeService()->loadContentType($contentInfo->contentTypeId); - - $contentVersion = null; - $relations = null; - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.content') { - $languages = Language::ALL; - if ($request->query->has('languages')) { - $languages = explode(',', $request->query->get('languages')); - } - - $contentVersion = $this->repository->getContentService()->loadContent($contentId, $languages); - $relations = $this->repository->getContentService()->loadRelations($contentVersion->getVersionInfo()); - } - - $restContent = new Values\RestContent( - $contentInfo, - $mainLocation, - $contentVersion, - $contentType, - $relations, - $request->getPathInfo() - ); - - if ($contentInfo->mainLocationId === null) { - return $restContent; - } - - return new Values\CachedValue( - $restContent, - ['locationId' => $contentInfo->mainLocationId] - ); - } - - /** - * Updates a content's metadata. - * - * @param mixed $contentId - * - * @return \Ibexa\Rest\Server\Values\RestContent - */ - public function updateContentMetadata($contentId, Request $request) - { - $updateStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - - // update section - if ($updateStruct->sectionId !== null) { - $section = $this->repository->getSectionService()->loadSection($updateStruct->sectionId); - $this->repository->getSectionService()->assignSection($contentInfo, $section); - $updateStruct->sectionId = null; - } - - // @todo Consider refactoring! ContentService::updateContentMetadata throws the same exception - // in case the updateStruct is empty and if remoteId already exists. Since REST version of update struct - // includes section ID in addition to other fields, we cannot throw exception if only sectionId property - // is set, so we must skip updating content in that case instead of allowing propagation of the exception. - foreach ($updateStruct as $propertyName => $propertyValue) { - if ($propertyName !== 'sectionId' && $propertyValue !== null) { - // update content - $this->repository->getContentService()->updateContentMetadata($contentInfo, $updateStruct); - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - break; - } - } - - try { - $locationInfo = $this->repository->getLocationService()->loadLocation($contentInfo->mainLocationId); - } catch (NotFoundException $e) { - $locationInfo = null; - } - - return new Values\RestContent( - $contentInfo, - $locationInfo - ); - } - - /** - * Loads a specific version of a given content object. - * - * @param mixed $contentId - * - * @return \Ibexa\Rest\Server\Values\TemporaryRedirect - */ - public function redirectCurrentVersion($contentId) - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - - return new Values\TemporaryRedirect( - $this->router->generate( - 'ibexa.rest.load_content_in_version', - [ - 'contentId' => $contentId, - 'versionNumber' => $contentInfo->currentVersionNo, - ] - ) - ); - } - - /** - * Loads a specific version of a given content object. - * - * @param mixed $contentId - * @param int $versionNumber - * - * @return \Ibexa\Rest\Server\Values\Version - */ - public function loadContentInVersion($contentId, $versionNumber, Request $request) - { - $languages = Language::ALL; - if ($request->query->has('languages')) { - $languages = explode(',', $request->query->get('languages')); - } - - $content = $this->repository->getContentService()->loadContent( - $contentId, - $languages, - $versionNumber - ); - $contentType = $this->repository->getContentTypeService()->loadContentType( - $content->getVersionInfo()->getContentInfo()->contentTypeId - ); - - $versionValue = new Values\Version( - $content, - $contentType, - $this->repository->getContentService()->loadRelations($content->getVersionInfo()), - $request->getPathInfo() - ); - - if ($content->contentInfo->mainLocationId === null || $content->versionInfo->status === VersionInfo::STATUS_DRAFT) { - return $versionValue; - } - - return new Values\CachedValue( - $versionValue, - ['locationId' => $content->contentInfo->mainLocationId] - ); - } - - /** - * Creates a new content draft assigned to the authenticated user. - * If a different userId is given in the input it is assigned to the - * given user but this required special rights for the authenticated - * user (this is useful for content staging where the transfer process - * does not have to authenticate with the user which created the content - * object in the source server). The user has to publish the content if - * it should be visible. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * - * @return \Ibexa\Rest\Server\Values\CreatedContent - */ - public function createContent(Request $request) - { - $contentCreate = $this->parseContentRequest($request); - - return $this->doCreateContent($request, $contentCreate); - } - - /** - * The content is deleted. If the content has locations (which is required in 4.x) - * on delete all locations assigned the content object are deleted via delete subtree. - * - * @param mixed $contentId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteContent($contentId) - { - $this->repository->getContentService()->deleteContent( - $this->repository->getContentService()->loadContentInfo($contentId) - ); - - return new Values\NoContent(); - } - - /** - * Creates a new content object as copy under the given parent location given in the destination header. - * - * @param mixed $contentId - * - * @return \Ibexa\Rest\Server\Values\ResourceCreated - */ - public function copyContent($contentId, Request $request) - { - $destination = $request->headers->get('Destination'); - - $parentLocationParts = explode('/', $destination); - $copiedContent = $this->repository->getContentService()->copyContent( - $this->repository->getContentService()->loadContentInfo($contentId), - $this->repository->getLocationService()->newLocationCreateStruct(array_pop($parentLocationParts)) - ); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_content', - ['contentId' => $copiedContent->id] - ) - ); - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - */ - public function copy(int $contentId, Request $request): Values\ResourceCreated - { - $contentService = $this->repository->getContentService(); - $locationService = $this->repository->getLocationService(); - - $contentInfo = $contentService->loadContentInfo($contentId); - - /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Location $destinationLocation */ - $destinationLocation = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent(), - ), - ); - - $copiedContent = $contentService->copyContent( - $contentInfo, - $locationService->newLocationCreateStruct($destinationLocation->getId()), - ); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_content', - ['contentId' => $copiedContent->id], - ) - ); - } - - /** - * Deletes a translation from all the Versions of the given Content Object. - * - * If any non-published Version contains only the Translation to be deleted, that entire Version will be deleted - * - * @param int $contentId - * @param string $languageCode - * - * @return \Ibexa\Rest\Server\Values\NoContent - * - * @throws \Exception - */ - public function deleteContentTranslation($contentId, $languageCode) - { - $contentService = $this->repository->getContentService(); - - $this->repository->beginTransaction(); - try { - $contentInfo = $contentService->loadContentInfo($contentId); - $contentService->deleteTranslation( - $contentInfo, - $languageCode - ); - - $this->repository->commit(); - - return new Values\NoContent(); - } catch (\Exception $e) { - $this->repository->rollback(); - throw $e; - } - } - - /** - * Returns a list of all versions of the content. This method does not - * include fields and relations in the Version elements of the response. - * - * @param mixed $contentId - * - * @return \Ibexa\Rest\Server\Values\VersionList - */ - public function loadContentVersions($contentId, Request $request) - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - - return new Values\VersionList( - $this->repository->getContentService()->loadVersions($contentInfo), - $request->getPathInfo() - ); - } - - /** - * The version is deleted. - * - * @param mixed $contentId - * @param mixed $versionNumber - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteContentVersion($contentId, $versionNumber) - { - $versionInfo = $this->repository->getContentService()->loadVersionInfo( - $this->repository->getContentService()->loadContentInfo($contentId), - $versionNumber - ); - - if ($versionInfo->isPublished()) { - throw new ForbiddenException('Versions with PUBLISHED status cannot be deleted'); - } - - $this->repository->getContentService()->deleteVersion( - $versionInfo - ); - - return new Values\NoContent(); - } - - /** - * Remove the given Translation from the given Version Draft. - * - * @param int $contentId - * @param int $versionNumber - * @param string $languageCode - * - * @return \Ibexa\Rest\Server\Values\NoContent - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - */ - public function deleteTranslationFromDraft($contentId, $versionNumber, $languageCode) - { - $contentService = $this->repository->getContentService(); - $versionInfo = $contentService->loadVersionInfoById($contentId, $versionNumber); - - if (!$versionInfo->isDraft()) { - throw new ForbiddenException('Translation can be deleted from a DRAFT version only'); - } - - $contentService->deleteTranslationFromDraft($versionInfo, $languageCode); - - return new Values\NoContent(); - } - - /** - * The system creates a new draft version as a copy from the given version. - * - * @param mixed $contentId - * @param mixed $versionNumber - * - * @return \Ibexa\Rest\Server\Values\CreatedVersion - */ - public function createDraftFromVersion($contentId, $versionNumber) - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - $contentType = $this->repository->getContentTypeService()->loadContentType($contentInfo->contentTypeId); - $contentDraft = $this->repository->getContentService()->createContentDraft( - $contentInfo, - $this->repository->getContentService()->loadVersionInfo($contentInfo, $versionNumber) - ); - - return new Values\CreatedVersion( - [ - 'version' => new Values\Version( - $contentDraft, - $contentType, - $this->repository->getContentService()->loadRelations($contentDraft->getVersionInfo()) - ), - ] - ); - } - - /** - * The system creates a new draft version as a copy from the current version. - * - * @param mixed $contentId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException if the current version is already a draft - * - * @return \Ibexa\Rest\Server\Values\CreatedVersion - */ - public function createDraftFromCurrentVersion($contentId) - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - $contentType = $this->repository->getContentTypeService()->loadContentType($contentInfo->contentTypeId); - $versionInfo = $this->repository->getContentService()->loadVersionInfo( - $contentInfo - ); - - if ($versionInfo->isDraft()) { - throw new ForbiddenException('Current version already has DRAFT status'); - } - - $contentDraft = $this->repository->getContentService()->createContentDraft($contentInfo); - - return new Values\CreatedVersion( - [ - 'version' => new Values\Version( - $contentDraft, - $contentType, - $this->repository->getContentService()->loadRelations($contentDraft->getVersionInfo()) - ), - ] - ); - } - - /** - * A specific draft is updated. - * - * @param mixed $contentId - * @param mixed $versionNumber - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException - * - * @return \Ibexa\Rest\Server\Values\Version - */ - public function updateVersion($contentId, $versionNumber, Request $request) - { - $contentUpdateStruct = $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - 'Url' => $this->router->generate( - 'ibexa.rest.update_version', - [ - 'contentId' => $contentId, - 'versionNumber' => $versionNumber, - ] - ), - ], - $request->getContent() - ) - ); - - $versionInfo = $this->repository->getContentService()->loadVersionInfo( - $this->repository->getContentService()->loadContentInfo($contentId), - $versionNumber - ); - - if (!$versionInfo->isDraft()) { - throw new ForbiddenException('Only versions with DRAFT status can be updated'); - } - - try { - $this->repository->getContentService()->updateContent($versionInfo, $contentUpdateStruct); - } catch (ContentValidationException $e) { - throw new BadRequestException($e->getMessage()); - } catch (ContentFieldValidationException $e) { - throw new RESTContentFieldValidationException($e); - } - - $languages = null; - if ($request->query->has('languages')) { - $languages = explode(',', $request->query->get('languages')); - } - - // Reload the content to handle languages GET parameter - $content = $this->repository->getContentService()->loadContent( - $contentId, - $languages, - $versionInfo->versionNo - ); - $contentType = $this->repository->getContentTypeService()->loadContentType( - $content->getVersionInfo()->getContentInfo()->contentTypeId - ); - - return new Values\Version( - $content, - $contentType, - $this->repository->getContentService()->loadRelations($content->getVersionInfo()), - $request->getPathInfo() - ); - } - - /** - * The content version is published. - * - * @param mixed $contentId - * @param mixed $versionNumber - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException if version $versionNumber isn't a draft - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function publishVersion($contentId, $versionNumber) - { - $versionInfo = $this->repository->getContentService()->loadVersionInfo( - $this->repository->getContentService()->loadContentInfo($contentId), - $versionNumber - ); - - if (!$versionInfo->isDraft()) { - throw new ForbiddenException('Only versions with DRAFT status can be published'); - } - - $this->repository->getContentService()->publishVersion( - $versionInfo - ); - - return new Values\NoContent(); - } - - /** - * Redirects to the relations of the current version. - * - * @param mixed $contentId - * - * @return \Ibexa\Rest\Server\Values\TemporaryRedirect - */ - public function redirectCurrentVersionRelations($contentId) - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - - return new Values\TemporaryRedirect( - $this->router->generate( - 'ibexa.rest.redirect_current_version_relations', - [ - 'contentId' => $contentId, - 'versionNumber' => $contentInfo->currentVersionNo, - ] - ) - ); - } - - /** - * Loads the relations of the given version. - * - * @param mixed $contentId - * @param mixed $versionNumber - * - * @return \Ibexa\Rest\Server\Values\RelationList - */ - public function loadVersionRelations($contentId, $versionNumber, Request $request) - { - $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0; - $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : -1; - - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - $relationList = $this->repository->getContentService()->loadRelations( - $this->repository->getContentService()->loadVersionInfo($contentInfo, $versionNumber) - ); - - $relationList = array_slice( - $relationList, - $offset >= 0 ? $offset : 0, - $limit >= 0 ? $limit : null - ); - - $relationListValue = new Values\RelationList( - $relationList, - $contentId, - $versionNumber, - $request->getPathInfo() - ); - - if ($contentInfo->mainLocationId === null) { - return $relationListValue; - } - - return new Values\CachedValue( - $relationListValue, - ['locationId' => $contentInfo->mainLocationId] - ); - } - - /** - * Loads a relation for the given content object and version. - * - * @param mixed $contentId - * @param int $versionNumber - * @param mixed $relationId - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\RestRelation - */ - public function loadVersionRelation($contentId, $versionNumber, $relationId, Request $request) - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - $relationList = $this->repository->getContentService()->loadRelations( - $this->repository->getContentService()->loadVersionInfo($contentInfo, $versionNumber) - ); - - foreach ($relationList as $relation) { - if ($relation->id == $relationId) { - $relation = new Values\RestRelation($relation, $contentId, $versionNumber); - - if ($contentInfo->mainLocationId === null) { - return $relation; - } - - return new Values\CachedValue( - $relation, - ['locationId' => $contentInfo->mainLocationId] - ); - } - } - - throw new Exceptions\NotFoundException("Relation not found: '{$request->getPathInfo()}'."); - } - - /** - * Deletes a relation of the given draft. - * - * @param mixed $contentId - * @param int $versionNumber - * @param mixed $relationId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function removeRelation($contentId, $versionNumber, $relationId, Request $request) - { - $versionInfo = $this->repository->getContentService()->loadVersionInfo( - $this->repository->getContentService()->loadContentInfo($contentId), - $versionNumber - ); - - $versionRelations = $this->repository->getContentService()->loadRelations($versionInfo); - foreach ($versionRelations as $relation) { - if ($relation->id == $relationId) { - if ($relation->type !== Relation::COMMON) { - throw new ForbiddenException('Relation is not of type COMMON'); - } - - if (!$versionInfo->isDraft()) { - throw new ForbiddenException('Relation of type COMMON can only be removed from drafts'); - } - - $this->repository->getContentService()->deleteRelation($versionInfo, $relation->getDestinationContentInfo()); - - return new Values\NoContent(); - } - } - - throw new Exceptions\NotFoundException("Could not find Relation '{$request->getPathInfo()}'."); - } - - /** - * Creates a new relation of type COMMON for the given draft. - * - * @param mixed $contentId - * @param int $versionNumber - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException if version $versionNumber isn't a draft - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException if a relation to the same content already exists - * - * @return \Ibexa\Rest\Server\Values\CreatedRelation - */ - public function createRelation($contentId, $versionNumber, Request $request) - { - $destinationContentId = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - $versionInfo = $this->repository->getContentService()->loadVersionInfo($contentInfo, $versionNumber); - if (!$versionInfo->isDraft()) { - throw new ForbiddenException('Relation of type COMMON can only be added to drafts'); - } - - try { - $destinationContentInfo = $this->repository->getContentService()->loadContentInfo($destinationContentId); - } catch (NotFoundException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - $existingRelations = $this->repository->getContentService()->loadRelations($versionInfo); - foreach ($existingRelations as $existingRelation) { - if ($existingRelation->getDestinationContentInfo()->id == $destinationContentId) { - throw new ForbiddenException('Relation of type COMMON to the selected destination content ID already exists'); - } - } - - $relation = $this->repository->getContentService()->addRelation($versionInfo, $destinationContentInfo); - - return new Values\CreatedRelation( - [ - 'relation' => new Values\RestRelation($relation, $contentId, $versionNumber), - ] - ); - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - */ - public function hideContent(int $contentId): Values\NoContent - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - - $this->repository->getContentService()->hideContent($contentInfo); - - return new Values\NoContent(); - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - */ - public function revealContent(int $contentId): Values\NoContent - { - $contentInfo = $this->repository->getContentService()->loadContentInfo($contentId); - - $this->repository->getContentService()->revealContent($contentInfo); - - return new Values\NoContent(); - } - - /** - * Creates and executes a content view. - * - * @deprecated Since platform 1.0. Forwards the request to the new /views location, but returns a 301. - * - * @return \Ibexa\Rest\Server\Values\RestExecutedView - */ - public function createView() - { - $response = $this->forward('ezpublish_rest.controller.views:createView'); - - // Add 301 status code and location href - $response->setStatusCode(301); - $response->headers->set('Location', $this->router->generate('ibexa.rest.views.create')); - - return $response; - } - - /** - * @param string $controller - * - * @return \Symfony\Component\HttpFoundation\Response - */ - protected function forward($controller) - { - $path['_controller'] = $controller; - $subRequest = $this->container->get('request_stack')->getCurrentRequest()->duplicate(null, null, $path); - - return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); - } - - /** - * @param \Symfony\Component\HttpFoundation\Request $request - * - * @return mixed - */ - protected function parseContentRequest(Request $request) - { - return $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type'), 'Url' => $request->getPathInfo()], - $request->getContent() - ) - ); - } - - /** - * @param \Symfony\Component\HttpFoundation\Request $request - * @param \Ibexa\Rest\Server\Values\RestContentCreateStruct $contentCreate - * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - * - * @return \Ibexa\Rest\Server\Values\CreatedContent - */ - protected function doCreateContent(Request $request, RestContentCreateStruct $contentCreate) - { - try { - $contentCreateStruct = $contentCreate->contentCreateStruct; - $contentCreate->locationCreateStruct->sortField = $contentCreateStruct->contentType->defaultSortField; - $contentCreate->locationCreateStruct->sortOrder = $contentCreateStruct->contentType->defaultSortOrder; - - $content = $this->repository->getContentService()->createContent( - $contentCreateStruct, - [$contentCreate->locationCreateStruct] - ); - } catch (ContentValidationException $e) { - throw new BadRequestException($e->getMessage()); - } catch (ContentFieldValidationException $e) { - throw new RESTContentFieldValidationException($e); - } - - $contentValue = null; - $contentType = null; - $relations = null; - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.content') { - $contentValue = $content; - $contentType = $this->repository->getContentTypeService()->loadContentType( - $content->getVersionInfo()->getContentInfo()->contentTypeId - ); - $relations = $this->repository->getContentService()->loadRelations($contentValue->getVersionInfo()); - } - - return new Values\CreatedContent( - [ - 'content' => new Values\RestContent( - $content->contentInfo, - null, - $contentValue, - $contentType, - $relations - ), - ] - ); - } -} diff --git a/src/lib/Server/Controller/ContentType.php b/src/lib/Server/Controller/ContentType.php deleted file mode 100644 index 4166000d..00000000 --- a/src/lib/Server/Controller/ContentType.php +++ /dev/null @@ -1,2483 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns a list of content types.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeInfoList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfoList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/GET/ContentTypeInfoList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeInfoList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfoListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/GET/ContentTypeInfoList.json.example', - ], - 'application/vnd.ibexa.api.ContentTypeList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeList', - ], - ], - 'application/vnd.ibexa.api.ContentTypeList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeListWrapper', - ], - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read the content types.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/types/{contentTypeId}', - name: 'Get content type', - openapi: new Model\Operation( - summary: 'Returns the content type with the provided ID.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the content type is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the content type.', - 'content' => [ - 'application/vnd.ibexa.api.ContentType+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentType', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/PUBLISH/ContentType.xml.example', - ], - 'application/vnd.ibexa.api.ContentType+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/GET/ContentType.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read this content type.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/types/{contentTypeId}', - name: 'Create Draft', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a draft and updates it with the given data.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new content type draft is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The content type Update schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentTypeUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/POST/ContentTypeUpdate.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeUpdateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/POST/ContentTypeUpdate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Draft created.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeInfo+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfo', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/PATCH/ContentTypeInfo.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeInfo+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfoWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/PATCH/ContentTypeInfo.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create the draft.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A content type with the given new identifier already exists. A draft already exists.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/types/{contentTypeId}', - name: 'Delete content type', - openapi: new Model\Operation( - summary: 'Deletes the provided content type.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - content type deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete this content type.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - There are object instances of this content type.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/types/{contentTypeId}/fieldDefinitions', - name: 'Get Field definition list', - openapi: new Model\Operation( - summary: 'Returns all Field definitions of the provided content type.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Field definitions are returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - return a list of Field definitions.', - 'content' => [ - 'application/vnd.ibexa.api.FieldDefinitionList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitions', - ], - ], - 'application/vnd.ibexa.api.FieldDefinitionList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionsWrapper', - ], - ], - ], - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/types/{contentTypeId}/fieldDefinitions/{fieldDefinitionId}', - name: 'Get Field definition', - openapi: new Model\Operation( - summary: 'Returns the Field definition by the given ID.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Field definition is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'fieldDefinitionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the Field definition.', - 'content' => [ - 'application/vnd.ibexa.api.FieldDefinition+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinition', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.xml.example', - ], - 'application/vnd.ibexa.api.FieldDefinition+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read the content type.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/types/{contentTypeId}/draft', - name: 'Get content type draft', - openapi: new Model\Operation( - summary: 'Returns the draft of the content type with the provided ID.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the content type is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the content type.', - 'content' => [ - 'application/vnd.ibexa.api.ContentType+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentType', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/PUBLISH/ContentType.xml.example', - ], - 'application/vnd.ibexa.api.ContentType+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/GET/ContentType.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read this content type.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type does not exist or does not have a draft.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/types/{contentTypeId}/draft', - name: 'Update content type draft', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates metadata of a draft. This method does not handle Field definitions. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new content type draft is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The content type update schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentTypeUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/POST/ContentTypeUpdate.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeUpdateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/POST/ContentTypeUpdate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'Draft metadata updated.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeInfo+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfo', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/PATCH/ContentTypeInfo.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeInfo+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfoWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/PATCH/ContentTypeInfo.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to update the draft.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A content type with the given new identifier already exists.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - There is no draft for this content type.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/types/{contentTypeId}/draft', - name: 'Delete content type draft', - openapi: new Model\Operation( - summary: 'Deletes the provided content type draft.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - content type draft deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete this content type draft.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type draft does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/types/{contentTypeId}/draft/fieldDefinitions', - name: 'Get Draft Field definition list', - openapi: new Model\Operation( - summary: 'Returns all Field definitions of the provided content type Draft.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Field definitions are returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - return a list of Field definitions.', - 'content' => [ - 'application/vnd.ibexa.api.FieldDefinitionList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitions', - ], - ], - 'application/vnd.ibexa.api.FieldDefinitionList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionsWrapper', - ], - ], - ], - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type draft does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/types/{contentTypeId}/draft/fieldDefinitions', - name: 'Add content type Draft Field definition', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new Field definition for the given content type.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new Field definition is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Field Definition Create schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.FieldDefinitionCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/field_definitions/POST/FieldDefinitionCreate.xml.example', - ], - 'application/vnd.ibexa.api.FieldDefinitionCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionCreateWrapper', - ], - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Field definition created.', - 'content' => [ - 'application/vnd.ibexa.api.FieldDefinition+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinition', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.xml.example', - ], - 'application/vnd.ibexa.api.FieldDefinition+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition or validation on the Field definition fails.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to add a Field definition.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A Field definition with the same identifier already exists in the given content type. The Field definition is of singular type, already existing in the given content type. The Field definition you want to add is of a type that can\'t be added to a content type that already has content instances.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/types/{contentTypeId}/draft/fieldDefinitions/{fieldDefinitionId}', - name: 'Get content type Draft Field definition', - openapi: new Model\Operation( - summary: 'Returns the Field definition by the given ID.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Field definition is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'fieldDefinitionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the Field definition.', - 'content' => [ - 'application/vnd.ibexa.api.FieldDefinition+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinition', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.xml.example', - ], - 'application/vnd.ibexa.api.FieldDefinition+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read the content type draft.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type or draft does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/types/{contentTypeId}/draft/fieldDefinitions/{fieldDefinitionId}', - name: 'Update content type Draft Field definition', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates the attributes of a Field definition.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Field definition is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Field definition update schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'fieldDefinitionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.FieldDefinitionUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/field_definitions/field_definition_id/PATCH/FieldDefinitionUpdate.xml.example', - ], - 'application/vnd.ibexa.api.FieldDefinitionUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionUpdateWrapper', - ], - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - attributes updated.', - 'content' => [ - 'application/vnd.ibexa.api.FieldDefinition+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinition', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.xml.example', - ], - 'application/vnd.ibexa.api.FieldDefinition+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/FieldDefinitionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/field_definition_id/GET/FieldDefinition.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to update the Field definition.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A Field definition with the given identifier already exists in the given content type.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/types/{contentTypeId}/draft/fieldDefinitions/{fieldDefinitionId}', - name: 'Delete content type Draft Field definition', - openapi: new Model\Operation( - summary: 'Deletes the provided Field definition.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'fieldDefinitionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - Field definition deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete this content type.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - There is no draft of the content type assigned to the authenticated user.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/types/{contentTypeId}/groups', - name: 'Get groups of content type', - openapi: new Model\Operation( - summary: 'Returns the content type group to which content type belongs to.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the content type group list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/groups/id/DELETE/ContentTypeGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/groups/id/DELETE/ContentTypeGroupRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read this content type.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/types/{contentTypeId}/groups', - name: 'Link group to content type', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'Links a content type group to the content type and returns the updated group list.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated content type group list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/groups/id/DELETE/ContentTypeGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/groups/id/DELETE/ContentTypeGroupRefList.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to add a group.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - The content type is already assigned to the group.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/types/{contentTypeId}/groups/{id}', - name: 'Unlink group from content type', - openapi: new Model\Operation( - summary: 'Removes the given group from the content type and returns the updated group list.', - tags: [ - 'Type', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated content type group list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/groups/id/DELETE/ContentTypeGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/groups/id/DELETE/ContentTypeGroupRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete this content type.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - content type cannot be unlinked from the only remaining group.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The resource does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/typegroups', - name: 'Get content type groups', - openapi: new Model\Operation( - summary: 'Returns a list of all content type groups. If an identifier is provided, loads the content type group for this identifier.', - tags: [ - 'Type Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the content type group list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns a list of content type groups.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeGroupList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/GET/ContentTypeGroupList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroupList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/GET/ContentTypeGroupList.json.example', - ], - ], - ], - Response::HTTP_TEMPORARY_REDIRECT => [ - 'description' => 'Temporary redirect.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read content types.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type group with the given identifier does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/typegroups', - name: 'Create content type group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new content type group.', - tags: [ - 'Type Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new content type group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The content type group input schema encoded in XML or JSON.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentTypeGroupInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/POST/ContentTypeGroupInput.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroupInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/POST/ContentTypeGroupInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Content type group created.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/POST/ContentTypeGroup.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/content_type_group_id/PATCH/ContentTypeGroup.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create this content type group.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A content type group with the same identifier already exists.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/typegroups/{contentTypeGroupId}', - name: 'Get content type group', - openapi: new Model\Operation( - summary: 'Returns the content type group with provided ID.', - tags: [ - 'Type Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the content type group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the content type group.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/GET/ContentTypeInfoList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/GET/ContentTypeInfoList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read this content type group.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type group does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/typegroups/{contentTypeGroupId}', - name: 'Update content type group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates a content type group. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Type Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated content type group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The content type group input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'ETag causes patching only if the specified ETag is the current one. Otherwise a 412 is returned.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentTypeGroupInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/POST/ContentTypeGroupInput.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroupInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/POST/ContentTypeGroupInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'Content type group updated.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/POST/ContentTypeGroup.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/content_type_group_id/PATCH/ContentTypeGroup.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create this content type group.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A content type group with the given identifier already exists.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - The current ETag does not match the one provided in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/typegroups/{contentTypeGroupId}', - name: 'Delete content type group', - openapi: new Model\Operation( - summary: 'Deletes the provided content type group.', - tags: [ - 'Type Groups', - ], - parameters: [ - new Model\Parameter( - name: 'contentTypeGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - content type group deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete this content type group.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - The content type group is not empty.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The content type group does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/typegroups/{contentTypeGroupId}/types', - name: 'List content types for group', - openapi: new Model\Operation( - summary: 'Returns a list of content types in the provided group.', - tags: [ - 'Type Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the list of content type info objects or content types (including Field definitions) is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns a list on content types.', - 'content' => [ - 'application/vnd.ibexa.api.ContentTypeInfoList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfoList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/content_type_group_id/types/GET/ContentTypeInfoList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeInfoList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeInfoListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/GET/ContentTypeInfoList.json.example', - ], - 'application/vnd.ibexa.api.ContentTypeList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/GET/ContentTypeInfoList.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/GET/ContentTypeInfoList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read the content types.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/typegroups/{contentTypeGroupId}/types', - name: 'Create content type', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new content type draft in the given content type group.', - tags: [ - 'Type Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new content type or draft is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The content type Create schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'contentTypeGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ContentTypeCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/content_type_group_id/types/POST/ContentTypeCreate.xml.example', - ], - 'application/vnd.ibexa.api.ContentTypeCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/typegroups/content_type_group_id/types/POST/ContentTypeCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Content type created.', - 'content' => [ - 'application/vnd.ibexa.api.ContentType+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentType', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/types/content_type_id/draft/PUBLISH/ContentType.xml.example', - ], - 'application/vnd.ibexa.api.ContentType+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ContentTypeWrapper', - ], - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition. Validation on a Field definition fails. Validation of the content type fails, e.g. multiple Fields of a same singular Field Type are provided. Publish is set to true and the input is not complete e.g. no Field definitions are provided.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create this content type.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A content type with same identifier already exists.', - ], - ], - ), -)] -/** - * ContentType controller. - */ -class ContentType extends RestController -{ - /** - * Content type service. - * - * @var \Ibexa\Contracts\Core\Repository\ContentTypeService - */ - protected $contentTypeService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\ContentTypeService $contentTypeService - */ - public function __construct(ContentTypeService $contentTypeService) - { - $this->contentTypeService = $contentTypeService; - } - - /** - * Creates a new content type group. - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedContentTypeGroup - */ - public function createContentTypeGroup(Request $request) - { - $createStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - try { - return new Values\CreatedContentTypeGroup( - [ - 'contentTypeGroup' => $this->contentTypeService->createContentTypeGroup($createStruct), - ] - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - /** - * Updates a content type group. - * - * @param $contentTypeGroupId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeGroup - */ - public function updateContentTypeGroup($contentTypeGroupId, Request $request) - { - $createStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - try { - $this->contentTypeService->updateContentTypeGroup( - $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId), - $this->mapToGroupUpdateStruct($createStruct) - ); - - return $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId, Language::ALL); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - /** - * Returns a list of content types of the group. - * - * @param string $contentTypeGroupId - * - * @return \Ibexa\Rest\Server\Values\ContentTypeList|\Ibexa\Rest\Server\Values\ContentTypeInfoList - */ - public function listContentTypesForGroup($contentTypeGroupId, Request $request) - { - $contentTypes = $this->contentTypeService->loadContentTypes( - $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId, Language::ALL), - Language::ALL - ); - - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.contenttypelist') { - return new Values\ContentTypeList($contentTypes, $request->getPathInfo()); - } - - return new Values\ContentTypeInfoList($contentTypes, $request->getPathInfo()); - } - - /** - * The given content type group is deleted. - * - * @param mixed $contentTypeGroupId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteContentTypeGroup($contentTypeGroupId) - { - $contentTypeGroup = $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId); - - $contentTypes = $this->contentTypeService->loadContentTypes($contentTypeGroup); - if (!empty($contentTypes)) { - throw new ForbiddenException('Only empty content type groups can be deleted'); - } - - $this->contentTypeService->deleteContentTypeGroup($contentTypeGroup); - - return new Values\NoContent(); - } - - /** - * Returns a list of all content type groups. - * - * @return \Ibexa\Rest\Server\Values\ContentTypeGroupList - */ - public function loadContentTypeGroupList(Request $request) - { - if ($request->query->has('identifier')) { - $contentTypeGroup = $this->contentTypeService->loadContentTypeGroupByIdentifier( - $request->query->get('identifier') - ); - - return new Values\TemporaryRedirect( - $this->router->generate( - 'ibexa.rest.load_content_type_group', - [ - 'contentTypeGroupId' => $contentTypeGroup->id, - ] - ) - ); - } - - return new Values\ContentTypeGroupList( - $this->contentTypeService->loadContentTypeGroups(Language::ALL) - ); - } - - /** - * Returns the content type group given by id. - * - * @param $contentTypeGroupId - * - * @return \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeGroup - */ - public function loadContentTypeGroup($contentTypeGroupId) - { - return $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId, Language::ALL); - } - - /** - * Loads a content type. - * - * @param $contentTypeId - * - * @return \Ibexa\Rest\Server\Values\RestContentType - */ - public function loadContentType($contentTypeId) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId, Language::ALL); - - return new Values\RestContentType( - $contentType, - $contentType->getFieldDefinitions()->toArray() - ); - } - - /** - * Returns a list of content types. - * - * @return \Ibexa\Rest\Server\Values\ContentTypeList|\Ibexa\Rest\Server\Values\ContentTypeInfoList - */ - public function listContentTypes(Request $request) - { - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.contenttypelist') { - $return = new Values\ContentTypeList([], $request->getPathInfo()); - } else { - $return = new Values\ContentTypeInfoList([], $request->getPathInfo()); - } - - if ($request->query->has('identifier')) { - $return->contentTypes = [$this->loadContentTypeByIdentifier($request)]; - - return $return; - } - - if ($request->query->has('remoteId')) { - $return->contentTypes = [ - $this->loadContentTypeByRemoteId($request), - ]; - - return $return; - } - - $limit = null; - if ($request->query->has('limit')) { - $limit = (int)$request->query->get('limit', null); - if ($limit <= 0) { - throw new BadRequestException('wrong value for limit parameter'); - } - } - $contentTypes = $this->getContentTypeList(); - $sort = $request->query->get('sort'); - if ($request->query->has('orderby')) { - $orderby = $request->query->get('orderby'); - $this->sortContentTypeList($contentTypes, $orderby, $sort); - } - $offset = $request->query->get('offset', 0); - $return->contentTypes = array_slice($contentTypes, $offset, $limit); - - return $return; - } - - /** - * Loads a content type by its identifier. - * - * @return \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType - */ - public function loadContentTypeByIdentifier(Request $request) - { - return $this->contentTypeService->loadContentTypeByIdentifier( - $request->query->get('identifier'), - Language::ALL - ); - } - - /** - * Loads a content type by its remote ID. - * - * @return \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType - */ - public function loadContentTypeByRemoteId(Request $request) - { - return $this->contentTypeService->loadContentTypeByRemoteId( - $request->query->get('remoteId'), - Language::ALL - ); - } - - /** - * Creates a new content type draft in the given content type group. - * - * @param $contentTypeGroupId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException - * - * @return \Ibexa\Rest\Server\Values\CreatedContentType - */ - public function createContentType($contentTypeGroupId, Request $request) - { - $contentTypeGroup = $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId); - $publish = ($request->query->has('publish') && $request->query->get('publish') === 'true'); - - try { - $contentTypeDraft = $this->contentTypeService->createContentType( - $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - // @todo Needs refactoring! Temporary solution so parser has access to get parameters - '__publish' => $publish, - ], - $request->getContent() - ) - ), - [$contentTypeGroup] - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } catch (ContentTypeValidationException $e) { - throw new BadRequestException($e->getMessage()); - } catch (ContentTypeFieldDefinitionValidationException $e) { - throw new BadRequestException($e->getMessage()); - } catch (Exceptions\Parser $e) { - throw new BadRequestException($e->getMessage()); - } - - if ($publish) { - $this->contentTypeService->publishContentTypeDraft($contentTypeDraft); - - $contentType = $this->contentTypeService->loadContentType($contentTypeDraft->id, Language::ALL); - - return new Values\CreatedContentType( - [ - 'contentType' => new Values\RestContentType( - $contentType, - $contentType->getFieldDefinitions()->toArray() - ), - ] - ); - } - - return new Values\CreatedContentType( - [ - 'contentType' => new Values\RestContentType( - $contentTypeDraft, - $contentTypeDraft->getFieldDefinitions()->toArray() - ), - ] - ); - } - - /** - * Copies a content type. The identifier of the copy is changed to - * copy_of__ and a new remoteId is generated. - * - * @param $contentTypeId - * - * @return \Ibexa\Rest\Server\Values\ResourceCreated - */ - public function copyContentType($contentTypeId) - { - $copiedContentType = $this->contentTypeService->copyContentType( - $this->contentTypeService->loadContentType($contentTypeId) - ); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_content_type', - ['contentTypeId' => $copiedContentType->id] - ) - ); - } - - /** - * Creates a draft and updates it with the given data. - * - * @param $contentTypeId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedContentType - */ - public function createContentTypeDraft($contentTypeId, Request $request) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId); - - try { - $contentTypeDraft = $this->contentTypeService->createContentTypeDraft( - $contentType - ); - } catch (BadStateException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - $contentTypeUpdateStruct = $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - ], - $request->getContent() - ) - ); - - try { - $this->contentTypeService->updateContentTypeDraft( - $contentTypeDraft, - $contentTypeUpdateStruct - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - return new Values\CreatedContentType( - [ - 'contentType' => new Values\RestContentType( - // Reload the content type draft to get the updated values - $this->contentTypeService->loadContentTypeDraft( - $contentTypeDraft->id - ) - ), - ] - ); - } - - /** - * Loads a content type draft. - * - * @param $contentTypeId - * - * @return \Ibexa\Rest\Server\Values\RestContentType - */ - public function loadContentTypeDraft($contentTypeId) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - - return new Values\RestContentType( - $contentTypeDraft, - $contentTypeDraft->getFieldDefinitions()->toArray() - ); - } - - /** - * Updates meta data of a draft. This method does not handle field definitions. - * - * @param $contentTypeId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\RestContentType - */ - public function updateContentTypeDraft($contentTypeId, Request $request) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - $contentTypeUpdateStruct = $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - ], - $request->getContent() - ) - ); - - try { - $this->contentTypeService->updateContentTypeDraft( - $contentTypeDraft, - $contentTypeUpdateStruct - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - return new Values\RestContentType( - // Reload the content type draft to get the updated values - $this->contentTypeService->loadContentTypeDraft( - $contentTypeDraft->id - ) - ); - } - - /** - * Creates a new field definition for the given content type draft. - * - * @param $contentTypeId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\CreatedFieldDefinition - */ - public function addContentTypeDraftFieldDefinition($contentTypeId, Request $request) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - $fieldDefinitionCreate = $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - ], - $request->getContent() - ) - ); - - try { - $this->contentTypeService->addFieldDefinition( - $contentTypeDraft, - $fieldDefinitionCreate - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } catch (ContentTypeFieldDefinitionValidationException $e) { - throw new BadRequestException($e->getMessage()); - } catch (BadStateException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - $updatedDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - foreach ($updatedDraft->getFieldDefinitions() as $fieldDefinition) { - if ($fieldDefinition->identifier == $fieldDefinitionCreate->identifier) { - return new Values\CreatedFieldDefinition( - [ - 'fieldDefinition' => new Values\RestFieldDefinition($updatedDraft, $fieldDefinition), - ] - ); - } - } - - throw new Exceptions\NotFoundException("Field definition not found: '{$request->getPathInfo()}'."); - } - - /** - * Loads field definitions for a given content type. - * - * @param $contentTypeId - * - * @return \Ibexa\Rest\Server\Values\FieldDefinitionList - * - * @todo Check why this isn't in the specs - */ - public function loadContentTypeFieldDefinitionList($contentTypeId) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId, Language::ALL); - - return new Values\FieldDefinitionList( - $contentType, - $contentType->getFieldDefinitions()->toArray() - ); - } - - /** - * Returns the field definition given by id. - * - * @param $contentTypeId - * @param $fieldDefinitionId - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\RestFieldDefinition - */ - public function loadContentTypeFieldDefinition($contentTypeId, $fieldDefinitionId, Request $request) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId, Language::ALL); - - foreach ($contentType->getFieldDefinitions() as $fieldDefinition) { - if ($fieldDefinition->id == $fieldDefinitionId) { - return new Values\RestFieldDefinition( - $contentType, - $fieldDefinition - ); - } - } - - throw new Exceptions\NotFoundException("Field definition not found: '{$request->getPathInfo()}'."); - } - - /** - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - */ - public function loadContentTypeFieldDefinitionByIdentifier( - int $contentTypeId, - string $fieldDefinitionIdentifier, - Request $request - ): Values\RestFieldDefinition { - $contentType = $this->contentTypeService->loadContentType($contentTypeId); - $fieldDefinition = $contentType->getFieldDefinition($fieldDefinitionIdentifier); - $path = $this->router->generate( - 'ibexa.rest.load_content_type_field_definition_by_identifier', - [ - 'contentTypeId' => $contentType->id, - 'fieldDefinitionIdentifier' => $fieldDefinitionIdentifier, - ] - ); - - if ($fieldDefinition === null) { - throw new Exceptions\NotFoundException( - sprintf("Field definition not found: '%s'.", $request->getPathInfo()) - ); - } - - return new Values\RestFieldDefinition( - $contentType, - $fieldDefinition, - $path - ); - } - - /** - * Loads field definitions for a given content type draft. - * - * @param $contentTypeId - * - * @return \Ibexa\Rest\Server\Values\FieldDefinitionList - */ - public function loadContentTypeDraftFieldDefinitionList($contentTypeId) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - - return new Values\FieldDefinitionList( - $contentTypeDraft, - $contentTypeDraft->getFieldDefinitions() - ); - } - - /** - * Returns the draft field definition given by id. - * - * @param $contentTypeId - * @param $fieldDefinitionId - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\RestFieldDefinition - */ - public function loadContentTypeDraftFieldDefinition($contentTypeId, $fieldDefinitionId, Request $request) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - - foreach ($contentTypeDraft->getFieldDefinitions() as $fieldDefinition) { - if ($fieldDefinition->id == $fieldDefinitionId) { - return new Values\RestFieldDefinition( - $contentTypeDraft, - $fieldDefinition - ); - } - } - - throw new Exceptions\NotFoundException("Field definition not found: '{$request->getPathInfo()}'."); - } - - /** - * Updates the attributes of a field definition. - * - * @param $contentTypeId - * @param $fieldDefinitionId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\FieldDefinitionList - */ - public function updateContentTypeDraftFieldDefinition($contentTypeId, $fieldDefinitionId, Request $request) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - $fieldDefinitionUpdate = $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - // @todo Needs refactoring! Temporary solution so parser has access to URL - 'Url' => $request->getPathInfo(), - ], - $request->getContent() - ) - ); - - $fieldDefinition = null; - foreach ($contentTypeDraft->getFieldDefinitions() as $fieldDef) { - if ($fieldDef->id == $fieldDefinitionId) { - $fieldDefinition = $fieldDef; - } - } - - if ($fieldDefinition === null) { - throw new Exceptions\NotFoundException("Field definition not found: '{$request->getPathInfo()}'."); - } - - try { - $this->contentTypeService->updateFieldDefinition( - $contentTypeDraft, - $fieldDefinition, - $fieldDefinitionUpdate - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - $updatedDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - foreach ($updatedDraft->getFieldDefinitions() as $fieldDef) { - if ($fieldDef->id == $fieldDefinitionId) { - return new Values\RestFieldDefinition($updatedDraft, $fieldDef); - } - } - - throw new Exceptions\NotFoundException("Field definition not found: '{$request->getPathInfo()}'."); - } - - /** - * Deletes a field definition from a content type draft. - * - * @param $contentTypeId - * @param $fieldDefinitionId - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function removeContentTypeDraftFieldDefinition($contentTypeId, $fieldDefinitionId, Request $request) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - - $fieldDefinition = null; - foreach ($contentTypeDraft->getFieldDefinitions() as $fieldDef) { - if ($fieldDef->id == $fieldDefinitionId) { - $fieldDefinition = $fieldDef; - } - } - - if ($fieldDefinition === null) { - throw new Exceptions\NotFoundException("Field definition not found: '{$request->getPathInfo()}'."); - } - - $this->contentTypeService->removeFieldDefinition( - $contentTypeDraft, - $fieldDefinition - ); - - return new Values\NoContent(); - } - - /** - * Publishes a content type draft. - * - * @param $contentTypeId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\RestContentType - */ - public function publishContentTypeDraft($contentTypeId) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - - $fieldDefinitions = $contentTypeDraft->getFieldDefinitions(); - if (empty($fieldDefinitions)) { - throw new ForbiddenException('Cannot publish an empty content type draft'); - } - - $this->contentTypeService->publishContentTypeDraft($contentTypeDraft); - - $publishedContentType = $this->contentTypeService->loadContentType($contentTypeDraft->id, Language::ALL); - - return new Values\RestContentType( - $publishedContentType, - $publishedContentType->getFieldDefinitions()->toArray() - ); - } - - /** - * The given content type is deleted. - * - * @param $contentTypeId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteContentType($contentTypeId) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId); - - try { - $this->contentTypeService->deleteContentType($contentType); - } catch (BadStateException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - return new Values\NoContent(); - } - - /** - * The given content type draft is deleted. - * - * @param $contentTypeId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteContentTypeDraft($contentTypeId) - { - $contentTypeDraft = $this->contentTypeService->loadContentTypeDraft($contentTypeId); - $this->contentTypeService->deleteContentType($contentTypeDraft); - - return new Values\NoContent(); - } - - /** - * Returns the content type groups the content type belongs to. - * - * @param $contentTypeId - * - * @return \Ibexa\Rest\Server\Values\ContentTypeGroupRefList - */ - public function loadGroupsOfContentType($contentTypeId) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId, Language::ALL); - - return new Values\ContentTypeGroupRefList( - $contentType, - $contentType->getContentTypeGroups() - ); - } - - /** - * Links a content type group to the content type and returns the updated group list. - * - * @param mixed $contentTypeId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException - * - * @return \Ibexa\Rest\Server\Values\ContentTypeGroupRefList - */ - public function linkContentTypeToGroup($contentTypeId, Request $request) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId); - - try { - $contentTypeGroupId = $this->requestParser->parseHref( - $request->query->get('group'), - 'contentTypeGroupId' - ); - } catch (Exceptions\InvalidArgumentException $e) { - // Group URI does not match the required value - throw new BadRequestException($e->getMessage()); - } - - $contentTypeGroup = $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId); - - $existingContentTypeGroups = $contentType->getContentTypeGroups(); - $contentTypeInGroup = false; - foreach ($existingContentTypeGroups as $existingGroup) { - if ($existingGroup->id == $contentTypeGroup->id) { - $contentTypeInGroup = true; - break; - } - } - - if ($contentTypeInGroup) { - throw new ForbiddenException('The content type is already linked to the provided group'); - } - - $this->contentTypeService->assignContentTypeGroup( - $contentType, - $contentTypeGroup - ); - - $existingContentTypeGroups[] = $contentTypeGroup; - - return new Values\ContentTypeGroupRefList( - $contentType, - $existingContentTypeGroups - ); - } - - /** - * Removes the given group from the content type and returns the updated group list. - * - * @param $contentTypeId - * @param $contentTypeGroupId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\ContentTypeGroupRefList - */ - public function unlinkContentTypeFromGroup($contentTypeId, $contentTypeGroupId) - { - $contentType = $this->contentTypeService->loadContentType($contentTypeId); - $contentTypeGroup = $this->contentTypeService->loadContentTypeGroup($contentTypeGroupId); - - $existingContentTypeGroups = $contentType->getContentTypeGroups(); - $contentTypeInGroup = false; - foreach ($existingContentTypeGroups as $existingGroup) { - if ($existingGroup->id == $contentTypeGroup->id) { - $contentTypeInGroup = true; - break; - } - } - - if (!$contentTypeInGroup) { - throw new Exceptions\NotFoundException('The content type is not in the provided group'); - } - - if (count($existingContentTypeGroups) == 1) { - throw new ForbiddenException('Cannot unlink the content type from its only remaining group'); - } - - $this->contentTypeService->unassignContentTypeGroup( - $contentType, - $contentTypeGroup - ); - - $contentType = $this->contentTypeService->loadContentType($contentTypeId); - - return new Values\ContentTypeGroupRefList( - $contentType, - $contentType->getContentTypeGroups() - ); - } - - /** - * Converts the provided ContentTypeGroupCreateStruct to ContentTypeGroupUpdateStruct. - * - * @param \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeGroupCreateStruct $createStruct - * - * @return \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeGroupUpdateStruct - */ - private function mapToGroupUpdateStruct(ContentTypeGroupCreateStruct $createStruct) - { - return new ContentTypeGroupUpdateStruct( - [ - 'identifier' => $createStruct->identifier, - 'modifierId' => $createStruct->creatorId, - 'modificationDate' => $createStruct->creationDate, - ] - ); - } - - /** - * @param array &$contentTypes - * @param string $orderby - * - * @return mixed - * - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException - */ - protected function sortContentTypeList(array &$contentTypes, $orderby, $sort = 'asc') - { - switch ($orderby) { - case 'name': - if ($sort === 'asc' || $sort === null) { - usort( - $contentTypes, - static function (APIContentType $contentType1, APIContentType $contentType2) { - return strcasecmp($contentType1->identifier, $contentType2->identifier); - } - ); - } elseif ($sort === 'desc') { - usort( - $contentTypes, - static function (APIContentType $contentType1, APIContentType $contentType2) { - return strcasecmp($contentType1->identifier, $contentType2->identifier) * -1; - } - ); - } else { - throw new BadRequestException('wrong value for sort parameter'); - } - break; - case 'lastmodified': - if ($sort === 'asc' || $sort === null) { - usort( - $contentTypes, - static function ($timeObj3, $timeObj4) { - $timeObj3 = strtotime($timeObj3->modificationDate->format('Y-m-d H:i:s')); - $timeObj4 = strtotime($timeObj4->modificationDate->format('Y-m-d H:i:s')); - - return $timeObj3 > $timeObj4; - } - ); - } elseif ($sort === 'desc') { - usort( - $contentTypes, - static function ($timeObj3, $timeObj4) { - $timeObj3 = strtotime($timeObj3->modificationDate->format('Y-m-d H:i:s')); - $timeObj4 = strtotime($timeObj4->modificationDate->format('Y-m-d H:i:s')); - - return $timeObj3 < $timeObj4; - } - ); - } else { - throw new BadRequestException('wrong value for sort parameter'); - } - break; - default: - throw new BadRequestException('wrong value for orderby parameter'); - break; - } - } - - /** - * @return ContentType[] - */ - protected function getContentTypeList() - { - $contentTypes = []; - foreach ($this->contentTypeService->loadContentTypeGroups() as $contentTypeGroup) { - $contentTypes = array_merge( - $contentTypes, - $this->contentTypeService->loadContentTypes($contentTypeGroup, Language::ALL) - ); - } - - return $contentTypes; - } -} diff --git a/src/lib/Server/Controller/Language.php b/src/lib/Server/Controller/Language.php deleted file mode 100644 index 88207781..00000000 --- a/src/lib/Server/Controller/Language.php +++ /dev/null @@ -1,129 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.LanguageList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LanguageList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/languages/GET/LanguageList.xml.example', - ], - 'application/vnd.ibexa.api.LanguageList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LanguageListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/languages/GET/LanguageList.json.example', - ], - ], - ], - ], - ), -)] -#[Get( - uriTemplate: '/languages/{code}', - name: 'Get language', - openapi: new Model\Operation( - tags: [ - 'Language', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the language is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'code', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Language+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Language', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/languages/code/GET/Language.xml.example', - ], - 'application/vnd.ibexa.api.Language+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LanguageWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/languages/code/GET/Language.json.example', - ], - ], - ], - ], - ), -)] -final class Language extends RestController -{ - private LanguageService $languageService; - - public function __construct(LanguageService $languageService) - { - $this->languageService = $languageService; - } - - public function listLanguages(): LanguageList - { - $languages = $this->languageService->loadLanguages(); - - if ($languages instanceof Traversable) { - $languages = iterator_to_array($languages); - } - - return new LanguageList($languages); - } - - public function loadLanguage(string $languageCode): ApiLanguage - { - return $this->languageService->loadLanguage($languageCode); - } -} diff --git a/src/lib/Server/Controller/Location.php b/src/lib/Server/Controller/Location.php deleted file mode 100644 index f258ed4c..00000000 --- a/src/lib/Server/Controller/Location.php +++ /dev/null @@ -1,852 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.LocationList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Location', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.xml.example', - ], - 'application/vnd.ibexa.api.LocationList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.json.example', - ], - ], - ], - Response::HTTP_TEMPORARY_REDIRECT => [ - 'description' => 'Temporary redirect to the main resource URL.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Location with the given ID (remote ID or URL Alias) does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/locations/{path}', - name: 'Load Location', - openapi: new Model\Operation( - summary: 'Loads the Location for the given path e.g. \'/content/locations/1/2/61\'.', - tags: [ - 'Location', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new Location is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Location+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Location', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.xml.example', - ], - 'application/vnd.ibexa.api.Location+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this Location.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Location with the given path does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/locations/{path}', - name: 'Delete subtree', - openapi: new Model\Operation( - summary: 'Deletes the complete subtree for the given path. Every content item which does not have any other Location is deleted. Otherwise the deleted Location is removed from the content item. The children are recursively deleted.', - tags: [ - 'Location', - ], - parameters: [ - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this subtree.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Location with the given ID does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/locations/{path}', - name: 'Update Location', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates the Location. This method can also be used to hide/reveal a Location via the hidden field in the LocationUpdate. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Location', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Location is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The LocationUpdate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.LocationUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationUpdateStruct', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/locations/location_id/PATCH/LocationUpdate.xml.example', - ], - 'application/vnd.ibexa.api.LocationUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationUpdateStructWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/locations/location_id/PATCH/LocationUpdate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Location+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Location', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.xml.example', - ], - 'application/vnd.ibexa.api.Location+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/POST/Location.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update this Location.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Location with the given ID does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/locations/{path}/children', - name: 'Get child Locations.', - openapi: new Model\Operation( - summary: 'Loads all child Locations for the given parent Location.', - tags: [ - 'Location', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new Location list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.LocationList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objects/content_id/locations/GET/LocationList.xml.example', - ], - 'application/vnd.ibexa.api.LocationList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/LocationListWrapper', - ], - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to read this content item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the content item with the given ID does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/locations/{path}/urlaliases', - name: 'List URL aliases for Location', - openapi: new Model\Operation( - summary: 'Returns the list of URL aliases for a Location.', - tags: [ - 'Location', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the URL alias list contains only references and is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the list of URL aliases.', - 'content' => [ - 'application/vnd.ibexa.api.UrlAliasRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/GET/UrlAliasRefList.xml.example', - ], - 'application/vnd.ibexa.api.UrlAliasRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasRefListWrapper', - ], - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The user has no permission to read URL aliases.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The Location was not found.', - ], - ], - ), -)] -/** - * Location controller. - */ -class Location extends RestController -{ - /** - * Location service. - * - * @var \Ibexa\Contracts\Core\Repository\LocationService - */ - protected $locationService; - - /** - * Content service. - * - * @var \Ibexa\Contracts\Core\Repository\ContentService - */ - protected $contentService; - - /** - * Trash service. - * - * @var \Ibexa\Contracts\Core\Repository\TrashService - */ - protected $trashService; - - /** - * URLAlias Service. - * - * @var \Ibexa\Contracts\Core\Repository\URLAliasService - */ - protected $urlAliasService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\LocationService $locationService - * @param \Ibexa\Contracts\Core\Repository\ContentService $contentService - * @param \Ibexa\Contracts\Core\Repository\TrashService $trashService - * @param \Ibexa\Contracts\Core\Repository\URLAliasService $urlAliasService - */ - public function __construct( - LocationService $locationService, - ContentService $contentService, - TrashService $trashService, - URLAliasService $urlAliasService - ) { - $this->locationService = $locationService; - $this->contentService = $contentService; - $this->trashService = $trashService; - $this->urlAliasService = $urlAliasService; - } - - /** - * Loads the location for a given ID (x)or remote ID. - * - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException - * - * @return \Ibexa\Rest\Server\Values\TemporaryRedirect - */ - public function redirectLocation(Request $request) - { - if ($request->query->has('id')) { - $location = $this->locationService->loadLocation($request->query->get('id')); - } elseif ($request->query->has('remoteId')) { - $location = $this->locationService->loadLocationByRemoteId($request->query->get('remoteId')); - } elseif ($request->query->has('urlAlias')) { - $urlAlias = $this->urlAliasService->lookup($request->query->get('urlAlias')); - $location = $this->locationService->loadLocation($urlAlias->destination); - } else { - throw new BadRequestException("At least one of 'id', 'remoteId' or 'urlAlias' parameters is required."); - } - - return new Values\TemporaryRedirect( - $this->router->generate( - 'ibexa.rest.load_location', - [ - 'locationPath' => trim($location->pathString, '/'), - ] - ) - ); - } - - /** - * Creates a new location for object with id $contentId. - * - * @param mixed $contentId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedLocation - */ - public function createLocation($contentId, Request $request) - { - $locationCreateStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $contentInfo = $this->contentService->loadContentInfo($contentId); - - try { - $createdLocation = $this->locationService->createLocation($contentInfo, $locationCreateStruct); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - return new Values\CreatedLocation(['restLocation' => new Values\RestLocation($createdLocation, 0)]); - } - - /** - * Loads a location. - * - * @param string $locationPath - * - * @return \Ibexa\Rest\Server\Values\RestLocation - */ - public function loadLocation($locationPath) - { - $location = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($locationPath) - ); - - if (trim($location->pathString, '/') != $locationPath) { - throw new Exceptions\NotFoundException( - "Could not find a Location with path string $locationPath" - ); - } - - return new Values\CachedValue( - new Values\RestLocation( - $location, - $this->locationService->getLocationChildCount($location) - ), - ['locationId' => $location->id] - ); - } - - /** - * Deletes a location. - * - * @param string $locationPath - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteSubtree($locationPath) - { - $location = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($locationPath) - ); - $this->locationService->deleteLocation($location); - - return new Values\NoContent(); - } - - /** - * Copies a subtree to a new destination. - * - * @param string $locationPath - * - * @return \Ibexa\Rest\Server\Values\ResourceCreated - */ - public function copySubtree($locationPath, Request $request) - { - $location = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($locationPath) - ); - - $destinationLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath( - $this->requestParser->parseHref( - $request->headers->get('Destination'), - 'locationPath' - ) - ) - ); - - $newLocation = $this->locationService->copySubtree($location, $destinationLocation); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_location', - [ - 'locationPath' => trim($newLocation->pathString, '/'), - ] - ) - ); - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - */ - public function copy(string $locationPath, Request $request): Values\ResourceCreated - { - $locationId = $this->extractLocationIdFromPath($locationPath); - $location = $this->locationService->loadLocation($locationId); - - $destinationLocation = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent(), - ), - ); - - $newLocation = $this->locationService->copySubtree($location, $destinationLocation); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_location', - [ - 'locationPath' => trim($newLocation->pathString, '/'), - ], - ) - ); - } - - /** - * Moves a subtree to a new location. - * - * @param string $locationPath - * - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException if the Destination header cannot be parsed as location or trash - * - * @return \Ibexa\Rest\Server\Values\ResourceCreated|\Ibexa\Rest\Server\Values\NoContent - */ - public function moveSubtree($locationPath, Request $request) - { - $locationToMove = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($locationPath) - ); - - $destinationLocationId = null; - $destinationHref = $request->headers->get('Destination'); - try { - // First check to see if the destination is for moving within another subtree - $destinationLocationId = $this->extractLocationIdFromPath( - $this->requestParser->parseHref($destinationHref, 'locationPath') - ); - - // We're moving the subtree - $destinationLocation = $this->locationService->loadLocation($destinationLocationId); - $this->locationService->moveSubtree($locationToMove, $destinationLocation); - - // Reload the location to get the new position is subtree - $locationToMove = $this->locationService->loadLocation($locationToMove->id); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_location', - [ - 'locationPath' => trim($locationToMove->pathString, '/'), - ] - ) - ); - } catch (Exceptions\InvalidArgumentException $e) { - // If parsing of destination fails, let's try to see if destination is trash - try { - $route = $this->requestParser->parse($destinationHref); - if (!isset($route['_route']) || $route['_route'] !== 'ibexa.rest.load_trash_items') { - throw new Exceptions\InvalidArgumentException(''); - } - // Trash the subtree - $trashItem = $this->trashService->trash($locationToMove); - - if (isset($trashItem)) { - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_trash_item', - ['trashItemId' => $trashItem->id] - ) - ); - } else { - // Only a location has been trashed and not the object - return new Values\NoContent(); - } - } catch (Exceptions\InvalidArgumentException $e) { - // If that fails, the Destination header is not formatted right - // so just throw the BadRequestException - throw new BadRequestException("{$destinationHref} is not an acceptable destination"); - } - } - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - */ - public function moveLocation(Request $request, string $locationPath): Values\ResourceCreated - { - $destinationLocation = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent(), - ), - ); - - $locationToMove = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($locationPath), - ); - - $this->locationService->moveSubtree($locationToMove, $destinationLocation); - - // Reload the location to get a new subtree position - $locationToMove = $this->locationService->loadLocation($locationToMove->id); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_location', - [ - 'locationPath' => trim($locationToMove->getPathString(), '/'), - ], - ), - ); - } - - /** - * Swaps a location with another one. - * - * @param string $locationPath - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function swapLocation($locationPath, Request $request) - { - $locationId = $this->extractLocationIdFromPath($locationPath); - $location = $this->locationService->loadLocation($locationId); - - $destinationLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath( - $this->requestParser->parseHref( - $request->headers->get('Destination'), - 'locationPath' - ) - ) - ); - - $this->locationService->swapLocation($location, $destinationLocation); - - return new Values\NoContent(); - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - */ - public function swap(Request $request, string $locationPath): Values\NoContent - { - $locationId = $this->extractLocationIdFromPath($locationPath); - $location = $this->locationService->loadLocation($locationId); - - $destinationLocation = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent(), - ), - ); - - $this->locationService->swapLocation($location, $destinationLocation); - - return new Values\NoContent(); - } - - /** - * Loads a location by remote ID. - * - * @todo remove, or use in loadLocation with filter - * - * @return \Ibexa\Rest\Server\Values\LocationList - */ - public function loadLocationByRemoteId(Request $request) - { - return new Values\LocationList( - [ - new Values\RestLocation( - $location = $this->locationService->loadLocationByRemoteId( - $request->query->get('remoteId') - ), - $this->locationService->getLocationChildCount($location) - ), - ], - $request->getPathInfo() - ); - } - - /** - * Loads all locations for content object. - * - * @param mixed $contentId - * - * @return \Ibexa\Rest\Server\Values\LocationList - */ - public function loadLocationsForContent($contentId, Request $request) - { - $restLocations = []; - $contentInfo = $this->contentService->loadContentInfo($contentId); - foreach ($this->locationService->loadLocations($contentInfo) as $location) { - $restLocations[] = new Values\RestLocation( - $location, - // @todo Remove, and make optional in VO. Not needed for a location list. - $this->locationService->getLocationChildCount($location) - ); - } - - return new Values\CachedValue( - new Values\LocationList($restLocations, $request->getPathInfo()), - ['locationId' => $contentInfo->mainLocationId] - ); - } - - /** - * Loads child locations of a location. - * - * @param string $locationPath - * - * @return \Ibexa\Rest\Server\Values\LocationList - */ - public function loadLocationChildren($locationPath, Request $request) - { - $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0; - $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : 10; - - $restLocations = []; - $locationId = $this->extractLocationIdFromPath($locationPath); - $children = $this->locationService->loadLocationChildren( - $this->locationService->loadLocation($locationId), - $offset >= 0 ? $offset : 0, - $limit >= 0 ? $limit : 25 - )->locations; - foreach ($children as $location) { - $restLocations[] = new Values\RestLocation( - $location, - $this->locationService->getLocationChildCount($location) - ); - } - - return new Values\CachedValue( - new Values\LocationList($restLocations, $request->getPathInfo()), - ['locationId' => $locationId] - ); - } - - /** - * Extracts and returns an item id from a path, e.g. /1/2/58 => 58. - * - * @param string $path - * - * @return mixed - */ - private function extractLocationIdFromPath($path) - { - $pathParts = explode('/', $path); - - return array_pop($pathParts); - } - - /** - * Updates a location. - * - * @param string $locationPath - * - * @return \Ibexa\Rest\Server\Values\RestLocation - */ - public function updateLocation($locationPath, Request $request) - { - $locationUpdate = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $location = $this->locationService->loadLocation($this->extractLocationIdFromPath($locationPath)); - - // First handle hiding/unhiding so that updating location afterwards - // will return updated location with hidden/visible status correctly updated - // Exact check for true/false is needed as null signals that no hiding/unhiding - // is to be performed - if ($locationUpdate->hidden === true) { - $this->locationService->hideLocation($location); - } elseif ($locationUpdate->hidden === false) { - $this->locationService->unhideLocation($location); - } - - return new Values\RestLocation( - $location = $this->locationService->updateLocation($location, $locationUpdate->locationUpdateStruct), - $this->locationService->getLocationChildCount($location) - ); - } -} diff --git a/src/lib/Server/Controller/ObjectState.php b/src/lib/Server/Controller/ObjectState.php deleted file mode 100644 index ba852447..00000000 --- a/src/lib/Server/Controller/ObjectState.php +++ /dev/null @@ -1,1023 +0,0 @@ - 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns a list of Object state groups.', - 'content' => [ - 'application/vnd.ibexa.api.ObjectStateGroupList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/GET/ObjectStateGroupList.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateGroupList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/GET/ObjectStateGroupList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read Object state groups.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objectstategroups', - name: 'Create Object state group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new Object state group.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new Object state group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Object state group input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ObjectStateGroupCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/POST/ObjectStateGroupCreate.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateGroupCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/POST/ObjectStateGroupCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Object state group created.', - 'content' => [ - 'application/vnd.ibexa.api.ObjectStateGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroup.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroup.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create an Object state group.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - An Object state group with the same identifier already exists.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}', - name: 'Get Object state group', - openapi: new Model\Operation( - summary: 'Returns the Object state group with the provided ID.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Object state group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the Object state group.', - 'content' => [ - 'application/vnd.ibexa.api.ObjectStateGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroup.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroup.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read this Object state group.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The Object state group does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}', - name: 'Update Object state group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates an Object state group. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Object state group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Object state group input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ObjectStateGroupUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroupUpdate.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateGroupUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupUpdateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroupUpdate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Object stated group updated.', - 'content' => [ - 'application/vnd.ibexa.api.ObjectStateGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroup.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/PATCH/ObjectStateGroup.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to update an Object state group.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - An Object state group with the provided identifier already exists.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - The current ETag does not match the one provided in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}', - name: 'Delete Object state group', - openapi: new Model\Operation( - summary: 'Deletes the given Object state group including Object states.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - Object state group deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete an Object state group.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The Object state group does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}/objectstates', - name: 'List Object states', - openapi: new Model\Operation( - summary: 'Returns a list of all Object states of the given group.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Object state list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns a list of Object states.', - 'content' => [ - 'application/vnd.ibexa.api.ObjectStateList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/GET/ObjectStateList.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/GET/ObjectStateList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read Object states.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}/objectstates', - name: 'Create Object state', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new Object state.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new Object state is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Object state input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ObjectStateCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/POST/ObjectStateCreate.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/POST/ObjectStateCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Object state created.', - 'content' => [ - 'application/vnd.ibexa.api.ObjectState+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectState', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectState.xml.example', - ], - 'application/vnd.ibexa.api.ObjectState+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectState.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create an Object state.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - An Object state with the same identifier already exists in the given group.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}/objectstates/{objectStateId}', - name: 'Get Object state', - openapi: new Model\Operation( - summary: 'Returns the Object state.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Object State is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the Object state.', - 'content' => [ - 'application/vnd.ibexa.api.ObjectState+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectState', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectState.xml.example', - ], - 'application/vnd.ibexa.api.ObjectState+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectState.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read this Object state.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The Object state does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}/objectstates/{objectStateId}', - name: 'Update Object state', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates an Object state. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Object state is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Object state input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.ObjectStateUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectStateUpdate.xml.example', - ], - 'application/vnd.ibexa.api.ObjectStateUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateUpdateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectStateUpdate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Object State updated', - 'content' => [ - 'application/vnd.ibexa.api.ObjectState+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectState', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectState.xml.example', - ], - 'application/vnd.ibexa.api.ObjectState+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/ObjectStateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/objectstategroups/object_state_group_id/objectstates/object_state_id/PATCH/ObjectState.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to update the Object state.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - An Object state with the provided identifier already exists in this group.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - The current ETag does not match the one provided in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/objectstategroups/{objectStateGroupId}/objectstates/{objectStateId}', - name: 'Delete Object state', - openapi: new Model\Operation( - summary: 'Deletes provided Object state.', - tags: [ - 'Object State Groups', - ], - parameters: [ - new Model\Parameter( - name: 'objectStateGroupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'objectStateId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - Object state deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete an Object state.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The Object state does not exist.', - ], - ], - ), -)] -/** - * ObjectState controller. - */ -class ObjectState extends RestController -{ - /** - * ObjectState service. - * - * @var \Ibexa\Contracts\Core\Repository\ObjectStateService - */ - protected $objectStateService; - - /** - * Content service. - * - * @var \Ibexa\Contracts\Core\Repository\ContentService - */ - protected $contentService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\ObjectStateService $objectStateService - * @param \Ibexa\Contracts\Core\Repository\ContentService $contentService - */ - public function __construct(ObjectStateService $objectStateService, ContentService $contentService) - { - $this->objectStateService = $objectStateService; - $this->contentService = $contentService; - } - - /** - * Creates a new object state group. - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedObjectStateGroup - */ - public function createObjectStateGroup(Request $request) - { - try { - $createdStateGroup = $this->objectStateService->createObjectStateGroup( - $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ) - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */$e->getMessage()); - } - - return new Values\CreatedObjectStateGroup( - [ - 'objectStateGroup' => $createdStateGroup, - ] - ); - } - - /** - * Creates a new object state. - * - * @param $objectStateGroupId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedObjectState - */ - public function createObjectState($objectStateGroupId, Request $request) - { - $objectStateGroup = $this->objectStateService->loadObjectStateGroup($objectStateGroupId); - - try { - $createdObjectState = $this->objectStateService->createObjectState( - $objectStateGroup, - $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ) - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - return new Values\CreatedObjectState( - [ - 'objectState' => new RestObjectState( - $createdObjectState, - $objectStateGroup->id - ), - ] - ); - } - - /** - * Loads an object state group. - * - * @param $objectStateGroupId - * - * @return \Ibexa\Contracts\Core\Repository\Values\ObjectState\ObjectStateGroup - */ - public function loadObjectStateGroup($objectStateGroupId) - { - return $this->objectStateService->loadObjectStateGroup($objectStateGroupId, Language::ALL); - } - - /** - * Loads an object state. - * - * @param $objectStateGroupId - * @param $objectStateId - * - * @return \Ibexa\Rest\Values\RestObjectState - */ - public function loadObjectState($objectStateGroupId, $objectStateId) - { - return new RestObjectState( - $this->objectStateService->loadObjectState($objectStateId, Language::ALL), - $objectStateGroupId - ); - } - - /** - * Returns a list of all object state groups. - * - * @return \Ibexa\Rest\Server\Values\ObjectStateGroupList - */ - public function loadObjectStateGroups() - { - return new Values\ObjectStateGroupList( - $this->objectStateService->loadObjectStateGroups(0, -1, Language::ALL) - ); - } - - /** - * Returns a list of all object states of the given group. - * - * @param $objectStateGroupId - * - * @return \Ibexa\Rest\Server\Values\ObjectStateList - */ - public function loadObjectStates($objectStateGroupId) - { - $objectStateGroup = $this->objectStateService->loadObjectStateGroup($objectStateGroupId); - - return new Values\ObjectStateList( - $this->objectStateService->loadObjectStates($objectStateGroup, Language::ALL), - $objectStateGroup->id - ); - } - - /** - * The given object state group including the object states is deleted. - * - * @param $objectStateGroupId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteObjectStateGroup($objectStateGroupId) - { - $this->objectStateService->deleteObjectStateGroup( - $this->objectStateService->loadObjectStateGroup($objectStateGroupId) - ); - - return new Values\NoContent(); - } - - /** - * The given object state is deleted. - * - * @param $objectStateId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteObjectState($objectStateId) - { - $this->objectStateService->deleteObjectState( - $this->objectStateService->loadObjectState($objectStateId) - ); - - return new Values\NoContent(); - } - - /** - * Updates an object state group. - * - * @param $objectStateGroupId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Contracts\Core\Repository\Values\ObjectState\ObjectStateGroup - */ - public function updateObjectStateGroup($objectStateGroupId, Request $request) - { - $updateStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $objectStateGroup = $this->objectStateService->loadObjectStateGroup($objectStateGroupId); - - try { - $updatedStateGroup = $this->objectStateService->updateObjectStateGroup($objectStateGroup, $updateStruct); - - return $updatedStateGroup; - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - /** - * Updates an object state. - * - * @param $objectStateGroupId - * @param $objectStateId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Values\RestObjectState - */ - public function updateObjectState($objectStateGroupId, $objectStateId, Request $request) - { - $updateStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $objectState = $this->objectStateService->loadObjectState($objectStateId); - - try { - $updatedObjectState = $this->objectStateService->updateObjectState($objectState, $updateStruct); - - return new RestObjectState($updatedObjectState, $objectStateGroupId); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - /** - * Returns the object states of content. - * - * @param $contentId - * - * @return \Ibexa\Rest\Values\ContentObjectStates - */ - public function getObjectStatesForContent($contentId) - { - $groups = $this->objectStateService->loadObjectStateGroups(); - $contentInfo = $this->contentService->loadContentInfo($contentId); - - $contentObjectStates = []; - - foreach ($groups as $group) { - try { - $state = $this->objectStateService->getContentState($contentInfo, $group); - $contentObjectStates[] = new RestObjectState($state, $group->id); - } catch (NotFoundException $e) { - // Do nothing - } - } - - return new ContentObjectStates($contentObjectStates); - } - - /** - * Updates object states of content - * An object state in the input overrides the state of the object state group. - * - * @param $contentId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Values\ContentObjectStates - */ - public function setObjectStatesForContent($contentId, Request $request) - { - $newObjectStates = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $countByGroups = []; - foreach ($newObjectStates as $newObjectState) { - $groupId = (int)$newObjectState->groupId; - if (array_key_exists($groupId, $countByGroups)) { - ++$countByGroups[$groupId]; - } else { - $countByGroups[$groupId] = 1; - } - } - - foreach ($countByGroups as $groupId => $count) { - if ($count > 1) { - throw new ForbiddenException( - /** @Ignore */ - "Multiple Object states provided for group with ID $groupId" - ); - } - } - - $contentInfo = $this->contentService->loadContentInfo($contentId); - - $contentObjectStates = []; - foreach ($newObjectStates as $newObjectState) { - $objectStateGroup = $this->objectStateService->loadObjectStateGroup($newObjectState->groupId); - $this->objectStateService->setContentState($contentInfo, $objectStateGroup, $newObjectState->objectState); - $contentObjectStates[(int)$objectStateGroup->id] = $newObjectState; - } - - return new ContentObjectStates($contentObjectStates); - } -} diff --git a/src/lib/Server/Controller/Role.php b/src/lib/Server/Controller/Role.php deleted file mode 100644 index d24f71e1..00000000 --- a/src/lib/Server/Controller/Role.php +++ /dev/null @@ -1,1990 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - list of all Roles.', - 'content' => [ - 'application/vnd.ibexa.api.RoleList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/GET/RoleList.xml.example', - ], - 'application/vnd.ibexa.api.RoleList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/GET/RoleList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/roles', - name: 'Create Role or Role draft', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new Role or Role draft.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new user is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The RoleInput schema encoded in XML or JSON.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.RoleInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/POST/RoleInput.xml.example', - ], - 'application/vnd.ibexa.api.RoleInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/POST/RoleInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.Role+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Role', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.xml.example', - ], - 'application/vnd.ibexa.api.Role+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create a Role or a Role draft.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/roles/{id}', - name: 'Load Role', - openapi: new Model\Operation( - summary: 'Loads a Role for the given ID.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the user list returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Role for the given ID.', - 'content' => [ - 'application/vnd.ibexa.api.Role+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Role', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.xml.example', - ], - 'application/vnd.ibexa.api.Role+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Role does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/roles/{id}', - name: 'Create Role Draft', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'Creates a new Role draft from an existing Role.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new user is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The RoleInput schema encoded in XML or JSON.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.RoleDraft+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleDraft', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/POST/RoleDraft.xml.example', - ], - 'application/vnd.ibexa.api.RoleDraft+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleDraftWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create a Role or a Role draft', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/user/roles/{id}', - name: 'Update Role', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates a Role. PATCH or POST with header X-HTTP-Method-Override PATCH', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new user is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The RoleInput schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'ETag Causes to patch only if the specified ETag is the current one. Otherwise a 412 is returned.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.RoleInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/POST/RoleInput.xml.example', - ], - 'application/vnd.ibexa.api.RoleInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/POST/RoleInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Role updated', - 'content' => [ - 'application/vnd.ibexa.api.Role+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Role', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.xml.example', - ], - 'application/vnd.ibexa.api.Role+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update the Role.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - the current ETag does not match with the provided one in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/roles/{id}', - name: 'Delete Role', - openapi: new Model\Operation( - summary: 'The given Role and all assignments to Users or User Groups are deleted.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the User is not authorized to delete this Role.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/roles/{id}/draft', - name: 'Load Role draft', - openapi: new Model\Operation( - summary: 'Loads a Role draft by original Role ID.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the User list returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Role draft by original Role ID.', - 'content' => [ - 'application/vnd.ibexa.api.Role+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Role', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.xml.example', - ], - 'application/vnd.ibexa.api.Role+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - there is no draft or Role with the given ID.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/user/roles/{id}/draft', - name: 'Update Role draft', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates a Role draft. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Role is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The RoleInput schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'Performs a PATCH only if the specified ETag is the current one. Otherwise a 412 is returned.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.RoleInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/POST/RoleInput.xml.example', - ], - 'application/vnd.ibexa.api.RoleInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/POST/RoleInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Role draft updated.', - 'content' => [ - 'application/vnd.ibexa.api.Role+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Role', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.xml.example', - ], - 'application/vnd.ibexa.api.Role+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/draft/PATCH/Role.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update the Role.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - there is no draft or Role with the given ID.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - the current ETag does not match with the one provided in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/roles/{id}/draft', - name: 'Delete Role draft', - openapi: new Model\Operation( - summary: 'The given Role draft is deleted.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this Role.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/roles/{id}/policies', - name: 'Load Policies', - openapi: new Model\Operation( - summary: 'Loads Policies for the given Role.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Policy list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.PolicyList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/GET/PolicyList.xml.example', - ], - 'application/vnd.ibexa.api.PolicyList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/GET/PolicyList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Role does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/roles/{id}/policies', - name: 'Delete Policies', - openapi: new Model\Operation( - summary: 'All Policies of the given Role are deleted.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - all Policies of the given Role are deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this content type.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/roles/{id}/policies', - name: 'Create Policy', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a Policy', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Policy is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'If set, the updated Policy is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.PolicyCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/POST/PolicyCreate.xml.example', - ], - 'application/vnd.ibexa.api.PolicyCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyCreateWrapper', - ], - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.Policy+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Policy', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/id/PATCH/Policy.xml.example', - ], - 'application/vnd.ibexa.api.Policy+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/id/GET/Policy.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition or validation of limitation in PolicyCreate fails.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create the Policy.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Role does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/user/roles/{id}/policies/{id}', - name: 'Update Policy', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates a Policy. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Policy is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'If set, the updated Policy is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'Causes to patch only if the specified ETag is the current one. Otherwise a 412 is returned.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.PolicyUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/id/PATCH/PolicyUpdate.xml.example', - ], - 'application/vnd.ibexa.api.PolicyUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyUpdateWrapper', - ], - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Policy+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Policy', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/id/PATCH/Policy.xml.example', - ], - 'application/vnd.ibexa.api.Policy+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/id/GET/Policy.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition or validation of limitation in PolicyUpdate fails.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update the Policy.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Role does not exist.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - the current ETag does not match with the one provided in the If-Match header.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/roles/{id}/policies/{id}', - name: 'Load Policy', - openapi: new Model\Operation( - summary: 'Loads a Policy for the given module and function.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Policy is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Policy+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Policy', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/id/PATCH/Policy.xml.example', - ], - 'application/vnd.ibexa.api.Policy+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/id/GET/Policy.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Role or Policy does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/roles/{id}/policies/{id}', - name: 'Delete Policy', - openapi: new Model\Operation( - summary: 'Deletes given Policy.', - tags: [ - 'User Role', - ], - parameters: [ - new Model\Parameter( - name: 'id', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - the given Policy is deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this content type.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Role or Policy does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/groups/{path}/roles', - name: 'Load Roles for User Group', - openapi: new Model\Operation( - summary: 'Returns a list of all Roles assigned to the given User Group.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignmentList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/GET/RoleAssignment.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignmentList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/DELETE/RoleAssignmentList.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/groups/{path}/roles', - name: 'Assign Role to User Group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Assigns a Role to a User Group.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The RoleAssignInput schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.RoleAssignInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/roles/POST/RoleAssignInput.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/POST/RoleAssignInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignmentList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/GET/RoleAssignment.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignmentList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/DELETE/RoleAssignmentList.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - validation of limitation in RoleAssignInput fails.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to assign this Role.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/groups/{path}/roles/{roleId}', - name: 'Load User Group Role Assignment', - openapi: new Model\Operation( - summary: 'Returns a Role assignment of the given User Group.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'roleId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns a Role assignment of the given User Group.', - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignment+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignment', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/GET/RoleAssignment.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignment+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/GET/RoleAssignment.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/groups/{path}/roles/{roleId}', - name: 'Unassign Role from User Group', - openapi: new Model\Operation( - summary: 'The given Role is removed from the User or User Group.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'roleId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignmentList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/GET/RoleAssignment.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignmentList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/DELETE/RoleAssignmentList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this Role assignment.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/policies', - name: 'List Policies for User', - openapi: new Model\Operation( - summary: 'Search all Policies which are applied to a given User.', - tags: [ - 'User Policy', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Policy list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Policies which are applied to a given User.', - 'content' => [ - 'application/vnd.ibexa.api.PolicyList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/GET/PolicyList.xml.example', - ], - 'application/vnd.ibexa.api.PolicyList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/roles/id/policies/GET/PolicyList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - ], - ), -)] -/** - * Role controller. - */ -class Role extends RestController -{ - /** - * Role service. - * - * @var \Ibexa\Contracts\Core\Repository\RoleService - */ - protected $roleService; - - /** - * User service. - * - * @var \Ibexa\Contracts\Core\Repository\UserService - */ - protected $userService; - - /** - * Location service. - * - * @var \Ibexa\Contracts\Core\Repository\LocationService - */ - protected $locationService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\RoleService $roleService - * @param \Ibexa\Contracts\Core\Repository\UserService $userService - * @param \Ibexa\Contracts\Core\Repository\LocationService $locationService - */ - public function __construct( - RoleService $roleService, - UserService $userService, - LocationService $locationService - ) { - $this->roleService = $roleService; - $this->userService = $userService; - $this->locationService = $locationService; - } - - /** - * Create new role. - * - * Defaults to publishing the role, but you can create a draft instead by setting the POST parameter publish=false - * - * @return \Ibexa\Rest\Server\Values\CreatedRole - */ - public function createRole(Request $request) - { - $publish = ( - !$request->query->has('publish') || - ($request->query->has('publish') && $request->query->get('publish') === 'true') - ); - - try { - $roleDraft = $this->roleService->createRole( - $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - // @todo Needs refactoring! Temporary solution so parser has access to get parameters - '__publish' => $publish, - ], - $request->getContent() - ) - ) - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } catch (UnauthorizedException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } catch (LimitationValidationException $e) { - throw new BadRequestException($e->getMessage()); - } catch (Exceptions\Parser $e) { - throw new BadRequestException($e->getMessage()); - } - - if ($publish) { - @trigger_error( - "Create and publish role in the same operation is deprecated, and will be removed in the future.\n" . - 'Instead, publish the role draft using Role::publishRoleDraft().', - E_USER_DEPRECATED - ); - - $this->roleService->publishRoleDraft($roleDraft); - - $role = $this->roleService->loadRole($roleDraft->id); - - return new Values\CreatedRole(['role' => new Values\RestRole($role)]); - } - - return new Values\CreatedRole(['role' => new Values\RestRole($roleDraft)]); - } - - /** - * Creates a new RoleDraft for an existing Role. - * - * @since 6.2 - * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ForbiddenException if the Role already has a Role Draft that will need to be removed first, - * or if the authenticated user is not allowed to create a role - * @throws \Ibexa\Rest\Server\Exceptions\BadRequestException if a policy limitation in the $roleCreateStruct is not valid - * - * @return \Ibexa\Rest\Server\Values\CreatedRole - */ - public function createRoleDraft($roleId, Request $request) - { - try { - $roleDraft = $this->roleService->createRoleDraft( - $this->roleService->loadRole($roleId) - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } catch (UnauthorizedException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } catch (LimitationValidationException $e) { - throw new BadRequestException($e->getMessage()); - } catch (Exceptions\Parser $e) { - throw new BadRequestException($e->getMessage()); - } - - return new Values\CreatedRole(['role' => new Values\RestRole($roleDraft)]); - } - - /** - * Loads list of roles. - * - * @return \Ibexa\Rest\Server\Values\RoleList - */ - public function listRoles(Request $request) - { - $roles = []; - if ($request->query->has('identifier')) { - try { - $role = $this->roleService->loadRoleByIdentifier($request->query->get('identifier')); - $roles[] = $role; - } catch (APINotFoundException $e) { - // Do nothing - } - } else { - $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0; - $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : -1; - - $roles = array_slice( - $this->roleService->loadRoles(), - $offset >= 0 ? $offset : 0, - $limit >= 0 ? $limit : null - ); - } - - return new Values\RoleList($roles, $request->getPathInfo()); - } - - /** - * Loads role. - * - * @param $roleId - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\Role - */ - public function loadRole($roleId) - { - return $this->roleService->loadRole($roleId); - } - - /** - * Loads a role draft. - * - * @param mixed $roleId Original role ID, or ID of the role draft itself - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\RoleDraft - */ - public function loadRoleDraft($roleId) - { - try { - // First try to load the draft for given role. - return $this->roleService->loadRoleDraftByRoleId($roleId); - } catch (NotFoundException $e) { - // We might want a newly created role, so try to load it by its ID. - // loadRoleDraft() might throw a NotFoundException (wrong $roleId). If so, let it bubble up. - return $this->roleService->loadRoleDraft($roleId); - } - } - - /** - * Updates a role. - * - * @param $roleId - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\Role - */ - public function updateRole($roleId, Request $request) - { - $createStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - $roleDraft = $this->roleService->createRoleDraft( - $this->roleService->loadRole($roleId) - ); - $roleDraft = $this->roleService->updateRoleDraft( - $roleDraft, - $this->mapToUpdateStruct($createStruct) - ); - - $this->roleService->publishRoleDraft($roleDraft); - - return $this->roleService->loadRole($roleId); - } - - /** - * Updates a role draft. - * - * @param mixed $roleId Original role ID, or ID of the role draft itself - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\RoleDraft - */ - public function updateRoleDraft($roleId, Request $request) - { - $createStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - try { - // First try to load the draft for given role. - $roleDraft = $this->roleService->loadRoleDraftByRoleId($roleId); - } catch (NotFoundException $e) { - // We might want a newly created role, so try to load it by its ID. - // loadRoleDraft() might throw a NotFoundException (wrong $roleId). If so, let it bubble up. - $roleDraft = $this->roleService->loadRoleDraft($roleId); - } - - return $this->roleService->updateRoleDraft($roleDraft, $this->mapToUpdateStruct($createStruct)); - } - - /** - * Publishes a role draft. - * - * @param mixed $roleId Original role ID, or ID of the role draft itself - * - * @return \Ibexa\Rest\Server\Values\PublishedRole - */ - public function publishRoleDraft($roleId) - { - try { - // First try to load the draft for given role. - $roleDraft = $this->roleService->loadRoleDraftByRoleId($roleId); - } catch (NotFoundException $e) { - // We might want a newly created role, so try to load it by its ID. - // loadRoleDraft() might throw a NotFoundException (wrong $roleId). If so, let it bubble up. - $roleDraft = $this->roleService->loadRoleDraft($roleId); - } - - $this->roleService->publishRoleDraft($roleDraft); - - $role = $this->roleService->loadRoleByIdentifier($roleDraft->identifier); - - return new Values\PublishedRole(['role' => new Values\RestRole($role)]); - } - - /** - * Delete a role by ID. - * - * @param $roleId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteRole($roleId) - { - $this->roleService->deleteRole( - $this->roleService->loadRole($roleId) - ); - - return new Values\NoContent(); - } - - /** - * Delete a role draft by ID. - * - * @since 6.2 - * - * @param $roleId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteRoleDraft($roleId) - { - $this->roleService->deleteRoleDraft( - $this->roleService->loadRoleDraft($roleId) - ); - - return new Values\NoContent(); - } - - /** - * Loads the policies for the role. - * - * @param $roleId - * - * @return \Ibexa\Rest\Server\Values\PolicyList - */ - public function loadPolicies($roleId, Request $request) - { - $loadedRole = $this->roleService->loadRole($roleId); - - return new Values\PolicyList($loadedRole->getPolicies(), $request->getPathInfo()); - } - - /** - * Deletes all policies from a role. - * - * @param $roleId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deletePolicies($roleId) - { - $loadedRole = $this->roleService->loadRole($roleId); - $roleDraft = $this->roleService->createRoleDraft($loadedRole); - /** @var \Ibexa\Contracts\Core\Repository\Values\User\PolicyDraft $policyDraft */ - foreach ($roleDraft->getPolicies() as $policyDraft) { - $this->roleService->removePolicyByRoleDraft($roleDraft, $policyDraft); - } - $this->roleService->publishRoleDraft($roleDraft); - - return new Values\NoContent(); - } - - /** - * Loads a policy. - * - * @param $roleId - * @param $policyId - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\Policy - */ - public function loadPolicy($roleId, $policyId, Request $request) - { - $loadedRole = $this->roleService->loadRole($roleId); - foreach ($loadedRole->getPolicies() as $policy) { - if ($policy->id == $policyId) { - return $policy; - } - } - - throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'."); - } - - /** - * Adds a policy to role. - * - * @param int $roleId ID of a role draft - * - * @return \Ibexa\Rest\Server\Values\CreatedPolicy - */ - public function addPolicy($roleId, Request $request) - { - $createStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - try { - // First try to treat $roleId as a role draft ID. - $role = $this->roleService->addPolicyByRoleDraft( - $this->roleService->loadRoleDraft($roleId), - $createStruct - ); - } catch (NotFoundException $e) { - // Then try to treat $roleId as a role ID. - $roleDraft = $this->roleService->createRoleDraft( - $this->roleService->loadRole($roleId) - ); - $roleDraft = $this->roleService->addPolicyByRoleDraft( - $roleDraft, - $createStruct - ); - $this->roleService->publishRoleDraft($roleDraft); - $role = $this->roleService->loadRole($roleId); - } catch (LimitationValidationException $e) { - throw new BadRequestException($e->getMessage()); - } - - return new Values\CreatedPolicy( - [ - 'policy' => $this->getLastAddedPolicy($role), - ] - ); - } - - /** - * Get the last added policy for $role. - * - * This is needed because the RoleService addPolicy() and addPolicyByRoleDraft() methods return the role, - * not the policy. - * - * @param $role \Ibexa\Contracts\Core\Repository\Values\User\Role - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\Policy - */ - private function getLastAddedPolicy($role) - { - $policies = $role->getPolicies(); - - $policyToReturn = $policies[0]; - for ($i = 1, $count = count($policies); $i < $count; ++$i) { - if ($policies[$i]->id > $policyToReturn->id) { - $policyToReturn = $policies[$i]; - } - } - - return $policyToReturn; - } - - /** - * Updates a policy. - * - * @param int $roleId ID of a role draft - * @param int $policyId ID of a policy - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\Policy - */ - public function updatePolicy($roleId, $policyId, Request $request) - { - $updateStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - try { - // First try to treat $roleId as a role draft ID. - $roleDraft = $this->roleService->loadRoleDraft($roleId); - foreach ($roleDraft->getPolicies() as $policy) { - if ($policy->id == $policyId) { - try { - return $this->roleService->updatePolicyByRoleDraft( - $roleDraft, - $policy, - $updateStruct - ); - } catch (LimitationValidationException $e) { - throw new BadRequestException($e->getMessage()); - } - } - } - } catch (NotFoundException $e) { - // Then try to treat $roleId as a role ID. - $roleDraft = $this->roleService->createRoleDraft( - $this->roleService->loadRole($roleId) - ); - foreach ($roleDraft->getPolicies() as $policy) { - if ($policy->originalId == $policyId) { - try { - $policyDraft = $this->roleService->updatePolicyByRoleDraft( - $roleDraft, - $policy, - $updateStruct - ); - $this->roleService->publishRoleDraft($roleDraft); - $role = $this->roleService->loadRole($roleId); - - foreach ($role->getPolicies() as $newPolicy) { - if ($newPolicy->id == $policyDraft->id) { - return $newPolicy; - } - } - } catch (LimitationValidationException $e) { - throw new BadRequestException($e->getMessage()); - } - } - } - } - - throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'."); - } - - /** - * Delete a policy from role. - * - * @param int $roleId ID of a role draft - * @param int $policyId ID of a policy - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deletePolicy($roleId, $policyId, Request $request) - { - try { - // First try to treat $roleId as a role draft ID. - $roleDraft = $this->roleService->loadRoleDraft($roleId); - $policy = null; - foreach ($roleDraft->getPolicies() as $rolePolicy) { - if ($rolePolicy->id == $policyId) { - $policy = $rolePolicy; - break; - } - } - if ($policy !== null) { - $this->roleService->removePolicyByRoleDraft($roleDraft, $policy); - - return new Values\NoContent(); - } - } catch (NotFoundException $e) { - // Then try to treat $roleId as a role ID. - $roleDraft = $this->roleService->createRoleDraft( - $this->roleService->loadRole($roleId) - ); - $policy = null; - foreach ($roleDraft->getPolicies() as $rolePolicy) { - if ($rolePolicy->originalId == $policyId) { - $policy = $rolePolicy; - break; - } - } - if ($policy !== null) { - $this->roleService->removePolicyByRoleDraft($roleDraft, $policy); - $this->roleService->publishRoleDraft($roleDraft); - - return new Values\NoContent(); - } - } - throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'."); - } - - /** - * Assigns role to user. - * - * @param $userId - * - * @return \Ibexa\Rest\Server\Values\RoleAssignmentList - */ - public function assignRoleToUser($userId, Request $request) - { - $roleAssignment = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $user = $this->userService->loadUser($userId); - $role = $this->roleService->loadRole($roleAssignment->roleId); - - try { - $this->roleService->assignRoleToUser($role, $user, $roleAssignment->limitation); - } catch (LimitationValidationException $e) { - throw new BadRequestException($e->getMessage()); - } - - $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user); - - return new Values\RoleAssignmentList($roleAssignments, $user->id); - } - - /** - * Assigns role to user group. - * - * @param $groupPath - * - * @return \Ibexa\Rest\Server\Values\RoleAssignmentList - */ - public function assignRoleToUserGroup($groupPath, Request $request) - { - $roleAssignment = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - $groupLocationParts = explode('/', $groupPath); - $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts)); - $userGroup = $this->userService->loadUserGroup($groupLocation->contentId); - - $role = $this->roleService->loadRole($roleAssignment->roleId); - - try { - $this->roleService->assignRoleToUserGroup($role, $userGroup, $roleAssignment->limitation); - } catch (LimitationValidationException $e) { - throw new BadRequestException($e->getMessage()); - } - - $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup); - - return new Values\RoleAssignmentList($roleAssignments, $groupPath, true); - } - - /** - * Un-assigns role from user. - * - * @param $userId - * @param $roleId - * - * @return \Ibexa\Rest\Server\Values\RoleAssignmentList - */ - public function unassignRoleFromUser($userId, $roleId) - { - $user = $this->userService->loadUser($userId); - - $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user); - foreach ($roleAssignments as $roleAssignment) { - if ($roleAssignment->role->id == $roleId) { - $this->roleService->removeRoleAssignment($roleAssignment); - } - } - $newRoleAssignments = $this->roleService->getRoleAssignmentsForUser($user); - - return new Values\RoleAssignmentList($newRoleAssignments, $user->id); - } - - /** - * Un-assigns role from user group. - * - * @param $groupPath - * @param $roleId - * - * @return \Ibexa\Rest\Server\Values\RoleAssignmentList - */ - public function unassignRoleFromUserGroup($groupPath, $roleId) - { - $groupLocationParts = explode('/', $groupPath); - $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts)); - $userGroup = $this->userService->loadUserGroup($groupLocation->contentId); - - $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup); - foreach ($roleAssignments as $roleAssignment) { - if ($roleAssignment->role->id == $roleId) { - $this->roleService->removeRoleAssignment($roleAssignment); - } - } - $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup); - - return new Values\RoleAssignmentList($roleAssignments, $groupPath, true); - } - - /** - * Loads role assignments for user. - * - * @param $userId - * - * @return \Ibexa\Rest\Server\Values\RoleAssignmentList - */ - public function loadRoleAssignmentsForUser($userId) - { - $user = $this->userService->loadUser($userId); - - $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user); - - return new Values\RoleAssignmentList($roleAssignments, $user->id); - } - - /** - * Loads role assignments for user group. - * - * @param $groupPath - * - * @return \Ibexa\Rest\Server\Values\RoleAssignmentList - */ - public function loadRoleAssignmentsForUserGroup($groupPath) - { - $groupLocationParts = explode('/', $groupPath); - $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts)); - $userGroup = $this->userService->loadUserGroup($groupLocation->contentId); - - $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup); - - return new Values\RoleAssignmentList($roleAssignments, $groupPath, true); - } - - /** - * Returns a role assignment to the given user. - * - * @param $userId - * @param $roleId - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\RestUserRoleAssignment - */ - public function loadRoleAssignmentForUser($userId, $roleId, Request $request) - { - $user = $this->userService->loadUser($userId); - $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user); - - foreach ($roleAssignments as $roleAssignment) { - if ($roleAssignment->getRole()->id == $roleId) { - return new Values\RestUserRoleAssignment($roleAssignment, $userId); - } - } - - throw new Exceptions\NotFoundException("Role assignment not found: '{$request->getPathInfo()}'."); - } - - /** - * Returns a role assignment to the given user group. - * - * @param $groupPath - * @param $roleId - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * - * @return \Ibexa\Rest\Server\Values\RestUserGroupRoleAssignment - */ - public function loadRoleAssignmentForUserGroup($groupPath, $roleId, Request $request) - { - $groupLocationParts = explode('/', $groupPath); - $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts)); - $userGroup = $this->userService->loadUserGroup($groupLocation->contentId); - - $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup); - foreach ($roleAssignments as $roleAssignment) { - if ($roleAssignment->getRole()->id == $roleId) { - return new Values\RestUserGroupRoleAssignment($roleAssignment, $groupPath); - } - } - - throw new Exceptions\NotFoundException("Role assignment not found: '{$request->getPathInfo()}'."); - } - - /** - * Search all policies which are applied to a given user. - * - * @return \Ibexa\Rest\Server\Values\PolicyList - */ - public function listPoliciesForUser(Request $request) - { - $user = $this->userService->loadUser((int)$request->query->get('userId')); - $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user, true); - - $policies = []; - foreach ($roleAssignments as $roleAssignment) { - $policies[] = $roleAssignment->getRole()->getPolicies(); - } - - return new Values\PolicyList( - !empty($policies) ? array_merge(...$policies) : [], - $request->getPathInfo() - ); - } - - /** - * Maps a RoleCreateStruct to a RoleUpdateStruct. - * - * Needed since both structs are encoded into the same media type on input. - * - * @param \Ibexa\Contracts\Core\Repository\Values\User\RoleCreateStruct $createStruct - * - * @return \Ibexa\Contracts\Core\Repository\Values\User\RoleUpdateStruct - */ - protected function mapToUpdateStruct(RoleCreateStruct $createStruct) - { - return new RoleUpdateStruct( - [ - 'identifier' => $createStruct->identifier, - ] - ); - } -} diff --git a/src/lib/Server/Controller/Section.php b/src/lib/Server/Controller/Section.php deleted file mode 100644 index 8428bc15..00000000 --- a/src/lib/Server/Controller/Section.php +++ /dev/null @@ -1,488 +0,0 @@ - false], - openapi: new Model\Operation( - summary: 'Creates a new Section.', - tags: [ - 'Section', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new Section is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Section input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.SectionInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/POST/SectionInput.xml.example', - ], - 'application/vnd.ibexa.api.SectionInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/POST/SectionInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.Section+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Section', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/section_id/PATCH/Section.xml.example', - ], - 'application/vnd.ibexa.api.Section+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/section_id/PATCH/Section.json.example', - ], - ], - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/sections', - name: 'Get Sections', - openapi: new Model\Operation( - summary: 'Returns a list of all Sections.', - tags: [ - 'Section', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Section list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.SectionList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/GET/SectionList.xml.example', - ], - 'application/vnd.ibexa.api.SectionList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/GET/SectionList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read the Section.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/sections/{sectionId}', - name: 'Get Section', - openapi: new Model\Operation( - summary: 'Returns the Section by given Section ID.', - tags: [ - 'Section', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Section is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'sectionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Section+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Section', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/section_id/PATCH/Section.xml.example', - ], - 'application/vnd.ibexa.api.Section+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/section_id/PATCH/Section.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read this Section.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The Section does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/content/sections/{sectionId}', - name: 'Update a Section', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates a Section. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'Section', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Section is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The Section input schema encoded in XML or JSON.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'sectionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.SectionInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/POST/SectionInput.xml.example', - ], - 'application/vnd.ibexa.api.SectionInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/POST/SectionInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Section updated.', - 'content' => [ - 'application/vnd.ibexa.api.Section+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Section', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/section_id/PATCH/Section.xml.example', - ], - 'application/vnd.ibexa.api.Section+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SectionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/sections/section_id/PATCH/Section.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create this Section.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - a Section with the given identifier already exists.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - the current ETag does not match with the one provided in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/sections/{sectionId}', - name: 'Delete Section', - openapi: new Model\Operation( - summary: 'The given Section is deleted.', - tags: [ - 'Section', - ], - parameters: [ - new Model\Parameter( - name: 'sectionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - given Section is deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this Section.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Section does not exist.', - ], - ], - ), -)] -/** - * Section controller. - */ -class Section extends RestController -{ - /** - * Section service. - * - * @var \Ibexa\Contracts\Core\Repository\SectionService - */ - protected $sectionService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\SectionService $sectionService - */ - public function __construct(SectionService $sectionService) - { - $this->sectionService = $sectionService; - } - - /** - * List sections. - * - * @return \Ibexa\Rest\Server\Values\SectionList - */ - public function listSections(Request $request) - { - if ($request->query->has('identifier')) { - $sections = [ - $this->loadSectionByIdentifier($request), - ]; - } else { - $sections = $this->sectionService->loadSections(); - } - - return new Values\SectionList($sections, $request->getPathInfo()); - } - - /** - * Loads section by identifier. - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Section - */ - public function loadSectionByIdentifier(Request $request) - { - return $this->sectionService->loadSectionByIdentifier( - // GET variable - $request->query->get('identifier') - ); - } - - /** - * Create new section. - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedSection - */ - public function createSection(Request $request) - { - try { - $createdSection = $this->sectionService->createSection( - $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ) - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - return new Values\CreatedSection( - [ - 'section' => $createdSection, - ] - ); - } - - /** - * Loads a section. - * - * @param $sectionId - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Section - */ - public function loadSection($sectionId) - { - return $this->sectionService->loadSection($sectionId); - } - - /** - * Updates a section. - * - * @param $sectionId - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Section - */ - public function updateSection($sectionId, Request $request) - { - $createStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - try { - return $this->sectionService->updateSection( - $this->sectionService->loadSection($sectionId), - $this->mapToUpdateStruct($createStruct) - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - /** - * Delete a section by ID. - * - * @param $sectionId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteSection($sectionId) - { - $this->sectionService->deleteSection( - $this->sectionService->loadSection($sectionId) - ); - - return new NoContent(); - } - - /** - * Maps a SectionCreateStruct to a SectionUpdateStruct. - * - * Needed since both structs are encoded into the same media type on input. - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\SectionCreateStruct $createStruct - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\SectionUpdateStruct - */ - protected function mapToUpdateStruct(SectionCreateStruct $createStruct) - { - return new SectionUpdateStruct( - [ - 'name' => $createStruct->name, - 'identifier' => $createStruct->identifier, - ] - ); - } -} diff --git a/src/lib/Server/Controller/SessionController.php b/src/lib/Server/Controller/SessionController.php deleted file mode 100644 index f0aeee36..00000000 --- a/src/lib/Server/Controller/SessionController.php +++ /dev/null @@ -1,499 +0,0 @@ - false], - openapi: new Model\Operation( - summary: 'Performs a login for the user or checks if session exists and returns the session and session cookie. The client will need to remember both session name/ID and CSRF token as this is for security reasons not exposed via GET.', - tags: [ - 'User Session', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the session is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The SessionInput schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Cookie', - in: 'header', - required: true, - description: 'Only needed for session\'s checking {sessionName}={sessionID}.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'X-CSRF-Token', - in: 'header', - required: true, - description: 'Only needed for session\'s checking. The {csrfToken} needed on all unsafe HTTP methods with session.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.SessionInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SessionInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/POST/SessionInput.xml.example', - ], - 'application/vnd.ibexa.api.SessionInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SessionInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/POST/SessionInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'Session already exists.', - 'content' => [ - 'application/vnd.ibexa.api.Session+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Session', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/POST/Session.xml.example', - ], - 'application/vnd.ibexa.api.Session+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SessionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/session_id/refresh/POST/Session.json.example', - ], - ], - ], - Response::HTTP_CREATED => [ - 'description' => 'Session is created.', - 'content' => [ - 'application/vnd.ibexa.api.Session+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Session', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/POST/Session.xml.example', - ], - 'application/vnd.ibexa.api.Session+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SessionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/session_id/refresh/POST/Session.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the authorization failed.', - ], - Response::HTTP_CONFLICT => [ - 'description' => 'Error - header contained a session cookie but different user was authorized.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/sessions/current', - name: 'Get current session', - openapi: new Model\Operation( - summary: 'Get current user session, if any.', - tags: [ - 'User Session', - ], - parameters: [ - new Model\Parameter( - name: 'Cookie', - in: 'header', - required: true, - description: 'Only needed for session\'s checking {sessionName}={sessionID}.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the session is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'User is currently logged in and has a valid session.', - 'content' => [ - 'application/vnd.ibexa.api.Session+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Session', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/POST/Session.xml.example', - ], - 'application/vnd.ibexa.api.Session+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SessionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/session_id/refresh/POST/Session.json.example', - ], - ], - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'User does not have a valid session, or it has expired.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/sessions/{sessionId}', - name: 'Delete session (logout a User)', - openapi: new Model\Operation( - summary: 'The user session is removed i.e. the user is logged out.', - tags: [ - 'User Session', - ], - parameters: [ - new Model\Parameter( - name: 'Cookie', - in: 'header', - required: true, - description: '{sessionName}={sessionID}', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'X-CSRF-Token', - in: 'header', - required: true, - description: 'The {csrfToken} needed on all unsafe HTTP methods with session.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'sessionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'OK - session deleted.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the session does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/sessions/{sessionId}/refresh', - name: 'Refresh session (deprecated)', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'Get the session\'s User information. Deprecated as of Ibexa DXP 4.6, use GET /user/sessions/current instead.', - tags: [ - 'User Session', - ], - parameters: [ - new Model\Parameter( - name: 'Cookie', - in: 'header', - required: true, - description: '{sessionName}={sessionID}', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'X-CSRF-Token', - in: 'header', - required: true, - description: 'The {csrfToken} needed on all unsafe HTTP methods with session.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'sessionId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.Session+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Session', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/POST/Session.xml.example', - ], - 'application/vnd.ibexa.api.Session+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/SessionWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/sessions/session_id/refresh/POST/Session.json.example', - ], - ], - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the session does not exist.', - ], - ], - ), -)] -/** - * @internal - */ -final class SessionController extends Controller -{ - public function __construct( - private readonly PermissionResolver $permissionResolver, - private readonly UserService $userService, - private readonly CsrfTokenManager $csrfTokenManager, - private readonly SecurityTokenStorageInterface $securityTokenStorage, - private readonly string $csrfTokenIntention, - private readonly ConfigResolverInterface $configResolver, - ) { - } - - /** - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function createSessionAction(Request $request): RestValue - { - try { - $session = $request->getSession(); - $csrfToken = $this->getCsrfToken(); - $token = $this->securityTokenStorage->getToken(); - - if ($token === null) { - throw new UnauthorizedException('The current user is not authenticated.'); - } - - /** @var \Ibexa\Core\MVC\Symfony\Security\User $user */ - $user = $token->getUser(); - - return new Values\UserSession( - $user->getAPIUser(), - $session->getName(), - $session->getId(), - $csrfToken, - !$token->hasAttribute('isFromSession') - ); - } catch (Exceptions\UserConflictException $e) { - // Already logged in with another user, this will be converted to HTTP status 409 - return new Values\Conflict(); - } catch (AuthenticationException $e) { - throw new UnauthorizedException('Invalid login or password'); - } catch (AccessDeniedException $e) { - throw new UnauthorizedException($e->getMessage()); - } - } - - /** - * @return \Ibexa\Rest\Server\Values\UserSession|\Symfony\Component\HttpFoundation\Response - */ - public function checkSessionAction(Request $request) - { - $session = $request->getSession(); - if ($session === null || !$session->isStarted()) { - return $this->logout($request); - } - - $currentUser = $this->userService->loadUser( - $this->permissionResolver->getCurrentUserReference()->getUserId() - ); - - return new Values\UserSession( - $currentUser, - $session->getName(), - $session->getId(), - $this->getCsrfToken(), - false - ); - } - - /** - * Refresh given session. - * - * @deprecated 5.0.0 The "SessionController::refreshSessionAction()" method is deprecated, will be removed in the next API version. Use SessionController::checkSessionAction() instead. - * - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - */ - public function refreshSessionAction(string $sessionId, Request $request): Values\UserSession|Response - { - trigger_deprecation( - 'ibexa/rest', - '4.6.7', - sprintf('The %s() method is deprecated, will be removed in the next API version.', __METHOD__) - ); - - $session = $request->getSession(); - - if ($session === null || !$session->isStarted() || $session->getId() !== $sessionId || !$this->hasStoredCsrfToken()) { - return $this->logout($request); - } - - $this->checkCsrfToken($request); - $currentUser = $this->userService->loadUser( - $this->permissionResolver->getCurrentUserReference()->getUserId() - ); - - return new Values\UserSession( - $currentUser, - $session->getName(), - $session->getId(), - $request->headers->get('X-CSRF-Token') ?? '', - false - ); - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - */ - public function deleteSessionAction(string $sessionId, Request $request): Values\DeletedUserSession|Response - { - /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ - $session = $request->getSession(); - if (!$session->isStarted() || $session->getId() !== $sessionId || !$this->hasStoredCsrfToken()) { - return $this->logout($request); - } - - $this->checkCsrfToken($request); - - return new Values\DeletedUserSession( - $this->logout($request) - ); - } - - private function hasStoredCsrfToken(): bool - { - return $this->csrfTokenManager->hasToken($this->csrfTokenIntention); - } - - /** - * Checks the presence / validity of the CSRF token. - * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the token is missing or invalid - */ - private function checkCsrfToken(Request $request): void - { - if (!$request->headers->has('X-CSRF-Token')) { - throw $this->createInvalidCsrfTokenException($request); - } - - $csrfToken = new CsrfToken( - $this->csrfTokenIntention, - $request->headers->get('X-CSRF-Token') - ); - - if (!$this->csrfTokenManager->isTokenValid($csrfToken)) { - throw $this->createInvalidCsrfTokenException($request); - } - } - - private function getCsrfToken(): string - { - return $this->csrfTokenManager->getToken($this->csrfTokenIntention)->getValue(); - } - - private function createInvalidCsrfTokenException(Request $request): UnauthorizedException - { - return new UnauthorizedException('Missing or invalid CSRF token'); - } - - private function logout(Request $request): Response - { - $path = '/'; - $domain = null; - - $session = $this->configResolver->getParameter('session'); - if (array_key_exists('cookie_domain', $session)) { - $domain = $session['cookie_domain']; - } - - if (array_key_exists('cookie_path', $session)) { - $path = $session['cookie_path']; - } - - $response = new Response(); - $requestSession = $request->getSession(); - - $response->headers->clearCookie( - $requestSession->getName(), - $path, - $domain - ); - - $response->setStatusCode(404); - $requestSession->clear(); - - return $response; - } -} diff --git a/src/lib/Server/Controller/Trash.php b/src/lib/Server/Controller/Trash.php deleted file mode 100644 index 4548b6c4..00000000 --- a/src/lib/Server/Controller/Trash.php +++ /dev/null @@ -1,409 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the list of items in the Trash.', - 'content' => [ - 'application/vnd.ibexa.api.Trash+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/Trash', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/trash/GET/Trash.xml.example', - ], - 'application/vnd.ibexa.api.Trash+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/TrashWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/trash/GET/Trash.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read the Trash.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/trash', - name: 'Empty Trash', - openapi: new Model\Operation( - summary: 'Empties the Trash.', - tags: [ - 'Trash', - ], - parameters: [ - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - Trash emptied.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to empty all items from Trash.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/trash/{trashItemid}', - name: 'Get Trash item', - openapi: new Model\Operation( - summary: 'Returns the item in Trash with the provided ID.', - tags: [ - 'Trash', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the item in Trash is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'trashItemid', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.TrashItem+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/TrashItem', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/trash/trash_itemid/GET/TrashItem.xml.example', - ], - 'application/vnd.ibexa.api.TrashItem+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/TrashItemWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/trash/trash_itemid/GET/TrashItem.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read the item in Trash.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - An item in Trash with the provided ID does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/trash/{trashItemid}', - name: 'Delete Trash item', - openapi: new Model\Operation( - summary: 'Deletes the provided item from Trash.', - tags: [ - 'Trash', - ], - parameters: [ - new Model\Parameter( - name: 'trashItemid', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - item deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete the provided item.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The provided item does not exist in Trash.', - ], - ], - ), -)] -/** - * Trash controller. - */ -class Trash extends RestController -{ - /** - * Trash service. - * - * @var \Ibexa\Contracts\Core\Repository\TrashService - */ - protected $trashService; - - /** - * Location service. - * - * @var \Ibexa\Contracts\Core\Repository\LocationService - */ - protected $locationService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\TrashService $trashService - * @param \Ibexa\Contracts\Core\Repository\LocationService $locationService - */ - public function __construct(TrashService $trashService, LocationService $locationService) - { - $this->trashService = $trashService; - $this->locationService = $locationService; - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - */ - public function trashLocation(string $locationPath): RestValue - { - $location = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($locationPath), - ); - - $trashItem = $this->trashService->trash($location); - - if ($trashItem === null) { - return new Values\NoContent(); - } - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_trash_item', - ['trashItemId' => $trashItem->getId()], - ), - ); - } - - /** - * Returns a list of all trash items. - * - * @return \Ibexa\Rest\Server\Values\Trash - */ - public function loadTrashItems(Request $request) - { - $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0; - $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : -1; - - $query = new Query(); - $query->offset = $offset >= 0 ? $offset : null; - $query->limit = $limit >= 0 ? $limit : null; - - $trashItems = []; - - foreach ($this->trashService->findTrashItems($query)->items as $trashItem) { - $trashItems[] = new Values\RestTrashItem( - $trashItem, - $this->locationService->getLocationChildCount($trashItem) - ); - } - - return new Values\Trash( - $trashItems, - $request->getPathInfo() - ); - } - - /** - * Returns the trash item given by id. - * - * @param $trashItemId - * - * @return \Ibexa\Rest\Server\Values\RestTrashItem - */ - public function loadTrashItem($trashItemId) - { - return new Values\RestTrashItem( - $trashItem = $this->trashService->loadTrashItem($trashItemId), - $this->locationService->getLocationChildCount($trashItem) - ); - } - - /** - * Empties the trash. - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function emptyTrash() - { - $this->trashService->emptyTrash(); - - return new Values\NoContent(); - } - - /** - * Deletes the given trash item. - * - * @param $trashItemId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteTrashItem($trashItemId) - { - $this->trashService->deleteTrashItem( - $this->trashService->loadTrashItem($trashItemId) - ); - - return new Values\NoContent(); - } - - /** - * Restores a trashItem. - * - * @param $trashItemId - * - * @return \Ibexa\Rest\Server\Values\ResourceCreated - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - */ - public function restoreTrashItem($trashItemId, Request $request) - { - $requestDestination = null; - try { - $requestDestination = $request->headers->get('Destination'); - } catch (InvalidArgumentException $e) { - // No Destination header - } - - $parentLocation = null; - if ($request->headers->has('Destination')) { - $locationPathParts = explode( - '/', - $this->requestParser->parseHref($request->headers->get('Destination'), 'locationPath') - ); - - try { - $parentLocation = $this->locationService->loadLocation(array_pop($locationPathParts)); - } catch (NotFoundException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - $trashItem = $this->trashService->loadTrashItem($trashItemId); - - if ($requestDestination === null) { - // If we're recovering under the original location - // check if it exists, to return "403 Forbidden" in case it does not - try { - $this->locationService->loadLocation($trashItem->parentLocationId); - } catch (NotFoundException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - $location = $this->trashService->recover($trashItem, $parentLocation); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_location', - [ - 'locationPath' => trim($location->pathString, '/'), - ] - ) - ); - } - - /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ForbiddenException - */ - public function restoreItem(int $trashItemId, Request $request): Values\ResourceCreated - { - try { - /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Location|null $locationDestination */ - $locationDestination = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent(), - ), - ); - } catch (ApiExceptions\NotFoundException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage(), 1, $e); - } - - $trashItem = $this->trashService->loadTrashItem($trashItemId); - - if ($locationDestination === null) { - try { - $locationDestination = $this->locationService->loadLocation($trashItem->parentLocationId); - } catch (NotFoundException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage(), 1, $e); - } - } - - $location = $this->trashService->recover($trashItem, $locationDestination); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_location', - [ - 'locationPath' => trim($location->getPathString(), '/'), - ], - ) - ); - } - - private function extractLocationIdFromPath(string $path): int - { - $pathParts = explode('/', $path); - $lastPart = array_pop($pathParts); - - Assert::integerish($lastPart); - - return (int)$lastPart; - } -} diff --git a/src/lib/Server/Controller/URLAlias.php b/src/lib/Server/Controller/URLAlias.php deleted file mode 100644 index bd20832f..00000000 --- a/src/lib/Server/Controller/URLAlias.php +++ /dev/null @@ -1,386 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the list of URL aliases.', - 'content' => [ - 'application/vnd.ibexa.api.UrlAliasRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/GET/UrlAliasRefList.xml.example', - ], - 'application/vnd.ibexa.api.UrlAliasRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/GET/UrlAliasRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read URL aliases.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/urlaliases', - name: 'Create URL alias', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a URL alias.', - tags: [ - 'Url Alias', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the created URL alias is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The URL alias input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.UrlAliasCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/POST/UrlAliasCreate.xml.example', - ], - 'application/vnd.ibexa.api.UrlAliasCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/POST/UrlAliasCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'URL alias created.', - 'content' => [ - 'application/vnd.ibexa.api.UrlAlias+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAlias', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/url_alias_id/GET/UrlAlias.xml.example', - ], - 'application/vnd.ibexa.api.UrlAlias+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/url_alias_id/GET/UrlAlias.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create a URL alias.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A URL alias with the same identifier already exists.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/urlaliases/{urlAliasId}', - name: 'Get URL alias', - openapi: new Model\Operation( - summary: 'Returns the URL alias with the given ID.', - tags: [ - 'Url Alias', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the URL alias is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'urlAliasId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the URL alias.', - 'content' => [ - 'application/vnd.ibexa.api.UrlAlias+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAlias', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/url_alias_id/GET/UrlAlias.xml.example', - ], - 'application/vnd.ibexa.api.UrlAlias+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlAliasWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlaliases/url_alias_id/GET/UrlAlias.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read URL aliases.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The URL alias does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/urlaliases/{urlAliasId}', - name: 'Delete URL alias', - openapi: new Model\Operation( - summary: 'Deletes the provided URL alias.', - tags: [ - 'Url Alias', - ], - parameters: [ - new Model\Parameter( - name: 'urlAliasId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - URL alias deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete a URL alias.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The URL alias does not exist.', - ], - ], - ), -)] -/** - * URLAlias controller. - */ -class URLAlias extends RestController -{ - /** - * URLAlias service. - * - * @var \Ibexa\Contracts\Core\Repository\URLAliasService - */ - protected $urlAliasService; - - /** - * Location service. - * - * @var \Ibexa\Contracts\Core\Repository\LocationService - */ - protected $locationService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\URLAliasService $urlAliasService - * @param \Ibexa\Contracts\Core\Repository\LocationService $locationService - */ - public function __construct(URLAliasService $urlAliasService, LocationService $locationService) - { - $this->urlAliasService = $urlAliasService; - $this->locationService = $locationService; - } - - /** - * Returns the URL alias with the given ID. - * - * @param $urlAliasId - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\URLAlias - */ - public function loadURLAlias($urlAliasId) - { - return $this->urlAliasService->load($urlAliasId); - } - - /** - * Returns the list of global URL aliases. - * - * @return \Ibexa\Rest\Server\Values\URLAliasRefList - */ - public function listGlobalURLAliases() - { - return new Values\URLAliasRefList( - $this->urlAliasService->listGlobalAliases(), - $this->router->generate('ibexa.rest.list_global_url_aliases') - ); - } - - /** - * Returns the list of URL aliases for a location. - * - * @param $locationPath - * - * @return \Ibexa\Rest\Server\Values\URLAliasRefList - */ - public function listLocationURLAliases($locationPath, Request $request) - { - $locationPathParts = explode('/', $locationPath); - - $location = $this->locationService->loadLocation( - array_pop($locationPathParts) - ); - - $custom = !($request->query->has('custom') && $request->query->get('custom') === 'false'); - - return new Values\CachedValue( - new Values\URLAliasRefList( - $this->urlAliasService->listLocationAliases($location, $custom), - $request->getPathInfo() - ), - ['locationId' => $location->id] - ); - } - - /** - * Creates a new URL alias. - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedURLAlias - */ - public function createURLAlias(Request $request) - { - $urlAliasCreate = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - if ($urlAliasCreate['_type'] === 'LOCATION') { - $locationPathParts = explode( - '/', - $this->requestParser->parseHref($urlAliasCreate['location']['_href'], 'locationPath') - ); - - $location = $this->locationService->loadLocation( - array_pop($locationPathParts) - ); - - try { - $createdURLAlias = $this->urlAliasService->createUrlAlias( - $location, - $urlAliasCreate['path'], - $urlAliasCreate['languageCode'], - $urlAliasCreate['forward'], - $urlAliasCreate['alwaysAvailable'] - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } else { - try { - $createdURLAlias = $this->urlAliasService->createGlobalUrlAlias( - $urlAliasCreate['resource'], - $urlAliasCreate['path'], - $urlAliasCreate['languageCode'], - $urlAliasCreate['forward'], - $urlAliasCreate['alwaysAvailable'] - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - } - - return new Values\CreatedURLAlias( - [ - 'urlAlias' => $createdURLAlias, - ] - ); - } - - /** - * The given URL alias is deleted. - * - * @param $urlAliasId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteURLAlias($urlAliasId) - { - $this->urlAliasService->removeAliases( - [ - $this->urlAliasService->load($urlAliasId), - ] - ); - - return new Values\NoContent(); - } -} diff --git a/src/lib/Server/Controller/URLWildcard.php b/src/lib/Server/Controller/URLWildcard.php deleted file mode 100644 index 3fc7be6c..00000000 --- a/src/lib/Server/Controller/URLWildcard.php +++ /dev/null @@ -1,322 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns a list of URL wildcards.', - 'content' => [ - 'application/vnd.ibexa.api.UrlWildcardList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcardList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/GET/UrlWildcardList.xml.example', - ], - 'application/vnd.ibexa.api.UrlWildcardList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcardListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/GET/UrlWildcardList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user has no permission to read URL wildcards.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/content/urlwildcards', - name: 'Create URL wildcard', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new URL wildcard.', - tags: [ - 'Url Wildcard', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new URL wildcard is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The URL Wildcard input schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.UrlWildcardCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcardCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/POST/UrlWildcardCreate.xml.example', - ], - 'application/vnd.ibexa.api.UrlWildcardCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcardCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/POST/UrlWildcardCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'URL wildcard created.', - 'content' => [ - 'application/vnd.ibexa.api.UrlWildcard+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcard', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/wildcard_id/GET/UrlWildcard.xml.example', - ], - 'application/vnd.ibexa.api.UrlWildcard+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcardWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/wildcard_id/GET/UrlWildcard.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - The input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to create a URL wildcard.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - A URL wildcard with the same identifier already exists.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/content/urlwildcards/{wildcardId}', - name: 'Get URL wildcard', - openapi: new Model\Operation( - summary: 'Returns the URL wildcard with the given ID.', - tags: [ - 'Url Wildcard', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the URL wildcard is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'wildcardId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - returns the URL wildcard.', - 'content' => [ - 'application/vnd.ibexa.api.UrlWildcard+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcard', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/wildcard_id/GET/UrlWildcard.xml.example', - ], - 'application/vnd.ibexa.api.UrlWildcard+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UrlWildcardWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/content/urlwildcards/wildcard_id/GET/UrlWildcard.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to read URL wildcards.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The URL wildcard does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/content/urlwildcards/{wildcardId}', - name: 'Delete URL wildcard', - openapi: new Model\Operation( - summary: 'Deletes the given URL wildcard.', - tags: [ - 'Url Wildcard', - ], - parameters: [ - new Model\Parameter( - name: 'wildcardId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content - URL wildcard deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - The user is not authorized to delete a URL wildcard.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - The URL wildcard does not exist.', - ], - ], - ), -)] -/** - * URLWildcard controller. - */ -class URLWildcard extends RestController -{ - /** - * URLWildcard service. - * - * @var \Ibexa\Contracts\Core\Repository\URLWildcardService - */ - protected $urlWildcardService; - - /** - * Construct controller. - * - * @param \Ibexa\Contracts\Core\Repository\URLWildcardService $urlWildcardService - */ - public function __construct(URLWildcardService $urlWildcardService) - { - $this->urlWildcardService = $urlWildcardService; - } - - /** - * Returns the URL wildcard with the given id. - * - * @param $urlWildcardId - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\URLWildcard - */ - public function loadURLWildcard($urlWildcardId) - { - return $this->urlWildcardService->load($urlWildcardId); - } - - /** - * Returns the list of URL wildcards. - * - * @return \Ibexa\Rest\Server\Values\URLWildcardList - */ - public function listURLWildcards() - { - return new Values\URLWildcardList( - $this->urlWildcardService->loadAll() - ); - } - - /** - * Creates a new URL wildcard. - * - * @throws \Ibexa\Rest\Server\Exceptions\ForbiddenException - * - * @return \Ibexa\Rest\Server\Values\CreatedURLWildcard - */ - public function createURLWildcard(Request $request) - { - $urlWildcardCreate = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - try { - $createdURLWildcard = $this->urlWildcardService->create( - $urlWildcardCreate['sourceUrl'], - $urlWildcardCreate['destinationUrl'], - $urlWildcardCreate['forward'] - ); - } catch (InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - return new Values\CreatedURLWildcard( - [ - 'urlWildcard' => $createdURLWildcard, - ] - ); - } - - /** - * The given URL wildcard is deleted. - * - * @param $urlWildcardId - * - * @return \Ibexa\Rest\Server\Values\NoContent - */ - public function deleteURLWildcard($urlWildcardId) - { - $this->urlWildcardService->remove( - $this->urlWildcardService->load($urlWildcardId) - ); - - return new Values\NoContent(); - } -} diff --git a/src/lib/Server/Controller/User.php b/src/lib/Server/Controller/User.php deleted file mode 100644 index ccb5532d..00000000 --- a/src/lib/Server/Controller/User.php +++ /dev/null @@ -1,2416 +0,0 @@ - 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Loads Users either for a given remote ID or Role.', - 'content' => [ - 'application/vnd.ibexa.api.UserList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/GET/User.xml.example', - ], - 'application/vnd.ibexa.api.UserList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/GET/User.json.example', - ], - 'application/vnd.ibexa.api.UserRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/GET/UserRefList.xml.example', - ], - 'application/vnd.ibexa.api.UserRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserRefListWrapper', - ], - ], - ], - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'If there are no visibile Users matching the filter.', - ], - ], - ), -)] -#[Head( - uriTemplate: '/user/users', - name: 'Verify Users', - openapi: new Model\Operation( - summary: 'Verifies if there are Users matching given filter.', - tags: [ - 'User', - ], - parameters: [ - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - verifies if there are Users matching the given filter.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - there are no visibile Users matching the filter.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/users/current', - name: 'Load current User', - openapi: new Model\Operation( - summary: 'Redirects to current User, if available.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the User is returned in XML or JSON format (after redirection).', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_TEMPORARY_REDIRECT => [ - 'description' => 'OK.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'User is not currently logged in.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/users/{userId}', - name: 'Load User', - openapi: new Model\Operation( - summary: 'Loads User with the given ID.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the User is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - the User with the given ID.', - 'content' => [ - 'application/vnd.ibexa.api.User+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/GET/User.xml.example', - ], - 'application/vnd.ibexa.api.User+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/GET/User.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Users.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/user/users/{userId}', - name: 'Update User', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates a User.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated User is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The UserUpdate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'Performs a PATCH only if the specified ETag is the current one.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.UserUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/PATCH/UserUpdate.xml.example', - ], - 'application/vnd.ibexa.api.UserUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserUpdateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/PATCH/UserUpdate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - User updated.', - 'content' => [ - 'application/vnd.ibexa.api.User+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/User', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/PATCH/User.xml.example', - ], - 'application/vnd.ibexa.api.User+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/PATCH/User.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update the User.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User does not exist.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - the current ETag does not match with the provided one in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/users/{userId}', - name: 'Delete User', - openapi: new Model\Operation( - summary: 'Deletes the given User.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No Content.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this User.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the user is the same as the authenticated User.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/users/{userId}/groups', - name: 'Load Groups of User', - openapi: new Model\Operation( - summary: 'Returns a list of User Groups the User belongs to. The returned list includes the resources for unassigning a User Group if the User is in multiple groups.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the link list of User Groups is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.UserGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/POST/UserGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/group_id/UserGroupRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read User Groups.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the user does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/users/{userId}/groups', - name: 'Assign User Group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapiContext: ['requestBody' => false], - openapi: new Model\Operation( - summary: 'Assigns the User to a User Group.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the link list of User Groups is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.UserGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/POST/UserGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/group_id/UserGroupRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to assign User Groups.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the new User Group does not exist or the User is already in this group.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User does not exist.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/users/{userId}/groups/{groupId}', - name: 'Unassign User Group', - openapi: new Model\Operation( - summary: 'Unassigns the User from a User Group.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the link list of User Groups is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'groupId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.UserGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/POST/UserGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/group_id/UserGroupRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to unassign User Groups.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the User is not in the given group.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/users/{userId}/roles', - name: 'Load Roles for User', - openapi: new Model\Operation( - summary: 'Returns a list of all Roles assigned to the given User.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignmentList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/POST/RoleAssignmentList.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignmentList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/DELETE/RoleAssignmentList.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/users/{userId}/roles', - name: 'Assign Role to User', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Assigns a Role to a user.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The RoleAssignInput schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.RoleAssignInput+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignInput', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/POST/RoleAssignInput.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignInput+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignInputWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/POST/RoleAssignInput.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignmentList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/POST/RoleAssignmentList.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignmentList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/DELETE/RoleAssignmentList.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - validation of limitation in RoleAssignInput fails.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to assign this Role.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/users/{userId}/roles/{roleId}', - name: 'Load User Role Assignment', - openapi: new Model\Operation( - summary: 'Returns a Role assignment to the given User.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'roleId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Role assignment to the given User Group.', - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignment+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignment', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/GET/RoleAssignment.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignment+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/GET/RoleAssignment.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/users/{userId}/roles/{roleId}', - name: 'Unassign Role from User', - openapi: new Model\Operation( - summary: 'The given Role is removed from the user.', - tags: [ - 'User', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the updated Role assignment list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'roleId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.RoleAssignmentList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/POST/RoleAssignmentList.xml.example', - ], - 'application/vnd.ibexa.api.RoleAssignmentList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/RoleAssignmentListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/roles/role_id/DELETE/RoleAssignmentList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this content type.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/users/{userId}/drafts', - name: 'Load user drafts', - openapi: new Model\Operation( - summary: 'Loads user\'s drafts', - tags: [ - '', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the version list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'userId', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - List the draft versions', - 'content' => [ - 'application/vnd.ibexa.api.VersionList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionList', - ], - ], - 'application/vnd.ibexa.api.VersionList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/VersionListWrapper', - ], - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the current user is not authorized to list the drafts of the given user.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/groups', - name: 'Load User Groups', - openapi: new Model\Operation( - summary: 'Loads User Groups for either an an ID or a remote ID or a Role.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'UserGroupList - If set, the User Group List is returned in XML or JSON format. UserGroupRefList - If set, the link list of User Group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'content' => [ - 'application/vnd.ibexa.api.UserGroupList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/GET/UserGroupList.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/GET/UserGroupList.json.example', - ], - 'application/vnd.ibexa.api.UserGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/POST/UserGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/group_id/UserGroupRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read User Groups.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/groups/root', - name: 'Get root User Group', - openapi: new Model\Operation( - summary: 'Redirects to the root User Group.', - tags: [ - 'User Group', - ], - parameters: [ - ], - responses: [ - Response::HTTP_MOVED_PERMANENTLY => [ - 'description' => 'Moved permanently.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/groups/subgroups', - name: 'Create a top level User Group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a top level User Group under the root. To create a child group under a parent group use \'/user/groups/{path}/subgroups\'.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new User Group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The UserGroupCreate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.UserGroupCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroupCreate.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroupCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'description' => 'Created - the User Group has been created', - 'content' => [ - 'application/vnd.ibexa.api.UserGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.xml.example', - ], - 'application/vnd.ibexa.api.UserGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create this User Group.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/groups/{path}', - name: 'Load User Group', - openapi: new Model\Operation( - summary: 'Loads User Groups for the given {path}.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new User Group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-None-Match', - in: 'header', - required: true, - description: 'ETag', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - loads User Groups.', - 'content' => [ - 'application/vnd.ibexa.api.UserGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.xml.example', - ], - 'application/vnd.ibexa.api.UserGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read User Groups.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User Group does not exist.', - ], - ], - ), -)] -#[Patch( - uriTemplate: '/user/groups/{path}', - name: 'Update User Group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Updates a User Group. PATCH or POST with header X-HTTP-Method-Override PATCH.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new User Group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The UserGroupUpdate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'If-Match', - in: 'header', - required: true, - description: 'Performs the PATCH only if the specified ETag is the current one. Otherwise a 412 is returned.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.UserGroupUpdate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupUpdate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/PATCH/UserGroupUpdate.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupUpdate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupUpdateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/PATCH/UserGroupUpdate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - updated User Group.', - 'content' => [ - 'application/vnd.ibexa.api.UserGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.xml.example', - ], - 'application/vnd.ibexa.api.UserGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to update the User Group.', - ], - Response::HTTP_PRECONDITION_FAILED => [ - 'description' => 'Error - if the current ETag does not match with the one provided in the If-Match header.', - ], - ], - ), -)] -#[Delete( - uriTemplate: '/user/groups/{path}', - name: 'Delete User Group', - openapi: new Model\Operation( - summary: 'The given User Group is deleted.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_NO_CONTENT => [ - 'description' => 'No content - the given User Group is deleted.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to delete this content type.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - the User Group is not empty.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/groups/{path}/users', - name: 'Load Users of Group', - openapi: new Model\Operation( - summary: 'Loads the Users of the Group with the given ID.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'UserList - If set, the User list returned in XML or JSON format. UserRefList - If set, the link list of Users returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - the Users of the Group with the given ID.', - 'content' => [ - 'application/vnd.ibexa.api.UserList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserList', - ], - ], - 'application/vnd.ibexa.api.UserList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserList', - ], - ], - 'application/vnd.ibexa.api.UserRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/GET/UserRefList.xml.example', - ], - 'application/vnd.ibexa.api.UserRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/id/users/GET/UserRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read User Groups.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User Group does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/groups/{path}/users', - name: 'Create User', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new User in the given Group.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new User is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The UserCreate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.UserCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/users/POST/UserCreate.xml.example', - ], - 'application/vnd.ibexa.api.UserCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/users/POST/UserCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.User+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/User', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/PATCH/User.xml.example', - ], - 'application/vnd.ibexa.api.User+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/PATCH/User.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create this User.', - ], - Response::HTTP_FORBIDDEN => [ - 'description' => 'Error - a User with the same login already exists.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the Group with the given ID does not exist.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/groups/{path}/subgroups', - name: 'Load subgroups', - openapi: new Model\Operation( - summary: 'Returns a list of the subgroups.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'UserGroupList - If set, the User Group list is returned in XML or JSON format. UserGroupRefList - If set, the link list of User Groups is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - list of the subgroups.', - 'content' => [ - 'application/vnd.ibexa.api.UserGroupList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/GET/UserGroupList.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/GET/UserGroupList.json.example', - ], - 'application/vnd.ibexa.api.UserGroupRefList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/POST/UserGroupRefList.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupRefList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupRefListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/groups/group_id/UserGroupRefList.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read User Groups.', - ], - Response::HTTP_NOT_FOUND => [ - 'description' => 'Error - the User Group does not exist.', - ], - ], - ), -)] -#[Post( - uriTemplate: '/user/groups/{path}/subgroups', - name: 'Create User Group', - extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false], - openapi: new Model\Operation( - summary: 'Creates a new User Group under the given parent. To create a top level group use \'/user/groups/subgroups\'.', - tags: [ - 'User Group', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the new User Group is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'Content-Type', - in: 'header', - required: true, - description: 'The UserGroupCreate schema encoded in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - new Model\Parameter( - name: 'path', - in: 'path', - required: true, - schema: [ - 'type' => 'string', - ], - ), - ], - requestBody: new Model\RequestBody( - content: new \ArrayObject([ - 'application/vnd.ibexa.api.UserGroupCreate+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupCreate', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroupCreate.xml.example', - ], - 'application/vnd.ibexa.api.UserGroupCreate+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupCreateWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroupCreate.json.example', - ], - ]), - ), - responses: [ - Response::HTTP_CREATED => [ - 'content' => [ - 'application/vnd.ibexa.api.UserGroup+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroup', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.xml.example', - ], - 'application/vnd.ibexa.api.UserGroup+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserGroupWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/groups/path/subgroups/POST/UserGroup.json.example', - ], - ], - ], - Response::HTTP_BAD_REQUEST => [ - 'description' => 'Error - the input does not match the input schema definition.', - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user is not authorized to create this User Group.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/policies', - name: 'List Policies for User', - openapi: new Model\Operation( - summary: 'Search all Policies which are applied to a given User.', - tags: [ - '', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the Policy list is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - Policies which are applied to a given User.', - 'content' => [ - 'application/vnd.ibexa.api.PolicyList+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyList', - ], - 'example' => self::POLICY_LIST_XML_EXAMPLE, - ], - 'application/vnd.ibexa.api.PolicyList+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/PolicyListWrapper', - ], - 'example' => self::POLICY_LIST_JSON_EXAMPLE, - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Roles.', - ], - ], - ), -)] -#[Get( - uriTemplate: '/user/current', - name: 'Load current User', - openapi: new Model\Operation( - summary: 'Loads the current user.', - tags: [ - 'User Current', - ], - parameters: [ - new Model\Parameter( - name: 'Accept', - in: 'header', - required: true, - description: 'If set, the User is returned in XML or JSON format.', - schema: [ - 'type' => 'string', - ], - ), - ], - responses: [ - Response::HTTP_OK => [ - 'description' => 'OK - the User with the given ID.', - 'content' => [ - 'application/vnd.ibexa.api.User+xml' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserList', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/GET/User.xml.example', - ], - 'application/vnd.ibexa.api.User+json' => [ - 'schema' => [ - '$ref' => '#/components/schemas/UserListWrapper', - ], - 'x-ibexa-example-file' => '@IbexaRestBundle/Resources/api_platform/examples/user/users/user_id/GET/User.json.example', - ], - ], - ], - Response::HTTP_UNAUTHORIZED => [ - 'description' => 'Error - the user has no permission to read Users. For example, Anonymous user can\'t load oneself.', - ], - ], - ), -)] -/** - * User controller. - */ -final class User extends RestController -{ - protected UserService $userService; - - protected RoleService $roleService; - - protected ContentService $contentService; - - protected ContentTypeService $contentTypeService; - - protected LocationService $locationService; - - protected SectionService $sectionService; - - /** - * Repository. - * - * @var \Ibexa\Contracts\Core\Repository\Repository - */ - protected $repository; - - private PermissionResolver $permissionResolver; - - public function __construct( - UserService $userService, - RoleService $roleService, - ContentService $contentService, - ContentTypeService $contentTypeService, - LocationService $locationService, - SectionService $sectionService, - Repository $repository, - PermissionResolver $permissionResolver - ) { - $this->userService = $userService; - $this->roleService = $roleService; - $this->contentService = $contentService; - $this->contentTypeService = $contentTypeService; - $this->locationService = $locationService; - $this->sectionService = $sectionService; - $this->repository = $repository; - $this->permissionResolver = $permissionResolver; - } - - /** - * Redirects to the root user group. - */ - public function loadRootUserGroup(): Values\PermanentRedirect - { - //@todo Replace hardcoded value with one loaded from settings - return new Values\PermanentRedirect( - $this->router->generate('ibexa.rest.load_user_group', ['groupPath' => '/1/5']) - ); - } - - /** - * Loads a user group for the given path. - */ - public function loadUserGroup(string $groupPath): RestValue - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - if (trim($userGroupLocation->pathString, '/') !== $groupPath) { - throw new NotFoundException( - "Could not find a Location with path string $groupPath" - ); - } - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId, - Language::ALL - ); - $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo(); - $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId); - - return new Values\CachedValue( - new Values\RestUserGroup( - $userGroup, - $contentType, - $userGroupContentInfo, - $userGroupLocation, - $this->contentService->loadRelations($userGroup->getVersionInfo()) - ), - ['locationId' => $userGroupLocation->id] - ); - } - - public function loadUser(int $userId): RestValue - { - $user = $this->userService->loadUser($userId, Language::ALL); - - $userContentInfo = $user->getVersionInfo()->getContentInfo(); - $contentType = $this->contentTypeService->loadContentType($userContentInfo->contentTypeId); - - try { - $userMainLocation = $this->locationService->loadLocation($userContentInfo->mainLocationId); - $relations = $this->contentService->loadRelations($user->getVersionInfo()); - } catch (UnauthorizedException $e) { - // TODO: Hack for special case to allow current logged in user to load him/here self (but not relations) - if ($user->id == $this->permissionResolver->getCurrentUserReference()->getUserId()) { - $userMainLocation = $this->repository->sudo( - function () use ($userContentInfo) { - return $this->locationService->loadLocation($userContentInfo->mainLocationId); - } - ); - // user may not have permissions to read related content, for security reasons do not use sudo(). - $relations = []; - } else { - throw $e; - } - } - - return new Values\CachedValue( - new Values\RestUser( - $user, - $contentType, - $userContentInfo, - $userMainLocation, - $relations - ), - ['locationId' => $userContentInfo->mainLocationId] - ); - } - - /** - * @see \Symfony\Component\Security\Http\Controller\UserValueResolver - */ - public function redirectToCurrentUser(?UserInterface $user): Values\TemporaryRedirect - { - if ($user === null) { - throw new UnauthorizedHttpException('', 'Not logged in.'); - } - - $userReference = $this->permissionResolver->getCurrentUserReference(); - - return new Values\TemporaryRedirect( - $this->router->generate('ibexa.rest.load_user', ['userId' => $userReference->getUserId()]) - ); - } - - /** - * Create a new user group under the given parent - * To create a top level group use /user/groups/1/5/subgroups. - * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function createUserGroup(string $groupPath, Request $request): Values\CreatedUserGroup - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - $createdUserGroup = $this->userService->createUserGroup( - $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ), - $this->userService->loadUserGroup( - $userGroupLocation->contentId - ) - ); - - $createdContentInfo = $createdUserGroup->getVersionInfo()->getContentInfo(); - $createdLocation = $this->locationService->loadLocation($createdContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($createdContentInfo->contentTypeId); - - return new Values\CreatedUserGroup( - [ - 'userGroup' => new Values\RestUserGroup( - $createdUserGroup, - $contentType, - $createdContentInfo, - $createdLocation, - $this->contentService->loadRelations($createdUserGroup->getVersionInfo()) - ), - ] - ); - } - - /** - * Create a new user group in the given group. - * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function createUser(string $groupPath, Request $request): Values\CreatedUser - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - $userGroup = $this->userService->loadUserGroup($userGroupLocation->contentId); - - $userCreateStruct = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent() - ) - ); - - try { - $createdUser = $this->userService->createUser($userCreateStruct, [$userGroup]); - } catch (ApiExceptions\InvalidArgumentException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage()); - } - - $createdContentInfo = $createdUser->getVersionInfo()->getContentInfo(); - $createdLocation = $this->locationService->loadLocation($createdContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($createdContentInfo->contentTypeId); - - return new Values\CreatedUser( - [ - 'user' => new Values\RestUser( - $createdUser, - $contentType, - $createdContentInfo, - $createdLocation, - $this->contentService->loadRelations($createdUser->getVersionInfo()) - ), - ] - ); - } - - public function updateUserGroup(string $groupPath, Request $request): Values\RestUserGroup - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId - ); - - $updateStruct = $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - // @todo Needs refactoring! Temporary solution so parser has access to URL - 'Url' => $request->getPathInfo(), - ], - $request->getContent() - ) - ); - - if ($updateStruct->sectionId !== null) { - $section = $this->sectionService->loadSection($updateStruct->sectionId); - $this->sectionService->assignSection( - $userGroup->getVersionInfo()->getContentInfo(), - $section - ); - } - - $updatedGroup = $this->userService->updateUserGroup($userGroup, $updateStruct->userGroupUpdateStruct); - $contentType = $this->contentTypeService->loadContentType( - $updatedGroup->getVersionInfo()->getContentInfo()->contentTypeId - ); - - return new Values\RestUserGroup( - $updatedGroup, - $contentType, - $updatedGroup->getVersionInfo()->getContentInfo(), - $userGroupLocation, - $this->contentService->loadRelations($updatedGroup->getVersionInfo()) - ); - } - - public function updateUser(int $userId, Request $request): Values\RestUser - { - $user = $this->userService->loadUser($userId); - - $updateStruct = $this->inputDispatcher->parse( - new Message( - [ - 'Content-Type' => $request->headers->get('Content-Type'), - // @todo Needs refactoring! Temporary solution so parser has access to URL - 'Url' => $request->getPathInfo(), - ], - $request->getContent() - ) - ); - - if ($updateStruct->sectionId !== null) { - $section = $this->sectionService->loadSection($updateStruct->sectionId); - $this->sectionService->assignSection( - $user->getVersionInfo()->getContentInfo(), - $section - ); - } - - $updatedUser = $this->userService->updateUser($user, $updateStruct->userUpdateStruct); - $updatedContentInfo = $updatedUser->getVersionInfo()->getContentInfo(); - $mainLocation = $this->locationService->loadLocation($updatedContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($updatedContentInfo->contentTypeId); - - return new Values\RestUser( - $updatedUser, - $contentType, - $updatedContentInfo, - $mainLocation, - $this->contentService->loadRelations($updatedUser->getVersionInfo()) - ); - } - - /** - * Given user group is deleted. - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function deleteUserGroup(string $groupPath): Values\NoContent - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId - ); - - // Load one user to see if user group is empty or not - $users = $this->userService->loadUsersOfUserGroup($userGroup, 0, 1); - if (!empty($users)) { - throw new Exceptions\ForbiddenException('Cannot delete non-empty User Groups'); - } - - $this->userService->deleteUserGroup($userGroup); - - return new Values\NoContent(); - } - - /** - * Given user is deleted. - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function deleteUser(int $userId): Values\NoContent - { - $user = $this->userService->loadUser($userId); - - if ($user->id == $this->permissionResolver->getCurrentUserReference()->getUserId()) { - throw new Exceptions\ForbiddenException('Cannot delete the currently authenticated User'); - } - - $this->userService->deleteUser($user); - - return new Values\NoContent(); - } - - /** - * Loads users. - */ - public function loadUsers(Request $request): RestValue - { - $restUsers = []; - - try { - if ($request->query->has('roleId')) { - $restUsers = $this->loadUsersAssignedToRole( - $this->requestParser->parseHref($request->query->get('roleId'), 'roleId') - ); - } elseif ($request->query->has('remoteId')) { - $restUsers = [ - $this->buildRestUserObject( - $this->userService->loadUser( - $this->contentService->loadContentInfoByRemoteId($request->query->get('remoteId'))->id, - Language::ALL - ) - ), - ]; - } elseif ($request->query->has('login')) { - $restUsers = [ - $this->buildRestUserObject( - $this->userService->loadUserByLogin($request->query->get('login'), Language::ALL) - ), - ]; - } elseif ($request->query->has('email')) { - foreach ($this->userService->loadUsersByEmail($request->query->get('email'), Language::ALL) as $user) { - $restUsers[] = $this->buildRestUserObject($user); - } - } - } catch (ApiExceptions\UnauthorizedException $e) { - $restUsers = []; - } - - if (empty($restUsers)) { - throw new NotFoundException('Could not find Users with the given filter'); - } - - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.userlist') { - return new Values\UserList($restUsers, $request->getPathInfo()); - } - - return new Values\UserRefList($restUsers, $request->getPathInfo()); - } - - public function verifyUsers(Request $request): Values\OK - { - // We let the NotFoundException loadUsers throws if there are no results pass. - $this->loadUsers($request)->users; - - return new Values\OK(); - } - - /** - * Loads a list of users assigned to role. - * - * @param mixed $roleId - * - * @return \Ibexa\Rest\Server\Values\RestUser[] - */ - public function loadUsersAssignedToRole($roleId): array - { - $role = $this->roleService->loadRole($roleId); - $roleAssignments = $this->roleService->getRoleAssignments($role); - - $restUsers = []; - - foreach ($roleAssignments as $roleAssignment) { - if ($roleAssignment instanceof UserRoleAssignment) { - $restUsers[] = $this->buildRestUserObject($roleAssignment->getUser()); - } - } - - return $restUsers; - } - - private function buildRestUserObject(RepositoryUser $user): Values\RestUser - { - return new Values\RestUser( - $user, - $this->contentTypeService->loadContentType($user->contentInfo->contentTypeId), - $user->contentInfo, - $this->locationService->loadLocation($user->contentInfo->mainLocationId), - $this->contentService->loadRelations($user->getVersionInfo()) - ); - } - - /** - * Loads user groups. - */ - public function loadUserGroups(Request $request): RestValue - { - $restUserGroups = []; - if ($request->query->has('id')) { - $userGroup = $this->userService->loadUserGroup($request->query->get('id'), Language::ALL); - $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo(); - $userGroupMainLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId); - - $restUserGroups = [ - new Values\RestUserGroup( - $userGroup, - $contentType, - $userGroupContentInfo, - $userGroupMainLocation, - $this->contentService->loadRelations($userGroup->getVersionInfo()) - ), - ]; - } elseif ($request->query->has('roleId')) { - $restUserGroups = $this->loadUserGroupsAssignedToRole($request->query->get('roleId')); - } elseif ($request->query->has('remoteId')) { - $restUserGroups = [ - $this->loadUserGroupByRemoteId($request), - ]; - } - - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.usergrouplist') { - return new Values\UserGroupList($restUserGroups, $request->getPathInfo()); - } - - return new Values\UserGroupRefList($restUserGroups, $request->getPathInfo()); - } - - /** - * Loads a user group by its remote ID. - */ - public function loadUserGroupByRemoteId(Request $request): Values\RestUserGroup - { - $contentInfo = $this->contentService->loadContentInfoByRemoteId($request->query->get('remoteId')); - $userGroup = $this->userService->loadUserGroup($contentInfo->id, Language::ALL); - $userGroupLocation = $this->locationService->loadLocation($contentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($contentInfo->contentTypeId); - - return new Values\RestUserGroup( - $userGroup, - $contentType, - $contentInfo, - $userGroupLocation, - $this->contentService->loadRelations($userGroup->getVersionInfo()) - ); - } - - /** - * Loads a list of user groups assigned to role. - * - * @param mixed $roleId - * - * @return \Ibexa\Rest\Server\Values\RestUserGroup[] - */ - public function loadUserGroupsAssignedToRole($roleId): array - { - $role = $this->roleService->loadRole($roleId); - $roleAssignments = $this->roleService->getRoleAssignments($role); - - $restUserGroups = []; - - foreach ($roleAssignments as $roleAssignment) { - if ($roleAssignment instanceof UserGroupRoleAssignment) { - $userGroup = $roleAssignment->getUserGroup(); - $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo(); - $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId); - - $restUserGroups[] = new Values\RestUserGroup( - $userGroup, - $contentType, - $userGroupContentInfo, - $userGroupLocation, - $this->contentService->loadRelations($userGroup->getVersionInfo()) - ); - } - } - - return $restUserGroups; - } - - /** - * Loads drafts assigned to user. - */ - public function loadUserDrafts(int $userId, Request $request): Values\VersionList - { - $contentDrafts = $this->contentService->loadContentDrafts( - $this->userService->loadUser($userId) - ); - - return new Values\VersionList($contentDrafts, $request->getPathInfo()); - } - - /** - * Moves the user group to another parent. - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function moveUserGroup(string $groupPath, Request $request): Values\ResourceCreated - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId - ); - - $locationPath = $this->requestParser->parseHref( - $request->headers->get('Destination'), - 'groupPath' - ); - - try { - $destinationGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($locationPath) - ); - } catch (ApiExceptions\NotFoundException $e) { - throw new Exceptions\ForbiddenException($e->getMessage()); - } - - try { - $destinationGroup = $this->userService->loadUserGroup($destinationGroupLocation->contentId); - } catch (ApiExceptions\NotFoundException $e) { - throw new Exceptions\ForbiddenException($e->getMessage()); - } - - $this->userService->moveUserGroup($userGroup, $destinationGroup); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_user_group', - [ - 'groupPath' => trim($destinationGroupLocation->pathString, '/') . '/' . $userGroupLocation->id, - ] - ) - ); - } - - /** - * @throws \Ibexa\Contracts\Rest\Exceptions\ForbiddenException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function moveGroup(string $groupPath, Request $request): Values\ResourceCreated - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId, - ); - - try { - /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Location $destinationLocation */ - $destinationLocation = $this->inputDispatcher->parse( - new Message( - ['Content-Type' => $request->headers->get('Content-Type')], - $request->getContent(), - ), - ); - } catch (ApiExceptions\NotFoundException $e) { - throw new ForbiddenException(/** @Ignore */ $e->getMessage(), 1, $e); - } - - $destinationGroup = $this->userService->loadUserGroup( - $destinationLocation->getContent()->getId(), - ); - - $this->userService->moveUserGroup($userGroup, $destinationGroup); - - return new Values\ResourceCreated( - $this->router->generate( - 'ibexa.rest.load_user_group', - [ - 'groupPath' => trim($destinationLocation->pathString, '/') - . '/' - . $userGroupLocation->getId(), - ], - ) - ); - } - - /** - * Returns a list of the sub groups. - */ - public function loadSubUserGroups(string $groupPath, Request $request): RestValue - { - $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0; - $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : 25; - - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId - ); - - $subGroups = $this->userService->loadSubUserGroups( - $userGroup, - $offset >= 0 ? $offset : 0, - $limit >= 0 ? $limit : 25, - Language::ALL - ); - - $restUserGroups = []; - foreach ($subGroups as $subGroup) { - $subGroupContentInfo = $subGroup->getVersionInfo()->getContentInfo(); - $subGroupLocation = $this->locationService->loadLocation($subGroupContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($subGroupContentInfo->contentTypeId); - - $restUserGroups[] = new Values\RestUserGroup( - $subGroup, - $contentType, - $subGroupContentInfo, - $subGroupLocation, - $this->contentService->loadRelations($subGroup->getVersionInfo()) - ); - } - - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.usergrouplist') { - return new Values\CachedValue( - new Values\UserGroupList($restUserGroups, $request->getPathInfo()), - ['locationId' => $userGroupLocation->id] - ); - } - - return new Values\CachedValue( - new Values\UserGroupRefList($restUserGroups, $request->getPathInfo()), - ['locationId' => $userGroupLocation->id] - ); - } - - /** - * Returns a list of user groups the user belongs to. - * The returned list includes the resources for unassigning - * a user group if the user is in multiple groups. - */ - public function loadUserGroupsOfUser(int $userId, Request $request): RestValue - { - $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0; - $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : 25; - - $user = $this->userService->loadUser($userId); - $userGroups = $this->userService->loadUserGroupsOfUser( - $user, - $offset >= 0 ? $offset : 0, - $limit >= 0 ? $limit : 25, - Language::ALL - ); - - $restUserGroups = []; - foreach ($userGroups as $userGroup) { - $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo(); - $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId); - - $restUserGroups[] = new Values\RestUserGroup( - $userGroup, - $contentType, - $userGroupContentInfo, - $userGroupLocation, - $this->contentService->loadRelations($userGroup->getVersionInfo()) - ); - } - - return new Values\CachedValue( - new Values\UserGroupRefList($restUserGroups, $request->getPathInfo(), $userId), - ['locationId' => $user->contentInfo->mainLocationId] - ); - } - - /** - * Loads the users of the group with the given path. - */ - public function loadUsersFromGroup(string $groupPath, Request $request): RestValue - { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($groupPath) - ); - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId - ); - - $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0; - $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : 25; - - $users = $this->userService->loadUsersOfUserGroup( - $userGroup, - $offset >= 0 ? $offset : 0, - $limit >= 0 ? $limit : 25, - Language::ALL - ); - - $restUsers = []; - foreach ($users as $user) { - $userContentInfo = $user->getVersionInfo()->getContentInfo(); - $userLocation = $this->locationService->loadLocation($userContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($userContentInfo->contentTypeId); - - $restUsers[] = new Values\RestUser( - $user, - $contentType, - $userContentInfo, - $userLocation, - $this->contentService->loadRelations($user->getVersionInfo()) - ); - } - - if ($this->getMediaType($request) === 'application/vnd.ibexa.api.userlist') { - return new Values\CachedValue( - new Values\UserList($restUsers, $request->getPathInfo()), - ['locationId' => $userGroupLocation->id] - ); - } - - return new Values\CachedValue( - new Values\UserRefList($restUsers, $request->getPathInfo()), - ['locationId' => $userGroupLocation->id] - ); - } - - /** - * Unassigns the user from a user group. - * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function unassignUserFromUserGroup(int $userId, string $groupPath): Values\UserGroupRefList - { - $user = $this->userService->loadUser($userId); - $userGroupLocation = $this->locationService->loadLocation((int)trim($groupPath, '/')); - - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId - ); - - try { - $this->userService->unAssignUserFromUserGroup($user, $userGroup); - } catch (ApiExceptions\InvalidArgumentException $e) { - // User is not in the group - throw new Exceptions\ForbiddenException($e->getMessage()); - } - - $userGroups = $this->userService->loadUserGroupsOfUser($user); - $restUserGroups = []; - foreach ($userGroups as $userGroup) { - $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo(); - $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId); - - $restUserGroups[] = new Values\RestUserGroup( - $userGroup, - $contentType, - $userGroupContentInfo, - $userGroupLocation, - $this->contentService->loadRelations($userGroup->getVersionInfo()) - ); - } - - return new Values\UserGroupRefList( - $restUserGroups, - $this->router->generate( - 'ibexa.rest.load_user_groups_of_user', - ['userId' => $userId] - ), - $userId - ); - } - - /** - * Assigns the user to a user group. - * - * @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException - * @throws \Ibexa\Core\Base\Exceptions\UnauthorizedException - */ - public function assignUserToUserGroup(int $userId, Request $request): Values\UserGroupRefList - { - $user = $this->userService->loadUser($userId); - - try { - $userGroupLocation = $this->locationService->loadLocation( - $this->extractLocationIdFromPath($request->query->get('group')) - ); - } catch (ApiExceptions\NotFoundException $e) { - throw new Exceptions\ForbiddenException($e->getMessage()); - } - - try { - $userGroup = $this->userService->loadUserGroup( - $userGroupLocation->contentId - ); - } catch (ApiExceptions\NotFoundException $e) { - throw new Exceptions\ForbiddenException($e->getMessage()); - } - - try { - $this->userService->assignUserToUserGroup($user, $userGroup); - } catch (ApiExceptions\NotFoundException $e) { - throw new Exceptions\ForbiddenException($e->getMessage()); - } - - $userGroups = $this->userService->loadUserGroupsOfUser($user); - $restUserGroups = []; - foreach ($userGroups as $userGroup) { - $userGroupContentInfo = $userGroup->getVersionInfo()->getContentInfo(); - $userGroupLocation = $this->locationService->loadLocation($userGroupContentInfo->mainLocationId); - $contentType = $this->contentTypeService->loadContentType($userGroupContentInfo->contentTypeId); - - $restUserGroups[] = new Values\RestUserGroup( - $userGroup, - $contentType, - $userGroupContentInfo, - $userGroupLocation, - $this->contentService->loadRelations($userGroup->getVersionInfo()) - ); - } - - return new Values\UserGroupRefList( - $restUserGroups, - $this->router->generate( - 'ibexa.rest.load_user_groups_of_user', - ['userId' => $userId] - ), - $userId - ); - } - - /** - * Extracts and returns an item id from a path, e.g. /1/2/58 => 58. - */ - private function extractLocationIdFromPath(string $path): int - { - $pathParts = explode('/', $path); - - return (int)array_pop($pathParts); - } -}