TomatoCMS in A Nutshell
-
Upload
siwawong-wuttipongprasert -
Category
Technology
-
view
2.992 -
download
0
description
Transcript of TomatoCMS in A Nutshell
TomatoCMS in A Nutshell
www.tomatocms.com
Table of Content
TomatoCMS : Background
TomatoCMS : Architecture
TomatoCMS : System Design
TomatoCMS : Components
TomatoCMS : Features (Current & New)
TomatoCMS : Background
Pre-Requisition PHP 5.2 or higher (PHP 5.2 is able to use but need to modify index.php)
MySQL server 5.0 or higher (Default/Recommend)
Background Knowledge Zend Framework – Not required jQuery – Should be MVC/OOP – Strong required PHP – Just familiar with web developer is OK Familiar with any CMS
(ASP.NET or PHP)
TomatoCMS Overview
A content management system based-on
OS Independents
Cross-Platforms
Multiple DBs
Web Server (with mod_rewrite)
Not support on IE6.0
The concept is …
Problem: Here is what we want to have on website
The concept is …
Imagine how it can be created
The concept is …
How to define the width of container / widget? => use 960 Grid System (12 columns)
The concept is …
How to define the layout? Construct the nested containers …
The concept …
How to define the layout? … and widget
We made it because …
How to manage layout?• Edit the layout file (XML file) manually• Visual Layout Editor: drag, drop, configure, preview
Demonstration Live-demo
You get the idea !!! 1 page = n * containers1 container = n * containers + m * widgets
TomatoCMS : Architecture
TomatoCMS : Stack View
3rd PartyCSSTidy
HTML Purifier
JSMin
PclZip ZFDebug
Tomato Library
Tomato_Autoloader
Tomato_Config
Tomato_GlobalKey
Tomato_Hook
Tomato_Language
Tomato_Layout
Tomato_Widget
Tomato_Zip
Tomato_Cache
Tomato Core Module
Standard Modules 3rd Party Modules
CSSTidy
HTML Purifier
JSMin
PclZip
ZFDebug
TomatoCMS : Layer View3rd
Par
ty
Tomato Library
Tomato_AutoloaderTomato_Autoloader
Tomato_ConfigTomato_Config
Tomato_GlobalKeyTomato_GlobalKey
Tomato_HookTomato_Hook
Tomato_LanguageTomato_Language
Tomato_LayoutTomato_Layout
Tomato_WidgetTomato_Widget
Tomato_ZipTomato_Zip
Tomato_CacheTomato_Cache
Tomato Core Module
Standard/3rd Party Modules Extension/Add-on
Web Application Framework
General/CommonLibrary
Application Framework
TomatoCMS : Stack View 3rd Party Library
Zend Framework 1.0 It’s ASP.NET3.5 Clone
CSSTidy allow CSS Parser and
Optimizer
HTML Purifier 4.1.0 Standards Compliant HTML
Filtering
JSMin Compress JavaScript for PHP
PclZip PHP library that manage ZIP
archives ZFDebug
Debugging code in Zend Framework
TomatoCMS : Stack View
Tomato Library Tomato_Autoloader: inherit from
Zend_Loader_Autoloader_ResourceZend_Loader_Autoloader_Resource
Tomato_Cache: manage Cache for Front-end & Back-end
Tomato_Config: read/manage configuration file Tomato_GlobalKey: HTTP logging Tomato_Hook: based class for Hook components Tomato_Language: Manage language packs for each
module/widget Tomato_Layout: Manage layout for front-end Tomato_Widget: Widget abstract class for manage
Widget componts Tomato_Version: Version of TomatoCMS (stable is 2.0.8) Tomato_Zip: Zip file management (refer to PclZip)
TomatoCMS : Stack View
Tomato Core Module: Handle & management TomatoCMS
Core Action : Behind the scene Authentication Cache Config Hook Locale
Bundle Feature : Support in back-end & Front-end Dashboard Language Log Message Module Page
Permalink Plugin Privillege Resource Role Rule
Target Template ** User Widget
TomatoCMS : Components Modules
Set of codes/container of components (i.e. widgets & hooks)
Inside modules Routing Languages Model ~ View ~ Controller Widgets Plug-in Hook ** Services **
Widgets Snip code for some interaction with user (e.g. display
feed) Inside widgets
Languages View ~ Model (rare)
TomatoCMS : Components (2) Plugin
Set of codes that work on “Pre-Dispatch” or “Post-Dispatch”
2 Levels access: - Global (not belong to any modules) Module (depended on module)
Hook Set of codes that work during “Pre-Dispatch” and “Post-
Dispatch” 2 Levels access: -
Global (not belong to any modules) Module (depended on module)
Plugin & Hook can’t access the DB layer
TomatoCMS : Naming
File & Class Naming: General Concept File Name : “CamelCase” with the first letter capitalized. Class Name : Mixed folder/sub-folder and separate by “_”
(Underscore) Apply to all components/libraries in TomatoCMS
Components Naming : “module” level Class naming : <Module Name>_<Sub Module>_<Class
Name> File Name: \application\ <Module Name>\<Sub Module>\
<Class Name>.php
Components Naming : Global level Class naming : <Component Type>_<Object Name>_<Type
Name> File Name: \application\ <Component Type>\<Object Name>\
<Type Name>.php Apply on : Hooks, Plug-ins
TomatoCMS : Naming
TomatoCMS Libraries (\libraries\Tomato) Start with “Tomato_Tomato_” and no need to inherit from any class Format: “Tomato_<Folder>_<Sub-Folder>_<Class Name>”
e.g. Tomato_Cache_File \libraries\Tomato\Cache\File.php Auto-loading when required to use
TomatoCMS Global Hooks (\ application\hooks) Format: “Hooks_<Hook Name>_Hook”
e.g. Hooks_BadWordsCensor_Hook \application\hooks\badwordscensor\Hook.php
TomatoCMS Global Plugin (\ application\plugins) Format: “Plugins_<Plugin Name>_Plugin”
e.g. Plugins_AdminAccess_Plugin \application\plugin\AdminAccess\Plugin.php
TomatoCMS : Naming
TomatoCMS Components (\application\modules) Basic Idea:
Class Name : <Module Name>_<Sub-Folder Name>_<Resource Name>
File Name : \appliation\modules\ <Module Name>\<Sub-Folder Name>\<Resource Name>.php
Controller: <Module Name>_<Resource Name>Controller e.g. Ad_BannerController \application\modules\ad\controllers\
BannerController.php Must extended from “Zend_Controller_Action”
Others Follow above rule Models ~ DAO ~ Interface Services Widgets
TomatoCMS : Folder Structure
v2.0.5 v2.0.6v2.0.7v2.0.8 (Stable)
v2.0.9v2.1.0 (Beta)
application
config
hooks
modules core **
moduleplugins
templates
js
libraries
skins
ZF
Tomato
3rd Party
config Remove in v.2.1.0
hooks
modules core **
moduleplugins
templates
js
libraries
skins
ZF
Tomato
3rd Party
In application folder before!
TomatoCMS : Why Change?
Easy to add 3rd party files on each module e.g. CSS JavaScript
Access resources (modules/widgets) via URL e.g. the thumbnails of modules/widgets
Change Model layer: “Fat Model, thin Controller” principle Easy to do unit-testing Able to perform other actions e.g. cache data, validate input,
integrate Zend_Form (in the future), etc.
Refer to : http://forum.tomatocms.com/viewtopic.php?f=41&t=937&p=2303&hilit=structure#p2303
TomatoCMS : System Design
TomatoCMS : System Design
System Overview Understand Zend Framework (ZF) MVC ZF Implementation in TomatoCMS TomatoCMS: Data Access Layer (DAL) TomatoCMS: Model vs DAL
System Overview
Request
TomotoCMS
Index.php
Bootstrap.phpBootstrap.php
Load Controller
Load Controller
Response
RenderView
RenderView
Load
Initialize everything
LoadData Object
LoadData Object
Call
Access
Understand ZF MVC M-V-C in Zend Framework ZF MVC : Structure ZF MVC : Behavior ZF MVC : Flow
M-V-C in ZF Zend_M…?
Model s can be very different : DB, Web-Services, Feeds, … etc.
For example: - Zend_Db (Adaptor Pattern) Zend_Service Zend_Feed Etc.
Zend_Controller Front Controller pattern Zend_Controller_Action
action methods correspond to various actions you wish the controller to be handle
Zend_View template system agnostic Zend_Layout: implement “Two Steps View” pattern
Refer to: http://www.slideshare.net/webholics/mvc-with-zend-framework
ZF MVC : StructureZend_ApplicationZend_Application
Zend_Controller_FrontZend_Controller_Front
Zend_Db_Table_AbstractZend_Db_Table_Abstract Zend_Controller_ActionZend_Controller_Action
Zend_ViewZend_View
ZF MVC : Behavior
Client
Request dispatch() route()
dispatch()action1Action()
render() action1.php
Response
ZF MVC : Flow
The basic Zend Framework workflow of handling a request is fairly simple.
Refer to: http://www.slideshare.net/Tricode/zend-framework-02-mvc-4977880
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)First the Request is ‘captured’
and aRequest Object is made. The Request Object is just a representation of the Request
itself.
By default the HTTP Request Object is
used. It holds attributes like the URL
and parameters.
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)
Secondly the Router is called.
The Router checks the Request Object, and alters it depending on registered Routes.
By default the Rewrite Router is used. This Router sets the controller, action and parameters from the URL.
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)
After the Routing is done, the Dispatch Loop is started.
The Dispatch Loop is performed until the status of the Request Object is set to ‘dispatched’.
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)The default Dispatcher is the Standard Dispatcher.
This Dispatcher defines controllers as UpperCamelCase classes that end with Controller, and derfines actions as lowerCamelCase methods ending with Action.
FooController::barAction()
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)
Next, the Action Controller is called.
This is the Controller that you have created yourself.
Like this:
/foo/bar
FooController::barAction()
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)
The Action Controller often implements a View.
As the View is rendered, the output is added to the Response Object.
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)After the Action Controller has finished the Dispatcher Loop normally finishes.
If the Action Controller resetted the Dispatched status of the Request Object, the Loop continues, and a new Dispatch is triggered.
For instance you can forward to another Action.
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF MVC : Flow (Cont’)At last the Response is sent back.
By default the Response used is the http Response.
Request Router preDispatch
Dispatcher
postDispatch
Actions left?
RequestObject
Action Controller
Send Response
Response Object
ZF Implementation in TomatoCMS MVC Structure
Not use : Zend_Db_Table Data Access : implement by Tomato Entity Class
MVC Behavior Same as standard ZF
Bootstrap Initialize useful classes for TomatoCMS
MVC Flow Same as standard ZF
ZF MVC Structure : Implementation
Zend_ApplicationZend_Application
Zend_Controller_FrontZend_Controller_Front
Zend_Db_Table_AbstractZend_Db_Table_Abstract Zend_Controller_ActionZend_Controller_Action
Zend_ViewZend_View
Not Used
BootStrap : TomatoCMS Heart-beat
Bootstrap
Zend_Application_Bootstrap_BootstrapZend_Application_Bootstrap_Bootstrap
BootStrap : Methods _initAutoload() Method
Register class name & auto-loading when required See naming conversion : Auto-Loader will look-up
Class/File conversion rule.
_initRoutes() Method Avoiding standard routing in ZF Routing: define in INI files under folder “\application\modules\<Module Name>\config\routes”
_initSession() Method Initialize session variables for store information Doesn’t allow to access session variable directly.
BootStrap : Methods (2) _initActionHelpers() method
Extend “Controllers action” automatically Standard Action-Helper : CSRF protection User-Defined Action-Helper: \Libraries\Tomato\Controller\Action\Helper
_initPlugins() methods Extend “dispatcher” automatically Standard Plug-in loaded when start TomatoCMS
Core_Controllers_Plugin_Init() Tomato_Controller_Plugin_Admin() Tomato_Controller_Plugin_Template() Core_Controllers_Plugin_HookLoader() Core_Controllers_Plugin_Auth() Core_Controllers_Plugin_Permalink() Tomato_Controller_Plugin_LocalizationRoute() Zend_Controller_Plugin_ErrorHandler()
TomatoCMS: DAL DAL = Data Access Layer Avoiding “Zend_Db_Table_Abstract” using
“Tomato_Db_Connection” Multiple support 3 kind of DBs
MySQL (with PDO and without PDO) MS-SQL (testing with 2005 & 2008) PostgreSQL Never tested
TomatoCMS: DAL structure
Tomato_Db_ConnectionTomato_Db_ConnectionTomato_Db_ConnectionTomato_Db_Connection
Connection(PDO_MySQL)Connection(PDO_MySQL)
Connection(MySQL)
Connection(MySQL)
Connection(PqSQL)
Connection(PqSQL)
Connection(MS-SQL)Connection(MS-SQL)
Tomato_Db_Connection_AbstractTomato_Db_Connection_AbstractTomato_Db_Connection_AbstractTomato_Db_Connection_Abstract
TomatoCMS: DAL Architecture
Tomato_Db_ConnectionTomato_Db_ConnectionTomato_Db_ConnectionTomato_Db_Connection
factory(contained $class of Tomato_Db_Connection_AbstractTomato_Db_Connection_Abstract))
getSlaveConnection()getSlaveConnection()getMasterConnection()getMasterConnection()
DB DB
• Purpose for Load-Balancing• Master & Slave : can be the same DB or different DB
• Purpose for Load-Balancing• Master & Slave : can be the same DB or different DB
TomatoCMS: Model vs DAO
Tomato_Model_EntityTomato_Model_EntityTomato_Model_EntityTomato_Model_Entity
Tomato_Model_DaoTomato_Model_DaoTomato_Model_DaoTomato_Model_Dao
Tomato_Db_ConnectionTomato_Db_ConnectionTomato_Db_ConnectionTomato_Db_Connection
MyModelMyModelMyModelMyModel
TomatoCMS: Model vs DALModel
Data encapsulation Only Properties for mapping table purpose
DAL Contain Business Logic Contain SQL native 1 Class = 1 DB type
TomatoCMS: DAL MechanismModel/DAO able to call from- Controller- Services (*)
$conn = Tomato_Db_Connection::factory()->getMasterConnection();$bannerDao = Tomato_Model_Dao_Factory::getInstance()
->setModule('ad') ->getBannerDao();$bannerDao->setDbConnection($conn);……$id = $bannerDao->add($banner);
$conn = Tomato_Db_Connection::factory()->getMasterConnection();$bannerDao = Tomato_Model_Dao_Factory::getInstance()
->setModule('ad') ->getBannerDao();$bannerDao->setDbConnection($conn);……$id = $bannerDao->add($banner);
$conn(Tomato_Db_Connection) DB
$bannerDAO(Tomato_Model_Dao_Factory)
setDBConnection
(Load by adapter type)
(*) Since 2.0.9, Controller won’t declare $conn/$Dao variables anymore. Services Object will handle this case
(*) Since 2.0.9, Controller won’t declare $conn/$Dao variables anymore. Services Object will handle this case
TomatoCMS : Components
TomatoCMS : Components TypeModule
Services Widgets View-Helpers Action-Helpers
Plug-insHooks
TomatoCMS: Components Original idea for components in TomatoCMS
Able to install/Uninstall easier we’ve GUI for configuration : Module ~ Plug-in ~ Hooks ~
Widget Scalability Modular system
TomatoCMS: Module Set of codes/container of components
Each module will not interface other modules Each module able to access other modules Each module able to depended on other modules Following “Modular Design” Principle
Inside modules Routing : Mapping URL with Action in Controller Languages : Multi-languages pack (e.g. EN, VN, TH, etc. Model ~ View ~ Controller : Already explain in previous chapter Widgets : Snip codes for interactive with user Plug-in ~ Hook : Explain next section Services : Independent class for re-used in module or between module View-Helper: aka, User-Control (in ASP.NET) reusable code for
view/display
TomatoCMS: Module StructureFor example: - “Comments” module
• /config/ contain XML files for identify module• /config/routes defined routing (mapping URL with Controller’s action)• /controllers• /languages contained language pack files (in INI)• /models• /views contained html file for display on GUI• /views/helpers contained view-helper code• /widgets contained widget code/html for display
TomatoCMS: Module Configuration
• Easy for installation• Dependency requirements• Able to upload directly to server
TomatoCMS: Module’s Components Main Components M~V~C objects Optional Components
Services e.g. get data from DB, calculation logic, business logic, etc.
Widget Some widget can has their own DAO/model
Plug-in/Hook View Helper
Same concept of “User Control” in ASP.NET Able to share between module
Action Helper Similar to “httpModule” in ASP.NET (2.0 or higher) Work automatically when URL has request
TomatoCMS: Plug-In Work with “Controller” object
Automatically work Bootstrap has load some plug-ins to work User able to defined plug-ins to load while start-up by
add plug-in name in “application.ini”
Work on 2 events type: - preDispatch
e.g. Auth (in Core module) Admin (in Tomato’s library)
postDispatch Localization ActionCache
TomatoCMS: Hook Hook
Working between preDispatch() and postDispatch() 2 types of Hooks: -
Filter Action
Hook Target Declare in “controller” Enabled “extra” flow to work
TomatoCMS: Hook (Cont’)e.g. class “Core_AuthController”
Has Hook
?
ExecuteHook
Other lines of codeHook
Target
TomatoCMS: Hook Target
Register “Hook” that related to the code