Global navigation

   Documentation Center
   eZ Studio & eZ Platform
     User Manual
     Technical Manual
     Glossary
   eZ Publish 4.x / legacy

 
eZ Publish (5.x)

eZ Publish 5.x | For eZ Platform & eZ Studio topics see Technical manual and User manual, for eZ Publish 4.x and Legacy topics see eZ Publish legacy

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Table of Contents
The

In the following recipes show , you will see how to create simple content. As we don't want to rely on a specific installation with predefined content types we first show how to create a content type group and a simple content type within this group. Then we will create a content object of the newly created content type. The last two recipes show how to create content containing images and xml text.

Creating a content type group

This snippet creates a content type group for a given identifier (Full code here).

Code Block
languagephp
titlecreate content type group
linenumberstrue
        // get the services from the repsitory
        $contentTypeService = $repository->getContentTypeService();
        try
        {
            // instanciate a create struct and create the group
            $contentTypeGroupCreateStruct = $contentTypeService->newContentTypeGroupCreateStruct( $contentTypeGroupIdentifier );
            $contentTypeGroup =  $contentTypeService->createContentTypeGroup( $contentTypeGroupCreateStruct );
            print_r( $contentTypeGroup );
        }
        catch ( UnauthorizedException $e )
        {
            // react on permission denied
            $output->writeln( $e->getMessage() );
        }
        catch ( ForbiddenException $e )
        {
            // react on identifier already exists
            $output->writeln( $e->getMessage() );
        }
Info
titleused classes

 

If this snipped is run with the same init code from recipe 1 we will get an UnauthorizedException.

The solution is described in the next recipe.

Setting the user for authorizing actions

By default the repository assumes the anonymous user is acting. To change this the following code can be executedContent, including complex fields like XmlText or Image.

Identifying to the repository with a login and a password

As seen earlier, the Repository executes operations with a user's credentials. In a web context, the currently logged in user is automatically identified. In a command line context, you need to manually log a user in. We have already seen how to manually load and set a user using its ID. If you would like to identify a user using his username and password instead, this can be achieved as follows.

Code Block
languagephp
titleauthentication
        // set specific user
		$userService = $repository->getUserService();
        $user = $userService->loadUserByCredentials( $user, $password );
        $repository$repository->setCurrentUser( $user );

If the user is identified by other mechanisms the user also can be loaded by its id via the service method

$userService->loadUser($id)

Creating content

Info
titleused classes

Creating a content type

...

Full code

https://github.com/ezsystems/CookbookBundle/blob/master/Command/CreateContentCommand.php

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 Publish.

Code Block
languagephp
titlecreate content type
        // get the repository from the di container
        /** @var $repository \eZ\Publish\API\Repository\Repository */
$repository = $this->getContainer()->get( 'ezpublish.api.repository' );

        // get the services from the repsitory
        $contentTypeService $contentService = $repository->getContentTypeService>getContentService();
        $userService $locationService = $repository->getUserService>getLocationService();

        // load the admin user and set it has current user in the repository
        $user = $userService->loadUser( 14 );
        $repository->setCurrentUser( $user );

        // load the content type group
        try
        {
            $contentTypeGroup = $contentTypeService->loadContentTypeGroupByIdentifier( $groupIdentifier );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\NotFoundException $e )
        {
            $output->writeln( "content type group with identifier $groupIdentifier not found" );
            return;
        }

        // instanciate a ContentTypeCreateStruct with the given content type identifier and set parameters
        $contentTypeCreateStruct = $contentTypeService->newContentTypeCreateStruct( $contentTypeIdentifier );
        $contentTypeCreateStruct->mainLanguageCode = 'eng-GB'; // the main language code for names and description
        $contentTypeCreateStruct->nameSchema = '<title>'; // the name schema for generating the content name by using the title attribute

        // set names for the content type
        $contentTypeCreateStruct->names = array(
            'eng-GB' => $contentTypeIdentifier . 'eng-GB',
            'ger-DE' => $contentTypeIdentifier . 'ger-DE',
        );

        // set description for the content type
        $contentTypeCreateStruct->descriptions = array(
            'eng-GB' => 'Description for ' . $contentTypeIdentifier . 'eng-GB',
            'ger-DE' => 'Description for ' . $contentTypeIdentifier . 'ger-DE',
        );

        /********************** add fields ***************************************/

        // add a title field
        $titleFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct( 'title', 'ezstring' );
        $titleFieldCreateStruct->names = array( 'eng-GB' => 'Title', 'ger-DE' => 'Titel' ); // set names
        $titleFieldCreateStruct->descriptions = array( 'eng-GB' => 'The Title', 'ger-DE' => 'Der Titel' ); // set descriptions
        $titleFieldCreateStruct->fieldGroup = 'content'; // set an group for the field definition
        $titleFieldCreateStruct->position = 10; // set position inside the content type
        $titleFieldCreateStruct->isTranslatable = true; // enable translation
        $titleFieldCreateStruct->isRequired = true; // require this field to set on content creation
        $titleFieldCreateStruct->isSearchable = true; // enabled to find field via content search

        $contentTypeCreateStruct->addFieldDefinition( $titleFieldCreateStruct );

        // add a body field
        $bodyFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct( 'body', 'ezstring' );
        $bodyFieldCreate->names = array( 'eng-GB' => 'Body', 'ger-DE' => 'Text' );
        $bodyFieldCreate->descriptions = array( 'eng-GB' => 'Description for Body', 'ger-DE' => 'Beschreibung Text' );
        $bodyFieldCreate->fieldGroup = 'content';
        $bodyFieldCreate->position = 20;
        $bodyFieldCreate->isTranslatable = true;
        $bodyFieldCreate->isRequired = true;
        $bodyFieldCreate->isSearchable = true;

        $contentTypeCreateStruct->addFieldDefinition( $bodyFieldCreate );

        // set the content type group for the content type
        $groups = array( $contentTypeGroup );
        try
        {
            // create the content type draft and publish it
            $contentTypeDraft = $contentTypeService->createContentType( $contentTypeCreateStruct,$groups );
            $contentTypeService->publishContentTypeDraft( $contentTypeDraft );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\UnauthorizedException $e )
        {
            // react on permission denied
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\ForbiddenException $e )
        {
            // react on identifier already exists
            $output->writeln( $e->getMessage() );
        }
        catch( \Exception $e )
        {
            $output->writeln( $e->getMessage() );
        }
    }
