Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Restructured 3.0 changelog
Moved some more important stuff up the page,
rewritten upgrading overview to be more task focused,
reduced excessive use of paragraphs to make the text more scannable.
  • Loading branch information
chillu committed Jul 4, 2012
1 parent 2b5214b commit de73db9
Showing 1 changed file with 123 additions and 136 deletions.
259 changes: 123 additions & 136 deletions docs/en/changelogs/3.0.0.md
Expand Up @@ -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

## Upgrading ##
### Framework

### Overview
* 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

* 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))
## Upgrading ##

### sapphire renamed to framework {#sapphire-rename}
### Common Upgrade Tasks

`sapphire` has been renamed to `framework`.
* 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 `<MyModel>::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

Please ensure the framework now resides in the new folder when upgrading.
### sapphire renamed to framework {#sapphire-rename}

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.
Expand All @@ -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.

Expand All @@ -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:

<?php
//...
function extraStatics($class, $extensionClass) {
if($class == 'MyClass') {
return array(
'db' => array(
'Title' => 'Varchar'
:::php
class MyExtension extends Extension {
// before
function extraStatics($class, $extensionClass) {
if($class == 'MyClass') {
return array(
'db' => array(
'Title' => 'Varchar'
);
);
);
}
}
}

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()`:
// after
static $db = array(
'Title' => 'Varchar'
);

<?php
//...
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);
// 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);
}
}

Alternatively, you can define statics on the extension directly, like this:

<?php
//...
static $db = array(
'Title' => 'Varchar'
);

### New ORM: More flexible and expressive querying via `DataList` {#new-orm-datalist}

Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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()`
Expand All @@ -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 ###

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.
### Aggregate changes for partial caching in templates ###

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.
`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')`.

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]###

Expand All @@ -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"}}

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -491,18 +480,16 @@ 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');

### Restructured files and folders [file-restructure]###

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`),
Expand Down

0 comments on commit de73db9

Please sign in to comment.