BBCode extension¶
In the Back Office, a Wysiwyg editor is used on several places where a rich text can be contributed. You can encounter it for instance on certain blocks or Content Types. Although most of the information entered in the editor is stored in the database in html format, you can also extend the possibilities by introducing custom BBCode tags. This is partially done via the Open Orchestra BBCode parser.
It’s important to note that by default, not all tags are enabled in BBCode format, only those you
want to declare. For instance, putting a text in bold in the rich text editor does not produce by
default a [b]
tag. Out of the box, there is only one BBCode tag: media
. But it is possible
to add your own tags.
In this documentation you will see how the BBCode feature fits in the main processes and how to create a new BBCode tag in your bundle.
Wysiwyg process¶
Open Orchestra uses TinyMce to render a rich text input. Normally, TinyMce generates html tags, but Open Orchestra has enhanced it to use BBCode. Here is the workflow triggered when editing an object using a form containing rich text fields:
- Each rich text field goes into a data transformer to interpret the BBCode tags. This data transformer calls the Open Orchestra BBCode parser to detect and transform valid BBCode tags into html tags.
- The resulting html is given to the TinyMce editor which treats it with its standard logic.
- When the user clicks in the toolbar to inject a BBCode tag (for instance by selecting a media), TinyMce inject the html representation of the BBCode, to be able to visually render the tag. For instance in the media case, you will see it in the editor.
- When the user saves the form, TinyMce replaces via javascript the html tags by their BBCode representations.
How to create a new BBCode and add it to the parser¶
Open Orchestra provides a simple ways of adding your own custom BBCode tags, depending on their nature. Two kind of tags exists:
- Simple tags are just text replacements. For instance a
[b]Some Text[/b]
should be replaced by<b>Some Text</b>
- Complex tags require more than a simple regexp conversion. For instance the tag
[media=format]MediaId[/media]
requires to fetch the media in the database, to detect its type and then to to return the corresponding html tag.
To add a new BBCode tag to the parser, you need to create its definition. There are two ways of adding a definition. To create a simple tag you can quickly set a configuration. But if you prefer, or if your tag requires a php analysis, you can use a Symfony service.
Create a simple BBCode tag via configuration¶
To create a simple BBCode definition, its possible to use a trivial configuration. The parameter
open_orchestra_bbcode.code_definitions
contains an array of declared simple tags. Here is the
declaration of the bold tag:
bold:
tag: b
html: <strong>{param}</strong>
- The key
bold
is the name of the definition used internally by the parser. - The
html
key is the html pattern of the code. The string{param}
will be replaced by the content of the BBcode tag. - The
tag
key is the label used in the BBCode tag. In this example, with thetag
key set tob
, the BBCode tag is[b]{param}[/b]
.
Simple tags can also include some options. For instance the tag [h]
which matches a <h*>
html tag requires an option to indicate the level of the header. For instance [h=1]Some text[/h]
will produce a <h1>
html tag. You still can declare this in a configuration file like this:
title:
tag: h
html: <h{option}>{param}</h{option}>
parameters:
use_option: true
To declare that a tag uses option, you must add the key parameters.use_option
and set it to true.
Note that when declaring a tag with option, that option becomes mandatory. So if the option is not
mandatory, you should declare two versions of the tag: one with option and one without. That way
the parser will use one or the other according to the presence of an option. The html
key uses
both {param} and {option} string to indicate where to place those informations.
The resulting BBCode will be [h={option}]{param}[/h]
Create a BBCode tag via a service¶
BBCode definitions can also be declared by services. A service tagged with
open_orchestra_bbcode.code_definitions
will be recognized as introducing new definitions. Such
a service includes a BBCode definition collection and serves it via the method getDefinitions
.
So you are free to code your own service, but it must implement
OpenOrchestra\BBcodeBundle\Definition\BBcodeDefinitionCollectionInterface
.
The definition collection must be composed of formatted elements implementing
OpenOrchestra\BBcodeBundle\Definition\BBcodeDefinitionInterface
. If your definition is a simple
regex replacement, as the one seen in the previous section, you can use an Open Orchestra definition
factory. But to create a BBCode tag with a more complex logic, you will have to create your own
definition class. Both ways are explained in the next sections.
Create simple definitions with the definition factory¶
You can quickly generate simple definitions using the OpenOrchestraBBcodeBundleDefinitionBBcodeDefinitionFactory.
This factory can be accessed via the service named open_orchestra_bbcode.definition.factory
To generate a new simple definition with this factory, call the method create
with the following
parameters:
$tag
: the BBCode tag, ieb
for the tag [b]$html
: the html representation of the tag, ie<strong>{param}</strong>
for the [b]tag$use_option
: whether the tag uses option or not
So to create a bold tag definition object, you can write:
$definition = $container->get('open_orchestra_bbcode.definition.factory')
->create('b', '<strong>{param}</strong>');
And to create a header tag definition:
$definition = $container->get('open_orchestra_bbcode.definition.factory')
->create('h', '<h{option}>{param}</h{option}>', true);
As mentionned before, to let Open Orchestra know your new definition, you have to add it to a
definition collection class implementing
OpenOrchestra\BBcodeBundle\Definition\BBcodeDefinitionCollectionInterface
. Then make that
collection a Symfony service tagged with open_orchestra_bbcode.code_definitions
.
Create complex definitions with a custom class¶
If the tag you want to create requires a more complex rendering, for instance a youtube
tag
searching in its parameter for a valid youtube id, you have to create your own definition class.
This definition class must implement
OpenOrchestra\BBcodeBundle\Definition\BBcodeDefinitionInterface
. The getHtml method receives a
BBcodeElementNode representing the BBCode tag and returns the matching html version of the tag. So
it is the location to inject the specific rendering logic of your tag.
Instead of creating a full class from scratch, you can also extend the class
OpenOrchestra\BBcodeBundle\Definition\BBcodeDefinition
and override the getHtml method.
Here is what could look like the getHtml method for the youtube
tag:
public function getHtml(BBcodeElementNode $el)
{
$content = '';
foreach ($el->getChildren() as $child) {
$content .= $child->getAsBBCode();
}
$foundMatch = preg_match('/v=([A-z0-9=\-]+?)(&.*)?$/i', $content, $matches);
if (!$foundMatch) {
return $el->getAsBBCode();
}
return '<iframe width="640" height="390" src="http://www.youtube.com/embed/'
. $matches[1] . '" frameborder="0" allowfullscreen></iframe>';
}
Unlike the configuration or the factory ways, creating a definition with such a class allows you to access the Symfony container and to use services to do a complex transformation.
Again to let Open Orchestra know this definition, you have to add it to a definition collection
implementing OpenOrchestra\BBcodeBundle\Definition\BBcodeDefinitionCollectionInterface
and tag
that service with open_orchestra_bbcode.code_definitions
.