Info
titleused classes

 

Creating content

In this recipe content is created under a given parent location. It is assumed that the loaded content type is the one created in recipe 4. (Full code here).

Code Block
languagephp
titlecreate content
        // get the repository from the di container
        $repository = $this->getContainer()->get( 'ezpublish.api.repository' );

        // get the services from the repsitory
        $contentService = $repository->getContentService();
        $locationService = $repository->getLocationService();
        $contentTypeService = $repository->getContentTypeService();
        $userService = $repository->getUserService();

        // load the admin user and set it has current user in the repository
        $user = $userService->loadUser( 14 );
        $repository->setCurrentUser( $user );
        try
        {
            // load the content type and instanciate a content create struct and set title and body fields
            $contentType = $contentTypeService->loadContentTypeByIdentifier( $contentTypeIdentifier );
            $contentCreateStruct = $contentService->newContentCreateStruct( $contentType, 'eng-GB' );
            $contentCreateStruct->setField( 'title', $title );
            $contentCreateStruct->setField( 'body', $body );

            // instanciate a location create struct from the parent location
            $locationCreateStruct = $locationService->newLocationCreateStruct( $parentLocationId );

            // create a draft using the content and location create structs and publish it
            $contentTypeService = $repository->getContentTypeService();

We first need the required services. In this case: ContentService, LocationService and ContentTypeService.

The ContentCreateStruct

As explained in the Public API Basics, 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. 

Code Block
languagephp
$contentType = $contentTypeService->loadContentTypeByIdentifier( 'article' );
$contentCreateStruct = $contentService->newContentCreateStruct( $contentType, 'eng-GB' );

We first need to get the ContentType we want to create a Content with. To do so, we use ContentTypeService::loadContentTypeByIdentifier(), with the wanted ContentType identifier, like 'article'. We finally get a ContentTypeCreateStruct using ContentService::newContentCreateStruct(), providing the ContentType and a Locale Code (eng-GB).

Setting the fields values

Code Block
languagephp
$contentCreateStruct->setField( 'title', 'My title' );
$contentCreateStruct->setField( 'intro', $intro );
$contentCreateStruct->setField( 'body', $body );

Using our create struct, we can now set the values for our Content's fields, using the setField() method. For now, we will just set the title. setField() for a TextLine Field simply expects a string as input argument. More complex FieldTypes, like Author or Image, expect different input values.

Note

The ContentCreateStruct::setField() method can take several type of arguments.

In any case, whatever the FieldType is, a Value of this type can be provided. For instance, a TextLine\Value can be provided for a TextLine\Type. Depending on the FieldType implementation itself, more specifically on the fromHash() method every FieldType implements, various arrays can be accepted, as well as primitive types, depending on the Type.

Setting the Location

In order to set a Location for our object, we must instantiate a LocationCreateStruct. This is done with LocationService::newLocationCreateStruct(), with the new Location's parent ID as an argument.

Code Block
languagephp
$locationCreateStruct = $locationService->newLocationCreateStruct( 2 );

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.

Code Block
languagephp
$draft = $contentService->createContent( $contentCreateStruct, array( $locationCreateStruct ) );
            $content = $contentService->publishVersion( $draft->versionInfo );
            print_r( $content );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\NotFoundException $e )
        {
            // react on content type or location not found
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $e )
        {
            // react on a field is not valid
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\ContentValidationException $e )
        {
            // react on a required field is missing or empty
            $output->writeln( $e->getMessage() );
        }
    }
