Widgets

From Cloudrexx Development Wiki
Jump to: navigation, search

Widgets are globally available placeholders provided by components.

How to create/register a widget

Any component can register any number of widgets. Widget names need to be unique across all components. Widgets are registered in postInit() hook. Here's a simple widget registration example:

public function postInit(\Cx\Core\Core\Controller\Cx $cx) {
    $this->getComponent('Widget')->registerWidget(
        new \Cx\Core_Modules\Widget\Model\Entity\FinalStringWidget(
            $this,
            'MY_FIRST_WIDGET',
            'Hello world'
        )
    );
}

This registers a widget that replaces the placeholder [[MY_SIMPLE_WIDGET]] in the template/content by the string Hello world.

Widget types

The widget type can be specified as an argument to the constructor of the widget class. To see which argument it is, please refer to the head of the constructor of the widget class in use.

Type Description Template-Format Identifier
Placeholder A widget of type placeholder is simply replaced by some content. Placeholder widget names are written in uppercase. In the template it has the following format:
[[MY_PLACEHOLDER_WIDGET]]
\Cx\Core_Modules\Widget\Model\Entity\Widget::TYPE_PLACEHOLDER
Block A widget of type block has content, which can be altered while parsing the widget. The block is then replaced with the parsed content. Block widget names are written in lowercase. In the template it has the following format:
<!-- START my_block_widget -->
    any content
<!-- END my_block_widget -->

Everything between the start and the end tag is passed to the widget for parsing.

\Cx\Core_Modules\Widget\Model\Entity\Widget::TYPE_BLOCK
Callback A widget of type callback is like a placeholder with arguments. Callback widget names are written in lowercase. In the template it has the following format:
func_my_callback_widget('foo', 'bar')

'foo' and 'bar' are passed to the widget render method as arguments.

\Cx\Core_Modules\Widget\Model\Entity\Widget::TYPE_CALLBACK

Widget classes

Class Description Supported Types
FinalStringWidget Use for static content Placeholder
EsiWidget Use for dynamic content Placeholder / Block / Callback
RandomEsiWidget Use for random content Placeholder / Block / Callback

Final string widgets

Final string widgets are always of type Placeholder. They are cached in the page cache. This means they should only be used for things which only change when the whole page they are used on changes. Two examples are:

  • [[CANONICAL_LINK]]: Depends on the page, only changes when the page changes. If the page changes, the respective page cache is flushed anyway.
  • [[PATH_OFFSET]]: Path offset should never change on a live system. If it does, the whole page cache should be flushed in order to avoid problems.

ESI widgets

In order to circumvent the cache limitations of a FinalStringWidget there are ESI widgets. ESI widgets are cached separately. Each ESI widget has its own cache lease time and its cache can be flushed individually (see Dropping EsiWidget Cache).

This is achieved by replacing ESI widgets (resp. their template-notation) by ESI element tags. The ESI element tags are then (before the response is sent back to the client) being replaced (by a reverse proxy or Cloudrexx itself) by the response of an Exposed method.

You can register your own EsiWidget along with any other widget class in postInit() of your ComponentController. You'll then have to implement and register (see Add another controller) a new controller that inherits from \Cx\Core_Modules\Widget\Controller\EsiWidgetController. Your own EsiWidgetController must implement the method parseWidget() which will then be used to fetch the content of your ESI widget.

ESI widget variables

ESI widget variables define on which information the widget depends. All necessary variables should be selected to ensure all necessary data is available for parsing. The less variables are selected, the more efficient the widget can be cached.

The selected data is passed to EsiWidgetController::parseWidget($name, $template, $response, $params) method. $params['$key'] will contain Passed content from the listing below:

ESI variable ($key) EsiWidget Constant Description Default if Passed content Short name [1]
Type Description
page ESI_VAR_ID_PAGE Widget depends on current page ESI variables are not overwritten by setEsiVariables() \Cx\Core\ContentManager\Model\Entity\Page The resolved page the widget is located on p
locale ESI_VAR_ID_LOCALE Widget depends on current locale ESI variables are not overwritten by setEsiVariables() \Cx\Core\Locale\Model\Entity\Locale The locale of the resolved page l
theme ESI_VAR_ID_THEME Widget depends on current theme ESI variables are not overwritten by setEsiVariables() and widget type is block \Cx\Core\View\Model\Entity\Theme The resolved theme t
channel ESI_VAR_ID_CHANNEL Widget depends on current channel ESI variables are not overwritten by setEsiVariables() and widget type is block string The resolved channel. One of:
  • \Cx\Core\View\Model\Entity\Theme::THEME_TYPE_WEB
  • \Cx\Core\View\Model\Entity\Theme::THEME_TYPE_PRINT
  • \Cx\Core\View\Model\Entity\Theme::THEME_TYPE_MOBILE
  • \Cx\Core\View\Model\Entity\Theme::THEME_TYPE_APP
  • \Cx\Core\View\Model\Entity\Theme::THEME_TYPE_PDF
