diff --git a/docs/en/04_Changelogs/4.0.0.md b/docs/en/04_Changelogs/4.0.0.md index 790cea7cd..8a3b71a99 100644 --- a/docs/en/04_Changelogs/4.0.0.md +++ b/docs/en/04_Changelogs/4.0.0.md @@ -64,10 +64,11 @@ as a standard first point of upgrade. Nearly all core PHP classes have been namespaced. For example, `DataObject` is now called `SilverStripe\ORM\DataObject`. 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: - composer global require silverstripe/upgrader - cd ~/Project/Root - ~/.composer/vendor/bin/upgrade-code upgrade ./mysite --write - +``` +composer global require silverstripe/upgrader +cd ~/Project/Root +~/.composer/vendor/bin/upgrade-code upgrade ./mysite --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. @@ -176,34 +177,33 @@ explicitly cast for that field. You can resolve this in your model by adding an explicit cast to HTML for those fields. - Before: - - :::php - class MyObject extends ViewableData { - public function getSomeHTML { - $title = Convert::raw2xml($this->Title); - return "

{$title}

"; - } +```php +class MyObject extends ViewableData { + public function getSomeHTML { + $title = Convert::raw2xml($this->Title); + return "

{$title}

"; } - +} +``` After: +```php +class MyObject extends ViewableData +{ + private static $casting = [ + 'SomeHTML' => 'HTMLText' + ]; - :::php - class MyObject extends ViewableData { - private static $casting = [ - 'SomeHTML' => 'HTMLText' - ]; - - public function getSomeHTML { - $title = Convert::raw2xml($this->Title); - return "

{$title}

"; - } + public function getSomeHTML + { + $title = Convert::raw2xml($this->Title); + return "

{$title}

"; } - +} +``` If you need to encode a field (such as HTMLText) for use in html attributes, use `.ATT` instead, or if used in an actual XML file use `.CDATA` (see [template casting](/developer_guides/templates/casting)). @@ -225,9 +225,10 @@ 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 +``` +SilverStripe\Filesystem\Flysystem\FlysystemAssetStore: + legacy_paths: true +``` See our ["File Management" guide](/developer_guides/files/file_management) for more information. @@ -241,10 +242,10 @@ this task is run manually during an explicit migration process, as this process large amounts of memory and run for an extended time. - :::yaml - File: - migrate_legacy_file: true - +```yaml +File: + migrate_legacy_file: true +``` This task will also support migration of existing File DataObjects to file versioning. Any pre-existing File DataObjects will be automatically published to the live stage, to ensure @@ -273,40 +274,38 @@ is intended to upload images for manipulation. Before: - - :::php - if($file instanceof Image) { - $upload = new UploadField(); - $upload->setAllowedFileCategories('image'); - } - +```php +if($file instanceof Image) { + $upload = new UploadField(); + $upload->setAllowedFileCategories('image'); +} +``` After: - - :::php - if($file->getIsImage()) { - $upload = new UploadField(); - $upload->setAllowedFileCategories('image/supported'); - } - +```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 an `Image` datatype, or refer to `DBFile('image/supported')`. E.g. - - :::php - class MyObject extends DataObject { - private static $has_one = array( - "ImageObject" => "Image" - ); - private static $db = array( - "ImageField" => "DBFile('image/supported')" - ); - } - +```php +class MyObject extends DataObject +{ + private static $has_one = array( + "ImageObject" => "Image" + ); + private static $db = array( + "ImageField" => "DBFile('image/supported')" + ); +} +``` #### Upgrading code that writes to `File` dataobjects, or writes files to the 'assets' folder @@ -321,27 +320,27 @@ 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(); - } - +```php +function importTempFile($tmp) { + copy($tmp, ASSETS_PATH . '/imported/' . basename($tmp)); + $file = new File(); + $file->setFilename('assets/imported/'.basename($tmp)); + $file->write(); +} +``` After: - - :::php - function importTempFile($tmp) { - Versioned::reading_stage('Stage'); - $file = new File(); - $file->setFromLocalFile($tmp, 'imported/'.basename($tmp)); - $file->write(); - $file->doPublish(); - } - +```php +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 used to generate the 'filename' value. This is because there is no longer an assumption that files are @@ -356,12 +355,11 @@ There are other important considerations in working with File dataobjects which to the public site. You will need to make sure to invoke `->doPublish()` on any File DataObject you wish visitors to be able to see. -You can disable File versioning by adding the following to your _config.php - - - :::php - File::remove_extension('Versioned'); +You can disable File versioning by adding the following to your `_config.php` +```php +File::remove_extension('Versioned'); +``` #### Upgrading code performs custom image manipulations @@ -375,48 +373,52 @@ For instance, code which sizes images to a fixed width should be updated as belo Before: - - :::php - // in MyImageExtension.php - class MyImageExtension extends DataExtension { - public function GalleryThumbnail($height) { - return $this->getFormattedImage('GalleryThumbnail', $height); - } - public function generateGalleryThumbnail(Image_Backend $backend, $height) { - return $backend->paddedResize(300, $height); - } +```php +// in MyImageExtension.php +class MyImageExtension extends DataExtension +{ + public function GalleryThumbnail($height) + { + return $this->getFormattedImage('GalleryThumbnail', $height); } - // in _config.php - Image::add_extension('MyImageExtension'); + public function generateGalleryThumbnail(Image_Backend $backend, $height) + { + return $backend->paddedResize(300, $height); + } +} +// in _config.php +Image::add_extension('MyImageExtension'); +``` Now image manipulations are implemented with a single method via a callback generator: +```php +// in MyImageExtension.php +class MyImageExtension extends Extension +{ + public function GalleryThumbnail($height) + { + // Generates the manipulation key + $variant = $this->owner->variantName(__FUNCTION__, $height); - :::php - // in MyImageExtension.php - class MyImageExtension extends Extension { - public function GalleryThumbnail($height) { - // 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); - }); - } + // 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); + }); } +} - // in _config.php - File::add_extension('MyImageExtension'); - SilverStripe\Filesystem\Storage\DBFile::add_extension('MyImageExtension'); - +// in _config.php +File::add_extension('MyImageExtension'); +\SilverStripe\Filesystem\Storage\DBFile::add_extension('MyImageExtension'); +``` There are a few differences in this new API: -* The extension is no longer specific to DataObjects, so it uses the generic 'Extension' class instead of 'DataExtension' +* The extension is no longer specific to DataObjects, so it uses the generic `Extension` class instead of `DataExtension` * 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 @@ -432,22 +434,23 @@ 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 - 'Varchar(200)', + 'Suburb' => 'Varchar(100)', + 'City' => 'Varchar(100)', + 'Country' => 'Varchar(100)' + ); - private static $composite_db = array( - 'Street' => 'Varchar(200)', - 'Suburb' => 'Varchar(100)', - 'City' => 'Varchar(100)', - 'Country' => 'Varchar(100)' - ); - - public function scaffoldFormField($title = null) { - new AddressFormField($this->getName(), $title); - } + public function scaffoldFormField($title = null) + { + new AddressFormField($this->getName(), $title); } - +} +``` #### Upgrading code that references `DataObject::database_fields` or `DataObject::db` @@ -483,26 +486,46 @@ fix a table name, to prevent it being changed (for instance, when applying a nam the `table_name` config can be applied to any DataObject class. - :::php - namespace SilverStripe\BannerManager; - class BannerImage extends \DataObject { - private static $table_name = 'BannerImage'; - } +```php +namespace SilverStripe\BannerManager; +use SilverStripe\ORM\DataObject; + +class BannerImage extends DataObject +{ + private static $table_name = 'BannerImage'; +} +``` In order to ensure you are using the correct table for any class a new [api:DataObjectSchema] service is available to manage these mappings (see [versioned documentation](/developer_guides/model/data_model_and_orm)). - :::php - public function countDuplicates($model, $fieldToCheck) { - $table = DataObject::getSchema()->tableForField($model, $field); - $query = new SQLSelect(); - $query->setFrom("\"{$table}\""); - $query->setWhere(["\"{$table}\".\"{$field}\"" => $model->$fieldToCheck]); - return $query->count(); - } +```php +public function countDuplicates($model, $fieldToCheck) +{ + $table = DataObject::getSchema()->tableForField($model, $field); + $query = new SQLSelect(); + $query->setFrom("\"{$table}\""); + $query->setWhere(["\"{$table}\".\"{$field}\"" => $model->$fieldToCheck]); + return $query->count(); +} +``` +#### 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'; +} +``` #### Upgrade implementations of augmentSQL @@ -511,27 +534,29 @@ type will raise a PHP error. Before: - :::php - function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) { - $locale = Translatable::get_current_locale(); - if(!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhere()))) { - $qry = sprintf('"Locale" = \'%s\'', Convert::raw2sql($locale)); - $query->addWhere($qry); - } +```php +function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) { + $locale = Translatable::get_current_locale(); + if(!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhere()))) { + $qry = sprintf('"Locale" = \'%s\'', Convert::raw2sql($locale)); + $query->addWhere($qry); } +} +``` After: - :::php - function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null) { - $locale = Translatable::get_current_locale(); - if(!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhereParameterised($parameters)))) { - $query->addWhere(array( - '"Locale"' => $locale - )); - } +```php +public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null) +{ + $locale = Translatable::get_current_locale(); + if (!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhereParameterised($parameters)))) { + $query->addWhere(array( + '"Locale"' => $locale + )); } - +} +``` #### Upgrade code that modifies the behaviour of ErrorPage @@ -553,29 +578,31 @@ In case that user code must customise this filename, such as for extensions whic for any error page, the extension point `updateErrorFilename` can be used. This extension point should also be used to replace any `alternateFilepathForErrorcode` used. - - :::php - class MyErrorPageExtension extends SiteTreeExtension { - public function updateErrorFilename(&$name, &$statuscode) { - if($this->owner->exists()) { - $locale = $this->Locale; - } else { - $locale = Translatable::get_current_locale(); - } - $name = "error-{$statusCode}-{$locale}.html"; +```php +class MyErrorPageExtension extends SiteTreeExtension +{ + public function updateErrorFilename(&$name, &$statuscode) + { + if ($this->owner->exists()) { + $locale = $this->Locale; + } else { + $locale = Translatable::get_current_locale(); } + $name = "error-{$statusCode}-{$locale}.html"; } +} +``` - - :::yaml - ErrorPage: - extensions: - - MyErrorPageExtension +```yml +ErrorPage: + extensions: + - MyErrorPageExtension +``` #### Upgrading asset web.config, .htaccess, or other server configuration Server configuration files for `/assets` are no longer static, and are regenerated via a set of -standard silverstripe templates on flush. These templates include: +standard SilverStripe templates on flush. These templates include: * `Assets_HTAccess.ss`: Template for public permissions on the Apache server. * `Assets_WebConfig.ss`: Template for public permissions on the IIS server. @@ -605,11 +632,12 @@ of items to disable. #### Upgrading TinyMCE to 4.0 - 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. +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: - 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: * Strikethrough * Styles dropdown * Block quotes @@ -625,25 +653,26 @@ 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: - :::php - $editor = HtmlEditorConfig::get('cms'); - $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'] - ]); +```php +$editor = HtmlEditorConfig::get('cms'); +$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'] +]); +``` For more information on available options and plugins please refer to the -[tinymce documentation](https://www.tinymce.com/docs/configure/) +[TinyMCE documentation](https://www.tinymce.com/docs/configure/) #### Upgrading DataObjects with the `Versioned` extension @@ -654,26 +683,27 @@ Rather than declaring the list of stages a model has, the constructor for `Versi 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. +```php +/** + * This model has staging and versioning. Stages will be "Stage" and "Live" + */ +class MyStagedModel extends DataObject +{ + private staic $extensions = array( + "SilverStripe\\ORM\\Versioning\\Versioned('StagedVersioned')" + ); +} - :::php - /** - * This model has staging and versioning. Stages will be "Stage" and "Live" - */ - class MyStagedModel extends DataObject { - private staic $extensions = array( - "Versioned('StagedVersioned')" - ); - } - - /** - * 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 { - private static $extensions = array( - "Versioned('Versioned')" - ); - } - +/** + * 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 +{ + private static $extensions = array( + "SilverStripe\\ORM\\Versioning\\Versioned('Versioned')" + ); +} +``` Additionally, the following api methods have been added: @@ -721,41 +751,48 @@ An exception to this is any classes which once had the `SS_` prefix, which will Before: - class MyObject extends DataObject { - private static $db = array( - 'Number' => 'Int', - 'Time' => 'SS_Datetime' - ); +``` +class MyObject extends DataObject { + private static $db = array( + 'Number' => 'Int', + 'Time' => 'SS_Datetime' + ); - /** - * @param Int $val - * @return Varchar - */ - public function TextNumber() { - return new Varchar('TextNumber', 'Number is ' . $this->Number); - } - } + /** + * @param Int $val + * @return Varchar + */ + public function TextNumber() { + return new Varchar('TextNumber', 'Number is ' . $this->Number); + } +} +``` After: - use SilverStripe\ORM\FieldType\DBVarchar; +```php +use SilverStripe\ORM\DataObject; +use SilverStripe\ORM\FieldType\DBVarchar; - class MyObject extends DataObject { - private static $db = array( - 'Number' => 'Int', - 'Time' => 'Datetime' - ); +class MyObject extends DataObject +{ + private static $db = array( + 'Number' => 'Int', + 'Time' => 'Datetime' + ); - /** - * @param Int $val - * @return Varchar - */ - public function TextNumber() { - return new DBVarchar('TextNumber', 'Number is ' . $this->Number); - } - } + /** + * @param Int $val + * @return Varchar + */ + public function TextNumber() + { + return new DBVarchar('TextNumber', 'Number is ' . $this->Number); + } +} +``` -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. +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. #### Upgrading from deprecated RestfulService