Skip to content

Instantly share code, notes, and snippets.

@andrerom
Last active December 13, 2018 16:41
Show Gist options
  • Save andrerom/f2f328029ae7a9d78b363282b3ddf4a4 to your computer and use it in GitHub Desktop.
Save andrerom/f2f328029ae7a9d78b363282b3ddf4a4 to your computer and use it in GitHub Desktop.
eZ Platform: Starting point for adding multi load for locations for REST
diff --git a/doc/specifications/rest/REST-API-V2.rst b/doc/specifications/rest/REST-API-V2.rst
index 961d311f83..a561074788 100644
--- a/doc/specifications/rest/REST-API-V2.rst
+++ b/doc/specifications/rest/REST-API-V2.rst
@@ -573,6 +573,7 @@ XML Example
<rootMediaFolder media-type="application/vnd.ez.api.Location+xml" href="/api/ezp/v2/content/locations/1/43"/>
<locationByRemoteId media-type="" href="/api/ezp/v2/content/locations{?remoteId}"/>
<locationByPath media-type="" href="/api/ezp/v2/content/locations{?locationPath}"/>
+ <locationByIds media-type="application/vnd.ez.api.LocationList+xml" href="/api/ezp/v2/content/locations{?ids}"/>
<trash media-type="application/vnd.ez.api.Trash+xml" href="/api/ezp/v2/content/trash"/>
<sections media-type="application/vnd.ez.api.SectionList+xml" href="/api/ezp/v2/content/sections"/>
<views media-type="application/vnd.ez.api.RefList+xml" href="/api/ezp/v2/views"/>
@@ -644,6 +645,10 @@ JSON Example
"_href": "/api/ezp/v2/content/locations{?remoteId}",
"_media-type": ""
},
+ "locationByIds": {
+ "_href": "/api/ezp/v2/content/locations{?ids}",
+ "_media-type": "application/vnd.ez.api.LocationList+json"
+ },
"objectStateGroups": {
"_href": "/api/ezp/v2/content/objectstategroups",
"_media-type": "application/vnd.ez.api.ObjectStateGroupList+json"
@@ -2128,6 +2133,57 @@ Load locations by id/remoteId/urlAlias
:Error Codes:
:404: If the location with the given id (remoteId or urlAlias) does not exist
+Load locationList by ids
+````````````````````
+:Resource: /content/locations
+:Method: GET
+:Description: loads the location for a given id (x), remote id or url alias.
+:Parameters: :ids: the ids of the locations. Comma separated value of location id's.
+:Headers:
+ :Accept:
+ :application/vnd.ez.api.LocationList+xml: if set the new location list is returned in xml format (see Location_)
+ :application/vnd.ez.api.LocationList+json: if set the new location list is returned in json format (see Location_)
+ :If-None-Match: <etag>
+:Response:
+
+.. code:: http
+
+ HTTP/1.1 200 OK
+ ETag: "<etag>"
+ Content-Type: <depending on accept header>
+ Content-Length: <length>
+.. parsed-literal::
+ Location_ (locationListType)
+
+XML Example
+'''''''''''
+
+*Example where we load location 2, 5 & 44, where 44 is either not found or not available for current user.*
+
+**TODO TODO** !!!! We are not interested in the shallow LocationList here, so maybe we need additional
+content-type for full location data to avoid round-trips??
+
+
+.. code:: http
+
+ GET /content/locations/?2,5,44 HTTP/1.1
+ Accept: application/vnd.ez.api.LocationList+xml
+
+.. code:: http
+
+ HTTP/1.1 200 OK
+ ETag: "<etag>"
+ Content-Type: application/vnd.ez.api.LocationList+xml
+ Content-Length: xxx
+
+.. code:: xml
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <LocationList href="/content/objects/?2,5,44" media-type="application/vnd.ez.api.LocationList+xml">
+ <Location href="/content/locations/1/2" media-type="application/vnd.ez.api.Location+xml"/>
+ <Location href="/content/locations/1/5" media-type="application/vnd.ez.api.Location+xml"/>
+ </LocationList>
+
Load location
`````````````
:Resource: /content/locations/<path>
diff --git a/eZ/Bundle/EzPublishRestBundle/Resources/config/default_settings.yml b/eZ/Bundle/EzPublishRestBundle/Resources/config/default_settings.yml
index 65a5a92e18..6025a14056 100644
--- a/eZ/Bundle/EzPublishRestBundle/Resources/config/default_settings.yml
+++ b/eZ/Bundle/EzPublishRestBundle/Resources/config/default_settings.yml
@@ -57,6 +57,9 @@ parameters:
locationByPath:
mediaType: ''
href: 'templateRouter.generate("ezpublish_rest_redirectLocation", {locationPath: "{locationPath}"})'
+ locationsByIds:
+ mediaType: 'LocationList'
+ href: 'templateRouter.generate("ezpublish_rest_loadLocationlist", {ids: "{ids}"})'
trash:
mediaType: 'Trash'
href: 'router.generate("ezpublish_rest_loadTrashItems")'
diff --git a/eZ/Bundle/EzPublishRestBundle/Resources/config/routing.yml b/eZ/Bundle/EzPublishRestBundle/Resources/config/routing.yml
index ab2059f1e7..372bbeca07 100644
--- a/eZ/Bundle/EzPublishRestBundle/Resources/config/routing.yml
+++ b/eZ/Bundle/EzPublishRestBundle/Resources/config/routing.yml
@@ -368,7 +368,12 @@ ezpublish_rest_setObjectStatesForContent:
# Locations
-
+ezpublish_rest_loadLocationlist:
+ path: /content/locations
+ defaults:
+ _controller: ezpublish_rest.controller.location:loadLocationList
+ methods: [GET]
+ condition: "request.query.has('ids')"
ezpublish_rest_redirectLocation:
path: /content/locations
diff --git a/eZ/Publish/Core/REST/Common/RequestParser/EzPublish.php b/eZ/Publish/Core/REST/Common/RequestParser/EzPublish.php
index 6a2b8967aa..ef472646d0 100644
--- a/eZ/Publish/Core/REST/Common/RequestParser/EzPublish.php
+++ b/eZ/Publish/Core/REST/Common/RequestParser/EzPublish.php
@@ -22,6 +22,7 @@ class EzPublish extends Pattern
protected $map = array(
'root' => '/',
'locations' => '/content/locations',
+ 'locationsByIds' => '/content/locations?ids={locations}',
'locationByRemote' => '/content/locations?remoteId={location}',
'locationById' => '/content/locations?id={location}',
'locationChildren' => '/content/locations{&location}/children',
diff --git a/eZ/Publish/Core/REST/Common/RequestParser/Pattern.php b/eZ/Publish/Core/REST/Common/RequestParser/Pattern.php
index 7caa1c0877..6f1c2be867 100644
--- a/eZ/Publish/Core/REST/Common/RequestParser/Pattern.php
+++ b/eZ/Publish/Core/REST/Common/RequestParser/Pattern.php
@@ -169,7 +169,11 @@ class Pattern implements RequestParser
throw new Exceptions\InvalidArgumentException("No value provided for '{$variableName}'.");
}
- $url = str_replace($matchSet[0], $values[$variableName], $url);
+ // handle array params (As comma separated lists)
+ $value = is_array($values[$variableName]) ? implode(',', $values[$variableName]) : $values[$variableName];
+
+ // replace value in string
+ $url = str_replace($matchSet[0], $value, $url);
unset($values[$variableName]);
}
diff --git a/eZ/Publish/Core/REST/Server/Controller/Location.php b/eZ/Publish/Core/REST/Server/Controller/Location.php
index b5499d9611..b18ce69298 100644
--- a/eZ/Publish/Core/REST/Server/Controller/Location.php
+++ b/eZ/Publish/Core/REST/Server/Controller/Location.php
@@ -9,6 +9,7 @@
namespace eZ\Publish\Core\REST\Server\Controller;
use eZ\Publish\API\Repository\URLAliasService;
+use eZ\Publish\API\Repository\Values\Content\Location as APILocation;
use eZ\Publish\Core\REST\Common\Message;
use eZ\Publish\Core\REST\Common\Exceptions;
use eZ\Publish\Core\REST\Server\Values;
@@ -327,6 +328,32 @@ class Location extends RestController
);
}
+ /**
+ * Loads several locations by IDs.
+ *
+ * @return \eZ\Publish\Core\REST\Server\Values\LocationList
+ */
+ public function loadLocationList(Request $request)
+ {
+ $list = new Values\LocationList(
+ array_map(
+ function(APILocation $location){
+ return new Values\RestLocation($location, '');
+ },
+ $this->locationService->loadLocationList(
+ explode(',', $request->query->get('ids', ''))
+ )
+ ),
+ $request->getPathInfo()
+ );
+
+
+ return new Values\CachedValue(
+ $list,
+ ['locationId' => $request->query->get('ids', '')]
+ );
+ }
+
/**
* Loads all locations for content object.
*
diff --git a/eZ/Publish/Core/REST/Server/Values/RestLocation.php b/eZ/Publish/Core/REST/Server/Values/RestLocation.php
index d4b32d44b6..57e3cb4476 100644
--- a/eZ/Publish/Core/REST/Server/Values/RestLocation.php
+++ b/eZ/Publish/Core/REST/Server/Values/RestLocation.php
@@ -26,6 +26,8 @@ class RestLocation extends RestValue
/**
* Number of children of the location.
*
+ * NB! Value will be missing (empty string) when RestLocation is part of a larger LocationList.
+ *
* @var int
*/
public $childCount;
  • Figure out if we need another content-type with full locations data to avoid round-trips
  • Adapt and add functional tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment