4.0.0-alpha1#
Overview#
Framework#
- Minimum PHP version raised to 5.5.0
- Minimum CMS browser requirement raised from Internet Explorer 8 to Internet Explorer 10
- Deprecate
SQLQueryin favourSQLSelect DataList::filterby null now internally generates "IS NULL" or "IS NOT NULL" conditions appropriately on queriesDataObjectconstructor now has an additional parameter, which must be included in subclasses.DataObject::database_fieldsnow returns all fields on that table.DataObject::dbnow returns composite fields.DataObject::ClassNamefield has been refactored into aDBClassNametype field.- Image manipulations have been moved into a new
[ImageManipulation](api:SilverStripe\Assets\ImageManipulation)trait. CMSFileAddControllerremoved.UploadField::setAllowedFileCategories('image')now excludes non-resizeable images. 'unresizeable_image' is can be used to validate these types.Image_BackendAPI now loads and saves fromAssetContainerinstances rather than local files.- The following File categories have been renamed: 'zip' to 'archive', 'doc' to 'document', and 'mov' to 'video'
File::updateLinksno longer takes urls as parameters. All file links are now identified either by theDataObject::IDin adata-fileidproperty, or via shortcodes. This is necessary because file urls are no longer able to identify assets.- Extension point
HtmlEditorField::processImagehas been removed, and moved toImage::regenerateImageHTML Upload::loadnow stores assets directly without saving into aFiledataobject.- Protected file storage is now a core Framework API. See [/developer_guides/files/file_security] for more information.
Object::useCustomClasshas been removed. You should use the config API with Injector instead.- Upgrade of TinyMCE to version 4.
Fileis 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 below for upgrade notes.- Removed
dev/tests/controller in favour of standardvendor/bin/phpunitcommand - Updated PHPUnit from 3.7 to 4.8 (upgrade notes).
Please remove any PHPUnit related
require_once()calls (e.g. inFeatureContextdefinitions of the behat-extension module). Runcomposer require --dev 'phpunit/phpunit:~4.8'on existing projects to pull in the new dependency. Object::invokeWithExtensionsnow has the same method signature asObject::extendand behaves the same way.CMSMainmodel actions have been changed:CMSBatchAction_DeleteandCMSMain::deleteare no longer deprecated.CMSBatchAction_DeleteFromLiveis removed.CMSMain.enabled_legacy_actionsconfig is removed.
DataObject::canhas new method signature with$contextparameter.SiteTree.alternatePreviewLinkis deprecated. UseupdatePreviewLinkinstead.Injectordependencies no longer automatically inherit from parent classes.
New API#
- New filesystem abstraction including new
DBFiledatabase field to hold file references. ShortcodeHandlerinterface to help generate standard handlers for HTML shortcodes in the editor.AssetNameGeneratorinterface, including aDefaultAssetNameGeneratorimplementation, which is used to generate renaming suggestions based on an original given filename in order to resolve file duplication issues.GeneratedAssetHandlerAPI now used to store and manage generated files (such as those used for error page cache or combined files).Requirements_MinifierAPI can be used to declare any new mechanism for minifying combined required files. By default this API is provided by theJSMinifierclass, but user code can substitute their own.AssetFieldformfield to provide anUploadFieldstyle uploader for the newDBFiledatabase field.AssetControlExtensionis applied by default to all DataObjects, in order to support the management of linked assets and file protection.ProtectedFileControllerclass is used to serve up protected assets.Objecthas been broken up into various traits, each of which can be added to other objects independently:ConfigurableProvides Config API helper methodsInjectableProvides Injector API helper methodsExtensibleAllows extensions to be applied
- 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) - Moved test database cleanup task from
sake dev/tests/cleanupdbtosake dev/tasks/CleanupTestDatabasesTask - Removed
TestRunnerandJSTestRunnerAPIs - Removed
PhpUnitWrapper,PhpUnitWrapper_3_4,PhpUnitWrapper_3_5,PhpUnitWrapper_Generic,SapphireTestSuiteAPIs - Removed
SapphireTest->skipTest, usemarkTestSkipped()in asetUp()method instead HtmlEditorConfigis now an abstract class, with a default implementationTinyMCEConfigfor the built in TinyMCE editor.HtmlEditorField::setEditorConfigmay now take an instance of aHtmlEditorConfigclass, as well as a standard config identifier name.- A lot of standard versioned API has been refactored from
SiteTreeintoVersionedextension. Now all versioned DataObjects havecanPublish(),canArchive(),canUnpublish(),doPublish(),doArchive()doUnpublish(),isPublished()andisonDraft()out of the box. However,do*()methods will no longer automatically checkcan*()permissions, and must be done by usercode before invocation. - GridField edit form now has improved support for versioned DataObjects, with basic publishing actions available when editing records.
VersionedAPI 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_stageis nowset_stagecurrent_stageis nowget_stagegetVersionedStagesis gone.get_live_stageis removed. Use theVersioned::LIVEconstant instead.getDefaultStageis removed. Use theVersioned::DRAFTconstant instead.$versionableExtensionsis nowprivate staticinstead ofprotected statichasStagesis added to check if an object has a given stage.stageTableis added to get the table for a given class and stage.
ChangeSetandChangeSetItemhave been added for batch publishing of versioned dataobjects.FormAction::setValidationExemptcan be used to turn on or off form validation for individual actions
Front-end build tooling for CMS interface#
- Management of CMS JavaScript dependencies via npm
- ES6 is now available in all core JavaScript files via Babel
- Bundling of core JavaScript via Browserify
- CMS build tasks managed by Gulp
For more details see the docs on working with client-side dependencies. Note that you don't need any of these tools for running Silverstripe or developing your own website. These improvements are mainly geared at CMS core development.
Added new front-end UI libraries#
- Added the following npm libraries:
- Added SilverStripeComponent base class for building React UIs
Compiling CSS#
Compass has been removed and CSS/sprite compilation is now handled with gulp (see Markup and Style Conventions).
Bootstrap CSS#
Bootstrap 4 Alpha.2 CSS is available in admin/css/bootstrap.
Changed paths of static assets#
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.
Care should also be taken when referencing images in these folders from your own stylesheets.
framework/javascript => framework/client/dist/
framework/javascript/lang => framework/client/lang/
framework/images => framework/client/dist/images/
framework/css => framework/client/dist/css/
framework/scss => framework/client/src/styles/
admin/javascript/ => admin/client/src/
admin/javascript/src/ => admin/client/src/legacy/ (mostly)
admin/javascript/lang/ => admin/client/lang/
admin/scss/ => admin/client/styles/legacy/
admin/css/ => admin/client/dist/css/
admin/css/screen.css => admin/client/dist/css/bundle.css
admin/images/ => admin/client/dist/images/
admin/images/sprites/src/ => admin/client/src/sprites/
admin/images/sprites/dist/ => admin/client/dist/sprites/
admin/font/ => admin/client/dist/font/
Deprecated classes/methods#
Core#
-
Added the following npm libraries:
- Page.js
-
Removed the following JavaScript libraries:
- History.js
-
debugmethodsquerystring argument has been removed from debugging.
ORM#
DataList::getRelationis removed, as it was mutable. UseDataList::applyRelationinstead, which is immutable.
ErrorPage#
ErrorPage.static_filepathconfig has been removed.ErrorPage::get_filepath_for_errorcodehas been removedErrorPage::alternateFilepathForErrorcodeextension point has been removed
See notes below on upgrading extensions to the ErrorPage class
Member#
MemberField 'RememberLoginToken' removed, replaced with 'RememberLoginHashes' has_many relationship
Assets and filesystem#
The following image manipulations previously deprecated has been removed:
Image::SetRatioSizesuperseded byFitImage::SetWidthsuperseded byScaleWidthImage::SetHeightsuperseded byScaleHeightImage::SetSizesuperseded byPadImage::PaddedImagesuperseded byPadImage::CroppedImagesuperseded byFillImage::AssetLibraryPreviewsuperseded byPreviewThumbnailImage::AssetLibraryThumbnailsuperseded byCMSThumbnail
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::deletedatabaseOnlyFile::link_shortcode_handlerrenamed tohandle_shortcodeFile::setParentIDFile::getFullPathFile::getRelativePathFile::Contentdatabase 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:
CleanImageManipulationCacheclassImage_CachedclassImage::regenerateFormattedImagesImage::getGeneratedImagesImage::deleteFormattedImagesAssetAdmin::deleteunusedthumbnailsAssetAdmin::getUnusedThumbnails
Many Folder methods have also been removed:
Folder::syncChildrenFolder::constructChildFolder::addUploadToFolder
The following filesystem synchronisation methods are also removed
Filesystem::syncAssetAdmin::doSync
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.
Requirements#
The following methods and properties on Requirements_Backend have been renamed:
Requirements_Backund::$combine_filesmade protected and renamed$combinedFilesRequirements_Backend::$combine_js_with_minmade protected and renamed$minifyCombinedFilesRequirements_Backend::$write_header_commentsmade protected and renamed$writeHeaderCommentRequirements_Backend::$write_js_to_bodymade protected and renamed to$writeJavascriptToBodyRequirements_Backend::$force_js_to_bottomrenamed to$forceJSToBottomget_combined_files_enabledrenamed togetCombinedFilesEnabledset_combined_files_enabledrenamed tosetCombinedFilesEnabledget_suffix_requirementsrenamed togetSuffixRequirementsset_suffix_requirementsrenamed tosetSuffixRequirementsget_custom_scriptsrenamed togetCustomScriptsunblock_allrenamed tounblockAllinclude_in_responserenamed toincludeInResponsecombine_filesrenamed tocombineFilesget_combine_filesrenamed togetCombinedFilesclear_combined_filesrenamed toclearCombinedFilesprocess_combined_filesrenamed toprocessCombinedFilesset_write_js_to_bodyrenamed tosetWriteJavascriptToBodyset_force_js_to_bottomrenamed tosetForceJSToBottom
New methods on Requirements are added to access these:
get_minify_combined_js_filesset_minify_combined_js_filesget_force_js_to_bottomget_write_js_to_body
Some methods on Requirements have had their method signatures changed:
includeInHTMLhas had the first parameter $template removed as it was previously deprecated.
And some methods on Requirements and Requirements_Backend have been removed as they are obsolete.
delete_combined_files(both classes)
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.
In addition, a new API for JavaScript files has been added to support front-end tools
such as browserify that pre-combine scripts. You can specify
a 'provides' option to the second parameter of Requirements::javascript to declare
included files.
For example:
Requirements::javascript('mysite/js/dist/bundle.js', ['provides' => [
'mysite/js/jquery.js'
'mysite/js/src/main.js',
'mysite/js/src/functions.js',
]]);
Upgrading#
Where your code once used SQLQuery you should now use SQLSelect in all cases, as SQLQuery has been removed.
See the 3.2.0 upgrading notes for details on how existing code should be upgraded.
New asset storage mechanism#
File system has been abstracted into an abstract interface. By default, the out of the box filesystem uses Flysystem 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.
SilverStripe\Filesystem\Flysystem\FlysystemAssetStore:
legacy_paths: true
See [/developer_guides/files/file_management] for more information on how the new system works.
Migrating file DataObject from 3.X to 4.0#
Since the structure of File dataobjects has changed, a new task MigrateFileTask has been added to assist
in migration of legacy files. Migration can be invoked by either this task, or can be configured to automatically
run during dev build by setting the File.migrate_legacy_file config to true. However, it's recommended that
this task is run manually during an explicit migration process, as this process could potentially consume
large amounts of memory and run for an extended time.
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 that previously visible assets remain visible to the public site.
If additional security or visibility rules should be applied to File dataobjects, then
make sure to correctly extend canView via extensions.
Upgrade code which acts on Image#
As all image-specific manipulations has been refactored from Image into an ImageManipulations trait, which
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.
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
is intended to upload images for manipulation.
Before:
if ($file instanceof Image) {
$upload = new UploadField();
$upload->setAllowedFileCategories('image');
}
After:
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').
For example:
namespace App\Model;
use SilverStripe\ORM\DataObject;
class MyObject extends DataObject
{
private static $has_one = [
"ImageObject" => "Image",
];
private static $db = [
"ImageField" => "DBFile('image/supported')",
];
}
Upgrading code that writes to File dataobjects, or writes files to the 'assets' folder#
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.
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.
Before:
function importTempFile($tmp)
{
copy($tmp, ASSETS_PATH . '/imported/' . basename($tmp));
$file = new File();
$file->setFilename('assets/imported/' . basename($tmp));
$file->write();
}
After:
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 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 between physical files and File DataObjects.
- Folder DataObjects are now purely logical DataObjects, and perform no actual filesystem folder creation on write.
- All Files are versioned, which means that by default, new File records will not be visible
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 file
use SilverStripe\Assets\File;
use SilverStripe\Versioned\Versioned;
File::remove_extension(Versioned::class);
Upgrading code performs custom image manipulations#
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:
// in MyImageExtension.php
namespace App\Extension;
use SilverStripe\Assets\Image_Backend;
use SilverStripe\ORM\DataExtension;
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);
}
}
// in _config.php
use App\Extension\MyImageExtension;
use SilverStripe\Assets\Image;
Image::add_extension(MyImageExtension::class);
Now image manipulations are implemented with a single method via a callback generator.
After:
// in MyImageExtension.php
namespace App\Extension;
use SilverStripe\Assets\Image_Backend;
use SilverStripe\Core\Extension;
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);
});
}
// ...
}
// in _config.php
use App\Extension\MyImageExtension;
use SilverStripe\Assets\File;
use SilverStripe\Filesystem\Storage\DBFile;
File::add_extension(MyImageExtension::class);
DBFile::add_extension(MyImageExtension::class);
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'
- This extension is added to both
DBFileandFile, 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
variantNameis 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
manipulateImageshould not be used in this case. A genericmanipulatemethod may be used, although the callback for this method both is given, and should return, anAssetStoreinstance and file tuple (Filename, Hash, and Variant) rather than an Image_Backend.
Upgrading code that uses composite db fields#
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.
The below describes the minimum amount of effort required to implement a composite DB field.
namespace App\ORM;
use App\Form\AddressFormField;
use SilverStripe\ORM\FieldType\DBComposite;
class MyAddressField extends DBComposite
{
private static $composite_db = [
'Street' => 'Varchar(200)',
'Suburb' => 'Varchar(100)',
'City' => 'Varchar(100)',
'Country' => 'Varchar(100)',
];
public function scaffoldFormField($title = null)
{
new AddressFormField($this->getName(), $title);
}
}
Upgrading code that references DataObject::database_fields or DataObject::db#
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
or class. For example Member::database_fields()
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
any child fields of these composites. This method can now take a second parameter $includesTable, which
when set to true (with a field name as the first parameter), will also include the table prefix in
Table.ClassName(args) format.
Update code that uses SQLQuery#
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 superseded 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.
Update implementations of augmentSQL#
Since this method now takes a SQLSelect as a first parameter, existing code referencing the deprecated SQLQuery
type will raise a PHP error.
For example:
Before:
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:
function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
{
$locale = Translatable::get_current_locale();
if (!preg_match('/("|\'|`)Locale("|\'|`)/', implode(' ', $query->getWhereParameterised($parameters)))) {
$query->addWhere([
'"Locale"' => $locale,
]);
}
}
Update code that modifies the behaviour of errorPage#
ErrorPage has been updated to use a configurable asset backend, similar to the AssetStore described above.
This replaces the ErrorPage.static_filepath config that was used to write local files.
As a result, error pages may be cached either to a local filesystem, or an external Flysystem store (which is configured via setting a new Flysystem backend with YAML).
ErrorPage::get_filepath_for_errorcode() has been removed, because the local path for a specific code is
no longer assumed. Instead you should use ErrorPage::get_content_for_errorcode which retrieves the
appropriate content for that error using one of the methods above.
In order to retrieve the actual filename (which is used to identify an error page regardless of base
path), you can use ErrorPage::get_error_filename() instead. Unlike the old get_filepath_for_errorcode
method, there is no $locale parameter.
In case that user code must customise this filename, such as for extensions which provide a locale value
for any error page, the extension point updateErrorFilename can be used. This extension point should
also be used to replace any alternateFilepathForErrorcode used.
For example:
namespace App\Extension;
// ...
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";
}
}
ErrorPage:
extensions:
- App\Extension\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:
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.
If upgrading from an existing installation, make sure to invoke ?flush=all at least once.
See [/developer_guides/files/file_security] for more information.
ListboxField is now multiple-only#
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.
GroupedDropdownField::setDisabled now only accepts a list of values#
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.
Upgrading requirements file paths#
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.
Core JavaScript files paths have changed, so if you're referencing these, you'll have to update your file paths. Files previously in admin/javascript are now located in admin/javascript/dist and files previously located in javascript are now locatied in javascript/dist.
If you're not doing this already, we suggest looking into a JavaScript bundler like Browserify, to combine JavaScript files. Silverstripe core is moving away from Requirements::combine_files in favour of Browserify as of 4.0 and Requirements::combine_files is being considered for deprecation in future versions.
Upgrading TinyMCE to 4.0#
Please see the TinyMCE upgrading guide 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:
- Strikethrough
- Styles dropdown
- Block quotes
- Horizontal Rule
- Undo / Redo
- Cut / Paste as word
- Select all
- Fullscreen
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:
$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
Upgrading DataObject models with the Versioned extension#
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.
For instance:
namespace App\Model;
// ...
/**
* This model has staging and versioning. Stages will be "Stage" and "Live"
*/
class MyStagedModel extends DataObject
{
private staic $extensions = [
"Versioned('StagedVersioned')",
];
}
namespace App\Model;
// ...
/**
* 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 = [
"Versioned('Versioned')",
];
}
Additionally, the following API methods have been added:
Versioned::publishRecursivePublishes this object, and all owned objectsVersioned::publishSinglePublishes this object, but not owned objectsVersioned::copyVersionToStageReplaces the oldpublishmethod.
These methods are deprecated:
Versioned::publishReplaced byVersioned::copyVersionToStageVersioned::doPublishReplaced byVersioned::publishRecursive
Implementation of ownership API#
In order to support the recursive publishing of dataobjects, a new API has been developed to allow developers to declare dependencies between objects. See the versioned documentation for more information.
By default all versioned dataobjects will automatically publish objects that they own.
ChangeSet batch publishing#
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.
New [image] shortcode in HTMLText fields#
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,
and existing <img> will continue to work.
Upgrading references to dBField and subclasses#
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.
For example:
namespace App\Model;
// ...
class MyObject extends DataObject
{
private static $db = [
'Number' => 'Int',
'Time' => 'SS_Datetime',
];
/**
* @param Int $val
* @return Varchar
*/
public function TextNumber()
{
return new Varchar('TextNumber', 'Number is ' . $this->Number);
}
}
Will become:
namespace App\Model;
use SilverStripe\Model\FieldType\DBVarchar;
// ...
class MyObject extends DataObject
{
private static $db = [
'Number' => 'Int',
'Time' => 'Datetime',
];
/**
* @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.
Change log#
Security#
- 2016-05-03 70480f5 HtmlEditorField_Toolbar#viewfile not whitelisting URLs (Damian Mooyman) - See ss-2015-027
API changes#
- 2016-05-10 7f03b88 Add empty campaign layout (Damian Mooyman)
- 2016-05-09 8b94dd8 Add CSRF to Campaign delete (Damian Mooyman)
- 2016-05-09 3edbfd9 Implement breadcrumbs via controllable state (Damian Mooyman)
- 2016-05-03 8ce3d90 Injector dependencies no longer inherit from parent classes automatically (Damian Mooyman)
- 2016-05-03 8d2cc91 Include asset-admin module in installer (Damian Mooyman)
- 2016-05-02 8b1146b Implement campaign item edit button (Damian Mooyman)
- 2016-05-02 6948267 LeftAndMain::menu_title can be overridden (#5423) (Damian Mooyman)
- 2016-05-02 0d4c71f Filtering on invalid relation is no longer a silent error (Damian Mooyman)
- 2016-05-01 46f69b0 set menu title without editing transifex masters (Damian Mooyman)
- 2016-04-27 72fcfbf Campaign preview for images (Damian Mooyman)
- 2016-04-27 1aa5492 Cleanup SilverStripeNavigator and CMSPreview (Damian Mooyman)
- 2016-04-27 4be5e7c Implement basic preview behaviour (Damian Mooyman)
- 2016-04-25 daf5385 in behaviour to flysystem reporting for root folders (Damian Mooyman)
- 2016-04-22 241cdfe Allow actions to declare they are exempt from validation themselves (Hamish Friedlander)
- 2016-04-20 e463fcc redux-logger respects ss environment (Damian Mooyman)
- 2016-04-19 43b0052 Remove artifact datalist overrides from UnsavedRelationList (Damian Mooyman)
- 2016-04-19 19de22f Moved frontend assets into admin/client/ (Ingo Schommer)
- 2016-04-19 e2afcd0 Implement back end for saving forms via react (Damian Mooyman)
- 2016-04-18 dbd17bd Remove routing from silverstripe-component (Damian Mooyman)
- 2016-04-18 2e90035 Campaign publish button (Damian Mooyman)
- 2016-04-12 31247a6 Replace baked-in and modified Chosen 0.9.8 with npm'ed in Chosen 1.5.1 (Hamish Friedlander)
- 2016-04-11 5900893 Implement campaign list view (Damian Mooyman)
- 2016-04-11 2d16d69 Use base data class for ChangeSetItem#ObjectClass, not just ClassName (Hamish Friedlander)
- 2016-04-07 05973ce Add i18n pluralisation (Damian Mooyman)
- 2016-04-05 db6251a Update to use new travis-artifacts (Damian Mooyman)
- 2016-04-01 3c2b531 Update Versioned methods (Damian Mooyman)
- 2016-04-01 716baa6 Support renamed Versioned API (Damian Mooyman)
- 2016-03-30 87ee436 Implement ChangeSets for batch publishing (Damian Mooyman)
- 2016-03-30 64b7a84 SapphireTest::logInWithPermission now supports multiple permissions (Damian Mooyman)
- 2016-03-30 29c5eff Add $context method to DataObject::can for consistency with canCreate() (Damian Mooyman)
- 2016-03-30 501b2f1 CMSMenu::get_cms_classes() is now sorted (Damian Mooyman)
- 2016-03-28 d22ad70 Support new DataObject::can() signature (Damian Mooyman)
- 2016-03-27 b2e4e96 Remove deprecated caching behaviour from ViewableData (closes #4063) (Loz Calver)
- 2016-03-23 8abede1 Add SS_Database::withTransaction for nice enclosed transactions (Damian Mooyman)
- 2016-03-22 094745e Formally support custom ownership relations (Damian Mooyman)
- 2016-03-21 2d56ea2 Move ss buttons plugin out of thirdparty (Damian Mooyman)
- 2016-03-17 4cc7b08 Update to use new Versioned API (Damian Mooyman)
- 2016-03-09 067d44a Update link tracking for image shortcodes (Damian Mooyman)
- 2016-03-08 8ae794e TinyMCE Image shortcodes (Ingo Schommer)
- 2016-03-07 14d74f7 Refactor for removal of CMSForm class (Damian Mooyman)
- 2016-03-07 634e86f Include File.ParentID in fulltext search results (Damian Mooyman)
- 2016-03-02 0848aca Massive refactor of Versioned (Damian Mooyman)
- 2016-02-26 8366d22 Replace old assets/.htaccess with better default (Damian Mooyman)
- 2016-02-25 b196d33 Ownership API (Damian Mooyman)
- 2016-02-25 c275c21 Extensible::invokeWithExtension has same method signature as Extensible::extend (Damian Mooyman)
- 2016-02-21 de6db9f Mark image tracking as owned (Damian Mooyman)
- 2016-02-16 99394a8 Remove references to class aliases; Use correct classname (Damian Mooyman)
- 2016-02-12 f20ad43 Update TinyMCE to 4.x (Damian Mooyman)
- 2016-01-27 829135a remove Object::useCustomClass (Damian Mooyman)
- 2016-01-26 1c907dd Support versioned File management (Damian Mooyman)
- 2016-01-26 510c556 File has Versioned extension (Damian Mooyman)
- 2016-01-25 9662d93 remove obsolete class loaders from test listeners (Damian Mooyman)
- 2016-01-25 17ee318 VirtualPage permissions now can be set independently of the mirrored page (Damian Mooyman)
- 2016-01-21 e77389d Standardise SS_List::map() implementation (Damian Mooyman)
- 2016-01-21 c976470 Refactor out Page default classname hack (Damian Mooyman)
- 2016-01-21 5138bf1 Refactor out Page default classname hack (Damian Mooyman)
- 2016-01-14 8e1ae55 Enable single javascript files to declare that they include other files (Damian Mooyman)
- 2015-12-21 99de74d Add isDisabledValue to SelectField (Damian Mooyman)
- 2015-12-13 62f183d before/afterExtend now support parameters passed by reference (Damian Mooyman)
- 2015-12-09 037467b Asset Access Control implementation (Damian Mooyman)
- 2015-11-30 c13b5d9 Enable advanced configuration options for requirements combined files (Damian Mooyman)
- 2015-11-26 c50dc06 Update ErrorPage to use FilesystemGeneratedAssetHandler (Damian Mooyman)
- 2015-11-26 ce28259 Replace CacheGeneratedAssetHandler with FlysystemGeneratedAssetHandler (Damian Mooyman)
- 2015-11-25 3842971 refactor LeftAndMain_Menu.ss into individually overridable components (Damian Mooyman)
- 2015-11-09 369f3dd Remove deprecated ListboxField::setMultiple() (Damian Mooyman)
- 2015-11-09 0b89747 Remove deprecated setMultiple() (Damian Mooyman)
- 2015-10-29 641c262 Enable linear-only restriction for DataList::applyRelation (Damian Mooyman)
- 2015-10-23 e17a49f Restore JS Minification (Damian Mooyman)
- 2015-10-19 d1ea74e Implement AssetField to edit DBFile fields (Damian Mooyman)
- 2015-10-14 2bd9d00 Remove filesystem sync (Damian Mooyman)
- 2015-10-13 227e2ba Move ErrorPage to new generated files API (Damian Mooyman)
- 2015-10-12 f9892c6 Generated files API (Damian Mooyman)
- 2015-09-23 f26c220 Support trait loading (Damian Mooyman)
- 2015-09-16 2b1e5ee Enable DataList::sort to support composite field names (similar to filter) (Damian Mooyman)
- 2015-09-15 be23989 Refactor of File / Folder to use DBFile (Damian Mooyman)
- 2015-09-14 051c69b (minor): Freshening up SS_Log API documentation and removed $extras param which was not being used anyway. (Patrick Nelson)
- 2015-09-10 10dece6 Consolidate DataObject db methods (Damian Mooyman)
- 2015-09-04 ee639de showqueries=1 now shows parameters (Damian Mooyman)
- 2015-09-04 9872fbe Refactor CompositeDBField into an abstract class (Damian Mooyman)
- 2015-09-03 ac27836 Implementation of RFC-1 Asset Abstraction (Damian Mooyman)
- 2015-08-30 aeccb8b Move DBField subclasses into SilverStripe\Model\FieldType namespace (Sam Minnee)
- 2015-08-28 f6fe142 Making ArrayList (and others) more consistent with DataList (Daniel Hensby)
- 2015-07-31 3e7eecf Remove SQLQuery (Damian Mooyman)
- 2015-07-23 1b8d295 Shift to Monolog for error reporting and logging (Sam Minnee)
- 2015-07-16 40cc567 Force resampling by default (Jonathon Menz)
- 2015-07-16 d1af214 Removed custom dev/tests/ execution (Ingo Schommer)
- 2015-07-16 a16588a Removed JSTestRunner (Ingo Schommer)
- 2015-06-17 4aa84f3 make DataObject::validate public (Damian Mooyman)
- 2015-06-17 55170a0 make DataObject::validate public (Damian Mooyman)
- 2015-06-12 513f019 default behaviour for Director::getAbsoluteUrl (Damian Mooyman)
- 2015-06-08 3bc76e6 Formalise new DataObject::canCreate argument (Damian Mooyman)
- 2015-06-08 e9d4863 Formalise new additional arguments to DataObject::canCreate, DataExtension::augmentSQL, and DataObject::extendedCan (Damian Mooyman)
- 2015-05-19 922d02f Enable filters to perform 'IS NULL' or 'IS NOT NULL' checks (Damian Mooyman)
- 2015-03-25 7f5608c Public visibility on DataQuery::selectField (Uncle Cheese)
- 2015-02-13 bdb1a95 Cleanup and refactor of select fields (Damian Mooyman)
Features and enhancements#
- 2016-04-11 21a1065 Add createEndpointFetcher to backend (Sam Minnee)
- 2016-04-03 a17c5cb Expose silverstripe-backend for modules to access. (Sam Minnee)
- 2016-03-27 1e7281a Add onBeforeRender() hook to GridField (Loz Calver)
- 2016-03-15 2923787 consistent file icons (Jonathon Menz)
- 2016-03-02 ae31619 styles for main nav (Paul Clarke)
- 2016-02-23 375bbf9 and fix for issue #3186 (Tyler Kidd)
- 2016-02-22 01c8d38 Passing $tmpFile to extension. (Taras Yemtsov)
- 2016-02-04 bab1f23 Cross device "Remember Me" feature (Jean-Fabien Barrois)
- 2015-12-22 c9ba0e4 Add ViewableData::setFailover() to refresh detected methods when changing failover (Loz Calver)
- 2015-08-27 52ca089 Ensure php7 builds pass. (Sam Minnee)
- 2015-07-29 a1f7dca Add βcallsβ section to Injector configs. (Sam Minnee)
- 2015-07-27 ebc3900 Replace DebugViewβs writeX() functions with renderX() functions. (Sam Minnee)
- 2015-05-27 223466a Configurable file version prefix (Jonathon Menz)
- 2015-05-01 9f91b47 Update SS_ConfigStaticManifest to use Reflection (micmania1)
Bugfixes#
- 2016-05-12 a61d0a2 Persistent Loading... indicator when no campaigns yet in admin (Hamish Friedlander)
- 2016-05-12 7393995 preview in Asset Admin (Hamish Friedlander)
- 2016-05-10 d1df67d SQLSelect count methods now cast to int (fixes #5498) (Loz Calver)
- 2016-05-09 1263bf8 Not being able to save when viewing page settings (Hamish Friedlander)
- 2016-05-09 2af63a8 add_i18n_javascript calls not being updated after JS move (Hamish Friedlander)
- 2016-05-09 b2786c2 add_i18n_javascript calls not being updated after JS move (Hamish Friedlander)
- 2016-05-05 b4cd617 Renaming to HTMLEditorConfig. (Frank Mullenger)
- 2016-05-05 cc7a2ae Add framework/admin tests (#118) (Daniel Hensby)
- 2016-05-02 f88d708 Fix GridFieldAddExistingAutocompleter and GridFieldExportButton (Damian Mooyman)
- 2016-05-02 096f30e Fix GridFieldAddExistingAutocompleter (Damian Mooyman)
- 2016-04-26 43f2680 Fix missing return in ReadonlyField (Damian Mooyman)
- 2016-04-22 9a4b93a Fix baseurl in IE missing leading / (Damian Mooyman)
- 2016-04-21 fa80753 Fix routing tests (Damian Mooyman)
- 2016-04-21 fa5b8b8 Fix error when modals are displayed (Damian Mooyman)
- 2016-04-21 b4f466f Correct framework/module dependencies for cms (Damian Mooyman)
- 2016-04-21 ae268ae #5363 Add .JSON option for templates (Robbie Averill)
- 2016-04-21 b2e8fd9 Fix form schema to use correct ID values (Damian Mooyman)
- 2016-04-19 0bd6273 Fix issue with Requirements mangling custom scripts (#5337) (Damian Mooyman)
- 2016-04-13 7e37abe Fix chosen dropdown on settings being cropped (Damian Mooyman)
- 2016-04-07 0aec89d for #5279 Addressing only a few PSR-2 items in one file, but primarily targeting Director::is_https() and invalid URL's. (Patrick Nelson)
- 2016-04-05 5a86f42 Fix error when using search bar (Damian Mooyman)
- 2016-04-03 640691f fix missing language on non-global configs (Damian Mooyman)
- 2016-03-31 d8d005d move test file to correct folder and fix class_exists (Damian Mooyman)
- 2016-03-31 e8a68c4 Prevent live manifest loading files from nested test directories (Damian Mooyman)
- 2016-03-30 c69e55c Fix issue with SapphireTest::assertDOSEquals incorrectly passing on empty set (Damian Mooyman)
- 2016-03-29 7907d20 changing all cases of filesize spelling to file size (Tim Kung)
- 2016-03-22 46b35ec Changes to support php7 and new DBFields (Sam Minnee)
- 2016-03-17 96c586b only output $CleartextPassword if it has a value (Christopher Darling)
- 2016-03-13 7769f03 Remove duplicate extension hook (Damian Mooyman)
- 2016-03-09 e2a377e Fix CleanupTestDatabaseTask (Damian Mooyman)
- 2016-03-09 3673a5e Inserting a 'Download a file' without selecting an image (Mike Cochrane)
- 2016-03-09 0b81bbe attempt to access https iframe from http interface (Mike Cochrane)
- 2016-03-09 a3ee9ec avoid javascript error when preview is https (Mike Cochrane)
- 2016-03-09 70062eb 'Settings' fields being overwritten by 'Content' fields (Mike Cochrane)
- 2016-03-06 3d99ed2 Better filtering of versionable tables during SQL augmentation (Damian Mooyman)
- 2016-03-03 4b5bd2d cleaner can* methods for Member (Nicolaas)
- 2016-03-01 3317d34 Prevent fatal errors during test failure halt tests (Damian Mooyman)
- 2016-02-24 beba0f2 Fix behat tests for asset abstraction (Damian Mooyman)
- 2016-02-23 0ee1564 Fix deprecated API usage in DataFormatter API and DataObjectTest (Damian Mooyman)
- 2016-02-12 a34f17f for #5028: Ensure empty YML configs don't break when merging them in (i.e. make sure it's traversable before foreach'ing over it). (Patrick Nelson)
- 2016-01-26 b1b403c Borders on CMS Actions (Daniel Hensby)
- 2016-01-26 c5fc9dd CMS actions alignment (Daniel Hensby)
- 2016-01-21 8872ed5 Fix broken travis yml (Damian Mooyman)
- 2016-01-21 6cebffd Fix SSViewerTest not restoring old requirements (Damian Mooyman)
- 2016-01-12 a7110be OptionsetField uses aria-required (Torleif West)
- 2016-01-11 122784b OptionsetField input has required #4901 (torleif)
- 2016-01-11 288c8a8 OptionsetField returns valid HTML #4901 (torleif)
- 2016-01-06 bf6337c Changes needed to respond to whitespace changes. (Sam Minnee)
- 2016-01-06 4aa5053 Fixes needed to adapt to whitespace changes. (Sam Minnee)
- 2015-12-22 24660af Parameters passed to includes overwrite all scopes (fixes #2617) (Loz Calver)
- 2015-12-22 b6627a2 Change Requirements::include_in_response() to not add empty (Jacob Buck)
- 2015-12-15 3188873 Fix incorrect error page handling (Damian Mooyman)
- 2015-12-02 ed76b3f Fix yml and behat (Damian Mooyman)
- 2015-12-02 387eb22 Fix CI (Damian Mooyman)
- 2015-11-04 fb43e59 Setting hide_ancestor=true causes a random page type to be hidden (Loz Calver)
- 2015-10-22 fe3d23f Fix GeneratedAssetHandler crashing on expired resources (Damian Mooyman)
- 2015-10-19 d7dcb41 Remove tab - invalid YAML (Loz Calver)
- 2015-10-15 27a8afe Fix regressions in fulltextsearch (Damian Mooyman)
- 2015-10-14 d884c85 Fix file link tracking for new asset abstraction (Damian Mooyman)
- 2015-09-28 1f632a1 Replace direct reference to $_REQUEST['url'] with request object getter (Damian Mooyman)
- 2015-09-28 8e3f549 Fix regressions in CMS from db field changes (Damian Mooyman)
- 2015-09-04 fa8702f Fix reference to missing Debug::loadErrorHandlers() (Damian Mooyman)
- 2015-08-28 f5af0c8 Donβt use SplFixedArray in PHP 7. (Sam Minnee)
- 2015-08-27 8518fc1 Clarify PHP7-incompatible call styles. (Sam Minnee)
- 2015-08-27 083799e Minimal data-model changes to support PHP7. (Sam Minnee)
- 2015-08-27 12a83d7 Removed PHP4 syntax from Diff.php (Sam Minnee)
- 2015-08-27 680b19a Correct PHP4-style constructors in SimpleTest. (Sam Minnee)
- 2015-08-14 e13aebc for #4502 Prevents JSON.parse() from scrambling sorted results from server-side. (Patrick Nelson)
- 2015-08-04 e94c0fa extraClass() method to match parent method (Florian Thoma)
- 2015-04-28 cadc02b for #4129: Ensure belongsToComponent() and hasManyComponent() methods return null instead of false, to be consistent with other relation component methods. (Patrick Nelson)
- 2015-04-28 512b3db Fix SiteTree / SiteConfig permissions (Ingo Schommer)
- 2015-03-10 622ad54 Fix yaml generation to conform to version 1.1, accepted by transifex (Damian Mooyman)
- 2014-12-15 1f7e627 How to folder on forms (Cam Findlay)
- 2014-12-10 6ff6c6f Removed multifile thirdparty library which isn't used any more in ss. (micmania1)
- 2014-12-08 ddd8330 Feedback to name the fields section to "field types" to make it clearer what the section is about. (Cam Findlay)
- 2014-12-08 1f181a6 use GFMD code blocks to fix code formatting consistency. (Cam Findlay)
- 2014-12-04 00e029f check for suite existence in endCurrentTest (Will Morgan)
- 2014-10-29 61a9b2a GridFieldPaginator now prevents viewing pages with no results (fixes #3192) (Loz Calver)