MANUAL
All the doumentation of this web site is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License
Add a new content and the editor to manage it
Add a new content and the editor to manage it
This tutorial will explain in detail to add a new Extension packed as a symfony's plugin to W3studioCms to extend the CMS creating a new content to insert markdown files into your website and how to create a new editor to manage it. Every time you need a new content for your website, it should be implemented as a new extension.
Create the plugin
The first thing is to create a new directory inside the plugins folder of your project and call it w3sExtensionMarkdownPlugin. The plugin's name is very important and it has to be created following the rule w3sExtension[Name]Plugin. This rule is mandatory. As explained, a W3StudioCMS' extension is simply a symfony's plugin, so the structure of the plugin's folder should be familiar. Refer to Chapter 17 of symfony's book to learn more.
Create the content
Add a new folder called lib under the w3sExtensionMarkdownPlugin directory, then add a new class and call it w3sContentManagerMarkdown.class.php. Open that file and add the following code:
class w3sContentManagerMarkdown extends w3sContentManager
{
}
Examine the name of class: it has to be called following this rule: w3sContentManager followed by the name you intend to give to that content, in this case Markdown.
This class extends the base class w3sContentManager that manages the page's contents. This class requires you to define three abstract methods: getDefaultValue(), which will display the default value when a new content is added, getInteractiveMenu() which will return the interactive menu to manage that content by javascript and getEditorName() which will return the name of the editor that will manage the content itself.
Add the following code that defines the required functions:
protected $defaultText = '<span style="font-weight:bold;">Markdown file: </span>';
public function getDefaultValue()
{
return $this->defaultText . w3sToolkit::toI18N('No file has been assigned yet');
}
public function getInteractiveMenu()
{
$editor = sprintf('activeEditor = new markdownEditor(%s, %s);', $this->content->getId(), $this->mapper->getSlotId());
return sprintf($this->defaultInteractiveMenu, $this->content->getId(), $this->mapper->getSlotId(), $editor);
}
public function getEditorName()
{
return 'Markdown';
}
In the getInteractiveMenu method, please notice the variable $activeEditor: it defines at client-side which is the editor that W3studioCMS has to open when a user clicks it to manage the content. In this case the client-side editor variable will be a markdownEditor.
w3sContentManager class has three methods which display the content when it is in editor, preview mode and when it has to be published. For this content we have to override them. Add the following code:
public function getDisplayContentForEditorMode()
{
return w3sToolkit::toI18N($this->defaultText . $this->content->getContent());
}
public function getDisplayContentForPreviewMode()
{
$markdown = new w3sMarkdown();
return $markdown->fromFile(sfConfig::get('app_w3s_markdown_dir') . DIRECTORY_SEPARATOR . $this->content->getContent());
}
public function getDisplayContentForPublishMode()
{
return sprintf('<?php $markdown = new w3sMarkdown(); echo $markdown->fromFile(sfConfig::get(\'sf_data_dir\') . DIRECTORY_SEPARATOR . \'markdown\' . DIRECTORY_SEPARATOR . \'%s\');?>', $this->content->getContent());
}
The code explains itself so I think there is no need to explain it in detail.
Every content is instanced by a class which uses an abstract factory design pattern to create the right content. The content creation is made using the class suffix of every content, in this case the parameter to pass to this class is Markdown, exactly the suffix used for the content's class. This class is called w3sContentManagerFactory.class.php and it is stored in the w3sCore/lib/content directory.
Display the content into the actionMenu
Every content is created from the Actions menu, so a new button is required in that menu. To add that button, add a new folder called config under the w3sExtensionMarkdownPlugin directory and create a new file called toolbar.yml under that directory. Add the following code to the file:
actionMenu:
buttons:
0:
image: <?php echo sfConfig::get('app_w3s_web_skin_images_dir')?>/w3s_interactive_menu/[your image].png
caption: Insert a Markdown file
action: W3sContent.addContent('Markdown')
imageTextRelation: 0
imageParams:
size: 32x32
This script adds a custom button to the actionMenu, the menu used to add a new content to the page. This means that the name of the section, actionMenu, is the toolbar menu which will be modified. A menu could have custom buttons only if it has a specific option called custom. Please examine in the config folder of the W3studioCMS plugin how is declared this menu to learm more.
Focus on the action param: it calls a javascript action, in this case the addContent function of the javascript W3sContent object and the argument passed is exactly the string Markdown which is the content class' suffix. This param will be stored in the database so W3studioCMS will know which type of content must be edited. At last remember to define the [your image] adding a new image to represent the button.
Store markdown files
A directory where the markdown files have to be placed is required, so it must be declared somewhere. The best place to set this parameter is the app.yml file under the plugin's config directory. Create that file then put this code inside:
all:
w3s_markdown_dir: %SF_DATA_DIR%/markdown
Don't forget to create the markdown folder under the data dir of your project.
Create the editor
To create a new editor add a new class under the lib folder and call it w3sEditorContentsMarkdown.class.php. This class will extend the BaseW3sEditorContents class, which is the base class to create a new editor for contents.
<?php
class class w3sEditorContentsMarkdown extends BaseW3sEditorContents
{
}
When you are creating an editor, you have to declare a protected variable called $editorSkeleton to define the editor's xhtml skeleton. If you forget this step an exception will be throwned. For this content the skeleton needed to edit the content is made by a combobox filled with the markdown files readed from the sf_data_dir/markdown folder, which has been declared in the app.yml file, with a button which will insert the content into the page. Note that this editor is very poor but it has the scope to teach you how to build a full working extension plugin for the cms. A more complex plugin to manage markdown files is already bundled from 1.1 release version.
protected $editorSkeleton = // Declares the editor's skeleton
'<div id="w3s_markdown_container">
<table border=0>
<tr>
<th>%s</th>
<td>%s</td>
</tr>
<tr>
<th></th>
<td>
<input id="w3s_edit_content_btn" onclick="activeEditor.edit(); return false;" type="submit" value="%s" />
</td>
</tr>
</table>
</div>';
BaseW3sEditorContents requires the drawEditor abstract method which has to be impemented to build a new w3dget. The drawEditor method is called by the renderEditor function in the w3sEditor class, to render the editor. Here is the code:
public function drawEditor()
{
if (!is_dir(sfConfig::get('app_w3s_markdown_dir'))) mkdir(sfConfig::get('app_w3s_markdown_dir'));
$files = sfFinder::type('file')->maxdepth(0)->relative()->sort_by_name()->in(sfConfig::get('app_w3s_markdown_dir'));
$markdown = array_combine($files, $files);
return sprintf($this->editorSkeleton, sfContext::getInstance()->getI18N()->__('Choose the markdown file'),
select_tag('w3s_markdown_file', options_for_select($markdown)),
sfContext::getInstance()->getI18N()->__('Insert markdown'));
}
This function fills the $editorSkeleton placeholders with the needed values.
activeEditor.edit(); is the ajax function that saves the contentand it will be defined shortly.
Add ajax transaction
The last thing to do is to create a new object on the client-sire to manage the content. The w3s_editor.js is a ready-to-use class which contains the APIs to manage a new editor on client-side. Create a directory called web under the plugin folder, them add a new one called js under the web folder just created and create a new file inside called w3s_editor_markdown.js. Open it and add the following code:
var markdownEditor = Class.create(w3sEditor, {
});
This creates a new markdownEditor object that extends the w3sEditor object. This code is quite enough to open your editor, but at least an edit function must be defined to override the standard one defined in the parent class.
Insert this code inside the object:
edit: function()
{
W3sContent.editContent($('w3s_markdown_file').value);
return false;
}
That's all. Simply the selected element of the combobox "w3s_markdown_file" is taken and it is passed to the W3sContent.editContent which saves it into the database.
Add a stylesheet
You can still add a stylesheet file to give the editor a better look. Add a new directory called css under the web folder and create a new file called w3s_markdown.css. Open it and add the following code:
#w3s_markdown_container{
border:1px solid #666;
background-color: #fff;
padding: 4px;
}
#w3s_markdown_container td{
padding: 4px;
}
At last is necessary to format the markdown contents to display the code sections highlighted and formatted with a font with a fixed width. Markdown uses pre and code to represent this kind of text, so create a new file called markdown.css and add this code.
pre {
padding:0.5em 0 0.5em 1em;
margin-bottom: 10px;
background-color:#222;
overflow:auto;
line-height: 17px;
}
code {
font-size: 12px;
color:#fff;
font-family: "Bitstream Vera Sans Mono", monospace;
}
Add the markdown stylesheet to frontend
Pay attention now: the javascripts and the stylesheets are automatically loaded when you work in editor mode, but they aren't in the frontend, so you have to enable them manually. Create a new view.yml file under the config folder and add the following code:
all:
stylesheets: [/w3sExtensionMarkdownPlugin/css/markdown.css: { raw_name: true }]
This adds the markdown file to the frontend. Every web folder of the plugin will be symlinked or copied into the web folder of your application, that's the reason of the path /w3sExtensionMarkdownPlugin/css/markdown.css.
For this particular kind of content you need a markdown converter and a simply class to manage it: you can find them into the bundled w3sExtensionMarkdownPlugin. Copy them into the plugin's lib folder.
That's all. Run the command symfony:publish-assets from the cli then clear the cache to make it works.
Now you have a new content for your CMS and a new editor to manage it.

