diff --git a/docs/en/changelogs/3.0.0.md b/docs/en/changelogs/3.0.0.md index f085af833..0f3237478 100644 --- a/docs/en/changelogs/3.0.0.md +++ b/docs/en/changelogs/3.0.0.md @@ -2,43 +2,89 @@ ## Overview ## - * New template engine - * New CMS interface design - * Image/Link insertion moved into a modal dialog instead of a sidebar +### CMS + + * New CMS interface design more geared towards complex content solutions + * List view for pages (sortable and filterable) + * More powerful media and link insertion (including auto-embedding of external sources) * Batch actions on site tree moved to an "Edit Tree" view - * "Add pages" dropdown now an "Add new" button which goes to a more descriptive page - * Renaming of sapphire to SilverStripe framework - * FormField classes now have their own HTML templates - * Allow usage of SilverStripe framework without the "cms" module + * "Add pages" shows a dedicated interface with more info about the page type * CMS JavaScript moved to [jQuery.entwine](https://github.com/hafriedlander/jquery.entwine) * CMS stylesheets are generated by SCSS to provide more flexible and robust styling +### Framework + + * Renaming of "sapphire" to SilverStripe "framework" + * Allow usage of SilverStripe framework without the "cms" module + * New template engine with more powerful syntax + * New ORM layer with expressive and fluent syntax + * New GridField component to replace ComplexTableField + * FormField classes now have their own HTML templates + * Moved functionality to modules: Widget, RestfulServer, SapphireSoapServer, Translatable, IPRestrictions, PageComment, HomepageForDomain + ## Upgrading ## -### Overview +### Common Upgrade Tasks - * Folders: `sapphire/` moved to `framework/`, replace with `FRAMEWORK_DIR` (in PHP) or `$ModulePath(framework)` (in templates). Be sure to update `.htaccess` or `web.config` ([more](#sapphire-rename)) - * Templates: `<% control %>` replaced by `<% loop %>` and `<% with %>` ([more](/reference/templates-upgrading-guide#control)) - * `DataObjectSet` is replaced by `DataList`; beware that `DataList->remove()` will delete an entry from the database ([more](#deprecated-classes)) - * `ComplexTableField` is replaced by `GridField`, which is similar to the `DataObjectManager` extension. - * `Director::redirect()` and `Director::redirectBack()` deprecated ([more] (#director-static-functions-deprecated-director-redirect-and-director-redirectback-in-particular) - * Changes in ORM, DataObject::get() deprecated ([more](#new-orm-datalist)) - * `DataObjectDecorator::extraStatics` deprecated ([more](#extensions)) - * Backend tab paths are shortened: `Root.Content.Main` becomes `Root.Main` ([more](#tab-paths)) + * Rename foder from `sapphire/`to `framework/`, replace own paths with `FRAMEWORK_DIR` (in PHP) or `$ModulePath(framework)` (in templates). Update paths in `.htaccess` or `web.config` ([more](#sapphire-rename)) + * Replace `<% control %>` in your templates with `<% loop %>` and `<% with %>` ([more](/reference/templates-upgrading-guide#control)) + * Replace `DataObjectSet` with `DataList` or `ArrayList` ([more](#deprecated-classes)) + * Rewrite `ComplexTableField` and `DataObjectManager` instances to `GridField` + * Rewrite `Director::redirect()` and `Director::redirectBack()` calls ([more] (#director-static-functions-deprecated-director-redirect-and-director-redirectback-in-particular) + * Use `::get()` rather than `DataObject::get()` ([more](#new-orm-datalist)) + * Use new syntax for `DataObjectDecorator::extraStatics` ([more](#extensions)) + * Change CMS tab paths from `Root.Content.Main` to `Root.Main`, move some field changes to new `SiteTree->getSettingsFields()` method ([more](#tab-paths)) + * Add new modules if using specific core features like Widget, RestfulServer, PageComment or Translatable ### sapphire renamed to framework {#sapphire-rename} -`sapphire` has been renamed to `framework`. - -Please ensure the framework now resides in the new folder when upgrading. - -Here's a list of steps to check: +The `sapphire` module has been renamed to `framework`. Please ensure the framework now resides in the new folder when upgrading. Here's a list of steps to check: * Remove your existing `sapphire` directory, and replace with `framework` from the new SilverStripe 3.0 package * Rename references of `sapphire` to `framework` in `.htaccess`, `web.config` and `/usr/bin/sake` (the last is only necessary if you use `sake`) * Find and replace any references to `sapphire` in your custom code to `framework`. In your PHP code, you can use the constant `FRAMEWORK_DIR`, which points to the framework directory, and in the templates you can use `$ModulePath(framework)` +### GridField: Replacement for TableListField and ComplexTableField [gridfield]### + +We have a new component for managing lists of objects: The `[GridField](/topics/grid-field)`. +It's a substantial rewrite of the features previously captured by `TableListField`, +`ComplexTableField`, `HasManyComplexTableField` and `ManyManyComplexTableField`. + +The legacy fields remain operational for now, although a switch to `GridField` is strongly encouraged, +for stability, interface and performance reasons. The `HasManyComplexTableField` and `ManyManyComplexTableField` +are no longer maintained, for those you do have to make the switch. +The `TableField` class will be deprecated soon, but we don't have an adequate replacement for it yet. + +Upgrade example: Record listing + + :::php + // before + $field = new TableListField('Companies', 'Company'); + $field->setPageSize(20); + // after + $field = new GridField('Companies', null, Company::get()); + $field->getConfig()->getComponentByType('GridFieldPaginator')->setItemsPerPage(20); + +Upgrade example: Record listing with view/edit interface + + :::php + // before + $field = new ComplexTableField($myController, 'Companies', 'Company'); + // after + $field = new GridField('Companies', null, Company::get(), GridFieldConfig_RecordEditor::create()); + + +Upgrade example: Relationship editing + + :::php + // before + $field = new HasManyComplexTableField($myController, 'MyRelation', 'MyRelationObject'); + // after + $field = new GridField('MyRelation', null, $myRecord->MyRelation(), GridFieldConfig_RelationEditor::create()); + +More information is available in the [GridField documentation](/topics/grid-field). + ### Object static functions replaced with new Config class {#new-config} Static functions for getting a static variable on the `Object` class have been deprecated, in favour of using the new `Config` class instead. @@ -63,21 +109,17 @@ Note the different options for the third parameter of `get()`: If you don't set an option, it will get all the values for the static, including inherited ones. This was previously known as `Object::combined_static()`. -### Director static functions deprecated, Director::redirect() and Director::redirectBack() in particular +### Director static functions deprecated (e.g. redirect() and redirectBack()) -`Director::redirect()` and `Director::redirectBack()` are now marked as deprecated. +`Director::redirect()` and `Director::redirectBack()` are now marked as deprecated. If you have a `Controller` instance and need to redirect, call `redirect()` or `redirectBack()` on the instance +instead, e.g. `$controller->redirect()` or `$controller->redirectBack()`. Most of the time, form action handler methods on a controller need only call `$this->redirect()` or `$this->redirectBack()`. -If you have a `Controller` instance and need to redirect, call `redirect()` or `redirectBack()` on the instance -instead, e.g. `$controller->redirect()` or `$controller->redirectBack()`. Most of the time, form action handler -methods on a controller need only call `$this->redirect()` or `$this->redirectBack()`. - -Use `Controller::curr()->redirect()` and `Controller::curr()->redirectBack()` if you need to redirect in contexts -where a controller might not be immediately available. +Use `Controller::curr()->redirect()` and `Controller::curr()->redirectBack()` if you need to redirect in contexts where a controller might not be immediately available. ### DataExtension and deprecated extraStatics on extension classes {#extensions} -`DataObjectDecorator` has been renamed to `DataExtension`. Any classes that extend `DataObjectDecorator` -should now extend `DataExtension` instead. +`DataObjectDecorator` has been renamed to `DataExtension`. Please extend this class in case you +have written your own extensions. `extraStatics()` on extensions is now deprecated. @@ -86,41 +128,36 @@ Instead of using `extraStatics()`, you can simply define static variables on you If you need custom logic, e.g. checking for a class before applying the statics on the extension, you can use `add_to_class()` as a replacement to `extraStatics()`. -Given the original `extraStatics` function: - - array( - 'Title' => 'Varchar' + :::php + class MyExtension extends Extension { + + // before + function extraStatics($class, $extensionClass) { + if($class == 'MyClass') { + return array( + 'db' => array( + 'Title' => 'Varchar' + ); ); - ); + } } + + // after + static $db = array( + 'Title' => 'Varchar' + ); + + // advanced syntax + static function add_to_class($class, $extensionClass, $args = null) { + if($class == 'MyClass') { + Config::inst()->update($class, 'db', array( + 'Title' => 'Varchar' + )); + } + parent::add_to_class($class, $extensionClass, $args); + } } -This would now become a static function `add_to_class`, and calls `update()` with an array -instead of returning it. It also needs to call `parent::add_to_class()`: - - update($class, 'db', array( - 'Title' => 'Varchar' - )); - } - parent::add_to_class($class, $extensionClass, $args); - } - -Alternatively, you can define statics on the extension directly, like this: - - 'Varchar' - ); ### New ORM: More flexible and expressive querying via `DataList` {#new-orm-datalist} @@ -163,6 +200,7 @@ for the presence of records, please call the count() method on the `DataList`: // after if(!DataObject::get('SiteTree', '"ParentID" = 5')->count()) echo "Page 5 has no children"; +Beware that `DataList->remove()` will delete an entry from the database. See the ["datamodel" documentation](../../topics/datamodel) for more details. ### New ORM: Changes to manipulation of SQL queries {#new-orm-sql-queries} @@ -204,23 +242,10 @@ The abstract `RelationList` class and its implementations `ManyManyList` and `Ha are replacing the `ComponentSet` API, which is only relevant if you have instanciated these manually. Relations are retrieved through the same way (e.g. `$myMember->Groups()`). -### Aggregate changes for partial caching in templates ### - -`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls -in PHP code, you should query with something like `Member::get()->max('LastEdited')`, that is, calling the aggregate on the `DataList` directly. -The same concept applies for replacing `RelationshipAggregate()`, just call the aggregate method on the relationship instead, -so something like `Member::get()->Groups()->max('LastEdited')`. - -For partial caching in templates, the syntax `<% cached Aggregate(Page).Max(LastEdited) %>` has been deprecated. The new syntax is similar, -except you use `List()` instead of `Aggregate()`, and the aggregate call `Max()` is now lowercase, as in `max()`. -An example of the new syntax is `<% cached List(Page).max(LastEdited) %>`. Check `DataList` class for more aggregate methods to use. - ### `SQLQuery` changes ### `SQLQuery` has been changed so direct access to internal properties `$from`, `$select`, `$orderby` is -now deprecated. - -Instead, there are now methods you can call which allow you to get and set SQL clauses instead. +now deprecated. Instead, there are now methods you can call which allow you to get and set SQL clauses instead. * `$from` getter is `getFrom()` and setters `setFrom()` and `addFrom()` * `$select` getter is `getSelect()` and setters `setSelect()` and `addSelect()` @@ -232,23 +257,19 @@ Instead, there are now methods you can call which allow you to get and set SQL c * `$distinct` getter is `getDistinct()` and setter `setDistinct()` * `$delete` getter is `getDelete()` and setter `setDelete()` * `$connective` getter is `getConnective()` and settter `setConnective()` - * `innerJoin()` has been renamed to `addInnerJoin()` * `leftJoin()` has been renamed to `addLeftJoin()` -### TinyMCE upgraded to 3.5 ### +### Aggregate changes for partial caching in templates ### -TinyMCE has been upgraded to version 3.5. +`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls +in PHP code, you should query with something like `Member::get()->max('LastEdited')`, that is, calling the aggregate on the `DataList` directly. +The same concept applies for replacing `RelationshipAggregate()`, just call the aggregate method on the relationship instead, +so something like `Member::get()->Groups()->max('LastEdited')`. -This change should be transparent to most people upgrading, but if you're using custom plugins for TinyMCE, -please ensure they are still working correctly with the new version. - -If you're upgrading from an SS 3.0 beta, TinyMCE HTML source editor and other popups might be blank. -This is caused by the TinyMCE compressor leaving stale cache files in the system temp folder from an earlier -version. - -To resolve this problem, simply delete the `{hash}.gz` files within your temp location (defined by `sys_get_temp_dir()` in PHP.) -These cache files will be regenerated next time the CMS is opened. +For partial caching in templates, the syntax `<% cached Aggregate(Page).Max(LastEdited) %>` has been deprecated. The new syntax is similar, +except you use `List()` instead of `Aggregate()`, and the aggregate call `Max()` is now lowercase, as in `max()`. +An example of the new syntax is `<% cached List(Page).max(LastEdited) %>`. Check `DataList` class for more aggregate methods to use. ### InnoDB driver for existing and new tables on MySQL (instead of MyISAM) [innodb]### @@ -270,12 +291,9 @@ Note: MySQL has made InnoDB the default engine in its [5.5 release](http://dev.m ### Convert::json2array() changes [raw2json]### -Convert JSON functions have been changed to use built-in json PHP functions `json_decode()` and `json_encode()` - +Convert JSON functions have been changed to use built-in json PHP functions `json_decode()` and `json_encode()`. Because `json_decode()` will convert nested JSON structures to arrays as well, this has changed the way it worked, -as before nested structures would be converted to an object instead. - -So, given the following JSON input to `Convert::json2array()`: +as before nested structures would be converted to an object instead. So, given the following JSON input to `Convert::json2array()`: {"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}} @@ -299,47 +317,6 @@ Now in SilverStripe 3.x, nested structures are arrays: ) ) - -### GridField: Replacement for TableListField and ComplexTableField [gridfield]### - -We have a new component for managing lists of objects: The `[GridField](/topics/grid-field)`. -It's a substantial rewrite of the features previously captured by `TableListField`, -`ComplexTableField`, `HasManyComplexTableField` and `ManyManyComplexTableField`. - -The legacy fields remain operational for now, although a switch to `GridField` is strongly encouraged, -for stability, interface and performance reasons. The `HasManyComplexTableField` and `ManyManyComplexTableField` -are no longer maintained, for those you do have to make the switch. -The `TableField` class will be deprecated soon, but we don't have an adequate replacement for it yet. - -Upgrade example: Record listing - - :::php - // before - $field = new TableListField('Companies', 'Company'); - $field->setPageSize(20); - // after - $field = new GridField('Companies', null, Company::get()); - $field->getConfig()->getComponentByType('GridFieldPaginator')->setItemsPerPage(20); - -Upgrade example: Record listing with view/edit interface - - :::php - // before - $field = new ComplexTableField($myController, 'Companies', 'Company'); - // after - $field = new GridField('Companies', null, Company::get(), GridFieldConfig_RecordEditor::create()); - - -Upgrade example: Relationship editing - - :::php - // before - $field = new HasManyComplexTableField($myController, 'MyRelation', 'MyRelationObject'); - // after - $field = new GridField('MyRelation', null, $myRecord->MyRelation(), GridFieldConfig_RelationEditor::create()); - -More information is available in the [GridField documentation](/topics/grid-field). - ### New template engine [templates]### The template engine has been completely rewritten, and although it is generally backward compatible, there are new features @@ -373,6 +350,18 @@ The page tree moved from a bespoke tree library to [JSTree](http://jstree.com), which required changes to markup of the tree and its JavaScript architecture. This includes changes to `TreeDropdownField` and `TreeMultiSelectField`. +### TinyMCE upgraded to 3.5 ### + +TinyMCE has been upgraded to version 3.5. + +This change should be transparent to most people upgrading, but if you're using custom plugins for TinyMCE, +please ensure they are still working correctly with the new version. + +If you're upgrading from an SS 3.0 beta, TinyMCE HTML source editor and other popups might be blank. +This is caused by the TinyMCE compressor leaving stale cache files in the system temp folder from an earlier +version. To resolve this problem, simply delete the `{hash}.gz` files within your temp location (defined by `sys_get_temp_dir()` in PHP.) +These cache files will be regenerated next time the CMS is opened. + ### Settings-related fields move from SiteTree->getCMSFields() to new SiteTree->getSettingsFields() [getcmsfields]### The fields and tabs are now split into two separate forms, which required a structural @@ -491,10 +480,9 @@ Please use the appropriate setters on the form field instance instead. ### EmailField now uses type "email" instead of type "text" {#email-form-field} EmailField now uses "email" for the `type` attribute, which integrates better with HTML5 features like -form validation in the browser. - -If you want to change this back to "text", use `setAttribute()` when constructing the field: +form validation in the browser. If you want to change this back to "text", use `setAttribute()` when constructing the field: + :::php $field = new EmailField('Email'); $field->setAttribute('type', 'text'); @@ -502,7 +490,6 @@ If you want to change this back to "text", use `setAttribute()` when constructin In order to make the SilverStripe framework useable without the `cms` module, we've moved some files around. - CMS base functionality which is not directly related to content pages (`SiteTree`) has been moved from the `cms` module into a new "sub-module" located in `framework/admin`. This includes generic management interfaces like "Files & Images" (`AssetAdmin`),