Declaring and modifying a content type


CMS Ametys supports different types of content (articles, news, photo galleries, FAQ, ...). The types of content available depend on the extensions (plugins) used.

The most commonly used content types are described in the User Manual.

A content type is a multiple extension point. An integrator can create new content types (seminar, job, etc.) according to your needs.

  1. General
  2. Icons or glyphs
  3. Attributes
    1. Simple declaration
    2. Validation
    3. Widget modification
    4. Composite attribute
    5. Enumerations
    6. Default values
    7. Restrictions
    8. Historical syntax
  4. The properties
    1. Referencing a model element
    2. Point to a class
  5. Global validation
  6. The views
    1. Syntax
    2. Attached views
    3. Simplified syntax
    4. View overload
    5. Mandatory and optional views
    6. Historical syntax
  7. Tags
  8. Multiple inheritance
  9. Specific types of content
    1. The roles
    2. Reference tables
    3. Private content type
    4. Abstract content type
  10. Defining a new content type
    1. Definition in the WEB-INF/param/content-types directory
    2. Definition in a plugin
  11. Modifying an existing content type
    1. Modification of the WEB-INF/param/content-types/_override directory
    2. Modification in a plugin
    3. Order in which overloads are taken into account
  12. Examples of content type declarations
    1. Complete example of a simple content type declaration
    2. Examples of simple content type modifications
  13. Indexing and searching
    1. Fulltext system property
    2. Facets
  14. Graphic rendering

 

General

A content type is defined by:

  • A unique identifier
  • A wording
  • A description
  • The default title for content of this type
  • Icons, glyphs or 16x16, 32x32 and 48x48 pixel icons
  • A right (optional) to restrict the creation of the type of content to those entitled to it
  • A set of typed attributes (e.g. title, description, image, files, date, etc.).
  • Properties (optional)
  • Des validateurs globaux (optionnel) pour définir des règles de validation entre plusieurs éléments (ex: startDate < endDate)
  • Views

Each view defines the list of attributes and properties it requires, from among the attributes and properties of the contained type. For example, an "abstract" view will need the title and illustration attributes, while a "main" view will need all attributes.

A content type is an extension point of type org.ametys.cms.contenttype.ContentTypeExtensionPoint. The declaration must comply with the following XML format:

XML content type declaration format

<extension point="org.ametys.cms.contenttype.ContentTypeExtensionPoint"
          id="org.ametys.web.default.Content.article"
          class="org.ametys.cms.contenttype.DefaultContentType">

   <content-type>
       <label i18n="true">CONTENT_ARTICLE_LABEL</label>
       <description i18n="true">CONTENT_ARTICLE_DESCRIPTION</description>
       <default-title i18n="true">CONTENT_ARTICLE_DEFAULT_TITLE</default-title>
       <icons>
            <glyph>ametysicon-text70</glyph>
           <small>img/content/article/icon-small.png</small>
           <medium>img/content/article/icon-medium.png</medium>
           <large>img/content/article/icon-large.png</large>
       </icons>

       <right>Web_Right_Article_Create</right>

<!-- Déclaration des attributs ici -->

<!-- Déclaration des propriétés ici -->

<!-- Déclaration des validateurs globaux ici -->

<!-- Déclaration des vues ici -->

   </content-type>
</extention>

Icons or glyphs

You can represent your content type either :

  • with 3 icons of 16x16, 32x32 and 48x48 pixel sizes 
<icons>
   <small>img/content/article/icon-small.png</small>
   <medium>img/content/article/icon-medium.png</medium>
   <large>img/content/article/icon-large.png</large>
</icons>
  • with a pictogram (glyph)

If you choose a glyph, remember to add the CSS file in which the glyph is defined.

<icons>
   <glyph>ametysicon-text70</glyph>
</icons>
<css>
    <file plugin="core-ui">font/ametys/AmetysIcon.css</file>
</css>

The glyph (or the "medium" icon if there is no glyph), as well as the label and description, are used for the "Add content" menu.

The glyph is also used when inserting content into a page and in search engine results. (In these 2 cases, if the glyph is not present, the "small" icon is used.

Attributes

Attributes are classic parameters as described on the Parameters general page, with a few variations and additional elements.

SinceAmetys 4.7, two syntaxes have coexisted:
- the classic syntax, detailed below,
- and the historical syntax, presented in a separate §.
It is possible to declare certain attributes with the classic syntax and others with the historical syntax.

Simple declaration

Like any parameter, an attribute has at least a unique name, a label, a description and a type (string, date, long, ...) and is declared as follows in the tag <cms:metadata>:

Example of the declaration of a "Title" string attribute, mandatory

<attribute name="title" type="string">
    <label i18n="true">CONTENT_ARTICLE_TITLE</label>
    <description i18n="true">CONTENT_ARTICLE_TITLE_DESC</description>
    <validation>
        <mandatory />
    </validation>
</attribute>

See list of types available for an attribute.

Validation

Instruction <validation> allows you to define validation rules for an attribute:

  • <mandatory> to make the attribute mandatory
  • <regexp> to define a regular expression
  • <invalidText> to personalize the message in the event of incorrect input (regular expression not respected)
  • <custom-validator> java class implementing the org.ametys.runtime.util.parameter.Validator to define your own validator
    • For example org.ametys.runtime.util.parameter.TextValidator for simple text fields or org.ametys.runtime.plugins.core.util.parameter.RichTextValidator for rich fields, support a

  • <maxlength> for a maximum supported number of characters

 

Example of validation for a mandatory "address mail" field

<validation>
    <custom-validator class="org.ametys.runtime.plugins.core.util.parameter.TextValidator"> 
        <maxlength>60</maxlength>
        <mandatory/>
        <regexp>^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z0-9][A-Za-z0-9]+)$</regexp>
        <invalidText i18n="true">PLUGINS_WEB_REGEXP_INVALID_MAIL</invalidText>
    </custom-validator>