ch
user ESI_VAR_ID_USER Widget depends on session - string The session-ID of the request u
currency ESI_VAR_ID_CURRENCY Widget depends on current currency - string [2] The currently set currency code (i.e. EUR) c
country ESI_VAR_ID_COUNTRY Widget depends on current country - string [2] The country the current request (its IP) originats from g
path ESI_VAR_ID_PAGE Widget depends on current path - string The path of the requested ressource pa
query ESI_VAR_ID_QUERY Widget depends on current URL query arguments - array The query string arguments of the requested ressource q
  1. Used for cache file name URL
  2. 2.0 2.1 This will be updated to return the object representation instead of a string

ESI widget variables can be set on the EsiWidget instance by using setEsiVariables() or setEsiVariable(). \Cx\Core_Modules\Widget\Model\Entity\EsiWidget provides the appropriate constants which can be combined using the bitwise OR operation.

Example
// create new block widget
$widget = new \Cx\Core_Modules\Widget\Model\Entity\EsiWidget(
    $this,
    'MY_FANCY_BLOCK_WIDGET',
    \Cx\Core_Modules\Widget\Model\Entity\Widget::TYPE_BLOCK
);

// make widget locale-dependent
// note: $widget->setEsiVariable() does append an additional ESI-variable to the
// widget (in contrary to $widget->setEsiVariables(), which does overwrite
// existing variables).
$widget->setEsiVariable(
    \Cx\Core_Modules\Widget\Model\Entity\EsiWidget::ESI_VAR_ID_LOCALE
);

// register block widget
$this->getComponent('Widget')->registerWidget($widget);

Set cache lease time

The default lease time for ESI widget equals the page cache lease time. The default cache lease time can be overwritten for each widget in EsiWidgetController::parseWidget() by setting an expiration date on the response:

$response->setExpirationDate(new \DateTime('+1hour')); // sets a maximum lease time of one hour

Clear cache

The cache of one or more ESI widgets can be cleared manually by calling:

$this->cx->getEvents()->triggerEvent(
    'clearEsiCache',
    array(
        'Widget',
        array(
            'MY_FIRST_WIDGET',
            'MY_SECOND_WIDGET',
        ),
    )
);

References

Random ESI widgets

If one or more entries of a list should be shown, randomly changing for each request, then RandomEsiWidget is the way to go. It basically works the same as a normal ESI widget, with the following differences:

  • Use setUniqueRepetitionCount() to set the number of entries to show (default is 1)
  • Implement \Cx\Core_Modules\Widget\Controller\RandomEsiWidgetController instead of \Cx\Core_Modules\Widget\Controller\EsiWidgetController
  • Use RandomEsiWidgetController::getRandomEsiWidgetContentInfos($widgetName, $params, $template) to return the list of available entries

Widget parsing

Widgets are parsed recursively. This means that widgets can be placed within the content of other widgets. However, a widget can never be placed within itself. If this is tried, the widget is simply not parsed.

Caching

If SSI/ESI-Caching is enabled, then the content of ESI widgets and Random ESI widgets is being cached. The cache is generated seperately for each resolved parse target.

Parse Targets

Widgets are parsed in the scope of so-called Parse Targets. A Parse Target represents a website element that contains HTML-code as well as Widgets. Currently there exist the following parse targets:

Parse Target Description
\Cx\Core\View\Model\Entity\Theme A functional HTML file of a webdesign template. This includes:
  • index.html
  • home.html (incl. custom content templates)
  • content.html (incl. custom content templates)
  • sidebar.html
Note: headlines.html, events.html, navbar.html, subnavbar.html, etc. are widgets on their own and can therefore also be used as container for other widgets as parsing is done recursively.
\Cx\Core\ContentManager\Model\Entity\Page Any page managed by the Content Manager
\Cx\Modules\Block\Model\Entity\Block Any content pane

Implement your own Parse Target

To add your own parse target (i.e. an entity of your own component), your entity has to implement \Cx\Core_Module\Widget\Model\Entity\WidgetParseTarget.

Then you could parse any widgets within your own parse target as follows:

$this->cx->getComponent('Widget')->parseWidgets(
    $template,          // Sigma template to parse 
    $this->getName(),   // Name of the component your parse target belongs to
    '<NameOfEntity>',   // Name of your entity that is being used as parse target
    $id                 // The resolved identifier of your entity that has been requested
);