mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
428 lines
20 KiB
Markdown
428 lines
20 KiB
Markdown
# 3.0.0 (unreleased) #
|
|
|
|
## Overview ##
|
|
|
|
* New template engine
|
|
* New CMS interface design
|
|
* "Page Content" and "Page Settings" are split into two interfaces
|
|
* Image/Link insertion moved into a modal dialog instead of a sidebar
|
|
* "Add pages" dropdown moved to a more descriptive modal dialog
|
|
* Allow usage of "sapphire" framework without the "cms" module
|
|
* CMS JavaScript moved to [jQuery.entwine](https://github.com/hafriedlander/jquery.entwine)
|
|
* CMS stylesheets are generated by SCSS to provide more flexible and robust styling
|
|
|
|
## Upgrading ##
|
|
|
|
### New ORM: More flexible and expressive querying via `DataList` ###
|
|
|
|
The new "fluent" syntax to retrieve ORM records allows for a more
|
|
expressive notation (instead of unnamed arguments).
|
|
|
|
:::php
|
|
// before
|
|
DataObject::get('Member', '"FirstName" = \'Sam'\', '"Surname" ASC");
|
|
// after
|
|
DataList::create('Member')->filter(array('FirstName' => 'Sam'))->sort('Surname');
|
|
|
|
The underlying record retrieval and management is rewritten from scratch, and features
|
|
lazy loading which fetches only the records it needs, as late as possible.
|
|
In order to retrieve all ORM records manually (as the previous ORM would've done),
|
|
please use `DataList->toArray()`.
|
|
|
|
The old getters (`DataObject::get()`, `DataObject:;get_one()`, `DataObject::get_by_id()`)
|
|
are now deprecated, but continue to operate. Instead of a `DataObjectSet`, they'll
|
|
now return a `DataList`.
|
|
|
|
:::php
|
|
// before
|
|
DataObject::get_one('Member', '"Email" = \'someone@example.com\'');
|
|
// after
|
|
DataList::create('Member')->filter('Email', 'someone@example.com')->First();
|
|
|
|
:::php
|
|
// before
|
|
DataObject::get_by_id('Member', 5);
|
|
// after
|
|
DataList::create('Member')->byID(5);
|
|
|
|
Note that they will return a `DataList` even if they're empty, so if you want to check
|
|
for the presence of records, please call the count() method on the `DataList`:
|
|
|
|
:::php
|
|
// before
|
|
if(!DataObject::get('SiteTree', '"ParentID" = 5')) echo "Page 5 has no children";
|
|
// after
|
|
if(!DataObject::get('SiteTree', '"ParentID" = 5')->count()) echo "Page 5 has no children";
|
|
|
|
See the ["datamodel" documentation](../../topics/datamodel) for more details.
|
|
|
|
### New ORM: Changes to manipulation of SQL queries ###
|
|
|
|
In the 2.4 ORM it was sometimes necessary to bypass the ORM for performance reasons. For example,
|
|
this command would have been intolerably slow:
|
|
|
|
:::php
|
|
DataList::create('SiteTree')->count();
|
|
|
|
The 3.0 ORM is more intelligent gives you tools you need to create high-performance code without
|
|
bypassing the ORM:
|
|
|
|
:::php
|
|
// before
|
|
echo DB::query("SELECT COUNT(*) FROM \"SiteTree\"")->value();
|
|
// after
|
|
echo DataList::create('SiteTree')->count()
|
|
|
|
Both `extendedSQL()` and `buildSQL()` have been deprecated. There is not currently any way of
|
|
overriding the query generation code equivalent to overriding `buildSQL()` in 2.4, but this facility
|
|
was error prone. If you need to access the `SQLQuery` object, you can call `->dataQuery()->query()`
|
|
on any DataList. Note that modifications to this query will **not** be passed back into the DataList.
|
|
|
|
:::php
|
|
// before
|
|
$query = singleton('SiteTree')->extendedSQL('ParentID = 5');
|
|
// after
|
|
$query = DataList::create('SiteTree')->filter('ParentID', 5)->dataQuery()->query();
|
|
|
|
We advise that you keep this kind of code to a minimum and that you use the DataList wherever possible.
|
|
If you find yourself needing to bypass the ORM in SilverStripe 3, we suggest you raise this
|
|
as a discussion topic on silverstripe-dev@groups.google.com, as we may want to add more tools to
|
|
the ORM to help you.
|
|
|
|
### New ORM: Better encapsulation of relationship queries with `RelationList` ###
|
|
|
|
The abstract `RelationList` class and its implementations `ManyManyList` and `HasManyList`
|
|
are replacing the `ComponentSet` API, which is only relevant if you have instanciated these manually.
|
|
Relations are retrieved through the same way (e.g. `$myMember->Groups()`).
|
|
|
|
### InnoDB driver for existing and new tables on MySQL (instead of MyISAM) ###
|
|
|
|
SilverStripe has traditionally created all MySQL tables with the MyISAM storage driver,
|
|
mainly to ensure a fulltext search based on MySQL works out of the box.
|
|
Since then, the framework has gained many alternatives for fulltext search
|
|
([sphinx](https://github.com/silverstripe/silverstripe-sphinx), [solr](https://github.com/nyeholt/silverstripe-solr), etc.), and relies more on database transactions and other features not available in MyISAM.
|
|
|
|
This change convert tables on existing databases when `dev/build` is called,
|
|
unless the `FullTextSearch` feature is enabled. In order to disable this behaviour,
|
|
you have to add the following code to your `_config.php` BEFORE running a `dev/build`:
|
|
|
|
:::php
|
|
DataObject::$create_table_options['MySQLDatabase] = 'ENGINE=MyISAM';
|
|
|
|
As with any SilverStripe upgrade, we recommend database backups before calling `dev/build`.
|
|
See [mysql.com](http://dev.mysql.com/doc/refman/5.5/en/converting-tables-to-innodb.html) for details on the conversion.
|
|
Note: MySQL has made InnoDB the default engine in its [5.5 release](http://dev.mysql.com/doc/refman/5.5/en/innodb-storage-engine.html).
|
|
|
|
### Convert::json2array() changes ###
|
|
|
|
Convert JSON functions have been changed to use built-in json PHP functions `json_decode()` and `json_encode()`
|
|
|
|
Because `json_decode()` will convert nested JSON structures to arrays as well, this has changed the way it worked,
|
|
as before nested structures would be converted to an object instead.
|
|
|
|
So, given the following JSON input to `Convert::json2array()`:
|
|
|
|
{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}
|
|
|
|
Here's the output from SilverStripe 2.4, with nested JSON as objects:
|
|
|
|
array(
|
|
'Joe' => 'Bloggs'
|
|
'Tom' => 'Jones',
|
|
'My' => stdObject(
|
|
Complicated => 'Structure' // property on object
|
|
)
|
|
)
|
|
|
|
Now in SilverStripe 3.x, nested structures are arrays:
|
|
|
|
array(
|
|
'Joe' => 'Bloggs',
|
|
'Tom' => 'Jones',
|
|
'My' => array(
|
|
'Complicated' => 'Structure' // key value on nested array
|
|
)
|
|
)
|
|
|
|
|
|
### GridField: Replacement for TableListField and ComplexTableField ###
|
|
|
|
We have a new component for managing lists of objects: The `[GridField](/topics/grid-field)`.
|
|
It's a substantial rewrite of the features previously captured by `TableListField`,
|
|
`ComplexTableField`, `HasManyComplexTableField` and `ManyManyComplexTableField`.
|
|
|
|
The legacy fields remain operational for now, although a switch to `GridField` is strongly encouraged,
|
|
for stability, interface and performance reasons. The `HasManyComplexTableField` and `ManyManyComplexTableField`
|
|
are no longer maintained, for those you do have to make the switch.
|
|
The `TableField` class will be deprecated soon, but we don't have an adequate replacement for it yet.
|
|
|
|
Upgrade example: Record listing
|
|
|
|
:::php
|
|
// before
|
|
$field = new TableListField('Companies', 'Company');
|
|
$field->setPageSize(20);
|
|
// after
|
|
$field = new GridField('Companies', null, DataList::create('Company'));
|
|
$field->getConfig()->getComponentByType('GridFieldPaginator')->setItemsPerPage(20);
|
|
|
|
Upgrade example: Record listing with view/edit interface
|
|
|
|
:::php
|
|
// before
|
|
$field = new ComplexTableField($myController, 'Companies', 'Company');
|
|
// after
|
|
$field = new GridField('Companies', null, DataList::create('Company'), GridFieldConfig_RecordEditor::create());
|
|
|
|
|
|
Upgrade example: Relationship editing
|
|
|
|
:::php
|
|
// before
|
|
$field = new HasManyComplexTableField($myController, 'MyRelation', 'MyRelationObject');
|
|
// after
|
|
$field = new GridField('MyRelation', null, $myRecord->MyRelation(), GridFieldConfig_RelationEditor::create());
|
|
|
|
More information is available in the [GridField documentation](/topics/grid-field).
|
|
|
|
### New template engine ###
|
|
|
|
The template engine has been completely rewritten, and although it is generally backward compatible, there are new features
|
|
and some features have been deprecated. See the [template upgrading guide](/reference/templates-upgrading-guide) and the
|
|
[template reference](/reference/templates) for more information.
|
|
|
|
### Removed view-specific accessors from ViewableData ####
|
|
|
|
Several methods in ViewableData that were originally added to expose values to the template language were moved,
|
|
in order to stop polluting the namespace. These were sometimes called by project-specific PHP code too, and that code
|
|
will need re-working.
|
|
|
|
See the [template upgrading guide](/reference/templates-upgrading-guide) for a list of methods and their replacements.
|
|
|
|
### New user interface for CMS ###
|
|
|
|
Most aspects of the interface have been redesigned, which necessitated a substantial
|
|
redevelopment of the underlying logic and presentation.
|
|
If you have customized the admin interface in any way, please review
|
|
the detailed changelog for this release. Many interface components have changed completely,
|
|
unfortunately there is no clear upgrade path for every interface detail.
|
|
As a starting point, have a look at the new templates in `cms/templates`
|
|
and `sapphire/admin/templates`, as well as the new [jQuery.entwine](https://github.com/hafriedlander/jquery.entwine)
|
|
based JavaScript logic. Have a look at the new ["Extending the CMS" guide](../howto/extending-the-cms),
|
|
["CSS" guide](../topics/css), ["JavaScript" guide](../topics/javascript) and
|
|
["CMS Architecture" guide](/reference/cms-architecture) to get you started.
|
|
|
|
### New tree library ###
|
|
|
|
The page tree moved from a bespoke tree library to [JSTree](http://jstree.com),
|
|
which required changes to markup of the tree and its JavaScript architecture.
|
|
This includes changes to `TreeDropdownField` and `TreeMultiSelectField`.
|
|
|
|
### Settings-related fields move from `SiteTree->getCMSFields()` to new `SiteTree->getSettingsFields()` ###
|
|
|
|
The fields and tabs are now split into two separate forms, which required a structural
|
|
change to the underlying class logic. In case you have added or removed fields
|
|
in the "Behaviour" or "Access" tab, please move these customizations to a new `getSettingsFields()` method.
|
|
In case of SiteTree extension through `updateCMSFields()` and a decorator/extension,
|
|
please use the new `updateSettingsFields()` instead.
|
|
|
|
### New `SiteTree::$description` field to describe purpose of a page type ###
|
|
|
|
Please use this static property to describe the purpose of your page types,
|
|
which will help users understand the new "Add page" dialog.
|
|
For example, a `TeamPage` type could be described as "Lists all team members, linking to their profiles".
|
|
Note: This property is optional (defaults to an empty string), but its usage is highly encouraged.
|
|
|
|
### New ModelAdmin interface, removed sub-controllers
|
|
|
|
ModelAdmin has been substanially rewritten to natively support the `[api:GridField]` API
|
|
for more flexible data presentation (replacing `[api:ComplexTableField]`),
|
|
and the `[api:DataList]` API for more expressive querying.
|
|
|
|
If you have overwritten any methods in the class, customized templates,
|
|
or implemented your own `$collection_controller_class`/`$record_controller_class` controllers,
|
|
please refer to the new [ModelAdmin documentation](/reference/modeladmin)
|
|
on details for how to achieve the same goals in the new class.
|
|
|
|
### Stylesheet preprocessing via SCSS and the "compass" module ###
|
|
|
|
CSS files in the `cms` and `sapphire/admin` modules are now generated through
|
|
the ["compass" SilverStripe module](http://silverstripe.org/compass-module), which uses
|
|
the ["Compass" framework](http://compass-style.org/) and the ["SCSS" language](http://sass-lang.com/).
|
|
This allows us to build more flexible and expressive stylesheets as a foundation for any
|
|
extensions to the CMS interface.
|
|
|
|
The "compass" module is only required if core stylesheets are modified,
|
|
not when simply using the CMS or developing other CMS functionality.
|
|
If you want to extend the CMS stylesheets for your own projects without SCSS,
|
|
please create a new CSS file and link it into the CMS via `[api:LeftAndMain::require_css()]`.
|
|
|
|
### Built-in Javascript validation removed ###
|
|
|
|
Built-in client-side form validation using `Validator.js` and `behaviour.js` has been removed, and is no longer supported.
|
|
Server-side validation remains. Developers are encouraged to use custom Javascript validation on their
|
|
forms if requiring client-side validation.
|
|
You don't need to explicitly disable JS validation through `Validator::set_javascript_validation_handler()`
|
|
any longer (the method is deprecated).
|
|
|
|
### FormField consistently adds classes to HTML elements ###
|
|
|
|
The [api:FormField] API has been refactored to use SilverStripe templates
|
|
for constructing the field HTML, as well as new accessors for HTML attributes.
|
|
This change makes the HTML a bit more predictable, but it also means that
|
|
you need to check any code (CSS, JavaScript, etc) relying on the old inconsistencies.
|
|
Particularly, CSS class names applied through [api:FormField->addExtraClass()]
|
|
and the "type" class are now consistently added to the container `<div>`
|
|
as well as the HTML form element itself.
|
|
|
|
:::html
|
|
Before (abbreviated):
|
|
<div class="field checkbox extraClass"...>
|
|
<input type="checkbox".../>
|
|
</div>
|
|
|
|
After (abbreviated):
|
|
<div class="field checkbox extraClass"...>
|
|
<input type="checkbox" class="checkbox extraClass".../>
|
|
</div>
|
|
|
|
### FormField constructor argument changes ###
|
|
|
|
In order to enforce a consistent parameter order in core [api:FormField] subclasses,
|
|
its no longer possible to set the following optional attributes via constructor arguments:
|
|
`$form`, `$maxLength`, `$rightTitle`, `$rows`/`$cols` (for `TextareaField` and `HtmlEditorField`)
|
|
and `$folderName` (for `FileField` and `SimpleImageField`).
|
|
Please use the appropriate setters on the form field instance instead.
|
|
|
|
### Restructured files and folders ###
|
|
|
|
In order to make the `sapphire` framework useable without the `cms` module,
|
|
we've moved some files around.
|
|
|
|
CMS base functionality which is not directly related to content pages (`SiteTree`)
|
|
has been moved from the `cms` module into a new "sub-module" located in `sapphire/admin`.
|
|
This includes generic management interfaces like "Files & Images" (`AssetAdmin`),
|
|
"Security" (`SecurityAdmin`) and the `ModelAdmin` class.
|
|
On the other hand, `SiteTree` related features were moved from `sapphire` to the `cms` module.
|
|
|
|
Due to the built-in PHP class autoloader,
|
|
this usually won't have any effect on your own code (unless you're including direct file paths).
|
|
For any other files (CSS files, templates, images, JavaScript) which might
|
|
be referenced by their path, please doublecheck that their path is still valid.
|
|
|
|
### Removed prototype.js and and behaviour.js dependencies from most core components
|
|
|
|
This will only affect you if you used either of those libraries,
|
|
or by extension on the globals set in `prototype_improvements.js` and `jquery_improvements.js`.
|
|
The `$$()` shorthand for `document.getElementsBySelector()` is no longer globally bound,
|
|
but rather just defined when used through other components. The `$()` shorthand
|
|
had two meanings, based on context: Either `document.getElementsById()` through prototype.js,
|
|
or as an alias for the `jQuery()` method. In general, we recommend not to rely on
|
|
the `$()` global in SilverStripe, as we unset it via `[jQuery.noConflict()](http://api.jquery.com/jQuery.noConflict/)`.
|
|
Use a [custom alias via function scope](http://api.jquery.com/jQuery.noConflict/#example-1) if possible.
|
|
|
|
### Moved `Translatable` extension into new 'translatable' module ###
|
|
|
|
If you are translating your `SiteTree` or `DataObject` classes with the `Translatable`
|
|
extension, please install the new module from `http://silverstripe.org/translatable-module`.
|
|
The following settings can be removed from your own `_config.php`, as they're automatically
|
|
included through `translatable/_config.php`:
|
|
|
|
Object::add_extension('SiteTree', 'Translatable');
|
|
Object::add_extension('SiteConfig', 'Translatable');
|
|
|
|
### Moved Group->IPRestrictions into a new 'securityextras' module
|
|
|
|
IP restrictions for group memberships in the "Security" section were a rarely used feature,
|
|
and cluttered up the interface. We've decided to move it to a separate module
|
|
called [securityextras](https://github.com/silverstripe-labs/silverstripe-securityextras).
|
|
To continue using these restrictions, just install the module - no data migration required.
|
|
|
|
### Moved comments system into new 'comments' module ###
|
|
|
|
This affects websites which have comments enabled, through the `$Comments`
|
|
placeholder and the `PageComment` class. See the ['comments' module](https://github.com/silverstripe/silverstripe-comments). To continue using comments, simply install the module - no data migration required.
|
|
|
|
### Moved SiteTree->HomepageForDomain into a new 'homepagefordomain' module
|
|
|
|
The setting determines difference homepages at arbitrary locations in the page tree,
|
|
and was rarely used in practice - so we moved it to a "[homepagefordomain](https://github.com/silverstripe-labs/silverstripe-homepagefordomain)" module.
|
|
|
|
### Removed "auto-merging" of member records from `Member->onBeforeWrite()`
|
|
|
|
Due to security reasons. Please use `DataObject->merge()` explicitly if this is desired behaviour.
|
|
|
|
### Unit tests require definition of used `DataObject` and `Extension` classes ###
|
|
|
|
This change was necessary in order to improve performance of the test framework,
|
|
and avoid rebuilding the database where no database access is required.
|
|
It also won't build any `DataObject` subclasses implementing the `TestOnly` interface,
|
|
unless these are explicitly noted.
|
|
|
|
* `SapphireTest->extraDataObjects`: List all `TestOnly` classes relevant to your test class here.
|
|
* `SapphireTest->requiredExtensions`: Maps `DataObject` classes to an array of required extensions.
|
|
Example: `array("MyTreeDataObject" => array("Versioned", "Hierarchy"))`
|
|
* `SapphireTest->illegalExtensions`: Does the reverse of `requiredExtensions`: Removes already applied extensions.
|
|
|
|
Alternatively, you can enforce database usage by setting `SapphireTest->usesDatabase` to `TRUE` in your test class.
|
|
|
|
### Breadcrumbs ###
|
|
|
|
Breadcrumbs have been altered to be their own template. In the process of this, the common static
|
|
SiteTree::$breadcrumbs_delimiter has been removed. To customise breadcrumbs now, create a template
|
|
BreadcrumbsTemplate.ss from cms/template to your theme or application.
|
|
|
|
### Deprecation API ###
|
|
|
|
There is a new deprecation API that generates deprecation notices. Calls to Deprecated methods
|
|
will only produce errors if the API was deprecated in the release equal to or earlier than the
|
|
"notification version".
|
|
|
|
`sapphire/_config.php` currently contains a call to throw notices calls to all methods deprecated
|
|
in 3.0.
|
|
|
|
Deprecation::notification_version('3.0.0');
|
|
|
|
If you change the notification version to 3.0.0-dev, then only methods deprecated in older versions
|
|
(e.g. 2.4) will trigger notices, and the other methods will silently pass. This can be useful if
|
|
you don't yet have time to remove all calls to deprecated methods.
|
|
|
|
Deprecation::notification_version('3.0.0-dev');
|
|
|
|
### Deprecated Classes ###
|
|
|
|
* `ComplexTableField`: Use `GridField` instead
|
|
* `DataObjectDecorator`: Use `DataExtension` instead
|
|
* `DataObjectSet`: Use `DataList` instead
|
|
* `FileIframeField`: Use `UploadField`
|
|
* `HasManyComplexTableField`: Use `GridField` instead
|
|
* `ImageField`: Use `UploadField` with `$myField->allowedExtensions = array('jpg', 'gif', 'png')`
|
|
* `ManyManyComplexTableField`: Use `GridField` instead
|
|
* `SimpleImageField`: Use `FileField` or `UploadField` with `setAllowedExtensions()`
|
|
* `TableListField`: Use `GridField` instead
|
|
|
|
### Renamed Classes ###
|
|
|
|
* `CMSMainMarkingFilter`: Use `CMSSiteTreeFilter_Search` instead *
|
|
* `DataObjectDecorator`: Use `DataExtension` instead (the class doesn't implement the [GOF "Decorator" pattern](http://en.wikipedia.org/wiki/Decorator_pattern))
|
|
* `MySQLFulltextSearchable`: Use `FulltextSearchable` instead
|
|
|
|
### Removed Classes ###
|
|
|
|
* `Archive`, `TarballArchive`: If you make use of these, copy the classes from 2.4 into your project.
|
|
* `AssetTableField`: Use `GridField` with `GridFieldConfig_RelationEditor` instead
|
|
* `ComponentSet`: Use `ManyManyList` or `HasManyList`
|
|
* `CustomRequiredFields`: Use `RequiredFields`
|
|
* `DataObjectLog`: There is no replacement for this.
|
|
* `DataObjectSet`: Use `ArrayList` or `DataList` instead
|
|
* `FieldSet`: Use `FieldList` instead
|
|
* `GeoIP`: Moved to separate ["geoip" module](https://github.com/silverstripe-labs/silverstripe-geoip)
|
|
* `MemberTableField`: Use `GridField` with `GridFieldConfig_RelationEditor` instead
|
|
* `Notifications`: If you make use of this, copy the classes from 2.4 into your project.
|
|
* `NZGovtPasswordValidator`: Moved to ["securityextras" module](https://github.com/silverstripe-labs/silverstripe-securityextras)
|
|
* `QueuedEmail`, `QueuedEmailDispatchTask`: If you make use of these, copy the classes from 2.4 into your project.
|
|
* `RestrictedTextField`, `UniqueTextField`, `UniqueRestrictedTextField`, `AutocompleteTextField`, `ConfirmedFormAction`: Use custom fields instead
|
|
* `SQLMap`: Use `SS_Map` instead
|
|
* `TreeSelectorField`: Use `TreeDropdownField` instead.
|
|
* `XML`: Use PHP's built-in SimpleXML instead
|