</validation>

See further examples on the Parameter overview page, chapter "Validation".

Widget modification

It is possible to specify a "widgetFor example, for an attribute of type "string", you can use "edition.textarea" to modify the attribute on several lines. For example, for an attribute of type "string", you can use widget "edition.textarea" to modify the attribute on several lines.
The widget tag is used for this purpose. <widget> as in the example below:

Example of a widget

<attribute name="abstract" type="string">
    <label i18n="false">CONTENT_ARTICLE_ABSTRACT</label>
    <description i18n="true">CONTENT_ARTICLE_ABSTRACT_DESC</description>
    <widget>edition.textarea</widget>
</attribute>

See the list of editing widgets available for content attributes.

Composite attribute

An attribute can be "composite", i.e. composed of other attributes. For example, an illustration is composed of a file and an alternative text.

Example of a composite attribute declaration

<attribute name="illustration" type="composite">
    <label i18n="true">CONTENT_ARTICLE_ILLUSTRATION</label>
    <description i18n="true">CONTENT_ARTICLE_ILLUSTRATION_DESC</description>
   <attribute name="image" type="file">
        <label i18n="true">CONTENT_ARTICLE_IMAGE</label>
        <description i18n="true">CONTENT_ARTICLE_IMAGE_DESC</description>
        <widget>external-or-resource-image</widget>
   </attribute>
   <attribute name="alt-text" type="string">
        <label i18n="true">CONTENT_ARTICLE_IMAGE_ALT</label>
        <description i18n="true">CONTENT_ARTICLE_IMAGE_ALT_DESC</description>
   </attribute>
</attribute>

Multiple composite attributes can be defined, i.e. they can be repeated as many times as required. For example, to be able to add 0 to n attachments to a content item. These are known as "repeaters".

Example of a repeater declaration

<attribute name="attachments" type="repeater" initial-size="0">
    <label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILES</label>
    <description i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILES_DESC</description>
   <add-label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_ADD</cms:add-label>
   <del-label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_DEL</cms:del-label>
   <attribute name="attachment" type="file">
        <label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE</label>
        <description i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_DESC</description> 
   </attribute> 
   <attribute name="attachment-text" type="string">
        <label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_TEXT</label>
        <description i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_TEXT_DESC</description> 
   </attribute> 
</attribute>

- add-label redefines the tooltip of the add button ("Add entry" by default)
- del-label redefine the tooltip of the delete button ("Delete an entry" by default)

-header-label permet de mettre un libellé personnalisé à chaque entrée du repeater.
  La valeur est une phrase qui va référencer les valeurs des champs du repeater avec la syntaxte {field}.
  Par exemple ici: {amout} € du {date} {sent:pick("", "(envoyée)")}

  entre les {} il faut mettre l'identifiant du champ, et facultativement une fonction à lui appliquer à choisir dans Ext.util.Format 
  Voici quelques exemples :
  * {date:date("c")} où "c" est un format de date à choisir dans Ext.Date 
  * {datetime:pick("", " - ")}{datetime} pour préfixer le datetime de " - " si il est non vide
  * {linkArticle:or("[Aucun]")} pour écrire "[Aucun]" si la valeur est vide
  * {boolean:pick("Faux", "Vrai")} pour un boolean

Enumerations

An enumerated attribute can take a value from a defined list: a static or dynamic list.

See parameter generality for writing a static list of values.

Default values

It is possible to define default values for an attribute. See general information on parameters.

For content attributes that specify a target content type, the default value can be of type "attribute". This allows you to search for the first content whose attribute has a particular value.

The target attribute cannot be in a composite or in a repeater, and must be of type string, long or double. 

Example:

The definition below defines the default French value for the "Language of instruction" attribute (value taken from a reference table).  

<attribute name="teachingLanguage" type="content" contentType="odf-enumeration.Language" multiple="true">
    <label i18n="true">PLUGINS_ODF_COURSE_TEACHINGLANG</label>
    <description i18n="true">PLUGINS_ODF_COURSE_TEACHINGLANG_DESC</description>
   <widget>edition.select-referencetable-content</widget>
   <default-value type="attribute" name="code">fr</default-value>
</attribute>

Restrictions

It is possible to define read and/or write restrictions on attributes.

The restrictions can be of several kinds:

  • read or read/write restriction
  • right-based read or read/write restriction
  • read or read/write restriction based on workflow status

Read or read/write restriction

<attribute name="typology" type="string">
    <label i18n="false">Typologie</label>
    <description i18n="false">Typologie de projet</description>
   <restrict-to>
       <cannot read-write-direction="write"/>
   </restrict-to>
</attribute>

In this configuration, if the read-write-direction is worth:

  • write: the contributor can see the attribute, but cannot modify it (read-only access)
  • read: the contributor can neither view nor modify the attribute

Right-based read or read/write restriction

<attribute name="typology" type="string">
    <label i18n="false">Typologie</label>
    <description i18n="false">Typologie de projet</description>
   <restrict-to>
       <right id="Web_Right_SuperEdit" read-write-direction="write"/>
   </restrict-to>
</attribute>

In this configuration,

  • the <right> determines the right of the contributor
  • if the read-write-direction is worth :
    • write: the contributor can only modify the attribute if he has the "Web_Right_SuperEdit" right; otherwise, he will have read-only access to the attribute.
    • read: the contributor will have read/write access to the attribute only if he/she has the "Web_Right_SuperEdit" right

Read or read/write restriction based on workflow state

<attribute name="typology" type="string">
    <label i18n="false">Typologie</label>
    <description i18n="false">Typologie de projet</description>
   <restrict-to>
       <workflow step="2" read-write-direction="write"/>
       <workflow step="3" read-write-direction="read"/>
   </restrict-to>
</attribute>

In this configuration,

  • the <workflow> determines the workflow state affected by the restriction
  • if the read-write-direction is worth :
    • write: the contributor can only modify the attribute if the content is currently in the defined workflow state
    • read: the contributor will only have read/write access to the attribute if the content is currently in the defined workflow state

Restrictions on multiple composites (repeater)

The restrictions described above may also apply to repeaters.

<attribute name="photos" type="repeater" initial-size="0">
    <label i18n="false">Photos</label>
    <description i18n="false">Photos</description>
   <add-label i18n="false">Ajouter une photos</add-label>
   <del-label i18n="false">Supprimer la photos</del-label>
   <restrict-to>
       <right read-write-direction="write" id="Web_Right_SuperEdit"/>
   </restrict-to>
   <attribute name="image" type="file">
        <label i18n="false">Fichier</label>
        <description i18n="false">Fichier image</description>
   </attribute>
   <attribute name="legend" type="string">
        <label i18n="false">Légende</label>
        <description i18n="false">Légende</description>
   </attribute>
</attribute>

If a contributor does not have write access to a repeater, then he/she will not be able to add, delete or move entries in the repeater.

Historical syntax

It's possible to do exactly the same things with historical syntax. The only differences are as follows:

  • We use the keyword metadata rather than attribute
  • Except for repeaters, for which we use the keyword repeater without having to specify a type.

Example of a "Title" attribute declaration using historical syntax

<metadata name="title" type="string">
    <label i18n="true">CONTENT_ARTICLE_TITLE</label>
    <description i18n="true">CONTENT_ARTICLE_TITLE_DESC</description>
    <validation>
        <mandatory />
    </validation>
</metadata>

Example of a repeater declaration using historical syntax

<repeater name="attachments" initial-size="0">
  <label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILES</label>
  <description i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILES_DESC</description>
  <add-label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_ADD</add-label>
  <del-label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_DEL</del-label>
  <metadata name="attachment" type="file">
        <label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE</label>
        <description i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_DESC</description> 
  </metadata> 
  <metadata name="attachment-text" type="string">
        <label i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_TEXT</label>
        <description i18n="true">PLUGINS_ODF_PROGRAM_ATTACHED_FILE_TEXT_DESC</description> 
  </metadata> 
</metadata>

The properties

A property is a data item whose value is calculated from content data.

It can either refer to another element of the model (attribute or property), or point to a class that will perform more complex calculations.

Properties only available since version 4.6

Referencing a model element

To reference a model element, the property declaration must indicate the path to that element:

<property name="zipcode" path="address/zipcode" />

A property can reference a model element to remote content. In the following example, linked-content is a content attribute of the content type being declared:

<property name="linked-title" path="linked-content/title" />
<property name="linked-creator" path="linked-content/creator" />

Point to a class

You can also create a more complex property by creating a class java and declaring a property that points to this class. For example, in project spaces, brief objects have a pinned property, which determines whether the brief object is tagged with the 'pin' label:

<property name="pinned" class="org.ametys.plugins.workspaces.wall.PinProperty">
   <label i18n="true">plugin.workspaces:PLUGINS_WORKSPACES_WALL_CONTENT_PIN_LABEL</label>
   <description i18n="true">plugin.workspaces:PLUGINS_WORKSPACES_WALL_CONTENT_PIN_DESC</description>
</property>

Global validation

The <global-validators> allows you to define validation rules between several attributes. You can define your own global validator by implementing the org.ametys.cms.contentype.ContentValidator. Des validateurs ermettant de vérifier les intervalles entre 2 attributs existent déjà dans Ametys :

  • org.ametys.cms.contenttype.validation.DateIntervalValidator pour vérifier l'intervalle entre 2 attributs de type date,
  • org.ametys.cms.contenttype.validation.DateTimeIntervalValidator pour vérifier l'intervalle entre 2 attributs de type datetime,
  • org.ametys.cms.contenttype.validation.LongIntervalValidator pour vérifier l'intervalle entre 2 attributs de type long,
  • org.ametys.cms.contenttype.validation.DoubleIntervalValidator pour vérifier l'intervalle entre 2 attributs de type double

A content type can contain several global validators. These validators are used to define validation rules between several attributes. For example, we can check that the value of an attribute of type date is lower than the value of another attribute of type date :

Example of the declaration of a global validator which checks that the value of the "start" attribute (of type datetime) is less than the value of the "end" attribute (also of type datetime).

<global-validators>
   <global-validator class="org.ametys.cms.contenttype.validation.DateTimeIntervalValidator">
     <startDate path="start"/>
      <endDate path="end"/>
   </global-validator>
</global-validators>

The views

A view is a set of model elements. Each view refers to the declared elements required to display it.

SinceAmetys 4.4, two view syntaxes have coexisted:
- the classic syntax, detailed below,
- and the historical syntax, presented in a separate §.
It is possible to declare some views with the classic syntax and others with the historical syntax.

ForAmetys versions prior to 4.4, only historical syntax is available.

Properties can only be referenced by views that use the new syntax.

Some views have a type attribute, set to "view" or "edition". SinceAmetys 4.6.0, this type is no longer used, and the attribute can be removed without any problem.

Syntax

A view is declared as follows, in the <view> :

Example of "main" view

<view name="main">
   <group name="group1" role="tab">
      <item ref="title" />
      <item ref="document-subtitle" />
          <item ref="illustration">
          <item ref="image" />
          <item ref="alt-text" />
      </item>
      <item ref="abstract" />
      <item ref="content" />
       <label i18n="true">plugin.cms:PLUGINS_CMS_VIEW_MAIN</label>
       <description i18n="true">plugin.cms:PLUGINS_CMS_VIEW_MAIN_DESC</description>
   </group>
</view>

Example of an "abstract" view

<view name="abstract">
  <group name="presentation" role="tab">
      <item ref="title" />
      <item ref="document-subtitle" />
      <item ref="illustration">
          <item ref="image" />
          <item ref="alt-text" />
      </item>
      <item ref="abstract" />
      <item ref="content" />
      <label i18n="true">plugin.myplugin:PRESENTATION_GROUP_LABEL</label>
      <description i18n="true">plugin.myplugin:PRESENTATION_GROUP_DESC</description>
   </group>
   <label i18n="true">plugin.cms:PLUGINS_CMS_VIEW_ABSTRACT</label>
   <description i18n="true">plugin.cms:PLUGINS_CMS_VIEW_ABSTRACT_DESC</description>
  <icons>
     <small>img/content/article/abstract-view-icon-small.png</small>
     <medium>img/content/article/abstract-view-icon-small.png</medium>
     <large>img/content/article/abstract-view-icon-small.png</large>
     <glyph>ametysicon-newspaper1</glyph>
     <decorator>decorator-ametysicon-test</decorator>
   </icons>
</view>
  • On the view  : 
    • The name is the view name (ex: main, abstract, link, details, ...) For more details on view names, see "Mandatory and optional views" below.
    • The internalThis optional feature allows you to "privatize" the view, i.e. make it invisible to the contributor. 
  • The  group is used to group the various elements of the view. 
    • The name corresponds to the group name. This attribute is optional, but may be necessary when you want to override views (see corresponding §).
    • The role attribute defines the grouping type: 
      • La valeur tab represents a grouping by tabs
      • The value fieldset corresponds to a border representing the grouping
      • This attribute is optional: if not defined, it takes the default value tab for the first grouping level, and the value fieldset for lower levels. 
    • The label defines the group label
    • The description defines the group description
  • Item tags refer to a model element described in the content type, indicating its name. This may be an attribute, a property defined by the content type, or a system property.

Pour les version 4.4 à 4.7 inclues, la syntaxe est <attribute-ref name="title" />, et non <item ref="title" />

  • the  label defines the view label. If left blank, the view name will be used as the label.
  • the description defines the view description
  • the icons tag is used to define view icons
    • small, medium and large tags, to define 16x16, 32x32 and 48x48 pixel icons respectively 
    • the glyph tag for the pictogram. If the pictogram is not specified, but there is a medium icon, this will be used.
    • decorator tag to add a decorator to the pictogram

Attached views

This view syntax can be used to create joined views (useful for linked content); here are some examples:

Adding a few attributes to linked content

In the example below, linked-content attributes "att1" and "att2" are added to the view

<item ref="linked-content">        
  <item ref="att1" />                
  <item ref="att2" />         
</item>

Add all view attributes

In the example below, all attributes present in the "abstract" view of the linked-content are added to the

<item ref="linked-content">
   <view name="abstract" />
</item>

Add all view attributes and other content attributes not present in the view

In the example below :

  • all attributes present in the "abstract" view of the linked-content are added to the view
  • The 'att1' attribute (not present in the abstract view) is added to the
<item ref="linked-content">        
   <view name="abstract" />                
  <item ref="att1" />         
<item>

Add all linked content attributes

In the example below, all attributes defined in the linked-content model are added to the view

<item ref="linked-content">
  <item ref="*" />
</item>

Add all the attributes of a composite (or repeater)

In the example below, all the attributes of the "illustration" composite are added to the view. 

<item ref="illustration">
  <item ref="*" />
</item>

Simplified syntax

Syntax available from version 4.8 ofAmetys

It is also possible to refer directly to a model element that is in a group, or in linked content with the following syntax:

<item ref="composite/linked-content/att1" /> 

You can also refer to a view :

<item ref="composite/linked-content[abstract]" />

or add all the elements of a linked content or composite (or repeater) :

<item ref="composite/linked-content/*" />
<item ref="illustration/*" />

View overload

As part of inheritance, or when modifying a content type (see corresponding § below), it is possible to override a view, for example to add an attribute, without redefining the view completely. To do this, simply add the override attribute, with the value true, when defining the view.

Modifying general view data

In the example below, the view's "privatization", label, description and icons are modified. These elements are not mandatory. If they are not filled in when a view is modified, the information in the overloaded view is taken into account.

<view name="abstract" override="true" internal="true">
  <label i18n="true">plugin.myplugin:MY_VIEW_ABSTACT</label>
  <description i18n="true">plugin.myplugin:MY_VIEW_ABSTACT_DESC</description>
   <icons>
     <small>img/content/article/abstract-view-other-icon-small.png</small>
     <medium>img/content/article/abstract-view-other-icon-small.png</medium>
     <large>img/content/article/abstract-view-other-icon-small.png</large>
     <glyph>ametysicon-newspaper2</glyph>
     <decorator>decorator-ametysicon-test2</decorator>
   </icons>
</view>

Add attribute at end of view

In the example below, the "subject" attribute is added at the end of the view

<view name="abstract" override="true">
<item ref="subject" />
</view>

Adding an attribute before another attribute

In the example below, the "subject" attribute is added before the "title" attribute. If the "title" attribute is not present in the view, the "subject" attribute is added at the end of the view.

<view name="abstract" override="true">
<item ref="subject" order-before="title" />
</view>

Adding an attribute after another attribute

In the example below, the "subject" attribute is added after the "title" attribute. If the "title" attribute is not present in the view, the "subject" attribute is added at the end of the view.

<view name="abstract" override="true">
<item ref="subject" order-after="title" />
</view>

Adding an attribute to a group

In the example below, the "subject" attribute is added at the end of the "presentation/general" group. If the "presentation/general" group is not present in the view, the "subject" attribute is added at the end of the view. To override a view that has groups, it is important that all the groups in this view are correctly named.

<view name="abstract" override="true">
<item ref="subject" group="presentation/general" />
</view>

Add an attribute after an attribute in a group

In the example below, the "subject" attribute is added after the "title" attribute, which is in the "presentation/general" group. If the "presentation/general" group is not present in the view, the "subject" attribute is added at the root of the view, after the "title" attribute if there is a reference to the "title" attribute at the root of the view, or at the end of the view. If the "title" attribute is not present in the "presentation/general" group, the "subject" attribute is added at the end of the "presentation/general" group.

<view name="abstract" override="true">
<item ref="subject" order-after="title" group="presentation/general" />
</view>

Deleting an attribute

In the example below, the "title" attribute at the view root is removed from the view. If the "title" attribute is not present in the view root, no element is deleted.

<view name="abstract" override="true">
 <remove-item ref="title" />
</view>

Deleting an attribute from a group

In the example below, the "title" attribute in the "presentation/general" group is removed from the view. If the "title" attribute is not present in the "presentation/general" group, no element is deleted.

<view name="abstract" override="true">
 <remove-item ref="presentation/general/title" />
</view>

Deleting an attribute in a composite

In the example below, the "alt-text" attribute in the "illustration" composite is removed from the view. If the "illustration/alt-text" attribute is not present in the view, no element is deleted.

<view name="abstract" override="true">
 <remove-item ref="illustration/alt-text" />
</view>

It is not possible to add an attribute to a composite or repeater.

Mandatory and optional views

You can define as many views as you like. However, some views are mandatory and must be declared for all types of content:

  • the "main" view (mandatory) used to render content in its "full" view
  • the "default-edition" view (optional) used for content modification. If this view is not present, the "main" view will be used for content modification.
  • the "abstract" view (optional) used to render content in its "summary" view (in a content upload, for example)
  • the "link" view (optional) used to render content in its "link" view
  • the "details" view (mandatory) to define the attributes to be displayed in the "Content properties" tool
  • the "index" view (optional) is used by the front-end search engine, to define saxed attributes in the case of page search services (old search engine), or the new page search engine. 

To be rendered, a view is linked to a file XSL. The input data XML for this XSL file corresponds to the attributes declared in this view.

Historical syntax

In this old syntax, a view is declared as follows, in the tag <metadata-set> :

Example of "main" view

<metadata-set name="main">
   <fieldset role="fieldset">
       <label>group1</label>
       <metadata-ref name="title" />
       <metadata-ref name="document-subtitle" />
       <metadata-ref name="illustration">
           <metadata-ref name="image" />
           <metadata-ref name="alt-text" />
       </metadata-ref>
       <metadata-ref name="abstract" />
       <metadata-ref name="content" />
   </fieldset>
   <label i18n="true">plugin.cms:PLUGINS_CMS_VIEW_MAIN</label>
   <description i18n="true">plugin.cms:PLUGINS_CMS_VIEW_MAIN</description>
</metadata-set>
  • On the metadata-set  : 
    • The name is the view name (e.g.: main, abstract, link, details, ...). For more details on view names, see "Mandatory and optional views" above.
    • The internalThis optional feature allows you to "privatize" the view, i.e. make it invisible to the contributor. 
  • The  fieldset defines the attribute grouping
    • The role attribute defines the type of grouping: 
      • The value tab represents a tabbed grouping
      • The value fieldset corresponds to a border representing the grouping
      • This attribute is optional: if not defined, it takes the default value tab for the first grouping level, and the value fieldset for lower levels. 
    • The label defines the group label
    • The description defines the group description
  • Beacons metadata-ref refer to an attribute described in the content type, indicating its name (it is not possible to reference a property in a view with the new syntax)
  • The  label defines the view label
  • The description defines the view description

With historical syntax, it is not possible to create joined views.

Tags

Content types can be tagged.

Tags enable specific processing at Java.

There are 3 tags recognized by all Ametys applications:

  • private: a private content type is one that cannot be created and does not appear in search engines by default.
  • reference-table: the content type is a reference table (see below).
  • mixin: content type that is semantically a role (see below)

The declaration of "tags" in the content type is written as :

<tags>
   <tag>reference-table</tag>
   <tag>private</tag>
</tags>

Tags can be inherited from the parent content type with the attribute inherited="true".

<tags inherited="true"/>

Custom tags

You can add your own tags.

  • No prior declaration required

  • Requires specific java code in specific tools

Multiple inheritance

Since Ametys v4, a content type can inherit from one or more content types.

Inheritance allows you to create a new type of content:

  • from attributes and views of one or more existing types
  • complete with new attributes
  • modify the definition of an existing attribute
  • complete with new views
  • modify existing views

For example, we could imagine a "geolocated event" content type that extends the "News" type to include a "geocode" attribute.

A search on "News" content will return both news and geolocated events.

The definition file corresponding to the "geolocated event" type definition would be :

<content-type xmlns:cms="http://www.ametys.org/schema/cms" extends="org.ametys.plugins.news.Content.news">
   <label i18n="true">plugin.myplugin:EVENT_LABEL</label>
   <description i18n="true">plugin.myplugin:EVENT_DESCRIPTION</description>
   <default-title i18n="true">plugin.myplugin:EVENT_DEFAULT_TITLE</default-title>

   <attribute name="geolocation" type="geocode">
        <label i18n="true">plugin.myplugin:EVENT_GEOLOCATION</label>
        <description i18n="true">plugin.myplugin:EVENT_GEOLOCATION_DESC</description>
   </attribute>

   <view name="main">
       <include from-supertype="org.ametys.plugins.news.Content.news" />
      <item ref="geolocation" />
   </view>
</content-type>

