mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 22:53:49 +00:00
prepare for merging doc into mono-repository
This commit is contained in:
333
docs/source/development/user-interface/widgets.rst
Normal file
333
docs/source/development/user-interface/widgets.rst
Normal file
@@ -0,0 +1,333 @@
|
||||
.. Copyright (C) 2016 Champs Libres Cooperative SCRLFS
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3
|
||||
or any later version published by the Free Software Foundation;
|
||||
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
A copy of the license is included in the section entitled "GNU
|
||||
Free Documentation License".
|
||||
|
||||
Widgets
|
||||
##############################################
|
||||
|
||||
Rationale
|
||||
=========
|
||||
|
||||
Widgets are useful if you want to publish content on a page provided by another bundle.
|
||||
|
||||
|
||||
Examples :
|
||||
|
||||
- you want to publish a list of people on the homepage ;
|
||||
- you may want to show the group belonging (see :ref:`group-bundle`) below of the vertical menu, only if the bundle is installed.
|
||||
|
||||
The administrator of the chill instance may configure the presence of widget. Although, some widget are defined by default (see :ref:`declaring-widget-by-default`).
|
||||
|
||||
Concepts
|
||||
========
|
||||
|
||||
A bundle may define *place(s)* where a widget may be rendered.
|
||||
|
||||
In a single *place*, zero, one or more *widget* may be displayed.
|
||||
|
||||
Some *widget* may require some *configuration*, and some does not require any configuration.
|
||||
|
||||
Example:
|
||||
|
||||
=========================================== ======== ============================= =======================================
|
||||
Use case place place defined by... widget provided by...
|
||||
=========================================== ======== ============================= =======================================
|
||||
Publishing a list of people on the homepage homepage defined by :ref:`main-bundle` widget provided by :ref:`person-bundle`
|
||||
=========================================== ======== ============================= =======================================
|
||||
|
||||
|
||||
|
||||
Creating a widget without configuration
|
||||
========================================
|
||||
|
||||
To add a widget, you should :
|
||||
|
||||
- define your widget, implementing :class:`Chill\MainBundle\Templating\Widget\WidgetInterface` ;
|
||||
- declare your widget with tag `chill_widget`.
|
||||
|
||||
|
||||
Define the widget class
|
||||
-----------------------
|
||||
|
||||
Define your widget class by implemeting :class:`Chill\MainBundle\Templating\Widget\WidgetInterface`.
|
||||
|
||||
Example :
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace Chill\PersonBundle\Widget;
|
||||
|
||||
use Chill\MainBundle\Templating\Widget\WidgetInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Add a button "add a person"
|
||||
*
|
||||
*/
|
||||
class AddAPersonWidget implements WidgetInterface
|
||||
{
|
||||
public function render(
|
||||
\Twig_Environment $env,
|
||||
$place,
|
||||
array $context,
|
||||
array $config
|
||||
) {
|
||||
// this will render a link to the page "add a person"
|
||||
return $env->render("ChillPersonBundle:Widget:homepage_add_a_person.html.twig");
|
||||
}
|
||||
}
|
||||
|
||||
Arguments are :
|
||||
|
||||
- :code:`$env` the :class:`\Twig_Environment`, which you can use to render your widget ;
|
||||
- :code:`$place` a string representing the place where the widget is rendered ;
|
||||
- :code:`$context` the context given by the template ;
|
||||
- :code:`$config` the configuration which is, in this case, always an empty array (see :ref:`creating-a-widget-with-config`).
|
||||
|
||||
.. note::
|
||||
|
||||
The html returned by the :code:`render` function will be considered as html safe. You should strip html before returning it. See also `How to escape output in template <http://symfony.com/doc/current/templating/escaping.html>`_.
|
||||
|
||||
|
||||
Declare your widget
|
||||
-------------------
|
||||
|
||||
Declare your widget as a service and add it the tag :code:`chill_widget`:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
service:
|
||||
chill_person.widget.add_person:
|
||||
class: Chill\PersonBundle\Widget\AddAPersonWidget
|
||||
tags:
|
||||
- { name: chill_widget, alias: add_person, place: homepage }
|
||||
|
||||
|
||||
The tag must contains those arguments :
|
||||
|
||||
- :code:`alias`: an alias, which will be used to reference the widget into the config
|
||||
- :code:`place`: a place where this widget is authorized
|
||||
|
||||
If you want your widget to be available on multiple places, you should add one tag with each place.
|
||||
|
||||
Conclusion
|
||||
----------
|
||||
|
||||
Once your widget is correctly declared, your widget should be available in configuration.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php app/console config:dump-reference chill_main
|
||||
# Default configuration for extension with alias: "chill_main"
|
||||
chill_main:
|
||||
[...]
|
||||
# register widgets on place "homepage"
|
||||
homepage:
|
||||
|
||||
# the ordering of the widget. May be a number with decimal
|
||||
order: ~ # Required, Example: 10.58
|
||||
|
||||
# the widget alias (see your installed bundles config). Possible values are (maybe incomplete) : person_list, add_person
|
||||
widget_alias: ~ # Required
|
||||
|
||||
If you want to add your widget by default, see :ref:`declaring-widget-by-default`.
|
||||
|
||||
.. _creating-a-widget-with-config:
|
||||
|
||||
Creating a widget **with** configuration
|
||||
========================================
|
||||
|
||||
You can declare some configuration with your widget, which allow administrators to add their own configuration.
|
||||
|
||||
To add some configuration, you will :
|
||||
|
||||
- declare a widget as defined above ;
|
||||
- optionnaly declare it as a service ;
|
||||
- add a widget factory, which will add configuration to the bundle which provide the place.
|
||||
|
||||
|
||||
Declare your widget class
|
||||
-------------------------
|
||||
|
||||
Declare your widget. You can use some configuration elements in your process, as used here :
|
||||
|
||||
.. literalinclude:: ./widgets/ChillPersonAddAPersonWidget.php
|
||||
:language: php
|
||||
|
||||
Declare your widget as a service
|
||||
--------------------------------
|
||||
|
||||
You can declare your widget as a service. Not tag is required, as the service will be defined by the :code:`Factory` during next step.
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
chill_person.widget.person_list:
|
||||
class: Chill\PersonBundle\Widget\PersonListWidget
|
||||
arguments:
|
||||
- "@chill.person.repository.person"
|
||||
- "@doctrine.orm.entity_manager"
|
||||
- "@chill.main.security.authorization.helper"
|
||||
- "@security.token_storage"
|
||||
# this widget is defined by the PersonListWidgetFactory
|
||||
|
||||
You can eventually skip this step and declare your service into the container through the factory (see above).
|
||||
|
||||
Declare your widget factory
|
||||
---------------------------
|
||||
|
||||
The widget factory must implements `Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface`. For your convenience, an :class:`Chill\MainBundle\DependencyInjection\Widget\Factory\AbstractWidgetFactory` will already implements some easy method.
|
||||
|
||||
.. literalinclude:: ./widgets/ChillPersonAddAPersonListWidgetFactory.php
|
||||
:language: php
|
||||
|
||||
.. note::
|
||||
You can declare your widget into the container by overriding the `createDefinition` method. By default, this method will return the already existing service definition with the id given by :code:`getServiceId`. But you can create or adapt programmatically the definition. `See the symfony doc on how to do it <http://symfony.com/doc/current/service_container/definitions.html#working-with-a-definition>`_.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function createDefinition(ContainerBuilder $containerBuilder, $place, $order, array $config)
|
||||
{
|
||||
$definition = new \Symfony\Component\DependencyInjection\Definition('my\Class');
|
||||
// create or adapt your definition here
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
You must then register your factory into the :code:`Extension` class which provide the place. This is done in the :code: `Bundle` class.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
# Chill/PersonBundle/ChillPersonBundle.php
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Chill\PersonBundle\Widget\PersonListWidgetFactory;
|
||||
|
||||
class ChillPersonBundle extends Bundle
|
||||
{
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$container->getExtension('chill_main')
|
||||
->addWidgetFactory(new PersonListWidgetFactory());
|
||||
}
|
||||
}
|
||||
|
||||
.. _declaring-widget-by-default:
|
||||
|
||||
Declaring a widget by default
|
||||
=============================
|
||||
|
||||
Use the ability `to prepend configuration of other bundle <http://symfony.com/doc/current/bundles/prepend_extension.html>`_. A living example here :
|
||||
|
||||
.. literalinclude:: ./widgets/ChillPersonExtension.php
|
||||
:language: php
|
||||
|
||||
|
||||
Defining a place
|
||||
================
|
||||
|
||||
Add your place in template
|
||||
--------------------------
|
||||
|
||||
A place should be defined by using the :code:`chill_widget` function, which take as argument :
|
||||
|
||||
- :code:`place` (string) a string defining the place ;
|
||||
- :code:`context` (array) an array defining the context.
|
||||
|
||||
The context should be documented by the bundle. It will give some information about the context of the page. Example: if the page concerns a people, the :class:`Chill\PersonBundle\Entity\Person` class will be in the context.
|
||||
|
||||
Example :
|
||||
|
||||
.. code-block:: html+jinja
|
||||
|
||||
{# an empty context on homepage #}
|
||||
{{ chill_widget('homepage', {} }}
|
||||
|
||||
.. code-block:: html+jinja
|
||||
|
||||
{# defining a place 'right column' with the person currently viewed
|
||||
{{ chill_widget('right_column', { 'person' : person } }}
|
||||
|
||||
|
||||
Declare configuration for you place
|
||||
-----------------------------------
|
||||
|
||||
In order to let other bundle, or user, to define the widgets inside the given place, you should open a configuration. You can use the Trait :class:`Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait`, which provide the method `addWidgetConfiguration($place, ContainerBuilder $container)`.
|
||||
|
||||
Example :
|
||||
|
||||
.. literalinclude:: ./widgets/ChillMainConfiguration.php
|
||||
:language: php
|
||||
:emphasize-lines: 17, 30, 32, 52
|
||||
:linenos:
|
||||
|
||||
.. _example-chill-main-extension:
|
||||
|
||||
You should also adapt the :class:`DependencyInjection\*Extension` class to add ContainerBuilder and WidgetFactories :
|
||||
|
||||
.. literalinclude:: ./widgets/ChillMainExtension.php
|
||||
:language: php
|
||||
:emphasize-lines: 25-39, 48-49, 56
|
||||
:linenos:
|
||||
|
||||
- line 25-39: we implements the method required by :class:`Chill\MainBundle\DependencyInjection\Widget\HasWidgetExtensionInterface` ;
|
||||
- line 48-49: we record the configuration of widget into container's parameter ;
|
||||
- line 56 : we create an instance of :class:`Configuration` (declared above)
|
||||
|
||||
Compile the possible widget using Compiler pass
|
||||
-----------------------------------------------
|
||||
|
||||
For your convenience, simply extends :class:`Chill\MainBundle\DependencyInjection\Widget\AbstractWidgetsCompilerPass`. This class provides a `doProcess(ContainerBuildere $container, $extension, $parameterName)` method which will do the job for you:
|
||||
|
||||
- :code:`$container` is the container builder
|
||||
- :code:`$extension` is the extension name
|
||||
- :code:`$parameterName` is the name of the parameter which contains the configuration for widgets (see :ref:`the example with ChillMain above <example-chill-main-extension>`.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace Chill\MainBundle\DependencyInjection\CompilerPass;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Chill\MainBundle\DependencyInjection\Widget\AbstractWidgetsCompilerPass;
|
||||
|
||||
/**
|
||||
* Compile the service definition to register widgets.
|
||||
*
|
||||
*/
|
||||
class WidgetsCompilerPass extends AbstractWidgetsCompilerPass {
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$this->doProcess($container, 'chill_main', 'chill_main.widgets');
|
||||
}
|
||||
}
|
||||
|
||||
As explained `in the symfony docs <http://symfony.com/doc/current/service_container/compiler_passes.html>`_, you should register your Compiler Pass into your bundle :
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace Chill\MainBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Chill\MainBundle\DependencyInjection\CompilerPass\WidgetsCompilerPass;
|
||||
|
||||
|
||||
class ChillMainBundle extends Bundle
|
||||
{
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
$container->addCompilerPass(new WidgetsCompilerPass());
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user