Info
titleused classes

 

Updating Content

In this recipe the previously created content is updated with a new title and body in the same language. (Full code here)

Code Block
languagephp
titleupdate content
         try
        {
            // create a content draft from the current published version
            

The LocationCreateStruct is provided as an array, since a Content can have multiple locations.

createContent() returns a new Content Value Object, with one version that has the DRAFT status. To make this Content visible, we need to publish it. This is done using ContentService::publishVersion(). This method expects a VersionInfo object as its parameter. In our case, we simply use the current version from $draft, with the versionInfo property.

Updating Content

Info
titleFull code

https://github.com/ezsystems/CookbookBundle/blob/master/Command/UpdateContentCommand.php

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, and publish the updated Version.

Code Block
languagephp
$contentInfo = $contentService->loadContentInfo( $contentId );
            $contentDraft = $contentService->createContentDraft( $contentInfo );

            // instanciate

To create our draft, we need to load the Content's ContentInfo using ContentService::loadContentInfo(). We can then use ContentService::createContentDraft() to add a new Draft to our Content.

Code Block
languagephp
// instantiate a content update struct and set the new fields
            $contentUpdateStruct = $contentService->newContentUpdateStruct();
            $contentUpdateStruct->initialLanguageCode = 'eng-GB'; // set language for new version
            $contentUpdateStruct->setField( 'title', $newtitle$newTitle );
            $contentUpdateStruct->setField( 'body', $newbody );

            // update and publish draft
            $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.

Code Block
languagephp
$contentDraft = $contentService->updateContent( $contentDraft->versionInfo, $contentUpdateStruct );
            $content = $contentService->publishVersion( $contentDraft->versionInfo );
            print_r( $content );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\NotFoundException $e )
        {
            // react on content not found
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $e )
        {
            // react on a field is not valid
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\ContentValidationException $e )
        {
            // react on a required field is missing or empty
            $output->writeln( $e->getMessage() );
        }
    }
Info
titleused classes

Translating content

...

We can now use ContentService::updateContent() to apply our ContentUpdateStruct to our draft's VersionInfo. Publishing is done exactly the same way as for a new content, using ContentService::publishVersion().

Handling translations

In the two previous examples, you have seen that we set the ContentUpdateStruct's initialLanguageCode property. To translate an object to a new language, set the locale to a new one.

Code Block
languagephp
titletranslating
            // set language for new version
            $contentUpdateStruct->initialLanguageCode = $newLanguage;
            // set fields
            'ger-DE';
$contentUpdateStruct->setField( 'title', $newtitle );
            $contentUpdateStruct->setField( 'body', $newbody );

Multiple translations at once

It is possible to to make an create or update in content  or create content with more than one language. But there is a restriction - content in multiple languages at once. There is one restriction: only one language can be assigned to the newly created version (which is displayed in the 4.x admin GUI in the translations column)set a version's language. This language is the one that will get a flag in the back office. However, you can set values in other languages for your attributes, using the setField method's third argument.

Code Block
languagephp
titleupdate multiple languages
            // set one language for new version
            $contentUpdateStruct->initialLanguageCode = 'frafre-FR';
			//
set fields for german - here the language has to be passed in third argument
            $contentUpdateStruct->setField( 'title', $newgermantitle, 'ger-DE' );
            $contentUpdateStruct->setField( 'body', $newgermanbody, 'ger-DE' );

           // set fields for french
            $contentUpdateStruct->setField( 'title', $newfrenchtitle );
            $contentUpdateStruct->setField( 'body', $newfrenchbody );


Since we don't specify a locale for the last two fields, they are set for the UpdateStruct's initialLanguageCode, fre-FR.

Creating Content containing an image

This recipe shows how to create an  content object containing an image. (Full code here)

// get the repository from the di container $repository = $this->getContainer()->get( 'ezpublish.api.repository' ); // get the services from the repsitory $contentService = $repository->getContentService(); $locationService = $repository->getLocationService(); $userService = $repository->getUserService(); $contentTypeService = $repository->getContentTypeService(); // load the admin user and set it has current user in the repository $user = $userService->loadUser( 14 ); $repository->setCurrentUser( $user ); try { // load the image content type and instanciate a content create struct $contentType = $contentTypeService->loadContentTypeByIdentifier( "image" ); $contentCreateStruct = $contentService->newContentCreateStruct( $contentType, 'eng-GB' ); $contentCreateStruct->setField('name',$name); // set name field // set image file field
Code Block
languagephp
titlecreating an image
Info
titleFull code

