From 7d46e7e7512dff5f423903727363c0ff4a44076c Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sun, 1 Jan 2012 18:24:09 +0100 Subject: [PATCH] MINOR Added CMS architecture documentation --- docs/en/howto/extend-cms-interface.md | 9 +- .../en/reference/_images/cms-architecture.png | Bin 0 -> 77410 bytes docs/en/reference/cms-architecture.md | 183 ++++++++++++++++++ docs/en/reference/leftandmain.md | 177 ----------------- docs/en/reference/modeladmin.md | 6 +- docs/en/topics/css.md | 15 +- 6 files changed, 198 insertions(+), 192 deletions(-) create mode 100644 docs/en/reference/_images/cms-architecture.png create mode 100644 docs/en/reference/cms-architecture.md delete mode 100644 docs/en/reference/leftandmain.md diff --git a/docs/en/howto/extend-cms-interface.md b/docs/en/howto/extend-cms-interface.md index 648dfb28c64..6be63dbe880 100644 --- a/docs/en/howto/extend-cms-interface.md +++ b/docs/en/howto/extend-cms-interface.md @@ -8,6 +8,9 @@ it is relatively easy to extend. As an example, we're going to add a permanent "bookmarks" bar to popular pages at the bottom of the CMS. A page can be bookmarked by a CMS author through a simple checkbox. +For a deeper introduction to the inner workings of the CMS, please refer to our +guide on [CMS Architecture](../reference/cms-architecture). + ## Overload a CMS template ## First of all, create a new folder structure in your SilverStripe webroot, which will @@ -136,4 +139,8 @@ and replace it with the following: In a few lines of code, we've customized the look and feel of the CMS. While this example is only scratching the surface, it includes most building -blocks and concepts for more complex extensions as well. \ No newline at end of file +blocks and concepts for more complex extensions as well. + +## Related + + * [CMS Architecture](../reference/cms-architecture) \ No newline at end of file diff --git a/docs/en/reference/_images/cms-architecture.png b/docs/en/reference/_images/cms-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..fbbc477d1a1bbab37f7ea7193c2b144f62859007 GIT binary patch literal 77410 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 literal 0 HcmV?d00001 diff --git a/docs/en/reference/cms-architecture.md b/docs/en/reference/cms-architecture.md new file mode 100644 index 00000000000..94f61e84fd4 --- /dev/null +++ b/docs/en/reference/cms-architecture.md @@ -0,0 +1,183 @@ +# CMS architecture + +## Introduction + +A lot can be achieved in SilverStripe by adding properties and form fields +to your own page types (via `[api:SiteTree->getCMSFields()]`), as well as creating +your own data management interfaces through `[api:ModelAdmin]`. But sometimes +you'll want to go deeper and tailor the underlying interface to your needs as well. +For example, to build a personalized CMS dashboard, or content "slots" where authors +can drag their content into. At its core, SilverStripe is a web application +built on open standards and common libraries, so lots of the techniques should +feel familiar to you. This is just a quick run down to get you started +with some special conventions. + +For a more practical-oriented approach to CMS customizations, refer to the +[Howto: Extend the CMS Interface](../howto/extend-cms-interface) which builds + + +## Markup and Style Conventions + +While SilverStripe is intended to work with JavaScript only, +we're following the principles of "[Progressive Enhancement](http://en.wikipedia.org/wiki/Progressive_enhancement)" +where feasible, relying on a comparatively light layer of JavaScript to enhance +forms and markup generated on the server. This allows seamless customization of +aspects like form fields. We're explaining this philosophy in more detail +on our [blog](http://www.silverstripe.org/the-3-0-ui-a-better-framework-for-your-ideas/)). + +All CSS in the CMS UI is written in the [SCSS language extensions](http://sass-lang.com/) +and the [Compass framework](http://compass-style.org/), which helps +us maintain expressive and concise style declarations. The files are located in `sapphire/admin/scss` +(and if you have the `cms` module installed, in `cms/scss`), and are compiled to a `css` folder on the +same directory path. Changes to the SCSS files can be automatically converted by installing +the ["compass" module](http://www.silverstripe.org/compass-module/) for SilverStripe, +although [installing the compass framework](http://compass-style.org/install/) directly works as well. +Each file describes its purpose at the top of the declarations. Note that you can write +plain CSS without SCSS for your custom CMS interfaces as well, we just mandate SCSS for core usage. + +As there's a whole lot of CSS driving the CMS, we have certain best practives around writing it: + * Use the `id` attribute sparingly. Remember that it "closes off" the structure to code reuse, as HTML elements + require unique `id` attributes. Code reuse can happen both in CSS and JavaScript behaviour. + * Separate presentation from structure in class names, e.g. `left-menu` is encoding the component position + (which might change later on). A more structural name could be `cms-menu` (or `cms-tools-menu` for a more specific version) + * Class naming: Use the `cms-` class prefix for major components in the cms interface, + and the `ss-ui-` prefix for extensions to jQuery UI. Don't use the `ui-` class prefix, its reserved for jQuery UI built-in styles. + * Use jQuery UI's built-in styles where possible, e.g. `ui-widget` for a generic container, or `ui-state-highlight` + to highlight a specific component. See the [jQuery UI Theming API](http://jqueryui.com/docs/Theming/API) for a full list. + +See our [system requirements](../installation/server-requirements) for a list of supported browsers. + +## Templates and Controllers + +The CMS backend is handled through the `[api:LeftAndMain]` controller class, +which contains base functionality like displaying and saving a record. +This is extended through various subclasses, e.g. to add a group hierarchy (`[api:SecurityAdmin]`), +a search interface (`[api:ModelAdmin]`) or an "Add Page" form (`[api:CMSPageAddController]`). + +The controller structure is too complex to document here, a good starting point +for following the execution path in code are `[api:LeftAndMain->getRecord()]` and `[api:LeftAndMain->getEditForm()]`. +If you have the `cms` module installed, have a look at `[api:CMSMain->getEditForm()]` for a good +example on how to extend the base functionality (e.g. by adding page versioning hints to the form). + +CMS templates are inherited based on their controllers, similar to subclasses of +the common `Page` object (a new PHP class `MyPage` will look for a `MyPage.ss` template). +We can use this to create a different base template with `LeftAndMain.ss` +(which corresponds to the `LeftAndMain` PHP controller class). +In case you want to retain the main CMS structure (which is recommended), +just create your own "Content" template (e.g. `MyCMSController_Content.ss`), +which is in charge of rendering the main content area apart from the CMS menu. + +Depending on the complexity of your layout, you'll also need to overload the +"EditForm" template (e.g. `MyCMSController_EditForm.ss`), e.g. to implement +a tabbed form which only scrolls the main tab areas, while keeping the buttons at the bottom of the frame. +This requires manual assignment of the template to your form instance, see `[api:CMSMain->getEditForm()]` for details. + +## Layout and Panels + +The CMS markup is structured into "panels", which are the base units containing +interface components (or other panels), as declared by the class `cms-panel`. Panels can be made collapsible, and +get the ability to be resized and aligned with a layout manager, in our case [jLayout](http://www.bramstein.com/projects/jlayout/). +This layout manager applies CSS declarations (mostly dimensions and positioning) via JavaScript, +by extracting additional metadata from the markup in the form of HTML5 data attributes. +We're using a "border layout" which separates the panels into five areas: north, south, east, west and center (all of which are optional). +As layouts can be nested, this allows for some powerful combinations. Our +[Howto: Extend the CMS Interface](../howto/extend-cms-interface) has a practical example on +how to add a bottom panel to the CMS UI. + +The various panels and UI components within them are not tightly coupled +to the layout engine, so any changes in dimension which impact the overall layout +need to be handled manually. In SilverStripe, we've established a convention for a `redraw()` +method on each panel and UI component for this purpose, which is usually invoked +through its parent container. Invocation order is crucial here, generally going from +innermost to outermost elements. For example, the tab panels have be applied in the CMS form +before the form itself is layouted with its sibling panels to avoid incorrect dimensions. + +![Layout variations](_images/cms-architecture.png) + +## Forms + +SilverStripe constructs forms and its fields within PHP, +mainly through the `[getCMSFields()](api:DataObject->getCMSFields())` method. +This in turn means that the CMS loads these forms as HTML via Ajax calls, +e.g. after saving a record (which requires a form refresh), or switching the section in the CMS> + +## JavaScript through jQuery.entwine + +[jQuery.entwine](https://github.com/hafriedlander/jquery.entwine) is a thirdparty library +which allows us to attach behaviour to DOM elements in a flexible and structured mannger. +It replaces the `behaviour.js` library used in previous versions of the CMS interface. +See [Topics: JavaScript](../topics/javascript) for more information on how to use it. +In the CMS interface, all entwine rules should be placed in the "ss" entwine namespace. +If you want to call methods defined within these rules outside of entwine logic, +you have to use this namespace, e.g. `$('.cms-menu').entwine('ss').collapse()`. + +Note that only functionality that is custom to the CMS application needs to be built +in jQuery.entwine, we're trying to reuse library code wherever possible. +The most prominent example of this is the usage of [jQuery UI](http://jqueryui.com) for +dialogs and buttons. + +## JavaScript and CSS dependencies via Requirements and Ajax + +The JavaScript logic powering the CMS is divided into many files, +which typically are included via the `[api:Requirements]` class, by adding +them to `[api:LeftAndMain->init()]` and its subclassed methods. +This class also takes care of minification and combination of the files, +which is crucial for the CMS performance (see `[api:Requirements::combine_files()]`). + +Due to the procedural and selector-driven style of UI programming in jQuery.entwine, +it can be difficult to find the piece of code responsible for a certain behaviour. +Therefore it is important to adhere to file naming conventions. +E.g. a feature only applicable to `ModelAdmin` should be placed in +`sapphire/admin/javascript/ModelAdmin.js`, while something modifying all forms (including ModelAdmin forms) +would be better suited in `sapphire/admin/javascript/LeftAndMain.EditForm.js`. +Selectors used in these files should mirrow the "scope" set by its filename, +so don't place a rule applying to all form buttons inside `ModelAdmin.js`. + +The CMS relies heavily on Ajax-loading of interfaces, so each interface and the JavaScript +driving it have to assume its underlying DOM structure is appended via Ajax callback +rather than being available when the browser window first loads. +jQuery.entwine is effectively an advanced version of [jQuery.live](http://api.jquery.com/live/) +and [jQuery.delegate](http://api.jquery.com/delegate/), so takes care of dynamic event binding. + +Most interfaces will require their own JavaScript and CSS files, so the Ajax loading has +to ensure they're loaded unless already present. A custom-built library called +`jQuery.ondemand` (located in `sapphire/thirdparty`) takes care of this transparently - +so as a developer just declare your dependencies through the `[api:Requirements]` API. + +## Ajax Loading and Browser History + +SilverStripe uses the HTML5 browser history to modify the URL without a complete window refresh, +and load its UI via Ajax by hooking into browser navigation events (through the +[history.js](https://github.com/balupton/History.js/) wrapper library). +This technique has an impact on how any Ajax load needs to happen: +In order to support browser history (and change the URL state), +a CMS developer needs to fire a navigation event rather than invoking the Ajax call directly. + +The main point of contact here is `$('.cms-container').loadPanel(, , <data>)` +in `LeftAndMain.js`. The `data` object can contain additional state which is required +in case the same navigation event is fired again (e.g. when the user pressed the back button). +Most commonly, the (optional) `data.selector` property declares which DOM element to replace +with the newly loaded HTML (it defaults to `.cms-content`). This is handy to only replace +e.g. an edit form, but leave the search panel in the same "content area" unchanged. + +No callbacks are allowed in this style of Ajax loading, as all state needs +to be "repeatable". Any logic required to be exected after the Ajax call +should be placed in jQuery.entinwe `onmatch()` rules which apply to the newly created DOM structures. +See `$('.cms-container').handleStateChange()` in `LeftAndMain.js` for details. + +Alternatively, form-related Ajax calls can be invoked through their own wrappers, +which don't cause history events and hence allow callbacks: `$('.cms-content').loadForm()` +and `$('.cms-content').submitForm()`. + +## Menu + +The navigation menu in the CMS is created through the `[api:CMSMenu]` API, +which auto-detects all subclasses of `LeftAndMain`. This means that your custom +`ModelAdmin` subclasses will already appear in there without any explicit definition. +To modify existing menu entries or create new ones, see `[api:CMSMenu::add_menu_item()]` +and `[api:CMSMenu::remove_menu_item()]`. + +## Related + + * [Howto: Extend the CMS Interface](../howto/extend-cms-interface) + * [Reference: ModelAdmin](../reference/modeladmin) \ No newline at end of file diff --git a/docs/en/reference/leftandmain.md b/docs/en/reference/leftandmain.md deleted file mode 100644 index b131d9f8781..00000000000 --- a/docs/en/reference/leftandmain.md +++ /dev/null @@ -1,177 +0,0 @@ -# LeftAndMain - -## Introduction - -LeftAndMain is the base class of all the admin area controllers. - -## Best Practices - -### Custom Access Checking - -You can customize access control in `[api:LeftAndMain]`. - - :::php - // mysite/_config.php - LeftAndMain::add_extension('MyLeftAndMain'); - - // MyLeftAndMain.php - class MyLeftAndMain extends Extension { - function augumentInit() { - // add custom requirements etc. - } - function alternateAccessCheck() { - // custom permission checks, e.g. to check for an SSL-connection, or an LDAP-group-membership - } - } - - -## Subclassing - -There are a few steps in creating a subclass of LeftAndMain. - -### MyAdmin.php - -The PHP file defining your new subclass is the first step in the process. This provides a good starting point: - - :::php - class MyAdmin extends LeftAndMain { - - static $url_segment = 'myadmin'; - static $url_rule = '$Action/$ID'; - static $menu_title = 'My Admin'; - static $menu_priority = 60; - - public function init() { - Requirements::javascript('cms/javascript/MyAdmin.js'); - parent::init(); - } - - /** - * Form which will be shown when we open one of the items - */ - public function getEditForm($id = null) { - return new Form($this, "EditForm", - new FieldList( - new ReadonlyField('id #',$id) - ), - new FieldList( - new FormAction('go') - ) - ); - } - } - - -### Templates - -Next, create templates, (classname)_left.ss and (classname)_right.ss. Again, here are a couple of starting points: - - * On the left, we're using the tree as a way of providing navigation. The left and side could be replaced with -anything but LeftAndMain has built-in support for trees. - * On the right, we have the skeleton that the form will be loaded into. - -MyAdmin_left.ss - - :::ss - <div class="title"><div>Functions</div></div> - - <div id="treepanes"> - <div id="sitetree_holder" style="overflow:auto"> - <% if Items %> - <ul id="sitetree" class="tree unformatted"> - <li id="$ID" class="root Root"><a>Items</a> - <ul> - <% control Items %> - <li id="record-$class"> - <a href="admin/my/show/$ID">$Title</a> - </li> - <% end_control %> - </ul> - </li> - </ul> - <% end_if %> - </div> - </div> - - -MyAdmin_right.ss - - :::ss - <div class="title"><div>My admin</div></div> - - <% if EditForm %> - $EditForm - <% else %> - <form id="Form_EditForm" action="admin/my?executeForm=EditForm" method="post" enctype="multipart/form-data"> - <p>Welcome to my $ApplicationName admin section. Please choose something from the left.</p> - </form> - <% end_if %> - - <p id="statusMessage" style="visibility:hidden"></p> - - - -### Customising the main menu - -*Minimum Requirement: Silverstripe 2.3* - -The static variable $url_segment determines the sub url of the controller. -The static variable $url_rule has the url format for the actions performed by the class. -The static variable $menu_title is the title of the administration panel in the menu. -The static variable $menu_priority tells the CMS where to put the menu item relative to other panels. - -For example: - - :::php - static $url_segment = 'myadmin'; - static $url_rule = '$Action/$ID'; - static $menu_title = 'My Admin'; - static $menu_priority = 60; - - -See also `[api:CMSMenu]` - -### Translatable Menu Titles - -Override the function getMenuTitle() to create a translated menu title name. Eg: - - :::php - public function getMenuTitle() { - return _t('LeftAndMain.MYADMIN', 'My Admin', PR_HIGH, 'Menu title'); - - - -## 'onload' javascript in the CMS {#onload-javascript} - - -You can have custom scripting called when a Page is loaded by clicking on the Site Content Tree. -This can be used to set up event handlers, or populate dropdowns, etc. -You could insert this code using Requirements from a custom page class. - - :::js - Behaviour.register({ - '#Form_EditForm' : { - initialize : function() { - this.observeMethod('PageLoaded', this.adminPageHandler); - this.adminPageHandler(); - }, - adminPageHandler : function() { - // Place your custom code here. - } - } - }); - -See [Javascript in the CMS](/topics/javascript#javascript-cms) - -## Related - -* `[api:CMSMain]` -* `[api:AssetAdmin]` -* `[api:SecurityAdmin]` -* `[api:ModelAdmin]` - -## TODO - -* Explain how to build the javascript file -* Explain how the ajax button handlers work -* Explain how to create little pop-up dialogs diff --git a/docs/en/reference/modeladmin.md b/docs/en/reference/modeladmin.md index 977076c4b1e..4e81868fc7d 100644 --- a/docs/en/reference/modeladmin.md +++ b/docs/en/reference/modeladmin.md @@ -111,5 +111,7 @@ customized for each `[api:DataObject]`'s search results using `$summary_fields`. ## Related * `[api:SearchContext]` -* [genericviews Module](http://silverstripe.org/generic-views-module) -* [Presentation about ModelAdmin at SupperHappyDevHouse Wellington](http://www.slideshare.net/chillu/modeladmin-in-silverstripe-23) +* [genericviews Module](http://silverstripe.org/generic-views-module) +* [Presentation about ModelAdmin at SupperHappyDevHouse Wellington](http://www.slideshare.net/chillu/modeladmin-in-silverstripe-23) +* [Reference: CMS Architecture](../reference/cms-architecture) +* [Howto: Extend the CMS Interface](../howto/extend-cms-interface) \ No newline at end of file diff --git a/docs/en/topics/css.md b/docs/en/topics/css.md index 39ecd0e6ffe..3605d7f079a 100644 --- a/docs/en/topics/css.md +++ b/docs/en/topics/css.md @@ -86,18 +86,9 @@ file. Then with this file you can define styles for the CMS or just import the s See [typography](/reference/typography) for more information. -## Writing good stylesheets for the CMS ## - - * Use the `id` attribute sparingly. Remember that it "closes off" the structure to code reuse, as HTML elements - require unique `id` attributes. Code reuse can happen both in CSS and JavaScript behaviour. - * Separate presentation from structure in class names, e.g. `left-menu` is encoding the component position - (which might change later on). A more structural name could be `cms-menu` (or `cms-tools-menu` for a more specific version) - * Class naming: Use the `cms-` class prefix for major components in the cms interface, - and the `ss-ui-` prefix for extensions to jQuery UI. Don't use the `ui-` class prefix, its reserved for jQuery UI built-in styles. - * Use jQuery UI's built-in styles where possible, e.g. `ui-widget` for a generic container, or `ui-state-highlight` - to highlight a specific component. See the [jQuery UI Theming API](http://jqueryui.com/docs/Theming/API) for a full list. - ## Related ## * [javascript](javascript) - * ["Compass" module](http://silverstripe.org/compass-module/): Allows writing CSS in SASS/LESS syntax, with better code management through mixins, includes and variables \ No newline at end of file + * ["Compass" module](http://silverstripe.org/compass-module/): Allows writing CSS in SASS/LESS syntax, with better code management through mixins, includes and variables + * [Reference: CMS Architecture](../reference/cms-architecture) + * [Howto: Extend the CMS Interface](../howto/extend-cms-interface) \ No newline at end of file