mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
add documentation for widget
This commit is contained in:
parent
53a6ca3d6b
commit
fe8ade2ca8
@ -38,7 +38,7 @@ Layout and UI
|
|||||||
|
|
||||||
Layout / Template usage <user-interface/layout-template-usage.rst>
|
Layout / Template usage <user-interface/layout-template-usage.rst>
|
||||||
Classes and mixins <user-interface/css-classes.rst>
|
Classes and mixins <user-interface/css-classes.rst>
|
||||||
Delegated blocks <user-interface/delegated-blocks.rst>
|
Widgets <user-interface/widgets.rst>
|
||||||
|
|
||||||
|
|
||||||
Help, I am lost !
|
Help, I am lost !
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
.. 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".
|
|
||||||
|
|
||||||
Delegating rendering of block to other bundles
|
|
||||||
##############################################
|
|
||||||
|
|
||||||
Sometimes, you may want to delegate part of your layout to another bundle(s), which might, or might not, installed.
|
|
||||||
|
|
||||||
Examples :
|
|
||||||
|
|
||||||
- you may want to show task in the top bar, only if the bundle "task" is installed (**Note**: this bundle does not exists... yet !)
|
|
||||||
- you may want to show the group belonging (see :ref:`group-bundle`) below of the vertical menu, only if the bundle is installed.
|
|
||||||
|
|
||||||
This is possible using `the symfony dispatcher event <http://symfony.com/doc/current/components/event_dispatcher/index.html>`_.
|
|
||||||
|
|
||||||
Inserting a delegated block inside a template
|
|
||||||
==============================================
|
|
||||||
|
|
||||||
Use the twig function :code:`chill_delegated_block`.
|
|
||||||
|
|
||||||
Example :
|
|
||||||
|
|
||||||
.. code-block:: html+jinja
|
|
||||||
|
|
||||||
<div class="my_block">{{ chill_delegated_block('my_block', { 'person': person }) }}</div>
|
|
||||||
|
|
||||||
In this example, the block name is :code:`my_block`, and the context is an array : :code:`{ 'person': person }`.
|
|
||||||
|
|
||||||
The :code:`div` will be filled with the html produced by the bundles which suscribed to the event :code:`chill_block.my_block`.
|
|
||||||
|
|
||||||
Subscribing to a delegated block
|
|
||||||
=================================
|
|
||||||
|
|
||||||
Create a :code:`Subscriber` or a :code:`Listener` as `described in the Symfony documentation <http://symfony.com/doc/current/cookbook/event_dispatcher/event_listener.html>`_.
|
|
||||||
|
|
||||||
You should listen to the event :code:`chill_block.block_name`, where `block_name` is the name of the delegated block. For instance, in the example above, the event will be :code:`chill_block.my_block`.
|
|
||||||
|
|
||||||
The event passed as argument will be an instance of :class:`Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent`. The context will be available as an array, as described in subscriber example. You may add content to the page using the :method:`Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent::addContent` method.
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
The code inserted by the function :code:`chill_delegated_block` **should be html safe**. You are encouraged to use an instance of the templating engine (aka Twig) to produce clean html.
|
|
||||||
|
|
||||||
Example :
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
namespace Chill\GroupBundle\Events;
|
|
||||||
|
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
|
||||||
use Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent;
|
|
||||||
|
|
||||||
|
|
||||||
class TemplatingPostVerticalMenuEventSubscriber implements EventSubscriberInterface
|
|
||||||
{
|
|
||||||
// constructor logic will take place here in a real world
|
|
||||||
|
|
||||||
public static function getSubscribedEvents()
|
|
||||||
{
|
|
||||||
return array('chill_block.person_post_vertical_menu' => array(
|
|
||||||
array('processRendering', 0) // you may change the priority if you want your content to be inserted upper or below of the other content.
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// here is where we add content to the event.
|
|
||||||
public function processRendering(DelegatedBlockRenderingEvent $event)
|
|
||||||
{
|
|
||||||
// we access the person using $event['person']
|
|
||||||
$memberships = $memberships = $this->membershipRepository
|
|
||||||
->findBy(array('person' => $event['person']));
|
|
||||||
|
|
||||||
// we add content to the templating using the templating engine
|
|
||||||
$event->addContent(
|
|
||||||
$this->templating
|
|
||||||
->render('ChillGroupBundle:Membership:short_listing.html.twig', array(
|
|
||||||
'memberships' => $memberships,
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
This tag is registered as a service :
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
services:
|
|
||||||
chill_group.membership_rendering_event:
|
|
||||||
class: Chill\GroupBundle\Events\TemplatingPostVerticalMenuEventSubscriber
|
|
||||||
tags:
|
|
||||||
- { name: kernel.event_subscriber }
|
|
||||||
|
|
||||||
You should have a look at the documentation of the bundle to know which delegated block are available and what is their context.
|
|
334
source/development/user-interface/widgets.rst
Normal file
334
source/development/user-interface/widgets.rst
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
.. 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 task in the top bar, only if the bundle "task" is installed (**Note**: this bundle does not exists... yet !)
|
||||||
|
- 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 `prepending the configuration of the bundle which define the place <http://symfony.com/doc/current/bundles/prepend_extension.html>`_).
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
# Chill\MainBundle\DependencyInjection\Configuration.php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||||
|
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||||
|
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the main bundle
|
||||||
|
*/
|
||||||
|
class Configuration implements ConfigurationInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
use AddWidgetConfigurationTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var ContainerBuilder
|
||||||
|
*/
|
||||||
|
private $containerBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(array $widgetFactories = array(),
|
||||||
|
ContainerBuilder $containerBuilder)
|
||||||
|
{
|
||||||
|
// we register here widget factories (see below)
|
||||||
|
$this->setWidgetFactories($widgetFactories);
|
||||||
|
// we will need the container builder later...
|
||||||
|
$this->containerBuilder = $containerBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getConfigTreeBuilder()
|
||||||
|
{
|
||||||
|
$treeBuilder = new TreeBuilder();
|
||||||
|
$rootNode = $treeBuilder->root('chill_main');
|
||||||
|
|
||||||
|
$rootNode
|
||||||
|
->children()
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
->arrayNode('widgets')
|
||||||
|
->canBeDisabled()
|
||||||
|
->children()
|
||||||
|
// we declare here all configuration for homepage place
|
||||||
|
->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
|
||||||
|
->end() // end of widgets/children
|
||||||
|
->end() // end of widgets
|
||||||
|
->end() // end of root/children
|
||||||
|
->end() // end of root
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
return $treeBuilder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
#Chill\MainBundle\DependencyInjection\ChillMainExtension.php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\Config\FileLocator;
|
||||||
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
|
use Symfony\Component\DependencyInjection\Loader;
|
||||||
|
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||||
|
use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface;
|
||||||
|
use Chill\MainBundle\DependencyInjection\Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class load config for chillMainExtension.
|
||||||
|
*/
|
||||||
|
class ChillMainExtension extends Extension implements Widget\HasWidgetFactoriesExtensionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* widget factory
|
||||||
|
*
|
||||||
|
* @var WidgetFactoryInterface[]
|
||||||
|
*/
|
||||||
|
protected $widgetFactories = array();
|
||||||
|
|
||||||
|
public function addWidgetFactory(WidgetFactoryInterface $factory)
|
||||||
|
{
|
||||||
|
$this->widgetFactories[] = $factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return WidgetFactoryInterface[]
|
||||||
|
*/
|
||||||
|
public function getWidgetFactories()
|
||||||
|
{
|
||||||
|
return $this->widgetFactories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load(array $configs, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
// configuration for main bundle
|
||||||
|
$configuration = $this->getConfiguration($configs, $container);
|
||||||
|
$config = $this->processConfiguration($configuration, $configs);
|
||||||
|
|
||||||
|
// add the key 'widget' without the key 'enable'
|
||||||
|
$container->setParameter('chill_main.widgets',
|
||||||
|
array('homepage' => $config['widgets']['homepage']));
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfiguration(array $config, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
return new Configuration($this->widgetFactories, $container);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
# Chill/PersonBundle/Widget/PersonListWidgetFactory
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Widget;
|
||||||
|
|
||||||
|
use Chill\MainBundle\DependencyInjection\Widget\Factory\AbstractWidgetFactory;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add configuration for the person_list widget.
|
||||||
|
*/
|
||||||
|
class PersonListWidgetFactory extends AbstractWidgetFactory
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* append the option to the configuration
|
||||||
|
* see http://symfony.com/doc/current/components/config/definition.html
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function configureOptions($place, NodeBuilder $node)
|
||||||
|
{
|
||||||
|
$node->booleanNode('only_active')
|
||||||
|
->defaultTrue()
|
||||||
|
->end();
|
||||||
|
$node->integerNode('number_of_items')
|
||||||
|
->defaultValue(50)
|
||||||
|
->end();
|
||||||
|
$node->scalarNode('filtering_class')
|
||||||
|
->defaultNull()
|
||||||
|
->end();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return an array with the allowed places where the widget can be rendered
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getAllowedPlaces()
|
||||||
|
{
|
||||||
|
return array('homepage');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return the widget alias
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getWidgetAlias()
|
||||||
|
{
|
||||||
|
return 'person_list';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return the service id for the service which will render the widget.
|
||||||
|
*
|
||||||
|
* this service must implements `Chill\MainBundle\Templating\Widget\WidgetInterface`
|
||||||
|
*
|
||||||
|
* the service must exists in the container, and it is not required that the service
|
||||||
|
* has the `chill_main` tag.
|
||||||
|
*/
|
||||||
|
public function getServiceId(ContainerBuilder $containerBuilder, $place, $order, array $config)
|
||||||
|
{
|
||||||
|
return 'chill_person.widget.person_list';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
# Chill/PersonBundle/Widget/PersonListWidget.php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Widget;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Templating\Widget\WidgetInterface;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Doctrine\ORM\Query\Expr;
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
|
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||||
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||||
|
use Symfony\Component\Security\Core\Role\Role;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a widget with person list.
|
||||||
|
*
|
||||||
|
* The configuration is defined by `PersonListWidgetFactory`
|
||||||
|
*/
|
||||||
|
class PersonListWidget implements WidgetInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository for persons
|
||||||
|
*
|
||||||
|
* @var EntityRepository
|
||||||
|
*/
|
||||||
|
protected $personRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity manager
|
||||||
|
*
|
||||||
|
* @var EntityManager
|
||||||
|
*/
|
||||||
|
protected $entityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the authorization helper
|
||||||
|
*
|
||||||
|
* @var AuthorizationHelper;
|
||||||
|
*/
|
||||||
|
protected $authorizationHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var TokenStorage
|
||||||
|
*/
|
||||||
|
protected $tokenStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var UserInterface
|
||||||
|
*/
|
||||||
|
protected $user;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
EntityRepository $personRepostory,
|
||||||
|
EntityManager $em,
|
||||||
|
AuthorizationHelper $authorizationHelper,
|
||||||
|
TokenStorage $tokenStorage
|
||||||
|
) {
|
||||||
|
$this->personRepository = $personRepostory;
|
||||||
|
$this->authorizationHelper = $authorizationHelper;
|
||||||
|
$this->tokenStorage = $tokenStorage;
|
||||||
|
$this->entityManager = $em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param type $place
|
||||||
|
* @param array $context
|
||||||
|
* @param array $config
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render(\Twig_Environment $env, $place, array $context, array $config)
|
||||||
|
{
|
||||||
|
$qb = $this->personRepository
|
||||||
|
->createQueryBuilder('person');
|
||||||
|
|
||||||
|
// show only the person from the authorized centers
|
||||||
|
$and = $qb->expr()->andX();
|
||||||
|
$centers = $this->authorizationHelper
|
||||||
|
->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE));
|
||||||
|
$and->add($qb->expr()->in('person.center', ':centers'));
|
||||||
|
$qb->setParameter('centers', $centers);
|
||||||
|
|
||||||
|
|
||||||
|
// add the "only active" where clause
|
||||||
|
if ($config['only_active'] === true) {
|
||||||
|
$qb->join('person.accompanyingPeriods', 'ap');
|
||||||
|
$or = new Expr\Orx();
|
||||||
|
// add the case where closingDate IS NULL
|
||||||
|
$andWhenClosingDateIsNull = new Expr\Andx();
|
||||||
|
$andWhenClosingDateIsNull->add((new Expr())->isNull('ap.closingDate'));
|
||||||
|
$andWhenClosingDateIsNull->add((new Expr())->gte(':now', 'ap.openingDate'));
|
||||||
|
$or->add($andWhenClosingDateIsNull);
|
||||||
|
// add the case when now is between opening date and closing date
|
||||||
|
$or->add(
|
||||||
|
(new Expr())->between(':now', 'ap.openingDate', 'ap.closingDate')
|
||||||
|
);
|
||||||
|
$and->add($or);
|
||||||
|
$qb->setParameter('now', new \DateTime(), Type::DATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// adding the where clause to the query
|
||||||
|
$qb->where($and);
|
||||||
|
|
||||||
|
$qb->setFirstResult(0)->setMaxResults($config['number_of_items']);
|
||||||
|
|
||||||
|
$persons = $qb->getQuery()->getResult();
|
||||||
|
|
||||||
|
return $env->render(
|
||||||
|
'ChillPersonBundle:Widget:homepage_person_list.html.twig',
|
||||||
|
array('persons' => $persons)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return UserInterface
|
||||||
|
*/
|
||||||
|
private function getUser()
|
||||||
|
{
|
||||||
|
// return a user
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
# Chill/PersonBundle/DependencyInjection/ChillPersonExtension.php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\Config\FileLocator;
|
||||||
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
|
use Symfony\Component\DependencyInjection\Loader;
|
||||||
|
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||||
|
use Chill\MainBundle\DependencyInjection\MissingBundleException;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the class that loads and manages your bundle configuration
|
||||||
|
*
|
||||||
|
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
|
||||||
|
*/
|
||||||
|
class ChillPersonExtension extends Extension implements PrependExtensionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function load(array $configs, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Add a widget "add a person" on the homepage, automatically
|
||||||
|
*
|
||||||
|
* @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container
|
||||||
|
*/
|
||||||
|
public function prepend(ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
$container->prependExtensionConfig('chill_main', array(
|
||||||
|
'widgets' => array(
|
||||||
|
'homepage' => array(
|
||||||
|
array(
|
||||||
|
'widget_alias' => 'add_person',
|
||||||
|
'order' => 2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user