silverstripe-framework/docs/en/changelogs/3.1.0.md

237 lines
12 KiB
Markdown
Raw Normal View History

# 3.1.0 (unreleased)
## Overview ##
2012-12-17 00:36:23 +01:00
### CMS
* "Split view" editing with side-by-side preview of the edited website
* Resizing of preview to common screen widths ("desktop", "tablet" and "smartphone")
* Decluttered "Edit Page" buttons by moving minor actions into a "more options" panel
* Auto-detect CMS changes and highlight the save button for better informancy
* Display "last edited" and "last published" data for pages in CMS
* CMS form fields now support help text through `setDescription()`, both inline and as tooltips
* Removed SiteTree "MetaTitle" and "MetaKeywords" fields
* More legible and simplified tab and menu styling in the CMS
### Framework
* `DataList` and `ArrayList` are now immutable, they'll return cloned instances on modification
* Behaviour testing support through [Behat](http://behat.org), with CMS test coverage
(see the [SilverStripe Behat Extension]() for details)
* Removed legacy table APIs (e.g. `TableListField`), use GridField instead
* Deny URL access if `Controller::$allowed_actions` is undefined
* Removed support for "*" rules in `Controller::$allowed_actions`
* Removed support for overriding rules on parent classes through `Controller::$allowed_actions`
* `RestfulService` verifies SSL peers by default
2012-12-17 00:36:23 +01:00
* Editing of relation table data (`$many_many_extraFields`) in `GridField`
* Optional integration with ImageMagick as a new image manipulation backend
* Support for PHP 5.4's built-in webserver
* Support for [Composer](http://getcomposer.org) dependency manager (also works with 3.0)
## Upgrading
### Deny URL access if `Controller::$allowed_actions` is undefined or empty array
In order to make controller access checks more consistent and easier to
understand, the routing will require definition of `$allowed_actions`
on your own `Controller` subclasses if they contain any actions
accessible through URLs, or any forms.
:::php
class MyController extends Controller {
// This action is now denied because no $allowed_actions are specified
public function myaction($request) {}
}
Please review all rules governing allowed actions in the
["controller" topic](/topics/controller).
### Removed support for "*" rules in `Controller::$allowed_actions`
The wildcard ('*') character allowed to define fallback rules
in case they weren't explicitly defined. This caused a lot of confusion,
particularly around inherited rules. We've decided to remove the feature,
you'll need to specificy each accessible action individually.
:::php
class MyController extends Controller {
public static $allowed_actions = array('*' => 'ADMIN');
// Always denied because not explicitly listed in $allowed_actions
public function myaction($request) {}
// Always denied because not explicitly listed in $allowed_actions
public function myotheraction($request) {}
}
Please review all rules governing allowed actions in the
["controller" topic](/topics/controller).
### Removed support for overriding rules on parent classes through `Controller::$allowed_actions`
Since 3.1, the `$allowed_actions` definitions only apply
to methods defined on the class they're also defined on.
Overriding inherited access definitions is no longer possible.
:::php
class MyController extends Controller {
public static $allowed_actions = array('myaction' => 'ADMIN');
public function myaction($request) {}
}
class MySubController extends MyController {
// No longer works
public static $allowed_actions = array('myaction' => 'CMS_ACCESS_CMSMAIN');
}
This also applies for custom implementations of `handleAction()` and `handleRequest()`,
which now have to be listed in the `$allowed_actions` specifically.
It also restricts `Extension` classes applied to controllers, which now
can only grant or deny access or methods they define themselves.
New approach with the [Config API](/topics/configuration)
:::php
class MySubController extends MyController {
public function init() {
parent::init();
Config::inst()->update('MyController', 'allowed_actions',
array('myaction' => 'CMS_ACCESS_CMSMAIN')
);
}
}
Please review all rules governing allowed actions in the
["controller" topic](/topics/controller).
### Grouped CMS Buttons
The CMS buttons are now grouped, in order to hide minor actions by default and declutter the interface.
This required changing the form field structure from a simple `FieldList`
to a `FieldList` which contains a `CompositeField` for all "major actions",
and a `TabSet` with a single tab for all "minor actions".
If you have previously added, removed or altered built-in CMS actions in any way,
you'll need to adjust your code.
:::php
class MyPage extends Page {
function getCMSActions() {
$actions = parent::getCMSActions();
// Inserting a new toplevel action (old)
$actions->push(new FormAction('MyAction'));
// Inserting a new toplevel action (new)
$actions->insertAfter(new FormAction('MyAction'), 'MajorActions');
// Removing an action, both toplevel and nested (no change required)
$actions->removeByName('action_unpublish');
// Inserting a new minor action (new)
$actions->addFieldToTab(
'Root.ActionMenus.MoreOptions',
new FormAction('MyMinorAction')
);
// Finding a toplevel action (no change required)
$match = $actions->dataFieldByName('action_save');
// Finding a nested action (new)
$match = $actions->fieldByName('ActionMenus.MoreOptions')
->fieldByName('action_MyMinorAction');
return $actions;
}
}
### GridField and ModelAdmin Permission Checks
`GridFieldDetailForm` now checks for `canEdit()` and `canDelete()` permissions
on your model. `GridFieldAddNewButton` checks `canCreate()`.
The default implementation requires `ADMIN` permissions.
You'll need to loosen those permissions if you want other users with CMS
access to interact with your data.
Since `GridField` is used in `ModelAdmin`, this change will affect both classes.
Example: Require "CMS: Pages section" access
:::php
class MyModel extends DataObject {
public function canView($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
public function canEdit($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
public function canDelete($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
public function canCreate($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
You can also implement [custom permission codes](/topics/permissions).
For 3.1.0 stable, we aim to further simplify the permission definitions,
in order to reduce the boilerplate code required to get a model editable in the CMS.
Note: GridField is already relying on the permission checks performed
through the CMS controllers, providing a simple level of security.
### RestfulService verifies SSL peers by default
This makes the implementation "secure by default", by removing
the call to `curl_setopt(CURLOPT_SSL_VERIFYPEER, false)`.
Failing to validate SSL peers makes HTTP requests vulnerable to man in the middle attacks.
The underlying `curl` library relies on the operating system for the resulting CA certificate
verification. On some systems (mainly Windows), these certificates are not available on
a standard PHP installation, and need to be added manually through `CURLOPT_CAINFO`.
Although it is not recommended, you can restore the old insecure behaviour with
the following configuration: `RestfulService::set_default_curl_option(CURLOPT_SSL_VERIFYPEER, false)`.
### Other
* `TableListField`, `ComplexTableField`, `TableField`, `HasOneComplexTableField`, `HasManyComplexTableField` and `ManyManyComplexTableField` have been removed from the core and placed into a module called "legacytablefields" located at https://github.com/silverstripe-labs/legacytablefields
* `prototype.js` and `behaviour.js` have been removed from the core, they are no longer used. If you have custom code relying on these two libraries, please update your code to include the files yourself
* `Object::has_extension()` and `Object::add_extension()` deprecated in favour of using late static binding, please use `{class}::has_extension()` and `{class}::add_extension()` instead, where {class} is the class name of your DataObject class.
2012-12-18 10:40:00 +01:00
* Removed `SiteTree.MetaKeywords` since they are irrelevant in terms of SEO ([seomoz article](http://www.mattcutts.com/blog/keywords-meta-tag-in-web-search/)) and general page informancy
* Removed `SiteTree.MetaTitle` as a means to customize the window title, use `SiteTree.Title` instead
* Deprecated `Profiler` class, use third-party solutions like [xhprof](https://github.com/facebook/xhprof/)
* Removed defunct or unnecessary debug GET parameters:
`debug_profile`, `debug_memory`, `profile_trace`, `debug_javascript`, `debug_behaviour`
* Removed `Member_ProfileForm`, use `CMSProfileController` instead
* `SiteTree::$nested_urls` enabled by default. To disable, call `SiteTree::disable_nested_urls()`.
* Removed CMS permission checks from `File->canEdit()` and `File->canDelete()`. If you have unsecured controllers relying on these permissions, please override them through a `DataExtension`.
* Moved email bounce handling to new ["emailbouncehandler" module](https://github.com/silverstripe-labs/silverstripe-emailbouncehandler),
including `Email_BounceHandler` and `Email_BounceRecord` classes,
as well as the `Member->Bounced` property.
* Deprecated global email methods `htmlEmail()` and `plaintextEmail`, as well as various email helper methods like `encodeMultipart()`. Use the `Email` API, or the `Mailer` class where applicable.
* Removed non-functional `$inlineImages` option for sending emails
* Removed support for keyed arrays in `SelectionGroup`, use new `SelectionGroup_Item` object
to populate the list instead (see [API docs](api:SelectionGroup)).
* `FormField->setDescription()` now renders in a `<span class="description">` by default, rather than a `title` attribute * Removed `Form->Name()`: Use getName()
* Removed `FormField->setContainerFieldSet()`: Use setContainerFieldList()
* Removed `FormField->rootFieldSet()`: Use rootFieldList()
* Removed `Group::map()`: Use DataList::("Group")->map()
* Removed `Member->generateAutologinHash()`: Tokens are no longer saved directly into the database in plaintext. Use the return value of the Member::generateAutologinTokenAndHash to get the token
* Removed `Member->sendInfo()`: use Member_ChangePasswordEmail or Member_ForgotPasswordEmail directly
* Removed `SQLMap::map()`: Use DataList::("Member")->map()
* Removed `SQLMap::mapInGroups()`: Use Member::map_in_groups()
* Removed `PasswordEncryptor::register()/unregister()`: Use config system instead
* Methods on DataList and ArrayList that used to both modify the existing list & return a new version now just return a new version. Make sure you change statements like `$list->filter(...)` to $`list = $list->filter(...)` for these methods:
- `ArrayList#reverse`
- `ArrayList#sort`
- `ArrayList#filter`
- `ArrayList#exclude`
- `DataList#where`
- `DataList#limit`
- `DataList#sort`
- `DataList#addFilter`
- `DataList#applyFilterContext`
- `DataList#innerJoin`
- `DataList#leftJoin`
- `DataList#find`
- `DataList#byIDs`
- `DataList#reverse`
* `DataList#dataQuery` has been changed to return a clone of the query, and so can't be used to modify the list's query directly. Use `DataList#alterDataQuery` instead to modify dataQuery in a safe manner.
* `ScheduledTask`, `QuarterHourlyTask`, `HourlyTask`, `DailyTask`, `MonthlyTask`, `WeeklyTask` and
`YearlyTask` are deprecated, please extend from `BuildTask` or `CliController`,
and invoke them in self-defined frequencies through Unix cronjobs etc.