@@ -134,7 +134,7 @@ To get the value of entry node with the namespace media, use:
### Handling Errors
If the web service returned an error (for example, API key not available or inadequate parameters),
-`[api:RestfulService]` can delegate the error handling to it's descendant class. To handle the errors, subclass
+[api:RestfulService] can delegate the error handling to it's descendant class. To handle the errors, subclass
`RestfulService and define a function called errorCatch.
:::php
@@ -220,4 +220,4 @@ $service->request('service.json', 'GET', null, null, $curlOptions);
## API Documentation
-* `[api:RestfulService]`
+* [api:RestfulService]
diff --git a/docs/en/02_Developer_Guides/11_Integration/02_RSSFeed.md b/docs/en/02_Developer_Guides/11_Integration/02_RSSFeed.md
index 55b21ce95..23c740d62 100644
--- a/docs/en/02_Developer_Guides/11_Integration/02_RSSFeed.md
+++ b/docs/en/02_Developer_Guides/11_Integration/02_RSSFeed.md
@@ -3,15 +3,15 @@ summary: Output records from your database as an RSS Feed.
# RSS Feed
-Generating RSS / Atom-feeds is a matter of rendering a `[api:SS_List]` instance through the `[api:RSSFeed]` class.
+Generating RSS / Atom-feeds is a matter of rendering a [api:SS_List] instance through the [api:RSSFeed] class.
-The `[api:RSSFeed]` class doesn't limit you to generating article based feeds, it is just as easy to create a feed of
-your current staff members, comments or any other custom `[api:DataObject]` subclasses you have defined. The only
+The [api:RSSFeed] class doesn't limit you to generating article based feeds, it is just as easy to create a feed of
+your current staff members, comments or any other custom [api:DataObject] subclasses you have defined. The only
logical limitation here is that every item in the RSS-feed should be accessible through a URL on your website, so it's
-advisable to just create feeds from subclasses of `[api:SiteTree]`.
+advisable to just create feeds from subclasses of [api:SiteTree].
-If you wish to generate an RSS feed that contains a `[api:DataObject]`, ensure you define a `AbsoluteLink` method on
+If you wish to generate an RSS feed that contains a [api:DataObject], ensure you define a `AbsoluteLink` method on
the object.
@@ -47,7 +47,7 @@ will normally go in your `Controllers` `init` method.
### Showing the 10 most recently updated pages
-You can use `[api:RSSFeed]` to easily create a feed showing your latest Page updates. The following example adds a page
+You can use [api:RSSFeed] to easily create a feed showing your latest Page updates. The following example adds a page
`/home/rss/` which displays an XML file the latest updated pages.
**mysite/code/Page.php**
@@ -87,7 +87,7 @@ You can use `[api:RSSFeed]` to easily create a feed showing your latest Page upd
### Rendering DataObjects in a RSSFeed
-DataObjects can be rendered in the feed as well, however, since they aren't explicitly `[api:SiteTree]` subclasses we
+DataObjects can be rendered in the feed as well, however, since they aren't explicitly [api:SiteTree] subclasses we
need to include a function `AbsoluteLink` to allow the RSS feed to link through to the item.
@@ -193,4 +193,4 @@ As we've added a new template (PlayersRss.ss) make sure you clear your SilverStr
## API Documentation
-* `[api:RSSFeed]`
+* [api:RSSFeed]
diff --git a/docs/en/02_Developer_Guides/11_Integration/How_Tos/embed_rss.md b/docs/en/02_Developer_Guides/11_Integration/How_Tos/embed_rss.md
index 4903a4bc9..02ab66794 100644
--- a/docs/en/02_Developer_Guides/11_Integration/How_Tos/embed_rss.md
+++ b/docs/en/02_Developer_Guides/11_Integration/How_Tos/embed_rss.md
@@ -2,7 +2,7 @@ title: Embed an RSS Feed
# Embed an RSS Feed
-`[api:RestfulService]` can be used to easily embed an RSS feed from a site. In this How to we'll embed the latest
+[api:RestfulService] can be used to easily embed an RSS feed from a site. In this How to we'll embed the latest
weather information from the Yahoo Weather API.
First, we write the code to query the API feed.
@@ -54,4 +54,4 @@ single field `Description`.
## Related
* [RestfulService Documentation](../restfulservice)
-* `[api:RestfulService]`
\ No newline at end of file
+* [api:RestfulService]
diff --git a/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md b/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md
index 470095011..42442d6d9 100644
--- a/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md
+++ b/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md
@@ -204,7 +204,7 @@ Results.PaginationSummary(4) defines how many pages the search will show in the
## Available SearchFilters
-See `[api:SearchFilter]` API Documentation
+See [api:SearchFilter] API Documentation
## Related Documentation
diff --git a/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md b/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md
index 82153ca2d..7f8055efa 100644
--- a/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md
+++ b/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md
@@ -41,8 +41,8 @@ default site search, have a look at those extensions and modify as required.
### Fulltext Filter
-SilverStripe provides a `[api:FulltextFiler]` which you can use to perform custom fulltext searches on
-`[api:DataList]`'s.
+SilverStripe provides a [api:FulltextFilter] which you can use to perform custom fulltext searches on
+[api:DataList]s.
Example DataObject:
@@ -78,4 +78,4 @@ field instead of the index.
## API Documentation
-* [api:FulltextSearchable]
\ No newline at end of file
+* [api:FulltextSearchable]
diff --git a/docs/en/02_Developer_Guides/13_i18n/index.md b/docs/en/02_Developer_Guides/13_i18n/index.md
index 634988c0a..be74b0436 100644
--- a/docs/en/02_Developer_Guides/13_i18n/index.md
+++ b/docs/en/02_Developer_Guides/13_i18n/index.md
@@ -24,7 +24,7 @@ The i18n class is enabled by default.
### Setting the locale
-To set the locale you just need to call `[api:i18n::set_locale()]` passing, as a parameter, the name of the locale that
+To set the locale you just need to call [api:i18n::set_locale()] passing, as a parameter, the name of the locale that
you want to set.
:::php
@@ -39,7 +39,7 @@ for a complete listing of available locales.
### Getting the locale
-As you set the locale you can also get the current value, just by calling `[api:i18n::get_locale()]`.
+As you set the locale you can also get the current value, just by calling [api:i18n::get_locale()].
### Declaring the content language in HTML {#declaring_the_content_language_in_html}
@@ -72,9 +72,9 @@ to write your own logic for any frontend output.
Config::inst()->update('i18n', 'date_format', 'dd.MM.YYYY');
Config::inst()->update('i18n', 'time_format', 'HH:mm');
-Most localization routines in SilverStripe use the [Zend_Date API](http://framework.zend.com/manual/en/zend.date.html).
+Most localization routines in SilverStripe use the [Zend_Date API](http://framework.zend.com/manual/1.12/en/zend.date.overview.html).
This means all formats are defined in
-[ISO date format](http://framework.zend.com/manual/en/zend.date.constants.html#zend.date.constants.selfdefinedformats),
+[ISO date format](http://framework.zend.com/manual/1.12/en/zend.date.constants.html),
not PHP's built-in [date()](http://nz.php.net/manual/en/function.date.php).
### Language Names
@@ -272,7 +272,7 @@ There are a few special cases:
## Language definitions
Each module can have one language table per locale, stored by convention in the `lang/` subfolder.
-The translation is powered by [Zend_Translate](http://framework.zend.com/manual/en/zend.translate.html),
+The translation is powered by [Zend_Translate](http://framework.zend.com/manual/current/en/modules/zend.i18n.translating.html),
which supports different translation adapters, dealing with different storage formats.
By default, SilverStripe 3.x uses a YAML format (through the [Zend_Translate_RailsYAML adapter](https://github.com/chillu/zend_translate_railsyaml)).
@@ -411,4 +411,4 @@ The `ss.i18n` object contain a couple functions to help and replace dynamic vari
* [Help to translate](../../contributing/translations) - Instructions for online collaboration to translate core
* [Help to translate](../../contributing/translation_process) - Instructions for adding translation to your own modules
* [http://www.i18nguy.com/](http://www.i18nguy.com/)
- * [balbus.tk i18n notes](http://www.balbus.tk/internationalize)
+ * [balbus.tk i18n notes](http://www.balbuss.com/internationalize/)
diff --git a/docs/en/02_Developer_Guides/14_Files/01_File_Management.md b/docs/en/02_Developer_Guides/14_Files/01_File_Management.md
index f1d957a29..2228ee64f 100644
--- a/docs/en/02_Developer_Guides/14_Files/01_File_Management.md
+++ b/docs/en/02_Developer_Guides/14_Files/01_File_Management.md
@@ -37,4 +37,4 @@ You may also notice the 'Sync files' button (highlighted below). This button all
## Upload
-Files can be managed through a `FileField` or an `UploadField`. The `[api:FileField]` class provides a simple HTML input with a type of "file", whereas an `[api:UploadField]` provides a much more feature-rich field (including AJAX-based uploads, previews, relationship management and file data management). See [`Reference - UploadField`](/developer_guides/forms/field_types/uploadfield) for more information about how to use the `UploadField` class.
\ No newline at end of file
+Files can be managed through a `FileField` or an `UploadField`. The [api:FileField] class provides a simple HTML input with a type of "file", whereas an [api:UploadField] provides a much more feature-rich field (including AJAX-based uploads, previews, relationship management and file data management). See [`Reference - UploadField`](/developer_guides/forms/field_types/uploadfield) for more information about how to use the `UploadField` class.
diff --git a/docs/en/02_Developer_Guides/14_Files/02_Images.md b/docs/en/02_Developer_Guides/14_Files/02_Images.md
index 46babf387..d2055f452 100644
--- a/docs/en/02_Developer_Guides/14_Files/02_Images.md
+++ b/docs/en/02_Developer_Guides/14_Files/02_Images.md
@@ -2,14 +2,14 @@ summary: Learn how to crop and resize images in templates and PHP code
# Image
-Represents an image object through the `[api:Image]` class, inheriting all base functionality from the `[api:File]` class with extra functionality including resizing.
+Represents an image object through the [api:Image] class, inheriting all base functionality from the [api:File] class with extra functionality including resizing.
## Usage
### Managing images through form fields
-Images can be uploaded like any other file, through `[api:FileField]`.
-More advanced usage is possible through `[api:UploadField]`,
+Images can be uploaded like any other file, through [api:FileField].
+More advanced usage is possible through [api:UploadField],
which provides thumbnails, a detail view of the image properties,
and management of relationships to other DataObject instances.
Allows upload of images through limiting file extensions with `setAllowedExtensions()`.
@@ -70,7 +70,7 @@ The image manipulation functions can be used in your code with the same names, e
Some of the MetaData functions need to be prefixed with 'get', example `getHeight()`, `getOrientation()` etc.
-Please refer to the `[api:Image]` API documentation for specific functions.
+Please refer to the [api:Image] API documentation for specific functions.
### Creating custom image functions
@@ -117,8 +117,8 @@ You can also create your own functions by extending the image class, for example
### Form Upload
-For usage on a website form, see `[api:FileField]`.
-If you want to upload images within the CMS, see `[api:UploadField]`.
+For usage on a website form, see [api:FileField].
+If you want to upload images within the CMS, see [api:UploadField].
### Image Quality
@@ -160,4 +160,4 @@ disappeared, you can try manually flushing the image cache.
http://localhost/dev/tasks/FlushGeneratedImagesTask
## API Documentation
-`[api:Image]`
+[api:Image]
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/01_ModelAdmin.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/01_ModelAdmin.md
index 239d045cc..28eb60f57 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/01_ModelAdmin.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/01_ModelAdmin.md
@@ -124,7 +124,7 @@ searched results. Every [api:DataObject] can have its own context, based on the
class makes a guess at how those fields should be searched, e.g. showing a checkbox for any boolean fields in your
`$db` definition.
-To remove, add or modify searchable fields, define a new `[api:DataObject::$searchable_fields]` static on your model
+To remove, add or modify searchable fields, define a new [api:DataObject::$searchable_fields] static on your model
class (see [SearchContext](../search/searchcontext) docs for details).
**mysite/code/Product.php**
@@ -167,7 +167,7 @@ model class, where you can add or remove columns. To change the title, use [api:
);
}
-The results list are retrieved from [api:SearchContext->getResults], based on the parameters passed through the search
+The results list are retrieved from [api:SearchContext::getResults()], based on the parameters passed through the search
form. If no search parameters are given, the results will show every record. Results are a [api:DataList] instance, so
can be customized by additional SQL filters, joins.
@@ -225,7 +225,7 @@ checkbox which limits search results to expensive products (over $100).
}
}
-To alter how the results are displayed (via `[api:GridField]`), you can also overload the `getEditForm()` method. For
+To alter how the results are displayed (via [api:GridField]), you can also overload the `getEditForm()` method. For
example, to add a new component.
**mysite/code/MyAdmin.php**
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/05_CMS_Architecture.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/02_CMS_Architecture.md
similarity index 93%
rename from docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/05_CMS_Architecture.md
rename to docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/02_CMS_Architecture.md
index 30a9ab512..602c8686c 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/05_CMS_Architecture.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/02_CMS_Architecture.md
@@ -3,8 +3,8 @@
## Introduction
A lot can be achieved in SilverStripe by adding properties and form fields
-to your own page types (via `[api:SiteTree->getCMSFields()]`), as well as creating
-your own data management interfaces through `[api:ModelAdmin]`. But sometimes
+to your own page types (via [api:SiteTree::getCMSFields()]), as well as creating
+your own data management interfaces through [api:ModelAdmin]. But sometimes
you'll want to go deeper and tailor the underlying interface to your needs as well.
For example, to build a personalized CMS dashboard, or content "slots" where authors
can drag their content into. At its core, SilverStripe is a web application
@@ -51,14 +51,14 @@ See our [system requirements](/getting_started/server_requirements) for a list o
## Templates and Controllers
-The CMS backend is handled through the `[api:LeftAndMain]` controller class,
+The CMS backend is handled through the [api:LeftAndMain] controller class,
which contains base functionality like displaying and saving a record.
-This is extended through various subclasses, e.g. to add a group hierarchy (`[api:SecurityAdmin]`),
-a search interface (`[api:ModelAdmin]`) or an "Add Page" form (`[api:CMSPageAddController]`).
+This is extended through various subclasses, e.g. to add a group hierarchy ([api:SecurityAdmin]),
+a search interface ([api:ModelAdmin]) or an "Add Page" form ([api:CMSPageAddController]).
The controller structure is too complex to document here, a good starting point
-for following the execution path in code are `[api:LeftAndMain->getRecord()]` and `[api:LeftAndMain->getEditForm()]`.
-If you have the `cms` module installed, have a look at `[api:CMSMain->getEditForm()]` for a good
+for following the execution path in code are [api:LeftAndMain::getRecord()] and [api:LeftAndMain::getEditForm()].
+If you have the `cms` module installed, have a look at [api:CMSMain::getEditForm()] for a good
example on how to extend the base functionality (e.g. by adding page versioning hints to the form).
CMS templates are inherited based on their controllers, similar to subclasses of
@@ -72,13 +72,13 @@ which is in charge of rendering the main content area apart from the CMS menu.
Depending on the complexity of your layout, you'll also need to overload the
"EditForm" template (e.g. `MyCMSController_EditForm.ss`), e.g. to implement
a tabbed form which only scrolls the main tab areas, while keeping the buttons at the bottom of the frame.
-This requires manual assignment of the template to your form instance, see `[api:CMSMain->getEditForm()]` for details.
+This requires manual assignment of the template to your form instance, see [api:CMSMain::getEditForm()] for details.
Often its useful to have a "tools" panel in between the menu and your content,
usually occupied by a search form or navigational helper.
In this case, you can either overload the full base template as described above.
-To avoid duplicating all this template code, you can also use the special `[api:LeftAndMain->Tools()]` and
-`[api:LeftAndMain->EditFormTools()]` methods available in `LeftAndMain`.
+To avoid duplicating all this template code, you can also use the special [api:LeftAndMain::Tools()] and
+[api:LeftAndMain::EditFormTools()] methods available in `LeftAndMain`.
These placeholders are populated by auto-detected templates,
with the naming convention of "_Tools.ss" and "_EditFormTools.ss".
So to add or "subclass" a tools panel, simply create this file and it's automatically picked up.
@@ -94,7 +94,7 @@ Refer to [Layout reference](/developer_guides/customising_the_admin_interface/cm
## Forms
SilverStripe constructs forms and its fields within PHP,
-mainly through the `[getCMSFields()](api:DataObject->getCMSFields())` method.
+mainly through the [getCMSFields()](api:DataObject::getCMSFields()) method.
This in turn means that the CMS loads these forms as HTML via Ajax calls,
e.g. after saving a record (which requires a form refresh), or switching the section in the CMS.
@@ -165,10 +165,10 @@ any particular element.
## JavaScript and CSS dependencies via Requirements and Ajax
The JavaScript logic powering the CMS is divided into many files,
-which typically are included via the `[api:Requirements]` class, by adding
-them to `[api:LeftAndMain->init()]` and its subclassed methods.
+which typically are included via the [api:Requirements] class, by adding
+them to [api:LeftAndMain::init()] and its subclassed methods.
This class also takes care of minification and combination of the files,
-which is crucial for the CMS performance (see `[api:Requirements::combine_files()]`).
+which is crucial for the CMS performance (see [api:Requirements::combine_files()]).
Due to the procedural and selector-driven style of UI programming in jQuery.entwine,
it can be difficult to find the piece of code responsible for a certain behaviour.
@@ -188,7 +188,7 @@ and [jQuery.delegate](http://api.jquery.com/delegate/), so takes care of dynamic
Most interfaces will require their own JavaScript and CSS files, so the Ajax loading has
to ensure they're loaded unless already present. A custom-built library called
`jQuery.ondemand` (located in `framework/thirdparty`) takes care of this transparently -
-so as a developer just declare your dependencies through the `[api:Requirements]` API.
+so as a developer just declare your dependencies through the [api:Requirements] API.
## Ajax Loading and Browser History
@@ -220,10 +220,10 @@ we often want to update these sections independently from their neighbouring con
In order for this to work, the CMS templates declare certain sections as "PJAX fragments"
through a `data-pjax-fragment` attribute. These names correlate to specific
-rendering logic in the PHP controllers, through the `[api:PjaxResponseNegotiator]` class.
+rendering logic in the PHP controllers, through the [api:PjaxResponseNegotiator] class.
Through a custom `X-Pjax` HTTP header, the client can declare which view they're expecting,
-through identifiers like `CurrentForm` or `Content` (see `[api:LeftAndMain->getResponseNegotiator()]`).
+through identifiers like `CurrentForm` or `Content` (see [api:LeftAndMain::getResponseNegotiator()]).
These identifiers are passed to `loadPanel()` via the `pjax` data option.
The HTTP response is a JSON object literal, with template replacements keyed by their Pjax fragment.
Through PHP callbacks, we ensure that only the required template parts are actually executed and rendered.
@@ -402,11 +402,11 @@ when using an input of type button, submit or reset, support is limited to plain
## Menu
-The navigation menu in the CMS is created through the `[api:CMSMenu]` API,
+The navigation menu in the CMS is created through the [api:CMSMenu] API,
which auto-detects all subclasses of `LeftAndMain`. This means that your custom
`ModelAdmin` subclasses will already appear in there without any explicit definition.
-To modify existing menu entries or create new ones, see `[api:CMSMenu::add_menu_item()]`
-and `[api:CMSMenu::remove_menu_item()]`.
+To modify existing menu entries or create new ones, see [api:CMSMenu::add_menu_item()]
+and [api:CMSMenu::remove_menu_item()].
New content panels are typically loaded via Ajax, which might change
the current menu context. For example, a link to edit a file might be clicked
@@ -422,7 +422,7 @@ which is picked up by the menu:
return 'my response';
}
-This is usually handled by the existing `[api:LeftAndMain]` logic,
+This is usually handled by the existing [api:LeftAndMain] logic,
so you don't need to worry about it. The same concept applies for
'X-Title' (change the window title) and 'X-ControllerURL' (change the URL recorded in browser history).
Note: You can see any additional HTTP headers through the web developer tools in your browser of choice.
@@ -437,13 +437,13 @@ For more information, see the [Howto: Customise the CMS tree](/developer_guides/
Note that a similar tree logic is also used for the
form fields to select one or more entries from those hierarchies
-(`[api:TreeDropdownField]` and `[api:TreeMultiselectField]`).
+([api:TreeDropdownField] and [api:TreeMultiselectField]).
## Tabs
We're using [jQuery UI tabs](http://jqueryui.com/), but in a customised fashion.
HTML with tabs can be created either directly through HTML templates in the CMS,
-or indirectly through a `[api:TabSet]` form field. Since tabsets are useable
+or indirectly through a [api:TabSet] form field. Since tabsets are useable
outside of the CMS as well, the baseline application of tabs happens via
a small wrapper around `jQuery.tabs()` stored in `TabSet.js`.
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md
index ce4cffd3f..598edb685 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md
@@ -349,7 +349,7 @@ attributes, or the jQuery.metadata plugin). For returning status messages, pleas
Only return evaluated JavaScript snippets if unavoidable. Most of the time you can just pass data around, and let the
clientside react to changes appropriately without telling it directly through JavaScript in AJAX responses. Don't use
-the `[api:Form]` SilverStripe class, which is built solely around
+the [api:Form] SilverStripe class, which is built solely around
this inflexible concept.
Example: Autocomplete input field loading page matches through AJAX
@@ -420,7 +420,7 @@ JavaScript:
Although they are the minority of cases, there are times when a simple HTML fragment isn't enough. For example, if you
have server side code that needs to trigger the update of a couple of elements in the CMS left-hand tree, it would be
-inefficient to send back the HTML of entire tree. SilverStripe can serialize to and from JSON (see the `[api:Convert]` class), and jQuery deals very well with it through
+inefficient to send back the HTML of entire tree. SilverStripe can serialize to and from JSON (see the [api:Convert] class), and jQuery deals very well with it through
[jQuery.getJSON()](http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback), as long as the HTTP content-type is
properly set.
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md
index 597993fdf..eac6d62db 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md
@@ -2,10 +2,10 @@
## Adding an administration panel
-Every time you add a new extension of the `[api:LeftAndMain]` class to the CMS,
-SilverStripe will automatically create a new `[api:CMSMenuItem]` for it
+Every time you add a new extension of the [api:LeftAndMain] class to the CMS,
+SilverStripe will automatically create a new [api:CMSMenuItem] for it
-The most popular extension of LeftAndMain is a `[api:ModelAdmin]` class, so
+The most popular extension of LeftAndMain is a [api:ModelAdmin] class, so
for a more detailed introduction to creating new `ModelAdmin` interfaces, read
the [ModelAdmin reference](../modeladmin).
@@ -51,7 +51,7 @@ On top of your administration windows, the menu can also have external links
(e.g. to external reference). In this example, we're going to add a link to
Google to the menu.
-First, we need to define a `[api:LeftAndMainExtension]` which will contain our
+First, we need to define a [api:LeftAndMainExtension] which will contain our
button configuration.
:::php
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Pages_List.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Pages_List.md
index 6210ef23b..4568ce429 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Pages_List.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Pages_List.md
@@ -10,8 +10,8 @@ as well as sort and filter them in a way that would be hard to achieve in a tree
But sometimes the default behaviour isn't powerful enough, and you want a more
specific list view for certain page types, for example to sort the list by
a different criteria, or add more columns to filter on. The resulting
-form is mainly based around a `[GridField](/reference/grid-field)` instance,
-which in turn includes all children in a `[DataList](/topics/datamodel)`.
+form is mainly based around a [GridField](/reference/grid-field) instance,
+which in turn includes all children in a [DataList](/topics/datamodel).
You can use these two classes as a starting point for your customizations.
Here's a brief example on how to add sorting and a new column for a
@@ -69,4 +69,4 @@ Now you just need to enable the extension in your [configuration file](../../con
extensions:
- NewsPageHolderCMSMainExtension
-You're all set! Don't forget to flush the caches by appending `?flush=all` to the URL.
\ No newline at end of file
+You're all set! Don't forget to flush the caches by appending `?flush=all` to the URL.
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Tree.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Tree.md
index 46193e87e..8377cdf75 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Tree.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Tree.md
@@ -7,10 +7,10 @@ by the [jstree](http://jstree.com) library. It is configured through
`framework/admin/javascript/LeftAndMain.Tree.js`, as well as some
HTML5 metadata generated on its container (see the `data-hints` attribute).
-The tree is rendered through `[api:LeftAndMain->getSiteTreeFor()]`,
+The tree is rendered through [api:LeftAndMain::getSiteTreeFor()],
which recursively collects all nodes based on various filtering criteria.
-The node strictly just has to implement the `[api:Hierarchy]` extension,
-but in the CMS usually is a `[api:SiteTree]` object.
+The node strictly just has to implement the [api:Hierarchy] extension,
+but in the CMS usually is a [api:SiteTree] object.
## Add status lozenges to tree nodes
@@ -43,13 +43,13 @@ code like this:
By applying the proper style sheet, the snippet html above could produce the look of:
![Page Node Screenshot](../../../_images/tree_node.png "Page Node")
-SiteTree is a `[api:DataObject]` which is versioned by `[api:Versioned]` extension.
+SiteTree is a [api:DataObject] which is versioned by [api:Versioned] extension.
Each node can optionally have publication status flags, e.g. "Removed from draft".
Each flag has a unique identifier, which is also used as a CSS class for easier styling.
Developers can easily add a new flag, delete or alter an existing flag on how it is looked
or changing the flag label. The customization of these lozenges could be done either through
-inherited subclass or `[api:DataExtension]`. It is just really about how we change the return
+inherited subclass or [api:DataExtension]. It is just really about how we change the return
value of function `SiteTree->getTreeTitle()` by two easily extendable methods
`SiteTree->getStatusClass()` and `SiteTree->getStatusFlags()`.
@@ -74,7 +74,7 @@ __Example: using a subclass__
}
}
-The above subclass of `[api:SiteTree]` will add a new flag for indicating its
+The above subclass of [api:SiteTree] will add a new flag for indicating its
__'Scheduled To Publish'__ status. The look of the page node will be changed
from ![Normal Page Node](../../../_images/page_node_normal.png) to ![Scheduled Page Node](../../../_images/page_node_scheduled.png). The getStatusFlags has an `updateStatusFlags()`
extension point, so the flags can be modified through `DataExtension` rather than
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_Site_Reports.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_Site_Reports.md
index fdc65d01c..6b927aa09 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_Site_Reports.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_Site_Reports.md
@@ -71,4 +71,4 @@ More useful reports can be created by changing the `DataList` returned in the `s
* More examples
## API documentation
-`[api:ReportAdmin]`
+[api:ReportAdmin]
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extending_An_Existing_ModelAdmin.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extending_An_Existing_ModelAdmin.md
index f1cc60c2f..d0b087821 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extending_An_Existing_ModelAdmin.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extending_An_Existing_ModelAdmin.md
@@ -1,7 +1,7 @@
## Extending existing ModelAdmin
Sometimes you'll work with ModelAdmins from other modules. To customize these interfaces, you can always subclass. But there's
-also another tool at your disposal: The `[api:Extension]` API.
+also another tool at your disposal: The [api:Extension] API.
:::php
class MyAdminExtension extends Extension {
@@ -19,4 +19,4 @@ Now enable this extension through your `[config.yml](/topics/configuration)` fil
- MyAdminExtension
The following extension points are available: `updateEditForm()`, `updateSearchContext()`,
-`updateSearchForm()`, `updateList()`, `updateImportForm`.
\ No newline at end of file
+`updateSearchForm()`, `updateList()`, `updateImportForm`.
diff --git a/docs/en/02_Developer_Guides/16_Execution_Pipeline/01_Flushable.md b/docs/en/02_Developer_Guides/16_Execution_Pipeline/01_Flushable.md
index e46ef19b5..ffe7cf975 100644
--- a/docs/en/02_Developer_Guides/16_Execution_Pipeline/01_Flushable.md
+++ b/docs/en/02_Developer_Guides/16_Execution_Pipeline/01_Flushable.md
@@ -6,17 +6,17 @@ summary: Allows a class to define it's own flush functionality.
## Introduction
Allows a class to define it's own flush functionality, which is triggered when `flush=1` is requested in the URL.
-`[api:FlushRequestFilter]` is run before a request is made, calling `flush()` statically on all
-implementors of `[api:Flushable]`.
+[api:FlushRequestFilter] is run before a request is made, calling `flush()` statically on all
+implementors of [api:Flushable].
## Usage
-To use this API, you need to make your class implement `[api:Flushable]`, and define a `flush()` static function,
+To use this API, you need to make your class implement [api:Flushable], and define a `flush()` static function,
this defines the actions that need to be executed on a flush request.
### Using with SS_Cache
-This example uses `[api:SS_Cache]` in some custom code, and the same cache is cleaned on flush:
+This example uses [api:SS_Cache] in some custom code, and the same cache is cleaned on flush:
:::php
+
+## Change Log
+
+### Security
+
+ * 2016-02-17 [faa94d5](https://github.com/silverstripe/silverstripe-framework/commit/faa94d51d570788dcebc2f2ef6e9de4d179ce1e4) Hostname, IP and Protocol Spoofing through HTTP Headers (Ingo Schommer) - See [ss-2016-003](http://www.silverstripe.org/download/security-releases/ss-2016-003)
+ * 2016-02-17 [15d4db3](https://github.com/silverstripe/silverstripe-framework/commit/15d4db3b4a7dbc9a7e089f9329a396f8408ed7d9) Block unauthenticated access to dev/build/defaults (Damian Mooyman) - See [ss-2015-028](http://www.silverstripe.org/download/security-releases/ss-2015-028)
+ * 2016-02-17 [e2c77c5](https://github.com/silverstripe/silverstripe-framework/commit/e2c77c5a8f13e901c51a3684210811559b592f0c) Ensure Gridfield actions respect CSRF (Damian Mooyman) - See [ss-2016-002](http://www.silverstripe.org/download/security-releases/ss-2016-002)
+ * 2015-11-11 [245e0aa](https://github.com/silverstripe/silverstripe-framework/commit/245e0aae2f5f3eb0acba1d198ad8e196bb224462) Fix FormField error messages not being encoded safely (Damian Mooyman) - See [ss-2015-026](http://www.silverstripe.org/download/security-releases/ss-2015-026)
+ * 2015-11-09 [53b3bc7](https://github.com/silverstripe/silverstripe-framework/commit/53b3bc707bcccb8f5e5060f85ab1398a0975bba2) Dont expose class on error (Hamish Friedlander) - See [ss-2015-025](http://www.silverstripe.org/download/security-releases/ss-2015-025)
+ * 2015-11-01 [ac4342d](https://github.com/silverstripe/silverstripe-framework/commit/ac4342d81d19201bd8d3814f168240db1ac565fe) XML escape RSSFeed $link parameter (Ingo Schommer) - See [ss-2015-022](http://www.silverstripe.org/download/security-releases/ss-2015-022)
+ * 2015-10-28 [97f21fd](https://github.com/silverstripe/silverstripe-framework/commit/97f21fddb3c565052f19ee3b35366f48e1e9a36f) Fix rewrite hash links XSS (Damian Mooyman) - See [ss-2015-021](http://www.silverstripe.org/download/security-releases/ss-2015-021)
+
+### Bugfixes
+
+ * 2016-02-15 [8771859](https://github.com/silverstripe/silverstripe-framework/commit/87718597e8f04872c285808d0666fbb69c5100ba) "where" method in SQLUpdate Example (Richard Rudy)
+ * 2016-01-28 [3fcf1e2](https://github.com/silverstripe/silverstripe-framework/commit/3fcf1e2c98629dcd0048ff9447bad4cd30b4bf95) edge case on many many extra fields (fixes 4991) (Mark Stephens)
+ * 2016-01-27 [3d0178e](https://github.com/silverstripe/silverstripe-cms/commit/3d0178ebc0b7408442ad2532f998ed47839e7117) Use correct formaction for doRollback exemption (Damian Mooyman)
+ * 2016-01-24 [d8e354d](https://github.com/silverstripe/silverstripe-framework/commit/d8e354d144383fb6459adf92731853d2e54268d6) PHPDocs on DataList::getIDList() and UnsavedRelationList::getIDList() (Damian Mooyman)
+ * 2016-01-22 [bf8bf5e](https://github.com/silverstripe/silverstripe-framework/commit/bf8bf5e4d558126bb99ea63881f1885faafddd3d) Prevent Versioned::doRollbackTo from creating incorrect versions on subclasses of Versioned DataObjects (Damian Mooyman)
+ * 2016-01-21 [cca7129](https://github.com/silverstripe/silverstripe-framework/commit/cca7129385dbb3be1001a8861423c2cf490f02d4) Revert lost documentation (Damian Mooyman)
+ * 2016-01-11 [85ba918](https://github.com/silverstripe/silverstripe-framework/commit/85ba918a54f51dd524d45f2c93172a18421ae3bf) Update field IDs for file link (fixes silverstripe/silverstripe-cms#1307) (Loz Calver)
+ * 2016-01-11 [d637141](https://github.com/silverstripe/silverstripe-cms/commit/d6371414876e32e7369ec0219a57d2186cfe3f0f) preg_quote() anchors in SiteTreeLinkTracking (fixes #1359) (Loz Calver)
+ * 2016-01-05 [00544ff](https://github.com/silverstripe/silverstripe-framework/commit/00544ff100048afdb7ccb1905304dddf8ab3205a) session_regenerate_id uses config system (Daniel Hensby)
+ * 2016-01-05 [4335d8e](https://github.com/silverstripe/silverstripe-framework/commit/4335d8ed221a2b402299b32e31f97fc2956ec161) Members with no ID inherit logged in user permission (Daniel Hensby)
+ * 2015-12-15 [afbb5cf](https://github.com/silverstripe/silverstripe-framework/commit/afbb5cfed4d29aea5868f0f12cd735dc5abe10d3) Vimeo oEmbed endpoint redirecting to no www (UndefinedOffset)
+ * 2015-12-14 [d265c9b](https://github.com/silverstripe/silverstripe-framework/commit/d265c9b733ddac27d6df286ce000b09e1c69b986) Allow omitting a value for OptionsetField submissions (fixes #4824) (Loz Calver)
+ * 2015-12-11 [5a21b2f](https://github.com/silverstripe/silverstripe-framework/commit/5a21b2fb15ed9c675594f0f990765bd4f97155c7) Guard against users being added to all groups on unsaved Group. (Mateusz Uzdowski)
+ * 2015-11-27 [94742fa](https://github.com/silverstripe/silverstripe-framework/commit/94742fa3e2efad8f77f4acd1f9d06bf74916c5e6) Revert method visibility regression (Damian Mooyman)
+ * 2015-11-18 [e9b833f](https://github.com/silverstripe/silverstripe-framework/commit/e9b833f5f0f989af8d611f8cfe71f0b0e2cb0159) ConfirmedPassword field correctly reports mismatching passwords (Christopher Darling)
+ * 2015-11-17 [68d99be](https://github.com/silverstripe/silverstripe-framework/commit/68d99be24b63a933f041cd80a248a7b7fa8d588c) Hidden errors for composite fields nested inside FieldGroups (fixes #4773) (Loz Calver)
+ * 2015-11-17 [97e90b8](https://github.com/silverstripe/silverstripe-cms/commit/97e90b8ebd8078bb60ecea66bdd3761380f93a61) RedirectorPage toggles not working (fixes #1328) (Loz Calver)
+ * 2015-11-17 [b624eb9](https://github.com/silverstripe/silverstripe-cms/commit/b624eb98f1d1ff36811a3294ad29b31a50683d60) Setting target for unwritten VirtualPage breaks write (Loz Calver)
+ * 2015-11-16 [2983d82](https://github.com/silverstripe/silverstripe-cms/commit/2983d823d1eef293ef11aac9e01336e23ed52b59) Ensure VirtualPage forwards request/response data to virtual controllers (fixes #1329) (Loz Calver)
+ * 2015-11-12 [fea1158](https://github.com/silverstripe/silverstripe-framework/commit/fea1158d193ed4d037df94101e3b3f2d24a6ce49) Fix print button only displaying first page (Damian Mooyman)
+ * 2015-11-11 [a40812a](https://github.com/silverstripe/silverstripe-framework/commit/a40812ac3320d27f243ef0ed54aa003fc53720b6) Don’t reuse DBConnector (fixes #4735) (Sam Minnee)
+ * 2015-11-05 [f577ecb](https://github.com/silverstripe/silverstripe-framework/commit/f577ecb81149d0d09dc846204f17b2153a244b5a) prevent use cache on browser back button (Igor Nadj)
diff --git a/docs/en/04_Changelogs/3.3.0.md b/docs/en/04_Changelogs/3.3.0.md
index 0c56d7686..9b1db9676 100644
--- a/docs/en/04_Changelogs/3.3.0.md
+++ b/docs/en/04_Changelogs/3.3.0.md
@@ -20,3 +20,64 @@ mode of the site frontend using the `?stage` querystring parameter.
This permission can be customised by altering the `Versioned.non_live_permissions`
config by assigning a different set of permissions.
+
+
+## Change Log
+
+### Security
+
+ * 2016-02-17 [893e497](https://github.com/silverstripe/silverstripe-framework/commit/893e49703de4aa1855b5364919cbb0826f754fbf) Hostname, IP and Protocol Spoofing through HTTP Headers (Ingo Schommer) - See [ss-2016-003](http://www.silverstripe.org/download/security-releases/ss-2016-003)
+ * 2016-02-17 [3398f67](https://github.com/silverstripe/silverstripe-framework/commit/3398f670d881447f8777b567f1ead7c0d8d253f5) Block unauthenticated access to dev/build/defaults (Damian Mooyman) - See [ss-2015-028](http://www.silverstripe.org/download/security-releases/ss-2015-028)
+ * 2016-02-17 [56e92f5](https://github.com/silverstripe/silverstripe-framework/commit/56e92f5a32e45849cc9361c8603c31d7010c9d36) Ensure Gridfield actions respect CSRF (Damian Mooyman) - See [ss-2016-002](http://www.silverstripe.org/download/security-releases/ss-2016-002)
+
+### API Changes
+
+ * 2015-12-07 [38e154a](https://github.com/silverstripe/silverstripe-framework/commit/38e154af0aae89a36f4d3906612ea4bbbf726177) Disable get parameter access to site stage mode (Damian Mooyman)
+ * 2015-12-02 [5353ac5](https://github.com/silverstripe/silverstripe-cms/commit/5353ac5315703240540c9cde0f5c8eeb5571bc19) Refactor versioned security into core module (Damian Mooyman)
+ * 2015-12-02 [6089a7c](https://github.com/silverstripe/silverstripe-framework/commit/6089a7c5bd25d6591deb154f1a34908fa91ac198) Create default security permission model for versioned data objects (Damian Mooyman)
+ * 2015-11-26 [6266f90](https://github.com/silverstripe/silverstripe-framework/commit/6266f909e0c098652582af44ea64f031ea9cdcea) Increased Permission.Code db field to 255 characters (Novusvetus)
+ * 2015-07-20 [ea9434f](https://github.com/silverstripe/silverstripe-framework/commit/ea9434ffeba8d5fbb1dfe38d76f3fed403a9886e) Lazy load template parser (Loz Calver)
+
+### Features and Enhancements
+
+ * 2015-12-14 [9467ab9](https://github.com/silverstripe/silverstripe-framework/commit/9467ab9a7e717cece3cee1693b16a055b58526ef) Implement unshift() in field list classes (closes #4834) (Loz Calver)
+ * 2015-12-01 [f7c270a](https://github.com/silverstripe/silverstripe-framework/commit/f7c270a3bad984910fa84f552dfa8b99324afb16) Use Config for determining Vary header (Marcus Nyeholt)
+ * 2015-11-10 [603cacc](https://github.com/silverstripe/silverstripe-framework/commit/603caccb90006b3a0592b129687659571112b9a8) CurrencyField to use Currency.currency_symbol (muskie9)
+ * 2015-09-25 [5c04dc5](https://github.com/silverstripe/silverstripe-framework/commit/5c04dc5d673aa11249310bcb6e382db4ee2bff7f) - Added new method to display the number of total items in a paginated list within templates (Marco Kernler)
+ * 2015-08-14 [1b57e0c](https://github.com/silverstripe/silverstripe-framework/commit/1b57e0ca5bdb5d80d6f78686669441ad8b2c9420) implement getter and setter usage for response (Stevie Mayhew)
+
+### Bugfixes
+
+ * 2016-02-09 [2ad490c](https://github.com/silverstripe/silverstripe-cms/commit/2ad490c3e2d256d8dcd16398631c114aa2a3370e) Prevent folders deleted on the filesystem from breaking asset interface (Damian Mooyman)
+ * 2016-01-22 [f80467a](https://github.com/silverstripe/silverstripe-cms/commit/f80467a74859fba58be835a878ceddbbb4601b42) Don't keep stale treeview data when refreshing Content area (Damian Mooyman)
+ * 2016-01-21 [e364fdb](https://github.com/silverstripe/silverstripe-cms/commit/e364fdb794896b5c6b4810d84c0dfac75d80b53b) Fix incorrect "Add Page" button selector (Damian Mooyman)
+ * 2016-01-20 [abc5556](https://github.com/silverstripe/silverstripe-cms/commit/abc5556520f891d0e3f5cf3d2c3838a194ac5335) Fix legacy breadcrumbs appearing on page save (Damian Mooyman)
+ * 2016-01-20 [df76d78](https://github.com/silverstripe/silverstripe-framework/commit/df76d783fe1f7baaeed67a7c6d63235facd364cd) Fix VersionedTest sometimes failing given certain querystring arguments (Damian Mooyman)
+ * 2016-01-20 [7c4e6f4](https://github.com/silverstripe/silverstripe-cms/commit/7c4e6f4b60567268ed879081823598438c90e729) prevent "Home page" being selected when no selection was made (Damian Mooyman)
+ * 2016-01-02 [b30d335](https://github.com/silverstripe/silverstripe-cms/commit/b30d33585f4640950dc573b9fa283c0db7b5f14c) Adding context parameter to canCreate-check in getClassDropdown of SiteTree (fixes #1334) (Stephan Bauer)
+ * 2016-01-02 [95e96fa](https://github.com/silverstripe/silverstripe-framework/commit/95e96fa2b2d0db9e26f8c716ee3d5e1a26ee09df) jquery.jstree patched to improve drag-and-drop handling (fixes #4881) (Stephan Bauer)
+ * 2015-12-22 [706877d](https://github.com/silverstripe/silverstripe-framework/commit/706877d72e6d64fd1093aa538cebad2311cbeca9) Get locale from <html> element for i18n.js (fixes #4854) (Loz Calver)
+ * 2015-12-22 [54ae002](https://github.com/silverstripe/silverstripe-cms/commit/54ae002d193d7677ff7a99527b37cbb6faa09343) FIx merge regressions in versioned tests (Damian Mooyman)
+ * 2015-12-22 [fce8251](https://github.com/silverstripe/silverstripe-framework/commit/fce82519bd6fcc313677b3687852ce15a3d5d202) Workaround for issues in testing version (Damian Mooyman)
+ * 2015-12-17 [36241d5](https://github.com/silverstripe-labs/silverstripe-reports/commit/36241d52a08ebce841f50fff91f3e4f4ac591be4) Fix regressions is SS_Report::canView (Damian Mooyman)
+ * 2015-12-15 [cd66917](https://github.com/silverstripe/silverstripe-framework/commit/cd66917a867275f3baf4c07efe2513db1ac92822) Vimeo oEmbed endpoint redirecting to no www (UndefinedOffset)
+ * 2015-12-15 [5d0f833](https://github.com/silverstripe-labs/silverstripe-reports/commit/5d0f833a397a2ce937e25b6a7c0350fdabdac63c) SS_Report canView should check permissions (Christopher Darling)
+ * 2015-12-09 [fa0160a](https://github.com/silverstripe/silverstripe-framework/commit/fa0160a874c536528d8300e034a7aa8bb6e23989) Fix regression in canViewStage (Damian Mooyman)
+ * 2015-11-24 [15ae37c](https://github.com/silverstripe/silverstripe-framework/commit/15ae37cf0351b654b5115183ab5a991c316e17e0) Image_Cached record class name (Jonathon Menz)
+ * 2015-10-31 [275ecfd](https://github.com/silverstripe/silverstripe-framework/commit/275ecfd8a95d4f7a025bb5025bb8d729a0e9eb70) Use `Object->hasMethod()` instead of `method_exists()` (madmatt)
+ * 2015-10-07 [71defe7](https://github.com/silverstripe/silverstripe-siteconfig/commit/71defe79b3e4fe7343f892ddf3aa8654725202c4) for #5 to facilitate validation on SiteConfig via DataExtension's. (Patrick Nelson)
+ * 2015-10-06 [a71d99c](https://github.com/silverstripe/silverstripe-framework/commit/a71d99cf8445a906ccd9b13242d36ae1e6a75d74) for #4663 ensuring return values from TabSet are retained from parent. Removing useless override. Cleaning up documentation in TabSet and return types. (Patrick Nelson)
+ * 2015-10-05 [12c4239](https://github.com/silverstripe/silverstripe-framework/commit/12c423909f721c6f5223007ad5e7ba6c162d63a4) (partial) for #3181 where non-submit buttons are being activated on "enter" key press (relates to CMS issue at https://github.com/silverstripe/silverstripe-cms/issues/1288). (Patrick Nelson)
+ * 2015-10-05 [332e490](https://github.com/silverstripe/silverstripe-cms/commit/332e4901478bf76705c7175e4af10b91d4c3b30f) (partial) for #1288 where non-submit buttons are being activated on "enter" key press (relates to framework issue at https://github.com/silverstripe/silverstripe-framework/issues/3181). (Patrick Nelson)
+ * 2015-10-05 [4a70ffe](https://github.com/silverstripe/silverstripe-framework/commit/4a70ffea0687c8c83b6210856e4c10f5aff0a883) Typo in cur methods PHPDoc (Corey Sewell)
+ * 2015-09-29 [5224fc4](https://github.com/silverstripe/silverstripe-framework/commit/5224fc460c6155c4f2253f42d88729b8f31066f6) Permission::checkMember() use of undefined variable $codes (Manuel Teuber)
+ * 2015-09-24 [c0be44d](https://github.com/silverstripe/silverstripe-framework/commit/c0be44d238c45853503fe1550fba0460a9a0f05c) fix response regression in initiation of request handler (Stevie Mayhew)
+ * 2015-09-17 [c9ba6e5](https://github.com/silverstripe/silverstripe-framework/commit/c9ba6e5d0064bfb09ebdb9e5f7054f8c3179f99a) Fix ClassInfo::table_for_object_field (Damian Mooyman)
+ * 2015-09-11 [5cc0878](https://github.com/silverstripe/silverstripe-framework/commit/5cc0878dc1feead47ead82c8f2beca02eefa102b) for #4597: Ensuring GridFieldConfig_RelationEditor is instantiated via Injector, not via "new" keyword. (Patrick Nelson)
+ * 2015-09-02 [2ae5d83](https://github.com/silverstripe/silverstripe-framework/commit/2ae5d83f08b994458aa93625e4ec7cb7f258bbae) Resampled images inherit source properties (Jonathon Menz)
+ * 2015-08-24 [80ce549](https://github.com/silverstripe/silverstripe-framework/commit/80ce5498d84088f8992de3f979071456e7d71746) disable archived pages from being droppable (Damian Mooyman)
+ * 2015-08-21 [b14794b](https://github.com/silverstripe/silverstripe-framework/commit/b14794b780b30d5a6d39df9ed080135ff25045a8) Fix bulk actions making sitetree unclickable (Damian Mooyman)
+ * 2015-08-19 [a19fe39](https://github.com/silverstripe/silverstripe-framework/commit/a19fe39301f8a6a2e80e9a9d294c425b8699dc0c) Avoid PHP 5.6 deprecation with access to HTTP_RAW_POST_DATA. Fixed #4511 (Sam Minnee)
+ * 2015-07-31 [6a45f4a](https://github.com/silverstripe/silverstripe-framework/commit/6a45f4a1e125b1a75d042e59b38824b24fd3cd0f) fix mismatched quotes (Damian Mooyman)
+ * 2015-06-15 [ca039e1](https://github.com/silverstripe/silverstripe-framework/commit/ca039e15ef7306d7b56d64d93892d2fb6173fcf7) Fix regressions in changes to batch action feature (David Craig)
+ * 2015-06-11 [8a4c518](https://github.com/silverstripe/silverstripe-framework/commit/8a4c51893b345f7653e77acdd3667bbe61346784) allow for increase_time_limit_to to work if $_increase_time_limit_max is not yet set (Stevie Mayhew)
diff --git a/docs/en/04_Changelogs/rc/3.2.2-rc1.md b/docs/en/04_Changelogs/rc/3.2.2-rc1.md
new file mode 100644
index 000000000..c0d18aec4
--- /dev/null
+++ b/docs/en/04_Changelogs/rc/3.2.2-rc1.md
@@ -0,0 +1,30 @@
+# 3.2.2-rc1
+
+
+
+## Change Log
+
+### Bugfixes
+
+ * 2016-02-15 [8771859](https://github.com/silverstripe/silverstripe-framework/commit/87718597e8f04872c285808d0666fbb69c5100ba) "where" method in SQLUpdate Example (Richard Rudy)
+ * 2016-01-28 [3fcf1e2](https://github.com/silverstripe/silverstripe-framework/commit/3fcf1e2c98629dcd0048ff9447bad4cd30b4bf95) edge case on many many extra fields (fixes 4991) (Mark Stephens)
+ * 2016-01-27 [3d0178e](https://github.com/silverstripe/silverstripe-cms/commit/3d0178ebc0b7408442ad2532f998ed47839e7117) Use correct formaction for doRollback exemption (Damian Mooyman)
+ * 2016-01-24 [d8e354d](https://github.com/silverstripe/silverstripe-framework/commit/d8e354d144383fb6459adf92731853d2e54268d6) PHPDocs on DataList::getIDList() and UnsavedRelationList::getIDList() (Damian Mooyman)
+ * 2016-01-22 [bf8bf5e](https://github.com/silverstripe/silverstripe-framework/commit/bf8bf5e4d558126bb99ea63881f1885faafddd3d) Prevent Versioned::doRollbackTo from creating incorrect versions on subclasses of Versioned DataObjects (Damian Mooyman)
+ * 2016-01-21 [cca7129](https://github.com/silverstripe/silverstripe-framework/commit/cca7129385dbb3be1001a8861423c2cf490f02d4) Revert lost documentation (Damian Mooyman)
+ * 2016-01-11 [85ba918](https://github.com/silverstripe/silverstripe-framework/commit/85ba918a54f51dd524d45f2c93172a18421ae3bf) Update field IDs for file link (fixes silverstripe/silverstripe-cms#1307) (Loz Calver)
+ * 2016-01-11 [d637141](https://github.com/silverstripe/silverstripe-cms/commit/d6371414876e32e7369ec0219a57d2186cfe3f0f) preg_quote() anchors in SiteTreeLinkTracking (fixes #1359) (Loz Calver)
+ * 2016-01-05 [00544ff](https://github.com/silverstripe/silverstripe-framework/commit/00544ff100048afdb7ccb1905304dddf8ab3205a) session_regenerate_id uses config system (Daniel Hensby)
+ * 2016-01-05 [4335d8e](https://github.com/silverstripe/silverstripe-framework/commit/4335d8ed221a2b402299b32e31f97fc2956ec161) Members with no ID inherit logged in user permission (Daniel Hensby)
+ * 2015-12-15 [afbb5cf](https://github.com/silverstripe/silverstripe-framework/commit/afbb5cfed4d29aea5868f0f12cd735dc5abe10d3) Vimeo oEmbed endpoint redirecting to no www (UndefinedOffset)
+ * 2015-12-14 [d265c9b](https://github.com/silverstripe/silverstripe-framework/commit/d265c9b733ddac27d6df286ce000b09e1c69b986) Allow omitting a value for OptionsetField submissions (fixes #4824) (Loz Calver)
+ * 2015-12-11 [5a21b2f](https://github.com/silverstripe/silverstripe-framework/commit/5a21b2fb15ed9c675594f0f990765bd4f97155c7) Guard against users being added to all groups on unsaved Group. (Mateusz Uzdowski)
+ * 2015-11-27 [94742fa](https://github.com/silverstripe/silverstripe-framework/commit/94742fa3e2efad8f77f4acd1f9d06bf74916c5e6) Revert method visibility regression (Damian Mooyman)
+ * 2015-11-18 [e9b833f](https://github.com/silverstripe/silverstripe-framework/commit/e9b833f5f0f989af8d611f8cfe71f0b0e2cb0159) ConfirmedPassword field correctly reports mismatching passwords (Christopher Darling)
+ * 2015-11-17 [68d99be](https://github.com/silverstripe/silverstripe-framework/commit/68d99be24b63a933f041cd80a248a7b7fa8d588c) Hidden errors for composite fields nested inside FieldGroups (fixes #4773) (Loz Calver)
+ * 2015-11-17 [97e90b8](https://github.com/silverstripe/silverstripe-cms/commit/97e90b8ebd8078bb60ecea66bdd3761380f93a61) RedirectorPage toggles not working (fixes #1328) (Loz Calver)
+ * 2015-11-17 [b624eb9](https://github.com/silverstripe/silverstripe-cms/commit/b624eb98f1d1ff36811a3294ad29b31a50683d60) Setting target for unwritten VirtualPage breaks write (Loz Calver)
+ * 2015-11-16 [2983d82](https://github.com/silverstripe/silverstripe-cms/commit/2983d823d1eef293ef11aac9e01336e23ed52b59) Ensure VirtualPage forwards request/response data to virtual controllers (fixes #1329) (Loz Calver)
+ * 2015-11-12 [fea1158](https://github.com/silverstripe/silverstripe-framework/commit/fea1158d193ed4d037df94101e3b3f2d24a6ce49) Fix print button only displaying first page (Damian Mooyman)
+ * 2015-11-11 [a40812a](https://github.com/silverstripe/silverstripe-framework/commit/a40812ac3320d27f243ef0ed54aa003fc53720b6) Don’t reuse DBConnector (fixes #4735) (Sam Minnee)
+ * 2015-11-05 [f577ecb](https://github.com/silverstripe/silverstripe-framework/commit/f577ecb81149d0d09dc846204f17b2153a244b5a) prevent use cache on browser back button (Igor Nadj)
diff --git a/docs/en/04_Changelogs/rc/3.2.2-rc2.md b/docs/en/04_Changelogs/rc/3.2.2-rc2.md
new file mode 100644
index 000000000..41a03f1f8
--- /dev/null
+++ b/docs/en/04_Changelogs/rc/3.2.2-rc2.md
@@ -0,0 +1,11 @@
+# 3.2.2-rc2
+
+
+
+## Change Log
+
+### Security
+
+ * 2016-02-17 [faa94d5](https://github.com/silverstripe/silverstripe-framework/commit/faa94d51d570788dcebc2f2ef6e9de4d179ce1e4) Hostname, IP and Protocol Spoofing through HTTP Headers (Ingo Schommer) - See [ss-2016-003](http://www.silverstripe.org/download/security-releases/ss-2016-003)
+ * 2016-02-17 [15d4db3](https://github.com/silverstripe/silverstripe-framework/commit/15d4db3b4a7dbc9a7e089f9329a396f8408ed7d9) Block unauthenticated access to dev/build/defaults (Damian Mooyman) - See [ss-2015-028](http://www.silverstripe.org/download/security-releases/ss-2015-028)
+ * 2016-02-17 [e2c77c5](https://github.com/silverstripe/silverstripe-framework/commit/e2c77c5a8f13e901c51a3684210811559b592f0c) Ensure Gridfield actions respect CSRF (Damian Mooyman) - See [ss-2016-002](http://www.silverstripe.org/download/security-releases/ss-2016-002)
diff --git a/docs/en/04_Changelogs/rc/3.3.0-rc3.md b/docs/en/04_Changelogs/rc/3.3.0-rc3.md
new file mode 100644
index 000000000..c5487e2a6
--- /dev/null
+++ b/docs/en/04_Changelogs/rc/3.3.0-rc3.md
@@ -0,0 +1,11 @@
+# 3.3.0-rc3
+
+
+
+## Change Log
+
+### Security
+
+ * 2016-02-17 [893e497](https://github.com/silverstripe/silverstripe-framework/commit/893e49703de4aa1855b5364919cbb0826f754fbf) Hostname, IP and Protocol Spoofing through HTTP Headers (Ingo Schommer) - See [ss-2016-003](http://www.silverstripe.org/download/security-releases/ss-2016-003)
+ * 2016-02-17 [3398f67](https://github.com/silverstripe/silverstripe-framework/commit/3398f670d881447f8777b567f1ead7c0d8d253f5) Block unauthenticated access to dev/build/defaults (Damian Mooyman) - See [ss-2015-028](http://www.silverstripe.org/download/security-releases/ss-2015-028)
+ * 2016-02-17 [56e92f5](https://github.com/silverstripe/silverstripe-framework/commit/56e92f5a32e45849cc9361c8603c31d7010c9d36) Ensure Gridfield actions respect CSRF (Damian Mooyman) - See [ss-2016-002](http://www.silverstripe.org/download/security-releases/ss-2016-002)
diff --git a/docs/en/05_Contributing/00_Issues_and_Bugs.md b/docs/en/05_Contributing/00_Issues_and_Bugs.md
index 08fb127b4..d27fe24ab 100644
--- a/docs/en/05_Contributing/00_Issues_and_Bugs.md
+++ b/docs/en/05_Contributing/00_Issues_and_Bugs.md
@@ -11,7 +11,7 @@ well written bug reports can be half of the solution already!
* [Framework Bugtracker](https://github.com/silverstripe/silverstripe-framework/issues)
* [CMS Bugtracker](https://github.com/silverstripe/silverstripe-cms/issues)
* [Documentation Bugtracker](https://github.com/silverstripe/silverstripe-framework/issues)
- * Search on [http://silverstripe.org/modules](http://silverstripe.org/modules) for module-specific bugtrackers
+ * Search on [http://addons.silverstripe.org/](http://addons.silverstripe.org/) for module-specific bugtrackers
* Request features: [UserVoice](http://silverstripe.uservoice.com).
Before submitting a bug:
@@ -19,7 +19,7 @@ Before submitting a bug:
* Ask for assistance on the [forums](http://www.silverstripe.org/community/forums/), [core mailinglist](http://groups.google.com/group/silverstripe-dev) or on [IRC](http://irc.silverstripe.org/) if you're unsure if its really a bug.
* Search for similar, existing tickets
* Is this a security issue? Please follow our separate reporting guidelines below.
- * Is this a issue with the core framework or cms? Modules have their own issue trackers (see [silverstripe.org/modules](http://www.silverstripe.org/modules/))
+ * Is this a issue with the core framework or cms? Modules have their own issue trackers (see [http://addons.silverstripe.org/](http://addons.silverstripe.org/))
* Try to reproduce your issue on a [clean installation](/getting_started/composer#using-development-versions), maybe the bug has already been fixed on an unreleased branch?
* The bugtracker is not the place to discuss enhancements, please use the forums or mailinglist.
Only log enhancement tickets if they gather a large interest in the community
diff --git a/docs/en/05_Contributing/01_Code.md b/docs/en/05_Contributing/01_Code.md
index fc5fcf9ea..f77573e37 100644
--- a/docs/en/05_Contributing/01_Code.md
+++ b/docs/en/05_Contributing/01_Code.md
@@ -161,7 +161,7 @@ Most importantly: Keep the first line short, and add more detail below.
This ensures commits are easy to browse, and look nice on github.com
(more info about [proper git commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)).
-As we automatically generate [changelogs](http://doc.silverstripe.org/sapphire/en/trunk/changelogs/) from them, we need a way to categorize and filter.
+As we automatically generate [changelogs](http://localhost/SpiritLevel/SS/doc.silverstripe.org/en/changelogs/) from them, we need a way to categorize and filter.
Please prefix **noteworthy** commit messages with one of the following tags:
* `NEW` New feature or major enhancement (both for users and developers)
diff --git a/docs/en/05_Contributing/03_Release_Process.md b/docs/en/05_Contributing/03_Release_Process.md
index 6e642c230..6e7d065e6 100644
--- a/docs/en/05_Contributing/03_Release_Process.md
+++ b/docs/en/05_Contributing/03_Release_Process.md
@@ -51,7 +51,7 @@ so we strive for giving ample warning on any upcoming changes through a "depreca
How to deprecate an API:
* Add a `@deprecated` item to the docblock tag, with a `{@link }` item pointing to the new API to use.
-* Update the deprecated code to throw a `[api:Deprecation::notice()]` error.
+* Update the deprecated code to throw a [api:Deprecation::notice()] error.
* Both the docblock and error message should contain the **target version** where the functionality is removed.
So, if you're committing the change to a *3.1* minor release, the target version will be *4.0*.
* Deprecations should not be committed to patch releases
diff --git a/docs/en/05_Contributing/04_Making_A_SilverStripe_Core_Release.md b/docs/en/05_Contributing/04_Making_A_SilverStripe_Core_Release.md
index aeb770cea..c016b595f 100644
--- a/docs/en/05_Contributing/04_Making_A_SilverStripe_Core_Release.md
+++ b/docs/en/05_Contributing/04_Making_A_SilverStripe_Core_Release.md
@@ -73,7 +73,7 @@ the [core committers](core_committers), who will assist with setting up your cre
* Admin permissions on [transifex](https://www.transifex.com/silverstripe/).
* AWS write permissions on the `silverstripe-ssorg-releases` s3 bucket.
* Permission on [silverstripe release announcement](https://groups.google.com/forum/#!forum/silverstripe-announce).
-* Moderator permissions in the #silverstripe [IRC channel]((http://www.silverstripe.org/community/contributing-to-silverstripe/irc-channel/))
+* Moderator permissions in the #silverstripe [IRC channel](http://www.silverstripe.org/community/contributing-to-silverstripe/irc-channel/)
### First time setup: Security releases
@@ -333,7 +333,7 @@ will need to be regularly updated.
* Create a release announcement forum sticky on the
[releases and announcements](http://www.silverstripe.org/community/forums/releases-and-announcements/)
forum category. Make this a global read-only sticky, and un-sticky any older release.
-* Update the #silverstripe [IRC](http://www.silverstripe.org/community/contributing-to-silverstripe/irc-channel/) topic to include the new release version.
+* Update the #silverstripe [IRC](https://www.silverstripe.org/community/contributing-to-silverstripe/irc-channel/) topic to include the new release version.
### Stage 4: Web platform installer release
@@ -342,8 +342,9 @@ The web platform installer is available [on the web app gallery](http://www.micr
In order to update this you will need a Microsoft live account, and have it authorised
by SilverStripe staff in order to publish these releases.
+
To update this release there is an additional download tool at
-[https://code.platform.silverstripe.com/silverstripe/webpi](https://code.platform.silverstripe.com/silverstripe/webpi)
+`[https://code.platform.silverstripe.com/silverstripe/webpi](https://code.platform.silverstripe.com/silverstripe/webpi)`
which will guide you through the process of generating a new zip release.
./make-package 3.2.4 3.2.4
@@ -363,6 +364,7 @@ to submit a new version, including:
* [Release Process](release_process)
* [Translation Process](translation_process)
* [Core committers](core_committers)
+* [WebPI Installer](https://docs.silverstripe.org/en/getting_started/installation/other_installation_options/windows_platform_installer/)
If at any time a release runs into an unsolveable problem contact the
core committers on the [discussion group](https://groups.google.com/forum/#!forum/silverstripe-committers)
diff --git a/docs/en/05_Contributing/05_Documentation.md b/docs/en/05_Contributing/05_Documentation.md
index 6c0c36552..82b6530b0 100644
--- a/docs/en/05_Contributing/05_Documentation.md
+++ b/docs/en/05_Contributing/05_Documentation.md
@@ -37,7 +37,7 @@ If you submit a new feature or an API change, we strongly recommend that your pa
## Repositories
* End-user help: [userhelp.silverstripe.org](http://github.com/silverstripe/userhelp.silverstripe.org)
-* Developer guides: [docs.silverstripe.org](http://github.com/silverstripe/docs.silverstripe.org)
+* Developer guides: [docs.silverstripe.org](http://github.com/silverstripe/doc.silverstripe.org)
* Developer API documentation: [api.silverstripe.org](http://github.com/silverstripe/api.silverstripe.org)
## Source control
diff --git a/docs/en/05_Contributing/06_Translations.md b/docs/en/05_Contributing/06_Translations.md
index 9312c5153..8d2f13066 100644
--- a/docs/en/05_Contributing/06_Translations.md
+++ b/docs/en/05_Contributing/06_Translations.md
@@ -59,7 +59,7 @@ Currently translated entities are not directly factored into code (for security
you can't see them straight away.
It is strongly encouraged that you check your translation this way, as its a good way to double check your translation
-works in the right context. Please use our [daily-builds](http://www.silverstripe.org/daily-builds/) for your local
+works in the right context. Please use our `[daily-builds](http://www.silverstripe.org/daily-builds/)` for your local
installation, to ensure you're looking at the most up to date interface. See "Download Translations" above to find out
how to retrieve the latest translation files.
@@ -135,7 +135,7 @@ This also applies for any modules staying compatible with SilverStripe 2.x.
## Contact
Translators have their own [mailinglist](https://groups.google.com/forum/#!forum/silverstripe-translators), but you can
-also reach a core member on [IRC](http://silverstripe.org/irc). The transifex.com interface has a built-in discussion
+also reach a core member on [IRC](https://irc.silverstripe.org). The transifex.com interface has a built-in discussion
board if you have specific comments on a translation.
## Related
@@ -143,4 +143,4 @@ board if you have specific comments on a translation.
* [i18n](/developer_guides/i18n): Developer-level documentation of Silverstripe's i18n capabilities
* [Translation Process](translation_process): Information about managing translations for the core team and/or module maintainers.
* [translatable](https://github.com/silverstripe/silverstripe-translatable): DataObject-interface powering the website-content translations
- * ["Translatable ModelAdmin" module](http://silverstripe.org/translatablemodeladmin-module/): An extension which allows translations of DataObjects inside ModelAdmin
+ * `["Translatable ModelAdmin" module](http://silverstripe.org/translatablemodeladmin-module/)`: An extension which allows translations of DataObjects inside ModelAdmin
diff --git a/docs/en/05_Contributing/07_Translation_Process.md b/docs/en/05_Contributing/07_Translation_Process.md
index 713d8f797..48c844441 100644
--- a/docs/en/05_Contributing/07_Translation_Process.md
+++ b/docs/en/05_Contributing/07_Translation_Process.md
@@ -130,4 +130,4 @@ files back into the JS files SilverStripe can actually read. This requires an in
* [i18n](/developer_guides/i18n/): Developer-level documentation of Silverstripe's i18n capabilities
* [Contributing Translations](/contributing/translations): Information for translators looking to contribute translations of the SilverStripe UI.
* [translatable](https://github.com/silverstripe/silverstripe-translatable): DataObject-interface powering the website-content translations
- * ["Translatable ModelAdmin" module](http://silverstripe.org/translatablemodeladmin-module/): An extension which allows translations of DataObjects inside ModelAdmin
+ * `["Translatable ModelAdmin" module](http://silverstripe.org/translatablemodeladmin-module/)`: An extension which allows translations of DataObjects inside ModelAdmin
diff --git a/docs/en/05_Contributing/09_Code_of_conduct.md b/docs/en/05_Contributing/09_Code_of_conduct.md
index 64e0bb167..4aaff9614 100644
--- a/docs/en/05_Contributing/09_Code_of_conduct.md
+++ b/docs/en/05_Contributing/09_Code_of_conduct.md
@@ -57,4 +57,4 @@ https://www.djangoproject.com/conduct/
http://web.archive.org/web/20141109123859/http://speakup.io/coc.html
-http://www.crnhq.org/pages.php?pID=10
+http://www.crnhq.org/files/66138/files/Handouts%20and%20Posters/ResolveTheConflictGuideposter.pdf
diff --git a/docs/en/index.md b/docs/en/index.md
index eb6c56441..12d168631 100644
--- a/docs/en/index.md
+++ b/docs/en/index.md
@@ -20,7 +20,7 @@ community. There are also several other websites with SilverStripe documentation
* The [API Documentation](http://api.silverstripe.org/) contains technical reference and class information.
* The [User Help](http://userhelp.silverstripe.com) website contains documentation related to working within the CMS.
-New features, API changes and the development [roadmap](http://www.silverstripe.org/roadmap/) for the product are
+New features, API changes and the development [roadmap](http://www.silverstripe.org/software/roadmap/) for the product are
discussed on the [core mailinglist](https://groups.google.com/forum/#!forum/silverstripe-dev) along with
[UserVoice](http://silverstripe.uservoice.com/forums/251266-new-features).
diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php
index ca9fa7f61..087f9ae34 100644
--- a/forms/gridfield/GridField.php
+++ b/forms/gridfield/GridField.php
@@ -833,6 +833,18 @@ class GridField extends FormField {
*/
public function gridFieldAlterAction($data, $form, SS_HTTPRequest $request) {
$data = $request->requestVars();
+
+ // Protection against CSRF attacks
+ $token = $this
+ ->getForm()
+ ->getSecurityToken();
+ if(!$token->checkRequest($request)) {
+ $this->httpError(400, _t("Form.CSRF_FAILED_MESSAGE",
+ "There seems to have been a technical problem. Please click the back button, ".
+ "refresh your browser, and try again."
+ ));
+ }
+
$name = $this->getName();
$fieldData = null;
diff --git a/javascript/HtmlEditorField.js b/javascript/HtmlEditorField.js
index 47be7b8cc..d0160ea6c 100644
--- a/javascript/HtmlEditorField.js
+++ b/javascript/HtmlEditorField.js
@@ -888,10 +888,11 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
action = "update";
}
- if(href.match(/^mailto:(.*)$/)) {
+ if(href.match(/^mailto:([^?]*)(\?subject=(.*))?$/)) {
return {
LinkType: 'email',
email: RegExp.$1,
+ Subject: decodeURIComponent(RegExp.$3),
Description: title
};
} else if(href.match(/^(assets\/.*)$/) || href.match(/^\[file_link\s*(?:\s*|%20|,)?id=([0-9]+)\]?(#.*)?$/)) {
diff --git a/lang/cs.yml b/lang/cs.yml
index aa4492189..60ec7fad0 100644
--- a/lang/cs.yml
+++ b/lang/cs.yml
@@ -301,7 +301,7 @@ cs:
FROMWEB: 'Z webu'
FindInFolder: 'Hledat ve složce'
IMAGEALT: 'Alternativní text (alt)'
- IMAGEALTTEXT: 'Alternativní text (alt) - bude zobrazen, pokud obrázek nemúže být zobrazen'
+ IMAGEALTTEXT: 'Alternativní text (alt) - bude ukázán, když obrázek nemúže být zobrazen'
IMAGEALTTEXTDESC: 'Zobrazeno na obrazovce, když obrázek nemůže být zobrazen'
IMAGEDIMENSIONS: Rozměry
IMAGEHEIGHTPX: Výška
@@ -336,13 +336,13 @@ cs:
LeftAndMain:
CANT_REORGANISE: 'Nemáte oprávnění měnit stránky nejvyšší úrovně. Vaše změna nebyla uložena.'
DELETED: Smazáno.
- DropdownBatchActionsDefault: 'Vyberte akci...'
+ DropdownBatchActionsDefault: Akce
HELP: Nápověda
PAGETYPE: 'Typ stránky'
PERMAGAIN: 'Byli jste odhlášeni z CMS. Pokud se chcete znovu přihlásit, zadejte níže své uživatelské jméno a heslo.'
PERMALREADY: 'Omlouvám se, ale nemůžete vstoupit do této části CMS. Pokud se chcete přihlásit jako někdo jiný, udělejte tak níže.'
PERMDEFAULT: 'Musíte být přihlášen/a k přístup do oblasti administrace, níže zadejte vaše přihlašovací údaje, prosím.'
- PLEASESAVE: 'Prosím uložte stránku: Tato stránka nemohla být aktualizována, protože ještě nebyla uložena.'
+ PLEASESAVE: 'Prosím uložte stránku: Tato stránka nemohla být aktualizována, ještě nebyla uložena.'
PreviewButton: Náhled
REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.'
SAVEDUP: Uloženo.
diff --git a/lang/de.yml b/lang/de.yml
index 59ba8b332..6bfc998b4 100644
--- a/lang/de.yml
+++ b/lang/de.yml
@@ -1,5 +1,7 @@
de:
AssetAdmin:
+ ALLOWEDEXTS: 'Erlaubte Dateiendungen'
+ HIDEALLOWEDEXTS: 'Verberge erlaubte Dateiendungen'
NEWFOLDER: Neuer Ordner
SHOWALLOWEDEXTS: 'Erlaubte Dateitypen anzeigen'
AssetTableField:
@@ -7,12 +9,14 @@ de:
DIM: Dimensionen
FILENAME: Dateiname
FOLDER: Ordner
+ HEIGHT: Höhe
LASTEDIT: 'Letzte Änderung'
OWNER: Eigentümer
SIZE: 'Größe'
TITLE: Titel
TYPE: 'Typ'
URL: URL
+ WIDTH: Breite
AssetUploadField:
ChooseFiles: 'Dateien auswählen'
DRAGFILESHERE: 'Dateien hier ablegen'
@@ -23,7 +27,9 @@ de:
FILES: Dateien
FROMCOMPUTER: 'Dateien auf Ihrem Computer auswählen'
FROMCOMPUTERINFO: 'Von Ihrem Computer hochladen'
+ REMOVEINFO: 'Entferne diese Datei aus dem Feld'
TOTAL: Insgesamt
+ TOUPLOAD: 'Dateien für den Upload auswählen...'
UPLOADINPROGRESS: 'Bitte warten sie... Upload im Gang'
UPLOADOR: oder
BBCodeParser:
@@ -146,6 +152,7 @@ de:
INVALID_REQUEST: 'Ungültige Anfrage'
DropdownField:
CHOOSE: (Auswahl)
+ CHOOSESEARCH: '(Auswahl und Suche)'
SOURCE_VALIDATION: 'Bitte wählen Sie aus der Liste. {value} ist kein gültiger Wert'
EmailField:
VALIDATION: 'Bitte geben Sie eine E-Mail-Adresse ein'
@@ -293,8 +300,6 @@ de:
FROMWEB: 'Aus dem Web'
FindInFolder: 'In Ordner suchen'
IMAGEALT: 'Alternativtext (alt)'
- IMAGEALTTEXT: 'Alternativer Text (alt) - angezeigt, wenn das Bild nicht dargestellt werden kann'
- IMAGEALTTEXTDESC: 'Wird von Screenreadern vorgelesen oder angezeigt, falls das Bild nicht dargestellt werden kann'
IMAGEDIMENSIONS: Dimensionen
IMAGEHEIGHTPX: Höhe (px)
IMAGETITLE: 'Titeltext (Tooltip) - für zusätzliche Informationen über das Bild'
@@ -326,11 +331,9 @@ de:
CANT_REORGANISE: 'Sie besitzen nicht die benötigten Zugriffsrechte um Seiten der höchsten Ebene zu bearbeiten. Ihre Änderungen wurden nicht gespeichert.'
DELETED: Gelöscht.
HELP: Hilfe
- PAGETYPE: 'Seitentyp'
PERMAGAIN: 'Sie wurden aus dem System ausgeloggt. Falls Sie sich wieder einloggen möchten, geben Sie bitte Benutzernamen und Passwort im untenstehenden Formular an.'
PERMALREADY: 'Leider dürfen Sie diesen Teil des CMS nicht aufrufen. Wenn Sie sich als jemand anderes einloggen wollen, benutzen Sie bitte das nachstehende Formular.'
PERMDEFAULT: 'Sie müssen angemeldet sein, um auf diesen Bereich zugreifen zu können. Bitte geben Sie Ihre Zugangsdaten ein.'
- PLEASESAVE: 'Diese Seite konnte nicht aktualisiert werden weil sie noch nicht gespeichert wurde - bitte speichern.'
PreviewButton: Vorschau
REORGANISATIONSUCCESSFUL: 'Der Seitenbaum wurde erfolgreich sortiert.'
SAVEDUP: Gespeichert.
diff --git a/lang/eo.yml b/lang/eo.yml
index 57195dcc0..0dc9dcd40 100644
--- a/lang/eo.yml
+++ b/lang/eo.yml
@@ -293,8 +293,6 @@ eo:
FROMWEB: 'El la TTT'
FindInFolder: 'Serĉi en dosierujo'
IMAGEALT: 'Alternativa teksto (alt)'
- IMAGEALTTEXT: 'Alternativa teksto (alt) - vidigi ĝin se ne eblas vidigi bildon'
- IMAGEALTTEXTDESC: 'Vidigita al ekranlegiloj aŭ se ne eblas vidii bildon'
IMAGEDIMENSIONS: Dimensioj
IMAGEHEIGHTPX: Alto
IMAGETITLE: 'Titola teksto (ŝpruchelpilo) - por plua informo pri la bildo'
@@ -326,11 +324,9 @@ eo:
CANT_REORGANISE: 'Vi ne rajtas ŝanĝi supronivelajn paĝojn. Via ŝanĝo ne konserviĝis.'
DELETED: Forigita.
HELP: Helpo
- PAGETYPE: 'Tipo de paĝo:'
PERMAGAIN: 'Vin adiaŭis la CMS. Se vi volas denove saluti, enigu salutnomon kaj pasvorton malsupre.'
PERMALREADY: 'Bedaŭrinde vi ne povas aliri tiun parton de la CMS. Se vi volas ensaluti kiel aliulo, faru tion sube.'
PERMDEFAULT: 'Necesas ensaluti por aliri la administran zonon; bonvolu enigi viajn akreditaĵoj sube.'
- PLEASESAVE: 'Bonvolu konservi paĝon: Ne eblis ĝisdatigi ĉi tiun paĝon ĉar ĝi ankoraŭ ne estas konservita.'
PreviewButton: Antaŭvido
REORGANISATIONSUCCESSFUL: 'Sukcese reorganizis la retejan arbon.'
SAVEDUP: Konservita.
diff --git a/lang/es.yml b/lang/es.yml
index d08f5f16c..144c826fe 100644
--- a/lang/es.yml
+++ b/lang/es.yml
@@ -301,8 +301,6 @@ es:
FROMWEB: 'Desde la web'
FindInFolder: 'Buscar en carpeta'
IMAGEALT: 'Texto alternativo (alt)'
- IMAGEALTTEXT: 'Texto alternativo (alt) - es mostrado si la imagen no puede ser visualizada'
- IMAGEALTTEXTDESC: 'Mostrar a los lectores de pantalla o si la imagen no se puede visualizar'
IMAGEDIMENSIONS: Dimensiones
IMAGEHEIGHTPX: Alto
IMAGETITLE: 'Texto del título (tooltip) - para obtener más información acerca de la imagen'
@@ -336,13 +334,10 @@ es:
LeftAndMain:
CANT_REORGANISE: 'Usted no tiene permiso para modificar las páginas de nivel superior. Su modificación no se ha guardado.'
DELETED: Borrado
- DropdownBatchActionsDefault: 'Elegir una acción...'
HELP: Ayuda
- PAGETYPE: 'Tipo de página'
PERMAGAIN: 'Ha sido desconectado del CMS. Si quiere volver a entrar, introduzca su nombre de usuario y contraseña a continuación.'
PERMALREADY: 'Lamentablemente no puede acceder a esta parte del CMS. Si quiere entrar como alguien distinto, hágalo a continuación'
PERMDEFAULT: 'Debes estar conectado para acceder al área de administración; por favor ingresa tus datos a continuación'
- PLEASESAVE: 'Por favor Guarde la Página: Esta página no se ha podido actualizar porque aún no ha sido salvada.'
PreviewButton: Vista previa
REORGANISATIONSUCCESSFUL: 'Reorganizado el árbol del sitio con éxito.'
SAVEDUP: Guardado
diff --git a/lang/fa_IR.yml b/lang/fa_IR.yml
index d67654e93..148e24ac8 100644
--- a/lang/fa_IR.yml
+++ b/lang/fa_IR.yml
@@ -318,9 +318,7 @@ fa_IR:
TITLE: 'آیفریم آپلود عکس'
LeftAndMain:
DELETED: حذف شده
- DropdownBatchActionsDefault: 'انتخاب یک عملیات...'
HELP: کمک
- PAGETYPE: 'نوع صفحه'
PERMAGAIN: 'شما از سیستم مدیریت محتوا خارج شده اید.اگر میخواهید دوباره وارد شوید نام کاربری و رمز عبور خود را در قسمت زیر وارد کنید'
PreviewButton: پیشنمایش
SAVEDUP: ذخیره شده
diff --git a/lang/fi.yml b/lang/fi.yml
index f82b8134c..f469275aa 100644
--- a/lang/fi.yml
+++ b/lang/fi.yml
@@ -299,8 +299,6 @@ fi:
FROMWEB: 'Webistä'
FindInFolder: 'Etsi kansiosta'
IMAGEALT: 'Vaihtoehtoinen teksti (alt)'
- IMAGEALTTEXT: 'Vaihtoehtoinen teksti (alt) - näytetään jos kuvaa ei voida näyttää'
- IMAGEALTTEXTDESC: 'Näytetään ruudunlukuohjelmille tai jos kuvaa ei voi näyttää'
IMAGEDIMENSIONS: Mitat
IMAGEHEIGHTPX: Korkeus
IMAGETITLE: 'Otsikko (tooltip) - kuvan lisätietoja varten'
@@ -333,11 +331,9 @@ fi:
CANT_REORGANISE: 'Sinulla ei ole oikeuksia mennä ylemmän tason sivuille. Muutoksiasi ei tallennettu.'
DELETED: Poistettu.
HELP: Ohje
- PAGETYPE: 'Sivutyyppi'
PERMAGAIN: 'Olet kirjautunut ulos CMS:stä. Jos haluat kirjautua uudelleen sisään, syötä käyttäjätunnuksesi ja salasanasi alla.'
PERMALREADY: 'Pahoittelut, mutta et pääse tähän osaan CMS:ää. Jos haluat kirjautua jonain muuna, voit tehdä sen alta.'
PERMDEFAULT: 'Sinun tulee olla kirjautuneena ylläpito-osioon; syötä tunnuksesi kenttiin.'
- PLEASESAVE: 'Tätä sivua ei voitu päivittää, koska sitä ei ole vielä tallennettu. Tallenna sivu.'
PreviewButton: Esikatselu
REORGANISATIONSUCCESSFUL: 'Hakemistopuu uudelleenjärjestettiin onnistuneesti.'
SAVEDUP: Tallennettu.
diff --git a/lang/lt.yml b/lang/lt.yml
index ef31520dd..c888f76ff 100644
--- a/lang/lt.yml
+++ b/lang/lt.yml
@@ -301,8 +301,6 @@ lt:
FROMWEB: 'Iš interneto'
FindInFolder: 'Rasti kataloge'
IMAGEALT: 'Alternatyvus tekstas (alt)'
- IMAGEALTTEXT: 'Alternatyvus tekstas (alt) - rodomas, jeigu nepavyko parodyti paveikslėlio'
- IMAGEALTTEXTDESC: 'Rodomas, jeigu nepavyko parodyti paveikslėlio'
IMAGEDIMENSIONS: Matmenys
IMAGEHEIGHTPX: Aukštis
IMAGETITLE: 'Pavadinimo tekstas (tooltip) - papildomai informacijai apie paveikslėlį'
@@ -336,13 +334,12 @@ lt:
LeftAndMain:
CANT_REORGANISE: 'Jūs neturite leidimo keisti aukščiausio lygio puslapių. Jūsų pakeitimai neišsaugoti.'
DELETED: Ištrinta.
- DropdownBatchActionsDefault: 'Pasirinkite veiksmą...'
+ DropdownBatchActionsDefault: Veiksmai
HELP: Pagalba
PAGETYPE: 'Puslapio tipas'
PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.'
PERMALREADY: 'Deja, bet Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau.'
PERMDEFAULT: 'Jūs turite būti prisijungę, norėdami pasiekti administravimo zoną; prašome suvesti prisijungimo duomenis į žemiau esančius laukelius.'
- PLEASESAVE: 'Prašome išsaugoti puslapį: Šis puslapis negali būti atnaujintas, nes jis dar nėra išsaugotas.'
PreviewButton: Peržiūra
REORGANISATIONSUCCESSFUL: 'Puslapių medis pertvarkytas sėkmingai.'
SAVEDUP: Išsaugota.
diff --git a/lang/sk.yml b/lang/sk.yml
index c0a94b7d9..9433fb357 100644
--- a/lang/sk.yml
+++ b/lang/sk.yml
@@ -301,8 +301,8 @@ sk:
FROMWEB: 'Z webu'
FindInFolder: 'Vyhľadať v priečinku'
IMAGEALT: 'Atlernatívny text (alt)'
- IMAGEALTTEXT: 'Atlernatívny text (alt) - zobrazí sa, ak obrázok nemože byť zobrazený'
- IMAGEALTTEXTDESC: 'Zobrazí sa na čítačke obrazovky alebo ak obrázok nemôže byť zobrazený'
+ IMAGEALTTEXT: 'Atlernatívny text (alt) - sa zobrazí, ak nemôže byť zobrazený obrázok'
+ IMAGEALTTEXTDESC: 'Zobrazí sa na obrazovke, keď obrázok nemôže byť zobrazený'
IMAGEDIMENSIONS: Rozmery
IMAGEHEIGHTPX: Výška
IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku'
@@ -336,13 +336,13 @@ sk:
LeftAndMain:
CANT_REORGANISE: 'Nemáte oprávnenie meniť stránky najvyššej úrovne. Vaša zmena nebola uložená.'
DELETED: Zmazané.
- DropdownBatchActionsDefault: 'Vybrať akciu...'
+ DropdownBatchActionsDefault: Akcie
HELP: Pomoc
- PAGETYPE: 'Typ stránky'
+ PAGETYPE: 'Typ stránky:'
PERMAGAIN: 'Boli ste odhlásený'
PERMALREADY: 'Je nám ľúto, ale k tejto časti CMS nemáte prístup . Ak sa chcete prihlásiť ako niekto iný, urobte tak nižšie.'
PERMDEFAULT: 'Musíte byť prihlásený/á k prístupu do oblasti administrácie, zadajte vaše prihlasovacie údaje dole, prosím.'
- PLEASESAVE: 'Uložte stránku, prosím. Táto stránka nemôže byť aktualizovaná, pretože ešte nebola uložená.'
+ PLEASESAVE: 'Prosím uložte stránku: Táto stránka nemôže byť aktualizovaná, ešte nebola uložená.'
PreviewButton: Náhľad
REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.'
SAVEDUP: Uložené.
diff --git a/lang/sv.yml b/lang/sv.yml
index 58a7564db..c35e712ce 100644
--- a/lang/sv.yml
+++ b/lang/sv.yml
@@ -293,8 +293,6 @@ sv:
FROMWEB: 'Från webben'
FindInFolder: 'Hitta i mapp'
IMAGEALT: 'Alternativ text (alt)'
- IMAGEALTTEXT: 'Alternativ text (alt) - visas om bilden inte kan visas'
- IMAGEALTTEXTDESC: 'Visas för skärmläsare eller om bilden inte kan visas'
IMAGEDIMENSIONS: Dimensioner
IMAGEHEIGHTPX: Höjd
IMAGETITLE: 'Titel text (tooltip) - för ytterligare information om bilden'
@@ -326,11 +324,9 @@ sv:
CANT_REORGANISE: 'Du har inte tillstånd att ändra sidor på toppnivå. Dina ändringar har inte sparats.'
DELETED: Raderad
HELP: Hjälp
- PAGETYPE: 'Sidtyp'
PERMAGAIN: 'Du har blivit utloggad. Om du vill logga in igen anger du dina uppgifter nedan.'
PERMALREADY: 'Tyvärr så har du inte åtkomst till den delen av CMSet. Om du vill logga in med en annan användare kan du göra det nedan'
PERMDEFAULT: 'Du måste vara inloggad för att få åtkomst till administrativa delarna; var vänlig att logga in med dina användaruppgifter nedan.'
- PLEASESAVE: 'Var god spara sidan. Den kan inte uppdateras för att den har inte sparats ännu.'
PreviewButton: Förhandsgranska
REORGANISATIONSUCCESSFUL: 'Omorganisationen av sidträdet luyckades.'
SAVEDUP: Sparad.
diff --git a/model/DataList.php b/model/DataList.php
index ed0c5f0c7..f7cfc92b6 100644
--- a/model/DataList.php
+++ b/model/DataList.php
@@ -916,7 +916,9 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
/**
* Returns an array with both the keys and values set to the IDs of the records in this list.
+ * Does not respect sort order. Use ->column("ID") to get an ID list with the current sort.
*
+ * @return array
*/
public function getIDList() {
$ids = $this->column("ID");
diff --git a/model/DataObject.php b/model/DataObject.php
index 275a304f2..6a0cb3cfd 100644
--- a/model/DataObject.php
+++ b/model/DataObject.php
@@ -2077,7 +2077,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
$candidateManyManys = (array)Config::inst()->get($candidate, 'many_many', Config::UNINHERITED);
foreach($candidateManyManys as $relation => $relatedClass) {
- if($relatedClass === $this->class) {
+ if (is_a($this, $relatedClass)) {
$relationName = $relation;
}
}
diff --git a/model/UnsavedRelationList.php b/model/UnsavedRelationList.php
index 05db48c92..cce190872 100644
--- a/model/UnsavedRelationList.php
+++ b/model/UnsavedRelationList.php
@@ -206,8 +206,10 @@ class UnsavedRelationList extends ArrayList {
/**
* Returns an array with both the keys and values set to the IDs of the records in this list.
+ * Does not respect sort order. Use ->column("ID") to get an ID list with the current sort.
+ * Does not return the IDs for unsaved DataObjects.
*
- * Does not return the IDs for unsaved DataObjects
+ * @return array
*/
public function getIDList() {
// Get a list of IDs of our current items - if it's not a number then object then assume it's a DO.
diff --git a/model/Versioned.php b/model/Versioned.php
index 17c3c926a..1b2a686dd 100644
--- a/model/Versioned.php
+++ b/model/Versioned.php
@@ -5,6 +5,8 @@
* allowing you to rollback changes and view history. An example of this is
* the pages used in the CMS.
*
+ * @property int $Version
+ *
* @package framework
* @subpackage model
*/
@@ -637,15 +639,17 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
$nextVersion = $nextVersion ?: 1;
- // Add the version number to this data
- $manipulation[$table]['fields']['Version'] = $nextVersion;
- $newManipulation['fields']['Version'] = $nextVersion;
-
- // Write AuthorID for baseclass
if($table === $baseDataClass) {
+ // Write AuthorID for baseclass
$userID = (Member::currentUser()) ? Member::currentUser()->ID : 0;
$newManipulation['fields']['AuthorID'] = $userID;
+
+ // Update main table version if not previously known
+ $manipulation[$table]['fields']['Version'] = $nextVersion;
}
+
+ // Update _versions table manipulation
+ $newManipulation['fields']['Version'] = $nextVersion;
$manipulation["{$table}_versions"] = $newManipulation;
}
@@ -672,6 +676,19 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
public function augmentWrite(&$manipulation) {
+ // get Version number from base data table on write
+ $version = null;
+ $baseDataClass = ClassInfo::baseDataClass($this->owner->class);
+ if(isset($manipulation[$baseDataClass]['fields'])) {
+ if ($this->migratingVersion) {
+ $manipulation[$baseDataClass]['fields']['Version'] = $this->migratingVersion;
+ }
+ if (isset($manipulation[$baseDataClass]['fields']['Version'])) {
+ $version = $manipulation[$baseDataClass]['fields']['Version'];
+ }
+ }
+
+ // Update all tables
$tables = array_keys($manipulation);
foreach($tables as $table) {
@@ -682,18 +699,13 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
// Get ID field
- $id = $manipulation[$table]['id'] ? $manipulation[$table]['id'] : $manipulation[$table]['fields']['ID'];
+ $id = $manipulation[$table]['id']
+ ? $manipulation[$table]['id']
+ : $manipulation[$table]['fields']['ID'];
if(!$id) {
user_error("Couldn't find ID in " . var_export($manipulation[$table], true), E_USER_ERROR);
}
- if($this->migratingVersion) {
- $manipulation[$table]['fields']['Version'] = $this->migratingVersion;
- }
-
- $version = isset($manipulation[$table]['fields']['Version'])
- ? $manipulation[$table]['fields']['Version']
- : null;
if($version < 0 || $this->_nextWriteWithoutVersion) {
// Putting a Version of -1 is a signal to leave the version table alone, despite their being no version
unset($manipulation[$table]['fields']['Version']);
@@ -703,7 +715,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
$this->augmentWriteVersioned($manipulation, $table, $id);
}
- // For base classes of versioned data objects
+ // Remove "Version" column from subclasses of baseDataClass
if(!$this->hasVersionField($table)) {
unset($manipulation[$table]['fields']['Version']);
}
@@ -925,56 +937,64 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Move a database record from one stage to the other.
*
- * @param fromStage Place to copy from. Can be either a stage name or a version number.
- * @param toStage Place to copy to. Must be a stage name.
- * @param createNewVersion Set this to true to create a new version number. By default, the existing version
- * number will be copied over.
+ * @param int|string $fromStage Place to copy from. Can be either a stage name or a version number.
+ * @param string $toStage Place to copy to. Must be a stage name.
+ * @param bool $createNewVersion Set this to true to create a new version number.
+ * By default, the existing version number will be copied over.
*/
public function publish($fromStage, $toStage, $createNewVersion = false) {
$this->owner->extend('onBeforeVersionedPublish', $fromStage, $toStage, $createNewVersion);
- $baseClass = $this->owner->class;
- while( ($p = get_parent_class($baseClass)) != "DataObject") $baseClass = $p;
+ $baseClass = ClassInfo::baseDataClass($this->owner->class);
$extTable = $this->extendWithSuffix($baseClass);
+ /** @var Versioned|DataObject $from */
if(is_numeric($fromStage)) {
$from = Versioned::get_version($baseClass, $this->owner->ID, $fromStage);
} else {
$this->owner->flushCache();
- $from = Versioned::get_one_by_stage($baseClass, $fromStage, "\"{$baseClass}\".\"ID\"={$this->owner->ID}");
+ $from = Versioned::get_one_by_stage($baseClass, $fromStage, array(
+ "\"{$baseClass}\".\"ID\" = ?" => $this->owner->ID
+ ));
+ }
+ if(!$from) {
+ user_error("Can't find {$this->owner->class}/{$this->owner->ID} in stage {$fromStage}", E_USER_WARNING);
+ return;
}
- $publisherID = isset(Member::currentUser()->ID) ? Member::currentUser()->ID : 0;
- if($from) {
- $from->forceChange();
- if($createNewVersion) {
- $latest = self::get_latest_version($baseClass, $this->owner->ID);
- $this->owner->Version = $latest->Version + 1;
- } else {
- $from->migrateVersion($from->Version);
- }
+ // Set version of new record
+ $from->forceChange();
+ if($createNewVersion) {
+ // Clear version to be automatically created on write
+ $from->Version = null;
+ } else {
+ $from->migrateVersion($from->Version);
// Mark this version as having been published at some stage
+ $publisherID = isset(Member::currentUser()->ID) ? Member::currentUser()->ID : 0;
DB::prepared_query("UPDATE \"{$extTable}_versions\"
SET \"WasPublished\" = ?, \"PublisherID\" = ?
WHERE \"RecordID\" = ? AND \"Version\" = ?",
array(1, $publisherID, $from->ID, $from->Version)
);
-
- $oldMode = Versioned::get_reading_mode();
- Versioned::reading_stage($toStage);
-
- $conn = DB::get_conn();
- if(method_exists($conn, 'allowPrimaryKeyEditing')) $conn->allowPrimaryKeyEditing($baseClass, true);
- $from->write();
- if(method_exists($conn, 'allowPrimaryKeyEditing')) $conn->allowPrimaryKeyEditing($baseClass, false);
-
- $from->destroy();
-
- Versioned::set_reading_mode($oldMode);
- } else {
- user_error("Can't find {$this->owner->URLSegment}/{$this->owner->ID} in stage $fromStage", E_USER_WARNING);
}
+
+ // Change to new stage, write, and revert state
+ $oldMode = Versioned::get_reading_mode();
+ Versioned::reading_stage($toStage);
+
+ $conn = DB::get_conn();
+ if(method_exists($conn, 'allowPrimaryKeyEditing')) {
+ $conn->allowPrimaryKeyEditing($baseClass, true);
+ $from->write();
+ $conn->allowPrimaryKeyEditing($baseClass, false);
+ } else {
+ $from->write();
+ }
+
+ $from->destroy();
+
+ Versioned::set_reading_mode($oldMode);
}
/**
diff --git a/tests/forms/gridfield/GridFieldDeleteActionTest.php b/tests/forms/gridfield/GridFieldDeleteActionTest.php
index 2d0f2c4d6..2f4d2d909 100644
--- a/tests/forms/gridfield/GridFieldDeleteActionTest.php
+++ b/tests/forms/gridfield/GridFieldDeleteActionTest.php
@@ -42,15 +42,54 @@ class GridFieldDeleteActionTest extends SapphireTest {
$this->assertEquals(3, count($deleteButtons), 'Delete buttons should show when logged in.');
}
+ public function testActionsRequireCSRF() {
+ $this->logInWithPermission('ADMIN');
+ $this->setExpectedException(
+ 'SS_HTTPResponse_Exception',
+ _t("Form.CSRF_FAILED_MESSAGE",
+ "There seems to have been a technical problem. Please click the back button, ".
+ "refresh your browser, and try again."
+ ),
+ 400
+ );
+ $stateID = 'testGridStateActionField';
+ $request = new SS_HTTPRequest(
+ 'POST',
+ 'url',
+ array(),
+ array(
+ 'action_gridFieldAlterAction?StateID='.$stateID,
+ 'SecurityID' => null,
+ )
+ );
+ $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
+ }
+
public function testDeleteActionWithoutCorrectPermission() {
if(Member::currentUser()) { Member::currentUser()->logOut(); }
$this->setExpectedException('ValidationException');
$stateID = 'testGridStateActionField';
- Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord',
- 'args'=>array('RecordID'=>$this->idFromFixture('GridFieldAction_Delete_Team', 'team1'))));
- $request = new SS_HTTPRequest('POST', 'url', array(),
- array('action_gridFieldAlterAction?StateID='.$stateID=>true));
+ Session::set(
+ $stateID,
+ array(
+ 'grid' => '',
+ 'actionName' => 'deleterecord',
+ 'args' => array(
+ 'RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1')
+ )
+ )
+ );
+ $token = SecurityToken::inst();
+ $request = new SS_HTTPRequest(
+ 'POST',
+ 'url',
+ array(),
+ array(
+ 'action_gridFieldAlterAction?StateID='.$stateID => true,
+ $token->getName() => $token->getValue(),
+ )
+ );
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
$this->assertEquals(3, $this->list->count(),
'User should\'t be able to delete records without correct permissions.');
@@ -59,10 +98,26 @@ class GridFieldDeleteActionTest extends SapphireTest {
public function testDeleteActionWithAdminPermission() {
$this->logInWithPermission('ADMIN');
$stateID = 'testGridStateActionField';
- Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord',
- 'args'=>array('RecordID'=>$this->idFromFixture('GridFieldAction_Delete_Team', 'team1'))));
- $request = new SS_HTTPRequest('POST', 'url', array(),
- array('action_gridFieldAlterAction?StateID='.$stateID=>true));
+ Session::set(
+ $stateID,
+ array(
+ 'grid'=>'',
+ 'actionName'=>'deleterecord',
+ 'args' => array(
+ 'RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1')
+ )
+ )
+ );
+ $token = SecurityToken::inst();
+ $request = new SS_HTTPRequest(
+ 'POST',
+ 'url',
+ array(),
+ array(
+ 'action_gridFieldAlterAction?StateID='.$stateID=>true,
+ $token->getName() => $token->getValue(),
+ )
+ );
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
$this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.');
}
@@ -76,11 +131,26 @@ class GridFieldDeleteActionTest extends SapphireTest {
$form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
$stateID = 'testGridStateActionField';
- Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord',
- 'args'=>array('RecordID'=>$this->idFromFixture('GridFieldAction_Delete_Team', 'team1'))));
- $request = new SS_HTTPRequest('POST', 'url', array(),
- array('action_gridFieldAlterAction?StateID='.$stateID=>true));
-
+ Session::set(
+ $stateID,
+ array(
+ 'grid'=>'',
+ 'actionName'=>'deleterecord',
+ 'args' => array(
+ 'RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1')
+ )
+ )
+ );
+ $token = SecurityToken::inst();
+ $request = new SS_HTTPRequest(
+ 'POST',
+ 'url',
+ array(),
+ array(
+ 'action_gridFieldAlterAction?StateID='.$stateID=>true,
+ $token->getName() => $token->getValue(),
+ )
+ );
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
$this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.');
diff --git a/tests/model/ManyManyListExtensionTest.php b/tests/model/ManyManyListExtensionTest.php
new file mode 100644
index 000000000..4b37e7848
--- /dev/null
+++ b/tests/model/ManyManyListExtensionTest.php
@@ -0,0 +1,119 @@
+objFromFixture('ManyManyListTest_IndirectPrimary', 'manymany_extra_primary');
+ $secondaries = $primary->Secondary();
+ $extraFields = $secondaries->getExtraFields();
+
+ $this->assertTrue(count($extraFields) > 0, 'has extra fields');
+ $this->assertTrue(isset($extraFields['DocumentSort']), 'has DocumentSort');
+
+ // Test from the secondary (which is extended) to the primary (not extended)
+ $secondary = $this->objFromFixture('ManyManyListTest_SecondarySub', 'manymany_extra_secondary');
+
+ $primaries = $secondary->Primary();
+ $extraFields = $primaries->getExtraFields();
+
+ $this->assertTrue(count($extraFields) > 0, 'has extra fields');
+ $this->assertTrue(isset($extraFields['DocumentSort']), 'has DocumentSort');
+ }
+}
+
+/**
+ * @package framework
+ * @subpackage tests
+ *
+ * A data object that implements the primary side of a many_many (where the extra fields are
+ * defined.) The many-many refers to ManyManyListTest_Secondary rather than ManyManyListTest_SecondarySub
+ * by design, because we're trying to test that a subclass instance picks up the extra fields of it's parent.
+ */
+class ManyManyListTest_IndirectPrimary extends DataObject implements TestOnly {
+
+ private static $db = array(
+ 'Title' => 'Varchar(255)'
+ );
+
+ private static $many_many = array(
+ 'Secondary' => 'ManyManyListTest_Secondary'
+ );
+
+ private static $many_many_extraFields = array(
+ 'Secondary' => array(
+ 'DocumentSort' => 'Int'
+ )
+ );
+}
+
+/**
+ * @package framework
+ * @subpackage tests
+ *
+ * A data object that implements the secondary side of a many_many when extended by
+ * ManyManyListTest_IndirectSecondaryExtension.
+ */
+class ManyManyListTest_Secondary extends DataObject implements TestOnly {
+
+ // Possibly not required, but want to simulate a real test failure case where
+ // database tables are present.
+ private static $db = array(
+ 'Title' => 'Varchar(255)'
+ );
+
+}
+
+/**
+ * @package framework
+ * @subpackage tests
+ *
+ * A data object that is a subclass of the secondary side. The test will create an instance of this,
+ * and ensure that the extra fields are available on the instance even though the many many is
+ * defined at the parent level.
+ */
+class ManyManyListTest_SecondarySub extends ManyManyListTest_Secondary {
+
+ // private static $db = array(
+ // 'Other' => 'Varchar(255)'
+ // );
+
+}
+
+/**
+ * @package framework
+ * @subpackage tests
+ *
+ * An extension that is applied to ManyManyListTest_Secondary that implements the other side of the many-many
+ * relationship.
+ */
+class ManyManyListTest_IndirectSecondaryExtension extends DataExtension implements TestOnly {
+
+ private static $db = array(
+ 'Title' => 'Varchar(255)'
+ );
+
+ private static $belongs_many_many = array(
+ 'Primary' => 'ManyManyListTest_IndirectPrimary'
+ );
+
+}
diff --git a/tests/model/ManyManyListExtensionTest.yml b/tests/model/ManyManyListExtensionTest.yml
new file mode 100644
index 000000000..a28c7be68
--- /dev/null
+++ b/tests/model/ManyManyListExtensionTest.yml
@@ -0,0 +1,6 @@
+ManyManyListTest_IndirectPrimary:
+ manymany_extra_primary:
+ Title: 'primary'
+ManyManyListTest_SecondarySub:
+ manymany_extra_secondary:
+ Title: 'secondary'
diff --git a/tests/model/VersionedTest.php b/tests/model/VersionedTest.php
index 37c6f9df7..43ff72eb1 100644
--- a/tests/model/VersionedTest.php
+++ b/tests/model/VersionedTest.php
@@ -198,15 +198,37 @@ class VersionedTest extends SapphireTest {
$page1 = $this->objFromFixture('VersionedTest_DataObject', 'page1');
$page1->Content = 'orig';
$page1->write();
- $oldVersion = $page1->Version;
+ $firstVersion = $page1->Version;
$page1->publish('Stage', 'Live', false);
- $this->assertEquals($oldVersion, $page1->Version, 'publish() with $createNewVersion=FALSE');
+ $this->assertEquals(
+ $firstVersion,
+ $page1->Version,
+ 'publish() with $createNewVersion=FALSE does not create a new version'
+ );
$page1->Content = 'changed';
$page1->write();
- $oldVersion = $page1->Version;
+ $secondVersion = $page1->Version;
+ $this->assertTrue($firstVersion < $secondVersion, 'write creates new version');
+
$page1->publish('Stage', 'Live', true);
- $this->assertTrue($oldVersion < $page1->Version, 'publish() with $createNewVersion=TRUE');
+ $thirdVersion = Versioned::get_latest_version('VersionedTest_DataObject', $page1->ID)->Version;
+ $liveVersion = Versioned::get_versionnumber_by_stage('VersionedTest_DataObject', 'Live', $page1->ID);
+ $stageVersion = Versioned::get_versionnumber_by_stage('VersionedTest_DataObject', 'Stage', $page1->ID);
+ $this->assertTrue(
+ $secondVersion < $thirdVersion,
+ 'publish() with $createNewVersion=TRUE creates a new version'
+ );
+ $this->assertEquals(
+ $liveVersion,
+ $thirdVersion,
+ 'publish() with $createNewVersion=TRUE publishes to live'
+ );
+ $this->assertEquals(
+ $stageVersion,
+ $secondVersion,
+ 'publish() with $createNewVersion=TRUE does not affect stage'
+ );
}
public function testRollbackTo() {
@@ -222,10 +244,11 @@ class VersionedTest extends SapphireTest {
$changedVersion = $page1->Version;
$page1->doRollbackTo($origVersion);
- $page1 = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage',
- sprintf('"VersionedTest_DataObject"."ID" = %d', $page1->ID));
+ $page1 = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', array(
+ '"VersionedTest_DataObject"."ID" = ?' => $page1->ID
+ ));
- $this->assertTrue($page1->Version > $changedVersion, 'Create a new higher version number');
+ $this->assertTrue($page1->Version == $changedVersion + 1, 'Create a new higher version number');
$this->assertEquals('orig', $page1->Content, 'Copies the content from the old version');
// check db entries