diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..bbdf0041 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 + +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false +insert_final_newline = false + +[*.{yaml,yml}] +indent_size = 2 +trim_trailing_whitespace = false + +# Makefile must be tab indented +[Makefile] +indent_style = tab diff --git a/source/_static/images/symfonycomponents/alert-1.png b/source/_static/images/symfonycomponents/alert-1.png new file mode 100644 index 00000000..af804fdd Binary files /dev/null and b/source/_static/images/symfonycomponents/alert-1.png differ diff --git a/source/_static/images/symfonycomponents/alert-custom-block.png b/source/_static/images/symfonycomponents/alert-custom-block.png new file mode 100644 index 00000000..550a35b0 Binary files /dev/null and b/source/_static/images/symfonycomponents/alert-custom-block.png differ diff --git a/source/_static/images/symfonycomponents/alert-variants.png b/source/_static/images/symfonycomponents/alert-variants.png new file mode 100644 index 00000000..e13f64cc Binary files /dev/null and b/source/_static/images/symfonycomponents/alert-variants.png differ diff --git a/source/devapi/index.rst b/source/devapi/index.rst index 8def2547..a5b3fc1c 100644 --- a/source/devapi/index.rst +++ b/source/devapi/index.rst @@ -10,6 +10,7 @@ Apart from the current documentation, you can also generate the full PHP documen database/index search controllers + symfonycomponents/index hlapi/index massiveactions rules diff --git a/source/devapi/symfonycomponents/alert.rst b/source/devapi/symfonycomponents/alert.rst new file mode 100644 index 00000000..37ed6b38 --- /dev/null +++ b/source/devapi/symfonycomponents/alert.rst @@ -0,0 +1,76 @@ +Alert +===== + +.. versionadded:: 12.0.0 + +Renders an alert box inline at its position in the HTML. + +.. image:: /_static/images/symfonycomponents/alert-1.png + :alt: Danger alert + +Props +----- + +All props are optional. + +* :code:`type` **string**. + + * Possible values: :code:`info` (default), :code:`success`, :code:`warning`, :code:`danger`. + +* :code:`title` **string**. + +* :code:`messages` **string|array**. The alert message. An array can be passed to display multiple messages. + +* :code:`icon` **string**. A CSS icon class, for example :code:`ti ti-info-circle`. + + * If not set, the icon is automatically determined from the alert type. + +* :code:`important` **bool**. When ``true``, the alert is visually highlighted. Defaults to ``false``. + +Blocks +------ + +title +^^^^^ + +Completely overrides the title, including the wrapping ``

`` element. + +content +^^^^^^^ + +Completely overrides the message area. + +.. code-block:: twig + + + +

+ Custom title block +

+
+ +
+ My alert content +
+
+ +.. image:: /_static/images/symfonycomponents/alert-custom-block.png + :alt: Example with custom twig block + +Variants +-------- + +Pre-typed variant components are available as shortcuts: + +.. code-block:: twig + + Success alert + Info alert + Warning alert + Danger alert + + Main alert + Main alert with type danger + +.. image:: /_static/images/symfonycomponents/alert-variants.png + :alt: Alert variants diff --git a/source/devapi/symfonycomponents/index.rst b/source/devapi/symfonycomponents/index.rst new file mode 100644 index 00000000..886d9485 --- /dev/null +++ b/source/devapi/symfonycomponents/index.rst @@ -0,0 +1,187 @@ +Symfony Twig Components +======================= + +.. versionadded:: 12.0 + +Twig Components is a `Symfony UX bundle `_ that allows configuring components in PHP. + +It also enables a cleaner integration with a :code:`Vue.js`-like syntax, making components easier to maintain and review compared to the legacy macro-based integration. + +The following components are available: + +.. toctree:: + :maxdepth: 1 + + alert + +Usage +----- + +Twig components support various integration modes. We recommend using the **Component HTML Syntax**. + + +Component HTML Syntax +^^^^^^^^^^^^^^^^^^^^^ + +`Symfony Documentation `_ + +.. code-block:: twig + + + +This syntax resembles modern frontend frameworks. + +To pass dynamic values such as variables, booleans, or arrays, prefix the prop name with ``:`` and use a Twig expression: + +.. code-block:: twig + + + +

+ Custom title block +

+ {{ parent() }} {# Renders the parent content — here: "Overridden title" #} +
+
+ +Most components also support a default ``content`` block. To inject content into it, place your markup directly inside the ```` tag: + +.. code-block:: twig + + + +

+ Custom title block +

+
+ +
+ My alert content +
+
+ +.. image:: /_static/images/symfonycomponents/alert-custom-block.png + :alt: Example with custom twig block + + +Component Twig Syntax +^^^^^^^^^^^^^^^^^^^^^ + +There is also a ``component()`` Twig function, but its use is discouraged except in rare cases. It is less readable and less flexible than the HTML syntax (no block overrides, and it visually blends in with other Twig function calls). + +.. code-block:: twig + + {{ component('Alert', { + type: 'warning', + title: __('My alert title.') + }) }} + +This integration mode will not be shown in the component documentation. + +Creating a Component +-------------------- + +`Symfony Documentation `_ + +A Twig component consists of two parts: a **PHP class** that declares the props and logic, and a **Twig template** that defines the markup. + +The PHP Class +^^^^^^^^^^^^^ + +Create a class under ``src/Twig/Components/`` and annotate it with ``#[AsTwigComponent]``. + +By default, **Public properties** become the component's props and are automatically available as variables in the template. + +**Public methods** are also accessible from the template via the special ``this`` variable. + +.. code-block:: php + + namespace Twig\Components; + + use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; + + #[AsTwigComponent(name: 'MyComponent', template: 'twig_components/MyComponent.html.twig')] + class MyComponent + { + public string $title = ''; + public bool $important = false; + + public function getComputedClass(): string + { + return $this->important ? 'text-bold' : ''; + } + } + +The ``name`` parameter sets the tag name used in templates (````). If omitted, it is derived from the class namespace relative to ``Twig\Components``. + +The ``template`` parameter is also optional. If omitted, Symfony derives the template path from the class namespace, resolved under ``templates/twig_components/``. + +.. note:: + + For components with multiple variants (e.g., ``Alert:Success``, ``Alert:Danger``), the recommended pattern is to extract shared props and logic into an abstract base class, then create lightweight variant classes that extend it and override the relevant defaults. See ``src/Twig/Components/Alert/`` (`Github `_) for a real-world example. + +The Twig Template +^^^^^^^^^^^^^^^^^ + +Place templates under ``templates/twig_components/``. Props are available directly as template variables. The component object itself is accessible via ``this``, which is useful for calling methods: + +.. code-block:: twig + +
+ {% block title %} + {% if title|length %} +

{{ title }}

+ {% endif %} + {% endblock %} + + {% block content %}{% endblock %} +
+ +Define ``{% block %}`` sections for any part of the markup that consumers may need to override. + +The ``{% block content %}`` block is special: any markup placed directly inside the component tag (without an explicit ````) is injected into it automatically: + +.. code-block:: twig + + This text is injected into the content block. + +Variants +^^^^^^^^ + +Variant components share a base class and, typically, the same template. The class name determines the component tag name: a class ``Twig\Components\Alert\Danger`` automatically resolves to the tag ````. + +.. code-block:: php + + namespace Twig\Components\Alert; + + use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; + + #[AsTwigComponent(template: 'twig_components/Alert/Info.html.twig')] + final class Danger extends AbstractAlert + { + public string $type = 'danger'; + } + +The ``template`` parameter is specified explicitly here because all Alert variants share a single template file (``twig_components/Alert/Info.html.twig``). + +Testing +^^^^^^^ + +Two levels of tests are recommended: + +- **Unit tests**: instantiate the PHP class directly and assert prop defaults and method return values. No GLPI environment needed. +- **Rendering tests**: render a Twig string using ``TemplateRenderer::getInstance()->renderFromStringTemplate()`` and assert the resulting HTML. These extend ``GLPITestCase``. + +Tests live in ``tests/functional/Twig/Components/`` (`GitHub `_). See ``AlertTest.php`` and ``AlertRenderingTest.php`` for examples. + +Debugging +^^^^^^^^^ + +To list all registered components and their resolved template paths, run: + +.. code-block:: bash + + bin/console symfony:debug:twig-component + + # Using Makefile + make console c='symfony:debug:twig-component' diff --git a/source/sourcecode.rst b/source/sourcecode.rst index b2b45b42..54aa4557 100644 --- a/source/sourcecode.rst +++ b/source/sourcecode.rst @@ -131,7 +131,11 @@ This is a brief description of GLPI main folders and files: * |phpfile| `*.php`: Classes * |folder| `stubs` + * |folder| `templates`: Twig templates files + + * |folder| `twig_components`: Symfony Twig Components (`see documentation `_) + * |folder| `tests`: unit and integration tests * |folder| `tools`: a bunch of tools * |folder| `version`: Current version for internal use