You're in the army now
Zend + TinyMCE
View Helper Container
The code for this file can be found here.
The container class acts as the main engine behind the view helper. It also allows us to insert a placeholder into the view/layout that will auto load all the required javascript includes. I have build mine with the php compressor active but the principles are the same should you not want to use it.
To start with you will need to create a container file relative to your TinyMce.php file. I use “TinyMce/Container.php”.
First thing we need to do is create the appropriate class and populate some variables that will contain our default values.
class MyLibrary_View_Helper_TinyMce_Container
{
protected $_enabled = false;
protected $_isXhtml = false;
protected $_localPath = '/scripts/tinymce/';
protected $_plugins = array('style', 'layer', 'table', 'save',
'advhr', 'advimage', 'advlink', 'emotions',
'iespell', 'insertdatetime', 'preview', 'media',
'searchreplace', 'print', 'contextmenu', 'paste',
'directionality', 'fullscreen', 'noneditable', 'visualchars',
'nonbreaking', 'xhtmlxtras', 'imagemanager', 'filemanager','template');
protected $_themes = array('simple', 'advanced');
protected $_languages = array('en');
protected $_defaultEditor = array('mode' => 'textareas',
'theme' => "simple",
'selector' => "tinyMceEditor",
'css' => ""
);
protected $_editors = false;
protected $_templates;
/**
* View Instance
*
* @var Zend_View_Interface
*/
public $view = null;
}
If your familiar with TinyMce a lot of this will seem familiar and easy enough to configure.
Next you will need to create and populate some methods. most of these ones shoud be very straight forward and are mainly dedicated getters and setters.
public function __construct()
{
$this->_templates = $this->_buildTemplates();
}
public function setView(Zend_View_Interface $view)
{
$this->view = $view;
}
public function enable()
{
$this->_enabled = true;
return $this;
}
public function disable()
{
$this->_enabled = false;
return $this;
}
public function isEnabled()
{
return $this->_enabled;
}
public function setLocalPath($path)
{
$this->_localPath = (string) $path;
return $this;
}
public function getLocalPath()
{
return $this->_localPath;
}
public function useLocalPath()
{
return (null === $this->_localPath) ? false : true;
}
public function setEditorOptions($config)
{
$this->addEditorOptions($config);
}
Now we try and tackle the more interesting methods.
setCompressorOptions() allows us to set/override specific options for use in TinyMce.
public function setCompressorOptions($location = '/scripts/tinymce/', array $plugins = null, array $themes = null, array $languages = null)
{
if (is_dir($_SERVER['DOCUMENT_ROOT'].$location)) {
$this->_localPath = $location;
} else {
throw new Exception('Could not verify the location of Tiny MCE Javascript components');
}
if ($plugins) {
$this->_plugins = $plugins;
}
if ($themes) {
$this->_themes = $themes;
}
if ($languages) {
$this->_languages = $languages;
}
}
addEditorOptions() builds the relevant options for the editor. In order to handle multiple editable areas on a page it checks the “selector” that has been passed in and stores it by the selector. This ensures that you are not getting duplicate code trying to load.
public function addEditorOptions($config)
{
if ($config instanceof Zend_Config) {
$config = $config->toArray();
}
// check for existsing css selector and overwrite
if (isset($config['editor_selector'])) {
$this->_editors[$config['editor_selector']] = $config;
} else {
$this->_editors['no_selector'] = $config;
}
}
I extended my version of the helper to also allow me to specify prebuilt templates. This is accessed and built through the _buildTemplates() method. As you will see I use a Zend_Db_Table object to get the templates that are to be used. This basically builds the required javascript string for loading templates. In order for this to work as intended I used long notation for it and required the following fields
- “name”: nameof teh template to display
- “filename”: name of the file to use (remember to change the path to your own location, orinclud ethe path in your field)
- “description”: a description of the template
protected function _buildTemplates()
{
$table = new content_templates();
$rows = $table->fetchTemplates();
if (count($rows) > 0) {
$templates = array();
while ($row = $rows->current()) {
$templates[] = '{
title : "'.$row->name.'",
src : "/files/pageTemplates/'.$row->filename.'",
description : "'.$row->description.'"
}';
$rows->next();
}
return ', template_templates : [' . PHP_EOL . join(', ', $templates) . ' ] ';
}
return '';
}
We now get to the magic methods that will generate the javascript output we need
First we start with _renderCompressor(). This will build the relevant javascript for the compressor to initialise from all the values that we have passed in.
protected function _renderCompressor()
{
$plugins = join(',',$this->_plugins);
$themes = join(',',$this->_themes);
$languages = join(',',$this->_languages);
$compressor = "
";
return $compressor;
}
Next we have a double hit with _renderInit() and _renderEditor().
_renderInit() is a wrapper function that builds the init for each editor specified by selector
_renderEditor actually builds the javascript string to output.
protected function _renderInit()
{
$init = '';
return $init;
}
protected function _renderEditor($config = null)
{
$editor = '
tinyMCE.init({' . PHP_EOL;
if (isset($config['mode'])) {
$editor .= ' mode: "'.$config['mode'].'" ' . PHP_EOL ;
unset($config['mode']);
if (!isset($config['plugins'])) {
$editor .= ', plugins: "'.join(',',$this->_plugins).'" '. PHP_EOL;
}
foreach($config AS $key => $value) {
if (is_array($value)) {
$value = join(', ',$value);
}
switch ($key) {
default:
$editor .= ', '.$key.': "'.$value.'" '.PHP_EOL;
break;
}
}
}
$editor .= $this->_templates;
$editor .= '
});'. PHP_EOL;
return $editor;
}
And to tie it all together we use a __toString(). As we will eventually use this as an object in out view/layout the ultimate idea is to just echo out the helper in the same manner as other static helpers that have been implemented by the Zend team.
public function __toString()
{
if (!$this->isEnabled()) {
return '';
}
$html = $this->_renderCompressor() . PHP_EOL
. $this->_renderInit() . PHP_EOL;
return $html;
}
Thats the hard work done. Now you can make use of the helper at any point by registering the view helper and then echoing it out. bear in mind that you will need to make sure that you set the right parameters if you access it directly from the view.
Now we can move onto the Form Element
| Print article | This entry was posted by Matt Cockayne on June 15, 2009 at 11:39 am, and is filed under Spec Ops. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |



about 1 year ago
It looks pretty good. I’ve to look some more into the code (especially the container), but there’s something wrong with your output. All > characters are converted into > so a simple copy/paste is impossible (but thanks to your svn we can still grab the code).
Also, you missed some parts of the FormTinyMce helper: the first lines of the file and the ending } for the class. Unfortunately you don’t have the helper placed in svn so I merged it myself with help of the FormTextArea view helper.
Keep up the good work!
about 1 year ago
Cheers for the feedback…
Will teach me to proof read my articles a bit more carefully.
Thankfully It was a quick fix to tidy it up. Also I have now committed the missing helper to subversion. but you were right in just merging it with the FormTextArea helper. thats what I did originally
I “borrowed” the container Idea directly from the ZendX_Jquery component. It made a lot of logical sense to use it in the same way.
about 1 year ago
I’m understanding the code something better now. Thanks for updating the svn
There’s only one point: the container has a _buildTemplates() method which uses a content_template class.
I’m not sure about this approach. For now I don’t have a content_template class and you’re not including the file. When I have more time, I’ll have a closer look towards a more general approach in the upcoming weeks (because I’m very eager to have a general TinyMce form component as well!).
about 1 year ago
The content_template class I used is just a generic table for populating the templates. You could in theory use any method you wanted.
the content_template that I implemented is as follows
class content_templates extends Zend_Db_Table_Abstract { /** * The default table name */ protected $_name = 'content_templates'; protected $_primary = 'uid'; public function fetchTemplates($active = 1) { $where = $this->getAdapter()->quoteInto('active= ? ', (int)$active); return $this->fetchAll($where); } }The SQL for this table is
Alternatively you could just as easily set up an array or config object to use inside the class.
class Zucchi_View_Helper_TinyMce_Container { protected $_templates = array(array('name' => 'name value', 'filename' => 'filename value', 'desciption' => 'description value')); /../ protected function _buildTemplates() { $rows = $this->_templates; if (count($rows) > 0) { $templates = array(); while ($row = $rows->current()) { $templates[] = '{ title : "'.$row->name.'", src : "/files/pageTemplates/'.$row->filename.'", description : "'.$row->description.'" }'; $rows->next(); } return ', template_templates : [' . PHP_EOL . join(', ', $templates) . ' ] '; } return ''; } }Eventually I intend to make the templates externally “populate-able” as I improve and extend it
Hope this helps
about 1 year ago
Ah, I see. The “template” is a tinyMce plugin (I never used it). Thanks for your detailed explanation! Please remember I’m very glad you gave these suggestions, but I think I’ll make a more general approach and avoid implicit use of any of the tinyMce plugins.
Because there’s no need to have the requirement for a template plugin, it’s imho better to leave it to the user if they need it
about 1 year ago
Ahh.. good point. I should have made that a little clearer. Yes it is a TinyMCE plugin that I tend to use by default. As My development of this helper continues I do intend to improve upon the activation of individual plugins independantly of the core of tinymce. Hopefully my next revision will cover this
about 1 year ago
Hi, nice tutorial, one thing I noticed though:
In the last example on the first page the first line reads:
[code]
class Zucchi_View_Helper_TinyMce_Container
{
[/code]
and I think it’s meant to be
[code]
class MyLibrary_View_Helper_tinyMce extends Zend_View_Helper_Abstract {
[/code]
Cheers!
about 1 year ago
Your absolutely right. Thanks for the spot.. I also noticed that some Of the code appears to have gotten mixed in with some of the container class… That should now look a bit more appropriate.
about 1 year ago
Hi Matt,
If you’re interested: I used your solution to improve the TinyMce form element a little bit. Please look here for a better explanation: http://juriansluiman.nl/en/blog/article/100/improved-tinymce-solution-for-the-zend-framework
about 1 year ago
I like the changes you made. I see you point regarding the fact that i did include a options/plugins of TinyMce that I really should have left out (i.e. templates).
I’m not so sure of the editor always being enabled though as I like to keep the amount of JS loaded to a minimum where possible, so being able to turn it on and off was very useful for me at the time I built the component.
I have given the idea of a container a lot of consideration and am not 100% on either way of implementation. I don’t think either way is right or wrong, just that it needs more investigation before I could say I prefer one over the other.
I have just been signed off as a contributor for the Zend Framework so I am hoping to put forward a proposal for a component that will allow direct integration of TinyMCE and any other suggested editors. I’ll keep you posted as it develops
about 1 year ago
hi,
very helpful article
just want to note that you have a typo in
public function setCompressorOptions($location = ‘/js/tiny_mce/’, array $plugins = null, array $themes = null, array $languaues = null)
should be $languaGes
about 1 year ago
Hi,
Great post!
I’m using the common structure created by the ZF shell script (zf.sh).
With the previous structure (like 2 years ago) I used to place my libraries just next to Zend’s in the library directory and the zend loader did the rest as I called CustomLib_SomeClass, but this does not work now.
I see you implemented something similar. Now, how do you tell Zend to “see” your libraries?
Cheers!
Mauro.
about 1 year ago
Hi Mauro
I still use my own external library and use the zf tool as well.. In order too register your own library you need to register it as a namespace in your application.ini file
I find that
; additional namespaces
autoloaderNamespaces.namespace = “Zucchi_”
works really well for me
about 9 months ago
what should be the file name and getter and setter method and folder structure
about 9 months ago
I am just new to zend framework ,I want to know what are file to be created and where it is to be stored