diff --git a/docs/api/api.md b/docs/api/api.md index 93a4cd3c29..53c244afa5 100644 --- a/docs/api/api.md +++ b/docs/api/api.md @@ -1,11 +1,10 @@ -1. [Developer](index.html) -2. [Documentation](Documentation_31429504.html) + # API An Application Programming Interface (API) allows you to connect your code to eZ Platform. -From the eZ Blog:  +From the eZ Blog: [How would you explain what an API is to your mom](http://ez.no/Blog/How-would-you-explain-what-an-API-is-to-your-mom) eZ Platform offers two APIs: @@ -13,5 +12,3 @@ eZ Platform offers two APIs: 2. The [Public (PHP) API](https://doc.ez.no/display/DEVELOPER/Public+API+Guide) exposes a Repository which allows you to create, read, update, manage and delete all objects available in eZ Platform, first and foremost content, but also related objects like sections, locations, content types, content types groups, languages and so on. There is also a [JavaScript API Client](JS-Client_31429579.html), useful for working with eZ Platform as a [headless CMS](http://ez.no/Blog/Content-as-a-Service-CaaS-Decoupled-CMS-and-Headless-CMS-101). - -  diff --git a/docs/api/extending_the_rest_api.md b/docs/api/extending_the_rest_api.md index 781fed3365..0067edce5e 100644 --- a/docs/api/extending_the_rest_api.md +++ b/docs/api/extending_the_rest_api.md @@ -1,7 +1,4 @@ -1. [Developer](index.html) -2. [Documentation](Documentation_31429504.html) -3. [API](API_31429524.html) -4. [REST API Guide](REST-API-Guide_31430286.html) + # Extending the REST API @@ -27,7 +24,7 @@ Let's create a very simple controller, that has a `sayHello()` method, that take **My/Bundle/RestBundle/Rest/Controller/DefaultController.php** -``` brush: +``` php namespace My\Bundle\RestBundle\Rest\Controller;   use eZ\Publish\Core\REST\Server\Controller as BaseController; @@ -47,7 +44,7 @@ As said earlier, your REST routes are required to use the REST URI prefix. To do **app/config/routing.yml** -``` brush: +``` myRestBundle_rest_routes: resource: "@MyRestBundle/Resources/config/routing_rest.yml" prefix: %ezpublish_rest.path_prefix% @@ -59,7 +56,7 @@ Next, you need to create the REST route. We need to define the route's [controll **My/Bundle/RestBundle/Resources/config/routing\_rest.yml** -``` brush: +``` yaml myRestBundle_hello_world: pattern: /my_rest_bundle/hello/{name} defaults: @@ -77,7 +74,7 @@ Let's say that our Controller will return a `My\Bundle\RestBundle\Rest\Values\He **My/Bundle/RestBundle/Rest/Values/Hello.php** -``` brush: +``` php namespace My\Bundle\RestBundle\Rest\Values;   class Hello @@ -95,7 +92,7 @@ We will return an instance of this class from our `sayHello()` controller method **My/Bundle/RestBundle/Rest/Controller/DefaultController.php** -``` brush: +``` php namespace My\Bundle\RestBundle\Controller; use eZ\Publish\Core\REST\Server\Controller as BaseController; @@ -120,7 +117,7 @@ Let's create the service for our ValueObjectVisitor first. **My/Bundle/RestBundle/Resources/config/services.yml** -``` brush: +``` yaml services: myRestBundle.value_object_visitor.hello: parent: ezpublish_rest.output.value_object_visitor.base @@ -138,7 +135,7 @@ It will receive as arguments: **My/Bundle/RestBundle/Rest/Controller/Default.php** -``` brush: +``` php namespace My\Bundle\RestBundle\Rest\ValueObjectVisitor; use eZ\Publish\Core\REST\Common\Output\ValueObjectVisitor; @@ -163,7 +160,7 @@ The easiest way to handle cache is to re-use the ` CachedValue When you want the response to be cached, return an instance of CachedValue, with your Value Object as the argument. You can also pass a location id using the second argument, so that the Response is tagged with it: -``` brush: +``` return new CachedValue($helloValue, ['locationId', 42]); ``` @@ -179,7 +176,7 @@ Let's see what it would look like with a Content-Type of application/vnd.my.Gree **application/vnd.my.Greetings+xml** -``` brush: +``` xml John doe @@ -190,7 +187,7 @@ First, we need to create a service with the appropriate tag in services.yml. **My/Bundle/RestBundle/Resources/config/services.yml** -``` brush: +``` yaml services: myRestBundle.input_parser.Greetings: parent: ezpublish_rest.input.parser @@ -207,7 +204,7 @@ For convenience, we will consider that our input parser returns an instance of o **My/Bundle/RestBundle/Rest/InputParser/Greetings.php** -``` brush: +``` php namespace My\Bundle\RestBundle\Rest\InputParser;   use eZ\Publish\Core\REST\Common\Input\BaseParser; @@ -235,7 +232,7 @@ class Greetings extends BaseParser **My/Bundle/RestBundle/Resources/config/services.yml** -``` brush: +``` yaml services: myRestBundle.controller.default: class: My\Bundle\RestBundle\Rest\Controller\Default @@ -252,7 +249,7 @@ You can register newly added resources so that they show up in the REST root res New resources can be registered with code like this: -``` brush: +``` ez_publish_rest: system: default: @@ -275,14 +272,3 @@ This syntax is based on [Symfony's expression language](http://symfony.com/doc/c The above configuration will add the following entry to the root resource: `` - -#### In this topic: - -- [Requirements](#ExtendingtheRESTAPI-Requirements) - - [Controller](#ExtendingtheRESTAPI-Controller) - - [Route](#ExtendingtheRESTAPI-Route) -- [Controller action](#ExtendingtheRESTAPI-Controlleraction) -- [ValueObjectVisitor](#ExtendingtheRESTAPI-ValueObjectVisitor) - - [Cache handling](#ExtendingtheRESTAPI-Cachehandling) -- [Input parser](#ExtendingtheRESTAPI-Inputparser) -- [Registering resources in the REST root](#ExtendingtheRESTAPI-RegisteringresourcesintheRESTroot) diff --git a/docs/api/field_type_api_and_best_practices.md b/docs/api/field_type_api_and_best_practices.md index 1e0b312dda..31dbc46ef9 100644 --- a/docs/api/field_type_api_and_best_practices.md +++ b/docs/api/field_type_api_and_best_practices.md @@ -1,10 +1,3 @@ -1. [Developer](index.html) -2. [Documentation](Documentation_31429504.html) -3. [API](API_31429524.html) - -# Field Type API and best practices - -Created by Dominika Kurek, last modified by Michał Maciej Kusztelak on May 08, 2017 # Field Type API & best practices @@ -14,7 +7,7 @@ The implementation of a custom Field Type is done based on the Field Type SPI an In order to provide custom functionality for a Field Type, the SPI interacts with multiple layers of the eZ Platform architecture, as shown in the following diagram: - ![](attachments/31430767/31430766.png) + ![](docs/api/img/field_type_overview.png) On the top layer, the Field Type needs to provide conversion from and to a simple PHP hash value to support the REST API. The generated hash value may only consist of scalar values and hashes. It must not contain objects or arrays with numerical indexes that aren't sequential and/or don't start with zero. @@ -28,7 +21,7 @@ On the bottom level, a Field Type can additionally hook into the Persistence SPI The following sequence diagram visualizes the process of creating a new `Content` across all layers, especially focused on the interaction with a `FieldType`. -![](attachments/31430767/31430764.png) +![](docs/api/img/create_content_sequence.png)   In the next lines/pages, this document explains how to implement a custom Field Type based on the SPI and what is expected from it. As a code example, please refer to the Url FieldType, which has been implemented as a reference. @@ -37,7 +30,7 @@ In the next lines/pages, this document explains how to implement a custom Field The interaction with the Public API is done through the interface `eZ\Publish\SPI\FieldType\FieldType`. A custom Field Type must provide an implementation of this interface. In addition, it is considered best practice to provide a value object class for storing the custom field value provided by the Field Type. -### FieldDefinition handling +## FieldDefinition handling In order to make use of a custom Field Type, the user must apply it in a `eZ\Publish\API\Repository\Values\ContentType\FieldDefinition` of a custom Content Type. The user may in addition provide settings for the Field Type and a validator configuration.  Since the Public API cannot know anything about these, their handling is delegated to the Field Type itself through the following methods: @@ -57,13 +50,13 @@ In addition to normal settings, the Field Type should provide a schema settings Before the Public API stores settings for the `FieldType` in a `FieldDefinition`, the type is asked to validate the settings (which were provided by the user). As a result, the `FieldType` must return if the given settings comply to the schema defined by `getSettingsSchema()`. `validateValidatorConfiguration()` Analog to `validateFieldSettings()`, this method verifies that the given validator configuration complies to the schema provided by `getValidatorConfigurationSchema()`. -It is important to note that while the schema definitions of the `FieldType` maybe both be of arbitrary, serializable format, it is highly recommended to use a simple hash structure. It is highly recommended to follow the [Best practices](#FieldTypeAPIandbestpractices-Bestpractices) in order to create future proof schemas. +It is important to note that while the schema definitions of the `FieldType` maybe both be of arbitrary, serializable format, it is highly recommended to use a simple hash structure. It is highly recommended to follow the [Best practices](../guide/best_practices.md) in order to create future proof schemas. **Note:** Since it is not possible to enforce a schema format, the code using a specific `FieldType` must basically know all `FieldType`s it deals with. This will also apply to all user interfaces and the REST API, which therefore must provide extension points to register handling code for custom `FieldType`. These extensions are not defined, yet. -#### Name of the Field Type +## Name of the Field Type If you implement Nameable as an extra service, and register this Service using the tag `nameable`, the method `{FieldType}Nameable->getFieldName()` will be used to retrieve the name. @@ -71,7 +64,7 @@ Otherwise the regular `{FieldType}->getName()` method is used. **Example from fieldtype\_services.yml** -``` brush: +``` yaml # Nameable services (for fieldtypes that need advance name handling) ezpublish.fieldType.ezobjectrelation.nameable_field: class: %ezpublish.fieldType.ezobjectrelation.nameable_field.class% @@ -83,7 +76,7 @@ Otherwise the regular `{FieldType}->getName()` method is used.   -### Value handling +## Value handling A field type needs to deal with the custom value format provided by it. In order for the public API to work properly, it delegates working with such custom field values to the corresponding Field Type. The `SPI\FieldType\FieldType` interface therefore provides the following methods: @@ -97,7 +90,7 @@ Note: The method must assert structural consistency of the value, but must not v Through settings, the `FieldType` can specify, that the user may define a default value for the `Field` of the type. If no such default is provided by the user, the `FieldType` itself is asked for an "empty value" as the final fallback. The value chain for a specific field is therefore like this, when a `Field` of the `FieldType` is filled out: -1. 1. Is a value provided by the filling user? + 1. Is a value provided by the filling user? 2. Is a default provided by the `FieldDefinition`? 3. Take the empty value provided by the `FieldType` @@ -105,7 +98,7 @@ Through settings, the `FieldType` can specify, that the user may define a defaul In contrast to `acceptValue()` this method validates the plausibility of the given value, based on the `FieldType` settings and validator configuration, stored in the corresponding `FieldDefinition`. -### Storage conversion +## Storage conversion As said above, the value format of a `FieldType` is free form. However, in order to make eZ Publish store the value in it's database, it must comply to certain rules at storage time. To not restrict the value itself, a `FieldValue` must be converted to the storage specific format used by the Persistence SPI: `eZ\Publish\SPI\Persistence\Content\FieldValue`. After restoring a Field of `FieldType`, the conversion must be undone. The following methods of the `FieldType` are responsible for that: @@ -125,7 +118,7 @@ The data to be stored in the eZ Publish database. This may either be a scalar va `$externalData` -The arbitrary data stored in this field will not be touched by any of the eZ Publish components directly, but will be hold available for [Storing external data](#FieldTypeAPIandbestpractices-Storingexternaldata). +The arbitrary data stored in this field will not be touched by any of the eZ Publish components directly, but will be hold available for [Storing external data](../api/Field_Type_API_and_best_practices.md#Storing-external-data). `$sortKey` @@ -149,7 +142,7 @@ This method is supposed to return the actual index data for the provided `eZ\Pub To be able to query data properly an indexable field type also is required to return search specification. You must return a hash map of `eZ\Publish\SPI\Persistence\Content\Search\FieldType` instances from this method, which could look like: -``` brush: +``` array( 'url'  => new Search\FieldType\StringField(),     'text' => new Search\FieldType\StringField(), @@ -158,7 +151,7 @@ array(  This example from the `Url` field type shows that the field type will always return two indexable values, both strings. They have the names `url` and `text` respectively. -### Search Field Values +## Search Field Values The search field values, returned by the `getIndexData` method are simple value objects consisting of the following properties: @@ -174,7 +167,7 @@ The value of the field An `eZ\Publish\SPI\Persistence\Content\Search\FieldType` instance, describing the type information of the field. -### Search Field Types +## Search Field Types There are bunch of available search field types, which are automagically handled by our Search backend configuration. When using those there is no requirement to adapt , for example, the Solr configuration in any way. You can always use custom field types, though, but these might require re-configuration of the search backend. For Solr this would mean adapting the schema.xml. @@ -216,7 +209,7 @@ Field used for IDs. Basically acts like the string field, but will not be querie Custom field, for custom search data types. Will probably require additional configuration in the search backend. -### Configuring Solr +## Configuring Solr As mentioned before, if you are using the standard type definitions **there is no need to configure the search backend in any way**. Everything will work fine. The field definitions are handled using `dynamicField` definitions in Solr, for example. @@ -224,7 +217,7 @@ If you want to configure the handling of your field, you can always add a specia You could also define a custom field definition dedicatedly for certain fields, like for the name field in an article: -``` brush: +``` ``` @@ -256,9 +249,9 @@ Must delete external data for the given `Field`, if exists. See search service -Each of the above methods receive a $context array, which contains information on the underlying storage and the environment. This context can be used to store data in the eZ Publish data storage, but outside of the normal structures (e.g. a custom table in an SQL database). Note that the Field Type must take care on it's own for being compliant to different data sources and that 3rd parties can extend the data source support easily. For more information about this, take a look at the [Best practices](#FieldTypeAPIandbestpractices-Bestpractices)[]() section. +Each of the above methods receive a $context array, which contains information on the underlying storage and the environment. This context can be used to store data in the eZ Publish data storage, but outside of the normal structures (e.g. a custom table in an SQL database). Note that the Field Type must take care on it's own for being compliant to different data sources and that 3rd parties can extend the data source support easily. For more information about this, take a look at the [Best practices](../api/Field_Type_API_and_best_practices.md#Best-practices) section. -## Legacy Storage conversion +### Legacy Storage conversion The `FieldType` system is designed for future storage back ends of eZ Publish. However, the old database schema (*Legacy Storage*) must still be supported. Since this database cannot store arbitrary value information as provided by a `FieldType`, another conversion step must take place if the Legacy Storage is used. @@ -284,13 +277,13 @@ Converts the other way around. Returns the storage column which is used for indexing. -### Registering a converter +## Registering a converter The registration of a `Converter` currently works through the `$config` parameter of `eZ\Publish\Core\Persistence\Legacy\Handler`. See the class documentation for further details.   -For global service container integration, see [Register Field Type](Register-Field-Type_31430769.html). +For global service container integration, see [Register Field Type](../api/Field_Type_API_and_best_practices.md#Register-field-type). ## REST API interaction @@ -320,7 +313,7 @@ Converts FieldType validator configuration to a simple hash format. Converts the other way around. -### Extension points +## Extension points Some `FieldTypes` will require additional processing, for example a `FieldType` storing a binary file, or one having more complex settings or validator configuration. For this purpose specific implementations of an abstract class `eZ\Publish\Core\REST\Common\FieldTypeProcessor` are used. This class provides following methods: @@ -350,13 +343,13 @@ Performs manipulations on a outgoing validator configuration hash, previously ge Base implementations of these methods simply return the given hash, so you can implement only the methods your `FieldType` requires. Some `FieldTypes` coming with the eZ Publish installation already implement processors and you are encouraged to take a look at them. -For details on registering a `FieldType` processor, see [Register Field Type](Register-Field-Type_31430769.html). +For details on registering a `FieldType` processor, see [Register Field Type](../api/Field_Type_API_and_best_practices.md#Register-field-type). ## Best practices In this chapter, best practices for implementing a custom FieldType are collected. We highly encourage following these practices to be future proof. -### Gateway based Storage +## Gateway based Storage In order to allow the usage of a `FieldType` that uses external data with different data storages, it is recommended to implement a gateway infrastructure and a registry for the gateways. In order to ease this action, the Core implementation of `FieldType` s provides corresponding interfaces and base classes. These can also be used for custom field types. @@ -372,7 +365,7 @@ The registry mechanism is realized as a base class for `FieldStorage` implementa `addGateway()` -Allows the registration of additional `StorageGateway`s from the outside. Furthermore, a hash map of `StorageGateway`s can be given to the constructor for basic initialization. This array should orginate from the Dependency Injection mechanism. +Allows the registration of additional `StorageGateway`s from the outside. Furthermore, a hash map of `StorageGateway`s can be given to the constructor for basic initialization. This array should originate from the Dependency Injection mechanism. `getGateway()` @@ -380,7 +373,7 @@ This protected method is used by the implementation to retrieve the correct `Sto As a reference for the usage of these infrastructure, the Keyword, Url and User types can be examined. -### Settings schema +## Settings schema It is recommended to use a simple hash map format for the settings schema retured by eZ\\Publish\\SPI\\FieldType\\FieldType::getSettingsSchema(), which follows these rules: @@ -391,7 +384,7 @@ It is recommended to use a simple hash map format for the settings schema reture An example schema could look like this: -``` brush: +``` array( 'backupData' => array( 'type' => 'bool', @@ -406,7 +399,7 @@ array(   -### Validator schema +## Validator schema The schema for validator configuration should have a similar format than the settings schema has, except it has an additional level, to group settings for a certain validation mechanism: @@ -418,7 +411,7 @@ The schema for validator configuration should have a similar format than the set For example, for the `ezstring` type, the validator schema could be: -``` brush: +``` array( 'stringLength' => array( 'minStringLength' => array( @@ -435,13 +428,13 @@ array( ## Registering a Field Type -To register a Field Type, see [Register Field Type](Register-Field-Type_31430769.html). +To register a Field Type, see [Register Field Type](../api/Field_Type_API_and_best_practices.md#Register-field-type). To be integrated in unit and integration tests, Field Types need to be registered through the `service.ini` in `eZ/Publish/Core/settings`. ## Templating -A FieldType always need a piece of template to be correctly displayed. See [Field Type template](Field-Type-template_31430773.html). +A FieldType always need a piece of template to be correctly displayed. See [Field Type template](../guide/Field_Type_API_and_best_practices.md#Field-Type-template). ## Testing @@ -452,7 +445,7 @@ A FieldType always need a piece of template to be correctly displayed. See [Fie For both test environments, infrastructure is already in place, so that you can easily implement the required tests for your custom `FieldType` -### Persistence SPI +## Persistence SPI This type of integration test ensures, that a Field Type stores its data properly on basis of different Persistence SPI implementations. @@ -466,13 +459,13 @@ The integration tests with the Persistence SPI can be found in `eZ\Publish\SPI\T Running the test is fairly simple: Just specify the global `phpunit.xml` for PHPUnit configuration and make it execute a single test or a directory of tests, for example: -``` brush: +``` bash $ phpunit -c phpunit.xml eZ/Publish/SPI/Tests/FieldType ``` in order to run all `FieldType` tests. -### Public API +## Public API On a second level, the interaction between an implementation of the Public API (aka the Business Layer) and the Field Type is tested. Again, there is a common base class as the infrastructural basis for such tests, which resides in `eZ\Publish\API\Repository\Tests\FieldType\BaseIntegrationTest`. @@ -482,52 +475,14 @@ Note that the In-Memory stubs for the Public API integration test suite, do not If your Field Type needs to convert data between `storeFieldData()` and `getFieldData()`, you need to implement a `eZ\Publish\API\Repository\Tests\Stubs\PseudoExternalStorage` in addition, which performs this task. Running the tests against the Business Layer implementation of the Public API is not affected by this. -  - - - -  - -#### In this topic: -- [Field Type API & best practices](#FieldTypeAPIandbestpractices-FieldTypeAPI&bestpractices) - - [Public API interaction](#FieldTypeAPIandbestpractices-PublicAPIinteraction) - - [FieldDefinition handling](#FieldTypeAPIandbestpractices-FieldDefinitionhandling) - - [Value handling](#FieldTypeAPIandbestpractices-Valuehandling) - - [Storage conversion](#FieldTypeAPIandbestpractices-Storageconversion) - - [Searching](#FieldTypeAPIandbestpractices-Searching) - - [Search Field Values](#FieldTypeAPIandbestpractices-SearchFieldValues) - - [Search Field Types](#FieldTypeAPIandbestpractices-SearchFieldTypes) - - [Configuring Solr](#FieldTypeAPIandbestpractices-ConfiguringSolr) - - [Storing external data](#FieldTypeAPIandbestpractices-Storingexternaldata) - - [Legacy Storage conversion](#FieldTypeAPIandbestpractices-LegacyStorageconversion) - - [Registering a converter](#FieldTypeAPIandbestpractices-Registeringaconverter) - - [REST API interaction](#FieldTypeAPIandbestpractices-RESTAPIinteraction) - - [Extension points](#FieldTypeAPIandbestpractices-Extensionpoints) - - [Best practices](#FieldTypeAPIandbestpractices-Bestpractices) - - [Gateway based Storage](#FieldTypeAPIandbestpractices-GatewaybasedStorage) - - [Settings schema](#FieldTypeAPIandbestpractices-Settingsschema) - - [Validator schema](#FieldTypeAPIandbestpractices-Validatorschema) - - [Registering a Field Type](#FieldTypeAPIandbestpractices-RegisteringaFieldType) - - [Templating](#FieldTypeAPIandbestpractices-Templating) - - [Testing](#FieldTypeAPIandbestpractices-Testing) - - [Persistence SPI](#FieldTypeAPIandbestpractices-PersistenceSPI) - - [Public API](#FieldTypeAPIandbestpractices-PublicAPI) -## Attachments: +## Field Type template -![](images/icons/bullet_blue.gif) [create\_content\_sequence.png](attachments/31430767/31430764.png) (image/png) -![](images/icons/bullet_blue.gif) [create\_content\_sequence.svg](attachments/31430767/31430765.svg) (image/svg+xml) -![](images/icons/bullet_blue.gif) [field\_type\_overview.png](attachments/31430767/31430766.png) (image/png) +## Defining your Field Type template -# Field Type template - -Created by Dominika Kurek, last modified by David Christian Liedle on May 04, 2017 - -# Defining your Field Type template - -In order to be used by [`ez_render_field()` Twig helper](ez_render_field_32114041.html), you need to define a **template containing a block** dedicated to the Field display. +In order to be used by [`ez_render_field()` Twig helper](../guide/twig_functions_reference.md), you need to define a **template containing a block** dedicated to the Field display. This block consists on a piece of template receiving specific variables you can use to make the display vary. @@ -535,7 +490,7 @@ You will find examples with built-in Field Types in [EzPublishCoreBundle/Resourc **Template for a FieldType with "myfieldtype" identifier** -``` brush: +``` {% block myfieldtype_field %} {# Your code here #} {% endblock %} @@ -545,48 +500,16 @@ By convention, your block **must** be named `_field`. ## Exposed variables - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fieldeZ\Publish\API\Repository\Values\Content\FieldThe field to display
contentInfoeZ\Publish\API\Repository\Values\Content\ContentInfoThe ContentInfo to which the field belongs to
versionInfoeZ\Publish\API\Repository\Values\Content\VersionInfoThe VersionInfo to which the field belongs to
fieldSettingsmixedSettings of the field (depends on the FieldType)
parametershashOptions passed to ez_render_field() under the parameters key
attrhashThe attributes to add the generate the HTML markup.
-Contains at least a class entry, containing <fieldtypeidentifier>-field
+ +| Name | Type | Description | +|------|------|-------------| +| field | eZ\Publish\API\Repository\Values\Content\Field | The field to display | +| contentInfo | eZ\Publish\API\Repository\Values\Content\ContentInfo | The ContentInfo to which the field belongs to | +| versionInfo | eZ\Publish\API\Repository\Values\Content\VersionInfo | The VersionInfo to which the field belongs to | +| fieldSettings | mixed | Settings of the field (depends on the FieldType) | +|parameters | hash | Options passed to ez_render_field() under the parameters key | +|attr | hash | The attributes to add the generate the HTML markup. Contains at least a class entry, containing -field | + ## Reusing blocks @@ -606,7 +529,7 @@ To make your template available, you must register it to the system. **app/config/ezplatform.yml** -``` brush: +``` yaml ezpublish: system: my_siteaccess: @@ -617,20 +540,18 @@ ezpublish: priority: 10 ``` -You can define these rules in a dedicated file instead of `app/config/ezplatform.yml`. Read the [cookbook recipe to learn more about it](Importing-settings-from-a-bundle_31429803.html). +You can define these rules in a dedicated file instead of `app/config/ezplatform.yml`. Read the [cookbook recipe to learn more about it](../cookbook/Importing_settings_from_a_bundle.md). # Register Field Type -Created by Dominika Kurek, last modified on Jul 06, 2017 +## Introduction -# Introduction +This document explains how to register a custom Field Type in eZ Platform. It will not contain the development part as it is already covered [in the API section](../api/Field_Type_API_and_best_practices.md). -This document explains how to register a custom Field Type in eZ Platform. It will not contain the development part as it is already covered [in the API section](Field-Type-API-and-best-practices_31430767.html). +Please be sure you first have read the [basic documentation on how to develop a custom Field Type](../api/Field_Type_API_and_best_practices.md). -Please be sure you first have read the [basic documentation on how to develop a custom Field Type](Field-Type-API-and-best-practices_31430767.html). - -# Service container configuration +## Service container configuration To be able to declare a FieldType, you need to have [registered a bundle in your application kernel](http://symfony.com/doc/master/book/page_creation.html#the-bundle-system). @@ -638,11 +559,11 @@ This bundle needs to expose some configuration for the service container somehow ## Basic configuration -This part relates to the [base FieldType class that interacts with the Publish API](Field-Type-API-and-best-practices_31430767.html#FieldTypeAPIandbestpractices-PublicAPIinteraction). +This part relates to the [base FieldType class that interacts with the Publish API](../api/Field_Type_API_and_best_practices.md#PublicAPI). Let's take a basic example from `ezstring` configuration. -``` brush: +``` parameters: ezpublish.fieldType.ezstring.class: eZ\Publish\Core\FieldType\TextLine\Type   @@ -668,15 +589,15 @@ Basic field types configuration is located in [EzPublishCoreBundle/Resources/co ## Legacy Storage Engine -### Converter +## Converter -As stated in [Field Type API & best practices](Field-Type-API-and-best-practices_31430767.html#FieldTypeAPIandbestpractices-LegacyStorageconversion), a conversion of Field Type values is needed in order to properly store the data into the *old* database schema (aka *Legacy Storage*). +As stated in [Field Type API & best practices](../api/Field_Type_API_and_best_practices.md#Legacy-storage-conversion), a conversion of Field Type values is needed in order to properly store the data into the *old* database schema (aka *Legacy Storage*). Those converters also need to be correctly exposed as services. **Field Type converter for ezstring** -``` brush: +``` parameters: ezpublish.fieldType.ezstring.converter.class: eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\Converter\TextLine   @@ -691,47 +612,23 @@ Here again we need to tag our converter service, with **`ezpublish.storageEngin As for the tag attributes: - ---- - - - - - - - - - - - - - - - - - - - - -
Attribute nameUsage
aliasRepresents the fieldTypeIdentifier (just like for the FieldType service)
lazy

