Merge pull request #7082 from open-sausages/pulls/4.0/diffs-in-changelog

Consistent 4.0 changelog docs formatting
This commit is contained in:
Ingo Schommer 2017-06-30 13:20:56 +12:00 committed by GitHub
commit afab2b04d8

View File

@ -193,36 +193,40 @@ For example, if you have the below `_ss_environment.php` file, your `.env` would
`_ss_environment.php`: `_ss_environment.php`:
:::php ```php
<?php <?php
// Environment // Environment
define('SS_ENVIRONMENT_TYPE', 'dev'); define('SS_ENVIRONMENT_TYPE', 'dev');
define('SS_DEFAULT_ADMIN_USERNAME', 'admin'); define('SS_DEFAULT_ADMIN_USERNAME', 'admin');
define('SS_DEFAULT_ADMIN_PASSWORD', 'password'); define('SS_DEFAULT_ADMIN_PASSWORD', 'password');
$_FILE_TO_URL_MAPPING[__DIR__] = 'http://localhost'; $_FILE_TO_URL_MAPPING[__DIR__] = 'http://localhost';
// Database
define('SS_DATABASE_CHOOSE_NAME', true); // Database
define('SS_DATABASE_CLASS', 'MySQLDatabase'); define('SS_DATABASE_CHOOSE_NAME', true);
define('SS_DATABASE_USERNAME', 'root') define('SS_DATABASE_CLASS', 'MySQLDatabase');
define('SS_DATABASE_PASSWORD', ''); define('SS_DATABASE_USERNAME', 'root')
define('SS_DATABASE_SERVER', '127.0.0.1'); define('SS_DATABASE_PASSWORD', '');
define('SS_DATABASE_SERVER', '127.0.0.1');
```
`.env`: `.env`:
## Environment ```
SS_ENVIRONMENT_TYPE="dev" ## Environment
SS_DEFAULT_ADMIN_USERNAME="admin" SS_ENVIRONMENT_TYPE="dev"
SS_DEFAULT_ADMIN_PASSWORD="password" SS_DEFAULT_ADMIN_USERNAME="admin"
SS_BASE_URL="http://localhost/" SS_DEFAULT_ADMIN_PASSWORD="password"
SS_BASE_URL="http://localhost/"
### Database ### Database
SS_DATABASE_CHOOSE_NAME="true" SS_DATABASE_CHOOSE_NAME="true"
SS_DATABASE_CLASS="MySQLDatabase" SS_DATABASE_CLASS="MySQLDatabase"
SS_DATABASE_USERNAME="root" SS_DATABASE_USERNAME="root"
SS_DATABASE_PASSWORD="" SS_DATABASE_PASSWORD=""
SS_DATABASE_SERVER="127.0.0.1" 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 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 Upgrade subclasses
:::php ```diff
// old -class MyClass extends Object
class MyClass extends Object {} -{
// new -}
class MyClass { +class MyClass
use Extensible; +{
use Injectable; + use Extensible;
use Configurable; + use Injectable;
+ use Configurable;
public function __construct() { +
// Only needed if using Extensible trait + public function __construct()
$this->constructExtensions(); + {
} + // Only needed if using Extensible trait
} + $this->constructExtensions();
+ }
+}
```
References to $this->class References to $this->class
```diff
-$obj->class
+get_class($obj);
:::php -$this->class;
// old +static::class;
$obj->class ```
$this->class;
// new
get_class($obj);
static::class;
Upgrade parse_class_spec() Upgrade parse_class_spec()
```diff
:::php -$spec = Object::parse_class_spec($spec);
// old +$spec = ClassInfo::parse_class_spec($spec);
$spec = Object::parse_class_spec($spec); ```
// new
$spec = ClassInfo::parse_class_spec($spec);
Upgrade create_from_string() Upgrade create_from_string()
:::php ```diff
// old -$obj = Object::create_from_string('Varchar(100)');
$obj = Object::create_from_string('Varchar(100)'); +$obj = Injector::inst()->create('Varchar(100)');
// new ```
$obj = Injector::inst()->create('Varchar(100)');
Extensions Extensions
```diff
:::php -Object::add_extension('File', 'Versioned');
// old +File::add_extension(Versioned::class);
Object::add_extension('File', 'Versioned'); +DataObject::add_extension(File::class, Versioned::class); // alternate
$has = Object::has_extension('File', 'Versioned');
$extensions = Object::get_extensions('File'); -$has = Object::has_extension('File', 'Versioned');
// new +$has = File::has_extension(Versioned::class);
File::add_extension(Versioned::class); +$has = DataObject::has_extension(File::class, Versioned::class); // alternate
$has = File::has_extension(Versioned::class)
$extensions = File::get_extensions(); -$extensions = Object::get_extensions('File');
+$extensions = File::get_extensions();
// new (alternate form) +$extensions = DataObject::get_extensions(File::class); // alternate
// 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);
#### Upgrade references to Session object #### Upgrade references to Session object
Session object is no longer statically accessible via `Session::inst()`. Instead, Session Session object is no longer statically accessible via `Session::inst()`. Instead, Session
is a member of the current request. is a member of the current request.
Before: ```diff
-public function httpSubmission($data, $form, $request)
:::php -{
public function httpSubmission($data, $form, $request) { - Session::set('loggedIn', null);
Session::set('loggedIn', null); -}
} +public function httpSubmission($data, $form, $request)
+{
+ $request->getSession()->set('loggedIn', null);
After: +}
```
:::php
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. 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: Before:
```php ```php
class MyObject extends ViewableData { class MyObject extends ViewableData
public function getSomeHTML { {
public function getSomeHTML
{
$title = Convert::raw2xml($this->Title); $title = Convert::raw2xml($this->Title);
return "<h1>{$title}</h1>"; 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 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. 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
{
:::php public function getCMSFields()
class MyClass extends DataObject { {
public function getCMSFields() { return new FieldList(
return new FieldList( new UploadField('Files')
new UploadField('Files') );
);
}
} }
}
```
4.x code After:
```php
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FileHandleField;
:::php class MyClass extends DataObject
use SilverStripe\ORM\DataObject; {
use SilverStripe\Forms\FieldList; public function getCMSFields()
use SilverStripe\Forms\FileHandleField; {
return FieldList::create(
class MyClass extends DataObject { Injector::inst()->create(FileHandleField::class, 'Files')
public function getCMSFields() { );
return FieldList::create(
Injector::inst()->create(FileHandleField::class, 'Files')
);
}
} }
}
```
#### Upgrade code that uses i18n #### 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. including both plurals and cross-module localisations.
:::php ```php
class MyObject extends DataObject, implements i18nEntityProvider class MyObject extends DataObject, implements i18nEntityProvider
{
public function provideI18nEntities()
{ {
public function provideI18nEntities() return [
{ 'MyObject.SINGULAR_NAME' => 'object',
return [ 'MyObject.PLURAL_NAME' => 'objects',
'MyObject.SINGULAR_NAME' => 'object', 'MyObject.PLURALS' => [
'MyObject.PLURAL_NAME' => 'objects', 'one' => 'An object',
'MyObject.PLURALS' => [ 'other' => '{count} objects',
'one' => 'An object', ],
'other' => '{count} objects', 'AnotherSection.DESCRIPTION' => [
], 'default' => 'This is the description for this section',
'AnotherSection.DESCRIPTION' => [ 'module' => 'extendedmodule',
'default' => 'This is the description for this section', ],
'module' => 'extendedmodule', ];
],
];
}
} }
}
```
In YML format this will be expressed as the below: 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`: `mymodule/lang/en.yml`:
:::yaml ```yaml
en: en:
MyObject: MyObject:
SINGULAR_NAME: 'object' SINGULAR_NAME: 'object'
PLURAL_NAME: 'objects' PLURAL_NAME: 'objects'
PLURALS: PLURALS:
one: 'An object', one: 'An object',
other: '{count} objects' other: '{count} objects'
```
`extendedmodule/lang/en.yml`: `extendedmodule/lang/en.yml`:
:::yaml ```yaml
en: en:
AnotherSection: AnotherSection:
DESCRIPTION: 'This is the description for this section' DESCRIPTION: 'This is the description for this section'
```
Usage of these pluralised strings is through the existing _t() method, Usage of these pluralised strings is through the existing _t() method,
and require a `|` pipe-delimeter with a {count} argument. and require a `|` pipe-delimeter with a {count} argument.
:::php ```php
public function pluralise($count) public function pluralise($count)
{ {
return _t('MyObject.PLURALS', 'An object|{count} objects', [ 'count' => $count ]); return _t('MyObject.PLURALS', 'An object|{count} objects', [ 'count' => $count ]);
} }
```
In templates this can also be invoked as below: In templates this can also be invoked as below:
:::ss ```ss
<%t MyObject.PLURALS 'An item|{count} items' count=$Count %> <%t MyObject.PLURALS 'An item|{count} items' count=$Count %>
```
#### Removed Member.DateFormat and Member.TimeFormat database settings #### 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. Note that this will not allow you to utilise certain file versioning features in 4.0.
``` ```yaml
SilverStripe\Filesystem\Flysystem\FlysystemAssetStore: SilverStripe\Filesystem\Flysystem\FlysystemAssetStore:
legacy_paths: true 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 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. is intended to upload images for manipulation.
Before: ```diff
-if($file instanceof Image) {
```php - $upload = new UploadField();
if($file instanceof Image) { - $upload->setAllowedFileCategories('image');
$upload = new UploadField(); -}
$upload->setAllowedFileCategories('image'); +if ($file->getIsImage()) {
} + $upload = new UploadField();
``` + $upload->setAllowedFileCategories('image/supported');
+}
After:
```php
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 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')`. an `Image` datatype, or refer to `DBFile('image/supported')`.
E.g.
```php ```php
class MyObject extends DataObject class MyObject extends DataObject
{ {
private static $has_one = array( private static $has_one = [
"ImageObject" => "Image" "ImageObject" => "Image"
); ];
private static $db = array( private static $db = [
"ImageField" => "DBFile('image/supported')" "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. 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. You would need to upgrade your code as below.
Before: ```diff
-function importTempFile($tmp)
-{
```php - copy($tmp, ASSETS_PATH . '/imported/' . basename($tmp));
function importTempFile($tmp) { - $file = new File();
copy($tmp, ASSETS_PATH . '/imported/' . basename($tmp)); - $file->setFilename('assets/imported/'.basename($tmp));
$file = new File(); - $file->write();
$file->setFilename('assets/imported/'.basename($tmp)); -}
$file->write(); +public function importTempFile($tmp)
} +{
``` + Versioned::reading_stage('Stage');
+ $file = new File();
After: + $file->setFromLocalFile($tmp, 'imported/' . basename($tmp));
+ $file->write();
```php + $file->doPublish();
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 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. The below describes the minimum amount of effort required to implement a composite DB field.
```php ```php
<?php
class MyAddressField extends DBComposite class MyAddressField extends DBComposite
{ {
private static $composite_db = array( private static $composite_db = ]
'Street' => 'Varchar(200)', 'Street' => 'Varchar(200)',
'Suburb' => 'Varchar(100)', 'Suburb' => 'Varchar(100)',
'City' => 'Varchar(100)', 'City' => 'Varchar(100)',
'Country' => 'Varchar(100)' 'Country' => 'Varchar(100)'
); ];
public function scaffoldFormField($title = null) public function scaffoldFormField($title = null)
{ {
@ -958,9 +941,10 @@ type will raise a PHP error.
Before: Before:
```php ```php
function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) { function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null)
{
$locale = Translatable::get_current_locale(); $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)); $qry = sprintf('"Locale" = \'%s\'', Convert::raw2sql($locale));
$query->addWhere($qry); $query->addWhere($qry);
} }
@ -974,9 +958,9 @@ public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
{ {
$locale = Translatable::get_current_locale(); $locale = Translatable::get_current_locale();
if (!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhereParameterised($parameters)))) { if (!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhereParameterised($parameters)))) {
$query->addWhere(array( $query->addWhere([
'"Locale"' => $locale '"Locale"' => $locale
)); ]);
} }
} }
``` ```
@ -1085,9 +1069,9 @@ if it only has versioning without staging.
*/ */
class MyStagedModel extends DataObject class MyStagedModel extends DataObject
{ {
private staic $extensions = array( private staic $extensions = [
"SilverStripe\\ORM\\Versioning\\Versioned('StagedVersioned')" "SilverStripe\\ORM\\Versioning\\Versioned('StagedVersioned')"
); ];
} }
/** /**
@ -1095,9 +1079,9 @@ class MyStagedModel extends DataObject
*/ */
class MyVersionedModel extends DataObject class MyVersionedModel extends DataObject
{ {
private static $extensions = array( private static $extensions = [
"SilverStripe\\ORM\\Versioning\\Versioned('Versioned')" "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: Before:
``` ```php
class MyObject extends DataObject { class MyObject extends DataObject
private static $db = array( {
private static $db = [
'Number' => 'Int', 'Number' => 'Int',
'Time' => 'SS_Datetime' 'Time' => 'SS_Datetime'
); ];
/** /**
* @param Int $val * @param Int $val
* @return Varchar * @return Varchar
*/ */
public function TextNumber() { public function TextNumber()
{
return new Varchar('TextNumber', 'Number is ' . $this->Number); return new Varchar('TextNumber', 'Number is ' . $this->Number);
} }
} }
@ -1172,10 +1158,10 @@ use SilverStripe\ORM\FieldType\DBVarchar;
class MyObject extends DataObject class MyObject extends DataObject
{ {
private static $db = array( private static $db = [
'Number' => 'Int', 'Number' => 'Int',
'Time' => 'Datetime' 'Time' => 'Datetime'
); ];
/** /**
* @param Int $val * @param Int $val
@ -1215,12 +1201,15 @@ specific functions.
#### Upgrading custom Authenticators #### 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: 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 ```yaml
SilverStripe\Security\Authenticator; SilverStripe\Security\Authenticator;
authenticators: authenticators:
- MyVendor\MyModule\MyAuthenticator - 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: 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 ```yaml
SilverStripe\Security\Authenticator: SilverStripe\Security\Authenticator:
default_authenticator: SilverStripe\Security\MemberAuthenticator 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()`, Caches should be retrieved through `Injector` instead of `Cache::factory()`,
and have a slightly different API (e.g. `set()` instead of `save()`). 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 // set a value and save it via the adapter
$cache = Cache::factory('myCache'); -$cache->save(1234, 'myCacheKey');
+$cache->set('myCacheKey', 1234);
// 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');
// 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: // Remove a cache key
-$cache->remove('myCacheKey');
+$cache->delete('myCacheKey');
:::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');
With the necessary minimal config in `_config/mycache.yml` With the necessary minimal config in `_config/mycache.yml`
:::yml ```yaml
--- ---
Name: mycache Name: mycache
--- ---
SilverStripe\Core\Injector\Injector: SilverStripe\Core\Injector\Injector:
Psr\SimpleCache\CacheInterface.myCache: Psr\SimpleCache\CacheInterface.myCache:
factory: SilverStripe\Core\Cache\CacheFactory factory: SilverStripe\Core\Cache\CacheFactory
constructor: constructor:
namespace: 'mycache' namespace: 'mycache'
```
##### Configuration Changes ##### Configuration Changes
@ -1320,36 +1295,37 @@ See our ["Caching" docs](/developer-guides/performance/caching) for more details
Before (`mysite/_config.php`): Before (`mysite/_config.php`):
:::php ```php
Cache::add_backend( Cache::add_backend(
'primary_memcached', 'primary_memcached',
'Memcached', 'Memcached',
array( [
'servers' => array( 'servers' => [
'host' => 'localhost', 'host' => 'localhost',
'port' => 11211, 'port' => 11211,
) ]
) ]
); );
Cache::pick_backend('primary_memcached', 'any', 10); Cache::pick_backend('primary_memcached', 'any', 10);
```
After (`mysite/_config/config.yml`): After (`mysite/_config/config.yml`):
:::yml ```yaml
--- ---
After: After:
- '#corecache' - '#corecache'
--- ---
SilverStripe\Core\Injector\Injector: SilverStripe\Core\Injector\Injector:
MemcachedClient: MemcachedClient:
class: 'Memcached' class: 'Memcached'
calls: calls:
- [ addServer, [ 'localhost', 11211 ] ] - [ addServer, [ 'localhost', 11211 ] ]
SilverStripe\Core\Cache\CacheFactory: SilverStripe\Core\Cache\CacheFactory:
class: 'SilverStripe\Core\Cache\MemcachedCacheFactory' class: 'SilverStripe\Core\Cache\MemcachedCacheFactory'
constructor: constructor:
client: '%$MemcachedClient client: '%$MemcachedClient
```
## <a name="api-changes"></a>API Changes ## <a name="api-changes"></a>API Changes