2015-09-10 05:46:23 +02:00
# 4.0.0 (unreleased)
2016-09-08 02:39:17 +02:00
## Introduction
This version introduces many breaking changes, which in most projects can be managed through a combination
of automatic upgrade processes as well as manual code review. This document reviews these changes and will
guide developers in preparing existing 3.x code for compatibility with 4.0
* [Highlights of Major Changes ](#overview )
* [Upgrading Guide ](#upgrading )
* [Standard Upgrade ](#upgrading-primary )
* [API Specific Upgrades ](#upgrading-specifics )
2017-07-14 04:43:00 +02:00
* [User code style upgrades ](#usercode-style-upgrades )
2016-09-08 02:39:17 +02:00
* [API Changes ](#api-changes )
* [General and Core API ](#overview-general )
* [ORM API ](#overview-orm )
* [Filesystem API ](#overview-filesystem )
* [Template and Form API ](#overview-template )
2017-01-18 04:58:48 +01:00
* [i18n ](#overview-i18n )
2017-01-13 17:12:25 +01:00
* [Email and Mailer ](#overview-mailer )
2017-03-24 12:17:26 +01:00
* [SapphireTest ](#overview-testing )
2017-07-14 04:43:00 +02:00
* [Security ](#overview-security )
2016-09-08 02:39:17 +02:00
## <a name="overview"></a>Highlights of major changes
2017-08-07 05:39:08 +02:00
* Minimum version dependencies have increased; PHP 5.5 and Internet Explorer 11 (or other modern browser)
2016-09-08 02:39:17 +02:00
is required.
* All code earlier marked as deprecated for 4.0 has now been removed. See
[deprecation documentation ](/contributing/release_process ) for information on code deprecation.
2017-07-19 00:16:59 +02:00
* All code has been migrated to follow the PSR-2 coding standard. Most significantly, all SilverStripe
2017-07-14 04:43:00 +02:00
classes are now namespaced, and some have been renamed. This has major implications for
2016-09-08 02:39:17 +02:00
arrangement of templates, as well as other references to classes via string literals or configuration.
2016-12-14 00:01:55 +01:00
Automatic upgrading tools have been developed to cope with the bulk of these changes (see
2017-07-19 00:16:59 +02:00
[upgrading notes ](#upgrading )). Some classes have been rearranged so that each file contains only one class definition. It is recommended that user code follow the same convention.
2017-07-14 04:43:00 +02:00
For example, page types and their controllers should longer be collated in a single file.
2017-05-17 07:40:13 +02:00
* Object class has been removed.
2016-09-08 02:39:17 +02:00
* Asset storage has been abstracted, and a new concept of `DBFile` references via database column references
now exists in addition to references via the existing `File` dataobject. File security and protected files
are now a core feature.
* A new front-end development process has been developed for the construction of javascript based components,
prominently featuring ReactJS to develop highly functional CMS content areas. A new standard form schema
API has been developed to allow back-end PHP constructed forms to scaffold themselves within ReactJS
powered sections.
2016-12-14 00:01:55 +01:00
* CMS CSS has been re-developed using bootstrap 4 as a base
2016-09-09 03:33:52 +02:00
([blog post](https://www.silverstripe.org/blog/a-frameworks-framework-why-silverstripe-4-will-use-bootstrap/))
2016-09-08 02:39:17 +02:00
* Asset admin has been replaced with a purely ReactJS powered upgrade, and split out
2016-09-09 03:33:52 +02:00
module called [asset-admin ](https://github.com/silverstripe/silverstripe-asset-admin/ ). You'll need to add this to your `composer.json` to retain file management capabilities for your CMS authors.
2016-09-08 02:39:17 +02:00
* Versioning is now a much more powerful feature, with the addition of campaigns to allow batches of related
or inter-dependent objects to be published as a single act. Dependencies between versioned objects can be
declared using the new ownership API, so that developers can ensure that relational consistency is
2016-09-09 03:33:52 +02:00
maintained during publishing. This new system can be managed via the new "Campaigns" CMS section ([blog post](https://www.silverstripe.org/blog/campaigns-in-silverstripe-4/))
2016-09-08 02:39:17 +02:00
* Template variable casting (e.g. `<h1>$Title</h1>` ) is enforced by default, which will ensure safe HTML encode
unless explicitly opted out.
* Themes are now configured to cascade, where you can specify a list of themes, and have the template engine
search programatically through a prioritised list when resolving template and CSS file paths.
2017-06-28 12:04:34 +02:00
* Removed module path constants (e.g. `FRAMWORK_PATH` ) and support for hardcoded file paths (e.g. `mysite/css/styles.css` )
2017-01-18 04:58:48 +01:00
* i18n Updated to use symfony/translation over zend Framework 1. Zend_Translate has been removed.
2017-02-23 20:39:57 +01:00
* Replaced `Zend_Cache` and the `Cache` API with a PSR-16 implementation (symfony/cache)
2017-01-30 16:34:55 +01:00
* _ss_environment.php files have been removed in favour of `.env` and "real" environment variables.
2017-03-10 04:43:10 +01:00
* admin has been moved to a new module [silverstripe/admin ](https://github.com/silverstripe/silverstripe-admin ).
2017-01-20 03:57:50 +01:00
* Behat support updated to behat 3. See the
[behat extension ](https://github.com/silverstripe/silverstripe-behat-extension ) for more information.
2017-06-22 18:39:33 +02:00
* The `GDBackend` and `ImagickBackend` classes have been replaced by a unified `InterventionBackend` which uses the
[intervention/image ](https://github.com/intervention/image ) library to power manipualations.
2017-08-14 00:24:48 +02:00
* Dependencies can managed via [recipe-plugin ](https://github.com/silverstripe/recipe-plugin ). See [recipe-core ](https://github.com/silverstripe/recipe-core ) and [recipe-cms ](https://github.com/silverstripe/recipe-cms ) as examples.
2017-07-02 05:27:17 +02:00
* Authentication has been upgraded to a modular approach using re-usable interfaces and easier to hook in to LoginHandlers.
2017-10-02 13:30:24 +02:00
* Core modules are installed in the `vendor/` folder by default (other modules can opt-in, see [guide ](/developer_guides/extending/how_tos/publish_a_module ))
2017-10-09 01:41:34 +02:00
* Renamed constant for temp folder from `TEMP_FOLDER` to `TEMP_PATH` for naming consistency with other path variables and constants
2016-09-08 02:39:17 +02:00
## <a name="upgrading"></a>Upgrading
The below sections describe how to go about updating an existing site to be prepared for upgrade to 4.0.
Most of these upgrading tasks will involve manual code review, although in some cases there are
2016-12-14 00:01:55 +01:00
some automated processes that users can run to
2016-09-08 02:39:17 +02:00
### <a name="upgrading-primary"></a>Standard Upgrade
This section describes the processes which every project upgrading to 4.0 should follow. This should be followed
as a standard first point of upgrade.
2017-10-10 04:23:00 +02:00
#### Upgrade project index.php and .htaccess rewrites
2017-10-02 13:30:24 +02:00
The location of SilverStripe's "entry file" has changed. Your project and server environment will need
2017-10-03 13:23:17 +02:00
to adjust the path to this file from `framework/main.php` to `index.php` .
2017-10-02 13:30:24 +02:00
If you are running Apache, adjust your `.htaccess` file. For other webservers,
please consult the [installation guides ](getting_started/installation/ ).
2017-10-04 17:45:56 +02:00
Since 4.0, URL rewrite capabilities are required,
unless you PHP's built-in webserver through [silverstripe/serve ](https://github.com/silverstripe/silverstripe-serve ).
2017-10-02 13:30:24 +02:00
2017-10-10 04:23:00 +02:00
The [upgrader tool ](https://github.com/silverstripe/silverstripe-upgrader/ ) has a task runner which
automates this process for you.
```
composer global require silverstripe/upgrader
cd ~/Project/Root
~/.composer/vendor/bin/upgrade-code doctor
```
This will ensure that your `.htaccess` and `index.php` are set to a reasonable default value
2017-10-10 10:28:02 +02:00
for a clean installation. If you have applied customisations to your `.htaccess`
file (e.g. a custom `main.php` , HTTP header configuration, deny file access),
you'll need to manually reapply these to the copied default file.
2017-10-10 04:23:00 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrade references to renamed and namespaced classes
2016-09-09 03:54:54 +02:00
Nearly all core PHP classes have been namespaced. For example, `DataObject` is now called `SilverStripe\ORM\DataObject` .
2017-07-14 04:43:00 +02:00
The below tasks describe how to upgrade an existing site to remain compatible with the newly upgraded classes.
##### Using the upgrader tool to automatically upgrade
This task should be run on every upgraded project.
We have developed an [upgrader tool ](https://github.com/silverstripe/silverstripe-upgrader/ ) to (semi-)automatically
update your 3.x code to the new naming. Here's an example how to upgrade your `mysite` folder:
2016-12-14 00:01:55 +01:00
2017-01-24 05:14:39 +01:00
```
composer global require silverstripe/upgrader
cd ~/Project/Root
~/.composer/vendor/bin/upgrade-code upgrade ./mysite --write
```
2016-09-08 02:39:17 +02:00
If you want to do a dry-run, omit the `--write` option to see a preview of a diff of
all changed project files.
2016-09-09 03:54:54 +02:00
This will resolve the majority of upgrading work, but we strongly recommend reviewing the diff
running some regression testing on your functionality. SilverStripe core classes can be referenced
in your PHP files, but also in YAML configuration and SilverStripe templates.
For a full list of renamed classes, check the `.upgrade.yml` definitions in each module.
The rename won't affect class-based permission codes or database table names.
2016-09-08 02:39:17 +02:00
2017-07-14 04:43:00 +02:00
##### Upgrade references to literal or class table names
2017-07-13 04:57:28 +02:00
2017-07-19 00:16:59 +02:00
In 3.x the class name of any DataObject matched the table name, but in 4.x all classes are namespaced, and it is
2017-07-14 04:43:00 +02:00
necessary to map between table and class for querying the database.
2017-07-13 04:57:28 +02:00
2017-07-14 04:43:00 +02:00
In order to ensure you are using the correct table for any class a new
[DataObjectSchema ](api:SilverStripe\ORM\DataObjectSchema ) service is available to manage these mappings
(see [versioned documentation ](/developer_guides/model/data_model_and_orm )).
2017-07-13 04:57:28 +02:00
2017-07-14 04:43:00 +02:00
For example, the below shows how you would update a query with a hard-coded table name:
2017-07-13 04:57:28 +02:00
2017-07-14 04:43:00 +02:00
```diff
2017-07-13 04:57:28 +02:00
public function countDuplicates($model, $fieldToCheck)
{
2017-08-07 05:11:17 +02:00
$query = new SilverStripe\ORM\Queries\SQLSelect();
2017-07-14 04:43:00 +02:00
+ $table = SilverStripe\ORM\DataObject::getSchema()->tableForField($model, $field);
- $query->setFrom("\"{$model}\"");
+ $query->setFrom("\"{$table}\"");
- $query->setWhere(["\"{$model}\".\"{$field}\"" => $model->$fieldToCheck]);
+ $query->setWhere(["\"{$table}\".\"{$field}\"" => $model->$fieldToCheck]);
return $query->count();
2017-07-13 04:57:28 +02:00
}
```
2017-07-14 04:43:00 +02:00
##### Replacing literal strings with fully qualified class name, or ::class constant
2017-07-13 04:57:28 +02:00
You'll need to update any strings that represent class names and make sure they're fully
qualified. In particular, relationship definitions such as `has_one` and `has_many` will need
to be updated to refer to fully qualified class names.
2017-07-19 00:16:59 +02:00
In configs and with literal PHP strings it is recommended to use the php `::class` constant,
2017-07-14 04:43:00 +02:00
as demonstrated below.
```diff
< ?php
+ use SilverStripe\ORM\DataObject;
+ use SilverStripe\Security\Member;
2017-07-19 00:16:59 +02:00
class MyClass extends DataObject
{
2017-07-14 04:43:00 +02:00
private static $has_one = [
- 'Author' => 'Member',
+ 'Author' => Member::class,
];
}
2017-07-13 04:57:28 +02:00
```
2017-07-19 00:16:59 +02:00
In the context of YAML, the magic constant `::class` does not apply. Fully qualified class names must be hard coded.
2017-07-13 04:57:28 +02:00
2017-07-14 04:43:00 +02:00
```diff
-MyObject:
+My\Project\MyObject:
2017-07-13 04:57:28 +02:00
property: value
```
2017-07-14 04:43:00 +02:00
##### Update references to literal classes to use Injector
2017-07-13 04:57:28 +02:00
2017-07-19 00:16:59 +02:00
In many places, classes namespaced in SilverStripe 4.x will still have a non-namespaced service
name that can be accessed via Injector. You should upgrade direct object constructors with
the Injector API.
2017-07-13 04:57:28 +02:00
2017-07-14 04:43:00 +02:00
E.g.
2017-07-13 04:57:28 +02:00
2017-07-14 04:43:00 +02:00
```diff
- $field = new Varchar();
+ $field = Injector::inst()->create('Varchar');
2017-07-14 01:19:32 +02:00
```
2017-07-13 04:57:28 +02:00
#### Migrate your controllers to their own files
The convention for naming controllers is now `[MyPageType]Controller` , where it used to be `[MyPageType]_Controller` . This change was made to be more compatible with the PSR-2 standards.
2017-07-14 01:19:32 +02:00
You can still use, for example, `Page_Controller` , but you will get a deprecation notice. It is
best to change it to `PageController` during your upgrade process. Keep in mind any modules or
other thirdparty code that extend `PageController` are likely to assume that class exists.
2017-07-13 04:57:28 +02:00
2017-07-13 07:00:12 +02:00
By default, a controller for a page type *must* reside in the same namespace as its page. To use different logic, override `SiteTree::getControllerName()` .
2017-07-13 04:57:28 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrade template locations and references
Templates are now much more strict about their locations. You can no longer put a template in an arbitrary
folder and have it be found. Case is now also checked on case-sensitive filesystems.
Either include the folder in the template name (`renderWith('MyEmail.ss')` => `renderWith('emails/MyEmail.ss')` ),
2017-09-20 05:09:49 +02:00
move the template into the correct directory, or both.
2016-09-08 02:39:17 +02:00
Core template locations have moved - if you're including or overriding these
(e.g. for FormField templates) please adjust to the new paths. The `forms` folder
no longer exists, and instead template locations will be placed in paths that match
the `SilverStripe\Forms` namespace.
2017-09-20 05:09:49 +02:00
#### Upgrade <% include %>
When using `<% include %>` template tag you can continue to leave out the `Includes` folder,
but this now will also search templates in the base folder if no Include can be found.
`<% include Sidebar %>` will match `Includes/Sidebar.ss` , but will also match `Sidebar.ss`
if the former is not present.
Please refer to our [template syntax ](/developer_guides/templates/syntax ) for details.
2017-07-14 04:43:00 +02:00
#### Upgrade static config settings to `private static`
2017-07-13 04:57:28 +02:00
2017-07-13 07:00:12 +02:00
If you have some class configuration statics defined and they aren't private,
you may find that they don't register anymore. For example, this code, taken from
2017-07-13 04:57:28 +02:00
the `silverstripe/tagfield` module will no longer work in SilverStripe 4.0.
2017-07-14 04:45:08 +02:00
2017-07-13 04:57:28 +02:00
```php
public static $allowed_actions = [
'suggest'
];
```
Changing the visibility to `private` (as per `RequestHandler::$allowed_actions`
visibility) will make it 4.0 compatible.
2017-07-14 04:45:08 +02:00
```diff
-public static $allowed_actions = [
+private static $allowed_actions = [
2017-07-13 04:57:28 +02:00
'suggest'
];
```
2017-06-28 12:04:34 +02:00
#### Upgrade module paths in file references
You should no longer rely on modules being placed in a deterministic folder (e.g. `/framework` ),
and use getters on the [Module ](api:SilverStripe\Core\Manifest\Module ) object instead.
They expect a module composer name, followed by the module relative path, separated by a double colon.
This prepares SilverStripe for moving modules out of the webroot at a later point.
Usage in templates:
```ss
<!-- before -->
< img src = "framework/images/image.png" / >
< % require css("framework/css/styles.css") %>
<!-- after -->
< img src = "$ModulePath(silverstripe/framework)/image.png" / >
< % require css("silverstripe/framework: css/styles.css") %>
```
Usage in Requirements:
```php
// before
Requirements::css('framework/css/styles.css');
// after
Requirements::css('silverstripe/framework: css/styles.css');
```
Usage with custom logic:
```php
// before
$moduleFilePath = FRAMEWORK_DIR . '/MyFile.php';
$baseFilePath = BASE_PATH . '/composer.json';
$mysiteFilePath = 'mysite/css/styles.css';
$themesFilePath = SSViewer::get_theme_folder() . '/css/styles.css';
$themeFolderPath = THEMES_DIR . '/simple';
// after
use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\View\ThemeResourceLoader;
$moduleFilePath = ModuleLoader::getModule('silverstripe/framework')->getRelativeResourcePath('MyFile.php');
$baseFilePath = Director::baseFolder() . '/composer.json';
$mysiteFilePath = ModuleLoader::getModule('mysite')->getRelativeResourcePath('css/styles.css');
$themesFilePath = ThemeResourceLoader::inst()->findThemedResource('css/styles.css');
$themeFolderPath = ThemeResourceLoader::inst()->getPath('simple');
```
2017-10-18 06:55:50 +02:00
Usage for Page and ModelAdmin:
```php
class ListingPage extends \Page {
private static $icon = 'mycompany/silverstripe-mymodule: client/images/sitetree_icon.png';
}
```
```php
class MyCustomModelAdmin extends \SilverStripe\Admin\ModelAdmin {
private static $menu_icon = 'mycompany/silverstripe-mymodule: client/images/modeladmin_icon.png';
}
```
2017-06-28 12:04:34 +02:00
To ensure consistency, we've also deprecated support for path constants:
* `FRAMEWORK_DIR` and `FRAMEWORK_PATH`
* `FRAMEWORK_ADMIN_DIR` and `FRAMEWORK_ADMIN_PATH`
* `FRAMEWORK_ADMIN_THIRDPARTY_DIR` and `FRAMEWORK_ADMIN_THIRDPARTY_PATH`
* `THIRDPARTY_DIR` and `THIRDPARTY_PATH`
* `CMS_DIR` and `CMS_PATH`
* `THEMES_DIR` and `THEMES_PATH`
2017-10-02 13:30:24 +02:00
#### Adapt tooling to modules in vendor folder
SilverStripe modules can now be installed like any other composer package: In the `vendor/` folder
instead of the webroot. Modules need to opt in to this behaviour after they've ensured
that no hardcoded path references exist (see "Upgrade module paths in file references").
All core modules have been moved over already:
```diff
-framework/
-cms/
...
+vendor/silverstripe/framework
+vendor/silverstripe/cms
```
Since the `vendor/` folder isn't publicly accessible, modules need to declare
which files need to be exposed via the new [vendor-plugin ](https://github.com/silverstripe/vendor-plugin )
(e.g. images or CSS/JS files). These files will be either symlinked or copied into a new `resources/`
folder automatically on `composer install` .
If your deployment process relies on `composer install` on the production environment,
and this environment supports symlinks, you don't need to change anything.
If you deploy release archives, either ensure those archives can correctly extract symlinks,
or explicitly switch to the "copy" mode to avoid symlinks.
2017-06-28 12:04:34 +02:00
2016-09-08 02:39:17 +02:00
### <a name="upgrading-specifics"></a>API Specific Upgrades
The below sections deal with upgrades to specific parts of various API. Projects which rely on certain
API should be upgraded as appropriate using any of the relevant processes documented below.
2017-07-14 04:43:00 +02:00
#### Upgrade references of SS_Log to use PSR-3 logging
One of the great changes that comes with SilverStripe 4 is the introduction of
[PSR-3 ](http://www.php-fig.org/psr/psr-3/ ) compatible logger interfaces. This
means we can use thirdparty services like Monolog. `SS_Log` has been replaced
with a logger which can be accessed using the LoggerInterface::class service.
For instance, code which logs errors should be upgraded as below:
```diff
-SS_Log::log('My error message', SS_Log::ERR);
+use Psr\Log\LoggerInterface;
+Injector::inst()->get(LoggerInterface::class)->error('My error message');
```
##### How to customise the default PSR-3 logger
If necessary, you may need to customise either the default logging handler, or
one of the error formatters. For example, if running unit tests you may want to
suppress errors. You can temporarily disable logging by setting a `NullHandler`
```yml
---
Name: custom-dev-logging
After: dev-logging
Only:
environment: dev
---
# Replace default handler with null
SilverStripe\Core\Injector\Injector:
Monolog\Handler\HandlerInterface: Monolog\Handler\NullHandler
```
Alternatively you can customise one or both of the below services:
- `Monolog\Formatter\FormatterInterface.detailed` service, which is used for displaying
detailed error messages useful for developers.
- `Monolog\Formatter\FormatterInterface.friendly` service, which is used to display "error"
page content to visitors of the site who encounter errors.
For example, a custom error page generator could be added as below:
```yml
---
Name: custom-errorpage
After:
- '#loggingformatters'
---
SilverStripe\Core\Injector\Injector:
Monolog\Formatter\FormatterInterface.friendly:
class: WebDesignGroup\ShopSite\Logging\ErrorPageFormatter
```
`WebDesignGroup\ShopSite\Logging\ErrorPageFormatter` should be a class that
implements the `Monolog\Formatter\FormatterInterface` interface.
2017-06-22 12:50:45 +02:00
#### Upgrade `mysite/_config.php`
The globals `$database` and `$databaseConfig` are deprecated. You should upgrade your
site _config.php files to use the `.env` configuration (below).
2017-07-14 04:43:00 +02:00
`conf/ConfigureFromEnv.php` is also no longer used, and references to this file should be deleted.
2017-06-22 12:50:45 +02:00
2017-07-14 04:43:00 +02:00
If you need to configure database details in PHP you should configure these details via `.env` file,
or alternatively (but less recommended) use the new `DB::setConfig()` api.
2017-06-22 12:50:45 +02:00
2017-07-13 04:57:28 +02:00
The global `$project` is deprecated in favour of the configuration setting
`SilverStripe\Core\Manifest\ModuleManifest.project` .
2017-07-14 04:43:00 +02:00
Changes to `mysite/_config.php` :
```diff
< ?php
-global $project;
-$project = 'mysite';
-include 'conf/ConfigureFromEnv.php';
```
And also add to `mysite/_config/mysite.yml` :
```yml
2017-07-13 04:57:28 +02:00
SilverStripe\Core\Manifest\ModuleManifest:
project: mysite
```
2017-06-22 12:50:45 +02:00
2017-02-23 04:01:59 +01:00
#### Upgrade of `_ss_environment.php` to `.env` configuration
The php configuration `_ss_environment.php` file has been replaced in favour of a non-executable
`.env` file, which follows a syntax similar to an `.ini` file for key/value pair assignment. Like
the old php file, `.env` may be placed in either the web root, or one level above.
For example, if you have the below `_ss_environment.php` file, your `.env` would be rewritten as follows:
`_ss_environment.php` :
2017-06-29 00:44:48 +02:00
```php
// Environment
define('SS_ENVIRONMENT_TYPE', 'dev');
define('SS_DEFAULT_ADMIN_USERNAME', 'admin');
define('SS_DEFAULT_ADMIN_PASSWORD', 'password');
$_FILE_TO_URL_MAPPING[__DIR__] = 'http://localhost';
// Database
define('SS_DATABASE_CHOOSE_NAME', true);
define('SS_DATABASE_CLASS', 'MySQLDatabase');
2017-07-14 04:43:00 +02:00
define('SS_DATABASE_USERNAME', 'root');
2017-06-29 00:44:48 +02:00
define('SS_DATABASE_PASSWORD', '');
define('SS_DATABASE_SERVER', '127.0.0.1');
```
2017-02-23 04:01:59 +01:00
`.env` :
2017-06-29 00:44:48 +02:00
```
## Environment
SS_ENVIRONMENT_TYPE="dev"
SS_DEFAULT_ADMIN_USERNAME="admin"
SS_DEFAULT_ADMIN_PASSWORD="password"
SS_BASE_URL="http://localhost/"
### Database
SS_DATABASE_CHOOSE_NAME="true"
SS_DATABASE_CLASS="MySQLDatabase"
SS_DATABASE_USERNAME="root"
SS_DATABASE_PASSWORD=""
SS_DATABASE_SERVER="127.0.0.1"
```
2017-02-23 04:01:59 +01:00
The removal of the `_ss_environment.php` file means that conditional logic is no longer available in the environment
variable set-up process. This generally encouraged bad practice and should be avoided. If you still require conditional
logic early in the bootstrap, this is best placed in the `_config.php` files.
2017-04-13 03:33:29 +02:00
Note also that `$_FILE_TO_URL_MAPPING` has been removed and replaced with `SS_BASE_URL` env var.
2017-09-20 00:07:32 +02:00
This url must be an absolute url with an optional protocol. The following are valid, for example:
```
SS_BASE_URL="http://localhost/"
SS_BASE_URL="https://localhost/"
SS_BASE_URL="//localhost/"
```
2017-02-23 04:01:59 +01:00
2017-06-22 12:50:45 +02:00
The global values `$database` and `$databaseConfig` have been deprecated, as has `ConfigureFromEnv.php`
which is no longer necessary.
2017-02-23 04:01:59 +01:00
See [Environment Management docs ](/getting-started/environment_management/ ) for full details.
2017-05-17 07:40:13 +02:00
#### Replace usages of Object class
Object has been superseded by a trio of traits which replace components of this legacy class:
- Injectable: Provides `MyClass::create()` and `MyClass::singleton()`
- Configurable: Provides `MyClass::config()`
2017-08-22 01:22:08 +02:00
- Extensible: Provides all methods related to extensions (E.g. add_extension()).
All custom method and extension instances are constructed lazily.
2017-05-17 07:40:13 +02:00
In particular specific Object class usages should be replaced as below:
Upgrade subclasses
2017-06-29 00:44:48 +02:00
```diff
-class MyClass extends Object
-{
-}
2017-08-07 03:53:23 +02:00
+use SilverStripe\Core\Extensible;
+use SilverStripe\Core\Injector\Injectable;
+use SilverStripe\Core\Config\Configurable;
2017-06-29 00:44:48 +02:00
+class MyClass
+{
+ use Extensible;
+ use Injectable;
+ use Configurable;
+}
```
2017-05-17 07:40:13 +02:00
References to $this->class
2017-06-29 00:44:48 +02:00
```diff
-$obj->class
+get_class($obj);
2017-05-17 07:40:13 +02:00
2017-06-29 00:44:48 +02:00
-$this->class;
+static::class;
```
2017-05-17 07:40:13 +02:00
Upgrade parse_class_spec()
2017-06-29 00:44:48 +02:00
```diff
-$spec = Object::parse_class_spec($spec);
+$spec = ClassInfo::parse_class_spec($spec);
```
2017-05-17 07:40:13 +02:00
Upgrade create_from_string()
2017-06-29 00:44:48 +02:00
```diff
-$obj = Object::create_from_string('Varchar(100)');
+$obj = Injector::inst()->create('Varchar(100)');
```
2017-05-17 07:40:13 +02:00
Extensions
2017-06-29 00:44:48 +02:00
```diff
2017-05-17 07:40:13 +02:00
2017-06-29 00:44:48 +02:00
-Object::add_extension('File', 'Versioned');
+File::add_extension(Versioned::class);
+DataObject::add_extension(File::class, Versioned::class); // alternate
-$has = Object::has_extension('File', 'Versioned');
+$has = File::has_extension(Versioned::class);
+$has = DataObject::has_extension(File::class, Versioned::class); // alternate
-$extensions = Object::get_extensions('File');
+$extensions = File::get_extensions();
+$extensions = DataObject::get_extensions(File::class); // alternate
```
2017-05-17 07:40:13 +02:00
2017-06-22 12:50:45 +02:00
#### Upgrade references to Session object
Session object is no longer statically accessible via `Session::inst()` . Instead, Session
is a member of the current request.
2017-06-29 00:44:48 +02:00
```diff
-public function httpSubmission($data, $form, $request)
-{
- Session::set('loggedIn', null);
-}
+public function httpSubmission($data, $form, $request)
+{
+ $request->getSession()->set('loggedIn', null);
+}
```
2017-06-22 12:50:45 +02:00
In some places it may still be necessary to access the session object where no request is available.
In rare cases it is still possible to access the request of the current controller via
`Controller::curr()->getRequest()` to gain access to the current session.
2017-05-17 07:40:13 +02:00
2017-10-05 06:23:02 +02:00
#### Upgrade extensions to work as singletons
In SilverStripe 4.0 extensions are now all singletons, meaning that state stored as protected vars
within extensions are now shared across all object instances that use this extension.
As a result, you must take care that all protected vars are either refactored to be stored against
the owner object, or are keyed in a fashion distinct to the parent.
E.g.
```diff
class MyExtension extends Extension {
public function getContent() {
- if (!$this->contentCache) {
- $this->contentCache = $this->generateContent();
- }
- return $this->contentCache;
+ $contentCache = $this->owner->getField('contentCache');
+ if (!$contentCache) {
+ $contentCache = $this->generateContent();
+ $this->owner->setField('contentCache', $contentCache);
+ }
+ return $contentCache;
}
}
```
In addition when using extensions with distinct constructor arguments it's advisable to
2017-10-08 23:56:02 +02:00
use `yml` to register those constructor arguments and use a service name or alias in
`private static $extensions` .
2017-10-05 06:23:02 +02:00
2017-10-08 23:56:02 +02:00
E.g. This is the service definition for the various versioned extension variants
2017-10-05 06:23:02 +02:00
```yaml
---
Name: versionedextension
---
SilverStripe\Core\Injector\Injector:
# Versioning only
SilverStripe\Versioned\Versioned.versioned:
class: SilverStripe\Versioned\Versioned
constructor:
mode: Versioned
# Staging and Versioning
SilverStripe\Versioned\Versioned.stagedversioned:
class: SilverStripe\Versioned\Versioned
constructor:
mode: StagedVersioned
# Default is alias for .stagedversioned
SilverStripe\Versioned\Versioned: '%$SilverStripe\Versioned\Versioned.stagedversioned'
```
Upgrade your extension references as below:
```diff
class MyClass extends DataObject {
private static $extensions = [
- Versioned::class . '(Versioned)',
+ Versioned::class . '.versioned',
];
}
```
2016-09-08 02:39:17 +02:00
#### Compatibility with the new front-end building tools
If you are using Requirements from 3.x then your scripts should continue to work as they did before.
The new front-end tooling is intended only for those wishing to customise the CMS look and feel, or behaviour.
Those wishing to customise the CMS should read about how to
[customise the admin interface ](/developer_guides/customising_the_admin_interface/ ).
#### Upgrade static references to asset paths
2016-04-19 11:04:43 +02:00
All static files (images, javascript, stylesheets, fonts) used for the CMS and forms interfaces
in `framework` and `cms` have moved locations. These assets are now placed in a `client/` subfolder,
to account for a structural change where both javascript and styles are co-located in component-specific folders.
This will affect you if you have used `Requirements::block()` on files in the `framework/` or `cms/` folder.
API Use Webpack
The bundle is generated by running “webpack” directly - gulp is no
longer needed as an intermediary. The resulting config is a lot shorter,
although more configuration is pushed into lib.js.
Modules are shared between javascript files as global variables.
Although this global state pollution is a bit messy, I don’t think it’s
practically any worse than the previous state, and it highlights the
heavy coupling between the different packages we have in place.
Reducing the width of the coupling between the core javascript and
add-on modules would probably be a better way of dealing with this than
replacing global variables with some other kind of global state.
The web pack execution seems roughly twice as fast - if I clear out my
framework/client/dist/js folder, it takes 13.3s to rebuild. However,
it’s not rebuilding other files inside dist, only the bundle files.
CSS files are now included from javascript and incorporated into
bundle.css by the webpack. Although the style-loader is helpful in some
dev workflows (it allows live reload), it introduces a flash of
unstyled content which makes it inappropriate for production.
Instead ExtractTextPlugin is used to write all the aggregated CSS
into a single bundle.css file. A style-loader-based configuration could
be introduced for dev environments, if we make use of the webpack live
reloader in the future.
Note that the following features have been removed as they don't appear to be
necessary when using Webpack:
- UMD module generation
- thirdparty dist file copying
LeftAndMain.js deps: Without it, ssui.core.js gets loaded too late,
which leads e.g. to buttons being initialised without this added behaviour.
2016-08-21 03:17:50 +02:00
Care should also be taken when referencing images in these folders from your own stylesheets (`url()`),
or via SilverStripe templates (`< img > ` tags).
2016-04-19 11:04:43 +02:00
2016-09-08 02:39:17 +02:00
`Requirements` now throws an exception then a file is not found, rather than
failing silently, so check your `Requirements` are pointing to files that exist.
2016-04-19 11:04:43 +02:00
```
2017-03-14 23:08:28 +01:00
framework/javascript => silverstripe-admin/client/dist/
framework/javascript/lang => silverstripe-admin/client/lang/
framework/images => silverstripe-admin/client/dist/images/
framework/css => silverstripe-admin/client/dist/css/
framework/scss => silverstripe-admin/client/src/styles/
admin/javascript/ => silverstripe-admin/client/src/
admin/javascript/src/ => silverstripe-admin/client/src/legacy/ (mostly)
admin/javascript/lang/ => silverstripe-admin/client/lang/
admin/scss/ => silverstripe-admin/client/styles/legacy/
admin/css/ => silverstripe-admin/client/dist/css/
admin/css/screen.css => silverstripe-admin/client/dist/css/bundle.css
admin/images/ => silverstripe-admin/client/dist/images/
admin/images/sprites/src/ => silverstripe-admin/client/src/sprites/
admin/images/sprites/dist/ => silverstripe-admin/client/dist/sprites/
admin/font/ => silverstripe-admin/client/dist/font/
2016-04-19 11:04:43 +02:00
```
2016-09-07 10:41:16 +02:00
Most JavaScript files in `framework/javascript` have been removed,
and are bundled through [Webpack ](http://webpack.github.io/ ) into a combined file instead.
If you have referenced these files elsewhere, please consider
running the ES6 source files in `admin/client/src/legacy`
through your own transpiling and bundle process.
2016-09-13 13:03:09 +02:00
This also includes JavaScript i18n support, and the removal of the `i18n::js_i18n`
configuration option used in `Requirements::add_i18n_javascript()` .
2016-09-07 10:41:16 +02:00
SilverStripe core is moving away from `Requirements::combine_files` in favour of Webpack as of
4.0. `Requirements::combine_files` is being considered for deprecation in future versions.
2015-09-15 04:52:02 +02:00
2016-09-15 04:48:38 +02:00
All JavaScript thirdparty dependencies have either been moved to NPM (see `package.json` ),
or moved into the `framework/admin/thirdparty` folder. If you are hotlinking to any
of these files, please consider packaging your own versions in your projects and modules.
For CMS modules, you can also use many library globals which the core bundles already expose
(see [Build Tooling ](/contributing/build_tooling )).
2016-12-14 00:01:55 +01:00
One commonly linked thirdparty dependency is `jquery.js` bundled with SilverStripe:
2016-09-15 04:48:38 +02:00
```
framework/thirdparty/jquery/jquery.js => framework/admin/thirdparty/jquery/jquery.js
```
2016-09-08 02:39:17 +02:00
#### Explicit text casting is now enforced on all template variables
2016-12-14 00:01:55 +01:00
2016-06-03 10:51:02 +02:00
Now whenever a `$Variable` is used in a template, regardless of whether any casts or methods are
suffixed to the reference, it will be cast to either an explicit DBField for that field, or
the value declared by the `default_cast` on the parent object.
2016-12-14 00:01:55 +01:00
2016-06-03 10:51:02 +02:00
The default value of `default_cast` is `Text` , meaning that now many cases where a field was
left un-uncoded, this will now be safely encoded via `Convert::raw2xml` . In cases where
un-cast fields were used to place raw HTML into templates, this will now encode this until
explicitly cast for that field.
2016-12-14 00:01:55 +01:00
2016-06-03 10:51:02 +02:00
You can resolve this in your model by adding an explicit cast to HTML for those fields.
2016-09-08 02:39:17 +02:00
Before:
2016-06-03 10:51:02 +02:00
2017-01-24 05:14:39 +01:00
```php
2017-07-03 03:22:12 +02:00
use SilverStripe\View\ViewableData;
use SilverStripe\Core\Convert;
2017-06-29 00:44:48 +02:00
class MyObject extends ViewableData
{
2017-08-07 05:11:17 +02:00
public function getSomeHTML
{
$title = Convert::raw2xml($this->Title);
return "< h1 > {$title}< / h1 > ";
}
2017-01-24 05:14:39 +01:00
}
```
2016-06-03 10:51:02 +02:00
After:
2017-01-24 05:14:39 +01:00
```php
2017-07-03 03:22:12 +02:00
class MyObject extends SilverStripe\View\ViewableData
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
private static $casting = [
'SomeHTML' => 'HTMLText'
];
2017-01-24 05:14:39 +01:00
2017-08-07 05:11:17 +02:00
public function getSomeHTML
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
$title = SilverStripe\Core\Convert::raw2xml($this->Title);
return "< h1 > {$title}< / h1 > ";
}
2017-01-24 05:14:39 +01:00
}
```
2016-09-08 02:39:17 +02:00
2016-06-03 10:51:02 +02:00
If you need to encode a field (such as HTMLText) for use in html attributes, use `.ATT`
2016-09-09 03:33:52 +02:00
instead, or if used in an actual XML file use `.CDATA` (see [template casting ](/developer_guides/templates/casting )).
2015-09-10 05:46:23 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrade code that uses SQLQuery
2015-07-31 07:18:49 +02:00
2016-09-09 03:33:52 +02:00
Where your code once used SQLQuery you should now use SQLSelect in all cases, as this has been removed (check the [3.2.0 ](3.2.0 ) upgrading notes).
2015-07-31 07:18:49 +02:00
2017-03-08 23:11:41 +01:00
#### Upgrade code that uses UploadField
This field has been superceded by a new class provided by the
[asset-admin ](https://github.com/silverstripe/silverstripe-asset-admin ) module, which provides a more
streamlined simpler mechanism for uploading File dataobjects.
A helper service `FileHandleField` is provided to assist with dependency injection. Where the asset-admin
module is not installed this service will fall back to the `FileField` class instead.
2017-06-29 00:44:48 +02:00
Usages of UploadField will need to be upgraded as below.
2017-03-08 23:11:41 +01:00
2017-06-29 00:44:48 +02:00
Before:
2017-03-08 23:11:41 +01:00
2017-06-29 00:44:48 +02:00
```php
2017-08-05 00:45:24 +02:00
use SilverStripe\Forms\FieldList;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\ORM\DataObject;
2017-06-29 00:44:48 +02:00
class MyClass extends DataObject
{
public function getCMSFields()
{
return new FieldList(
new UploadField('Files')
);
2017-03-08 23:11:41 +01:00
}
2017-06-29 00:44:48 +02:00
}
```
2017-03-08 23:11:41 +01:00
2017-06-29 00:44:48 +02:00
After:
2017-03-08 23:11:41 +01:00
2017-06-29 00:44:48 +02:00
```php
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FileHandleField;
2017-03-08 23:11:41 +01:00
2017-06-29 00:44:48 +02:00
class MyClass extends DataObject
{
public function getCMSFields()
{
return FieldList::create(
Injector::inst()->create(FileHandleField::class, 'Files')
);
2017-03-08 23:11:41 +01:00
}
2017-06-29 00:44:48 +02:00
}
```
2017-03-08 23:11:41 +01:00
2017-01-18 04:58:48 +01:00
#### Upgrade code that uses i18n
In many cases, localisation strings which worked in 3.x will continue to work in 4.0, however certain patterns
have been deprecated and will be removed in 5.0. These include:
- _t calls with sprintf-style placeholders (`%s`). Replace with named placeholders instead.
- _t calls with non-associative injection arguments. Please use an associative array for all arguments.
2017-01-25 04:35:13 +01:00
- _t calls which do not include a default value will now raise a warning. This can be disabled by setting
the `i18n.missing_default_warning` config to false.
2017-01-18 04:58:48 +01:00
Note: If you attempt to use non-associative injection arguments with named placeholders, the result will
now trigger an exception.
Implementors of i18nEntityProvider should note that the return type for provideI18nEntities() has changed as well.
The non-associative array return type is deprecated. If returning a default string for a module
other than itself, it should return an array with the `default` and `module` keys respectively.
Full locale-rule respecting localisation for plural forms is now supported. The default
2017-01-25 04:35:13 +01:00
key for an object plural form is `<Namespaced\ClassName>.PLURALS` , and follows CLDR array form for each
2017-01-18 04:58:48 +01:00
pluralisation. See [the CLDR chart ](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html )
for reference.
The below demonstrates how you can provide new localisation strings for an object,
including both plurals and cross-module localisations.
2017-06-29 00:44:48 +02:00
```php
2017-08-05 00:45:24 +02:00
use SilverStripe\ORM\DataObject;
2017-06-29 00:44:48 +02:00
class MyObject extends DataObject, implements i18nEntityProvider
{
public function provideI18nEntities()
2017-01-18 04:58:48 +01:00
{
2017-06-29 00:44:48 +02:00
return [
'MyObject.SINGULAR_NAME' => 'object',
'MyObject.PLURAL_NAME' => 'objects',
'MyObject.PLURALS' => [
'one' => 'An object',
'other' => '{count} objects',
],
'AnotherSection.DESCRIPTION' => [
'default' => 'This is the description for this section',
'module' => 'extendedmodule',
],
];
2017-01-18 04:58:48 +01:00
}
2017-06-29 00:44:48 +02:00
}
```
2017-01-18 04:58:48 +01:00
In YML format this will be expressed as the below:
`mymodule/lang/en.yml` :
2017-07-14 04:43:00 +02:00
```yml
2017-06-29 00:44:48 +02:00
en:
MyObject:
SINGULAR_NAME: 'object'
PLURAL_NAME: 'objects'
PLURALS:
one: 'An object',
other: '{count} objects'
```
2017-01-18 04:58:48 +01:00
`extendedmodule/lang/en.yml` :
2017-07-14 04:43:00 +02:00
```yml
2017-06-29 00:44:48 +02:00
en:
AnotherSection:
DESCRIPTION: 'This is the description for this section'
```
2017-01-18 04:58:48 +01:00
2017-01-25 04:35:13 +01:00
Usage of these pluralised strings is through the existing _t() method,
and require a `|` pipe-delimeter with a {count} argument.
2017-01-18 04:58:48 +01:00
2017-06-29 00:44:48 +02:00
```php
public function pluralise($count)
{
return _t('MyObject.PLURALS', 'An object|{count} objects', [ 'count' => $count ]);
}
```
2017-01-18 04:58:48 +01:00
2017-01-25 04:35:13 +01:00
In templates this can also be invoked as below:
2017-01-18 04:58:48 +01:00
2017-06-29 00:44:48 +02:00
```ss
< %t MyObject.PLURALS 'An item|{count} items' count=$Count %>
```
2017-01-18 04:58:48 +01:00
2017-03-30 23:37:21 +02:00
#### Removed Member.DateFormat and Member.TimeFormat database settings
We're using [native HTML5 date and time pickers ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date )
in `DateField` and `TimeField` now ([discussion](https://github.com/silverstripe/silverstripe-framework/issues/6626)),
where the browser localises the output based on the browser/system preferences.
In this context it no longer makes sense to give users control over their own
date and time formats in their CMS profile.
2017-04-03 02:00:59 +02:00
Consequently, we've also removed `MemberDatetimeOptionsetField` .
2017-03-30 23:37:21 +02:00
`Member->getDateFormat()` and `Member->getTimeFormat()` still exist, and default to
the [IntlDateFormatter defaults ](http://php.net/manual/en/class.intldateformatter.php ) for the selected locale.
2016-09-08 02:39:17 +02:00
#### New asset storage mechanism
2015-09-03 07:46:08 +02:00
File system has been abstracted into an abstract interface. By default, the out of the box filesystem
uses [Flysystem ](http://flysystem.thephpleague.com/ ) with a local storage mechanism (under the assets directory).
Because the filesystem now uses the sha1 of file contents in order to version multiple versions under the same
filename, the default storage paths in 4.0 will not be the same as in 3.
In order to retain existing file paths in line with framework version 3 you should set the
`\SilverStripe\Filesystem\Flysystem\FlysystemAssetStore.legacy_paths` config to true.
Note that this will not allow you to utilise certain file versioning features in 4.0.
2017-07-14 04:43:00 +02:00
```yml
2017-01-24 05:14:39 +01:00
SilverStripe\Filesystem\Flysystem\FlysystemAssetStore:
legacy_paths: true
```
2015-09-03 07:46:08 +02:00
2016-09-09 03:33:52 +02:00
See our ["File Management" guide ](/developer_guides/files/file_management ) for more information.
2015-09-03 07:46:08 +02:00
2017-09-08 01:25:30 +02:00
Depending on your server configuration, it may also be necessary to adjust your assets folder
permissions. Please see the [common installation problems ](/getting_started/installation/common_problems )
guide for configuration instruction.
2016-09-08 02:39:17 +02:00
#### Migrating File DataObject from 3.x to 4.0
2015-09-15 04:52:02 +02:00
2017-10-02 04:07:47 +02:00
Since the structure of `File` dataobjects has changed between 3.0 and 4.0, a new task `MigrateFileTask`
has been added to assist in migration of legacy files.
2015-09-15 04:52:02 +02:00
2017-10-02 04:07:47 +02:00
You can run this task on the command line:
2015-09-15 04:52:02 +02:00
2017-10-02 04:07:47 +02:00
```
$ ./framework/sake dev/tasks/MigrateFileTask
2017-01-24 05:14:39 +01:00
```
2015-09-15 04:52:02 +02:00
2017-10-02 04:07:47 +02:00
For more information on this task please consult the [file migration documentation ](/developer_guides/files/file_migration ).
2016-01-26 04:56:07 +01:00
2017-08-31 04:19:04 +02:00
Note that any File dataobject which is not in the `File.allowed_extensions` config will be deleted
from the database during migration. Any invalid file on the filesystem will not be deleted,
but will no longer be attached to a dataobject anymore, and should be cleaned up manually.
To disable this, set the following config:
```yaml
SilverStripe\Assets\FileMigrationHelper:
delete_invalid_files: false
```
2016-09-08 02:39:17 +02:00
#### Upgrade code which acts on `Image`
2015-09-15 04:52:02 +02:00
2016-12-14 00:01:55 +01:00
As all image-specific manipulations has been refactored from `Image` into an `ImageManipulations` trait, which
2015-09-15 04:52:02 +02:00
is applied to both `File` and `DBFile` . These both implement a common interface `AssetContainer` , which
has the `getIsImage()` method. In some cases, it may be preferable to invoke this method to detect
if the asset is an image or not, rather than checking the subclass, as the asset may also be a `DBFile` with
an image filter applied, rather than an instance of the `Image` dataobject.
In addition, a new file category `image/supported` has been added, which is a subset of the `image` category.
2017-07-03 03:22:12 +02:00
This is the subset of all image types which may be assigned to the `[Image](api:SilverStripe\Assets\Image)` dataobject, and may have
manipulations applied to it. This should be used as the file type restriction on any `[UploadField](api:SilverStripe\AssetAdmin\Forms\UploadField)` which
2015-09-15 04:52:02 +02:00
is intended to upload images for manipulation.
2017-06-29 00:44:48 +02:00
```diff
-if($file instanceof Image) {
2017-08-07 05:11:17 +02:00
- $upload = new UploadField();
- $upload->setAllowedFileCategories('image');
2017-06-29 00:44:48 +02:00
-}
+if ($file->getIsImage()) {
2017-08-07 05:11:17 +02:00
+ $upload = new UploadField();
+ $upload->setAllowedFileCategories('image/supported');
2017-06-29 00:44:48 +02:00
+}
2017-01-24 05:14:39 +01:00
```
2015-09-15 04:52:02 +02:00
In cases where image-only assets may be assigned to relationships then your datamodel should specify explicitly
an `Image` datatype, or refer to `DBFile('image/supported')` .
2017-01-24 05:14:39 +01:00
```php
2017-08-31 14:48:07 +02:00
use SilverStripe\Assets\Image;
2017-07-03 03:22:12 +02:00
class MyObject extends SilverStripe\ORM\DataObject
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
private static $has_one = [
2017-08-31 14:48:07 +02:00
"ImageObject" => Image::class
2017-08-07 05:11:17 +02:00
];
private static $db = [
"ImageField" => "DBFile('image/supported')"
];
2017-01-24 05:14:39 +01:00
}
```
2015-09-15 04:52:02 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrading code that writes to `File` dataobjects, or writes files to the 'assets' folder
2015-09-15 04:52:02 +02:00
2016-03-08 21:37:06 +01:00
In the past all that was necessary to write a `File` DataObject to the database was to ensure a physical file
existed in the assets folder, and that the Filename of the DataObject was set to the same location.
2015-09-15 04:52:02 +02:00
Since the storage of physical files is no longer a standard location, it's necessary to delegate the writing of such
files to the asset persistence layer. As a wrapper for an individual file, you can use any of the `setFrom*`
methods to assign content from a local (e.g. temporary) file, a stream, or a string of content.
You would need to upgrade your code as below.
2017-06-29 00:44:48 +02:00
```diff
-function importTempFile($tmp)
-{
2017-08-07 05:11:17 +02:00
- copy($tmp, ASSETS_PATH . '/imported/' . basename($tmp));
- $file = new File();
- $file->setFilename('assets/imported/'.basename($tmp));
- $file->write();
2017-06-29 00:44:48 +02:00
-}
+public function importTempFile($tmp)
+{
+ Versioned::reading_stage('Stage');
+ $file = new File();
+ $file->setFromLocalFile($tmp, 'imported/' . basename($tmp));
2017-08-07 05:11:17 +02:00
+ $file->write();
+ $file->doPublish();
2017-06-29 00:44:48 +02:00
+}
2017-01-24 05:14:39 +01:00
```
2015-09-15 04:52:02 +02:00
Note that 'assets' is no longer present in the new code, and the path beneath what was once assets is now
used to generate the 'filename' value. This is because there is no longer an assumption that files are
stored in the assets folder.
There are other important considerations in working with File dataobjects which differ from legacy:
* File synchronisation is no longer automatic. This is due to the fact that there is no longer a 1-to-1 relationship
2016-03-08 21:37:06 +01:00
between physical files and File DataObjects.
* Folder DataObjects are now purely logical DataObjects, and perform no actual filesystem folder creation on write.
2016-01-26 04:56:07 +01:00
* All Files are versioned, which means that by default, new File records will not be visibile
2016-03-08 21:37:06 +01:00
to the public site. You will need to make sure to invoke `->doPublish()` on any File DataObject
2016-01-26 04:56:07 +01:00
you wish visitors to be able to see.
2017-01-24 05:14:39 +01:00
You can disable File versioning by adding the following to your `_config.php`
2016-01-26 04:56:07 +01:00
2017-01-24 05:14:39 +01:00
```php
2017-07-03 03:22:12 +02:00
SilverStripe\Assets\File::remove_extension('Versioned');
2017-01-24 05:14:39 +01:00
```
2015-09-15 04:52:02 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrading code performs custom image manipulations
2015-09-15 04:52:02 +02:00
As file storage and handling has been refactored into the abstract interface, many other components which were
once specific to Image.php have now been moved into a shared `ImageManipulation` trait. Manipulations of file content,
which are used to generate what are now called "variants" of assets, is now a generic api available to both `File`
and `DBFile` classes through this trait.
Custom manipulations, applied via extensions, must be modified to use the new API.
For instance, code which sizes images to a fixed width should be updated as below:
Before:
2017-01-24 05:14:39 +01:00
```php
// in MyImageExtension.php
2017-07-03 03:22:12 +02:00
class MyImageExtension extends SilverStripe\ORM\DataExtension
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
public function GalleryThumbnail($height)
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
return $this->getFormattedImage('GalleryThumbnail', $height);
}
2015-09-15 04:52:02 +02:00
2017-08-07 05:11:17 +02:00
public function generateGalleryThumbnail(Image_Backend $backend, $height)
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
return $backend->paddedResize(300, $height);
}
2017-01-24 05:14:39 +01:00
}
2015-09-15 04:52:02 +02:00
2017-01-24 05:14:39 +01:00
// in _config.php
2017-07-03 03:22:12 +02:00
SilverStripe\Assets\Image::add_extension('MyImageExtension');
2017-01-24 05:14:39 +01:00
```
2015-09-15 04:52:02 +02:00
2016-09-09 03:33:52 +02:00
Now image manipulations are implemented with a single method via a callback generator:
2015-09-15 04:52:02 +02:00
2017-01-24 05:14:39 +01:00
```php
2017-08-05 00:45:24 +02:00
use SilverStripe\Assets\File;
2017-01-24 05:14:39 +01:00
// in MyImageExtension.php
2017-07-03 03:22:12 +02:00
class MyImageExtension extends SilverStripe\Core\Extension
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
public function GalleryThumbnail($height)
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
// Generates the manipulation key
$variant = $this->owner->variantName(__FUNCTION__, $height);
// Instruct the backend to search for an existing variant with this key,
// and include a callback used to generate this image if it doesn't exist
return $this->owner->manipulateImage($variant, function (Image_Backend $backend) use ($height) {
return $backend->paddedResize(300, $height);
});
}
2017-01-24 05:14:39 +01:00
}
2015-09-15 04:52:02 +02:00
2017-01-24 05:14:39 +01:00
// in _config.php
File::add_extension('MyImageExtension');
\SilverStripe\Filesystem\Storage\DBFile::add_extension('MyImageExtension');
```
2015-09-15 04:52:02 +02:00
There are a few differences in this new API:
2017-01-24 05:14:39 +01:00
* The extension is no longer specific to DataObjects, so it uses the generic `Extension` class instead of `DataExtension`
2015-09-15 04:52:02 +02:00
* This extension is added to both `DBFile` and `File` , or order to make this manipulation available to non-dataobject
file references as well, but it could be applied to either independently.
* A helper method `variantName` is invoked in order to help generate a unique variant key. Custom code may use another
generation mechanism.
* Non-image files may also have manipulations, however the specific `manipulateImage` should not be used in this case.
A generic `manipulate` method may be used, although the callback for this method both is given, and should return,
an `AssetStore` instance and file tuple (Filename, Hash, and Variant) rather than an Image_Backend.
2015-09-03 07:46:08 +02:00
2017-06-29 08:45:17 +02:00
#### Upgrading code that uses File or Image shortcode handler
The `handle_shortcode` methods have been removed from the core File and Image classes and moved to separate classes in their own respective namespace. Image and File do not implement the ShortcodeHandler interface anymore.
The shortcode handler for `File` has been moved to `SilverStripe\Assets\ShortcodesFileShortcodeProvider` and the Image handler has been moved to `SilverStripe\Assets\Shortcodes\ImageShortcodeProvider`
Before this change, to use the handle_shortcode method, you would do something like this:
```
< ?php
2017-08-03 05:57:29 +02:00
class MyShortcodeUser extends Object
{
2017-06-29 08:45:17 +02:00
2017-08-07 05:11:17 +02:00
private $content;
2017-06-29 08:45:17 +02:00
2017-08-03 06:25:49 +02:00
public function Content($arguments, $parser, $shortcode)
{
2017-06-29 08:45:17 +02:00
return File::handle_shortcode($arguments, $this->content, $parser, $shortcode);
}
}
```
In the new situation, this would look like this:
```
< ?php
use SilverStripe\Assets\Shortcodes\FileShortcodeProvider;
2017-08-03 05:57:29 +02:00
class MyShortcodeUser extends Object
2017-06-29 08:45:17 +02:00
2017-08-03 05:57:29 +02:00
{
2017-06-29 08:45:17 +02:00
2017-08-07 05:11:17 +02:00
private $content;
2017-06-29 08:45:17 +02:00
2017-08-03 06:25:49 +02:00
public function Content($arguments, $parser, $shortcode)
{
2017-06-29 08:45:17 +02:00
return FileShortcodeProvider::handle_shortcode($arguments, $this->content, $parser, $shortcode);
}
}
```
2016-09-08 02:39:17 +02:00
#### Upgrading code that uses composite db fields.
2015-09-10 05:46:23 +02:00
2015-08-30 07:02:55 +02:00
The `CompositeDBField` interface has been replaced with an abstract class, `DBComposite` . In many cases, custom code
that handled saving of content into composite fields can be removed, as it is now handled by the base class.
2015-09-10 05:46:23 +02:00
The below describes the minimum amount of effort required to implement a composite DB field.
2017-01-24 05:14:39 +01:00
```php
2017-07-03 03:22:12 +02:00
use SilverStripe\ORM\FieldType\DBComposite;
2017-01-24 05:14:39 +01:00
class MyAddressField extends DBComposite
{
2017-08-07 05:11:17 +02:00
private static $composite_db = [
'Street' => 'Varchar(200)',
'Suburb' => 'Varchar(100)',
'City' => 'Varchar(100)',
'Country' => 'Varchar(100)'
];
public function scaffoldFormField($title = null, $params = null)
2017-01-24 05:14:39 +01:00
{
2017-08-07 05:11:17 +02:00
new SilverStripe\Forms\TextField($this->getName(), $title);
}
2017-01-24 05:14:39 +01:00
}
```
2015-09-10 05:46:23 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrading code that references `DataObject::database_fields` or `DataObject::db`
2015-09-10 05:46:23 +02:00
These methods have been updated to include base fields (such as ID, ClassName, Created, and LastEdited), as
well as composite DB fields.
`DataObject::database_fields` does not have a second parameter anymore, and can be called directly on an object
2016-09-09 03:33:52 +02:00
or class. E.g. `Member::database_fields()` .
2015-09-10 05:46:23 +02:00
If user code requires the list of fields excluding base fields, then use custom_database_fields instead, or
make sure to call `unset($fields['ID']);` if this field should be excluded.
`DataObject:db()` will return all logical fields, including foreign key ids and composite DB Fields, alongside
2016-12-14 00:01:55 +01:00
any child fields of these composites. This method can now take a second parameter $includesTable, which
2015-09-10 05:46:23 +02:00
when set to true (with a field name as the first parameter), will also include the table prefix in
`Table.ClassName(args)` format.
2016-09-08 02:39:17 +02:00
#### Upgrade code that uses SQLQuery
2015-09-10 05:46:23 +02:00
SQLQuery is still implemented, but now extends the new SQLSelect class and has some methods
deprecated. Previously this class was used for both selecting and deleting, but these
have been superceded by the specialised SQLSelect and SQLDelete classes.
Take care for any code or functions which expect an object of type `SQLQuery` , as
these references should be replaced with `SQLSelect` . Legacy code which generates
`SQLQuery` can still communicate with new code that expects `SQLSelect` as it is a
subclass of `SQLSelect` , but the inverse is not true.
2017-01-24 05:14:39 +01:00
#### Upgrade BuildTask classes
Similarly to the `$table_name` configuration property for DataObjects, you should define a `private static $segment` for `BuildTask`
instances to ensure that you can still run your task via `sake dev/tasks/MyTask` . Without defining it, the default
will be a fully-qualified class name like `sake dev/tasks/Me-MyModule-Tasks-MyTask` . This can also be configured in YAML.
```php
use SilverStripe\Dev\BuildTask;
class MyTask extends BuildTask
{
private static $segment = 'MyTask';
}
```
2016-05-25 07:09:29 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrade implementations of augmentSQL
2015-09-10 05:46:23 +02:00
Since this method now takes a `SQLSelect` as a first parameter, existing code referencing the deprecated `SQLQuery`
type will raise a PHP error.
Before:
2017-01-24 05:14:39 +01:00
```php
2017-06-29 00:44:48 +02:00
function augmentSQL(SQLQuery & $query, DataQuery & $dataQuery = null)
{
2017-08-07 05:11:17 +02:00
$locale = Translatable::get_current_locale();
if(!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhere()))) {
$qry = sprintf('"Locale" = \'%s\'', Convert::raw2sql($locale));
$query->addWhere($qry);
}
2017-01-24 05:14:39 +01:00
}
```
2015-09-10 05:46:23 +02:00
After:
2017-01-24 05:14:39 +01:00
```php
public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
{
2017-08-07 05:11:17 +02:00
$locale = Translatable::get_current_locale();
if (!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhereParameterised($parameters)))) {
$query->addWhere([
'"Locale"' => $locale
]);
}
2017-01-24 05:14:39 +01:00
}
```
2015-10-23 02:51:26 +02:00
2017-06-27 06:31:31 +02:00
#### Moved ErrorPage into a new module
2015-10-23 02:51:26 +02:00
2017-06-27 06:31:31 +02:00
ErrorPage has been moved to a separate [silverstripe/errorpage module ](http://addons.silverstripe.org/add-ons/silverstripe/errorpage )
to allow for alternative approaches to managing error responses.
The module is installed by default on new projects, but needs to be added to existing projects
to preserve functionality on the existing "Page not found" and "Server error" pages in the CMS.
composer require silverstripe/errorpage
Alternatively you can implement your own `onBeforeHTTPError()` handling to present custom errors.
By default, SilverStripe will display a plaintext "not found" message when the module isn't installed.
Check the [module upgrading guide ](http://addons.silverstripe.org/add-ons/silverstripe/errorpage )
for more configuration API changes on the `ErrorPage` class.
2015-10-23 02:51:26 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrading asset web.config, .htaccess, or other server configuration
2015-12-09 22:19:23 +01:00
2016-03-08 21:37:06 +01:00
Server configuration files for `/assets` are no longer static, and are regenerated via a set of
2017-01-24 05:14:39 +01:00
standard SilverStripe templates on flush. These templates include:
2015-12-09 22:19:23 +01:00
* `Assets_HTAccess.ss` : Template for public permissions on the Apache server.
* `Assets_WebConfig.ss` : Template for public permissions on the IIS server.
* `Protected_HTAccess.ss` : Template for the protected store on the Apache server (should deny all requests).
* `Protected_WebConfig.ss` : Template for the protected store on the IIS server (should deny all requests).
You will need to make sure that these files are writable via the web server, and that any necessary
configuration customisation is done via overriding these templates.
2017-09-08 01:25:30 +02:00
Depending on your server configuration, it may also be necessary to adjust your assets folder
permissions. Please see the [common installation problems ](/getting_started/installation/common_problems )
guide for configuration instruction.
2016-03-08 21:37:06 +01:00
If upgrading from an existing installation, make sure to invoke `?flush=all` at least once.
2015-12-09 22:19:23 +01:00
2016-09-09 03:33:52 +02:00
See our ["File Security" guide ](/developer_guides/files/file_security ) for more information.
2015-02-13 05:35:39 +01:00
2016-09-08 02:39:17 +02:00
#### `ListboxField` is now multiple-only
2015-02-13 05:35:39 +01:00
Previously, this field would operate as either a single select (default) or multi-select by setting
`setMultiple` to either true or false.
Now this field should only be used for multi-selection. Single-selection should be done using
a regular `DropdownField` .
2016-09-08 02:39:17 +02:00
#### `GroupedDropdownField::setDisabled` now only accepts a list of values.
2015-02-13 05:35:39 +01:00
Where previously you could specify a list of grouped values in the same way as `setSource` , this
method now only accepts either a non-associative array of values (not titles) or an `SS_List`
of items to disable.
2016-09-08 02:39:17 +02:00
#### Upgrading TinyMCE to 4.0
2016-02-12 04:00:15 +01:00
2017-01-24 05:14:39 +01:00
Please see the [tinymce upgrading guide ](http://archive.tinymce.com/wiki.php/Tutorial:Migration_guide_from_3.x )
to assist with upgrades to customisations to tinymce 3.
In Framework 4.0 the user interface for TinyMCE has been trimmed down considerably, with certain toolbar
buttons removed from the default cms configuration. These include:
2016-12-14 00:01:55 +01:00
2016-02-12 04:00:15 +01:00
* Strikethrough
* Styles dropdown
* Block quotes
* Horizontal Rule
* Undo / Redo
* Cut / Paste as word
* Select all
* Fullscreen
2016-12-14 00:01:55 +01:00
2016-02-12 04:00:15 +01:00
However, these function may be enabled on a case by case basis through modifification of the default
tinymce config, or by creating custom configurations.
The optional `ss_macron` plugin for inserting Māori diacritical marks
has been removed from core. You can configure the built-in `charmap` plugin instead:
2016-12-14 00:01:55 +01:00
2017-01-24 05:14:39 +01:00
```php
2017-07-03 03:22:12 +02:00
$editor = SilverStripe\Forms\HTMLEditor\HtmlEditorConfig::get('cms');
2017-01-24 05:14:39 +01:00
$editor->enablePlugins('charmap');
$editor->addButtonsToLine(1, 'charmap');
$editor->setOption('charmap_append', [
['256','A - macron'],
['274','E - macron'],
['298','I - macron'],
['332','O - macron'],
['362','U - macron'],
['257','a - macron'],
['275','e - macron'],
['299','i - macron'],
['333','o - macron'],
['363','u - macron']
]);
```
2016-12-14 00:01:55 +01:00
2016-02-12 04:00:15 +01:00
For more information on available options and plugins please refer to the
2017-01-24 05:14:39 +01:00
[TinyMCE documentation ](https://www.tinymce.com/docs/configure/ )
2016-02-25 05:32:41 +01:00
2016-09-08 02:39:17 +02:00
#### Upgrading DataObjects with the `Versioned` extension
2016-03-02 06:18:10 +01:00
In most cases, versioned models with the default versioning parameters will not need to be changed. However,
there are now additional restrictions on the use of custom stage names.
Rather than declaring the list of stages a model has, the constructor for `Versioned` will take a single mode
parameter, which declares whether or not the model is versioned and has a draft and live stage, or alternatively
if it only has versioning without staging.
2017-10-05 06:23:02 +02:00
Each form of this extension is registered under the appropriate service identifier, which you should use in your
model as below:
2017-01-24 05:14:39 +01:00
```php
2017-08-05 00:45:24 +02:00
use SilverStripe\ORM\DataObject;
2017-10-05 06:23:02 +02:00
use SilverStripe\ORM\Versioning\Versioned;
2017-08-05 00:45:24 +02:00
2017-01-24 05:14:39 +01:00
/**
* This model has staging and versioning. Stages will be "Stage" and "Live"
*/
2017-07-03 03:22:12 +02:00
class MyStagedModel extends SilverStripe\ORM\DataObject
2017-01-24 05:14:39 +01:00
{
2017-08-07 11:40:59 +02:00
private static $extensions = [
2017-10-05 06:23:02 +02:00
Versioned::class . '.stagedversioned',
2017-08-07 05:11:17 +02:00
];
2017-01-24 05:14:39 +01:00
}
/**
* This model has versioning only, and will not has a draft or live stage, nor be affected by the current stage.
*/
class MyVersionedModel extends DataObject
{
2017-08-07 05:11:17 +02:00
private static $extensions = [
2017-10-05 06:23:02 +02:00
Versioned::class . '.versioned',
2017-08-07 05:11:17 +02:00
];
2017-01-24 05:14:39 +01:00
}
```
2016-03-02 06:18:10 +01:00
2016-04-01 05:27:59 +02:00
Additionally, the following api methods have been added:
* `Versioned::publishRecursive` Publishes this object, and all owned objects
* `Versioned::publishSingle` Publishes this object, but not owned objects
* `Versioned::copyVersionToStage` Replaces the old `publish` method.
2016-12-14 00:01:55 +01:00
2016-04-01 05:27:59 +02:00
These methods are deprecated:
* `Versioned::publish` Replaced by `Versioned::copyVersionToStage`
* `Versioned::doPublish` Replaced by `Versioned::publishRecursive`
2016-09-08 02:39:17 +02:00
#### Implementation of ownership API
2016-02-25 05:32:41 +01:00
In order to support the recursive publishing of dataobjects, a new API has been developed to allow
2017-07-13 07:00:12 +02:00
developers to declare dependencies between objects. This is done to ensure that the published state
of linked components are consistent with their "owner." Without the concept of ownership, these linked
components could be implicitly exposed on the frontend, which may not align with the intent of the
content author.
2017-07-19 00:16:59 +02:00
For instance, on a products page which has a list of products, the products should not be published unless the products page is, too. The ownership API solves this by allowing you to declare
2017-07-13 07:00:12 +02:00
a two-way relationship between objects, typically, but not necessarily, linked by a database relationship
(`has_many`, `many_many` , etc.).
```php
2017-08-05 00:45:24 +02:00
use SilverStripe\Versioned\Versioned;
use Page;
use SilverStripe\ORM\DataObject;
2017-07-19 00:16:59 +02:00
class ProductPage extends Page
{
2017-07-13 07:00:12 +02:00
private static $has_many = [
'Products' => Product::class
];
private static $owns = [
'Products'
];
}
2017-07-19 00:16:59 +02:00
class Product extends DataObject
{
2017-07-13 07:00:12 +02:00
private static $extensions = [
Versioned::class
];
private static $has_one = [
'Parent' => ProductPage::class
];
}
```
If your objects are linked by something other than a database relationship, for instance, a custom
getter that is computed at runtime, the same rules can be applied, as long as you provide an `$owned_by`
setting on the child object.
2016-03-02 06:18:10 +01:00
2017-07-19 00:16:59 +02:00
For more information, see the [DataObject ownership ](https://docs.silverstripe.org/en/4/developer_guides/model/versioning/#dataobject-ownership ) documentation and the [versioning ](/developer_guides/model/versioning ) documentation
2016-03-08 12:20:51 +01:00
2016-09-08 02:39:17 +02:00
#### ChangeSet batch publishing
2016-03-30 23:37:12 +02:00
ChangeSet objects have been added, which allow groups of objects to be published in
a single atomic transaction.
This API will utilise the ownership API to ensure that changes to any object include
all necessary changes to owners or owned entities within the same changeset.
2016-09-08 02:39:17 +02:00
#### New `[image]` shortcode in `HTMLText` fields
2016-03-08 12:20:51 +01:00
The new Ownership API relies on relationships between objects.
Many of these relationships are already made explicit through `has_one` , `has_many` and `many_many` .
Images inserted into `HTMLText` fields (through a WYSIWYG editor) need to be tracked as well.
Instead of `<img>` tags, the field will insert `[image]` shortcodes which point to the database identifier
of the `Image` record rather than its path on the filesystem. The shortcode will be automatically replaced
when the field is rendered. Newly inserted images will automatically receive the shortcode and ownership tracking,
2016-12-14 00:01:55 +01:00
and existing `<img>` will continue to work.
2015-08-30 07:02:55 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrading references to DBField and subclasses
2015-08-30 07:02:55 +02:00
A major change in 4.0 is the introduction of namespaced DBField subclasses. Now as a standard, all DBField subclasses have a `DB` prefix, are namespaced, and have an associative alias which omits the DB prefix.
This means that for the most part, code that worked in 3.0 won't need to be changed, although if you have any hard class literals which reference the old classes, they will need to be updated to point to the new namespaced classes.
An exception to this is any classes which once had the `SS_` prefix, which will now be instead prefixed with `DB` , and have an un-aliased prefix. For example `SS_Datetime` is now `DBDateTime` , and has the alias `DateTime` which may be used in config.
2016-09-09 03:33:52 +02:00
Before:
2015-08-30 07:02:55 +02:00
2017-06-29 00:44:48 +02:00
```php
2017-07-03 03:22:12 +02:00
use SilverStripe\ORM\DataObject;
2017-06-29 00:44:48 +02:00
class MyObject extends DataObject
{
private static $db = [
2017-01-24 05:14:39 +01:00
'Number' => 'Int',
'Time' => 'SS_Datetime'
2017-06-29 00:44:48 +02:00
];
2017-01-24 05:14:39 +01:00
/**
* @param Int $val
* @return Varchar
*/
2017-06-29 00:44:48 +02:00
public function TextNumber()
{
2017-01-24 05:14:39 +01:00
return new Varchar('TextNumber', 'Number is ' . $this->Number);
}
}
```
2015-08-30 07:02:55 +02:00
2016-09-09 03:33:52 +02:00
After:
2015-08-30 07:02:55 +02:00
2017-01-24 05:14:39 +01:00
```php
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBVarchar;
class MyObject extends DataObject
{
2017-06-29 00:44:48 +02:00
private static $db = [
2017-01-24 05:14:39 +01:00
'Number' => 'Int',
'Time' => 'Datetime'
2017-06-29 00:44:48 +02:00
];
2017-01-24 05:14:39 +01:00
/**
* @param Int $val
* @return Varchar
*/
public function TextNumber()
{
return new DBVarchar('TextNumber', 'Number is ' . $this->Number);
}
}
```
2015-08-30 07:02:55 +02:00
2017-01-24 05:14:39 +01:00
Note that string references to `SS_Datetime` passed to injector, or used in config values, will still work, and will refer to the updated class names.
2016-05-27 03:09:03 +02:00
2016-09-08 02:39:17 +02:00
#### Upgrading from deprecated RestfulService
2016-05-27 03:09:03 +02:00
Install Guzzle to get an API consuming library.
`composer require guzzlehttp/guzzle` or add `guzzlehttp/guzzle: "^6.0"` to your composer.json.
For information on how to use Guzzle, please see the extensive [Guzzle documentation ](http://docs.guzzlephp.org/en/latest/ )
In case you want to keep using RestfulService, you can use `Firesphere/silverstripe-restfulservice` , but it is unmaintained and deprecated.
2016-09-08 02:39:17 +02:00
#### Upgrading from deprecated Oembed
2016-05-27 03:09:03 +02:00
2016-12-14 00:01:55 +01:00
Instead of Oembed, the framework now relies on [oscarotero/Embed ](https://github.com/oscarotero/Embed ) to handle getting the shortcode-data for embedding.
2016-05-27 03:09:03 +02:00
If you have custom embedding-code relying on Oembed, please refer to the documentation provided by oscarotero.
2016-07-19 11:58:35 +02:00
2016-09-08 02:39:17 +02:00
#### Admin URL can now be configured via custom Director routing rule
2016-07-19 11:58:35 +02:00
2016-12-14 00:01:55 +01:00
The default `admin/` URL to access the CMS interface can now be changed via a custom Director routing rule for
`AdminRootController` . If your website or module has hard coded `admin` URLs in PHP, templates or JavaScript, make sure
to update those with the appropriate function or config call. See
[CMS architecture ](/developer_guides/customising_the_admin_interface/cms-architecture#the-admin-url ) for language
2016-09-08 02:39:17 +02:00
specific functions.
2017-04-17 05:07:28 +02:00
#### Upgrading custom Authenticators
2017-07-02 05:27:17 +02:00
The methods `register` and `unregister` on `Authenticator` are deprecated in favor of the `Config` system. This means that any custom Authenticator needs to be registered through the yml config. For further information on how to create a custom authentication method, [see the Authentication documentation ](/developer_guides/Security/Authentication ).
2017-06-29 00:44:48 +02:00
2017-07-14 04:43:00 +02:00
```yml
2017-04-17 05:07:28 +02:00
SilverStripe\Security\Authenticator;
authenticators:
- MyVendor\MyModule\MyAuthenticator
```
2017-06-29 00:44:48 +02:00
2017-04-17 05:07:28 +02:00
If there is no authenticator registered, `Authenticator` will try to fall back on the `default_authenticator` , which can be changed using the following config, replacing the MemberAuthenticator with your authenticator:
2017-06-29 00:44:48 +02:00
2017-07-14 04:43:00 +02:00
```yml
2017-04-17 05:07:28 +02:00
SilverStripe\Security\Authenticator:
default_authenticator: SilverStripe\Security\MemberAuthenticator
```
As soon as a custom authenticator is registered, the default authenticator will not be available anymore, unless enabled specifically in the config.
By default, the `SilverStripe\Security\MemberAuthenticator` is seen as the default authenticator until it's explicitly set in the config.
2017-02-22 23:42:36 +01:00
2017-07-02 05:27:17 +02:00
##### IdentityStore and RequestFilters
As of SilverStripe 4, every request is authenticated against an `IdentityStore` , by default a CookieAuthenticationHandler and a SessionAuthenticationHandler, which are called from the `AuthenticationHandler` . If there is a valid `Member` , it is set on `Security::setCurrentUser()` , which defaults no `null` .
IdentityStores are responsible for logging members in and out (e.g. destroy cookies and sessions, or instantiate them).
2017-02-22 23:42:36 +01:00
#### Upgrading Config API usages
Performance optimisations have been made to Config which, under certain circumstances, require developer
care when modifying or caching config values. The top level config object is now immutable on application
bootstrap, and requires a developer to invoke `Config::modify()` to make mutable prior to modification.
This will immediately have a slight performance hit, so should be done sparingly, and avoided at all
if possible in performance intensive applications.
In addition, the `Config::inst()->update()` method is deprecated, and replaced with `Config::modify()->set()` and
`Config::modify()->merge()` to respectively replace and merge config.
When config is merged (either via modification or merged between yml blocks) falsey-values (including nulls)
now replace any prior values (even arrays).
One removed feature is the `Config::FIRST_SET` option. Either use uninherited config directly on the class
directly, or use the inherited config lookup. As falsey values now overwrite all parent class values, it is
now generally safer to use the default inherited config, where in the past you would need to use `FIRST_SET` .
2017-04-13 06:22:39 +02:00
#### Upgrading Cache API
We have replaced the unsupported `Zend_Cache` library with [symfony/cache ](https://github.com/symfony/cache ).
This also allowed us to remove SilverStripe's `Cache` API and use dependency injection with a standard
[PSR-16 ](http://www.php-fig.org/psr/psr-16/ ) cache interface instead.
Caches should be retrieved through `Injector` instead of `Cache::factory()` ,
and have a slightly different API (e.g. `set()` instead of `save()` ).
2017-06-29 00:44:48 +02:00
```diff
-$cache = Cache::factory('myCache');
+use Psr\SimpleCache\CacheInterface;
+$cache = Injector::inst()->get(CacheInterface::class . '.myCache');
// create a new item by trying to get it from the cache
-$myValue = $cache->load('myCacheKey');
+$myValue = $cache->get('myCacheKey');
// set a value and save it via the adapter
-$cache->save(1234, 'myCacheKey');
+$cache->set('myCacheKey', 1234);
// retrieve the cache item
-if (!$cache->load('myCacheKey')) {
- // ... item does not exists in the cache
-}
+if (!$cache->has('myCacheKey')) {
+ // ... item does not exists in the cache
+}
// Remove a cache key
-$cache->remove('myCacheKey');
+$cache->delete('myCacheKey');
```
2017-04-13 06:22:39 +02:00
2017-07-14 04:43:00 +02:00
With the necessary minimal config in _config/mycache.yml
2017-04-13 06:22:39 +02:00
2017-07-14 04:43:00 +02:00
```yml
2017-06-29 00:44:48 +02:00
---
Name: mycache
---
SilverStripe\Core\Injector\Injector:
Psr\SimpleCache\CacheInterface.myCache:
factory: SilverStripe\Core\Cache\CacheFactory
constructor:
namespace: 'mycache'
```
2017-04-13 06:22:39 +02:00
##### Configuration Changes
Caches are now configured through dependency injection services instead of PHP.
See our ["Caching" docs ](/developer-guides/performance/caching ) for more details.
2017-07-14 04:43:00 +02:00
Before (mysite/_config.php):
2017-04-13 06:22:39 +02:00
2017-06-29 00:44:48 +02:00
```php
Cache::add_backend(
'primary_memcached',
'Memcached',
[
'servers' => [
'host' => 'localhost',
'port' => 11211,
]
]
);
Cache::pick_backend('primary_memcached', 'any', 10);
```
2017-04-13 06:22:39 +02:00
2017-07-14 04:43:00 +02:00
After (mysite/_config/config.yml):
2017-04-13 06:22:39 +02:00
2017-07-14 04:43:00 +02:00
```yml
2017-06-29 00:44:48 +02:00
---
After:
- '#corecache'
---
SilverStripe\Core\Injector\Injector:
MemcachedClient:
class: 'Memcached'
calls:
- [ addServer, [ 'localhost', 11211 ] ]
SilverStripe\Core\Cache\CacheFactory:
class: 'SilverStripe\Core\Cache\MemcachedCacheFactory'
constructor:
client: '%$MemcachedClient
```
2017-02-22 23:42:36 +01:00
2017-07-14 04:43:00 +02:00
### <a name="usercode-style-upgrades"></a>User-code style upgrades
Although it is not mandatory to upgrade project code to follow SilverStripe and
PSR-2 standard it is highly recommended to ensure that code is consistent. The below sections
will assist you with bringing yourself up to speed.
Please note that before upgrading user code style it is necessary to run the standard upgrade path
to fix references and usages of framework API.
#### Upgrading user-code to use namespaces
Upgrading code to use namespaces is quite a complex process, and as such we have provided
several development tools and processes to help make the upgrade user friendly and as
automated as possible.
##### Using the upgrader tool to automatically apply namespaces
2017-07-19 00:16:59 +02:00
The [upgrader tool ](https://github.com/silverstripe/silverstripe-upgrader/ ) provides a feature
2017-07-14 04:43:00 +02:00
to not only automatically namespace code, but will provide automatic upgrade of other code
references to those classes.
Use the below to setup upgrader, and apply a namespace to a given code folder.
```
composer global require silverstripe/upgrader
cd ~/Project/Root
~/.composer/vendor/bin/upgrade-code add-namespace "WebDesignGroup\ShopSite" ./mysite/code --recursive --write
```
If you want to do a dry-run, omit the `--write` option to see a preview of a diff of
all changed project files.
This task will do the following:
- Add the given namespace to all files in the code class, and subdirectories.
- Sub-namespaces will be applied based on directory structure
- All references to classes in any namespaced files will be safely retained with additional `use` directives
added as necessary.
- Register all namespaced classese in a mysite/.upgrade.yml file for migration of other code
This task will not do the following, and must be done manually:
- Adding `table_name` to any namespaced classes
- Upgrade other references to namespaced classes outside of this folder
- Migrate any database table records
Please see the following steps for more information.
##### Using the upgrader tool to update references to namespaced user classes
Once a project has been namespaced all newly renamed classes will have a mapping included in the `mysite/.upgrade.yml`
file. If you have any user-code that references these, you may need to run the upgrader again (as you did did
to upgrade your project to namespaced framework classe).
```
composer global require silverstripe/upgrader
cd ~/Project/Root
~/.composer/vendor/bin/upgrade-code upgrade ./othercode --write
```
##### Updating custom dataobjects to use existing table names
Once you have namespaced your user code it will be necessary to customise the `table_name` config
for your dataobjects, in order to ensure the correct table is used after upgrade. It is recommended
to point this to the base name of the class, excluding namespace, as in 3.x.
```diff
namespace WebDesignGroup\ShopSite;
use SilverStripe\ORM\DataObject;
use Page;
class GalleryPage extends Page
{
+ private static $table_name = 'GalleryPage';
}
```
##### Class name remapping
If you've namespaced one of your custom page types, you may notice a message in the CMS
telling you it's obsolete. This is likely because the `ClassName`
field in the `SiteTree` table still contains the singular model name, e.g. `GalleryPage`
and that when you change it to `WebDesignGroup\ShopSite\GalleryPage` then everything
works again.
The `dev/build` task is configured to look for a legacy class name mapping
configuration setting and will update this for you automatically. You can use
this to add DB upgrading rules for your own classes.
For example, you could upgrade references to the newly namespaced Banner class by adding
this to your `mysite/_config/upgrade.yml` file:
```yml
SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
GalleryPage: WebDesignGroup\ShopSite\GalleryPage
```
The next time you run a dev/build the class name for all `GalleryPage` pages will
be automatically updated to the new `WebDesignGroup\ShopSite\GalleryPage`
#### Using php code checker to automatically update to PSR-2
You can use the [php codesniffer ](https://github.com/squizlabs/PHP_CodeSniffer ) tool
to not only detect and lint PSR-2 coding errors, but also do some minimal automatic
code style migration.
- Install the necessary library:
`composer require squizlabs/php_codesniffer`
- Copy silverstripe standards config file from framework/phpcs.xml to your project root:
`cp ./framework/phpcs.xml ./phpcs.xml`
- Run the automatic upgrade tool on your code folder
`vendor/bin/phpcbf ./mysite/code`
- Run the automatic linting tool to detect and manually fix other errors:
`vendor/bin/phpcs ./mysite/code`
Repeat the final step and manually repair suggested changes, as necessary,
until you no longer have any linting issues.
#### Upgrade user-code to use PSR-4 autoloading
While not critical to an upgrade, SilverStripe 4.0 has adopted the [PS-4 autoloading ](http://www.php-fig.org/psr/psr-4/ )
standard for the core modules, so it's probably a good idea to be consistent.
You can implement this in your composer configuration like so:
```json
{
"autoload": {
"psr-4": {
"WebDesignGroup\\ShopSite\\": "mysite/src/"
}
}
}
```
Now you just need to ensure that each class site in the correct folder location
(including case sensitivity) to match its namespace. For example,
`WebDesignGroup\ShopSite\Model\GalleryItem.php` should live at `mysite/src/Model/GalleryItem.php` .
Note that you don’ t have to use `src/` as the root folder name. You can continue
to use `code/` if you want to. SilverStripe has adopted the PSR-4 approach and
have also started to use `src/` as a default folder location instead of
`code/` . If you’ re going to change, it's probably a good time to do it while you're
upgrading.
For examples, take a look at the file/folder structure and to the
`composer.json` configuration in either the `framework` or `cms` modules.
Please note that there are changes to template structure which in some cases
require templates to be in a folder location that matches the namespace of the class
that it belongs to, e.g. `themes/mytheme/templates/MyVendor/Foobar/Model/MyModel.ss` .
2016-09-08 02:39:17 +02:00
## <a name="api-changes"></a>API Changes
### <a name="overview-general"></a>General and Core API
#### <a name="overview-general-api"></a>General and Core API Additions / Changes
2017-03-20 00:50:10 +01:00
* Minimum PHP version raised to 5.6 (with support for PHP 7.x)
2017-06-22 12:50:45 +02:00
* Dropped support for PHP safe mode (removed php 5.4).
2017-03-20 00:50:10 +01:00
* Once PHP versions become [unsupported by the PHP Project ](http://php.net/supported-versions.php )),
we drop support for those versions in the [next minor release](/contributing/release-process
This means PHP 5.6 and PHP 7.0 support will become unsupported in Dec 2018.
2017-03-30 23:48:22 +02:00
* Minimum CMS browser requirement raised from Internet Explorer 8 to Internet Explorer 11
2016-12-14 00:01:55 +01:00
* Updated PHPUnit from 3.7 to 4.8 ([upgrade notes](https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-4.0.0#backwards-compatibility-issues)).
Please remove any PHPUnit related `require_once()` calls (e.g. in `FeatureContext`
2016-09-08 02:39:17 +02:00
definitions of the [behat-extension ](https://github.com/silverstripe-labs/silverstripe-behat-extension ) module).
Run `composer require --dev 'phpunit/phpunit:~4.8'` on existing projects to pull in the new dependency.
2017-01-16 05:31:48 +01:00
* `always_populate_raw_post_data` will now raise a deprecation warning in install.php when running in php 5.x,
unless set to `-1` . This is due to `$HTTP_RAW_POST_DATA` being removed in php 7.
See the [http://php.net/manual/en/reserved.variables.httprawpostdata.php ](php documentation ) for more information.
2016-09-08 02:39:17 +02:00
* Admin URL can now be configured via custom Director routing rule
* `Controller::init` visibility changed to protected. Use `Controller::doInit()` instead.
2016-09-30 03:09:33 +02:00
* `Controller::join_links` supports an array of link sections.
2016-09-08 02:39:17 +02:00
* `Object::useCustomClass` has been removed. You should use the config API with Injector instead.
* `Object::invokeWithExtensions` now has the same method signature as `Object::extend` and behaves the same way.
* `ServiceConfigurationLocator` is now an interface not a class.
* `i18nTextCollectorTask` merge is now true by default.
* `Object` has been broken up into various traits, each of which can be added to other objects independently:
* `Configurable` Provides Config API helper methods
* `Injectable` Provides Injector API helper methods
* `Extensible` Allows extensions to be applied
2017-06-22 12:50:45 +02:00
* `Convert` class has extra methods for formatting file sizes in php_ini compatible format
* `Convert::memstring2bytes()` will parse a php_ini memory size.
* `Convert::bytes2memstring()` will format the memory size with the appropriate scale.
2016-09-08 02:39:17 +02:00
* `SiteTree.alternatePreviewLink` is deprecated. Use `updatePreviewLink` instead.
* `Injector` dependencies no longer automatically inherit from parent classes.
* `$action` parameter to `Controller::Link()` method is standardised.
* Moved test database cleanup task from `sake dev/tests/cleanupdb` to `sake dev/tasks/CleanupTestDatabasesTask`
2016-10-14 03:30:05 +02:00
* `Injector::load` given a `src` parameter will no longer guess the
service name from the filename. Now the service name will either
by the array key, or the `class` parameter value.
2017-01-11 04:58:59 +01:00
* Uniqueness checks for `File.Name` is performed on write only (not in `setName()` )
2017-01-26 05:20:08 +01:00
* Created `Resettable` interface to better declare objects which should be reset between tests.
2017-02-14 06:19:09 +01:00
* Added a server requirement for the php-intl extension (shipped by default with most PHP distributions)
* Replaced Zend_Date and Zend_Locale with the php-intl extension.
* Consistently use CLDR date formats (rather than a mix of CLDR and date() formats)
2017-02-22 04:12:46 +01:00
* Moved config into a new module: [silverstripe/config ](https://github.com/silverstripe/silverstripe-config/ ).
See upgrading notes below.
* Falsey config values (null, 0, false, etc) can now replace non-falsey values.
* Introduced new ModuleLoader manifest, which allows modules to be found via composer name.
2017-05-19 04:38:06 +02:00
E.g. `$cms = ModuleLoader::inst()->getManifest()->getModule('silverstripe/cms')`
2017-03-14 03:20:51 +01:00
* `ClassManifest::getOwnerModule()` now returns a `Module` object instance.
2017-05-17 07:40:13 +02:00
* `Object` class has been removed.
* `parse_class_spec` moved to `ClassInfo`
* `create_from_spec` functionality removed, but now supportede by `Injector` natively.
* `Injectable` , `Extensible` and `Configurable` traits added to support other methods.
2017-03-02 03:24:38 +01:00
* Certain methods have been moved from `Controller` to `RequestHandler` :
* `Link`
* `redirect`
* `redirectBack`
* `RequestHandler` link and redirection behaviour has been enhanced slightly:
* `Link` now relies on the `url_segment` handler being provided for the class.
If left unset, this will raise an error.
* `getBackURL` and `getReturnReferer` have been added to safely inspect the current request
to see if there is a url to redirect back to.
2017-03-29 06:23:49 +02:00
* `LeftAndMain` class has had all tree manipulation code moved into CMS module class `CMSMain` .
This includes:
* `LeftAndMain_TreeNode` class -> renamed to `CMSMain_TreeNode`
* `SiteTreeAsUL` removed (override left in `CMSMain` )
* `getSiteTreeFor()` -> moved to `CMSMain`
* `getsubtree()` -> moved to `CMSMain`
* `updatetreenodes()` -> moved to `CMSMain`
* `savetreenodes()` -> moved to `CMSMain`
2017-05-25 03:43:13 +02:00
* `EditorToolbar()` method renamed to `Modals()` and now returns a `ModalController` handler
instance rather than a `HTMLEditorField_Toolbar`
2017-04-13 03:33:29 +02:00
* Some `Director` API have been removed.
* $dev_servers
* $test_servers
* $urlParams and setUrlParams()
* `Director.alternate_host` removed. Use `Director.alternate_base_url` instead.
* `Director.alternate_protocol` removed. Use `Director.alternate_base_url` instead.
* Global enviromnent variables changed:
* 'BlockUntrustedIPS' env setting has been removed.
All IPs are untrusted unless `SS_TRUSTED_PROXY_IPS` is set to '*'
See [Environment Management docs ](/getting-started/environment_management/ ) for full details.
2017-06-23 07:28:04 +02:00
* `SS_TRUSTED_PROXY_HOST_HEADER` , `SS_TRUSTED_PROXY_PROTOCOL_HEADER` , and `SS_TRUSTED_PROXY_IP_HEADER`
are no longer supported. These settings should go into the Injector service configuration for
TrustedProxyMiddleware instead.
2017-04-13 03:33:29 +02:00
* `MODULES_PATH` removed
* `MODULES_DIR` removed
* `SS_HOST` removed. Use `SS_BASE_URL` instead.
2017-06-15 04:20:12 +02:00
* `Member::canLogIn()` now returns boolean. Use `Member::validateCanLogin()` to get a `ValidationResult`
* `Security` methods deprecated:
* `has_default_admin` use `DefaultAdminService::hasDefaultAdmin()` instead
* `check_default_admin` use `DefaultAdminService::isDefaultAdminCredentials()` instead
* `default_admin_username` use `DefaultAdminService::getDefaultAdminUsername()` instead
* `default_admin_password` use `DefaultAdminService::getDefaultAdminPassword()` instead
* `setDefaultAdmin` use `DefaultAdminService::setDefaultAdmin()` instead
* `clearDefaultAdmin` use `DefaultAdminService::clearDefaultAdmin()` instead
* `findAnAdministrator` use `DefaultAdminService::findOrCreateDefaultAdmin()` instead
* `Member` methods deprecated:
* `checkPassword` . Use Authenticator::checkPassword() instead
2017-06-23 01:43:19 +02:00
* `RequestFilter` has been deprecated in favour of
[HTTPMiddleware ](/developer_guides/controllers/middlewares ). Also the legacy RequestFilter
API has changed: $session and $dataModel variables removed from preRequest / postRequest.
2017-10-05 06:23:02 +02:00
* `Extension` instances are now singletons and no longer are constructed once per extended object.
See the 'Upgrade extensions to work as singletons' section on this page for more information.
2016-09-08 02:39:17 +02:00
#### <a name="overview-general-removed"></a>General and Core Removed API
2017-06-22 12:50:45 +02:00
* Removed `ConfigureFromEnv.php` as it's no longer necessary.
* `Session` object has had significant refactoring. This object no longer is accessed via
`Session::inst()` , but instead should be queried from the current request via `$request->getSession()` .
All static methods have been removed, and the `inst_` prefix removed from all instance members.
Please see the upgrading section on Session object for more details.
* `Director.rules` config no longer support `redirect:<url>` directly via config.
2017-10-16 04:17:16 +02:00
* `Director::set_environment_type()` has been removed.
2017-06-22 12:50:45 +02:00
Get the `Kernel` instance via injector and query `getEnvironment()` instead.
E.g. `$type = Injector::inst()->get(Kernel::class)->getEnvironment();` .
2017-08-29 22:35:41 +02:00
* The environment can no longer be configured via YAML (`Director.environment_type`).
Use a [.env file ](/getting_started/environment_management ) to manage environment settings.
2017-06-22 12:50:45 +02:00
* Many global methods have been refactored into `Environment` or `Convert` class.
* `increase_xdebug_nesting_level_to` removed (functionality has been inlined into `AppKernel` )
* `set_increase_time_limit_max` moved to `Environment::setTimeLimitMax()`
* `get_increase_time_limit_max` moved to `Environment::getTimeLimitMax()`
* `set_increase_memory_limit_max` moved to `Environment::setMemoryLimitMax()`
* `get_increase_memory_limit_max` moved to `Environment::getMemoryLimitMax()`
* `increase_time_limit_to` moved to `Environment::increaseTimeLimitTo()`
* `increase_memory_limit_to` moved to `Environment::increaseMemoryLimitTo()`
* `translate_memstring` moved to `Convert::memstring2bytes` .
* `getTempFolder` moved to `TempFolder::getTempFolder()`
* `getTempParentFolder` removed.
* `getTempFolderUsername` removed.
2016-09-08 02:39:17 +02:00
* `CMSMain::buildbrokenlinks()` action is removed.
2017-06-22 12:50:45 +02:00
* `Injector::unregisterAllObjects()` has been removed. Use `unregisterObjects` to unregister
groups of objects limited by type instead.
2017-03-16 01:30:38 +01:00
* `SS_Log` class has been removed. Use `Injector::inst()->get(LoggerInterface::class)` instead.
2016-09-08 02:39:17 +02:00
* Removed `CMSBatchAction_Delete`
* Removed `CMSBatchAction_DeleteFromLive`
* Removed `CMSMain.enabled_legacy_actions` config.
2017-03-29 06:23:49 +02:00
* `CMSmain.getCMSTreeTitle` is now ignored on extensions. Use `updateCMSTreeTitle` in extensions instead.
2016-09-08 02:39:17 +02:00
* Removed ability to run tests via web requests (`http://mydomain.com/dev/tests`), use the standard CLI
command instead (`vendor/bin/phpunit`).
* Removed `dev/jstests/` controller (no replacement)
* Removed `TestRunner` and `JSTestRunner` APIs
* Removed `PhpUnitWrapper` , `PhpUnitWrapper_3_4` , `PhpUnitWrapper_3_5` , `PhpUnitWrapper_Generic` , `SapphireTestSuite` APIs
2017-04-21 03:34:23 +02:00
* Removed `SapphireTestReporter` and `CliTestReporter`
2016-09-08 02:39:17 +02:00
* Removed `SapphireTest::skipTest()` , use `markTestSkipped()` in a `setUp()` method instead
* Removed the `History.js` javascript library.
* `debugmethods` querystring argument has been removed from debugging.
2017-06-13 02:59:11 +02:00
* Moved `ErrorPage` into a new module: [silverstripe/errorpage ](http://addons.silverstripe.org/add-ons/silverstripe/errorpage ). See upgrading notes in that module.
2016-09-22 17:56:37 +02:00
* Removed `VirtualPage_Controller` . Virtual pages will now share whichever controller the “target” page uses
2016-09-08 02:39:17 +02:00
* Removed `Config_LRU`
* Removed `SilverStripeInjectionCreator`
* Removed `i18n::get_translatable_modules` method.
* Removed `i18nTextCollector_Writer_Php`
2017-03-14 03:20:51 +01:00
* `i18nTextCollector` no longer collects from `themes/<theme>` root dir.
Modules which provide themes via `<moduleName>/themes/<theme>` are now preferred.
2016-09-08 02:39:17 +02:00
* Removed `i18nSSLegacyAdapter`
* Removed `FunctionalTest::stat`
* Removed `LeftAndMainMarkingFilter`
* Removed `Controller::getFormOwner`
2017-04-21 02:12:20 +02:00
* Removed `TeamCityListener`
2016-09-08 02:39:17 +02:00
* The Spyc YAML library has been removed from /thirdparty. Please load it yourself, or use the
Symfony YAML component that’ s automatically installed by composer.
* `RestfulService` has been removed. Use Guzzle instead. See Upgrading notes.
* Our self-maintained `Oembed` implementation has been removed, in favour of introducing
[oscarotero/Embed ](https://github.com/oscarotero/Embed ) as a dependency.
2016-09-13 22:47:48 +02:00
* Removed TextParser and BBCodeParser. These are available in an archived module,
[silverstripe-archive/bbcodeparser ](https://github.com/silverstripe-archive/silverstripe-bbcodeparser )
2017-01-30 22:56:52 +01:00
* Removed `ViewableData::ThemeDir` . Use `ThemeResourceLoader::findThemedResource` in conjunction with `SSViewer::get_themes` instead.
2017-02-22 04:12:46 +01:00
* Removed `Config::FIRST_SET` and `Config::INHERITED`
2017-03-02 03:24:38 +01:00
* Removed `RequestHandler.require_allowed_actions` . This is now fixed to on and cannot be
disabled.
2017-03-14 03:20:51 +01:00
* Config or module searching methods have been removed from `ClassManifest` . Use `ModuleLoader`
to get this information instead:
- `getModules`
- `getConfigDirs`
- `getConfigs`
2017-05-08 11:07:16 +02:00
* Removed `Session::set_config()` and `Session::get_config()` . Use the `Session.timeout` config setting instead
2017-05-08 11:10:17 +02:00
* Removed `Security::set_login_recording()` and `Security::get_login_recording()` .
Use the `Security.login_recording` config setting instead.
2017-05-08 11:17:28 +02:00
* Removed `ModelAsController::find_old_page()` . Use `OldPageRedirector::find_old_page()` instead
* Removed `RootURLController:set_default_homepage_link()` and `RootURLController::get_default_homepage_link()` .
Use the `RootURLController.default_homepage_link` config setting instead.
2017-05-08 10:13:38 +02:00
* Removed `CreditCardField` , `CountryDropdownField` , `PhoneNumberField` , `MemberDatetimeOptionsetField` , `InlineFormAction` .
Use custom code instead
* Removed `ResetFormAction` , use `FormAction::create()->setAttribute('type', 'reset')` instead
2017-05-19 03:45:07 +02:00
* `Injector` now complies with [PSR-11 ](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md ).
Accordingly, `hasService()` has been renamed to `has()` , and `get()` will throw
`SilverStripe\Core\Injector\InjectorNotFoundException` when the service can't be found.
2017-05-19 05:53:44 +02:00
* Removed `CustomMethods::createMethod()` . Use closures instead.
2017-10-05 06:23:02 +02:00
* Removed `Extension::$ownerBaseClass` property. You should use $this->owner->baseClass() instead.
The second argument of `Extension::setOwner()` has also been removed.
2016-12-14 00:01:55 +01:00
2016-09-08 02:39:17 +02:00
#### <a name="overview-general-deprecated"></a>General and Core Deprecated API
A very small number of methods were chosen for deprecation, and will be removed in 5.0 rather than 4.0
* `ClassInfo::baseDataClass` - Use `DataObject::getSchema()->baseDataClass()` instead.
* `ClassInfo::table_for_object_field` - Use `DataObject::getSchema()->tableForField()` instead
2017-02-22 04:12:46 +01:00
* `Config::inst()->update()` is deprecated. Use `Config::modify()->set()` or `Config::modify()->merge()`
instead.
2016-09-08 02:39:17 +02:00
### <a name="overview-orm"></a>ORM API
#### <a name="overview-orm-api"></a>ORM API Additions / Changes
* Deprecate `SQLQuery` in favour `SQLSelect`
2016-09-26 07:22:19 +02:00
* `DataObject.many_many` 'through' relationships now support join dataobjects in place of
automatically generated join tables. See the [/developer_guides/relations ](datamodel relationship docs )
for more info.
* `DataList::filter` by null now internally generates "IS NULL" or "IS NOT NULL" conditions
appropriately on queries.
* `DataList::createDataObject` is now public.
2016-09-08 02:39:17 +02:00
* `DataObject` constructor now has an additional parameter, which must be included in subclasses.
* `DataObject::db` now returns composite fields.
* `DataObject::ClassName` field has been refactored into a `DBClassName` type field.
* `DataObject::can` has new method signature with `$context` parameter.
2016-10-11 06:50:19 +02:00
* `DataObject::duplicate` Now requires explicit flag to duplicate belongs_many_many (off by default),
but now works with unsaved relations. By default only many_many are duplicated.
2016-09-08 02:39:17 +02:00
* `DBHTMLText` no longer enables shortcodes by default. Two injector aliases have been created for this
class which can be used to select the correct behaviour:
* `HTMLText` : `DBHTMLText` with shortcodes enabled
* `HTMLFragment` : `DBHTMLText` without shortcodes enabled (as default)
2017-03-10 04:43:10 +01:00
* `CMSPreviewable` has been moved from the `SilverStripe\Admin` namespace to `SilverStripe\ORM`
2016-09-08 02:39:17 +02:00
* Changes to `DBString` formatting:
* `NoHTML` is renamed to `Plain`
* `LimitWordCountXML` is removed. Use `LimitWordCount` instead.
* `BigSummary` is removed. Use `Summary` instead.
* Most limit methods on `DBHTMLText` now plain text rather than attempt to manipulate the underlying HTML.
2017-05-08 11:05:11 +02:00
* `FormField::Title` and `FormField::RightTitle` are now cast as plain text by default (but can be overridden).
* `FormField#createTag()` has been renamed to `FormField::create_tag()`
2017-03-29 06:23:49 +02:00
* `Hierarchy` class has had much of it's functionality refactored out into `MarkedSet` :
* `isMarked`
* `isTreeOpened`
* `isExpanded`
* `markByID`
* `markPartialTree`
* `markExpanded`
* `markUnexpanded`
* `markToExpose`
* `markClosed`
* `markOpened`
* `markedNodeIDs`
* `getChildrenAsUL` replaced with `renderChildren` , which now takes a template name.
* `markingFilterMatches` (and made protected)
* `markChildren` (and made protected)
2016-09-08 02:39:17 +02:00
* Removed `DataList::applyFilterContext` private method
* Search filter classes (e.g. `ExactMatchFilter` ) are now registered with `Injector`
via a new `DataListFilter.` prefix convention.
see [search filter documentation ](/developer_guides/model/searchfilters ) for more information.
2017-01-20 03:57:50 +01:00
* `Permission::flush_permission_cache()` renamed to `reset()` and added to `Resettable` interface.
2016-09-08 02:39:17 +02:00
* `Versioned` API has some breaking changes:
* Versioned constructor now only allows a single string to declare whether staging is enabled or not. The
number of names of stages are no longer able to be specified. See below for upgrading notes for models
with custom stages.
* `reading_stage` is now `set_stage` and throws an error if setting an invalid stage.
* `current_stage` is now `get_stage`
* `getVersionedStages` is gone.
* `get_live_stage` is removed. Use the `Versioned::LIVE` constant instead.
* `getDefaultStage` is removed. Use the `Versioned::DRAFT` constant instead.
* `$versionableExtensions` is now `private static` instead of `protected static`
* `hasStages` is addded to check if an object has a given stage.
* `stageTable` is added to get the table for a given class and stage.
2016-12-14 00:01:55 +01:00
* Any extension declared via `versionableExtensions` config on Versioned dataobject must now
2016-09-08 02:39:17 +02:00
`VersionableExtension` interface at a minimum. `Translatable` has been removed from default
`versionableExtensions`
2016-10-18 07:19:59 +02:00
* The default CMS delete behaviour for versioned dataobjects is now to delete from both draft
and live stages, and to save to the archive. There is no longer a separate "Archive" action.
* Any writes to versioned dataobjects (in either Draft or Live) will always write to the draft
(main) table as a source of truth. This means that records created in Live mode will always be
available to the CMS and in draft mode.
2016-10-20 03:49:22 +02:00
* `_versions` suffixed tables are now renamed to `_Versions` . This fix will be automatically
applied during dev/build.
2016-10-05 03:16:09 +02:00
* A lot of standard versioned API has been refactored from `SiteTree` into `Versioned` extension.
* All versioned DataObjects have `canPublish()` , `canArchive()` , `canUnpublish()` permission checks
* All versioned Dataobjects have `doPublish()` , `doArchive()` , `doPublish()` , and `doUnpublish()` actions.
However, `do*()` methods will no longer automatically check `can*()` permissions, and must be done by
usercode before invocation.
* `SiteTree::getIsAddedToStage()` moved to `Versioned` and renamed to `isOnDraftOnly()`
* `SiteTre::getIsModifiedOnStage()` moved to `Versioned` and renamed to `isModifiedOnDraft()`
* `SiteTree::isPublished()` moved to `Versioned` .
* `SiteTree::getExistsOnLive()` removed in favour of `isPublished()`
* `isOnDraft()` added to `Versioned` .
* `isArchived()` added to `Versioned` .
* `isOnLiveOnly()` added to `Versioned` .
2016-09-08 02:39:17 +02:00
* `ChangeSet` and `ChangeSetItem` have been added for batch publishing of versioned dataobjects.
* `DataObject.table_name` config can now be used to customise the database table for any record.
* `DataObjectSchema` class added to assist with mapping between classes and tables.
2017-08-07 11:40:59 +02:00
* `DataObject.indexes` now uses `columns` instead of `value` to define index contents.
2017-02-14 06:19:09 +01:00
* `DBMoney` values are now treated as empty only if `Amount` field is null. If an `Amount` value
is provided without a `Currency` specified, it will be formatted as per the current locale.
2017-05-08 11:09:13 +02:00
* Removed `DatabaseAdmin#clearAllData()` . Use `DB::get_conn()->clearAllData()` instead
2017-06-22 12:50:45 +02:00
* `SapphireTest` temp DB methods have been removed and put into a new `TempDatabase` class.
This allows applications to create temp databases when not running tests.
This class now takes a connection name as a constructor class, and no longer
has static methods.
The following methods have been moved to this new class and renamed as non-static:
* `using_temp_db` -> `isUsed()`
* `kill_temp_db` -> `kill()`
* `empty_temp_db` _> `clearAllData()`
* `create_temp_db` -> `build()`
* `delete_all_temp_dbs` -> `deleteAll()`
* `resetDBSchema` -> `resetSchema()`
2017-01-26 05:20:08 +01:00
The below methods have been added or had their functionality updated to `DBDate` , `DBTime` and `DBDatetime`
* `getTimestamp()` added to get the respective date / time as unix timestamp (seconds since 1970-01-01)
2017-02-14 06:19:09 +01:00
* `Format()` method now use [CLDR format strings ](http://userguide.icu-project.org/formatparse/datetime ),
rather than [PHP format string ](http://php.net/manual/en/function.date.php ).
E.g. `d/m/Y H:i:s` (php format) should be replaced with to `dd/MM/y HH:mm:ss` (CLDR format).
2017-01-26 05:20:08 +01:00
* getISOFormat() added which returns the standard date/time ISO 8601 pattern in CLDR format.
2017-02-14 06:19:09 +01:00
* `setValue` method is now a lot more restrictive, and expects dates and times to be passed in
ISO 8601 format (y-MM-dd) or (HH:mm:ss). Certain date formats will attempt to parse with
the below restrictions:
- `/` , `.` or `-` are supported date separators, but will be replaced with `-` internally.
- US date formats (m-d-y / y-d-m) will not be supported and may be parsed incorrectly.
(Note: Date form fields will still support localised date formats).
- `dd-MM-y` will be converted to `y-MM-dd` internally.
- 2-digit values for year will now raise errors.
2017-01-26 05:20:08 +01:00
* `FormatFromSettings` will default to `Nice()` format if no member is logged in.
* `Nice` , `Long` and `Full` methods will now follow standard formatting rules for the
current locale, rather than pre-defined formats.
* `Short` added to format concise date/time values, as a shorter version than `Nice`
* `getFormatter` method added, which returns a locale-specific date/time formatter.
`DBTime` specific changes:
2017-04-21 02:04:44 +02:00
2017-01-26 05:20:08 +01:00
* Added `DBTime::FormatFromSettings`
2016-12-14 00:01:55 +01:00
2016-09-08 02:39:17 +02:00
#### <a name="overview-orm-removed"></a>ORM Removed API
2017-06-22 12:50:45 +02:00
* Deprecated globals `$database` and `$databaseConfig` . Please use `DB::setConfig()` instead.
* `DataModel` removed
2017-05-11 11:07:27 +02:00
* `DataObject::can*` methods no longer accept a member ID. These must now be passed a Member object or left null
2016-10-06 06:31:38 +02:00
* `DataObject::db` removed and replaced with `DataObjectSchema::fieldSpec` and `DataObjectSchema::fieldSpecs`
* `DataObject::manyManyComponent` moved to `DataObjectSchema`
* `DataObject::belongsToComponent` moved to `DataObjectSchema`
* `DataObject::hasOneComponent` moved to `DataObjectSchema`
* `DataObject::hasManyComponent` moved to `DataObjectSchema`
* `DataObject::getRemoteJoinField` moved to `DataObjectSchema`
* `DataObject::database_fields` renamed and moved to `DataObjectSchema::databaseFields`
* `DataObject::has_own_table` renamed and moved to `DataObjectSchema::classHasTable`
* `DataObject::composite_fields` renamed and moved to `DataObjectSchema::compositeFields` `
* `DataObject::manyManyExtraFieldsForComponent` moved to `DataObjectSchema`
2017-09-03 23:23:07 +02:00
* `DataObject::$destroyed` is now deprecated
2016-09-26 07:22:19 +02:00
* Removed `DataObject::validateModelDefinitions` . Relations are now validated within `DataObjectSchema`
2016-10-06 06:31:38 +02:00
* Removed `DataObject` methods `hasOwnTableDatabaseField` , `has_own_table_database_field` and
`hasDatabaseFields` are superceded by `DataObjectSchema::fieldSpec` .
2016-10-07 00:23:22 +02:00
Use `$schema->fieldSpec($class, $field, DataObjectSchema::DB_ONLY | DataObjectSchema::UNINHERITED )` .
2016-10-06 06:31:38 +02:00
Exclude `uninherited` option to search all tables in the class hierarchy.
* Removed `DataObject::is_composite_field` . Use `DataObjectSchema::compositeField` instead.
* Removed `DataObject::custom_database_fields` . Use `DataObjectSchema::databaseFields`
or `DataObjectSchema::fieldSpecs` instead.
2016-09-08 02:39:17 +02:00
* Removed `DataList::getRelation` , as it was mutable. Use `DataList::applyRelation` instead, which is immutable.
* Removed `DataList::applyFilterContext` private method
* `Member` Field 'RememberLoginToken' removed, replaced with 'RememberLoginHashes' has_many relationship
* Removed `UpgradeSiteTreePermissionSchemaTask`
* Removed `EncryptAllPasswordsTask`
* Removed `DBString::LimitWordCountXML()` method. Use `LimitWordCount` for XML safe version.
2016-10-05 03:16:09 +02:00
* Removed `SiteTree::getExistsOnLive()` . Use `isPublished()` instead.
* Removed `SiteTree::getIsDeletedFromStage()` . Use `isOnDraft()` instead (inverse case).
2016-09-26 07:22:19 +02:00
* `DataObject.many_many` no longer supports triangular resolution. Both the `many_many` and `belongs_many_many`
must point directly to the specific class on the opposing side, not a subclass or parent.
* `DataObject::validateModelDefinitions()` has been removed. Validation and parsing of config is now handled
within `DataObjectSchema` .
2016-10-18 07:19:59 +02:00
* `CMSBatchAction_Delete` removed. Use `CMSBatchAction_Archive` instead.
2017-01-26 05:20:08 +01:00
* Removed several DBDate methods:
- `past_date`
- `prior_monday`
- `weekday`
- `next_day`
- `day_before`
- `days_between`
* `nice_format` has been removed from `DBDate` / `DBTime` / `DBDatetime` has been removed in favour of
locale-specific formatting for Nice()
2017-02-14 06:19:09 +01:00
* Removed several `DBTime` methods:
- `TwelveHour`
- `Nice24`
2017-01-26 05:20:08 +01:00
* Removed some `DBMoney` methods due to lack of support in php-intl.
- `NiceWithShortname`
- `NiceWithName`
- `getShortName`
- `getCurrencyName`
* Removed additional arguments from `DBMoney::getSymbol` . The result of this value is
now localised based on the currency code assigned to the `DBMoney` instance
* Removed `DBMoney::getAllowedCurrencies` . Apply validation to `MoneyField` instead.
2017-03-29 06:23:49 +02:00
* `Hierarchy` has lots of removed api:
- `parentStack()` removed. Use `getAncestors()` instead
- `doAllChildrenIncludingDeleted()` removed. Use `AllChildrenIncludingDeleted()` instead.
- `naturalNext` removed.
- `naturalPrev` removed.
- `markingFinished` removed.
2016-12-14 00:01:55 +01:00
2016-09-08 02:39:17 +02:00
### <a name="overview-filesystem"></a>Filesystem API
#### <a name="overview-filesystem-api"></a>Filesystem API Additions / Changes
2017-07-03 03:22:12 +02:00
* Image manipulations have been moved into a new `[ImageManipulation](api:SilverStripe\Assets\ImageManipulation)` trait.
2016-09-08 02:39:17 +02:00
* `CMSFileAddController` removed.
* `UploadField::setAllowedFileCategories('image')` now excludes non-resizeable images. 'unresizeable_image' is
can be used to validate these types.
* `Image_Backend` API now loads and saves from `AssetContainer` instances rather than local files.
* The following File categories have been renamed: 'zip' to 'archive', 'doc' to 'document', and 'mov' to 'video'
* `File::updateLinks` no longer takes urls as parameters. All file links are now identified either by
the `DataObject::ID` in a `data-fileid` property, or via shortcodes. This is necessary because file
urls are no longer able to identify assets.
* Extension point `HtmlEditorField::processImage` has been removed, and moved to `Image::regenerateImageHTML`
* `Upload::load` now stores assets directly without saving into a `File` dataobject.
* Protected file storage is now a core Framework API. See [/developer_guides/files/file_security] for
more information.
* `File` is now versioned, and should be published before they can be used on the frontend.
See section on [Migrating File DataObject from 3.x to 4.0 ](#migrating-file-dataobject-from-3x-to-40 )
below for upgrade notes.
* New filesystem abstraction including new `DBFile` database field to hold file references.
* `ShortcodeHandler` interface to help generate standard handlers for HTML shortcodes in the editor.
2017-06-29 08:45:17 +02:00
* `handle_shortcode` methods are removed from `File` and `Image` and moved to their own classes in `SilverStripe\Assets\Shortcodes` and are named `FileShortcodeProvider` and `ImageShortcodeProvider` respectively.
2016-09-08 02:39:17 +02:00
* `AssetNameGenerator` interface, including a `DefaultAssetNameGenerator` implementation, which is used to generate
renaming suggestions based on an original given filename in order to resolve file duplication issues.
* `GeneratedAssetHandler` API now used to store and manage generated files (such as those used for error page
cache or combined files).
* `Requirements_Minifier` API can be used to declare any new mechanism for minifying combined required files.
By default this api is provided by the `JSMinifier` class, but user code can substitute their own.
* `AssetField` formfield to provide an `UploadField` style uploader for the new `DBFile` database field.
* `AssetControlExtension` is applied by default to all DataObjects, in order to support the management
of linked assets and file protection.
* `ProtectedFileController` class is used to serve up protected assets.
2017-10-18 02:11:22 +02:00
* `AssetAdaptor` has a new config `default_server` which helps tell the code which server type to use if no matching type was found by scanning the server software - defaults to `apache`
2016-09-08 02:39:17 +02:00
#### <a name="overview-filesystem-removed"></a>Filesystem removed API
The following image manipulations previously deprecated has been removed:
* `Image::SetRatioSize` superceded by `Fit`
* `Image::SetWidth` superceded by `ScaleWidth`
* `Image::SetHeight` superceded by `ScaleHeight`
* `Image::SetSize` superceded by `Pad`
* `Image::PaddedImage` superceded by `Pad`
* `Image::CroppedImage` superceded by `Fill`
* `Image::AssetLibraryPreview` superceded by `PreviewThumbnail`
* `Image::AssetLibraryThumbnail` superceded by `CMSThumbnail`
The following `File` methods have been removed. Since there is no longer any assumed local path for any file,
methods which dealt with such paths may no longer be relied on.
* `File::deletedatabaseOnly`
* `File::link_shortcode_handler` renamed to `handle_shortcode`
* `File::setParentID`
* `File::getFullPath`
* `File::getRelativePath`
* `File::Content` database field is removed
Image manipulations have been moved out of Image.php and now available to any File or DBFile which has the
appropriate mime types. The following file manipulations classes and methods have been removed:
* `Image_Cached` class
* `Image::regenerateFormattedImages` method
* `Image::getGeneratedImages` method
* `Image::deleteFormattedImages` method
2017-06-29 08:45:17 +02:00
* `Image::handle_shortcode` moved to `SilverStripe\Assets\Shortcodes\ImageShortcodeProvider::handle_shortcode`
2016-09-08 02:39:17 +02:00
* `AssetAdmin::deleteunusedthumbnails` method
* `AssetAdmin::getUnusedThumbnails` method
Many `Folder` api have also been removed:
* `Folder_UnusedAssetsField` class
* `Folder::syncChildren` method
* `Folder::constructChild` method
* `Folder::addUploadToFolder` method
The following filesystem synchronisation methods and tasks are also removed
* `RegenerateCachedImagesTask` class
* `CleanImageManipulationCache` class
* `Filesystem::sync` method
* `AssetAdmin::doSync` method
### <a name="overview-template"></a>Template and Form API
#### <a name="overview-template-api"></a>Template and Form API Additions / Changes
* Upgrade of TinyMCE to version 4.
* Templates now use a standard template lookup system via `SSViewer::get_templates_by_class`
which builds a candidate list for a given class. Actual resolution of existing templates
for any list of candidates is actually performed by `SSViewer::chooseTemplate`
* `HtmlEditorConfig` is now an abstract class, with a default implementation `TinyMCEConfig` for the built in
TinyMCE editor.
* `HtmlEditorField::setEditorConfig` may now take an instance of a `HtmlEditorConfig` class, as well as a
standard config identifier name.
* `HeaderField` requires a `$name` constructor argument (`new HeaderField('MyName', 'My Title')`
* `default_cast` is now enforced on all template variables. See upgrading notes below.
* FormField templates no longer look in the 'forms' folder for templates. As all form fields are
now namespaced, the path for these templates will now match the namespace of the given class instead.
* `$module` parameter in `themedCSS` and `themedJavascript` removed.
* Theme selector has been removed from SiteConfig. Please use `SSViewer.themes` config instead.
* `FormAction::setValidationExempt` can be used to turn on or off form validation for individual actions
* GridField edit form now has improved support for versioned DataObjects, with basic publishing
actions available when editing records.
* `PopoverField` added to provide popup-menu behaviour in react forms (currently not available for
non-react forms).
2016-10-20 01:42:24 +02:00
* Introduction of experimental `FormFactory` API as a substitute for DataObject classes being responsible
for building their own form fields. This builds a form based on a given controller and model,
and can be customised on a case by case basis. This has been introduced initially for the asset-admin
module.
2016-12-14 00:02:05 +01:00
* Introduced `AssetAdmin\Forms\UploadField` as a react-friendly version of UploadField. This may also
be used in normal entwine forms for managing files in a similar way to UploadField. However, this
does not support inline editing of files.
2017-02-14 06:19:09 +01:00
* Added method `FormField::setSubmittedValue($value, $data)` to process input submitted from form
submission, in contrast to `FormField::setValue($value, $data)` which is intended to load its
value from the ORM. The second argument to setValue() has been added.
2017-04-18 00:34:18 +02:00
* `HTMLValue` service name is now fully qualified `SilverStripe\View\Parsers\HTMLValue` .
* FormField::create_tag() has been moved to `HTML` class and renamed to createTag. Invoke with
`HTML::createTag()` .
2016-12-14 00:02:05 +01:00
2016-09-08 02:39:17 +02:00
The following methods and properties on `Requirements_Backend` have been renamed:
* `Requirements_Backund::$combine_files` made protected and renamed `$combinedFiles`
* `Requirements_Backend::$combine_js_with_min` made protected and renamed `$minifyCombinedFiles`
* `Requirements_Backend::$write_header_comments` made protected and renamed `$writeHeaderComment`
* `Requirements_Backend::$write_js_to_body` made protected and renamed to `$writeJavascriptToBody`
* `Requirements_Backend::$force_js_to_bottom` renamed to `$forceJSToBottom`
* `get_combined_files_enabled` renamed to `getCombinedFilesEnabled`
* `set_combined_files_enabled` renamed to `setCombinedFilesEnabled`
* `get_suffix_requirements` renamed to `getSuffixRequirements`
* `set_suffix_requirements` renamed to `setSuffixRequirements`
* `get_custom_scripts` renamed to `getCustomScripts`
* `unblock_all` renamed to `unblockAll`
* `include_in_response` renamed to `includeInResponse`
* `combine_files` renamed to `combineFiles`
* `get_combine_files` renamed to `getCombinedFiles`
* `clear_combined_files` renamed to `clearCombinedFiles`
* `process_combined_files` renamed to `processCombinedFiles`
* `set_write_js_to_body` renamed to `setWriteJavascriptToBody`
* `set_force_js_to_bottom` renamed to `setForceJSToBottom`
New methods on `Requirements` are added to access these:
* `get_minify_combined_js_files`
* `set_minify_combined_js_files`
* `get_force_js_to_bottom`
* `get_write_js_to_body`
2016-12-14 00:01:55 +01:00
2016-09-08 02:39:17 +02:00
Some methods on `Requirements` have had their method signatures changed:
* `includeInHTML` has had the first parameter $template removed as it was previously deprecated.
A new config `Requirements_Backend.combine_in_dev` has been added in order to allow combined files to be
forced on during development. If this is off, combined files is only enabled in live environments.
2016-11-23 06:09:10 +01:00
Form validation has been refactored significantly. A new `FormMessage` trait has been created to
handle field-level and form-level messages. This has the following properties:
* `setMessage` to assign a message, type, and cast
* `getMessage` retrieves the message string
* `getMessageType` retrieves the message type (E.g. error, good, info)
* `getMessageCast` retrieves the cast type
* `getMessageCastingHelper` retrieves the DBField cast to use for the appropriate message cast
* `getSchemaMessage` encodes this message for form schema use in ReactJS.
2017-03-02 03:24:38 +01:00
`Form` behaviour methods have been changed:
2016-11-23 06:09:10 +01:00
2017-03-02 03:24:38 +01:00
* __construct() now allows a RequestHandler to be passed as a first argument, rather than a Controller.
in addition this argument is now optional. This allows forms to be constructed as a model only.
2016-11-23 06:09:10 +01:00
* `validate` is replaced with `validationResult` instead, which returns a `ValidationResult` instance.
This is no longer automatically persisted in the state by default, unless a redirection occurs.
You can also save any response in the state by manually invoking `saveFormState` inside a custom
validation response handler.
* `setupFormErrors` renamed to `restoreFormState`
* `resetValidation` renamed to `clearFormState`
* `loadMessagesFrom` method created to load a ValidationResult into a form.
* `setMessage` . third parameter is now $cast type
* `messageForForm` removed. Use `setMessage` or `sessionMessage` instead.
* `getSessionValidationResult` / `setSessionValidationResult` used to get / set session errors
* `getSessionData` / `setSessionData` used to get / set field values cached in the session
* `getAjaxErrorResponse` and `getRedirectReferer` created to simplify `getValidationErrorResponse`
* `addErrorMessage` removed. Users can either use `sessionMessage` or `sessionError` to add a
form level message, throw a ValidationException during submission, or add a custom validator.
2017-03-02 03:24:38 +01:00
* `Form` is no longer a `RequestHandler` , but implements the `HasRequestHandler` interface and returns
a `FormRequestHandler` instance from `getRequestHandler()` . the `Form` constructor no longer has
any mandatory parameters, and the first parameter allows a non-`Controller` `RequestHandler` to be
passed. Certain methods have been moved from `Form` to `FormRequestHandler` :
* `buttonClicked`
* `checkAccessAction`
* `handleField`
* `httpSubmission`
* `Link`
2016-11-23 06:09:10 +01:00
`Validator` methods have changed:
* `validate` method now returns a `ValidationResult` instance.
* `requireField` method removed. Use `RequiredFields` subclass instead.
`ValidationResult` now has these methods:
* `serialize` / `unserialize` for saving within session state
* `messageList` renamed to `getMessages`
* `error` method replaced with `addMessage` / `addError` / `addFieldMessage` / `addFieldError`
* `valid` renamed to `isValid`
`ValidationException` has these changes:
* `$message` second constructor parameter is removed. Constructor only accepts `$result` ,
which may be a string, and optional `$code`
2017-01-26 05:20:08 +01:00
New `DatetimeField` methods replace `getConfig()` / `setConfig()` :
* `getTimezone()` / `setTimezone()`
* `getDateTimeOrder()` / `setDateTimeOrder()`
* `getLocale()` / `setLocale()`
2017-02-14 06:19:09 +01:00
* `datavaluefield` config is removed as internal data value is now fixed to ISO 8601 format
2017-01-26 05:20:08 +01:00
2017-04-21 02:04:44 +02:00
The `DatetimeField` has changed behaviour:
2017-04-26 03:49:59 +02:00
* It uses a combined input instead of a composite from `DateField` and `TimeField`
Consequently, `getDateField()` and `getTimeField()` have been removed.
* It returns [ISO 8601 normalised dates ](https://html.spec.whatwg.org/multipage/infrastructure.html#local-dates-and-times )
by default in `Value()` , which include a "T" separator between date and time.
This is required to allow HTML5 input. Either use `setHTML5(false)` to set your custom format,
or use `dataValue()` to retrieve a whitespace separated representation.
2017-04-26 23:18:38 +02:00
* It no longer accepts `setValue()` as an array with 'date' and 'time' keys
2017-04-21 02:04:44 +02:00
* Added `getHTML5()` / `setHTML5()`
2017-01-26 05:20:08 +01:00
New `DateField` methods replace `getConfig()` / `setConfig()` :
2017-03-30 23:37:21 +02:00
* `getDateFormat()` / `setDateFormat()`
2017-01-26 05:20:08 +01:00
* `getMinDate()` / `setMinDate()`
* `getMaxDate()` / `setMaxDate()`
* `getLocale()` / `setLocale()`
2017-03-30 23:37:21 +02:00
The `DateField` has changed behavior:
2017-04-03 02:00:59 +02:00
* `DateField` no longer provides a jQuery UI date picker (`showcalendar` option),
and uses [HTML5 date pickers ](https://www.wufoo.com/html5/types/4-date.html ) by default instead.
2017-03-30 23:37:21 +02:00
* `DateField` provides an optional polyfill for
[browsers without HTML5 date picker support ](http://caniuse.com/#feat=input-datetime )
2017-04-03 02:00:59 +02:00
* The `dmyfields` option has been replced with native HTML5 behaviour (as one single `<input type=date>` ).
2017-03-30 23:37:21 +02:00
* `getClientLocale` / `setClientLocale` have been removed (handled by `DateField->locale` and browser settings)
2017-01-26 05:20:08 +01:00
New `TimeField` methods replace `getConfig()` / `setConfig()`
* `getTimeFormat()` / `setTimeFormat()`
* `getLocale()` / `setLocale()`
2017-03-30 23:37:21 +02:00
* `getClientConfig()` has been removed (in favour of `setHTML5()` )
2016-11-23 06:09:10 +01:00
2016-09-08 02:39:17 +02:00
#### <a name="overview-template-removed"></a>Template and Form Removed API
* Removed `TabularStyle`
* Removed `NestedForm`
* Removed `FieldList` methods:
* `getTabPathRewrites`
* `setTabPathRewrites`
* `rewriteTabPath`
2016-11-23 06:09:10 +01:00
* Removed `Form` methods (see above for replacements):
2016-09-08 02:39:17 +02:00
* `transformTo`
* `callfieldmethod`
* `single_field_required`
* `current_action`
* `set_current_action`
2016-11-23 06:09:10 +01:00
* `setupFormErrors`
* `resetValidation`
* `messageForForm`
* `addErrorMessage`
2017-03-02 03:24:38 +01:00
* `testSubmission`
* `testAjaxSubmission`
2016-11-23 06:09:10 +01:00
* Removed `Validator::requireField()` method.
* Removed `ValidationResult` (see above for replacements):
* `messageList`
* `codeList`
* `message`
* `starredList`
* `error`
* `valid`
2016-09-08 02:39:17 +02:00
* Removed `ReportAdminForm.ss` template
* `FormField::dontEscape()` has been removed. Escaping is now managed on a class by class basis.
* Removed `PermissionCheckboxSetField::getAssignedPermissionCodes()` (never implemented)
* `Requirements::delete_combined_files()` and `Requirements::delete_combined_files()` methods have been removed
as they are obsolete.
2017-01-26 05:20:08 +01:00
* Removed `DatetimeField` , `DateField` and `TimeField` methods `getConfig` and `setConfig` . Individual
getters and setters for individual options are provided instead. See above for list of new methods.
2017-02-14 06:19:09 +01:00
* Removed `NumericField_Readonly` . Use `setReadonly(true)` instead.
2017-02-22 04:12:46 +01:00
* `SSViewer` deprecated methods removed:
* `set_source_file_comments()`
* `get_source_file_comments()`
* `getOption`
2017-04-03 02:00:59 +02:00
* `setOption`
* Removed `MemberDatetimeOptionsetField` (no replacement)
* Removed `DateField_View_JQuery` (replaced with native HTML5 support in `DateField` )
2017-05-25 03:43:13 +02:00
* The following HTMLEditorField_* classes have been removed:
* `HTMLEditorField_Toolbar` (replaced With `ModalController` in admin module)
* `HTMLEditorField_Embed` (replaced with `EmbedResource` in asset-admin module)
* `HTMLEditorField_File`
* `HTMLEditorField_Flash`
* `HTMLEditorField_Image`
2017-01-13 17:12:25 +01:00
2017-01-18 04:58:48 +01:00
### <a name="overview-i18n"></a>i18n API
2017-01-13 17:12:25 +01:00
2017-01-18 04:58:48 +01:00
#### <a name="overview-i18n-api"></a>i18n API Additions / Changes
* Upgrade of i18n to symfony/translation
* Localisation based on language-only (without any specific locale) is now supported
2017-01-25 04:35:13 +01:00
* `i18nEntityProvider::provideI18nEntities()` Now is expected to return only a single array
2017-01-18 04:58:48 +01:00
map of key to default values.
2017-01-25 04:35:13 +01:00
* i18n keys for '.PLURAL_NAME' and '.SINGULAR_NAME' have been changed back to use the namespaced class names
for all DataObject subclasses, rather than just the basename without namespace.
2017-01-18 04:58:48 +01:00
* i18n key for locale-respective pluralisation rules added as '.PLURALS'. These can be configured
within yaml in array format as per [ruby i18n pluralization rules ](http://guides.rubyonrails.org/i18n.html#pluralization ).
2017-02-14 06:19:09 +01:00
* `i18n.all_locales` config moved to `SilverStripe\i18n\Data\Locales.locales`
* `i18n.common_languages` config moved to `SilverStripe\i18n\Data\Locales.languages`
* `i18n.likely_subtags` config moved to `SilverStripe\i18n\Data\Locales.likely_subtags`
* `i18n.tinymce_lang` config moved to `SilverStripe\Forms\HTMLEditor\TinyMCEConfig.tinymce_lang`
* `i18n::get_tinymce_lang()` moved to `SilverStripe\Forms\HTMLEditor\TinyMCEConfig::get_tinymce_lang()`
* `i18n::get_locale_from_lang()` moved to `SilverStripe\i18n\Data\Locales::localeFromLang()`
* `i18n::get_lange_from_locale()` moved to `SilverStripe\i18n\Data\Locales::langFromLocale()`
* `i18n::validate_locale()` moved to `SilverStripe\i18n\Data\Locales::validate()`
* `i18n::get_common_languages()` moved to `SilverStripe\i18n\Data\Locales::getLanguages()`
* `i18n::get_locale_name()` moved to `SilverStripe\i18n\Data\Locales::localeName()`
* `i18n::get_language_name()` moved to `SilverStripe\i18n\Data\Locales::languageName()`
* `i18n.module_priority` config moved to `SilverStripe\i18n\Data\Sources.module_priority`
* `i18n::get_owner_module()` moved to `SilverStripe\Core\Manifest\ClassManifest::getOwnerModule()`
2017-03-14 03:20:51 +01:00
This now returns a `Module` object instance instead of a string.
2017-02-14 06:19:09 +01:00
* `i18n::get_existing_translations()` moved to `SilverStripe\i18n\Data\Sources::getKnownLocales()`
2017-01-18 04:58:48 +01:00
#### <a name="overview-i18n-removed"></a>i18n API Removed API
2017-01-13 17:12:25 +01:00
2017-01-25 04:35:13 +01:00
* `Zend_Translate` removed
2017-01-26 05:20:08 +01:00
* `i18n::_t()` Support for sprintf-style `%s` arguments deprecated
* `i18n::_t()` Using non-associative injection with named parameters is now an error
* `i18n::get_language_name()` removed.
* `i18n::get_language_code()` removed.
* `i18n::get_common_locales()` removed.
* `i18n.common_locales` config removed
2017-01-13 17:12:25 +01:00
2017-07-14 04:43:00 +02:00
#### <a name="overview-mailer"></a>Email Additions / Changes
2017-01-13 17:12:25 +01:00
2017-01-18 04:58:48 +01:00
* `Mailer` converted to an interface
* `SwfitMailer` added as new default mailer
* `Email` re-written to be powered by [SwiftMailer ](https://github.com/swiftmailer/swiftmailer )
2017-01-13 17:12:25 +01:00
* Default template body variable renamed from `$Body` to `$EmailContent`
* `$email->setTemplate()` renamed to `$email->setHTMLTemplate()`
* Added `$email->setPlainTemplate` for rendering plain versions of email
2017-02-01 09:21:03 +01:00
* `$email->populateTemplate()` has been replaced with `$email->setData()`
2017-03-24 12:17:26 +01:00
### <a name="overview-testing"></a>SapphireTest
2017-07-19 15:25:46 +02:00
* `is_running_tests()` is no longer public and user code should not rely on this. Test-specific behaviour
2017-07-07 00:45:39 +02:00
should be implemented in `setUp()` and `tearDown()`
2017-03-24 12:17:26 +01:00
* `setUpOnce` removed. Please use `setUpBeforeClass`
* `tearDownOnce` removed. Please use `tearDownAfterClass`
* `TestListener` class removed
* `SapphireTest::$requiredExtensions` renamed to `SapphireTest::$required_extensions` and made static
* `SapphireTest::$extraDataObjects` renamed to `SapphireTest::$extra_dataobjects` and made static
* `SapphireTest::$extraControllers` renamed to `SapphireTest::$extra_controllers` and made static
2017-04-18 07:04:40 +02:00
2017-07-14 04:43:00 +02:00
### <a name="overview-security"></a>Security
2017-04-18 07:04:40 +02:00
* `LoginForm` now has an abstract method `getAuthenticatorName()` . If you have made subclasses of this,
you will need to define this method and return a short name describing the login method.
2017-10-05 05:34:20 +02:00
* `MemberLoginForm` has a new constructor argument for the authenticator class, although this is usually
2017-04-18 07:04:40 +02:00
constructed by `MemberAuthenticator` and won't affect normal use.
2017-10-05 05:34:20 +02:00
* `Authenticator` methods `register` and `unregister` are deprecated in favour of using `Config`
* Unused `SetPassword` property removed from `Member` . Use `Member::changePassword` or set `Password` directly.