To avoid having to completely redefine the "main" view, the instruction <include from-supertype=".."> can be used to include all attributes of the inherited view.

If, on the other hand, you want to insert the new attribute in a specific place on the modification form, you'll need to redefine the view.

Since version 4.6, views can be overloaded without being completely redefined. See § Content type overloading.

To inherit multiple content types, the inherited content types must be separated by commas.

Specific types of content

The roles

Roles are transversal content types that complement the semantics of a content type.

It is possible to create content from a role.

For example:

  • The Dateable role lets you add dates to a content type
  • The Locatable role adds an address to a content type
  • News inherits Article and adds the Dateable role
  • Event inherits News and adds the Locatable role

A search of all Dateable content will return both News and Events.

Technically, a "role" is very similar to a content type:

  • it is declared in the same way by specifying the "mixin" tag (see the chapter on tags above)
  • it is used with content type inheritance
  • they can also be added dynamically via the GUI

If we take the example of geolocated events above, we can imagine another way of doing things using a :

  • definition of the "content-type.Localisable" role

    <content-type xmlns:cms="http://www.ametys.org/schema/cms">
       <label i18n="true">plugin.myplugin:LOCALISABLE_LABEL</label>
       <description i18n="true">plugin.myplugin:LOCALISABLE_DESCRIPTION</description>
    
       <tags>
           <tag>mixin</tag>
       </tags>
    
       <attribute name="geolocation" type="geocode">
            <label i18n="true">plugin.myplugin:EVENT_GEOLOCATION</label>
            <description i18n="true">plugin.myplugin:EVENT_GEOLOCATION_DESC</description>
       </attribute>
    
       <view name="main">
          <item ref="geolocation" />
       </view>
    </cms:content-type>
  • definition of the "Geolocated event" type, which inherits the "News" and "Locatable" types

    <content-type xmlns:cms="http://www.ametys.org/schema/cms" extends="org.ametys.plugins.news.Content.news,content-type.Localisable">
       <label i18n="true">plugin.myplugin:EVENT_LABEL</label>
       <description i18n="true">plugin.myplugin:EVENT_DESCRIPTION</description>
       <default-title i18n="true">plugin.myplugin:EVENT_DEFAULT_TITLE</default-title>
    
       <view name="main">
           <include from-supertype="org.ametys.plugins.news.Content.news" />
           <include from-supertype="content-type.Localisable" />
       </view>
    </cms:content-type>
    
    

     

Reference tables

Reference tables are content types that can be used with dedicated editing and search tools.

Allowed attribute types are limited to simple attributes: a reference table cannot contain composites or repeaters.

This type of reference table can only be modified in a table.

A reference table is declared by specifying the "reference-table" tag (see the chapter on tags above).

If you want reference table values to appear in the search engine, you need to add a property to their title. (see the Indexing and Searching chapter below)

Private content type

A private content type is one that cannot be created using the standard tools ("Add content" menu or when creating a page) and that does not appear in search engines by default.

Content types ODF (training, courses, elp, ...) are private content types. They have their own search and creation tools. They cannot be searched using the standard search tool.

A private type is declared by specifying the "private" tag (see the section on tags above).

Abstract content type

A content type can be declared "abstract" with the attribute abstract="true"

<content-type abstract="true">
   [...]
<content-type>

Defining a new content type

A content type can be defined in 2 places:

  • in the WEB-INF/param/content-types directory
  • in a new plugin for more advanced processing, such as customizing the rendering pipeline.

Definition in the WEB-INF/param/content-types directory

In WEB-INF/param/content-types/[nom_du_plugin] the new content type is defined as follows:

  • un fichier <id_du_content_type>.xml contient la déclaration du nouveau type de contenu (attributs + vues) comme décrit ci-dessus.

    Exemple de fichier <id_du_contenu>.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <content-type xmlns:cms="http://www.ametys.org/schema/cms">
       <label i18n="true">application:CONTENT_SEMINAIRE_LABEL</label>
       <description i18n="true">application:CONTENT_SEMINAIRE_DESCRIPTION</description>
       <default-title i18n="true">application:CONTENT_SEMINAIRE_DEFAULT_TITLE</default-title>
       <icons>
           <small>img/seminaire_16.png</small>
           <medium>img/seminaire_32.png</medium>
       </icons>
    
       [...]
    </content-type>
  • l'identifiant réel interne du type de contenu est "content-type.<id_du_content_type>"
  • the resources/img directory contains resources (notably the 16x16 and 32x32 pixel icons of the content type)
  • the default catalog i18n is that of the application (in WEB-INF/i18n)
  • le répertoire stylesheets/content-type.<id_du_content_type> contient l'ensemble des fichiers content-type.<id_du_content_type>.xsl et content-type.<id_du_content_type>-<nom_de_la_vue>.xsl pour le rendu graphique des différentes vues

The [plugin_name] directory can correspond to any existing plugins name. We recommend using "web".

Example of file organization for the declaration of a new "seminar" content type

Definition in a plugin

In plugin, a new content type is defined in an extension in the file plugin.xml:

<extension point="org.ametys.cms.contenttype.ContentTypeExtensionPoint"
          id="org.ametys.web.default.Content.article"
          class="org.ametys.cms.contenttype.DefaultContentType">

   <content-type>
        [...]
   </content-type>
</extension>

Modifying an existing content type

It is possible to override an existing content type. For example, to add attributes and/or global validators, or to override views. As with the declaration of a new content type, modifications can be defined in 2 places:

  • in the WEB-INF/param/content-types/_override directory
  • in a new plugin to eventually set up more advanced treatments.

Modification of the WEB-INF/param/content-types/_override directory

To override a content type, you can create a <id du content type>.xml in the WEB-INF/param/content-types/_override of your application

Example of overloading "News" and "Multimedia gallery" content

