mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Cleanup 3.2 changelog for release
This commit is contained in:
parent
78a3f703f2
commit
4d37e21bc6
@ -37,7 +37,7 @@ explicitly logging in or by invoking the "remember me" functionality.
|
|||||||
|
|
||||||
DB::query(sprintf(
|
DB::query(sprintf(
|
||||||
'UPDATE "Member" SET "LastVisited" = %s, "NumVisit" = "NumVisit" + 1 WHERE "ID" = %d',
|
'UPDATE "Member" SET "LastVisited" = %s, "NumVisit" = "NumVisit" + 1 WHERE "ID" = %d',
|
||||||
DB::getConn()->now(),
|
DB::get_conn()->now(),
|
||||||
$this->owner->ID
|
$this->owner->ID
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ come from user input.
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
$records = DB::preparedQuery('SELECT * FROM "MyClass" WHERE "ID" = ?', array(3));
|
$records = DB::prepared_query('SELECT * FROM "MyClass" WHERE "ID" = ?', array(3));
|
||||||
$records = MyClass::get()->where(array('"ID" = ?' => 3));
|
$records = MyClass::get()->where(array('"ID" = ?' => 3));
|
||||||
$records = MyClass::get()->where(array('"ID"' => 3));
|
$records = MyClass::get()->where(array('"ID"' => 3));
|
||||||
$records = DataObject::get_by_id('MyClass', 3);
|
$records = DataObject::get_by_id('MyClass', 3);
|
||||||
@ -48,7 +48,7 @@ Parameterised updates and inserts are also supported, but the syntax is a little
|
|||||||
))
|
))
|
||||||
->assignSQL('"Created"', 'NOW()')
|
->assignSQL('"Created"', 'NOW()')
|
||||||
->execute();
|
->execute();
|
||||||
DB::preparedQuery(
|
DB::prepared_query(
|
||||||
'INSERT INTO "MyClass" ("Name", "Position", "Age", "Created") VALUES(?, ?, GREATEST(0,?,?), NOW())'
|
'INSERT INTO "MyClass" ("Name", "Position", "Age", "Created") VALUES(?, ?, GREATEST(0,?,?), NOW())'
|
||||||
array('Daniel', 'Accountant', 24, 28)
|
array('Daniel', 'Accountant', 24, 28)
|
||||||
);
|
);
|
||||||
@ -100,7 +100,7 @@ and [datamodel](/developer_guides/model) for ways to parameterise, cast, and con
|
|||||||
|
|
||||||
* `SQLQuery`
|
* `SQLQuery`
|
||||||
* `DB::query()`
|
* `DB::query()`
|
||||||
* `DB::preparedQuery()`
|
* `DB::prepared_query()`
|
||||||
* `Director::urlParams()`
|
* `Director::urlParams()`
|
||||||
* `Controller->requestParams`, `Controller->urlParams`
|
* `Controller->requestParams`, `Controller->urlParams`
|
||||||
* `SS_HTTPRequest` data
|
* `SS_HTTPRequest` data
|
||||||
|
@ -1,60 +1,200 @@
|
|||||||
# 3.2.0 (unreleased)
|
# 3.2.0
|
||||||
|
|
||||||
## Overview
|
## Contents
|
||||||
|
|
||||||
### Framework
|
* [Major Changes](#major-changes)
|
||||||
|
* [Removed API](#deprecated-classesmethods-removed)
|
||||||
|
* [New API](#new-and-changed-api)
|
||||||
|
* [Bugfixes](#bugfixes)
|
||||||
|
* [Upgrading Notes](#upgrading-notes)
|
||||||
|
|
||||||
* Minimum PHP version raised to 5.3.3
|
## Major changes
|
||||||
* `DataObject::validate()` method visibility changed to public
|
|
||||||
* `NumericField` now uses HTML5 "number" type instead of "text"
|
|
||||||
* `UploadField` "Select from files" shows files in all folders by default
|
|
||||||
* `UploadField` won't display an overwrite warning unless `Upload::replaceFile` is true
|
|
||||||
* `HtmlEditorField` no longer substitutes `<blockquote />` for indented text
|
|
||||||
* `ClassInfo::dataClassesFor` now returns classes which should have tables, regardless of whether those
|
|
||||||
tables actually exist.
|
|
||||||
* `SS_Filterable`, `SS_Limitable` and `SS_Sortable` now explicitly extend `SS_List`
|
|
||||||
* `Convert::html2raw` no longer wraps text by default and can decode single quotes.
|
|
||||||
* `Mailer` no longer calls `xml2raw` on all email subject line, and now must be passed in via plain text.
|
|
||||||
* `ErrorControlChain` now supports reload on exceptions
|
|
||||||
* `FormField::validate` now requires an instance of `Validator`
|
|
||||||
* Implementation of new "Archive" concept for page removal, which supercedes "delete". Where deletion removed
|
|
||||||
pages only from draft, archiving removes from both draft and live simultaneously.
|
|
||||||
* Support for multiple HtmlEditorConfigs on the same page.
|
|
||||||
* Most of the `Image` manipulation methods have been renamed
|
|
||||||
* New `Image` methods `CropWidth` and `CropHeight` added
|
|
||||||
* 'Max' versions of `Image` methods introduced to prevent up-sampling
|
|
||||||
|
|
||||||
#### Deprecated classes/methods removed
|
* Minimum PHP version raised to 5.3.3
|
||||||
|
* Introduction of new parameterised ORM
|
||||||
|
* Default support for PDO
|
||||||
|
* Moved SS_Report and ReportAdmin out to a separate module. If you're using
|
||||||
|
composer or downloading a release, this module should be included for you.
|
||||||
|
Otherwise, you'll need to include the module yourself
|
||||||
|
(https://github.com/silverstripe-labs/silverstripe-reports)
|
||||||
|
* Moved SiteConfig also out to its own module. This will be included by
|
||||||
|
default if you include the CMS module.
|
||||||
|
(https://github.com/silverstripe/silverstripe-siteconfig)
|
||||||
|
* Implementation of new "Archive" concept for page removal, which supercedes
|
||||||
|
"delete from draft". Where deletion removed pages only from draft, archiving
|
||||||
|
removes from both draft and live simultaneously.
|
||||||
|
* Most of the `Image` manipulation methods have been renamed
|
||||||
|
|
||||||
* `ToggleField` was deprecated in 3.1, and has been removed. Use custom Javascript with `ReadonlyField` instead.
|
## Deprecated classes/methods removed
|
||||||
* `ExactMatchMultiFilter` was deprecated in 3.1, and has been removed. Use `ExactMatchFilter` instead.
|
|
||||||
* `NegationFilter` was deprecated in 3.1, and has been removed. Use `ExactMatchFilter:not` instead.
|
* `ToggleField` was deprecated in 3.1, and has been removed. Use custom Javascript with `ReadonlyField` instead.
|
||||||
* `StartsWithMultiFilter` was deprecated in 3.1, and has been removed. Use `StartsWithFilter` instead.
|
* `ExactMatchMultiFilter` was deprecated in 3.1, and has been removed. Use `ExactMatchFilter` instead.
|
||||||
* `ScheduledTask` and subclasses like `DailyTask` were deprecated in 3.1, and have been removed.
|
* `NegationFilter` was deprecated in 3.1, and has been removed. Use `ExactMatchFilter:not` instead.
|
||||||
|
* `StartsWithMultiFilter` was deprecated in 3.1, and has been removed. Use `StartsWithFilter` instead.
|
||||||
|
* `ScheduledTask` and subclasses like `DailyTask` were deprecated in 3.1, and have been removed.
|
||||||
Use custom code instead, or a module like silverstripe-crontask: https://github.com/silverstripe-labs/silverstripe-crontask
|
Use custom code instead, or a module like silverstripe-crontask: https://github.com/silverstripe-labs/silverstripe-crontask
|
||||||
* `Cookie::forceExpiry()` was removed. Use `Cookie::force_expiry()` instead
|
* `Cookie::forceExpiry()` was removed. Use `Cookie::force_expiry()` instead
|
||||||
* `Object` statics removal: `get_static()`, `set_static()`, `uninherited_static()`, `combined_static()`,
|
* `Object` statics removal: `get_static()`, `set_static()`, `uninherited_static()`, `combined_static()`,
|
||||||
`addStaticVars()` and `add_static_var()` removed. Use the Config methods instead.
|
`addStaticVars()` and `add_static_var()` removed. Use the Config methods instead.
|
||||||
* `GD` methods removed: `setGD()`, `getGD()`, `hasGD()`. Use `setImageResource()`, `getImageResource()`, and `hasImageResource()` instead
|
* `GD` methods removed: `setGD()`, `getGD()`, `hasGD()`. Use `setImageResource()`, `getImageResource()`, and `hasImageResource()` instead
|
||||||
* `DataExtension::get_extra_config()` removed, no longer supports `extraStatics` or `extraDBFields`. Define your
|
* `DataExtension::get_extra_config()` removed, no longer supports `extraStatics` or `extraDBFields`. Define your
|
||||||
statics on the class directly.
|
statics on the class directly.
|
||||||
* `DataList::getRange()` removed. Use `limit()` instead.
|
* `DataList::getRange()` removed. Use `limit()` instead.
|
||||||
* `SQLMap` removed. Call `map()` on a `DataList` or use `SS_Map` directly instead.
|
* `SQLMap` removed. Call `map()` on a `DataList` or use `SS_Map` directly instead.
|
||||||
* `Profiler` removed. Use xhprof or xdebug for profiling instead.
|
* `Profiler` removed. Use xhprof or xdebug for profiling instead.
|
||||||
* `Aggregate` removed. Call aggregate methods on a `DataList` instead e.g. `Member::get()->max('LastEdited')`
|
* `Aggregate` removed. Call aggregate methods on a `DataList` instead e.g. `Member::get()->max('LastEdited')`
|
||||||
* `MySQLDatabase::set_connection_charset()` removed. Use `MySQLDatabase.connection_charset` config setting instead
|
* `MySQLDatabase::set_connection_charset()` removed. Use `MySQLDatabase.connection_charset` config setting instead
|
||||||
* `SQLConditionalExpression/SQLQuery` `select()`, `limit()`, `orderby()`, `groupby()`, `having()`, `from()`, `leftjoin()`, `innerjoin()`, `where()` and `whereAny()` removed.
|
* `SQLConditionalExpression/SQLQuery` `select()`, `limit()`, `orderby()`, `groupby()`, `having()`, `from()`, `leftjoin()`, `innerjoin()`, `where()` and `whereAny()` removed.
|
||||||
Use `set*()` and `add*()` methods instead.
|
Use `set*()` and `add*()` methods instead.
|
||||||
* Template `<% control $MyList %>` syntax removed. Use `<% loop $MyList %>` instead.
|
* Template `<% control $MyList %>` syntax removed. Use `<% loop $MyList %>` instead.
|
||||||
* Object::singleton() method for better type-friendly singleton generation
|
* Removed `Member.LastVisited` and `Member.NumVisits` properties, see
|
||||||
|
[Howto: Track Member Logins](/extending/how_tos/track_member_logins) to restore functionality as custom code
|
||||||
|
|
||||||
### CMS
|
## New and changed API
|
||||||
|
|
||||||
* `SearchForm::getSearchQuery` no longer pre-escapes search keywords and must be cast in your template
|
* Implementation of a parameterised query framework eliminating the need to manually escape variables for
|
||||||
|
use in SQL queries. This has been integrated into nearly every level of the database ORM.
|
||||||
|
* Refactor of database connectivity classes into separate components linked together through dependency injection
|
||||||
|
* Refactor of `SQLQuery` into separate objects for each query type: `SQLQuery`, `SQLDelete`, `SQLUpdate` and `SQLInsert`
|
||||||
|
* PDO is now a standard connector, and is available for all database interfaces
|
||||||
|
* `DataObject::validate()` method visibility changed to public
|
||||||
|
* `NumericField` now uses HTML5 "number" type instead of "text"
|
||||||
|
* `UploadField` "Select from files" shows files in all folders by default
|
||||||
|
* `UploadField` won't display an overwrite warning unless `Upload::replaceFile` is true
|
||||||
|
* `HtmlEditorField` no longer substitutes `<blockquote />` for indented text
|
||||||
|
* `ClassInfo::dataClassesFor` now returns classes which should have tables, regardless of whether those
|
||||||
|
tables actually exist.
|
||||||
|
* `SS_Filterable`, `SS_Limitable` and `SS_Sortable` now explicitly extend `SS_List`
|
||||||
|
* `Convert::html2raw` no longer wraps text by default and can decode single quotes.
|
||||||
|
* `Mailer` no longer calls `xml2raw` on all email subject line, and now must be passed in via plain text.
|
||||||
|
* `ErrorControlChain` now supports reload on exceptions
|
||||||
|
* `FormField::validate` now requires an instance of `Validator`
|
||||||
|
* API: Removed URL routing by controller name
|
||||||
|
* Security: The multiple authenticator login page should now be styled manually - i.e. without the default jQuery
|
||||||
|
UI layout. A new template, Security_MultiAuthenticatorLogin.ss is available.
|
||||||
|
* Security: This controller's templates can be customised by overriding the `getTemplatesFor` function.
|
||||||
|
* API: Form and FormField ID attributes rewritten.
|
||||||
|
* `SearchForm::getSearchQuery` no longer pre-escapes search keywords and must
|
||||||
|
be cast in your template
|
||||||
|
* Helper function `DB::placeholders` can be used to generate a comma separated list of placeholders
|
||||||
|
useful for creating "WHERE ... IN (?,...)" SQL fragments
|
||||||
|
* Implemented Convert::symbol2sql to safely encode database and table names and identifiers.
|
||||||
|
E.g. `Convert::symbol2sql('table.column') => '"table"."column"';`
|
||||||
|
* `Convert::raw2sql` may now quote the escaped value, as well as safely escape it, according to the current
|
||||||
|
database adaptor's preference.
|
||||||
|
* `DB` class has been updated and many static methods have been renamed to conform to coding convention.
|
||||||
|
* Renamed API:
|
||||||
|
* `affectedRows` -> `affected_rows`
|
||||||
|
* `checkAndRepairTable` -> `check_and_repair_table`
|
||||||
|
* `createDatabase` -> `create_database`
|
||||||
|
* `createField` -> `create_field`
|
||||||
|
* `createTable` -> `create_table`
|
||||||
|
* `dontRequireField` -> `dont_require_field`
|
||||||
|
* `dontRequireTable` -> `dont_require_table`
|
||||||
|
* `fieldList` -> `field_list`
|
||||||
|
* `getConn` -> `get_conn`
|
||||||
|
* `getGeneratedID` -> `get_generated_id`
|
||||||
|
* `isActive` -> `is_active`
|
||||||
|
* `requireField` -> `require_field`
|
||||||
|
* `requireIndex` -> `require_index`
|
||||||
|
* `requireTable` -> `require_table`
|
||||||
|
* `setConn` -> `set_conn`
|
||||||
|
* `tableList` -> `table_list`
|
||||||
|
* Deprecated API:
|
||||||
|
* `getConnect` (Was placeholder for PDO connection string building code, but is made
|
||||||
|
redundant after the PDOConnector being fully abstracted)
|
||||||
|
* New API:
|
||||||
|
* `build_sql` - Hook into new SQL generation code
|
||||||
|
* `get_connector` (Nothing to do with getConnect)
|
||||||
|
* `get_schema`
|
||||||
|
* `placeholders`
|
||||||
|
* `prepared_query`
|
||||||
|
* `SS_Database` class has been updated and many functions have been deprecated, or refactored into
|
||||||
|
the various other database classes. Most of the database management classes remain in the database
|
||||||
|
controller, due to individual databases (changing, creating of, etc) varying quite a lot from
|
||||||
|
API to API, but schema updates within a database itself is managed by an attached DBSchemaManager
|
||||||
|
* Refactored into DBSchemaManager:
|
||||||
|
* `createTable`
|
||||||
|
* `alterTable`
|
||||||
|
* `renameTable`
|
||||||
|
* `createField`
|
||||||
|
* `renameField`
|
||||||
|
* `fieldList`
|
||||||
|
* `tableList`
|
||||||
|
* `hasTable`
|
||||||
|
* `enumValuesForField`
|
||||||
|
* `beginSchemaUpdate` and `endSchemaUpdate` -> Use `schemaUpdate` with a callback
|
||||||
|
* `cancelSchemaUpdate`
|
||||||
|
* `isSchemaUpdating`
|
||||||
|
* `doesSchemaNeedUpdating`
|
||||||
|
* `transCreateTable`
|
||||||
|
* `transAlterTable`
|
||||||
|
* `transCreateField`
|
||||||
|
* `transCreateField`
|
||||||
|
* `transCreateIndex`
|
||||||
|
* `transAlterField`
|
||||||
|
* `transAlterIndex`
|
||||||
|
* `requireTable`
|
||||||
|
* `dontRequireTable`
|
||||||
|
* `requireIndex`
|
||||||
|
* `hasField`
|
||||||
|
* `requireField`
|
||||||
|
* `dontRequireField`
|
||||||
|
* Refactored into DBQueryBuilder
|
||||||
|
* `sqlQueryToString`
|
||||||
|
* Deprecated:
|
||||||
|
* `getConnect` - Was intended for use with PDO, but was never implemented, and is now
|
||||||
|
redundant, now that there is a stand-alone `PDOConnector`
|
||||||
|
* `prepStringForDB` - Use `quoteString` instead
|
||||||
|
* `dropDatabase` - Use `dropSelectedDatabase`
|
||||||
|
* `createDatabase` - Use `selectDatabase` with the second parameter set to true instead
|
||||||
|
* `allDatabaseNames` - Use `databaseList` instead
|
||||||
|
* `currentDatabase` - Use `getSelectedDatabase` instead
|
||||||
|
* `addslashes` - Use `escapeString` instead
|
||||||
|
* `LogErrorEmailFormatter` now better displays SQL queries in errors by respecting line breaks
|
||||||
|
* Installer has been majorly upgraded to handle the new database configuration options
|
||||||
|
and additional PDO functionality.
|
||||||
|
* Created `SS_DatabaseException` to emit database errors. Query information such as SQL
|
||||||
|
and any relevant parameters may be used by error handling user code that catches
|
||||||
|
this exception.
|
||||||
|
* The `SQLConditionGroup` interface has been created to represent dynamically
|
||||||
|
evaluated SQL conditions. This may be used to wrap a class that generates
|
||||||
|
a custom SQL clause(s) to be evaluated at the time of execution.
|
||||||
|
* `DataObject` constants CHANGE_NONE, CHANGE_STRICT, and CHANGE_VALUE have been created
|
||||||
|
to provide more verbosity to field modification detection. This replaces the use of
|
||||||
|
various magic numbers with the same meaning.
|
||||||
|
* create_table_options now uses constants as API specific filters rather than strings.
|
||||||
|
This is in order to promote better referencing of elements across the codebase.
|
||||||
|
See `FulltextSearchable->enable` for example.
|
||||||
|
* `$FromEnd` iterator variable now available in templates.
|
||||||
|
* Support for multiple HtmlEditorConfigs on the same page.
|
||||||
|
* Object::singleton() method for better type-friendly singleton generation
|
||||||
|
* New `Image` methods `CropWidth` and `CropHeight` added
|
||||||
|
* 'Max' versions of `Image` methods introduced to prevent up-sampling
|
||||||
|
* Update Image method names in PHP code and templates
|
||||||
|
* `SetRatioSize` -> `Fit`
|
||||||
|
* `CroppedImage` -> `Fill`
|
||||||
|
* `PaddedImage` -> `Pad`
|
||||||
|
* `SetSize` -> `Pad`
|
||||||
|
* `SetWidth` -> `ScaleWidth`
|
||||||
|
* `SetHeight` -> `ScaleHeight`
|
||||||
|
|
||||||
## Changelog
|
## Bugfixes
|
||||||
|
|
||||||
### CMS
|
* Reduced database regeneration chances on subsequent rebuilds after the initial dev/build
|
||||||
|
* Elimination of various SQL injection vulnerability points
|
||||||
|
* `DataObject::writeComponents()` now called correctly during `DataObject::write()`
|
||||||
|
* Fixed missing theme declaration in installer
|
||||||
|
* Fixed incorrect use of non-existing exception classes (e.g. `HTTPResponse_exception`)
|
||||||
|
* `GridState` fixed to distinguish between check for missing values, and creation of
|
||||||
|
nested state values, in order to prevent non-empty values being returned for
|
||||||
|
missing keys. This was breaking `DataObject::get_by_id` by passing in an object
|
||||||
|
for the ID.
|
||||||
|
* Fixed order of `File` fulltext searchable fields to use same order as actual fields.
|
||||||
|
This is required to prevent unnecessary rebuild of MS SQL databases when fulltext
|
||||||
|
searching is enabled.
|
||||||
|
|
||||||
|
## Upgrading Notes
|
||||||
|
|
||||||
### DataObject::validate() method visibility changed to public
|
### DataObject::validate() method visibility changed to public
|
||||||
|
|
||||||
@ -63,6 +203,7 @@ The visibility of `DataObject::validate()` has been changed from `protected` to
|
|||||||
Any existing classes that currently set this as `protected` should be changed like in
|
Any existing classes that currently set this as `protected` should be changed like in
|
||||||
this example:
|
this example:
|
||||||
|
|
||||||
|
|
||||||
::php
|
::php
|
||||||
class MyDataClass extends DataObject {
|
class MyDataClass extends DataObject {
|
||||||
...
|
...
|
||||||
@ -72,13 +213,17 @@ this example:
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
### UploadField "Select from files" shows files in all folders by default
|
### UploadField "Select from files" shows files in all folders by default
|
||||||
|
|
||||||
In order to list files in a single folder by default (previous default behaviour),
|
In order to list files in a single folder by default (previous default behaviour),
|
||||||
use `setDisplayFolderName()` with a folder path relative to `assets/`:
|
use `setDisplayFolderName()` with a folder path relative to `assets/`:
|
||||||
|
|
||||||
|
|
||||||
|
:::php
|
||||||
UploadField::create('MyField')->setDisplayFolderName('Uploads');
|
UploadField::create('MyField')->setDisplayFolderName('Uploads');
|
||||||
|
|
||||||
|
|
||||||
### UploadField won't display an overwrite warning unless Upload:replaceFile is true
|
### UploadField won't display an overwrite warning unless Upload:replaceFile is true
|
||||||
|
|
||||||
The configuration setting `UploadField:overwriteWarning` is dependent on `Upload:replaceFile`
|
The configuration setting `UploadField:overwriteWarning` is dependent on `Upload:replaceFile`
|
||||||
@ -88,6 +233,7 @@ To display a warning before overwriting a file:
|
|||||||
|
|
||||||
Via config:
|
Via config:
|
||||||
|
|
||||||
|
|
||||||
::yaml
|
::yaml
|
||||||
Upload:
|
Upload:
|
||||||
# Replace an existing file rather than renaming the new one.
|
# Replace an existing file rather than renaming the new one.
|
||||||
@ -96,12 +242,15 @@ Via config:
|
|||||||
# Warning before overwriting existing file (only relevant when Upload: replaceFile is true)
|
# Warning before overwriting existing file (only relevant when Upload: replaceFile is true)
|
||||||
overwriteWarning: true
|
overwriteWarning: true
|
||||||
|
|
||||||
|
|
||||||
Or per instance:
|
Or per instance:
|
||||||
|
|
||||||
|
|
||||||
::php
|
::php
|
||||||
$uploadField->getUpload()->setReplaceFile(true);
|
$uploadField->getUpload()->setReplaceFile(true);
|
||||||
$uploadField->setOverwriteWarning(true);
|
$uploadField->setOverwriteWarning(true);
|
||||||
|
|
||||||
|
|
||||||
### File.allowed_extensions restrictions
|
### File.allowed_extensions restrictions
|
||||||
|
|
||||||
Certain file types such as swf, html, htm, xhtml and xml have been removed from the list
|
Certain file types such as swf, html, htm, xhtml and xml have been removed from the list
|
||||||
@ -130,35 +279,160 @@ languages like JavaScript won't be able to read them.
|
|||||||
To set it back to be non-HTTP only, you need to set the `$httpOnly` argument to false when calling
|
To set it back to be non-HTTP only, you need to set the `$httpOnly` argument to false when calling
|
||||||
`Cookie::set()`.
|
`Cookie::set()`.
|
||||||
|
|
||||||
### Bugfixes
|
### API: Removed URL routing by controller name
|
||||||
* Migration of code to use new parameterised framework
|
|
||||||
|
|
||||||
### Framework
|
The auto-routing of controller class names to URL endpoints
|
||||||
|
has been removed (rule: `'$Controller//$Action/$ID/$OtherID': '*'`).
|
||||||
|
This increases clarity in routing since it makes URL entpoints explicit,
|
||||||
|
and thereby simplifies system and security reviews.
|
||||||
|
|
||||||
* Implementation of a parameterised query framework eliminating the need to manually escape variables for
|
Please access any custom controllers exclusively through self-defined
|
||||||
use in SQL queries. This has been integrated into nearly every level of the database ORM.
|
[routes](/reference/director). For controllers extending `Page_Controller`,
|
||||||
* Refactor of database connectivity classes into separate components linked together through dependency injection
|
simply use the provided page URLs.
|
||||||
* Refactor of `SQLQuery` into separate objects for each query type: `SQLQuery`, `SQLDelete`, `SQLUpdate` and `SQLInsert`
|
|
||||||
* Rename of API methods to conform to coding conventions
|
|
||||||
* PDO is now a standard connector, and is available for all database interfaces
|
|
||||||
* Additional database and query generation tools
|
|
||||||
|
|
||||||
## Bugfixes
|
|
||||||
|
|
||||||
* Reduced database regeneration chances on subsequent rebuilds after the initial dev/build
|
:::php
|
||||||
* Elimination of various SQL injection vulnerability points
|
class MyController extends Controller {
|
||||||
* `DataObject::writeComponents()` now called correctly during `DataObject::write()`
|
static $allowed_actions = array('myaction');
|
||||||
* Fixed missing theme declaration in installer
|
public function myaction($request) {
|
||||||
* Fixed incorrect use of non-existing exception classes (e.g. `HTTPResponse_exception`)
|
// ...
|
||||||
* `GridState` fixed to distinguish between check for missing values, and creation of
|
}
|
||||||
nested state values, in order to prevent non-empty values being returned for
|
}
|
||||||
missing keys. This was breaking `DataObject::get_by_id` by passing in an object
|
|
||||||
for the ID.
|
|
||||||
* Fixed order of `File` fulltext searchable fields to use same order as actual fields.
|
Create a new file `mysite/_config/routes.yml`
|
||||||
This is required to prevent unnecessary rebuild of MS SQL databases when fulltext
|
(read more about the [config format](/topics/configuration)).
|
||||||
searching is enabled.
|
Your controller is now available on `http://yourdomain.com/my-controller-endpoint`,
|
||||||
|
after refreshing the configuration cache through `?flush=all`.
|
||||||
|
|
||||||
|
|
||||||
|
:::yaml
|
||||||
|
---
|
||||||
|
Name: my-routes
|
||||||
|
After: framework/routes#coreroutes
|
||||||
|
---
|
||||||
|
Director:
|
||||||
|
rules:
|
||||||
|
'my-controller-endpoint//$Action' : 'MyController'
|
||||||
|
|
||||||
|
|
||||||
|
The auto-routing is still in place for unit tests,
|
||||||
|
since its a frequently used feature there. Although we advise against it,
|
||||||
|
you can reinstate the old behaviour through a director rule:
|
||||||
|
|
||||||
|
|
||||||
|
:::yaml
|
||||||
|
---
|
||||||
|
Name: my-routes
|
||||||
|
After: framework/routes#coreroutes
|
||||||
|
---
|
||||||
|
Director:
|
||||||
|
rules:
|
||||||
|
'$Controller//$Action/$ID/$OtherID': '*'
|
||||||
|
|
||||||
|
|
||||||
|
### API: Default Form and FormField ID attributes rewritten.
|
||||||
|
|
||||||
|
Previously the automatic generation of ID attributes throughout the Form API
|
||||||
|
could generate invalid ID values such as Password[ConfirmedPassword] as well
|
||||||
|
as duplicate ID values between forms on the same page. For example, if you
|
||||||
|
created a field called `Email` on more than one form on the page, the resulting
|
||||||
|
HTML would have multiple instances of `#Email`. ID should be a unique
|
||||||
|
identifier for a single element within the document.
|
||||||
|
|
||||||
|
This rewrite has several angles, each of which is described below. If you rely
|
||||||
|
on ID values in your CSS files, Javascript code or application unit tests *you
|
||||||
|
will need to update your code*.
|
||||||
|
|
||||||
|
#### Conversion of invalid form ID values
|
||||||
|
|
||||||
|
ID attributes on Form and Form Fields will now follow the
|
||||||
|
[HTML specification](http://www.w3.org/TR/REC-html40/types.html#type-cdata).
|
||||||
|
Generating ID attributes is now handled by the new `FormTemplateHelper` class.
|
||||||
|
|
||||||
|
Please test each of your existing site forms to ensure that they work
|
||||||
|
correctly in particular, javascript and css styles which rely on specific ID
|
||||||
|
values.
|
||||||
|
|
||||||
|
#### Invalid ID attributes stripped
|
||||||
|
|
||||||
|
ID attributes will now be run through `Convert::raw2htmlid`. Invalid characters
|
||||||
|
are replaced with a single underscore character. Duplicate, leading and trailing
|
||||||
|
underscores are removed. Custom ID attributes (set through `setHTMLID`) will not
|
||||||
|
be altered.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
|
||||||
|
:::html
|
||||||
|
<form id="MyForm[Form]"
|
||||||
|
<div id="MyForm[Form][ID]">
|
||||||
|
|
||||||
|
|
||||||
|
Now:
|
||||||
|
|
||||||
|
|
||||||
|
:::html
|
||||||
|
<form id="MyForm_Form">
|
||||||
|
<div id="MyForm_Form_ID">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Namespaced FormField ID's
|
||||||
|
|
||||||
|
Form Field ID values will now be namespaced with the parent form ID.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
|
||||||
|
:::html
|
||||||
|
<div id="Email">
|
||||||
|
|
||||||
|
|
||||||
|
Now:
|
||||||
|
|
||||||
|
|
||||||
|
:::html
|
||||||
|
<div id="MyForm_Email">
|
||||||
|
|
||||||
|
|
||||||
|
#### FormField wrapper containers suffixed with `_Holder`
|
||||||
|
|
||||||
|
Previously both the container div and FormField tag shared the same ID in
|
||||||
|
certain cases. Now, the wrapper div in the default `FormField` template will be
|
||||||
|
suffixed with `_Holder`.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
|
||||||
|
:::html
|
||||||
|
<div id="Email">
|
||||||
|
<input id="Email" />
|
||||||
|
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
|
||||||
|
:::html
|
||||||
|
<div id="MyForm_Email_Holder"
|
||||||
|
<input id="MyForm_Email" />
|
||||||
|
|
||||||
|
|
||||||
|
#### Reverting to the old specification
|
||||||
|
|
||||||
|
If upgrading existing forms is not feasible, developers can opt out of the new
|
||||||
|
specifications by using the `FormTemplateHelper_Pre32` class rules instead of
|
||||||
|
the default ones.
|
||||||
|
|
||||||
|
|
||||||
|
`mysite/config/_config.yml`:
|
||||||
|
|
||||||
|
|
||||||
|
:::yaml
|
||||||
|
Injector:
|
||||||
|
FormTemplateHelper:
|
||||||
|
class: FormTemplateHelper_Pre32
|
||||||
|
|
||||||
## Upgrading
|
|
||||||
|
|
||||||
### Update code that uses SQLQuery
|
### Update code that uses SQLQuery
|
||||||
|
|
||||||
@ -177,6 +451,7 @@ although now a new SQLDelete object should be created from the original SQLQuery
|
|||||||
|
|
||||||
Before:
|
Before:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
$query = new SQLQuery('*');
|
$query = new SQLQuery('*');
|
||||||
@ -185,8 +460,10 @@ Before:
|
|||||||
$query->setDelete(true);
|
$query->setDelete(true);
|
||||||
$query->execute();
|
$query->execute();
|
||||||
|
|
||||||
|
|
||||||
After:
|
After:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
$query = SQLDelete::create()
|
$query = SQLDelete::create()
|
||||||
@ -194,8 +471,10 @@ After:
|
|||||||
->setWhere(array('"SiteTree"."ShowInMenus"' => 0));
|
->setWhere(array('"SiteTree"."ShowInMenus"' => 0));
|
||||||
$query->execute();
|
$query->execute();
|
||||||
|
|
||||||
|
|
||||||
Alternatively:
|
Alternatively:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
$query = SQLQuery::create()
|
$query = SQLQuery::create()
|
||||||
@ -204,6 +483,7 @@ Alternatively:
|
|||||||
->toDelete();
|
->toDelete();
|
||||||
$query->execute();
|
$query->execute();
|
||||||
|
|
||||||
|
|
||||||
### Update code that interacts with SQL strings to use parameters
|
### Update code that interacts with SQL strings to use parameters
|
||||||
|
|
||||||
The Silverstripe ORM (object relation model) has moved from using escaped SQL strings
|
The Silverstripe ORM (object relation model) has moved from using escaped SQL strings
|
||||||
@ -225,9 +505,10 @@ As a result of this upgrade there are now very few cases where `Convert::raw2sql
|
|||||||
|
|
||||||
Examples of areas where queries should be upgraded are below:
|
Examples of areas where queries should be upgraded are below:
|
||||||
|
|
||||||
1. #### Querying the database directly through DB, including non-SELECT queries
|
#### 1. Querying the database directly through DB, including non-SELECT queries
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -236,7 +517,9 @@ Examples of areas where queries should be upgraded are below:
|
|||||||
DB::query("UPDATE \"SiteTree\" SET \"Title\" LIKE '%" . Convert::raw2sql($myTitle) . "%' WHERE \"ID\" = 1");
|
DB::query("UPDATE \"SiteTree\" SET \"Title\" LIKE '%" . Convert::raw2sql($myTitle) . "%' WHERE \"ID\" = 1");
|
||||||
$myPages = DB::query(sprintf('SELECT "ID" FROM "MyObject" WHERE "Title" = \'%s\'', Convert::raw2sql($parentTitle)));
|
$myPages = DB::query(sprintf('SELECT "ID" FROM "MyObject" WHERE "Title" = \'%s\'', Convert::raw2sql($parentTitle)));
|
||||||
|
|
||||||
After:
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -250,9 +533,11 @@ Examples of areas where queries should be upgraded are below:
|
|||||||
array($parentTitle)
|
array($parentTitle)
|
||||||
);
|
);
|
||||||
|
|
||||||
2. #### Querying the database through `DataList`, `DataQuery`, `SQLQuery`, and `DataObject`
|
|
||||||
|
|
||||||
Before:
|
#### 2. Querying the database through `DataList`, `DataQuery`, `SQLQuery`, and `DataObject`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -264,7 +549,9 @@ Examples of areas where queries should be upgraded are below:
|
|||||||
'"Title" = \'' . Convert::raw2sql($title) . '\''
|
'"Title" = \'' . Convert::raw2sql($title) . '\''
|
||||||
);
|
);
|
||||||
|
|
||||||
After:
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -276,16 +563,18 @@ Examples of areas where queries should be upgraded are below:
|
|||||||
'"Title" = ?', $title
|
'"Title" = ?', $title
|
||||||
);
|
);
|
||||||
|
|
||||||
3. #### Interaction with `DataList::sql()`, `DataQuery::sql()`, `SQLQuery::sql()`, or `SQLQuery::getJoins()` methods
|
|
||||||
|
|
||||||
The place where legacy code would almost certainly fail is any code that calls
|
#### 3. Interaction with `DataList::sql()`, `DataQuery::sql()`, `SQLQuery::sql()`, or `SQLQuery::getJoins()` methods
|
||||||
DataList::sql`, `DataQuery::sql`, `SQLQuery::sql` or `SQLQuery::getJoins()`, as the api requires that user
|
|
||||||
code passes in an argument here to retrieve SQL parameters by value.
|
|
||||||
|
|
||||||
User code that assumes parameterless queries will likely fail, and need to be
|
The place where legacy code would almost certainly fail is any code that calls
|
||||||
updated to handle this case properly.
|
DataList::sql`, `DataQuery::sql`, `SQLQuery::sql` or `SQLQuery::getJoins()`, as the api requires that user
|
||||||
|
code passes in an argument here to retrieve SQL parameters by value.
|
||||||
|
|
||||||
|
User code that assumes parameterless queries will likely fail, and need to be
|
||||||
|
updated to handle this case properly.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -303,7 +592,9 @@ Examples of areas where queries should be upgraded are below:
|
|||||||
// Pass new query to database connector
|
// Pass new query to database connector
|
||||||
DB::query($sql);
|
DB::query($sql);
|
||||||
|
|
||||||
After:
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -325,10 +616,12 @@ Examples of areas where queries should be upgraded are below:
|
|||||||
// Note that DB::query($sql) would fail, as it would contain ? with missing parameters
|
// Note that DB::query($sql) would fail, as it would contain ? with missing parameters
|
||||||
DB::prepared_query($sql, $parameters);
|
DB::prepared_query($sql, $parameters);
|
||||||
|
|
||||||
Also note that the parameters may not be a single level array, as certain values
|
|
||||||
may be forced to be cast as a certain type (where supported by the current API).
|
|
||||||
|
|
||||||
E.g.
|
Also note that the parameters may not be a single level array, as certain values
|
||||||
|
may be forced to be cast as a certain type (where supported by the current API).
|
||||||
|
|
||||||
|
E.g.
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -339,7 +632,87 @@ Examples of areas where queries should be upgraded are below:
|
|||||||
)
|
)
|
||||||
DB::prepared_query('DELETE FROM "MyObject" WHERE ParentID = ? OR IsValid = ?', $parameters);
|
DB::prepared_query('DELETE FROM "MyObject" WHERE ParentID = ? OR IsValid = ?', $parameters);
|
||||||
|
|
||||||
4. ### Update code that interacts with the DB schema
|
|
||||||
|
#### 4. Interaction with `SQLQuery::getWhere()` method
|
||||||
|
|
||||||
|
As all where conditions are now parameterised, the format of the results returned by `SQLQuery::getWhere()`
|
||||||
|
will not always equate with that in FrameWork 3.1. Once this would be a list of strings, what will
|
||||||
|
now be returned is a list of conditions, each of which is an associative array mapping the
|
||||||
|
condition string to a list of parameters provided.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
|
||||||
|
:::php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Increment value of a single condition
|
||||||
|
$conditions = $query->getWhere();
|
||||||
|
$new = array();
|
||||||
|
foreach($conditions as $condition) {
|
||||||
|
if(preg_match('/\"Count\" = (?<count>\d+)/', $condition, $matches)) {
|
||||||
|
$condition = '"Count" = '.($matches['count'] + 1);
|
||||||
|
}
|
||||||
|
$new[] = $condition;
|
||||||
|
}
|
||||||
|
$query->setWhere($new);
|
||||||
|
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
|
||||||
|
:::php
|
||||||
|
// Increment value of a single condition
|
||||||
|
$conditions = $query->getWhere();
|
||||||
|
$new = array();
|
||||||
|
foreach($conditions as $condition) {
|
||||||
|
// $condition will be a single length array
|
||||||
|
foreach($condition as $predicate => $parameters) {
|
||||||
|
if('"Count" = ?' === $predicate) {
|
||||||
|
$parameters[0] = $parameters[0] + 1;
|
||||||
|
}
|
||||||
|
$new[] = array($predicate => $parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$query->setWhere($new);
|
||||||
|
|
||||||
|
|
||||||
|
In cases where user code will manipulate the results of this value, it may be useful to
|
||||||
|
replace this method call with the new `getWhereParameterised($parameters)` method, where
|
||||||
|
applicable.
|
||||||
|
|
||||||
|
This method returns a manipulated form of the where conditions stored by the query, so
|
||||||
|
that it matches the list of strings consistent with the old 3.1 `SQLQuery::getWhere()` behaviour.
|
||||||
|
Additionally, the list of parameters is safely extracted, flattened, and can be passed out
|
||||||
|
through the `$parameters` argument which is passed by reference.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
|
||||||
|
:::php
|
||||||
|
public function filtersOnColumn($query, $column) {
|
||||||
|
$regexp = '/^(.*\.)?("|`)?' . $column . ' ("|`)?\s?=/';
|
||||||
|
foreach($this->getWhere() as $predicate) {
|
||||||
|
if(preg_match($regexp, $predicate)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
|
||||||
|
:::php
|
||||||
|
public function filtersOnColumn($query, $column) {
|
||||||
|
$regexp = '/^(.*\.)?("|`)?' . $column . ' ("|`)?\s?=/';
|
||||||
|
foreach($this->getWhereParameterised($parameters) as $predicate) {
|
||||||
|
if(preg_match($regexp, $predicate)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#### 5. Update code that interacts with the DB schema
|
||||||
|
|
||||||
Updating database schema is now done by `updateSchema` with a callback, rather than relying
|
Updating database schema is now done by `updateSchema` with a callback, rather than relying
|
||||||
on user code to call `beginSchemaUpdate` and `endSchemaUpdate` around the call.
|
on user code to call `beginSchemaUpdate` and `endSchemaUpdate` around the call.
|
||||||
@ -350,6 +723,7 @@ interact with it via `DB::get_schema` instead of `DB::get_conn` (previously name
|
|||||||
|
|
||||||
Before:
|
Before:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
$conn = DB::getConn();
|
$conn = DB::getConn();
|
||||||
@ -359,8 +733,10 @@ Before:
|
|||||||
}
|
}
|
||||||
$conn->endSchemaUpdate();
|
$conn->endSchemaUpdate();
|
||||||
|
|
||||||
|
|
||||||
After:
|
After:
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
$schema = DB::get_schema();
|
$schema = DB::get_schema();
|
||||||
@ -370,6 +746,7 @@ After:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Also should be noted is that many functions have been renamed to conform better with
|
Also should be noted is that many functions have been renamed to conform better with
|
||||||
coding conventions. E.g. `DB::requireTable` is now `DB::require_table`
|
coding conventions. E.g. `DB::requireTable` is now `DB::require_table`
|
||||||
|
|
||||||
@ -381,6 +758,7 @@ feature which performs both unpublish and deletion simultaneously.
|
|||||||
|
|
||||||
To restore "delete from live" add the following config to your site's config.yml.
|
To restore "delete from live" add the following config to your site's config.yml.
|
||||||
|
|
||||||
|
|
||||||
:::yml
|
:::yml
|
||||||
CMSMain:
|
CMSMain:
|
||||||
enabled_legacy_actions:
|
enabled_legacy_actions:
|
||||||
@ -395,106 +773,3 @@ In order to remove the new "archive" action and restore the old "delete" action
|
|||||||
enabled_legacy_actions:
|
enabled_legacy_actions:
|
||||||
- CMSBatchAction_Delete
|
- CMSBatchAction_Delete
|
||||||
|
|
||||||
|
|
||||||
### Update Image method names in PHP code and templates
|
|
||||||
|
|
||||||
* `SetRatioSize` -> `Fit`
|
|
||||||
* `CroppedImage` -> `Fill`
|
|
||||||
* `PaddedImage` -> `Pad`
|
|
||||||
* `SetSize` -> `Pad`
|
|
||||||
* `SetWidth` -> `ScaleWidth`
|
|
||||||
* `SetHeight` -> `ScaleHeight`
|
|
||||||
|
|
||||||
### Other
|
|
||||||
|
|
||||||
* Helper function `DB::placeholders` can be used to generate a comma separated list of placeholders
|
|
||||||
useful for creating "WHERE ... IN (?,...)" SQL fragments
|
|
||||||
* Implemented Convert::symbol2sql to safely encode database and table names and identifiers.
|
|
||||||
E.g. `Convert::symbol2sql('table.column') => '"table"."column"';`
|
|
||||||
* `Convert::raw2sql` may now quote the escaped value, as well as safely escape it, according to the current
|
|
||||||
database adaptor's preference.
|
|
||||||
* `DB` class has been updated and many static methods have been renamed to conform to coding convention.
|
|
||||||
* Renamed API:
|
|
||||||
- `affectedRows` -> `affected_rows`
|
|
||||||
- `checkAndRepairTable` -> `check_and_repair_table`
|
|
||||||
- `createDatabase` -> `create_database`
|
|
||||||
- `createField` -> `createField`
|
|
||||||
- `createTable` -> `createTable`
|
|
||||||
- `dontRequireField` -> `dont_require_field`
|
|
||||||
- `dontRequireTable` -> `dont_require_table`
|
|
||||||
- `fieldList` -> `field_list`
|
|
||||||
- `getConn` -> `get_conn`
|
|
||||||
- `getGeneratedID` -> `get_generated_id`
|
|
||||||
- `isActive` -> `is_active`
|
|
||||||
- `requireField` -> `require_field`
|
|
||||||
- `requireIndex` -> `require_index`
|
|
||||||
- `requireTable` -> `require_table`
|
|
||||||
- `setConn` -> `set_conn`
|
|
||||||
- `tableList` -> `table_list`
|
|
||||||
* Deprecated API:
|
|
||||||
- `getConnect` (Was placeholder for PDO connection string building code, but is made
|
|
||||||
redundant after the PDOConnector being fully abstracted)
|
|
||||||
* New API:
|
|
||||||
- `build_sql` - Hook into new SQL generation code
|
|
||||||
- `get_connector` (Nothing to do with getConnect)
|
|
||||||
- `get_schema`
|
|
||||||
- `placeholders`
|
|
||||||
- `prepared_query`
|
|
||||||
* `SS_Database` class has been updated and many functions have been deprecated, or refactored into
|
|
||||||
the various other database classes. Most of the database management classes remain in the database
|
|
||||||
controller, due to individual databases (changing, creating of, etc) varying quite a lot from
|
|
||||||
API to API, but schema updates within a database itself is managed by an attached DBSchemaManager
|
|
||||||
* Refactored into DBSchemaManager:
|
|
||||||
- `createTable`
|
|
||||||
- `alterTable`
|
|
||||||
- `renameTable`
|
|
||||||
- `createField`
|
|
||||||
- `renameField`
|
|
||||||
- `fieldList`
|
|
||||||
- `tableList`
|
|
||||||
- `hasTable`
|
|
||||||
- `enumValuesForField`
|
|
||||||
- `beginSchemaUpdate` and `endSchemaUpdate` -> Use `schemaUpdate` with a callback
|
|
||||||
- `cancelSchemaUpdate`
|
|
||||||
- `isSchemaUpdating`
|
|
||||||
- `doesSchemaNeedUpdating`
|
|
||||||
- `transCreateTable`
|
|
||||||
- `transAlterTable`
|
|
||||||
- `transCreateField`
|
|
||||||
- `transCreateField`
|
|
||||||
- `transCreateIndex`
|
|
||||||
- `transAlterField`
|
|
||||||
- `transAlterIndex`
|
|
||||||
- `requireTable`
|
|
||||||
- `dontRequireTable`
|
|
||||||
- `requireIndex`
|
|
||||||
- `hasField`
|
|
||||||
- `requireField`
|
|
||||||
- `dontRequireField`
|
|
||||||
* Refactored into DBQueryBuilder
|
|
||||||
- `sqlQueryToString`
|
|
||||||
* Deprecated:
|
|
||||||
- `getConnect` - Was intended for use with PDO, but was never implemented, and is now
|
|
||||||
redundant, now that there is a stand-alone `PDOConnector`
|
|
||||||
- `prepStringForDB` - Use `quoteString` instead
|
|
||||||
- `dropDatabase` - Use `dropSelectedDatabase`
|
|
||||||
- `createDatabase` - Use `selectDatabase` with the second parameter set to true instead
|
|
||||||
- `allDatabaseNames` - Use `databaseList` instead
|
|
||||||
- `currentDatabase` - Use `getSelectedDatabase` instead
|
|
||||||
- `addslashes` - Use `escapeString` instead
|
|
||||||
* LogErrorEmailFormatter now better displays SQL queries in errors by respecting line breaks
|
|
||||||
* Installer has been majorly upgraded to handle the new database configuration options
|
|
||||||
and additional PDO functionality.
|
|
||||||
* Created SS_DatabaseException to emit database errors. Query information such as SQL
|
|
||||||
and any relevant parameters may be used by error handling user code that catches
|
|
||||||
this exception.
|
|
||||||
* The SQLConditionGroup interface has been created to represent dynamically
|
|
||||||
evaluated SQL conditions. This may be used to wrap a class that generates
|
|
||||||
a custom SQL clause(s) to be evaluated at the time of execution.
|
|
||||||
* DataObject constants CHANGE_NONE, CHANGE_STRICT, and CHANGE_VALUE have been created
|
|
||||||
to provide more verbosity to field modification detection. This replaces the use of
|
|
||||||
various magic numbers with the same meaning.
|
|
||||||
* create_table_options now uses constants as API specific filters rather than strings.
|
|
||||||
This is in order to promote better referencing of elements across the codebase.
|
|
||||||
See `FulltextSearchable->enable` for example.
|
|
||||||
* `$FromEnd` iterator variable now available in templates.
|
|
||||||
|
@ -1,146 +0,0 @@
|
|||||||
# 3.2.0 (unreleased)
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
### CMS
|
|
||||||
|
|
||||||
* Moved SS_Report and ReportAdmin out to a separate module. If you're using
|
|
||||||
composer or downloading a release, this module should be included for you.
|
|
||||||
Otherwise, you'll need to include the module yourself
|
|
||||||
(https://github.com/silverstripe-labs/silverstripe-reports)
|
|
||||||
|
|
||||||
### Framework
|
|
||||||
|
|
||||||
* API: Removed URL routing by controller name
|
|
||||||
* Security: The multiple authenticator login page should now be styled manually - i.e. without the default jQuery
|
|
||||||
UI layout. A new template, Security_MultiAuthenticatorLogin.ss is available.
|
|
||||||
* Security: This controller's templates can be customised by overriding the `getTemplatesFor` function.
|
|
||||||
* API: Form and FormField ID attributes rewritten.
|
|
||||||
|
|
||||||
## Details
|
|
||||||
|
|
||||||
### API: Removed URL routing by controller name
|
|
||||||
|
|
||||||
The auto-routing of controller class names to URL endpoints
|
|
||||||
has been removed (rule: `'$Controller//$Action/$ID/$OtherID': '*'`).
|
|
||||||
This increases clarity in routing since it makes URL entpoints explicit,
|
|
||||||
and thereby simplifies system and security reviews.
|
|
||||||
|
|
||||||
Please access any custom controllers exclusively through self-defined
|
|
||||||
[routes](/reference/director). For controllers extending `Page_Controller`,
|
|
||||||
simply use the provided page URLs.
|
|
||||||
|
|
||||||
:::php
|
|
||||||
class MyController extends Controller {
|
|
||||||
static $allowed_actions = array('myaction');
|
|
||||||
public function myaction($request) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Create a new file `mysite/_config/routes.yml`
|
|
||||||
(read more about the [config format](/topics/configuration)).
|
|
||||||
Your controller is now available on `http://yourdomain.com/my-controller-endpoint`,
|
|
||||||
after refreshing the configuration cache through `?flush=all`.
|
|
||||||
|
|
||||||
:::yaml
|
|
||||||
---
|
|
||||||
Name: my-routes
|
|
||||||
After: framework/routes#coreroutes
|
|
||||||
---
|
|
||||||
Director:
|
|
||||||
rules:
|
|
||||||
'my-controller-endpoint//$Action' : 'MyController'
|
|
||||||
|
|
||||||
|
|
||||||
The auto-routing is still in place for unit tests,
|
|
||||||
since its a frequently used feature there. Although we advise against it,
|
|
||||||
you can reinstate the old behaviour through a director rule:
|
|
||||||
|
|
||||||
:::yaml
|
|
||||||
---
|
|
||||||
Name: my-routes
|
|
||||||
After: framework/routes#coreroutes
|
|
||||||
---
|
|
||||||
Director:
|
|
||||||
rules:
|
|
||||||
'$Controller//$Action/$ID/$OtherID': '*'
|
|
||||||
|
|
||||||
### API: Default Form and FormField ID attributes rewritten.
|
|
||||||
|
|
||||||
Previously the automatic generation of ID attributes throughout the Form API
|
|
||||||
could generate invalid ID values such as Password[ConfirmedPassword] as well
|
|
||||||
as duplicate ID values between forms on the same page. For example, if you
|
|
||||||
created a field called `Email` on more than one form on the page, the resulting
|
|
||||||
HTML would have multiple instances of `#Email`. ID should be a unique
|
|
||||||
identifier for a single element within the document.
|
|
||||||
|
|
||||||
This rewrite has several angles, each of which is described below. If you rely
|
|
||||||
on ID values in your CSS files, Javascript code or application unit tests *you
|
|
||||||
will need to update your code*.
|
|
||||||
|
|
||||||
#### Conversion of invalid form ID values
|
|
||||||
|
|
||||||
ID attributes on Form and Form Fields will now follow the
|
|
||||||
[HTML specification](http://www.w3.org/TR/REC-html40/types.html#type-cdata).
|
|
||||||
Generating ID attributes is now handled by the new `FormTemplateHelper` class.
|
|
||||||
|
|
||||||
Please test each of your existing site forms to ensure that they work
|
|
||||||
correctly in particular, javascript and css styles which rely on specific ID
|
|
||||||
values.
|
|
||||||
|
|
||||||
#### Invalid ID attributes stripped
|
|
||||||
|
|
||||||
ID attributes will now be run through `Convert::raw2htmlid`. Invalid characters
|
|
||||||
are replaced with a single underscore character. Duplicate, leading and trailing
|
|
||||||
underscores are removed. Custom ID attributes (set through `setHTMLID`) will not
|
|
||||||
be altered.
|
|
||||||
|
|
||||||
Before:
|
|
||||||
<form id="MyForm[Form]"
|
|
||||||
<div id="MyForm[Form][ID]">
|
|
||||||
|
|
||||||
Now:
|
|
||||||
<form id="MyForm_Form">
|
|
||||||
<div id="MyForm_Form_ID">
|
|
||||||
|
|
||||||
#### Namespaced FormField ID's
|
|
||||||
|
|
||||||
Form Field ID values will now be namespaced with the parent form ID.
|
|
||||||
|
|
||||||
Before:
|
|
||||||
<div id="Email">
|
|
||||||
|
|
||||||
Now:
|
|
||||||
<div id="MyForm_Email">
|
|
||||||
|
|
||||||
#### FormField wrapper containers suffixed with `_Holder`
|
|
||||||
|
|
||||||
Previously both the container div and FormField tag shared the same ID in
|
|
||||||
certain cases. Now, the wrapper div in the default `FormField` template will be
|
|
||||||
suffixed with `_Holder`.
|
|
||||||
|
|
||||||
Before:
|
|
||||||
<div id="Email">
|
|
||||||
<input id="Email" />
|
|
||||||
|
|
||||||
After:
|
|
||||||
<div id="MyForm_Email_Holder"
|
|
||||||
<input id="MyForm_Email" />
|
|
||||||
|
|
||||||
#### Reverting to the old specification
|
|
||||||
|
|
||||||
If upgrading existing forms is not feasible, developers can opt out of the new
|
|
||||||
specifications by using the `FormTemplateHelper_Pre32` class rules instead of
|
|
||||||
the default ones.
|
|
||||||
|
|
||||||
:::yaml
|
|
||||||
# mysite/config/_config.yml
|
|
||||||
|
|
||||||
Injector:
|
|
||||||
FormTemplateHelper:
|
|
||||||
class: FormTemplateHelper_Pre32
|
|
||||||
|
|
||||||
### Further Changes
|
|
||||||
|
|
||||||
* Removed `Member.LastVisited` and `Member.NumVisits` properties, see [Howto: Track Member Logins](doc.silverstripe.org/framework/en/trunk/howto/track-member-logins) to restore functionality as custom code
|
|
Loading…
Reference in New Issue
Block a user