silverstripe-framework/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md

242 lines
7.7 KiB
Markdown
Raw Normal View History

# How to extend the CMS interface #
## Introduction ##
2014-11-07 20:43:57 +01:00
The CMS interface works just like any other part of your website: It consists of
PHP controllers, templates, CSS stylesheets and JavaScript. Because it uses the
same base elements, it is relatively easy to extend.
2014-11-07 20:43:57 +01:00
As an example, we're going to add a permanent "bookmarks" link list to popular pages
into the main CMS menu. 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
2016-01-14 11:59:53 +01:00
guide on [CMS Architecture](/developer_guides/customising_the_admin_interface/cms_architecture).
2011-11-22 11:06:46 +01:00
## Overload a CMS template ##
2014-11-07 20:43:57 +01:00
If you place a template with an identical name into your application template
directory (usually `mysite/templates/`), it'll take priority over the built-in
one.
2011-11-22 11:06:46 +01:00
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).
2011-11-22 11:06:46 +01:00
We can use this to create a different base template with `LeftAndMain.ss`
(which corresponds to the `LeftAndMain` PHP controller class).
2014-11-07 20:43:57 +01:00
Copy the template markup of the base implementation at `framework/admin/templates/Includes/LeftAndMain_Menu.ss`
into `mysite/templates/Includes/LeftAndMain_Menu.ss`. It will automatically be picked up by
the CMS logic. Add a new section into the `<ul class="cms-menu-list">`
2014-11-07 20:43:57 +01:00
2011-11-22 11:06:46 +01:00
:::ss
...
<ul class="cms-menu-list">
<!-- ... -->
<li class="bookmarked-link first">
<a href="admin/pages/edit/show/1">Edit "My popular page"</a>
</li>
<li class="bookmarked-link last">
<a href="admin/pages/edit/show/99">Edit "My other page"</a>
</li>
</ul>
2011-11-22 11:06:46 +01:00
...
2014-11-07 20:43:57 +01:00
Refresh the CMS interface with `admin/?flush=all`, and you should see those
2014-11-07 20:43:57 +01:00
hardcoded links underneath the left-hand menu. We'll make these dynamic further down.
2011-11-22 11:06:46 +01:00
## Include custom CSS in the CMS
2014-11-07 20:43:57 +01:00
In order to show the links a bit separated from the other menu entries,
we'll add some CSS, and get it to load
with the CMS interface. Paste the following content into a new file called
`mysite/css/BookmarkedPages.css`:
2011-11-22 11:06:46 +01:00
:::css
.bookmarked-link.first {margin-top: 1em;}
Load the new CSS file into the CMS, by setting the `LeftAndMain.extra_requirements_css`
[configuration value](../../configuration).
2013-04-05 15:34:29 +02:00
:::yml
LeftAndMain:
extra_requirements_css:
2015-07-15 16:36:19 +02:00
- mysite/css/BookmarkedPages.css
2011-11-22 11:06:46 +01:00
## Create a "bookmark" flag on pages ##
2014-11-07 20:43:57 +01:00
Now we'll define which pages are actually bookmarked, a flag that is stored in
the database. For this we need to decorate the page record with a
`DataExtension`. Create a new file called `mysite/code/BookmarkedPageExtension.php`
and insert the following code.
2011-11-22 11:06:46 +01:00
:::php
<?php
2011-11-22 11:06:46 +01:00
class BookmarkedPageExtension extends DataExtension {
private static $db = array(
'IsBookmarked' => 'Boolean'
);
2014-11-07 20:43:57 +01:00
public function updateCMSFields(FieldList $fields) {
2011-11-22 11:06:46 +01:00
$fields->addFieldToTab('Root.Main',
new CheckboxField('IsBookmarked', "Show in CMS bookmarks?")
);
}
}
2011-11-22 11:09:43 +01:00
Enable the extension in your [configuration file](../../configuration)
2011-11-22 11:06:46 +01:00
:::yml
SiteTree:
extensions:
- BookmarkedPageExtension
2011-11-22 11:09:43 +01:00
2011-11-22 11:06:46 +01:00
In order to add the field to the database, run a `dev/build/?flush=all`.
Refresh the CMS, open a page for editing and you should see the new checkbox.
## Retrieve the list of bookmarks from the database
One piece in the puzzle is still missing: How do we get the list of bookmarked
2014-11-07 20:43:57 +01:00
pages from the database into the template we've already created (with hardcoded
links)? Again, we extend a core class: The main CMS controller called
`LeftAndMain`.
2011-11-22 11:09:43 +01:00
Add the following code to a new file `mysite/code/BookmarkedLeftAndMainExtension.php`;
2011-11-22 11:09:43 +01:00
2011-11-22 11:06:46 +01:00
:::php
<?php
2011-11-22 11:06:46 +01:00
class BookmarkedPagesLeftAndMainExtension extends LeftAndMainExtension {
public function BookmarkedPages() {
return Page::get()->filter("IsBookmarked", 1);
2011-11-22 11:06:46 +01:00
}
}
2014-11-07 20:43:57 +01:00
Enable the extension in your [configuration file](../../configuration)
2011-11-22 11:06:46 +01:00
:::yml
LeftAndMain:
extensions:
- BookmarkedPagesLeftAndMainExtension
2011-11-22 11:06:46 +01:00
As the last step, replace the hardcoded links with our list from the database.
Find the `<ul>` you created earlier in `mysite/admin/templates/LeftAndMain.ss`
2011-11-22 11:06:46 +01:00
and replace it with the following:
:::ss
<ul class="cms-menu-list">
<!-- ... -->
<% loop $BookmarkedPages %>
<li class="bookmarked-link $FirstLast">
<li><a href="admin/pages/edit/show/$ID">Edit "$Title"</a></li>
</li>
2012-06-26 17:32:46 +02:00
<% end_loop %>
2011-11-22 11:06:46 +01:00
</ul>
2011-11-22 11:09:43 +01:00
## Extending the CMS actions
2014-11-07 20:43:57 +01:00
CMS actions follow a principle similar to the CMS fields: they are built in the
backend with the help of `FormFields` and `FormActions`, and the frontend is
responsible for applying a consistent styling.
The following conventions apply:
2014-11-07 20:43:57 +01:00
* New actions can be added by redefining `getCMSActions`, or adding an extension
with `updateCMSActions`.
2014-11-07 20:43:57 +01:00
* It is required the actions are contained in a `FieldSet` (`getCMSActions`
returns this already).
2014-11-07 20:43:57 +01:00
* Standalone buttons are created by adding a top-level `FormAction` (no such
button is added by default).
2014-11-07 20:43:57 +01:00
* Button groups are created by adding a top-level `CompositeField` with
`FormActions` in it.
* A `MajorActions` button group is already provided as a default.
2014-11-07 20:43:57 +01:00
* Drop ups with additional actions that appear as links are created via a
`TabSet` and `Tabs` with `FormActions` inside.
2014-11-07 20:43:57 +01:00
* A `ActionMenus.MoreOptions` tab is already provided as a default and contains
some minor actions.
2014-11-07 20:43:57 +01:00
* You can override the actions completely by providing your own
`getAllCMSFields`.
Let's walk through a couple of examples of adding new CMS actions in `getCMSActions`.
2014-11-07 20:43:57 +01:00
First of all we can add a regular standalone button anywhere in the set. Here
we are inserting it in the front of all other actions. We could also add a
button group (`CompositeField`) in a similar fashion.
:::php
$fields->unshift(FormAction::create('normal', 'Normal button'));
2014-11-07 20:43:57 +01:00
We can affect the existing button group by manipulating the `CompositeField`
already present in the `FieldList`.
:::php
$fields->fieldByName('MajorActions')->push(FormAction::create('grouped', 'New group button'));
2014-11-07 20:43:57 +01:00
Another option is adding actions into the drop-up - best place for placing
infrequently used minor actions.
:::php
$fields->addFieldToTab('ActionMenus.MoreOptions', FormAction::create('minor', 'Minor action'));
2014-11-07 20:43:57 +01:00
We can also easily create new drop-up menus by defining new tabs within the
`TabSet`.
:::php
$fields->addFieldToTab('ActionMenus.MyDropUp', FormAction::create('minor', 'Minor action in a new drop-up'));
<div class="hint" markdown='1'>
Empty tabs will be automatically removed from the `FieldList` to prevent clutter.
</div>
2014-11-07 20:43:57 +01:00
To make the actions more user-friendly you can also use alternating buttons as
detailed in the [CMS Alternating Button](cms_alternating_button)
how-to.
### Implementing handlers
Your newly created buttons need handlers to bind to before they will do anything.
To implement these handlers, you will need to create a `LeftAndMainExtension` and add
applicable controller actions to it:
:::php
class CustomActionsExtension extends LeftAndMainExtension {
private static $allowed_actions = array(
'sampleAction'
);
public function sampleAction()
{
// Create the web
}
}
The extension then needs to be registered:
:::yaml
LeftAndMain:
extensions:
- CustomActionsExtension
You can now use these handlers with your buttons:
:::php
$fields->push(FormAction::create('sampleAction', 'Perform Sample Action'));
2011-11-22 11:06:46 +01:00
## Summary
In a few lines of code, we've customised the look and feel of the CMS.
2011-11-22 11:06:46 +01:00
While this example is only scratching the surface, it includes most building
blocks and concepts for more complex extensions as well.
## Related
* [Reference: CMS Architecture](../cms_architecture)
* [Reference: Layout](../cms_layout)
* [Rich Text Editing](/developer_guides/forms/field_types/htmleditorfield)
* [CMS Alternating Button](cms_alternating_button)