Consistent 4.0 changelog docs formatting

Added diff styling, requires merge of https://github.com/silverstripe/silverstripe-docsviewer/pull/134.
This commit is contained in:
Ingo Schommer 2017-06-29 10:44:48 +12:00 committed by Aaron Carlino
parent ee05c586b6
commit 3ffc6ebcd7

View File

@ -193,36 +193,40 @@ For example, if you have the below `_ss_environment.php` file, your `.env` would
`_ss_environment.php`:
:::php
<?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');
define('SS_DATABASE_USERNAME', 'root')
define('SS_DATABASE_PASSWORD', '');
define('SS_DATABASE_SERVER', '127.0.0.1');
```php
<?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');
define('SS_DATABASE_USERNAME', 'root')
define('SS_DATABASE_PASSWORD', '');
define('SS_DATABASE_SERVER', '127.0.0.1');
```
`.env`:
## Environment
SS_ENVIRONMENT_TYPE="dev"
SS_DEFAULT_ADMIN_USERNAME="admin"
SS_DEFAULT_ADMIN_PASSWORD="password"
SS_BASE_URL="http://localhost/"
```
## 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"
### Database
SS_DATABASE_CHOOSE_NAME="true"
SS_DATABASE_CLASS="MySQLDatabase"
SS_DATABASE_USERNAME="root"
SS_DATABASE_PASSWORD=""
SS_DATABASE_SERVER="127.0.0.1"
```
The removal of the `_ss_environment.php` file means that conditional logic is no longer available in the environment
@ -251,93 +255,82 @@ In particular specific Object class usages should be replaced as below:
Upgrade subclasses
:::php
// old
class MyClass extends Object {}
// new
class MyClass {
use Extensible;
use Injectable;
use Configurable;
public function __construct() {
// Only needed if using Extensible trait
$this->constructExtensions();
}
}
```diff
-class MyClass extends Object
-{
-}
+class MyClass
+{
+ use Extensible;
+ use Injectable;
+ use Configurable;
+
+ public function __construct()
+ {
+ // Only needed if using Extensible trait
+ $this->constructExtensions();
+ }
+}
```
References to $this->class
```diff
-$obj->class
+get_class($obj);
:::php
// old
$obj->class
$this->class;
// new
get_class($obj);
static::class;
-$this->class;
+static::class;
```
Upgrade parse_class_spec()
:::php
// old
$spec = Object::parse_class_spec($spec);
// new
$spec = ClassInfo::parse_class_spec($spec);
```diff
-$spec = Object::parse_class_spec($spec);
+$spec = ClassInfo::parse_class_spec($spec);
```
Upgrade create_from_string()
:::php
// old
$obj = Object::create_from_string('Varchar(100)');
// new
$obj = Injector::inst()->create('Varchar(100)');
```diff
-$obj = Object::create_from_string('Varchar(100)');
+$obj = Injector::inst()->create('Varchar(100)');
```
Extensions
```diff
:::php
// old
Object::add_extension('File', 'Versioned');
$has = Object::has_extension('File', 'Versioned');
$extensions = Object::get_extensions('File');
// new
File::add_extension(Versioned::class);
$has = File::has_extension(Versioned::class)
$extensions = File::get_extensions();
// new (alternate form)
// Note: The class the extension method is called on MUST be a parent class
// of the first argument.
DataObject::add_extension(File::class, Versioned::class); // alternate
$has = DataObject::has_extension(File::class, Versioned::class); // alternate
$extensions = DataObject::get_extensions(File::class);
-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
```
#### Upgrade references to Session object
Session object is no longer statically accessible via `Session::inst()`. Instead, Session
is a member of the current request.
Before:
:::php
public function httpSubmission($data, $form, $request) {
Session::set('loggedIn', null);
}
After:
:::php
public function httpSubmission($data, $form, $request) {
$request->getSession()->set('loggedIn', null);
}
```diff
-public function httpSubmission($data, $form, $request)
-{
- Session::set('loggedIn', null);
-}
+public function httpSubmission($data, $form, $request)
+{
+ $request->getSession()->set('loggedIn', null);
+}
```
In some places it may still be necessary to access the session object where no request is available.
@ -422,8 +415,10 @@ You can resolve this in your model by adding an explicit cast to HTML for those
Before:
```php
class MyObject extends ViewableData {
public function getSomeHTML {
class MyObject extends ViewableData
{
public function getSomeHTML
{
$title = Convert::raw2xml($this->Title);
return "<h1>{$title}</h1>";
}
@ -462,38 +457,40 @@ 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.
Usages of UploadField will need to be upgraded as below.
Usages of UploadField will need to be upgraded as below:
Before:
3.x code
:::php
class MyClass extends DataObject {
public function getCMSFields() {
return new FieldList(
new UploadField('Files')
);
}
```php
class MyClass extends DataObject
{
public function getCMSFields()
{
return new FieldList(
new UploadField('Files')
);
}
}
```
4.x code
After:
```php
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FileHandleField;
:::php
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FileHandleField;
class MyClass extends DataObject {
public function getCMSFields() {
return FieldList::create(
Injector::inst()->create(FileHandleField::class, 'Files')
);
}
class MyClass extends DataObject
{
public function getCMSFields()
{
return FieldList::create(
Injector::inst()->create(FileHandleField::class, 'Files')
);
}
}
```
#### Upgrade code that uses i18n
@ -521,25 +518,26 @@ The below demonstrates how you can provide new localisation strings for an objec
including both plurals and cross-module localisations.
:::php
class MyObject extends DataObject, implements i18nEntityProvider
```php
class MyObject extends DataObject, implements i18nEntityProvider
{
public function provideI18nEntities()
{
public function provideI18nEntities()
{
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',
],
];
}
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',
],
];
}
}
```
In YML format this will be expressed as the below:
@ -547,41 +545,43 @@ In YML format this will be expressed as the below:
`mymodule/lang/en.yml`:
:::yaml
en:
MyObject:
SINGULAR_NAME: 'object'
PLURAL_NAME: 'objects'
PLURALS:
one: 'An object',
other: '{count} objects'
```yaml
en:
MyObject:
SINGULAR_NAME: 'object'
PLURAL_NAME: 'objects'
PLURALS:
one: 'An object',
other: '{count} objects'
```
`extendedmodule/lang/en.yml`:
:::yaml
en:
AnotherSection:
DESCRIPTION: 'This is the description for this section'
```yaml
en:
AnotherSection:
DESCRIPTION: 'This is the description for this section'
```
Usage of these pluralised strings is through the existing _t() method,
and require a `|` pipe-delimeter with a {count} argument.
:::php
public function pluralise($count)
{
return _t('MyObject.PLURALS', 'An object|{count} objects', [ 'count' => $count ]);
}
```php
public function pluralise($count)
{
return _t('MyObject.PLURALS', 'An object|{count} objects', [ 'count' => $count ]);
}
```
In templates this can also be invoked as below:
:::ss
<%t MyObject.PLURALS 'An item|{count} items' count=$Count %>
```ss
<%t MyObject.PLURALS 'An item|{count} items' count=$Count %>
```
#### Removed Member.DateFormat and Member.TimeFormat database settings
@ -609,7 +609,7 @@ In order to retain existing file paths in line with framework version 3 you shou
Note that this will not allow you to utilise certain file versioning features in 4.0.
```
```yaml
SilverStripe\Filesystem\Flysystem\FlysystemAssetStore:
legacy_paths: true
```
@ -656,38 +656,29 @@ This is the subset of all image types which may be assigned to the `[api:Image]`
manipulations applied to it. This should be used as the file type restriction on any `[api:UploadField]` which
is intended to upload images for manipulation.
Before:
```php
if($file instanceof Image) {
$upload = new UploadField();
$upload->setAllowedFileCategories('image');
}
```
After:
```php
if ($file->getIsImage()) {
$upload = new UploadField();
$upload->setAllowedFileCategories('image/supported');
}
```diff
-if($file instanceof Image) {
- $upload = new UploadField();
- $upload->setAllowedFileCategories('image');
-}
+if ($file->getIsImage()) {
+ $upload = new UploadField();
+ $upload->setAllowedFileCategories('image/supported');
+}
```
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')`.
E.g.
```php
class MyObject extends DataObject
{
private static $has_one = array(
private static $has_one = [
"ImageObject" => "Image"
);
private static $db = array(
];
private static $db = [
"ImageField" => "DBFile('image/supported')"
);
];
}
```
@ -701,29 +692,22 @@ files to the asset persistence layer. As a wrapper for an individual file, you c
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.
Before:
```php
function importTempFile($tmp) {
copy($tmp, ASSETS_PATH . '/imported/' . basename($tmp));
$file = new File();
$file->setFilename('assets/imported/'.basename($tmp));
$file->write();
}
```
After:
```php
public function importTempFile($tmp)
{
Versioned::reading_stage('Stage');
$file = new File();
$file->setFromLocalFile($tmp, 'imported/' . basename($tmp));
$file->write();
$file->doPublish();
}
```diff
-function importTempFile($tmp)
-{
- copy($tmp, ASSETS_PATH . '/imported/' . basename($tmp));
- $file = new File();
- $file->setFilename('assets/imported/'.basename($tmp));
- $file->write();
-}
+public function importTempFile($tmp)
+{
+ Versioned::reading_stage('Stage');
+ $file = new File();
+ $file->setFromLocalFile($tmp, 'imported/' . basename($tmp));
+ $file->write();
+ $file->doPublish();
+}
```
Note that 'assets' is no longer present in the new code, and the path beneath what was once assets is now
@ -858,15 +842,14 @@ that handled saving of content into composite fields can be removed, as it is no
The below describes the minimum amount of effort required to implement a composite DB field.
```php
<?php
class MyAddressField extends DBComposite
{
private static $composite_db = array(
private static $composite_db = ]
'Street' => 'Varchar(200)',
'Suburb' => 'Varchar(100)',
'City' => 'Varchar(100)',
'Country' => 'Varchar(100)'
);
];
public function scaffoldFormField($title = null)
{
@ -958,9 +941,10 @@ type will raise a PHP error.
Before:
```php
function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) {
function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null)
{
$locale = Translatable::get_current_locale();
if(!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhere()))) {
if(!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhere()))) {
$qry = sprintf('"Locale" = \'%s\'', Convert::raw2sql($locale));
$query->addWhere($qry);
}
@ -974,9 +958,9 @@ public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
{
$locale = Translatable::get_current_locale();
if (!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhereParameterised($parameters)))) {
$query->addWhere(array(
$query->addWhere([
'"Locale"' => $locale
));
]);
}
}
```
@ -1085,9 +1069,9 @@ if it only has versioning without staging.
*/
class MyStagedModel extends DataObject
{
private staic $extensions = array(
private staic $extensions = [
"SilverStripe\\ORM\\Versioning\\Versioned('StagedVersioned')"
);
];
}
/**
@ -1095,9 +1079,9 @@ class MyStagedModel extends DataObject
*/
class MyVersionedModel extends DataObject
{
private static $extensions = array(
private static $extensions = [
"SilverStripe\\ORM\\Versioning\\Versioned('Versioned')"
);
];
}
```
@ -1147,18 +1131,20 @@ An exception to this is any classes which once had the `SS_` prefix, which will
Before:
```
class MyObject extends DataObject {
private static $db = array(
```php
class MyObject extends DataObject
{
private static $db = [
'Number' => 'Int',
'Time' => 'SS_Datetime'
);
];
/**
* @param Int $val
* @return Varchar
*/
public function TextNumber() {
public function TextNumber()
{
return new Varchar('TextNumber', 'Number is ' . $this->Number);
}
}
@ -1172,10 +1158,10 @@ use SilverStripe\ORM\FieldType\DBVarchar;
class MyObject extends DataObject
{
private static $db = array(
private static $db = [
'Number' => 'Int',
'Time' => 'Datetime'
);
];
/**
* @param Int $val
@ -1215,12 +1201,15 @@ specific functions.
#### Upgrading custom Authenticators
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:
```yaml
SilverStripe\Security\Authenticator;
authenticators:
- MyVendor\MyModule\MyAuthenticator
```
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:
```yaml
SilverStripe\Security\Authenticator:
default_authenticator: SilverStripe\Security\MemberAuthenticator
@ -1257,60 +1246,46 @@ This also allowed us to remove SilverStripe's `Cache` API and use dependency inj
Caches should be retrieved through `Injector` instead of `Cache::factory()`,
and have a slightly different API (e.g. `set()` instead of `save()`).
Before:
```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');
:::php
$cache = Cache::factory('myCache');
// create a new item by trying to get it from the cache
$myValue = $cache->load('myCacheKey');
// set a value and save it via the adapter
$cache->save(1234, 'myCacheKey');
// retrieve the cache item
if (!$cache->load('myCacheKey')) {
// ... item does not exists in the cache
}
// Remove a cache key
$cache->remove('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
+}
After:
:::php
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->get('myCacheKey');
// set a value and save it via the adapter
$cache->set('myCacheKey', 1234);
// retrieve the cache item
if (!$cache->has('myCacheKey')) {
// ... item does not exists in the cache
}
$cache->delete('myCacheKey');
// Remove a cache key
-$cache->remove('myCacheKey');
+$cache->delete('myCacheKey');
```
With the necessary minimal config in `_config/mycache.yml`
:::yml
---
Name: mycache
---
SilverStripe\Core\Injector\Injector:
Psr\SimpleCache\CacheInterface.myCache:
factory: SilverStripe\Core\Cache\CacheFactory
constructor:
namespace: 'mycache'
```yaml
---
Name: mycache
---
SilverStripe\Core\Injector\Injector:
Psr\SimpleCache\CacheInterface.myCache:
factory: SilverStripe\Core\Cache\CacheFactory
constructor:
namespace: 'mycache'
```
##### Configuration Changes
@ -1320,36 +1295,37 @@ See our ["Caching" docs](/developer-guides/performance/caching) for more details
Before (`mysite/_config.php`):
:::php
Cache::add_backend(
'primary_memcached',
'Memcached',
array(
'servers' => array(
'host' => 'localhost',
'port' => 11211,
)
)
);
Cache::pick_backend('primary_memcached', 'any', 10);
```php
Cache::add_backend(
'primary_memcached',
'Memcached',
[
'servers' => [
'host' => 'localhost',
'port' => 11211,
]
]
);
Cache::pick_backend('primary_memcached', 'any', 10);
```
After (`mysite/_config/config.yml`):
:::yml
---
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
```yaml
---
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
```
## <a name="api-changes"></a>API Changes