Boolean indicating if the converter should be lazy loaded or not.

-

Performance wise, it is recommended to set it to true unless you have very specific reasons.

callback

If lazy is set to true, it represents the callback that will be called to build the converter. Any valid callback can be used.

-

Note that if the callback is defined in the converter class, the class name can be omitted.
-This way, in the example above, the full callback will be resolved to eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\Converter\TextLine::create

+| Attribute name | Usage | +|----------------|-------| +| alias | Represents the fieldTypeIdentifier (just like for the FieldType service) | +| lazy | Boolean indicating if the converter should be lazy loaded or not. Performance wise, it is recommended to set it to true unless you have very specific reasons. | +| callback | If lazy is set to true, it represents the callback that will be called to build the converter. Any valid callback can be used. Note that if the callback is defined in the converter class, the class name can be omitted. This way, in the example above, the full callback will be resolved to eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\Converter\TextLine::create | The converter configuration for basic field types are located in [eZ/Publish/Core/settings/fieldtype\_external\_storages.yml](https://github.com/ezsystems/ezpublish-kernel/blob/master/eZ/Publish/Core/settings/fieldtype_external_storages.yml). -### External storage +## External storage -A Field Type has the [ability to store its value (or part of it) in external data sources](Field-Type-API-and-best-practices_31430767.html#FieldTypeAPIandbestpractices-Storingexternaldata). This is made possible through the `eZ\Publish\SPI\FieldType\FieldStorage` interface. Thus, if one wants to use this functionality, he needs to define a service implementing this interface and tagged as **`ezpublish.fieldType.externalStorageHandler`** to be recognized by the Repository. +A Field Type has the [ability to store its value (or part of it) in external data sources](Field_Type_API_and_best_practices.md#Storing-external-data). This is made possible through the `eZ\Publish\SPI\FieldType\FieldStorage` interface. Thus, if one wants to use this functionality, he needs to define a service implementing this interface and tagged as **`ezpublish.fieldType.externalStorageHandler`** to be recognized by the Repository. Here is an example for **ezurl** field type: **External storage handler for ezurl** -``` brush: +``` parameters: ezpublish.fieldType.ezurl.externalStorage.class: eZ\Publish\Core\FieldType\Url\UrlStorage   @@ -746,13 +643,13 @@ The configuration is straight forward. Nothing specific except the **`ezpublish. External storage configuration for basic field types is located in [EzPublishCoreBundle/Resources/config/fieldtypes.yml](https://github.com/ezsystems/ezp-next/blob/master/eZ/Bundle/EzPublishCoreBundle/Resources/config/fieldtypes.yml). -### Gateway based storage +## Gateway based storage As stated in the [Field Type best practices](Field-Type-API-and-best-practices_31430767.html#FieldTypeAPIandbestpractices-GatewaybasedStorage), in order to be storage agnostic and external storage handler should use a *storage gateway*. This can be done by implementing another service implementing `eZ\Publish\Core\FieldType\StorageGateway` and being tagged as `ezpublish.fieldType.externalStorageHandler.gateway`. **Storage gateway for ezurl** -``` brush: +``` parameters: ezpublish.fieldType.ezurl.storage_gateway.class: eZ\Publish\Core\FieldType\Url\UrlStorage\Gateway\LegacyStorage   @@ -763,25 +660,10 @@ services: - {name: ezpublish.fieldType.externalStorageHandler.gateway, alias: ezurl, identifier: LegacyStorage} ``` - - - - - - - - - - - - - - - - - -
Attribute nameUsage
aliasRepresents the fieldTypeIdentifier (just like for the FieldType service)
identifierIdentifier for the gateway.
-Must be unique per storage engine. LegacyStorage is the convention name for Legacy Storage Engine.
+| Attribute name | Usage | +|----------------|-------| +| alias | Represents the fieldTypeIdentifier (just like for the FieldType service) | +| identifier | Identifier for the gateway. Must be unique per storage engine. LegacyStorage is the convention name for Legacy Storage Engine. | For this to work properly, your storage handler must inherit from `eZ\Publish\Core\FieldType\GatewayBasedStorage`. @@ -791,11 +673,10 @@ The gateway configuration for basic field types are located in [EzPublishCoreBun -# Settings schema and allowed validators +## Settings schema and allowed validators -Created by Dominika Kurek, last modified on Apr 22, 2016 -# Internal Field Type conventions and best practices +## Internal Field Type conventions and best practices FieldType->$settingsSchema and FieldType->$allowedValidators are intentionally left free-form, to give broadest freedom to Field Type developers. However, for internal Field Types (aka those delivered with eZ Platform), a common standard should be established as best practice. The purpose of this page is to collect and unify this standard. diff --git a/docs/api/general_rest_usage.md b/docs/api/general_rest_usage.md index 13a7474794..2950d8839a 100644 --- a/docs/api/general_rest_usage.md +++ b/docs/api/general_rest_usage.md @@ -1,13 +1,9 @@ -1. [Developer](index.html) -2. [Documentation](Documentation_31429504.html) -3. [API](API_31429524.html) -4. [REST API Guide](REST-API-Guide_31430286.html) + # General REST usage -Created by Dominika Kurek, last modified on Apr 22, 2016 -As explained in the [introduction](REST-API-Guide_31430286.html), the REST API is based on a very limited list of general principles: +As explained in the [introduction](../api/rest_api_guide.md), the REST API is based on a very limited list of general principles: - each resource (uri) interacts with a part of the system (Content, URL aliases, User Groups, etc.), - for each resource, one or more verbs are available, each having a different effect (delete a Content item, get a URL Alias, list user groups, etc.), @@ -15,17 +11,17 @@ As explained in the [introduction](REST-API-Guide_31430286.html), the REST API i ## Anatomy of a REST call -### What we can learn from a GET request +## What we can learn from a GET request This verb is used to query the API for information. It is one of the two operations web browsers implement, and the one most commonly used. -#### Request +## Request The only requirement for this verb is usually the resource URI, and the accept header. On top of that, cache request headers can be added, like `If-None-Match`, but those aren't fully implemented yet in eZ Publish 5.0. **Load ContentInfo request** -``` brush: +``` GET /content/objects/23 HTTP/1.1 Accept: application/vnd.ez.api.ContentInfo+xml ``` @@ -40,7 +36,7 @@ The API will reply with: **Load ContentInfo response** -``` brush: +``` HTTP/1.1 200 OK Accept-Patch: application/vnd.ez.api.ContentUpdate+xml;charset=utf8 Content-Type: application/vnd.ez.api.ContentInfo+xml @@ -49,17 +45,17 @@ Content-Length: xxx The length of our content, provided by the Content-Length header, isn't *that* useful. -##### HTTP Code +## HTTP Code The API responded here with a standard 200 OK HTTP response code, which is the expected response code for a "normal" GET request. Some GET requests, like [getting a Content item's current version](https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst#13241%C2%A0%C2%A0%C2%A0get-current-version), may reply with a 301 Moved permanently, or 307 Temporary redirect code. Errors will be indicated with HTTP error codes, like 404 for Not Found, or 500 for Internal server error. The [REST specifications](https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst) provide the list of every HTTP response code you can expect from implemented resources. -##### Content-Type header +## Content-Type header As long as a response contains an actual HTTP body, the Content-Type header will be used to specify which Content-Type is contained in the response. In that case, a ContentInfo (`Content-Type: application/vnd.ez.api.ContentInfo`) in XML (`Content-Type: application/vnd.ez.api.ContentInfo+xml`) -##### Accept-Patch header +## Accept-Patch header This is a very interesting one. @@ -69,21 +65,21 @@ This last part means that if we send a PATCH /content/objects/23 request with a REST will use the `Accept-Patch` header to indicate how to **modify** the returned **data**. -##### Other headers: Location +## Other headers: Location Depending on the resource, request & response headers will vary. For instance, [creating content](https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst#13231%C2%A0%C2%A0%C2%A0creating-content), or [getting a Content item's current version](https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst#13241%C2%A0%C2%A0%C2%A0get-current-version) will both send a `Location` header to provide you with the requested resource's ID. Those particular headers generally match a specific list of HTTP response codes. Location is sent by `201 Created`, `301 Moved permanently,` `307 Temporary redirect responses`. This list isn't finished, but you can expect those HTTP responses to provide you with a Location header. -##### Other headers: Destination +## Other headers: Destination This request header is the request counterpart of the Location response header. It is used in a COPY / MOVE operation, like [copying a Content item](https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst#13236%C2%A0%C2%A0%C2%A0copy-content), on a resource to indicate where the resource should be moved to, using the ID of the destination. -#### Response body +## Response body **Load ContentInfo response body**  Expand source -``` brush: +``` xml @@ -109,7 +105,7 @@ As explained above, the API has told us that we could modify content object 23 b The REST API data structs mostly match a PHP Public API value object -#### Value objects representation +## Value objects representation Value objects like [ContentInfo](https://github.com/ezsystems/ezp-next/blob/master/eZ/Publish/API/Repository/Values/Content/ContentInfo.php) basically feature two types of fields: basic, local fields (modified, name...) and foreign field(s) references (sectionId, mainLocationId). @@ -132,7 +128,7 @@ URI parameters are of course also used. They usually serve as filters / options **GET request with limit parameter** -``` brush: +``` GET /content/objects/59/versions/2/relations&limit=5 HTTP/1.1 Accept: application/vnd.ez.api.RelationList+xml ``` @@ -147,7 +143,7 @@ In addition to the usual GET, POST, PUT and DELETE HTTP verbs, the API supports **PATCH HTTP request** -``` brush: +``` POST /content/objects/59 HTTP/1.1 X-HTTP-Method-Override: PATCH ``` @@ -164,7 +160,7 @@ Due to this, we decided not to enable siteaccess matching with REST. In order to **X-Siteaccess header example** -``` brush: +``` GET / HTTP/1.1 Host: api.example.com Accept: application/vnd.ez.api.Root+json @@ -173,19 +169,10 @@ X-Siteaccess: ezdemo_site_admin   -#### In this topic: - -- [Anatomy of a REST call](#GeneralRESTusage-AnatomyofaRESTcall) - - [What we can learn from a GET request](#GeneralRESTusage-WhatwecanlearnfromaGETrequest) -- [Request parameters](#GeneralRESTusage-Requestparameters) -- [Custom HTTP verbs](#GeneralRESTusage-CustomHTTPverbs) -- [Specifying a siteaccess](#GeneralRESTusage-Specifyingasiteaccess) - # REST API Authentication -Created by Dominika Kurek, last modified on Apr 22, 2016 The REST API supports two authentication methods: session, and basic.  @@ -214,7 +201,7 @@ To enable HTTP Basic authentication, you need to edit app`/config/security.yml`, **ezplatform.yml** -``` brush: +``` yaml ezpublish_rest: pattern: ^/api/ezp/v2 stateless: true @@ -228,16 +215,14 @@ Most HTTP client libraries as well as REST libraries do support this method one **Raw HTTP request with basic authentication** -``` brush: +``` GET / HTTP/1.1 Host: api.example.com Accept: application/vnd.ez.api.Root+json Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== ``` -# Error handling - -Created by Dominika Kurek, last modified on Apr 22, 2016 +## Error handling Error handling in the REST API is fully based on HTTP error codes. As a web developer, you are probably familiar with the most common ones: 401 Unauthorized, 404 Not Found or 500 Internal Server Error. The REST API uses those, along with a few more, to allow proper error handling. @@ -271,9 +256,8 @@ Returned when an accept header sent with the requested isn't supported. It is up to you, in your client implementation, to handle those codes by checking if an error code (4xx or 5xx) was returned instead of the expected 2xx or 3xx. -# REST API Countries list +## REST API Countries list -Created by Dominika Kurek, last modified on Apr 22, 2016 Countries list is a REST service that gives access to an [ISO-3166](http://en.wikipedia.org/wiki/ISO_3166) formatted list of world countries. It is useful when presenting a country options list from any application. @@ -283,7 +267,7 @@ To send a GET request to the REST API Countries list, you have to provide the Co **Countries list request** -``` brush: +``` Resource: /api/ezp/v2/services/countries Method: GET Content-Type: application/vnd.ez.api.CountriesList+xml @@ -297,7 +281,7 @@ See the [General REST usage documentation page](General-REST-usage_31430291.html **Countries list request** -``` brush: +``` GET /api/ezp/v2/services/countries Host: example.com Accept: application/vnd.ez.api.CountriesList+xml @@ -309,7 +293,7 @@ The HTTP response will it be with a 200 OK Header. **Countries list response headers** -``` brush: +``` HTTP/1.1 200 Content-Type: application/vnd.ez.api.CountriesList+xml ``` @@ -327,7 +311,7 @@ See [the ISO-3166 glossary](http://www.iso.org/iso/home/standards/country_codes/ **Body XML Response** -``` brush: +``` xml Afghanistan ``` -### With Bower +## With Bower Alternatively, the JavaScript REST Client can be installed directly in any project with [Bower](http://bower.io/): **Installing with bower** -``` brush: +``` php $ bower install --save ezsystems/ez-js-rest-client ``` @@ -62,22 +58,22 @@ In essence, the operations available through those services are asynchronous, so 1. `error`: depending on the success of the operation, this parameter is either `false` or a [`CAPIError`](http://ezsystems.github.io/javascript-rest-client/classes/CAPIError.html) instance representing the error 2. `response`: it's always of a [`Response`](http://ezsystems.github.io/javascript-rest-client/classes/Response.html) instance allowing you to retrieve any information from the REST API response -### Instantiation and authentication +## Instantiation and authentication [The `eZ.CAPI` constructor function](http://ezsystems.github.io/javascript-rest-client/classes/CAPI.html) expects two parameters: 1. the API end point URI -2. an authentication agent instance to configure the client for [the authentication mechanism configuration in eZ Platform](REST-API-Authentication_31430293.html). +2. an authentication agent instance to configure the client for [the authentication mechanism configuration in eZ Platform](../general_rest_usage.md#REST-API-Authentication). The JavaScript REST Client comes with two authentication agents for the Session and Basic Auth authentication mechanism. -#### Session auth +## Session auth The Session Auth Agent expects an object describing the existing Session or containing the credentials for the user to create the corresponding session. So if the user is not yet authenticated, the client can be instantiated with: **Session Authentication (new session)** -``` brush: +``` php var capi, credentials = { login: 'admin', @@ -103,7 +99,7 @@ If the user already has a session, the agent expects an object describing the se **Session Authentication (existing session)** -``` brush: +``` var capi, sessionInfo = { name: 'eZSESSID', // name of the session, might also be something like eZSESSID98defd6ee70dfb1dea416cecdf391f58 @@ -125,13 +121,13 @@ capi.isLoggedIn(function (error, response) { }); ``` -#### Basic auth +## Basic auth When configured in the Basic Authentication, the basic auth agent just expects the user's credentials: **Basic Authentication** -``` brush: +``` php var capi, credentials = { login: 'admin', @@ -151,13 +147,13 @@ capi.logIn(function (error, response) { }); ``` -### Loading a ContentInfo or a Content +## Loading a ContentInfo or a Content To load a ContentInfo, you need [the Content Service](http://ezsystems.github.io/javascript-rest-client/classes/ContentService.html), it is returned by the `getContentService` method on the client instance: **Loading a ContentInfo** -``` brush: +``` php var capi, contentService, contentRestId = '/api/ezp/v2/content/objects/1', credentials = { @@ -182,13 +178,13 @@ contentService.loadContentInfo(contentRestId, function (error, response) { If you run this example, you should see in the browser network panel a GET HTTP request to with the necessary headers to get a JSON representation of the ContentInfo. If you want to load the Content instead, you can use [the `loadContent` method](http://ezsystems.github.io/javascript-rest-client/classes/ContentService.html#method_loadContent). -### Moving a Location +## Moving a Location To move a Location, [the Content Service](http://ezsystems.github.io/javascript-rest-client/classes/ContentService.html) is also needed, this operation will generate a MOVE HTTP request. If configured for the session authentication mechanism, the client will automatically add the CSRF Token. **Moving a Location** -``` brush: +``` php var capi, contentService, locationRestId = '/api/ezp/v2/content/locations/1/43/53', // Media/Multimedia in a default install newParentLocationRestId = '/api/ezp/v2/content/locations/1/43/52', // Media/Files in a default install @@ -211,13 +207,13 @@ contentService.moveSubtree(locationRestId, newParentLocationRestId, function (er }) ``` -### Searching for Content or Location +## Searching for Content or Location -Searching for Content or Location can be done with [REST views](https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst#views). REST views can be configured with the [search engine criteria](Search_31429673.html#Search-SearchCriteriaReference) to match some Content items or Locations: +Searching for Content or Location can be done with [REST views](https://github.com/ezsystems/ezpublish-kernel/blob/master/doc/specifications/rest/REST-API-V2.rst#views). REST views can be configured with the [search engine criteria](../guide/search_criteria_reference.md) to match some Content items or Locations: **REST views** -``` brush: +``` php var capi, contentService, query,  credentials = { login: 'admin', diff --git a/docs/api/public_php_api.md b/docs/api/public_php_api.md index 15d8df5b35..178aec2c33 100644 --- a/docs/api/public_php_api.md +++ b/docs/api/public_php_api.md @@ -1,10 +1,7 @@ -1. [Developer](index.html) -2. [Documentation](Documentation_31429504.html) -3. [API](API_31429524.html) + # eZ Platform Public PHP API -Created by Dominika Kurek, last modified on Apr 22, 2016 The PHP API is also commonly referred to as the "*Public API*". Currently it exposes a Repository which allows you to create, read, update, manage and delete all objects available in eZ Platform, first and foremost content, but also related objects like Sections, Locations, Content Types, Content Type groups, languages and so on. @@ -16,7 +13,7 @@ It will allow you to create, retrieve, update and delete all the eZ Platform obj **Obtaining the eZ Platform Repository via the service container** -``` brush: +``` php /** @var $repository \eZ\Publish\API\Repository\Repository $repository = $container->get( 'ezpublish.api.repository' ); ``` @@ -69,19 +66,10 @@ In order to update or create elements in the Repository, you will use structs. T Using them is also covered in the Cookbook. -#### In this topic: - -- [eZ Platform API Repository](#eZPlatformPublicPHPAPI-eZPlatformAPIRepository) -- [The service container](#eZPlatformPublicPHPAPI-Theservicecontainer) -- [Authentication](#eZPlatformPublicPHPAPI-Authentication) -- [Services](#eZPlatformPublicPHPAPI-Services) -- [Value objects](#eZPlatformPublicPHPAPI-Valueobjects) -- [Create and update structs](#eZPlatformPublicPHPAPI-Createandupdatestructs) # Public API Guide -Created by Dominika Kurek, last modified by Sarah Haïm-Lubczanski on Jun 30, 2016 The public API will give you an easy access to the eZ Platform content repository. This repository is the core component that manages content, Locations, Sections, Content Types, Users, User groups, and Roles. It also provides a new, clear interface for plugging in custom Field Types. @@ -114,7 +102,7 @@ This is the file where we define our action's URL matching. The generated file c **Generated routing.yml** -``` brush: +``` yaml ez_systems_cookbook_homepage: path: /hello/{name} defaults: { _controller: EzSystemsCookbookBundle:Default:index } @@ -124,7 +112,7 @@ We can safely remove this default code, and replace it with this: **Edited routing.yml** -``` brush: +``` yaml ezsystems_cookbook_hello: path: /cookbook/hello/{name} defaults: { _controller: EzSystemsCookbookBundle:Default:hello } @@ -138,7 +126,7 @@ This controller was generated by the bundle generator. It contains one method,  **DefaultController::helloAction()** -``` brush: +``` javascript public function helloAction( $name ) { $response = new \Symfony\Component\HttpFoundation\Response; @@ -171,7 +159,6 @@ With both command line scripts and HTTP routes, you have the basics you need to # Browsing, finding, viewing -Created by Dominika Kurek, last modified on Jun 28, 2017 We will start by going through the various ways to find and retrieve content from eZ Platform using the API. While this will be covered in further dedicated documentation, it is necessary to explain a few basic concepts of the Public API. In the following recipes, you will learn about the general principles of the API as they are introduced in individual recipes. @@ -183,7 +170,7 @@ Let's first see the full code. You can see the Command line version at getContainer()->get( 'ezpublish.api.repository' ); $contentService = $repository->getContentService(); $contentTypeService = $repository->getContentTypeService(); @@ -219,7 +206,7 @@ catch( \eZ\Publish\API\Repository\Exceptions\UnauthorizedException $e ) Let's analyze this code block by block. -``` brush: +``` php $repository = $this->getContainer()->get( 'ezpublish.api.repository' ); $contentService = $repository->getContentService(); $contentTypeService = $repository->getContentTypeService(); @@ -228,7 +215,7 @@ $fieldTypeService = $repository->getFieldTypeService(); This is the initialization part. As explained above, everything in the Public API goes through the repository via dedicated services. We get the repository from the service container, using the method `get()` of our container, obtained via `$this->getContainer()`. Using our `$repository` variable, we fetch the two services we will need using `getContentService()` and `getFieldTypeService()`. -``` brush: +``` php try { // iterate over the field definitions of the content type and print out each field's identifier and value @@ -239,7 +226,7 @@ Everything starting from line 5 is about getting our Content and iterating over The first thing we do is use the Content Service to load a Content item using its ID, 66: `$contentService->loadContent ` `( 66 )`. As you can see on the API doc page, this method expects a Content ID, and returns a [Content Value Object](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/Values/Content/Content.html). -``` brush: +``` php foreach( $contentType->fieldDefinitions as $fieldDefinition ) { // ignore ezpage @@ -278,13 +265,13 @@ If you want to take SiteAccess languages into account, you have two options: Otherwise if you want to use an altogether different language, you can specify a language code in the `getField()` call: -``` brush: +``` php $content->getFieldValue( $fieldDefinition->identifier, 'fre-FR' ) ``` **Exceptions handling** -``` brush: +``` php catch ( \eZ\Publish\API\Repository\Exceptions\NotFoundException $e ) { $output->writeln( "No content with id $contentId found" ); @@ -311,7 +298,7 @@ In this code, we introduce the [LocationService](http://apidoc.ez.no/sami/trunk/ **Loading a Location** -``` brush: +``` php try { // load the starting location and browse @@ -332,7 +319,7 @@ As for the ContentService, `loadLocation()` returns a Value Object, here a ` **Iterating over a Location's children** -``` brush: +``` php private function browseLocation( Location $location, OutputInterface $output, $depth = 0 ) { $childLocationList = $this->locationService->loadLocationChildren( $location, $offset = 0, $limit = -1 ); @@ -366,7 +353,7 @@ We introduce here several new services: [`URLAliasService`](http://apidoc.ez.no/ **Services initialization** -``` brush: +``` php /** @var $repository \eZ\Publish\API\Repository\Repository */ $repository = $this->getContainer()->get( 'ezpublish.api.repository' ); $contentService = $repository->getContentService(); @@ -380,7 +367,7 @@ $userService = $repository->getUserService(); In a command line script, the repository runs as if executed by the anonymous user. In order to identify it as a different user, you need to use the ` UserService ` as follows (in this example `14` is the ID of the administrator user): -``` brush: +``` php $administratorUser = $userService->loadUser( 14 ); $repository->setCurrentUser( $administratorUser ); ``` @@ -393,7 +380,7 @@ V1.6 Since v1.6.0, as the `setCurrentUser` method is deprecated, you need to use the following code (here for the `admin` user, to be replaced with a different login as needed): -``` brush: +``` php $permissionResolver = $repository->getPermissionResolver(); $user = $userService->loadUserByLogin('admin'); $permissionResolver->setCurrentUserReference($user); @@ -403,7 +390,7 @@ $permissionResolver->setCurrentUserReference($user); We will now load a `ContentInfo` object using the provided ID and use it to get our Content item's metadata -``` brush: +``` php $contentInfo = $contentService->loadContentInfo( $contentId ); ``` @@ -411,7 +398,7 @@ $contentInfo = $contentService->loadContentInfo( $contentId ); **Getting Content Locations** -``` brush: +``` php // show all locations of the content $locations = $locationService->loadLocations( $contentInfo ); $output->writeln( "LOCATIONS" ); @@ -432,7 +419,7 @@ We now want to list relations from and to our Content. Since relations are versi **Browsing a Content's relations** -``` brush: +``` php // show all relations of the current version $versionInfo = $contentService->loadVersionInfo( $contentInfo ); $relations = $contentService->loadRelations( $versionInfo ); @@ -455,7 +442,7 @@ We can of course get our Content item's metadata by using the Value Object's pro **Primitive object metadata** -``` brush: +``` php // show meta data $output->writeln( "\nMETADATA" ); $output->writeln( " Name: " . $contentInfo->name ); @@ -471,7 +458,7 @@ $output->writeln( " Always available: " . ( $contentInfo->alwaysAv We can use [`UserService::loadUser()`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/UserService.html#method_loadUser) with Content `ownerId` property of our `ContentInfo` to load the Content's owner as a ` User ` Value Object. -``` brush: +``` php $owner = $userService->loadUser( $contentInfo->ownerId ); $output->writeln( " Owner: " . $owner->contentInfo->name ); ``` @@ -482,7 +469,7 @@ To get the current version's creator, and not the content's owner, you need to u The Section's ID can be found in the `sectionId` property of the `ContentInfo` object. To get the matching Section Value Object, you need to use the `SectionService::loadSection()` method. -``` brush: +``` php $section = $sectionService->loadSection( $contentInfo->sectionId ); $output->writeln( " Section: $section->name" ); ``` @@ -491,7 +478,7 @@ $output->writeln( " Section: $section->name" ); To conclude we can also iterate over the Content's version, as ` VersionInfo ` Value Objects. -``` brush: +``` php $versionInfoArray = $contentService->loadVersions( $contentInfo ); if ( !empty( $versionInfoArray ) ) { @@ -550,7 +537,7 @@ We introduce here a new object: `Query`. It is used to build up a Content query   -``` brush: +```php $query = new \eZ\Publish\API\Repository\Values\Content\Query(); // Use 'query' over 'filter' for FullText to get hit score (relevancy) with Solr/Elastic $query->query = new Query\Criterion\FullText( $text ); @@ -568,7 +555,7 @@ The full list of criteria can be found on your installation in the following dir The `Query` object is given as an argument to [`SearchService::findContent()`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/SearchService.html#method_findContent). This method returns a `SearchResult` object. This object provides you with various information about the search operation (number of results, time taken, spelling suggestions, or facets, as well as, of course, the results themselves. -``` brush: +``` php $result = $searchService->findContent( $query ); $output->writeln( 'Found ' . $result->totalCount . ' items' ); foreach ( $result->searchHits as $searchHit ) @@ -601,7 +588,7 @@ Full code As explained in the previous chapter, Criterion objects are grouped together using logical criteria. We will now see how multiple criteria objects can be combined into a fine grained search `Query`. -``` brush: +``` php use eZ\Publish\API\Repository\Values\Content\Query\Criterion; use eZ\Publish\API\Repository\Values\Content;   @@ -635,7 +622,7 @@ Note that the criterion behaves differently depending on the method you use, bec This example shows the usage of both `$languageFilter` and `Criterion\Visibility`: -``` brush: +``` php $query = new LocationQuery([ 'filter' => new Criterion\LogicalAnd([ new Criterion\Visibility(Criterion\Visibility::VISIBLE), @@ -657,7 +644,7 @@ A search isn't only meant for searching, it also provides the interface for what Following the examples above we now change it a bit to combine several criteria with both an AND and an OR condition. -``` brush: +``` javascript use eZ\Publish\API\Repository\Values\Content\Query\Criterion; use eZ\Publish\API\Repository\Values\Content;   @@ -691,7 +678,7 @@ The above example is fine, but it can be optimized a bit by taking advantage of You can also use the [`ContentTypeIdentifier`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/Values/Content/Query/Criterion/ContentTypeIdentifier.html) Criterion: -``` brush: +``` php use eZ\Publish\API\Repository\Values\Content\Query\Criterion; use eZ\Publish\API\Repository\Values\Content;   @@ -708,7 +695,7 @@ $query->filter = new Criterion\LogicalAnd( $result = $searchService->findContent( $query ); ``` -Tip +**Tip** All filter criteria are capable of doing an "IN" selection, the ParentLocationId above could, for example, have been provided "array( 2, 43 )" to include second level children in both your content tree (2) and your media tree (43). @@ -737,7 +724,7 @@ To be able to take advantage of facets, we can set the `Query->facetBuilders` pr As an example, let's `apply UserFacet ` to be able to group content according to the creator: -``` brush: +``` php use eZ\Publish\API\Repository\Values\Content\Query\Criterion; use eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder;   @@ -766,7 +753,7 @@ Thanks to the fact that the " searchHits " property of the [`SearchResult`](http   -``` brush: +``` php use eZ\Publish\API\Repository\Values\Content\Query;   // [...] @@ -782,7 +769,6 @@ $resultCount = $searchService->findContent( $query )->totalCount; # Managing Content -Created by Dominika Kurek, last modified on Jun 06, 2017 In the following recipes, you will see how to create Content, including complex fields like XmlText or Image. @@ -792,7 +778,7 @@ As seen earlier, the Repository executes operations with a user's credentials. I **authentication** -``` brush: +``` php $user = $userService->loadUserByCredentials( $username, $password ); $repository->setCurrentUser( $user ); ``` @@ -803,7 +789,7 @@ Since v1.6.0, as the `setCurrentUser` method is deprecated, you need to use the **authentication** -``` brush: +``` php $permissionResolver = $repository->getPermissionResolver(); $user = $userService->loadUserByCredentials( $username, $password ); $permissionResolver->setCurrentUserReference($user); @@ -817,7 +803,7 @@ Full code We will now see how to create Content using the Public API. This example will work with the default Folder (ID 1) Content Type from eZ Platform. -``` brush: +``` php /** @var $repository \eZ\Publish\API\Repository\Repository */ $repository = $this->getContainer()->get( 'ezpublish.api.repository' ); $contentService = $repository->getContentService(); @@ -831,7 +817,7 @@ We first need the required services. In this case: `ContentService`, `LocationSe As explained in [eZ Platform Public PHP API](eZ-Platform-Public-PHP-API_31429583.html), Value Objects are read only. Dedicated objects are provided for Update and Create operations: structs, like `ContentCreateStruct` or `UpdateCreateStruct`. In this case, we need to use a `ContentCreateStruct`.  -``` brush: +``` php $contentType = $contentTypeService->loadContentTypeByIdentifier( 'article' ); $contentCreateStruct = $contentService->newContentCreateStruct( $contentType, 'eng-GB' ); ``` @@ -840,7 +826,7 @@ We first need to get the [`ContentType`](http://apidoc.ez.no/sami/trunk/NS/html/ ### Setting the fields values -``` brush: +``` php $contentCreateStruct->setField( 'title', 'My title' ); $contentCreateStruct->setField( 'intro', $intro ); $contentCreateStruct->setField( 'body', $body ); @@ -852,19 +838,19 @@ The ` ContentCreateStruct::setField() ` method can take several ty In any case, whatever the Field Type is, a Value of this type can be provided. For instance, a TextLine\\Value can be provided for a TextLine\\Type. Depending on the Field Type implementation itself, more specifically on the `fromHash()` method every Field Type implements, various arrays can be accepted, as well as primitive types, depending on the Type. -### Setting the Location +## Setting the Location In order to set a Location for our object, we must instantiate a [`LocationCreateStruct`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/Values/Content/LocationCreateStruct.html). This is done with `LocationService::newLocationCreateStruct()`, with the new Location's parent ID as an argument. -``` brush: +``` php $locationCreateStruct = $locationService->newLocationCreateStruct( 2 ); ``` -### Creating and publishing +## Creating and publishing To actually create our Content in the Repository, we need to use `ContentService::createContent()`. This method expects a `ContentCreateStruct`, as well as a `LocationCreateStruct`. We have created both in the previous steps. -``` brush: +``` php $draft = $contentService->createContent( $contentCreateStruct, array( $locationCreateStruct ) ); $content = $contentService->publishVersion( $draft->versionInfo ); ``` @@ -881,14 +867,14 @@ Full code We will now see how the previously created Content can be updated. To do so, we will create a new draft for our Content, update it using a [`ContentUpdateStruct`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/Values/Content/ContentUpdateStruct.html), and publish the updated Version. -``` brush: +``` php $contentInfo = $contentService->loadContentInfo( $contentId ); $contentDraft = $contentService->createContentDraft( $contentInfo ); ``` To create our draft, we need to load the Content item's ContentInfo using `ContentService::loadContentInfo()`. We can then use `ContentService::createContentDraft()` to add a new Draft to our Content. -``` brush: +``` php // instantiate a content update struct and set the new fields $contentUpdateStruct = $contentService->newContentUpdateStruct(); $contentUpdateStruct->initialLanguageCode = 'eng-GB'; // set language for new version @@ -898,7 +884,7 @@ $contentUpdateStruct->setField( 'body', $newBody ); To set the new values for this version, we request a `ContentUpdateStruct` from the `ContentService` using the `newContentUpdateStruct()` method. Updating the values hasn't changed: we use the `setField()` method. -``` brush: +``` php $contentDraft = $contentService->updateContent( $contentDraft->versionInfo, $contentUpdateStruct ); $content = $contentService->publishVersion( $contentDraft->versionInfo ); ``` @@ -911,7 +897,7 @@ In the two previous examples, you have seen that we set the ContentUpdateStruct' **translating** -``` brush: +``` php $contentUpdateStruct->initialLanguageCode = 'ger-DE'; $contentUpdateStruct->setField( 'title', $newtitle ); $contentUpdateStruct->setField( 'body', $newbody ); @@ -921,7 +907,7 @@ It is possible to create or update content in multiple languages at once. There **update multiple languages** -``` brush: +``` php // set one language for new version $contentUpdateStruct->initialLanguageCode = 'fre-FR'; @@ -944,7 +930,7 @@ As explained above, the `setField()` method can accept various values: an instan We assume that we use the default image class. Creating our Content, using the Content Type and a ContentCreateStruct, has been covered above, and can be found in the full code. Let's focus on how the image is provided. -``` brush: +``` php $file = '/path/to/image.png'; $value = new \eZ\Publish\Core\FieldType\Image\Value( @@ -962,13 +948,13 @@ This time, we create our image by directly providing an [`Image\Value`](http://a Images also implement a static [`fromString()`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/Core/FieldType/Image/Value.html#method_fromString) method that will, given a path to an image, return an `Image\Value` object. -``` brush: +``` php $value = \eZ\Publish\Core\FieldType\Image\Value::fromString( '/path/to/image.png' ); ``` But as said before, whatever you provide `setField()` with is sent to the `acceptValue()` method. This method really is the entry point to the input formats a Field Type accepts. In this case, you could have provided setField with either a hash, similar to the one we provided the Image\\Value constructor with, or the path to your image, as a string. -``` brush: +``` php $contentCreateStruct->setField( 'image', '/path/to/image.png' );   // or @@ -991,7 +977,7 @@ Another very commonly used Field Type is the rich text one, `XmlText`. **working with xml text** -``` brush: +``` php $xmlText = <<< EOX
@@ -1012,14 +998,14 @@ Using a custom format as input More input formats will be added later. The API for that is actually already available: you simply need to implement the [`XmlText\Input`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/Core/FieldType/XmlText/Input.html) interface. It contains one method, [`getInternalRepresentation()`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/Core/FieldType/XmlText/Input.html#method_getInternalRepresentation), that must return an internal XML string. Create your own bundle, add your implementation to it, and use it in your code! -``` brush: +``` php $input = new \My\XmlText\CustomInput( 'My custom format string' ); $contentCreateStruct->setField( 'body', $input ); ``` ## Deleting Content -``` brush: +``` php $contentService->deleteContent( $contentInfo ); ``` @@ -1030,7 +1016,6 @@ Use with caution! # Working with Locations -Created by Dominika Kurek, last modified on Apr 22, 2016 ## Adding a new Location to a Content item @@ -1040,7 +1025,7 @@ Full code We have seen earlier how you can create a Location for a newly created `Content`. It is of course also possible to add a new [`Location`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/Values/Content/Location.html) to an existing `Content`. -``` brush: +``` php try { $locationCreateStruct = $locationService->newLocationCreateStruct( $parentLocationId ); @@ -1062,7 +1047,7 @@ catch ( \eZ\Publish\API\Repository\Exceptions\UnauthorizedException $e ) This is the required code. As you can see, both the ContentService and the LocationService are involved. Errors are handled the usual way, by intercepting the Exceptions the used methods may throw. -``` brush: +``` php $locationCreateStruct = $locationService->newLocationCreateStruct( $parentLocationId ); ``` @@ -1070,13 +1055,13 @@ Like we do when creating a new Content item, we need to get a new `LocationCreat In this example, we use the default values for the various `LocationCreateStruct` properties. We could of course have set custom values, like setting the Location as hidden ($location->hidden = true), or changed the remoteId (`$location->remoteId = $myRemoteId`). -``` brush: +``` php $contentInfo = $contentService->loadContentInfo( $contentId ); ``` To add a Location to a Content item, we need to specify the Content, using a [`ContentInfo`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/Values/Content/ContentInfo.html) object. We load one using `ContentService::loadContentInfo()`, using the Content ID as the argument. -``` brush: +``` php $newLocation = $locationService->createLocation( $contentInfo, $locationCreateStruct ); ``` @@ -1090,7 +1075,7 @@ Full code We mentioned earlier that a Location's visibility could be set while creating the Location, using the hidden property of the LocationCreateStruct. Changing a Location's visibility may have a large impact in the Repository: doing so will affect the Location's subtree visibility. For this reason, a `LocationUpdateStruct` doesn't let you toggle this property. You need to use the `LocationService` to do so. -``` brush: +``` php $hiddenLocation = $locationService->hideLocation( $location ); $unhiddenLocation = $locationService->unhideLocation( $hiddenLocation ); ``` @@ -1103,13 +1088,13 @@ The explanation above is valid for most Repository objects. Modification of prop Deleting Locations can be done in two ways: delete, or trash.  -``` brush: +``` php $locationService->deleteLocation( $locationInfo ); ``` [`LocationService::deleteLocation()`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/LocationService.html#method_deleteLocation) will permanently delete the Location, as well as all its descendants. Content that has only one Location will be permanently deleted as well. Those with more than one won't be, as they are still referenced by at least one Location. -``` brush: +``` php $trashService->trash( $locationInfo ); ``` @@ -1121,7 +1106,7 @@ The `TrashService` can be used to list, restore and delete Locations that were p This is done using the `ContentService`, by updating the `ContentInfo` with a `ContentUpdateStruct` that sets the new main location: -``` brush: +``` php $repository = $this->getContainer()->get( 'ezpublish.api.repository' ); $contentService = $repository->getContentService(); $contentInfo = $contentService->loadContentInfo( $contentId ); @@ -1137,7 +1122,6 @@ Credits to [Gareth Arnott](https://doc.ez.no/display/~arnottg) for the snippet. # Other recipes -Created by Dominika Kurek, last modified on Apr 22, 2016 ## Assigning Section to content @@ -1149,7 +1133,7 @@ The Section that a Content item belongs to can be set during creation, using the **assign section to content** -``` brush: +``` php $contentInfo = $contentService->loadContentInfo( $contentId ); $section = $sectionService->loadSection( $sectionId ); $sectionService->assignSection( $contentInfo, $section ); @@ -1159,7 +1143,7 @@ This operation involves the `SectionService`, as well as the `ContentService`. **assign section to content** -``` brush: +``` php $contentInfo = $contentService->loadContentInfo( $contentId ); ``` @@ -1167,7 +1151,7 @@ We use `ContentService::loadContentInfo()` to get the Content we want to update **assign section to content** -``` brush: +``` php $section = $sectionService->loadSection( $sectionId ); ``` @@ -1175,7 +1159,7 @@ $section = $sectionService->loadSection( $sectionId ); **assign section to content** -``` brush: +``` php $sectionService->assignSection( $contentInfo, $section ); ``` @@ -1193,7 +1177,7 @@ Creating a `ContentType` is actually almost more complex than creating Content. Let's split the code in three major parts. -``` brush: +``` php try { $contentTypeGroup = $contentTypeService->loadContentTypeGroupByIdentifier( 'content' ); @@ -1227,7 +1211,7 @@ Using the create struct's properties, we can set the Type's properties: The next big part is to add FieldDefinition objects to our Content Type. -``` brush: +```php // add a TextLine Field with identifier 'title' $titleFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct( 'title', 'ezstring' ); $titleFieldCreateStruct->names = array( 'eng-GB' => 'Title' ); @@ -1263,7 +1247,7 @@ Each field's properties are set using the create struct's properties: Once the properties for each create struct are set, the field is added to the Content Type create struct using [`ContentTypeCreateStruct::addFieldDefinition()`](http://apidoc.ez.no/sami/trunk/NS/html/eZ/Publish/API/Repository/Values/ContentType/ContentTypeCreateStruct.html#method_addFieldDefinition). -``` brush: +``` php try { $contentTypeDraft = $contentTypeService->createContentType( $contentTypeCreateStruct, array( $contentTypeGroup ) ); diff --git a/docs/api/rest_api_guide.md b/docs/api/rest_api_guide.md index a1885e911b..5d2a504a81 100644 --- a/docs/api/rest_api_guide.md +++ b/docs/api/rest_api_guide.md @@ -1,10 +1,8 @@ -1. [Developer](index.html) -2. [Documentation](Documentation_31429504.html) -3. [API](API_31429524.html) + # REST API Guide -Created by Dominika Kurek, last modified by David Christian Liedle on Jul 11, 2016 + The REST API v2 introduced in eZ Platform allows you to interact with an eZ Platform installation using the HTTP protocol, following a [REST](http://en.wikipedia.org/wiki/Representational_state_transfer) interaction model. @@ -52,33 +50,18 @@ Other headers will be used in HTTP requests for specifying the siteaccess to int Responses returned by the API will also use custom headers to indicate information about the executed operation. -  - -#### In this topic: - -- [Accessing the REST API](#RESTAPIGuide-AccessingtheRESTAPI) -- [Basics](#RESTAPIGuide-Basics) - - [Resources](#RESTAPIGuide-Resources) - - [HTTP verbs](#RESTAPIGuide-HTTPverbs) - - [Media type headers](#RESTAPIGuide-Mediatypeheaders) - - [Other headers](#RESTAPIGuide-Otherheaders) - -#### Related topics: - -- [REST API reference](REST-API-reference_31430594.html) -- [Getting started with the REST API](Getting-started-with-the-REST-API_31430289.html) # Getting started with the REST API -Created by Dominika Kurek, last modified on Apr 22, 2016 ## Installation -No special preparations are necessary to use the REST API. As long as your eZ Platform is correctly configured, the REST API is available on your site using the URI `/api/ezp/v2/`. If you have installed eZ Platform in a subfolder, prepend the path with this subfolder: http://example.com/**su****b/folder/ezpublish**/api/ezp/v2/. +No special preparations are necessary to use the REST API. As long as your eZ Platform is correctly configured, the REST API is available on your site using the URI `/api/ezp/v2/`. If you have installed eZ Platform in a subfolder, prepend the path with this subfolder: http://example.com/**sub/folder/ezpublish**/api/ezp/v2/. +!!! note Please note that the `/api/ezp/v2` prefix will be used in all REST hrefs, but not in URIs. ## Configuration @@ -91,7 +74,7 @@ To enable basic auth based authentication, you need to edit `app/config/security **security.yml** -``` brush: +```yaml security: # ... firewalls: @@ -114,7 +97,7 @@ One of the main reasons for this API is to help implement JavaScript / AJAX inte **REST API with JavaScript** -``` brush: +```javascript