Example of overloading in the _override folder: addition of the "subject" attribute, redefinition of the "link" view and overloading of the "main" view.

<?xml version="1.0" encoding="UTF-8" ?>

<content-type xmlns:cms="http://www.ametys.org/schema/cms">
   <attribute name="subject" type="string">
        <label i18n="true">application:CONTENT_NEWS_SUBJECT</label>
        <description i18n="true">application:CONTENT_NEWS_SUBJECT_DESC</description>
   </attribute>

   <view name="link">
      <item ref="title" />
      <item ref="document-subtitle" />
      <item ref="start-date" />
      <item ref="end-date" /> 
      <item ref="subject" /> 
       <label i18n="true">plugin.web:PLUGINS_WEB_VIEW_ABSTRACT</label>
   </view>

  <view name="main" override="true">
     <item ref="subject" order-before="abstract" />
   </view>
</content-type>

Modification in a plugin

In plugin, modifications to a content type are defined in an extension in the file plugin.xml. It is possible to modify several content types at once.

The modification of a content type can be conditional. For example, you can use the org.ametys.cms.contenttype.ConfigBasedContentTypeOverrides class to make changes only if a configuration parameter is specified, or if its value is true (in the case of a Boolean parameter). You can also create your own conditions, by creating a java class in your plugin, which implements the org.ametys.cms.contenttype.ContentTypeOverridesExtension interface.

The org.ametys.cms.contenttype.StaticContentTypeOverrides class allows unconditional modifications.

Example of overloading in a plugin : Article and News types, unconditional

<extension point="org.ametys.cms.contenttype.ContentTypeOverridesExtensionPoint"
        id="org.ametys.web.default.Content.override.article"
    class="org.ametys.cms.contenttype.StaticContentTypeOverrides">

   <content-types>
     <content-type id="org.ametys.web.default.Content.article" />
     <content-type id="org.ametys.plugins.news.Content.news" />
   </content-types>

 [...]

</extension>

Example of overloading in a plugin : type Article only if the configuration parameter "runtime.ametys.public" is set to true.

<extension point="org.ametys.cms.contenttype.ContentTypeOverridesExtensionPoint"
        id="org.ametys.web.default.Content.override.article"
      class="org.ametys.cms.contenttype.ConfigBasedContentTypeOverrides">

   <content-types>
     <content-type id="org.ametys.web.default.Content.article" />
   </content-types>
  <config-param>runtime.ametys.public</config-param>

 [...]
</extension>

Order in which overloads are taken into account

So there are several places to create or modify a content type and its elements. Here is the order in which the various element declarations will be taken into account:

  1. First, we look at the elements defined by the content type's parents (using the same algo as above).
  2. Then we look at the elements defined or modified in the initial declaration of the type
  3. Then we look at the modifications made by the overloads in the extensions. Note that overloads in extensions are done in random order. We don't know in advance whether a given extension will be taken into account before any other extension.
  4. And finally in the WEB-INF/param/content-types directory

Overloading views is more complex, because in each of the above cases, it's possible to completely redefine a view, or just overload a few elements. We start by finding out at which level (initial declaration, overload by extension or WEB-INF/param/content-types directory) the last complete (re)definition of the view is located. Then look for overloads in equivalent levels or below.

Examples of content type declarations

The examples below provide an overview of the syntax for declaring a content type. The algorithm for modifying the elements of a content type is also described.

Complete example of a simple content type declaration

Here's a complete example of how to declare a new content type, part of the News type:

<?xml version="1.0" encoding="UTF-8" ?>

