eZ Platform Rich Text Custom Attributes
eZ Platform 2.x has evolved a lot - tons of great changes/improvements. But one vital feature is still missing: custom CSS classes and custom attributes. This could prevent a large number of eZ Publish 5.4 sites migrating to the latest eZ Platform version.
That's why we decided to help by submitting a few pull requests. Among them, are:
- EZP-29301: Added support for custom attributes on elements which extends eZ Platform schema and allows for the storage of custom attributes. It was merged in eZ Platform 2.5.1.
- Handled custom attributes when converting XmlText to RichText which allows running migrations from eZ Publish 5.4 to eZ Platform without custom attributes loss. It is going to be merged and released very soon.
So right now is possible to store custom attributes, and it will be possible to migrate them from eZ Publish 5.4 very soon. But there is no way to manage them in eZ Platform. eZ Systems plans to release this feature in upcoming 3.x.
In the meantime, ezplatform-custom-attributes solves this problem. It provides a way to set up custom classes and attributes. And it also brings the new UI to them in the Online Editor:
Installation
There is nothing special; you know the drill:
- Require
contextualcode/ezplatform-custom-attributes
viacomposer
:composer require contextualcode/ezplatform-custom-attributes
- Activate the bundle in
app/AppKernel.php
:$bundles = [ ... new ContextualCode\EzPlatformCustomAttributesBundle\EzPlatformCustomAttributesBundle(), ];
- Clear the caches:
php bin/console cache:clear
-
JavaScript translations are in use, so you need to dump them and run
encore
:php bin/console bazinga:js-translation:dump web/assets --merge-domains yarn encore dev
After the steps above, the installation is complete. You should now see the new "Elements Path" block in the Online Editor. You are able to click on any element in that block; if the clicked element has been defined to be able to have at least one custom class or attribute a new UI will be shown to edit them.
The next step is to configure custom classes and custom attributes.
Configuration
Custom classes and attributes are set up per each HTML element in the yml
configuration file. An example configuration looks like the following:
ezrichtext_extension:
custom_classes:
p: [p-class-1, p-class-2, p-class-3]
table: [table-class-1, table-class-2]
a: [a-class-1, 'icon icon--upload']
custom_attributes:
tr:
hide:
type: checkbox
p:
max-length:
type: text
default: 80
pre:
language:
type: select
options: [javascript, php, java]
embed_views: [embed, list, block, custom-1, custom-2]
Custom Classes
For custom_classes
you just specify an HTML element and the array of its custom CSS classes.
Admin will be able to select multiple options from the dropdown.
You can define multiple classes separated by space as one selection option.
Custom Attributes
Similarly, for custom_attributes
, it is required to define custom attribute settings per each HTML element. There are following options:
-
type
possible values are:text
,textarea
,select
,checkbox
-
default
applicable only fortext
andtextarea
attributes -
options
is used only forselect
attributes, and it contains an array of possible options
Embed View Types
For embed_views
you just need to specify an array of possible embed view types.
Migration
If you are migrating from eZ Publish 5.4 and your content has a lot of custom classes and attributes, it might be very time-consuming to configure all of them. To simplify this task its better to use the ezplatform:generate-custom-attributes-configuration
command. This script will generate a configuration based on the content stored in the database. Example usage:
php bin/console ezplatform:generate-custom-attributes-configuration --config-file=src/AppBundle/Resources/config/custom_attributes.yml
Extracting Custom Classes from Rich Text fields
===============================================
2/2 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
Extracting Custom Attributes from Rich Text fields
==================================================
4/4 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
Extracting Embed Views from Rich Text fields
============================================
3/3 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
! [NOTE] Found 2 elements with custom classes: table, p
! [NOTE] Found 3 elements with custom attributes: tr, pre, p
! [NOTE] Found 2 elements with embed views: line, embed
[OK] Configurations are saved into "src/AppBundle/Resources/config/custom_attributes.yml"
After the custom classes/attributes and embed view types configuration is done you should see and be able to edit them in the Online Editor. At this point, you might want to make their labels more editor friendly. And it is done via translations.
Translations
We are using JavaScript translations (custom_attributes
translations domain). So all the custom class and attribute labels are translated on the client side.
To set up custom labels start with creating a custom_attributes.<LANGUAGE-CODE>.yaml
translation file in your bundle. A good example would be src/AppBundle/Resources/translations/custom_attributes.en.yaml
.
Then you need to add the actual labels there. Supported types are:
Custom Classes
- Class label, its translation message key should follow
options.<css-class-name>.label
pattern. Examples:options.p-class-1.label: 'Paragraph Class 1' options.p-class-2.label: 'Paragraph Class 2' options.p-class-3.label: 'Paragraph Class 3' options.table-class-1.label: 'Table Class 1' options.table-class-2.label: 'Table Class 2'
Custom Attributes
- Attribute title, the pattern is
attributes.<name>.label
. Examples:attributes.hide.label: 'Hide' attributes.max-length.label: 'Maximal Length' attributes.language.label: 'Language'
- Options labels (only for
select
type attributes), its key pattern isoptions.<option>.label
. Examples:options.javascript.label: 'JavaScript' options.php.label: 'PHP' options.java.label: 'Java'
Embed View Types
- View type label, the pattern is
embed.view..<view-identifier>
. Examples:embed.view.list: 'List' embed.view.block: 'Block' embed.view.custom-1: 'Custom 1' embed.view.custom-2: 'Custom 2'
Updating the Translations
Please note, every time after custom attributes translations are changed you need to dump them and run encore
:
php bin/console bazinga:js-translation:dump web/assets --merge-domains
yarn encore dev
So now the remaining part would be to handle the custom classes and attributes on the front-end.
Rendering
Custom Classes
There is nothing special about the rendering of custom classes on the front-end. They are set as a class
attribute on the corresponding HTML elements.
Custom Attributes
Custom attributes are rendered as data
attributes with an ezattribute-
prefix by default. So if for some element max-length
is set to 10
, on the front-end it will be rendered as data-ezattribute-max-length="10"
attribute. It works in most cases, but there are few ways to customize it.
XSL Stylesheets
One of the possible ways to implement advanced rendering for custom attributes is to use custom XSL stylesheets. This option is the best for performance, but it requires some extensive knowledge of XSL. Also, you need to be familiar with eZ Platform Rich Text schema. In this case, Rich Text content is modified at the stage when it is transformed from the format it is stored into the database to HTML5.
Example implementation:
- Define custom XSL Stylesheet:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:docbook="http://docbook.org/ns/docbook" exclude-result-prefixes="docbook" version="1.0"> <xsl:output indent="yes" encoding="UTF-8"/> <xsl:template match="docbook:tr[docbook:ezattribute[docbook:ezvalue[@key='hide' and text()='true']]]"/> </xsl:stylesheet>
- Notify eZ Platform about the custom XSL Stylesheet via
ezpublish.system.default.fieldtypes.ezrichtext.output_custom_tags
configuration parameter.
Rich Text Converter
Alternatively, you can use Rich Text Converters to implement advanced rendering for custom attributes. In this case, Rich Text content is manipulated in PHP, which makes easier to develop and debug it. Basically you define a new service with a ezpublish.ezrichtext.converter.output.xhtml5
tag, which implements EzSystems\EzPlatformRichText\eZ\RichText\Converter
interface. And that's all!
Example implementation:
- Create a new Rich Text Converter
-
Define it as a service with
ezpublish.ezrichtext.converter.output.xhtml5
tag
Embed View Types
After custom embed view type is set, add its settings into ezsettings.default.content_view_defaults
hash. And that's all.
Example
You can grab a working example of eZ Platform with ezplatform-custom-attributes from https://gitlab.com/contextualcode/ezplatform-custom-attributes-example. Please check out AppBundle
there. It has examples of all possible configurations and customizations in the scope of custom classes and attributes.
Highlights
There are no reasons why you can't start using ezplatform-custom-attributes right now, and then use the official Custom Attributes feature due to be released in eZ Platform 3.
-
First of all, we want to highlight that ezplatform-custom-attributes does not modify the Rich Text schema. This means you don't need to make any changes to your data during your eZ Platform 3 upgrade. And you don't need to run any migration scripts.
-
Custom classes and attributes rendering is done by using built-in eZ Platform functionality. So if you implement it now, it should stay the same in eZ Platform 3.
-
The only thing that's going to be changed in eZ Platform 3 is the admin UI. An that point you can just disable this bundle and the new UI will be picked up.
-
The only part might need to be changed during eZ Platform 3 migrations is custom classes and attributes configurations. That's going to depend on the configuration format for custom classes and Attributes in eZ Platform 3.
So please have a try ezplatform-custom-attributes. We would love to hear your feedback. PRs and comments are very welcome!