Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 128 additions & 10 deletions bundles/block/create_your_own_blocks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,24 @@ for instance ``acme_main.block.rss``::
Create a Block Service
----------------------

If the configuration and logic already satisfies your needs, you should use an
already existing block service. For your RSS block, you need a custom service
The block service is responsible for rendering the blocks of a specific type,
as returned by the ``getType`` method.

A block service contains:

* The ``load`` method to initialize a block before rendering;
* The ``execute`` method to render the block;
* The ``setDefaultSettings`` to define default settings;
* Cache configuration;
* Form configuration;
* JavaScript and Stylesheet files to be loaded.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @wouterj i cleaned the line up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also be reflected for the other occurences of stylesheet(s) in this PR. After that (and my other comments), you can hit the merge button


If the code of an existing service class satisfies your needs, you can simply
create a new service (see next section) with that existing class. The block
services provided by the CmfBlockBundle are in the namespace
``Symfony\Cmf\Bundle\BlockBundle\Block``.

For your RSS block, you need a custom service
that knows how to fetch the feed data of an ``RssBlock``::

// src/Acme/MainBundle/Block/RssBlockService.php
Expand Down Expand Up @@ -159,8 +175,8 @@ that knows how to fetch the feed data of an ``RssBlock``::
}

// These methods are required by the sonata block service interface.
// They are not used in the CMF. To edit, create a sonata admin or
// something else that builds a form and collects the data.
// They are not used in the CMF. To edit, create a symfony form or
// a sonata admin.

public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
Expand All @@ -173,17 +189,117 @@ that knows how to fetch the feed data of an ``RssBlock``::
}
}

The execute method simply reads the RSS feed and forwards the items to
a template. See :ref:`bundle-block-execute` for more information on the
``execute`` method of the block service. To not make your page very slow
by fetching the feed on each request, have a look at the
:doc:`cache documentation <cache>`.
.. _bundle-block-execute:

The Execute Method
~~~~~~~~~~~~~~~~~~

This method of the block service contains *controller* logic. It is called
by the block framework to render a block. In this example, it checks if the
block is enabled and if so renders RSS items with a template.

.. note::

If you need complex logic to handle a block, it is recommended to move that
logic into a dedicated service and inject that service into the block
service and defer execution in the ``execute`` method, passing along
arguments determined from the block.

.. tip::

When you do a block that will be slow to render, like this example where
we read an RSS feed, you should activate :doc:`block caching <cache>`.

Default Settings
~~~~~~~~~~~~~~~~

The method ``setDefaultSettings`` allows your service to provide default
configuration options for a block. Settings can be altered in multiple
places afterwards, cascading as follows:

* Default settings from the block service;
* If you use a 3rd party bundle you might want to change them in the bundle
configuration for your application see :ref:`bundle-block-configuration`;
* Settings can be altered through template helpers (see example below);
* And settings can also be altered in a block document. Do this only for
settings that are individual to the specific block instance rather than
all blocks of a type. These settings will be stored in the database.

Example of how settings can be overwritten through a template helper:

.. configuration-block::

.. code-block:: jinja

{{ sonata_block_render({'name': 'rssBlock'}, {
'title': 'Symfony2 CMF news',
'url': 'http://cmf.symfony.com/news.rss'
}) }}

.. code-block:: html+php

<?php $view['blocks']->render(array('name' => 'rssBlock'), array(
'title' => 'Symfony2 CMF news',
'url' => 'http://cmf.symfony.com/news.rss',
)) ?>

The Load Method
~~~~~~~~~~~~~~~

The method ``load`` can be used to load additional data into a block. It is
called each time a block is rendered before the ``execute`` method is called.

Form Configuration
~~~~~~~~~~~~~~~~~~

The methods ``buildEditForm`` and ``buildCreateForm`` specify how to build the
the forms for editing using a frontend or backend UI. The method
``validateBlock`` contains the validation configuration. This is not used in
the CMF and it is recommended to instead build forms or Sonata admin classes
that can handle the block documents.

Cache Configuration
~~~~~~~~~~~~~~~~~~~

The method ``getCacheKeys`` contains cache keys to be used for caching the
block. See the section :doc:`block cache <cache>` for more on caching.

JavaScripts and Stylesheets
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The methods ``getJavaScripts`` and ``getStylesheets`` of the service class
define the JavaScript and Stylesheet files needed by a block. There is a
twig function and a templating helper to render all links for all blocks used
on the current page:

.. configuration-block::

.. code-block:: jinja

{{ sonata_block_include_javascripts("all") }}
{{ sonata_block_include_stylesheets("all") }}

.. code-block:: html+php

<?php $view['blocks']->includeJavaScripts('all') ?>
<?php $view['blocks']->includeStylesheets('all') ?>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i even moved this here, as we don't use it in the provided cmf blocks. if people use blocks provided by sonata that use this feature, i hope they read the sonata docs.


.. note::

