![]() |
|
sfDynamicCMSPlugin - 0.3.0Dynamic Content Management System (CMS) for Symfony 1.0 |
|
![]() |
13
users
Sign-in
to change your status |
This plugin allows you to add a Dynamic Content Management System (CMS) to your Symfony project with the following features:
|
This plugin is not exactly a CMS, it is more a CMF (Content Management Framework).
This plugin allows you to add a Dynamic Content Management System (CMS) to your Symfony project with the following features:
The aim is to give a backend admin to navigation and content management for all kind of Symfony Project. Then plugin usage is quite more complex and quite different that sfSimpleCMS but permits to be used in any kind of project.
This CMS is not l10n, you can't have different versions for a page. But you can maintain different versions for a whole website. Then websites can be totaly different according to their culture and managed separately.
This CMS is currently used by all websites (15+) developped by the author : mainly e-commerce and corporate websites.
| Name | Status | |
|---|---|---|
|
|
lead | moc.naeco-moc <<ta>> niavlys |
Copyright (c) 2007-2008 Sylvain Papet
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
| Version | License | API | Released |
|---|---|---|---|
| 0.4.3beta | MIT license | 0.4.3beta | 16/12/2008 |
| 0.4.2beta | MIT license | 0.4.2beta | 02/12/2008 |
| 0.4.1beta | MIT license | 0.4.1beta | 25/11/2008 |
| 0.4.0beta | MIT license | 0.4.0beta | 24/11/2008 |
| Version | License | API | Released |
|---|---|---|---|
| 0.4.3beta | MIT license | 0.4.3beta | 16/12/2008 |
| 0.4.2beta | MIT license | 0.4.2beta | 02/12/2008 |
| 0.4.1beta | MIT license | 0.4.1beta | 25/11/2008 |
| 0.4.0beta | MIT license | 0.4.0beta | 24/11/2008 |
| Version | License | API | Released |
|---|---|---|---|
| 0.4.3beta | MIT license | 0.4.3beta | 16/12/2008 |
| 0.4.2beta | MIT license | 0.4.2beta | 02/12/2008 |
| 0.4.1beta | MIT license | 0.4.1beta | 25/11/2008 |
| 0.4.0beta | MIT license | 0.4.0beta | 24/11/2008 |
| 0.3.2alpha | MIT license | 0.3.2alpha | 13/06/2008 |
| 0.3.1alpha | MIT license | 0.3.1alpha | 06/06/2008 |
| 0.3.0alpha | MIT license | 0.3.0alpha | 06/06/2008 |
| 0.2.5alpha | MIT license | 0.2.5alpha | 26/05/2008 |
| 0.2.4alpha | MIT license | 0.2.4alpha | 13/05/2008 |
| 0.2.3alpha | MIT license | 0.2.3alpha | 25/04/2008 |
| 0.2.2alpha | MIT license | 0.2.2alpha | 24/04/2008 |
| 0.2.1alpha | MIT license | 0.2.1alpha | 10/04/2008 |
| 0.2.0alpha | MIT license | 0.2.0alpha | 26/03/2008 |
| 0.1.2beta | MIT license | 0.1.2beta | 25/03/2008 |
| 0.1.1beta | MIT license | 0.1.1beta | 18/03/2008 |
| 0.1.0beta | MIT license | 0.1.0beta | 14/03/2008 |
This plugin is not exactly a CMS, it is more a CMF (Content Management Framework).
This plugin allows you to add a Dynamic Content Management System (CMS) to your Symfony project with the following features:
Manage different versions of a website (different applications or cultures)
For each version : create and manage a tree structure for navigations ; breadcrumb navigation
Associate pages to navigation elements and edit pages information (title & meta) and content
Manage navigation url and routing parameters for navigation elements (generation of routing rules in route.yml)
Manage access credential of navigation elements
Manage administrator and editor credentials for admin module management
Manage page templates (global or specific to version) and template slots
Manage page contents with slots
Manage menus
i18n ready (the interface is translated / french translation included)
Can be used in any kind of module (by extending it or not).
The aim is to give a backend admin to navigation and content management for all kind of Symfony Project. Then plugin usage is quite more complex and quite different that sfSimpleCMS but permits to be used in any kind of project.
This CMS is not l10n, you can't have different versions for a page. But you can maintain different versions for a whole website. Then websites can be different according to their culture.
This CMS is currently used by all websites (10) developped by the author : mainly e-commerce and corporate websites.






Editor credential permits to access only third screenshot (edit content only).
Administrator credential permits to access the 3 first screenshots (manage navigation & pages).
Developper credential permits to access all screenshots (manage versions, menu, url & routing).
You should have good basic Symfony knowledge, because the plugin is designed to be very extensible, it might be not easy to grips with it.
The prerequisites for using the sfDynamicCMS plugin are:
The page tree strucure use the sfPropelActAsNestedSetBehaviorPlugin.
The page content use the sfPropelSlotBehaviorPlugin version 0.1.4 at least.
These 2 plugins must be installed and behaviors enabled in your propel.ini.
It is advised to have the following plugins :
Rich text editing uses tinyMCE (or FCKeditor). You must install tinyMCE if you want a wysiwyg interface for text editing.
sfGuardPlugin to manage permission
Typical installation : frontend use sfDynamicCMS module & backend use sfDynamicCMSAdmin module
To install the plugin for a symfony project, the usual process is to use the symfony command line:
$ php symfony plugin-install http://plugins.symfony-project.com/sfDynamicCMSPlugin
Alternatively, if you don't have PEAR installed, you can download the latest package attached to this plugin's wiki page and extract it under your project's plugins/ directory. You will also have to copy the contents of the myproject/plugins/sfDynamicCMSPlugin/web/ directory into a myproject/web/sfDynamicCMSPlugin/ directory.
Rebuild the model, generate the SQL code for the new tables and insert it into your database:
$ php symfony propel-build-all
Enable the new sfDynamicCMS modules in frontend via the settings.yml file.
// in myproject/apps/frontend/config/settings.yml all: .settings: enabled_modules: sfDynamicCMS
Enable the new sfDynamicCMSAdmin modules in backend, via the settings.yml file.
// in myproject/apps/backend/config/settings.yml all: .settings: enabled_modules: sfDynamicCMSAdmin
Clear all routes in routing.yml of frontend. It is possible to add your specific routes (first test without) but it is not advised to have routes which use :module parameter (except if you have well understand sfDynamicCMS routing system).
Give write permission to routing.yml (-rw-rw-rw- / 666) of your application managed by sfDynamicCMS (frontend usualy). Be carefull when using 'symfony fix-perms' command.
Optionnal : in frontend, add sfDynamicCMSFilter to build index before actions
rendering: web_debug: security:
sfDynamicCMS: class: sfDynamicCMSFilter
cache: common: flash: execution:
Clear the cache to enable the autoloading to find the new classes:
$ php symfony cc
sfDynamicCMSAdmin configuration require mainly to describe slots. The aim is to have a syntax which look like "Admin generator" generator.yml files for slots description. Usually configuration is also used to describe global templates which are used by all version. It is possible in admin to define templates that are used only in a specific version.
Templates & nodes system are based on sfPropelSlotBehavior plugin so configuration works in the same way than this plugin.
app.yml sfDynamicCMS:
dev_credentials: superadmin
sf_culture: true
templates:
intro:
title: "Intro page"
slots: []
home:
title: "Homepage"
slots: [text]
page1:
title: "Page model 1"
slots: [image, doc_file](text,)
page2:
title: "Page model 2"
slots: [date, products_ads](column1,)
contact:
title: "Contact"
slots: [email](text_contact,)
slots:
text:
title: "Text"
type: Text
params : size=100x10
column1:
title: "Text - 1st column"
type: Text
help: Don't use "CTRL+V" keystroke but "paste" icons.
params: rich=true tinymce_options=height:500,width:300
date:
title: "Publication date"
type: Date
products_ads:
title: "Products"
type: Double_list
params: related_class=Products retrieve_method=doSelectPublished
image:
title: "Image"
type: Image
params: include_link=page include_remove=true
upload_dir: page
help: Download a JPEG file
doc_file:
title: "Documentation"
type: File
params: include_link=doc_pdf include_remove=true
upload_dir: doc_pdf
help: "Download a pdf file"
email:
title: "E-mail address"
type: Input
params: size=40
dev_credentials: Credential to access developper features (version and routing management). If you use sfGuard and are superadmin, you don't need to define it
sf_culture : Usage of the plugin in a multilingual context (with :sf_culture routing parameter) (false by default)
app.ymlall:
sfDynamicCMS:
title: "My Website rules da world"
default_module: page
default_action: sfDynamicCMS
routes_register: true
sf_culture: true
index: session
forward404: true
dev:
sfDynamicCMS:
index: true
recommanded :
title : default title or title prefix/sufix
default_module module called by default while routing (default : sfDynamicCMS)
default_action action called by default while routing (default : sfDynamicCMS)
facultative :
routes_register : Use the plugin's routes (true by default)
sf_culture : Usage of the plugin in a multilingual context (with :sf_culture routing parameter) (false by default)
index : Use node index to store all nodes in memory to do less database requests (true by default, options : false, true, session)
forward404 : Redirect to 404 if node is not found (true by default)
Start using the plugin by browsing to the admin module's default page:
http://myproject/backend_dev.php/sfDynamicCMSAdmin
Admin is divided in 2 sections :
version management
navigation and content management
If the plugin is used for the first time (when there is no version), it is needed to start by creating a version.
Then :
Create a version (usualy default culture and frontend application)
Define slots and page templates : as global (in app.yml) or as defined for this version only (in page template section)
Create root navigation element (or homepage)
Create navigation elements, create pages, define template used by pages, ...
Manage rooting parameters of navigation elements
Manage pages linked to navigation elements
Manage content of pages
Create a new version
...
Next : If you want to use all the power of sfDynamicCMS you should extend one or many modules with sfDynamicCMS module.
sfDynamicPlugin's slots not have anything to do with Symfony's slots using in view. Slots are the content logic of pages like fields are the content logic of your database table, so sfDynamicPlugin's slots describe content part of a page like : title, text, picture, link, etc. It can be also, parameters for a page like : show_title, number_column, news_attached_to...
Then each page templates are composed of slots. Then template without slots content only static content. Each slots have a type, it can be : text, rich text (using tiny_mce), date, file, checkbox, selectbox, list selection, etc.
Slots description are attached to templates and slots content are attached to pages.
Templates you design might use method to retrieve the slot content like :
echo $current_page->getSlotValue('my_text');
For more information, take a look to sfPropelSlotBehaviorPlugin.
You can extend any module without modify how it work.
It is possible to extend a module dedicated to be used as CMS module (for classical pages).
It is also possible to extend a module which contain business logic like product catalog, news, ecommerce module
Without extending module, it is also possible to use all sfDynamicCMS features by coding your own methods
It permit :
to get current navigation element information to know where are the visitor in the website
to get current page template and define it automaticaly
to get current page information (title, meta tags, template) and fill it automaticaly
to get page content (slots)
First extends the actions.php :
actions should inherit from BasesfDynamicCMSActions
require_once(sfConfig::get('sf_plugins_dir'). '/sfDynamicCMSPlugin/modules/sfDynamicCMS/lib/BasesfDynamicCMSActions.class.php');
class myModuleActions extends BasesfDynamicCMSActions { ...
It is recommanded (but optionnal) to add the SfDynamicCMS features to all module actions by adding this 2 lines in preExecute method. You can also add this 2 lines only in actions which need SfDynamicCMS features.
// Always retrieve navigation information and page content
public function preExecute()
{
$this->executeSfDynamicCMS();
}
// OR //
public function executeNews()
{
$this->executeSfDynamicCMS();
// ... my article action code (business logic) ... //
$this->news=NewsPeer::getLastNewsPublished();
}
first line concern navigation : it just return the current element in navigation tree (if sfDynamicCMS is able to find it).
second line concern page, template and content : it return the current page linked to the navigation element Moreother, this feature automaticaly define page title, page meta-tags and page template.
Usually, the template file used is named with the name of the template and the suffix "Success" like my_templateSuccess.php.
But if a template file named with the name of action and the suffix "Success" exist like indexSuccess.php, it will overide this.
It permits to use page content (structured with a generic template slots) with a specific template defined for a specific action.
Then be carefull, indexSuccess.php will overide your template file if you use index action which is usualy the default action (this may change for a future version).
Templates are not included in sfDynamicCMS, you have to create it.
Example, add in your template 'articleSuccess.php' :
getSlotValue('image')) echo image_tag('/uploads/page/'.$current_page->getImage('image'));
echo $current_page->getRichText('text');
if($page_oeuvre->getSlotValue('author')) echo ''.link_to($current_page->getSlotValue('author'),$current_page->getSlotValue('link')).'
';
$next_node=$current_node->retrieveNextSibling();
if (next_node) echo '.link_to_with_path('next article',$next_node->getFirstInternalUri()).
;
?>
Be carefull, as you see in example, you need to use link_to_with_path (or button_to_with_path or url_for_with_path) for sfDynamicCMS generated links.
Use the 'main_menu' menu defined with sfDynamicCmsAdmin module
<?php use_helper('sfDynamicCMS'); ?>
<div id="menu"><?php
$options=array('class'=>'elem','node_template'=>'<li id="menu-%%STRIPPED_TITLE%%">%%LINK%%','title'=>'%%TITLE%%','link_content'=>'<span>%%TITLE%%</span>');
$options_selected=array('class'=>'elem-sel','node_template'=>'<li id="menu-%%STRIPPED_TITLE%%-sel">%%LINK%%','link_content'=>'<span>%%TITLE%%</span>');
echo sfDynamicCMSMenu('main_menu',1,false,$options,$options_selected);
?></div>
Use the children node of current node to generate a submenu for current section.
components.class.php :
public function executeSubmenu()
{
//get current first level navigation element (main menu opened)
$this->current_section = sfDynamicCMS::getInstance()->getCurrentNode(1);
}
_submenu.php
<?php } ?>
This method is used in link_to_node helper and every helper using it (like sfDynamicCMSMenu).
getFirstInternalUri() method try to get the first uri to node containing a page by browsing down the tree. If no node containing a page is found, it return uri to the current node.
Example 1 : If you have a node which is only a section's title (no content) named "activities" containing several pages like "e-commerce", "intranet", etc. A call to getFirstInternalUri() on "activities" node will return a symfony uri on "activities/e-commerce" because activities have no content and is only a section title.
Example 2 : If you have a node which use custom routing to use your own module like "product catalog" and then has no page assigned to. This node has no child. A call to getFirstInternalUri() on this node will return a symfony uri to "product".
Then the aim is to have a main menu on your website with different type of link : link to a page, link to a section, link to your own module. You should used getFirstInternalUri() method to retrieve symfony uri on menu elements to retrieve Symfony uri to the web pages associated to.
In opposition to Symfony routing system, sfDynamic navigation is organize in a hierarchy. So route rules are organize in a tree and URL can be relative which is impossible with routing.yml rules.
The aim is to have a tree managed navigation which permit :
CMS pages with automated route & url management system. The you can give to your client the ability to manage their website easily like in every CMS : they don't care about url or route (and they don't have access to it).
Dynamic pages (like a product catalog) using the url, the extension, the module, the action and the parameters you want for a given element (like in Symfony) to not loose Symfony flexibility and had business logic. By this way, your own-design modules can use sfDynamicCMS features.
So it is possible to combine cms advantages and simplicity for your client with your custom-built modules which use all the powerfull features offered by Symfony and sfDynamicCMS.
Root element url might be "/" or "/my_cms"
Children element url can be relative or absolute (but on first level it is the same because route url is "/"). Absolute url start with a "/" and relative url doesn't. It is also possible to have default url which is a relative url generated automaticaly with menu name (stripped menu name) and hard url (to be used in menu generation) starting with http://.
Then there is 4 kinds of url :
default url generated automaticaly (leave the url field empty)
relative url : a word (eg: "about-the-company" or "company/team") which will be concateneted with parent url to generate the final url
absolute url : an url starting with a "/" (eg: "/my-custom-url") which don't care of parent element, url is what you want.
hard url : an url starting with "http://" : usefull when you generate menu which contain external (or e-mail - to come) links.
Url can have like in routing.yml rules : "" character or parameters (eg: "books/:book_id/") but you might have to use custom routing in this case.
After defining the way to call the page, "the url", you have to define how it reacts. Then sfDynamicCMS permits 3 ways to define a route :
Default routing : route managed automaticaly by sfDynamicCMS
Custom routing : route managed by sfDynamicCMS, same routing parameters that routing.yml can be defined, you have the advantage to have a tree routing feature and route recognize by the CMS.
Traditionnal routing : routing rules defined in routing.yml of the application. Not recommanded but possible.
By using Custom routing, sfDynamicCMSAdmin module generate rules in routing.yml (without erasing your own rules). sfDynamicCMS will recognize this kind of rules. This way is usefull to merge your business logic with cms features offered by sfDynamicCMS.
By using Default way, there is nothing to define, route is managed automaticaly but not permit to have use a specific module or action. Default routing doesn't appear in routing.yml, this rules are executed after custom and traditionnal routing rules.
Traditionnal rules can defined in routing.yml before or after the sfDynamicCMS rules (which are automaticaly updated). Be carefull because sfDynamicCMS might not be able to find where are located this rules in sfDynamicCMS navigation tree.
@sfDynamicCMS_homepage : main homepage (default culture)
@sfDynamicCMS_culture_homepage : homepage of the current culture*
@sfDynamicCMS_culture_homepage?sf_culture=xx : homepage of the xx culture
@sfDynamicCMS?url=... : link by url (might be unusefull, use sfDynamicCMS helper)
@sfDynamicCMS_custom_route_xx : custom route (xx = Node ID)
this route is set only if sfDynamicCMS is used in a multilingual context
Please note that this plugin is in perpetual development. If you want to help and improve it, please contact Sylvain Papet (my firstname @ com-ocean.com).
Business logic :
"version" = nav (navigation tree) => SfDynamicCmsNav class & sf_dynamic_cms_nav table
"navigation element" = node (navigation node) => SfDynamicCmsNode class & sf_dynamic_cms_node table
"Page" = page => SfDynamicCmsPage class & sf_dynamic_cms_page table
"Menu" = menu => SfDynamicCmsMenu class & sf_dynamic_cms_menu table
The plugin has 2 main goals :
manage navigation and version
manage pages and content The aim is to have independance between these 2 logics
sfDynamicCMS class :
sfDynamicCMS : represent current version: the sfDynamicCMS navigation. Use in your module to perform navigation management.
sfDynamicCMSTools : static functions to use in extended module and static function used by sfDynamicCMSAdmin
model classes : for nav, node, page & slot
slotType classes : used in sfDynamicCMSAdmin & model (works look-like sfSimpleCms slots)
A lot of things can be refactored and improved.
@sfDynamicCMS_homepage & @sfDynamicCMS_culture_homepage rules badly work when root nodes use custom routing.
Be carefull, some custom routes can overide default routes in some case.
Example : Parent node "Videos" : url="/video" (1) (default routing)
Node "myVideoPage" : url="myPage" (2) (default routing, cms page)
Node "myVideo" : url=":video_param" (3) (custom routing, custom module using a video database)
(absolute url are respectively: "/video", "/video/myPage", "/video/:video_param")
Limitation : Even if "myVideoPage" node is placed before "myVideo", 3rd node rule will overide 2nd node rule. There is 2 solutions to resolve it.
First solution : add a prefix to "myVideo" url :
Second solution : Define a custom routes for "myVideoPage" and fill module and action with default module and default action.
An other solution, if "video_param" is a number, add requirement for video_id parameter.
This version contains Break Compatibility mainly because slots are outsourced to sfPropelSlotBehavior plugin and schema is updated.
Upgrade from 0.2.x to 0.3 : * first make a backup of your database and your project * install sfPropelSlotBehaviorPlugin 0.1.4 (see requirements section of this doc ) and create sfSlots table in your Database * upgrade sfDynamicCMSPlugin to 0.3.x * rebuild your model (symfony propel-build-model) * clear cache * launch ugrade process http://www.my_domain.tld/backend.php/sfDynamicCMSAdmin/upgrade (MySQL) * when you are sure that all work fine, you can delete "sf_dynamic_cms_slot" table
Changes: * in frontend app.yml, for slots & templates description : you should rename "name" to "title" * Be careful Node's isVisible() and getVisibleChildren() methods might be used instead of isPublished() and getPublishedChildren() method for menu(s)
Upgrade note : You need for each version to regenerate routing config file(s) & database : http://www.my_domain.tld/backend.php/sfDynamicCMSAdmin/generateRouting
sylvio : downgrade to Alpha (Beta was not correct in precedent version)
sylvio : BC (Break compatibility) in sf_dynamic_node table :
"name" field renamed "url" field and "url" field renamed "absolute_url" field, then use getUrl() instead of getName() in template
ALTER TABLE `sf_dynamic_cms_node` CHANGE `url` `absolute_url` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
ALTER TABLE `sf_dynamic_cms_node` CHANGE `name` `url` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL

