Create PagibleAI Content Elements

To create new content elements, you need to define them within the schemas array in the ./config/cms.php file.

Table of Contents:

Example

Adding a new content element called "Quote" with a text field for the quote and a string field for the author, you would add the following to the content array of the schemas configuration:

'quote' => [
    'group' => 'content',
    'icon' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6,17H3V3H6V17M8,5H19A2,2 0 0,1 21,7V17A2,2 0 0,1 19,19H8V5Z" /></svg>',
    'fields' => [
        'text' => [
            'type' => 'text',
            'label' => 'Quote',
            'min' => 1,
            'default' => 'This is a default quote.',
        ],
        'author' => [
            'type' => 'string',
            'default' => 'Default Author',
        ],
    ],
],

This defines a quote element in the content group with a speech bubble icon. It has two fields: text (a required text field) and author (a string field).

Required Properties

Each element definition consists of a key (the element's type) and an array containing the element's configuration. This configuration includes:

  • group: Specifies the group this element belongs to (e.g., 'basic', 'media', 'content', 'forms'). This helps organize elements in the CMS interface.
  • icon: An SVG string used as an icon for the element in the CMS interface. Make sure, the icon contains fill="currentColor" to be dark mode compatible.
  • fields: An associative array defining the fields that make up the content element. The key of each item in the fields array is the name of the field, and the value is an array that describes the field's properties.

Note: Use field names like title, text and file if possible and appropriate. Then, the values of these fields are used in the new content element when its type is changed by the editor in the admin backend.

Available field types

Each field definition requires a type, which determines the type of input the user will see in the CMS. Here's a summary of the available field types, along with configuration examples:

audio

For selecting an audio file.

  • accept: Accepted mime type, e.g. audio/*
  • label: Title displayed in the admin backend for the field
  • required: True/false value if a file must be selected
'audio_file' => [
    'type' => 'audio',
    'label' => 'Select Audio',
    'accept' => 'audio/*',
    'required' => true,
],

autocomplete

For text input with autocomplete suggestions.

  • api-type: GQL or REST depending on the requested API
  • default: Initial default value of the field
  • empty-text: Text shown if no items are returned by the API
  • item-title: Key to the attribute containing the item title; can be a path separated by slashes (/)
  • item-value: Key of the attribute containing the item value; can be a path separated by slashes (/)
  • label: Title displayed in the admin backend for the field
  • list-key: Path to the list of items with names separated by a slash (/)
  • multiple: True/false value if selecting multiple items is allowed
  • options: Initial list of option to select from
  • placeholder: Text shown in the empty autocomplete field
  • query: GraphQL query to fetch suggestions (api-type: GQL)
  • required: True/false value if an item must be selected
  • url: JSON API URL to fetch suggestions from (api-type: REST)

REST API example:

{
    "items": [
        {"name": "Aimeos", "url": "https://github.com/aimeos"},
        {"name": "Laravel", "url": "https://github.com/laravel"}
    ],
    "total": 2
}

For a REST API returning JSON content like outlined above, use this configuration:

'autocomplete_field' => [
    'type' => 'autocomplete',
    'api-type' => 'REST',
    'label' => 'Search Items',
    'url' => '/api/repos?filter=_term_', 
    'list-key' => 'items',
    'item-title' => 'name',
    'item-value' => 'url',
    'placeholder' => 'Start typing to search...',
    'empty-text' => 'No items found.',
    'multiple' => false,
    'required' => true,
    'default' => ['label' => 'Aimeos', 'value' => 'https://github.com/aimeos'],
],

GraphQL API example:

{
    "data": {
        "pages": {
            "data": [
                {
                    "id": "1",
                    "title": "Home page",
                    "latest": {
                        "data": "..."
                    }
                },
                {
                    "id": "2",
                    "title": "Products | Pagible",
                    "latest": {
                        "data": "..."
                    }
                }
            }
        }
    }
}

For a GraphQL API returning content like outlined above, use this configuration:

'autocomplete_field' => [
    'type' => 'autocomplete',
    'api-type' => 'GQL',
    'label' => 'Search Items',
    'url' => '/graphql',
    
    'query' => 'query {
        pages(filter: {title: _term_}) {
            data {
                id
                title
                latest {
                    data
                }
            }
        }
    }',
    'list-key' => 'pages/data',
    'item-title' => 'title',
    'item-value' => 'id',
    'placeholder' => 'Start typing to search...',
    'empty-text' => 'No items found.',
    'multiple' => false,
    'required' => true,
    'default' => ['label' => 'Home page', 'value' => '1'],
],

checkbox

A standard checkbox.

  • default: Initial default value of the field (true/false)
  • label: Title displayed in the admin backend for the field
  • off: Value if unchecked
  • on: Value if checked
'agree_terms' => [
    'type' => 'checkbox',
    'label' => 'I agree to the terms and conditions',
    'on' => 'yes',
    'off' => 'no',
    'default' => 'no',
],

color

A color picker, value will be a hex string like #FFFFFF.

  • default: Initial default value of the field (hex color)
  • label: Title displayed in the admin backend for the field
  • required: True/false value if a color must be selected
'background_color' => [
    'type' => 'color',
    'label' => 'Background Color',
    'required' => false,
    'default' => '#FF0000',
],

combobox

A dropdown list with an associated text input.

  • api-type: GQL or REST depending on the requested API
  • default: Initial default value of the field
  • empty-text: Text shown if no items are returned by the API
  • item-title: Key of the attribute containing the item title; can be a path separated by a slash (/)
  • item-value: Key of the attribute containing the item value; can be a path separated by a slash (/)
  • label: Title displayed in the admin backend for the field
  • list-key: Path to the list of items with names separated by a slash (/)
  • multiple: True/false value if selecting multiple items is allowed
  • options: Initial list of option to select from
  • placeholder: Text shown in the empty combobox field
  • query: GraphQL query to fetch suggestions (api-type: GQL)
  • required: True/false value if an item must be selected
  • url: JSON API URL to fetch suggestions from (api-type: REST)
'category' => [
    'type' => 'combobox',
    'label' => 'Category',
    'options' => [
        ['label' => 'Technology', 'value' => 'tech'],
        ['label' => 'Design', 'value' => 'design'],
    ],
    'placeholder' => 'Select or type a category',
    'required' => true,
    'default' => ['label' => 'Technology', 'value' => 'tech'],
],

date

For selecting a date.

  • allowed: List of dates in YYYY-MM-DD format to select from
  • default: Initial default value of the field in YYYY-MM-DD format
  • label: Title displayed in the admin backend for the field
  • max: Maximum allowed date in YYYY-MM-DD format
  • min: Minimum allowed date in YYYY-MM-DD format
  • multiple: True/false value if selecting multiple dates is allowed
  • placeholder: Text shown in the empty date field
  • required: True/false value if a date must be selected
'event_date' => [
    'type' => 'date',
    'label' => 'Event Date',
    'min' => '2024-01-01',
    'max' => '2024-12-31',
    'required' => true,
    'default' => '2024-06-15',
],

file

For selecting a generic file.

  • accept: Accepted mime type, e.g. application/pdf
  • label: Title displayed in the admin backend for the field
  • required: True/false value if a file must be selected
'document' => [
    'type' => 'file',
    'label' => 'Upload Document',
    'accept' => 'application/pdf',
    'required' => false,
],

hidden

A hidden field that's not visible in the UI, useful for passing data e.g. to actions.

'action' => [
    'type' => 'hidden',
    'value' => '\Aimeos\Cms\Actions\Blog',
],

html

For HTML input.

  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • placeholder: Text shown in the empty text field
'custom_html' => [
    'type' => 'html',
    'label' => 'Custom HTML',
    'placeholder' => '<p>Enter your HTML content here...</p>',
    'default' => '<p>Default HTML content</p>',
],

image

For selecting an image file.

  • accept: Accepted mime type, e.g. image/jpeg
  • label: Title displayed in the admin backend for the field
  • required: True/false value if an image must be selected
'profile_image' => [
    'type' => 'image',
    'label' => 'Profile Image',
    'accept' => 'image/jpeg, image/png',
    'required' => true,
],

images

For selecting multiple images in a specific order.

  • accept: Accepted mime type, e.g. image/webp
  • label: Title displayed in the admin backend for the field
  • max: Maximum number of images allowed
  • min: Minimum number of images required
'gallery_images' => [
    'type' => 'images',
    'label' => 'Gallery Images',
    'accept' => 'image/webp, image/jpeg',
    'min' => 2,
    'max' => 5,
],

items

For creating a list of structured items.

  • default: Initial default value of the field
  • item: Associative array (key is the data name) defining the item that can contain these settings:
    • type: One of the available field types (required)
    • label: Title displayed in the admin backend for the field
    • max: Maximum number of characters/items allowed
    • min: Minimum number of characters/items required
    • placeholder: Text shown in the empty text field
  • label: Title displayed in the admin backend for the field
  • max: Maximum number of items allowed
  • min: Minimum number of items required
'team_members' => [
    'type' => 'items',
    'label' => 'Team Members',
    'min' => 1,
    'max' => 3,
    'default' => ['name' => 'John Doe', 'position' => 'CEO', 'description' => 'The manager'],
    'item' => [
        'name' => [
            'type' => 'string',
            'label' => 'Full name',
            'min' => 3,
            'max' => 100,
            'placeholder' => 'Enter full name',
            'class' => 'name-field',
            'default' => 'John Doe',
        ],
        'position' => [
            'type' => 'string',
            'label' => 'Position',
            'min' => 2,
            'max' => 50,
            'placeholder' => 'Enter position',
            'class' => 'position-field',
            'default' => 'Software Engineer',
        ],
        'image' => [
            'type' => 'image',
            'label' => 'Team Member Image',
            'accept' => 'image/jpeg, image/png',
            'required' => false,
        ],
        'description' => [
            'type' => 'text',
            'label' => 'Description',
            'placeholder' => 'Enter description',
            'default' => 'A dedicated team member.',
        ],
    ],
],

markdown

For rich text formatting.

  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • max: Maximum number of characters allowed in the input field
  • min: Minimum number of characters required in the input field
'description' => [
    'type' => 'markdown',
    'label' => 'Description',
    'default' => 'Default **markdown** content.',
],

number

For numeric input.

  • default: Value used by default
  • label: Title displayed in the admin backend for the field
  • max: Maximum number allowed
  • min: Minimum number required
  • placeholder: Text shown in the empty number field
  • required: True/false value if a valid number is required
  • step: Allowed steps when incrementing/decrementing, e.g. "10", "1", "0.1", "0.01" or any number in between
'quantity' => [
    'type' => 'number',
    'label' => 'Quantity',
    'min' => 1,
    'max' => 100,
    'default' => 1,
    'required' => true,
],

plaintext

For plain text input without formatting.

  • class: CSS class to apply to the input field
  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • max: Maximum number of characters allowed in the input field
  • min: Minimum number of characters required in the input field
  • placeholder: Text shown in the empty text field
'username' => [
    'type' => 'plaintext',
    'label' => 'Username',
    'min' => 3,
    'max' => 50,
    'placeholder' => 'Enter your username',
    'class' => 'username-field',
    'default' => 'defaultuser',
],

radio

A radio button group.

  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • options: List of associative arrays with "label" and "value" keys
  • required: True/false value if a selected option is required
'plan' => [
    'type' => 'radio',
    'label' => 'Choose your plan',
    'options' => [
        ['label' => 'Basic', 'value' => 'basic'],
        ['label' => 'Pro', 'value' => 'pro'],
        ['label' => 'Enterprise', 'value' => 'enterprise'],
    ],
    'required' => true,
    'default' => 'basic',
],

range

A range slider where start and end value can be selected.

  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • max: Maximum number allowed
  • min: Minimum number required
  • step: Steps available when changing the range slider, e.g. "10", "1", "0.1", "0.01" or any number in between
'price_range' => [
    'type' => 'range',
    'label' => 'Price Range',
    'min' => 0,
    'max' => 1000,
    'step' => 10,
    'default' => [100, 500],
],

select

A dropdown list.

  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • multiple: True/false value if selecting multiple items is allowed
  • options: List of associative arrays with "label" and "value" keys
  • placeholder: Text shown in the empty select field
  • required: True/false value if a selected option is required
'category' => [
    'type' => 'select',
    'label' => 'Category',
    'options' => [
        ['label' => 'Technology', 'value' => 'tech'],
        ['label' => 'Design', 'value' => 'design'],
        ['label' => 'Marketing', 'value' => 'marketing'],
    ],
    'placeholder' => 'Select a category',
    'required' => true,
    'default' => 'tech',
],

slider

A slider for a single value.

  • default: Initial default value of the field between min and max value (including)
  • label: Title displayed in the admin backend for the field
  • max: Maximum number allowed
  • min: Minimum number required
  • step: Steps available when changing the slider, e.g. "10", "1", "0.1", "0.01" or any number in between
'discount' => [
    'type' => 'slider',
    'label' => 'Discount',
    'min' => 0,
    'max' => 50,
    'step' => 1,
    'default' => 10,
],

string

A simple text field with no formatting options.

  • class: CSS class to apply to the input field
  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • max: Maximum number of characters allowed in the input field
  • min: Minimum number of characters required in the input field
  • placeholder: Text shown in the empty text field
'title' => [
    'type' => 'string',
    'label' => 'Title',
    'min' => 5,
    'max' => 100,
    'placeholder' => 'Enter title',
    'class' => 'title-field',
    'default' => 'Default Title Example',
],

switch

A toggle switch.

  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • off: Value if unchecked
  • on: Value if checked
'is_active' => [
    'type' => 'switch',
    'label' => 'Active',
    'on' => 'true',
    'off' => 'false',
    'default' => 'true',
],

table

For creating a table with several rows and columns.

  • default: Initial default value of the field (two dimensional array)
  • label: Title displayed in the admin backend for the field
  • min: Minimum number of columns required
  • placeholder: Text shown in the empty text field
  • required: True/false value if table data is required
'pricing_table' => [
    'type' => 'table',
    'label' => 'Pricing Table',
    'min' => 2,
    'required' => true,
    'default' => [['Header 1', 'Header 2'], ['Row 1 Col 1', 'Row 1 Col 2']],
],

text

For text input with limited formatting options (bold, italic, links).

  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
'body' => [
    'type' => 'text',
    'label' => 'Body',
    'default' => 'This is some default body text.',
],

url

For URL input.

  • allowed: URI schemas allowed for URLs (default: "http" and "https")
  • default: Initial default value of the field
  • label: Title displayed in the admin backend for the field
  • placeholder: Text shown in the empty text field
  • required: True/false value if URL is required
'website' => [
    'type' => 'url',
    'label' => 'Website URL',
    'placeholder' => 'Enter website URL',
    'required' => false,
    'default' => 'https://www.example.com',
],

video

For selecting a video file.

  • accept: Accepted mime type, e.g. "video/mp4"
  • label: Title displayed in the admin backend for the field
  • required: True/false value if a file must be selected
'promo_video' => [
    'type' => 'video',
    'label' => 'Promotional Video',
    'accept' => 'video/mp4, video/webm',
    'required' => true,
],