Here's a blog post for all you hard-core developers.
This week we are merging a number of exciting changes from a development branch - known as "branches/roa" to some - into the main subversion trunk release. Those of you who wish to access these features early will be able to do so by using the subversion trunk or the daily builds.
Update: These features have been merged into the main trunk and stabilised.
With these features, we are improving the usefulness not just of SilverStripe CMS, but of Sapphire, the underlying application framework that we developed in-house to power the CMS. The common thread in all these new features is that, by increasing the intelligence of the model layer, we are able to provide an out-of-the-box application with a completed user interface, that tailors itself to the data model that it is given.
The SilverStripe CMS is a good example of this: you are able to easily customise the content fields available on each page, but the overall CMS interface is there for you out of the box, and is fairly consistent from site-to-site. These new developments take the paradigm that we successfully applied to content management, and extend it to support a wider range of applications, such a CRM systems.
Historically, we haven't said a lot about the Sapphire framework, but you can expect this to change. The Sapphire framework is becoming an increasingly important part of the software that SilverStripe produces.
So, what are these new features? Here is a quick sneak-preview of what they will all be; more detailed developer documentation will be available soon.
ModelAdmin is a revised version of GenericDataAdmin, re-written from the ground up. It lets you build a sophistic data management application solely by defining the data model that you wish to manage. It is supported by two more general enhancements: SearchContext and scaffolding. Both of these enhancements are part of the Sapphire framework, usable in a wide range of applications beyond CMSes.
SearchContext is a class that eases the creation of a search form and the generation of its result set. It is used to make the search system in both ModelAdmin and RestfulServer.
Given a set of search filter definitions, it will create an appropriate search form, and then it will create a SQL query when that form is submitted. As well as searching on fields of the the DataObject itself, it also lets you traverse DataObject relationships to search by fields in related objects. For example, suppose that we have an Organisation DataObject. Instead of having its address fields directly on it, has a 1-many relationship with an OrganisationLocation DataObject. If you were to define the following on your Organisation object, then ModelAdmin and other users of the search context would be able to search for Organisation objects by looking for related OrganisationLocation objects.
static $searchable_fields = array(
"Name" => array(
"OrganizationLocations.State.ID" => array(
"title" => "State",
"OrganizationLocations.City" => array(
"title" => "City",
Our scaffolding system is a way of generating sets of FormFields for editing a DataObject, based its definition. For example, a Varchar would be editable with a TextField, and an Enum would be editable with a DropdownField. SilverStripe takes this a step further, and can generate fields for editing relationships as well as regular fields. For example, a ComplexTableField is generated for a has_many relationship, and a ComplexTableField with an autocomplete facility is generated for a many_many relationship.
To access the scaffolded fields, just call getCMSFields() on any DataObject. ModelAdmin uses this to build its add & edit forms for records.
The RestfulServer is another system that makes use of this enhanced data model to provide you more useful functionality out of the box.
On any of your data objects, simply specify static $api_access = true;. You will then be able to access your database using RESTful requests. All the the requests start with /api/v1, which is handled by the RestfulServer controller. Here are some example requests that you could make on the RESTful server, if you set Page::$api_access to true:
- GET http://www.example.com/api/v1/Page/36.xml: Get Page record #36 in an XML format.
- GET http://www.example.com/api/v1/Page/24/Children.json: Get all the children of page #24 in JSON format.
- PUT http://www.example.com/api/v1/Page/24.json: Update page #24 using JSON format.
Security is configured using the canView() and canEdit() methods on your data-objects, and RESTful users can authenticate themselves by sending their regular log-in details over HTTP basic authentication.
New URL Hander
As part all this work on ModelAdmin we've improved the URL handler that processes requests. To give an example, consider the processing of the URL "admin/crm/Organisation/36/edit".
Historically, a URL such has this would have been handled by a single Controller. It would have been up to that controller to identify the different URL components and amend the responses of all handler functions accordingly.
Now, however, the URL is processed by a chain of controllers and sub-controllers:
- admin/crm directs Sapphire to the ModelAdmin class you have created
- Organisation/36 directs to a special "sub-controller" that will handle any requests about Organisation #36 within that model admin.
- edit is an action on that sub-controller. Specifically, it will provide the interface for editing Organisation #36.
The URLs can be arbitrarily deep. This makes it easier create complex FormField subclasses that have their own behaviour such as pop-ups or ajax responses. In particular, we used this new URL handler to clean up the internals of ComplexTableField.
That covers the changes that I wanted to introduce! I'll update this post once we have merged these changes back.
Post your comment
Comments for this post are now closed.