This mechanism is not recommended. For optimal load times, it is better
to have a central assets definition for your project and aggregate them
into a single Stylesheet and a single JavaScript file, e.g. with assetic_,
rather than having individual ``<link>`` and ``<script>`` tags for each
single file.

Register the Block Service
--------------------------

To make the block work, the last step is to define the service. Do not forget
to tag your service with ``sonata.block`` to make it known to the
SonataBlockBundle. The first argument is the name of the block this service
handles, as per the ``getType`` method of the block. The second argument is the
templating, in order to be able to render this block.
``templating`` service, in order to be able to render this block.

.. configuration-block::

Expand Down Expand Up @@ -221,3 +337,5 @@ templating, in order to be able to render this block.
))
->addTag('sonata.block')
;

.. _assetic: http://symfony.com/doc/current/cookbook/assetic/asset_management.html
130 changes: 6 additions & 124 deletions bundles/block/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -199,131 +199,13 @@ helper. Therefore, use the BlockContext to get or alter a setting if needed.
Block Service
-------------

If you look inside the ``SimpleBlock`` class, you will notice the method
``getType``. This defines the name of the block service that processes the
block when it is rendered.
Internally, the block bundle uses a block service to work with each type
of block. The service is configured to handle a *type* of block. The
blocks themselves identify their type in the ``getType`` method.

A block service contains:

* An execute method;
* Default settings;
* Dorm configuration;
* Cache configuration;
* JavaScript files and stylesheet assets to be loaded;
* A load method.

The block services provided by the Symfony2 CMF BlockBundle are in the
namespace ``Symfony\Cmf\Bundle\BlockBundle\Block``.

.. note::

Always make sure you implement the interface
``Sonata\BlockBundle\Block\BlockServiceInterface`` or extend a block
service like ``Sonata\BlockBundle\Block\BaseBlockService``.

.. _bundle-block-execute:

The Execute Method
~~~~~~~~~~~~~~~~~~

This method of a block service contains *controller* logic::

// ...
if ($block->getEnabled()) {
$feed = false;
if ($blockContext->getSetting('url', false)) {
$feed = $this->feedReader->import($block);
}

return $this->renderResponse($blockContext->getTemplate(), array(
'feed' => $feed,
'block' => $blockContext->getBlock(),
'settings' => $blockContext->getSettings(),
), $response);
}
// ...

.. note::

If you need complex logic to handle a block, it is recommended to move that
logic into a dedicated service and inject that service into the block
service and call it in the ``execute`` method.

Default Settings
~~~~~~~~~~~~~~~~

The method ``setDefaultSettings`` specifies the default settings for a block.
Settings can be altered in multiple places afterwards, cascading as follows:

* Default settings are stored in the block service;
* If you use a 3rd party bundle you might want to change them in the bundle
configuration for your application see :ref:`bundle-block-configuration`;
* Settings can be altered through template helpers (see example);
* And settings can also be altered in a block document, the advantage is that
settings are stored in the database and are individual to the specific block
instead of all blocks of a type.

Example of how settings can be specified through a template helper:

.. configuration-block::

.. code-block:: jinja

{{ sonata_block_render({'name': 'rssBlock'}, {
'title': 'Symfony2 CMF news',
'url': 'http://cmf.symfony.com/news.rss'
}) }}

.. code-block:: html+php

<?php $view['blocks']->render(array('name' => 'rssBlock'), array(
'title' => 'Symfony2 CMF news',
'url' => 'http://cmf.symfony.com/news.rss',
)) ?>

Form Configuration
~~~~~~~~~~~~~~~~~~

The methods ``buildEditForm`` and ``buildCreateForm`` specify how to build the
the forms for editing using a frontend or backend UI. The method
``validateBlock`` contains the validation configuration.

Cache Configuration
~~~~~~~~~~~~~~~~~~~

The method ``getCacheKeys`` contains cache keys to be used for caching the
block.

JavaScript and Stylesheets
~~~~~~~~~~~~~~~~~~~~~~~~~~

The methods ``getJavaScripts`` and ``getStylesheets`` can be used to define
JavaScript and stylesheet assets needed by a block. Use the twig helpers
``sonata_block_include_javascripts`` and ``sonata_block_include_stylesheets``
to render them:

.. configuration-block::

.. code-block:: jinja

{{ sonata_block_include_javascripts() }}
{{ sonata_block_include_stylesheets() }}

.. code-block:: html+php

<?php $view['blocks']->includeJavaScripts() ?>
<?php $view['blocks']->includeStylesheets() ?>

.. note::

This will output the JavaScript files and stylesheets for all blocks loaded in
the service container of your application.

The Load Method
~~~~~~~~~~~~~~~

The method ``load`` can be used to load additional data. It is called each
time a block is rendered before the ``execute`` method is called.
When using the provided blocks, you do not need to worry about the block
service. It is only relevant when
:doc:`creating your own blocks <create_your_own_blocks>`.

.. _bundle-block-rendering:

Expand Down