<extension xmlns:cms="http://www.ametys.org/schema/cms"
           class="org.ametys.cms.contenttype.DefaultContentType">
  <content-type>

        <label i18n="true">CONTENT_NEWS_LABEL</label>
        <description i18n="true">CONTENT_NEWS_DESCRIPTION</description>
        <default-title i18n="true">CONTENT_NEWS_DEFAULT_TITLE</default-title>

       <!-- Les icônes -->        
       <icons>
            <glyph>ametysicon-newspaper1</glyph>
            <small>img/news_16.png</small>
            <medium>img/news_32.png</medium>
            <large>img/news_48.png</large>
        </icons>
        <css>
            <file plugin="core-ui">font/ametys/AmetysIcon.css</file>
      </css>
        
       <!-- Liste des attributs -->
        <attribute name="title" type="string">
            <label i18n="true">CONTENT_NEWS_TITLE</label>
            <description i18n="true">CONTENT_NEWS_TITLE_DESC</description>
            <validation>
                <mandatory />
            </validation>
        </attribute>
        
        <attribute name="document-subtitle" type="string">
            <label i18n="true">CONTENT_NEWS_SUBTITLE</label>
            <description i18n="true">CONTENT_NEWS_SUBTITLE_DESC</description>
      </attribute>
    
        <attribute name="illustration" type="composite">
            <label i18n="true">CONTENT_NEWS_ILLUSTRATION</label>
            <description i18n="true">CONTENT_NEWS_ILLUSTRATION_DESC</description>
            <attribute name="image" type="file">
                <label i18n="true">CONTENT_NEWS_IMAGE</label>
                <description i18n="true">CONTENT_NEWS_IMAGE_DESC</description>
                <widget>edition.file</widget>
                <widget-params>
                    <param name="allowSources">external,resource</param>
                    <param name="filter">image</param>
                </widget-params>
            </attribute>
            <attribute name="alt-text" type="string">
                <label i18n="true">CONTENT_NEWS_IMAGE_ALT</label>
                <description i18n="true">CONTENT_NEWS_IMAGE_ALT_DESC</description>
            </attribute>
        </attribute>
    
        <attribute name="start-date" type="datetime">
            <label i18n="true">CONTENT_NEWS_START_DATE</label>
            <description i18n="true">CONTENT_NEWS_START_DATE_DESC</description>
            <validation>
                <invalidText i18n="true">CONTENT_NEWS_DATE_INVALID_FORMAT</invalidText>
            </validation>
        </attribute>
        <attribute name="end-date" type="datetime">
            <label i18n="true">CONTENT_NEWS_END_DATE</label>
            <description i18n="true">CONTENT_NEWS_END_DATE_DESC</description>
            <validation>
                <invalidText i18n="true">CONTENT_NEWS_DATE_INVALID_FORMAT</invalidText>
            </validation>
        </attribute>
    
        <attribute name="content" type="rich-text">
            <label i18n="true">CONTENT_NEWS_CONTENT</label>
            <description i18n="true">plugin.news:CONTENT_NEWS_CONTENT_DESC</description>
            <validation>
                <mandatory />
            </validation>
      </attribute>

       <!-- Validation globale -->
        <global-validators>
            <global-validator class="org.ametys.cms.contenttype.validation.DateTimeIntervalValidator">
                <startDate path="start-date"/>
                <endDate path="end-date"/>
            </global-validator>
        </global-validators>
    
       <!-- Vue principale -->
        <view name="main">
          <item ref="title" />
          <item ref="document-subtitle" />
          <item ref="start-date" />
          <item ref="end-date" />
          <item ref="illustration/*" />
        <item ref="content" />
            <label i18n="true">plugin.cms:PLUGINS_CMS_VIEW_MAIN</label>
            <description i18n="true">plugin.cms:PLUGINS_CMS_VIEW_MAIN_DESC</description>
        </view>
    
      <!-- Autres vues -->
        <view name="abstract">
          <item ref="title" />
          <item ref="start-date" />
          <item ref="end-date" />
          <item ref="illustration/*" />
            <label i18n="true">plugin.cms:PLUGINS_CMS_VIEW_ABSTRACT</label>
            <description i18n="true">plugin.cms:PLUGINS_CMS_VIEW_ABSTRACT_DESC</description>
        </view>
      
        <view name="link">
          <item ref="title" />
          <item ref="document-subtitle" />
          <item ref="start-date" />
          <item ref="end-date" />
            <label i18n="true">plugin.cms:PLUGINS_CMS_VIEW_LINK</label>
            <description i18n="true">plugin.cms:PLUGINS_CMS_VIEW_LINK_DESC</description>
        </view>
  
        <view name="details" internal="true">
          <item ref="title" />
          <item ref="document-subtitle" />
          <item ref="start-date" />
          <item ref="end-date" />
            <dublin-core/>
        </view>
    </content-type>
</extension>

Examples of simple content type modifications

Addition of an abstract attribute and overloading of main and abstract views:

<extension point="org.ametys.cms.contenttype.ContentTypeOverridesExtensionPoint"
          id="org.ametys.web.default.Content.override.article"
          class="org.ametys.cms.contenttype.StaticContentTypeOverrides">

    <content-types>
       <content-type id="org.ametys.plugins.news.Content.news" />
    </content-types>

    <attribute name="abstract" type="string">
       <label i18n="true">CONTENT_NEWS_ABSTRACT</label>
       <description i18n="true">CONTENT_NEWS_ABSTRACT_DESC</description>
       <widget>edition.textarea</widget>
    </attribute>

    <view name="main" override="true">
     <item ref="abstract" order-after="document-subtitle" />
    </view>
  
    <view name="abstract" override="true">
     <item ref="abstract" order-after="title" />
    </view>

</extension>

Adding a comment attribute and overloading the main view :

<extension point="org.ametys.cms.contenttype.ContentTypeOverridesExtensionPoint"
          id="org.ametys.web.default.Content.override.article"
          class="org.ametys.cms.contenttype.StaticContentTypeOverrides">

    <content-types>
       <content-type id="org.ametys.plugins.news.Content.news" />
    </content-types>

  <attribute name="comment" type="boolean">
       <label i18n="true">CONTENT_NEWS_COMMENT</label>
       <description i18n="true">CONTENT_NEWS_COMMENT_DESC</description>
    </attribute>

    <view name="main" override="true">
    <item ref="abstract" order-after="document-subtitle" />
  </view>

</extension>

The 2 extensions will be loaded in random order, so the order of the attributes in the view may change. For example, in the main view of the example above, the 2 added attributes are added after the same "document-subtitle" attribute. The first extension loaded will put its attribute after "document-subtitle", the second extension between "document-subtitle" and the attribute added by the first extension.

Redefinition of the abstract view in the _override folder :

<?xml version="1.0" encoding="UTF-8" ?>

<content-type xmlns:cms="http://www.ametys.org/schema/cms">
     <view name="abstract">
       <item ref="title" />
       <item ref="comment" />
         <label i18n="true">plugin.cms:PLUGINS_CMS_VIEW_ABSTRACT</label>
         <description i18n="true">plugin.cms:PLUGINS_CMS_VIEW_ABSTRACT_DESC</description>
     </view>
</content-type>

We redefine the abstract view in the _override folder, i.e. at the last modification level. The abstract view will therefore contain only the "title" and "abstract" attributes.

Indexing and searching

All model elements (attributes and properties), as well as all system properties, are indexed in Solr. They can therefore be used as search columns.

Fulltext system property

This property contains all content test data. It therefore contains all data that can be converted to text format, with the exception of content data.

To add the title of linked content to the fulltext of current content, you can add a property in the content type to point to the title of the linked content.

Example:

<property name="linked-title" path="linked-content/title" />

As the property itself is of type string, it will be integrated into the fulltext

Facets

To be used as a facet in a search, a model element (attribute or property) must either be of type boolean, user or content, or have an enumerator.

Graphic rendering

The graphic rendering of a content type is covered in the Graphic integration section.

Back to top