From 0dfe71288afd9e67f864835c25bf9c070eb76d20 Mon Sep 17 00:00:00 2001 From: Ante Prkacin Date: Thu, 2 Oct 2025 14:35:22 +0200 Subject: [PATCH 1/4] NGSTACK-474 update 'Site API Content views' section with wildcards for Twig templates, extended view config and redirections docs --- docs/introduction/index.rst | 12 +- docs/reference/configuration.rst | 303 ++++++++++++++++++++----------- 2 files changed, 204 insertions(+), 111 deletions(-) diff --git a/docs/introduction/index.rst b/docs/introduction/index.rst index f130d3ed..745cc1bf 100644 --- a/docs/introduction/index.rst +++ b/docs/introduction/index.rst @@ -16,7 +16,7 @@ verbose when used for building websites. Site API fixes this by implementing a d on top of Ibexa Repository API which is designed for developing websites. Having a dedicated layer enables us to take an extra step and do things you would not typically want -to do in Repository API. With Site API we can we can implement lazy loaded properties and methods +to do in Repository API. With Site API we can implement lazy loaded properties and methods that enable content model traversal directly from the entities because: 1. it's a dedicated layer for building websites @@ -61,7 +61,7 @@ and mistakes and improves the overall developer experience. Handling Content from different siteaccesses ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Additionally to what's described above, it possible to safely fetch Content from different +Additionally to what's described above, its possible to safely fetch Content from different siteaccesses as well. That is controlled by :ref:`Cross-siteaccess Content` feature, read the documentation there for more information on how and when that is the case. @@ -169,6 +169,8 @@ prefixed with ``inner``. Example usage from Twig:

Content ID: {{ content.innerContent.id }}

Location ID: {{ location.innerLocation.id }}

Field ID: {{ field.innerField.id }}

+

Inner Content Info: {{ contentInfo.innerContentInfo }}

+

Inner Content Type: {{ contentInfo.innerContentType }}