https://github.com/ezsystems/CookbookBundle/blob/master/Command/CreateImageCommand.php

As explained above, the setField() method can accept various values: an instance of the FieldType's Value class, a primitive type, or a hash. The last two depend on what the Type::acceptValue() method is build up to handle. TextLine can, for instance, accept a simple string as an input value. In this example, you will see how to set an Image value.

We assume that we use the default image class. Creating our Content, using the ContentType and a ContentCreateStruct, has been covered above, and can be found in the full code. Let's focus on how the image is provided.

Code Block
languagephp
$file = '/path/to/image.png';

$value = new \eZ\Publish\Core\FieldType\Image\Value(
                array(
                    'path' => $file'/path/to/image.png',
                    'fileSize' => filesize($file '/path/to/image.png' ),
                    'fileName' => basename($file 'image.png' ),
                    'alternativeText' => $name'My image'
               )
            );
            $contentCreateStruct->setField( 'image' , $value );

            // instanciate a location create struct and create and publish the content
            $locationCreateStruct = $locationService->newLocationCreateStruct( $parentLocationId );
            $draft = $contentService->createContent( $contentCreateStruct,array( $locationCreateStruct ) );
            $content = $contentService->publishVersion( $draft->versionInfo );
            print_r( $content );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\NotFoundException $e )
        {
            // react on content type or location not found
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException $e )
        {
            // react on remote id exists already
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $e )
        {
            // react on a field is not valid
            $output->writeln( $e->getMessage() );
        }
        catch( \eZ\Publish\API\Repository\Exceptions\ContentValidationException $e )
        {
            // react on a required field is missing or empty
            $output->writeln( $e->getMessage() );
        }
    }

 

Create Content with XML Text

...

This time, we create our image by directly providing an Image\Value object. The values are directly provided to the constructor using a hash with predetermined keys that depend on each Type. In this case: the path where the image can be found, its size, the file name, and an alternative text.

Images also implement a static fromString() method that will, given a path to an image, return an Image\Value object.

Code Block
languagephp
$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 FieldType 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.

Code Block
languagephp
$contentCreateStruct->setField( 'image', '/path/to/image.png' );
 
// or
 
$contentCreateStruct->setField( 'image', array(
    'path' => '/path/to/image.png',
    'fileSize' => filesize( '/path/to/image.png' ),
    'fileName' => basename( 'image.png' ),
    'alternativeText' => 'My image'
);

Create Content with XML Text

Info
titleFull code

https://github.com/ezsystems/CookbookBundle/blob/master/Command/CreateXMLContentCommand.php

Another very commonly used FieldType is the rich text one, XmlText.

Code Block
languagephp
titleworking with xml text
             // load a folder content type and instanciate a content creation struct
            $contentType = $contentTypeService->loadContentTypeByIdentifier( "folder" );
            $contentCreateStruct = $contentService->newContentCreateStruct( $contentType, "eng-GB" );
            $contentCreateStruct->setField( "name", $name ); // set name of the folder
            $xmltext = "$xmlText = <<< EOX
<?xml version='1.0' encoding='utf-8'?><section><paragraph>This>
<section>
<paragraph>This is a <strong>image test</strong></paragraph>
                        <paragraph><embed view='embed' size='medium' object_id='$imageId'/></paragraph><paragraph>
</section>"
EOX;
            $contentCreateStruct->setField( "description"'body', $xmltext$xmlText ); // set description of the folder

            // instanciate a location create struct and create and publsidh the content
            $locationCreateStruct = $locationService->newLocationCreateStruct( $parentLocationId );
            $draft = $contentService->createContent( $contentCreateStruct, array( $locationCreateStruct ) );
            $content = $contentService->publishVersion( $draft->versionInfo );
            print_r( $content );

As for the last example above, we use the multiple formats accepted by setField(), and provide our XML string as is. The only accepted format as of 5.0 is internal XML, the one stored in the Legacy database.

Info

The XSD for the internal XML representation can be found in the kernel: https://github.com/ezsystems/ezpublish-kernel/blob/master/eZ/Publish/Core/FieldType/XmlText/Input/Resources/schemas/ezxml.xsd.

We embed an image in our XML, using the <embed> tag, providing an image Content ID as the object_id attribute.

Note
titleUsing 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 interface. It contains one method, getInternalRepresentation(), that must return an internal XML string. Create your own bundle, add your implementation to it, and use it in your code!

Code Block
languagephp
$input = new \My\XmlText\CustomInput( 'My custom format string' );
$contentCreateStruct->setField( 'body', $input );

Deleting Content

 

Code Block
languagephp
$contentService->deleteContent( $contentInfo );

ContentService::deleteContent() method expects a ContentInfo as an argument. It will delete the given Content, all of its Locations, as well as all of the Content's Locations' descendants and their associated Content. Use with caution !