For more details see :doc:`Templating ` and :doc:`Objects ` reference pages. @@ -192,7 +194,7 @@ The API provides you with a set of **read-only** services: that is not the configured engine for the repository. Why? While Solr search engine provides more features and more performance than Legacy search - engine, it's a separate system needs to be synchronized with changes in the database. This + engine, it's a separate system that needs to be synchronized with changes in the database. This synchronization comes with a delay, which can be a problem in some cases. FilterService gives you access to search that is always up to date, because it uses Legacy search @@ -219,7 +221,7 @@ For more details see :doc:`Services reference ` page. Integration with Ibexa ---------------------- -You can use the Site API services described above as you would normally do it a Symfony application. +You can use the Site API services described above as you would normally do in a Symfony application. But these are also integrated into Ibexa's view layer. There is a Site API version of the view configuration, available under ``ng_content_view`` key: @@ -241,7 +243,7 @@ need to handle it with code that will inject Site API objects to the template, i Ibexa objects. Together with this we provide Site API version of the Content View object, which is used by the default Content view controller and :doc:`custom controllers `. -With the configuration from above you you will be able to render a line view for an article by +With the configuration from above you will be able to render a line view for an article by executing a request to ``ng_content::viewAction``. However, that does not mean URL aliases will be handled by the Site API view configuration as well. This needs to be explicitly enabled, per siteaccess: diff --git a/docs/reference/configuration.rst b/docs/reference/configuration.rst index 982bf112..545a820d 100644 --- a/docs/reference/configuration.rst +++ b/docs/reference/configuration.rst @@ -313,7 +313,7 @@ variables inside Twig templates will be instances of Site API Content and Locati variable, and so on. If needed you can still use ``content_view`` rules. This will allow you to have both Site API -template override rules as well as original Ibexa CMS template override rules, so you can rewrite +template override rules as well as original Ibexa CMS template rules, so you can rewrite your templates bit by bit. You can decide which one to use by directly rendering either ``ng_content::viewAction`` or ``ibexa_content::viewAction`` controller. @@ -353,132 +353,99 @@ Rendering a line view for an article with ``ng_content::viewAction`` would use It is also possible to use custom controllers, this is documented on :doc:`Custom controllers reference` documentation page. -.. _content_view_fallback_configuration: - -Content View fallback -~~~~~~~~~~~~~~~~~~~~~ +Placeholders for Twig templates +------------------------------- -You can configure fallback between Site API and Ibexa CMS views. Fallback can be controlled -through two configuration options (showing default values): +If you named all your Twig templates after the content types, you can set a **placeholder** for +``template`` key in your Content view. Here is an example: .. code-block:: yaml ibexa: system: frontend_group: - ng_site_api: - fallback_to_secondary_content_view: true - fallback_without_subrequest: true - -- ``fallback_to_secondary_content_view`` - - With this option you control whether **automatic fallback** will be used. By default, automatic - fallback is disabled. Secondary content view means the fallback can be used both from Site API - to Ibexa CMS views, and from Ibexa CMS to Site API content views. Which one will be used is - defined by ``site_api_is_primary_content_view`` configuration documented above. - -- ``fallback_without_subrequest`` - - With this option you can control whether the fallback will use a subrequest (default), or Twig - functions that can render content view without a subrequest. That applies both to automatic and - manually configured fallback. Rendering views without a subrequest is faster in debug mode, - where profiling is turned on. Depending on the number of views used on a page, performance - improvement when not using subrequest can be significant. - -.. warning:: - - Because of reverse siteaccess matching limitations, when ``fallback_without_subrequest`` is - turned off, links in the preview in the admin UI will not be correctly generated. To work around - that problem, turn the option on. - -.. note:: - - When fallback is enabled default templates for the primary view will not be used. Otherwise the - fallback would never happen, because the primary view would always use the default templates - instead of falling back to the secondary view. Similarly, when falling back to the secondary - view, if its view configuration doesn't match, the default template of the secondary view will - be rendered. - - -You can also configure fallback manually, per view. This is done by configuring a view to render one -of two special templates, depending if the fallback is from Site API to Ibexa CMS views or the -opposite. - -- ``@NetgenIbexaSiteApi/content_view_fallback/to_ibexa/view.html.twig`` - - This template is used for fallback from Site API to Ibexa CMS views. In the following example - it's used to configure fallback for ``line`` view of ``article`` ContentType: - - .. code-block:: yaml - - ibexa: - system: - frontend_group: - ng_content_view: - line: - article: - template: '@NetgenIbexaSiteApi/content_view_fallback/to_ibexa/view.html.twig' - match: - Identifier\ContentType: article - -- ``@NetgenIbexaSiteApi/content_view_fallback/to_site_api/view.html.twig`` - - This template is used for fallback from Ibexa CMS to Site API views. In the following example - it's used to configure fallback for all ``full`` views: - - .. code-block:: yaml - - ibexa: - system: - frontend_group: - content_view: - full: - catch_all: - template: '@NetgenIbexaSiteApi/content_view_fallback/to_site_api/view.html.twig' - match: ~ - -.. _show_hidden_items_configuration: - -Internal Content View route on frontend siteaccesses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ng_content_view: + payload: + common: + template: "@ibexadesign/content/views/payload/{content_type}.html.twig" + match: + Identifier\ContentType: + - ng_article + - ng_blog_post + - ng_category -Ibexa allows use of internal Content View route from the admin UI on the frontend -siteaccesses. That might not be desirable in all cases, so Site API provides two configuration -options to control whether the internal route will be enabled on a frontend siteaccess and, if -enabled, whether it will permanently (HTTP code 308) redirect to the URL alias. +This reduces the need to have multiple similar views and enables you to +have one view with specific format for template names. The above example means that +in your project, you have the following file structure: -By default, both options are set to true and the route will be enabled and it will permanently -redirect to the URL alias: +.. code-block:: none -.. code-block:: yaml + ... + ├── content/ + │ ├──views/ + │ │ ├──payload/ + │ │ │ ├── ng_article.html.twig + │ │ │ ├── ng_blog_post.html.twig + │ │ │ ├── ng_category.html.twig - ibexa: - system: - frontend_group: - ng_site_api: - enable_internal_view_route: true - redirect_internal_view_route_to_url_alias: true +Extending configuration from some Content view +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Configure showing hidden items -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is possible to configure a Content view to **extend** the configuration of another Content view. +Let's say that you have defined two views that both render a list of items. In one view, +you want to render them without intro, and in the other one, you want to render them with intro. +In order to not need the same configuration twice, you can set that one Content view **extends** +the configuration from another one - using ``extends: ``. -You can configure whether hidden Content and Location objects will be shown by default through -``show_hidden_items`` configuration option (``false`` by default): +Here is an example: .. code-block:: yaml ibexa: system: frontend_group: - ng_site_api: - show_hidden_items: false - -This affects loading Location's children and siblings, Content's relations and search through Query -Types. In Query Types you can override the configured option by explicitly defining ``visible`` -condition, see :doc:`the Query Type documentation` for more details. + ng_content_view: + listitem: + common: + template: "@ibexadesign/content/views/listitem/{content_type}.html.twig" + params: + with_intro: false + match: + Identifier\ContentType: + - file + - ng_article + - ng_audio + - ng_banner + - ng_blog_post + - ng_gallery + - ng_news + - ng_recipe + - ng_video + listitem_with_intro: + common: + extends: listitem/common + params: + with_intro: true + +This enables you to define the configuration only once and have it be extended to +multiple other Content views, while overriding the parameters (key ``params``) +send to Twig template. + +In Twig template, you can then check the ``with_intro`` param like so: + +.. code-block:: twig + +
+

+ {{ content.name }} +

+ {% if with_intro|default(false) %} + {{ content.fields.intro.value }} + {% endif %}

+

Redirections -~~~~~~~~~~~~ +------------ With Site API, it's also possible to configure redirects directly from the view configuration. Redirections have their own semantic configuration under ``redirect`` key in configuration for a @@ -671,6 +638,130 @@ through the ``parameter`` function, which also enables negating a boolean parame keep_request_method: '%kernel.debug%' match: ~ +.. _content_view_fallback_configuration: + +Content View fallback +~~~~~~~~~~~~~~~~~~~~~ + +You can configure fallback between Site API and Ibexa CMS views. Fallback can be controlled +through two configuration options (showing default values): + +.. code-block:: yaml + + ibexa: + system: + frontend_group: + ng_site_api: + fallback_to_secondary_content_view: true + fallback_without_subrequest: true + +- ``fallback_to_secondary_content_view`` + + With this option you control whether **automatic fallback** will be used. By default, automatic + fallback is disabled. Secondary content view means the fallback can be used both from Site API + to Ibexa CMS views, and from Ibexa CMS to Site API content views. Which one will be used is + defined by ``site_api_is_primary_content_view`` configuration documented above. + +- ``fallback_without_subrequest`` + + With this option you can control whether the fallback will use a subrequest (default), or Twig + functions that can render content view without a subrequest. That applies both to automatic and + manually configured fallback. Rendering views without a subrequest is faster in debug mode, + where profiling is turned on. Depending on the number of views used on a page, performance + improvement when not using subrequest can be significant. + +.. warning:: + + Because of reverse siteaccess matching limitations, when ``fallback_without_subrequest`` is + turned off, links in the preview in the admin UI will not be correctly generated. To work around + that problem, turn the option on. + +.. note:: + + When fallback is enabled default templates for the primary view will not be used. Otherwise the + fallback would never happen, because the primary view would always use the default templates + instead of falling back to the secondary view. Similarly, when falling back to the secondary + view, if its view configuration doesn't match, the default template of the secondary view will + be rendered. + + +You can also configure fallback manually, per view. This is done by configuring a view to render one +of two special templates, depending if the fallback is from Site API to Ibexa CMS views or the +opposite. + +- ``@NetgenIbexaSiteApi/content_view_fallback/to_ibexa/view.html.twig`` + + This template is used for fallback from Site API to Ibexa CMS views. In the following example + it's used to configure fallback for ``line`` view of ``article`` ContentType: + + .. code-block:: yaml + + ibexa: + system: + frontend_group: + ng_content_view: + line: + article: + template: '@NetgenIbexaSiteApi/content_view_fallback/to_ibexa/view.html.twig' + match: + Identifier\ContentType: article + +- ``@NetgenIbexaSiteApi/content_view_fallback/to_site_api/view.html.twig`` + + This template is used for fallback from Ibexa CMS to Site API views. In the following example + it's used to configure fallback for all ``full`` views: + + .. code-block:: yaml + + ibexa: + system: + frontend_group: + content_view: + full: + catch_all: + template: '@NetgenIbexaSiteApi/content_view_fallback/to_site_api/view.html.twig' + match: ~ + +.. _show_hidden_items_configuration: + +Internal Content View route on frontend siteaccesses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Ibexa allows use of internal Content View route from the admin UI on the frontend +siteaccesses. That might not be desirable in all cases, so Site API provides two configuration +options to control whether the internal route will be enabled on a frontend siteaccess and, if +enabled, whether it will permanently (HTTP code 308) redirect to the URL alias. + +By default, both options are set to true and the route will be enabled and it will permanently +redirect to the URL alias: + +.. code-block:: yaml + + ibexa: + system: + frontend_group: + ng_site_api: + enable_internal_view_route: true + redirect_internal_view_route_to_url_alias: true + +Configure showing hidden items +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can configure whether hidden Content and Location objects will be shown by default through +``show_hidden_items`` configuration option (``false`` by default): + +.. code-block:: yaml + + ibexa: + system: + frontend_group: + ng_site_api: + show_hidden_items: false + +This affects loading Location's children and siblings, Content's relations and search through Query +Types. In Query Types you can override the configured option by explicitly defining ``visible`` +condition, see :doc:`the Query Type documentation` for more details. + .. _named_object_configuration: Named objects From 19c0978001fb667fee1e2fbf4acb746a929ac1c7 Mon Sep 17 00:00:00 2001 From: Ante Prkacin Date: Fri, 3 Oct 2025 15:44:35 +0200 Subject: [PATCH 2/4] NGSTACK-474 fix a few typos and add a note for Twig template placeholders --- docs/reference/configuration.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/reference/configuration.rst b/docs/reference/configuration.rst index 545a820d..50b8eab2 100644 --- a/docs/reference/configuration.rst +++ b/docs/reference/configuration.rst @@ -211,7 +211,7 @@ be generated on the current siteaccess. Example configuration: - 42 - 256 -If only a single items needs to be configured, you can also use shortcut configuration: +If only a single item needs to be configured, you can also use shortcut configuration: .. code-block:: yaml @@ -250,7 +250,7 @@ for example: - group_3 - group_4 -If only a single items needs to be configured, you can also use shortcut configuration: +If only a single item needs to be configured, you can also use shortcut configuration: .. code-block:: yaml @@ -374,6 +374,12 @@ If you named all your Twig templates after the content types, you can set a **pl - ng_blog_post - ng_category +.. note:: + + The placeholder for Twig templates will only work if you match by **content_type**. + It will not work for any other available matcher (if you're interested, you can find + all the available matchers on the following URL: https://doc.ibexa.co/en/latest/templating/templates/view_matcher_reference/) + This reduces the need to have multiple similar views and enables you to have one view with specific format for template names. The above example means that in your project, you have the following file structure: From 305559bf53a0f0380107bf3a0aae1f321368afe8 Mon Sep 17 00:00:00 2001 From: Ante Prkacin Date: Sat, 4 Oct 2025 16:39:37 +0200 Subject: [PATCH 3/4] NGSTACK-474 fix small typos in docs --- docs/reference/objects.rst | 2 +- docs/reference/query_types.rst | 2 +- docs/reference/services.rst | 6 +++--- docs/reference/templating.rst | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/reference/objects.rst b/docs/reference/objects.rst index 48d66387..f093ed3f 100644 --- a/docs/reference/objects.rst +++ b/docs/reference/objects.rst @@ -38,7 +38,7 @@ their counterparts in Ibexa CMS Repository API. Main benefits they provide over ``Content`` represents a Content item in the Ibexa CMS Repository. -The first difference from Repository Content is that it exist it a single translation only, meaning +The first difference from Repository Content is that it exist in a single translation only, meaning it contains the fields for only one translation. That will always be the translation to be rendered on the siteaccess. You won't need to choose the field in the correct translation, manually or through some kind of helper service. The Content's single translation is always the correct one. diff --git a/docs/reference/query_types.rst b/docs/reference/query_types.rst index e9aa4e27..ce9ef5da 100644 --- a/docs/reference/query_types.rst +++ b/docs/reference/query_types.rst @@ -510,7 +510,7 @@ Templating -------------------------------------------------------------------------------- Configured queries will be available in Twig templates, through ``ng_query``, ``ng_sudo_query``, ``ng_raw_query`` or ``ng_sudo_raw_query``. -The difference it that the former will return a ``Pagerfanta`` instance, while the latter will +The difference is that the former will return a ``Pagerfanta`` instance, while the latter will return an instance of ``SearchResult``. That also means ``ng_query`` and ``ng_sudo_query`` will use ``max_per_page`` and ``page`` parameters to configure the pager, while ``ng_raw_query`` and ``ng_sudo_raw_query`` ignore them and execute the configured query directly. diff --git a/docs/reference/services.rst b/docs/reference/services.rst index 3f126ed8..6d2ff960 100644 --- a/docs/reference/services.rst +++ b/docs/reference/services.rst @@ -173,17 +173,17 @@ FilterService | **Container service ID** | ``netgen.ibexa_site_api.filter_service`` | +--------------------------------+------------------------------------------------+ -The purpose of the ``FindService`` is to find Content and Locations by using Ibexa CMS +The purpose of the ``FilterService`` is to find Content and Locations by using Ibexa CMS Repository Search API. That is the same as ``FindService``, but with the difference that it will always use Legacy search engine. While Solr search engine provides more features and more performance than Legacy search engine, it's -a separate system needs to be synchronized with changes in the database. This synchronization +a separate system that needs to be synchronized with changes in the database. This synchronization comes with a delay, which can be a problem in some cases. FilterService gives you access to search that is always up to date, because it uses Legacy search engine that works directly with database. At the same time, search on top of Solr, with all the -advanced features (like fulltext search or facets) is still available through FindService. +advanced features (like fulltext search or facets) is still available through ``FindService``. The service will return ``SearchResult`` object from the Repository API containing Site API objects. diff --git a/docs/reference/templating.rst b/docs/reference/templating.rst index 8ee2752f..ebbf25d0 100644 --- a/docs/reference/templating.rst +++ b/docs/reference/templating.rst @@ -585,7 +585,7 @@ Location children .. note:: - If the Location doesn't contain any children, optionally limited by the the given ContentType, + If the Location doesn't contain any children, optionally limited by the given ContentType, the method will return ``null``. Make sure to check if that's the case. - **Filtering through Location's children** From 111b015db0a8e72b37cded886f9929c376d13506 Mon Sep 17 00:00:00 2001 From: Ante Prkacin Date: Wed, 15 Oct 2025 15:07:21 +0200 Subject: [PATCH 4/4] NGSTACK-474 small changes for configuration and objects docs --- docs/reference/configuration.rst | 9 ++++----- docs/reference/objects.rst | 4 ++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/reference/configuration.rst b/docs/reference/configuration.rst index 50b8eab2..aa94351c 100644 --- a/docs/reference/configuration.rst +++ b/docs/reference/configuration.rst @@ -394,8 +394,8 @@ in your project, you have the following file structure: │ │ │ ├── ng_blog_post.html.twig │ │ │ ├── ng_category.html.twig -Extending configuration from some Content view -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Extending configuration from an existing Content view +----------------------------------------------------- It is possible to configure a Content view to **extend** the configuration of another Content view. Let's say that you have defined two views that both render a list of items. In one view, @@ -433,9 +433,8 @@ Here is an example: params: with_intro: true -This enables you to define the configuration only once and have it be extended to -multiple other Content views, while overriding the parameters (key ``params``) -send to Twig template. +This enables defining the configuration once and extending it in multiple other Content views, +overriding the parameters sent (key ``params``) to the Twig template. In Twig template, you can then check the ``with_intro`` param like so: diff --git a/docs/reference/objects.rst b/docs/reference/objects.rst index f093ed3f..5eda4b76 100644 --- a/docs/reference/objects.rst +++ b/docs/reference/objects.rst @@ -715,6 +715,10 @@ Properties +-----------------------------+----------------+----------------------------------------------------------+ | ``$contentTypeDescription`` | ``string`` | Description of the Content Type | +-----------------------------+----------------+----------------------------------------------------------+ +| ``$innerContentInfo`` | ``ContentInfo``| Ibexa's original ContentInfo object | ++-----------------------------+----------------+----------------------------------------------------------+ +| ``$innerContentType`` | ``ContentType``| Ibexa's original ContentType object | ++-----------------------------+----------------+----------------------------------------------------------+ | ``$mainLocation`` | `Location`_ | Content's main Location object | +-----------------------------+----------------+----------------------------------------------------------+