reactivate api: links

added deleted link back in

updated some external links
This commit is contained in:
David Alexander 2016-02-09 14:52:11 -07:00
parent b55a5435b1
commit d633cad9ec
74 changed files with 451 additions and 453 deletions

View File

@ -144,7 +144,7 @@ Sitemap.php
* PHP OpenID (http://openidenabled.com/php-openid/) * PHP OpenID (http://openidenabled.com/php-openid/)
* Browscap (http://browscap.org/) * Browscap (http://browscap.org/)
* Plotr (http://www.solutoire.com/plotr/) * Plotr (http://www.solutoire.com/plotr/)
* SWFUpload (http://profandesign.se/swfupload/) * `SWFUpload (http://profandesign.se/swfupload/)`
* Improved classes * Improved classes
* CalendarDateField * CalendarDateField
* Refactored part of Field() into HTMLField() so it can be used in PopupDateTimeField * Refactored part of Field() into HTMLField() so it can be used in PopupDateTimeField

View File

@ -217,8 +217,8 @@ Right:
### HTMLEditorField (TinyMCE) stores content as UTF8 instead of HTML Entities ### HTMLEditorField (TinyMCE) stores content as UTF8 instead of HTML Entities
Prior to 2.4.0, the TinyMCE JavaScript library would store a subset of special characters as HTML entities (see [TinyMCE Prior to 2.4.0, the TinyMCE JavaScript library would store a subset of special characters as HTML entities (see `[TinyMCE
Configuration](http://wiki.moxiecode.com/index.php/TinyMCE:Configuration/entities)). SilverStripe expects UTF8 for user Configuration](http://wiki.moxiecode.com/index.php/TinyMCE:Configuration/entities)`). SilverStripe expects UTF8 for user
input in the CMS, database storage as well as output. We have made this behaviour more consistent by converting the input in the CMS, database storage as well as output. We have made this behaviour more consistent by converting the
TinyMCE entities back into UTF8 for database storage. TinyMCE entities back into UTF8 for database storage.

View File

@ -145,7 +145,7 @@ Affected classes and methods:
### Usage of Controller::join_links() to concatenate links now mandatory ### Usage of Controller::join_links() to concatenate links now mandatory
The `[api:Controller::join_links()]` method The [api:Controller::join_links()] method
to create links within SilverStripe controllers is now mandatory. This method ensures that links with existing GET to create links within SilverStripe controllers is now mandatory. This method ensures that links with existing GET
parameters don't break through string concatenation. parameters don't break through string concatenation.
@ -177,9 +177,9 @@ Full controller example:
Using this method is particularly important for any custom Using this method is particularly important for any custom
`[api:TableListField]` or [api:TableListField] or
`[api:ComplexTableField]` subclasses and any [api:ComplexTableField] subclasses and any
`[api:LeftAndMain]` subclass for the CMS UI. These classes in [api:LeftAndMain] subclass for the CMS UI. These classes in
particular were refactored to secure destructive links against Cross Site Request Forgery (CSRF). This is achieved via a particular were refactored to secure destructive links against Cross Site Request Forgery (CSRF). This is achieved via a
mandatory "SecurityID" GET parameter appended to the base link. mandatory "SecurityID" GET parameter appended to the base link.

View File

@ -15,11 +15,11 @@ Default setting:
Overriding these defaults Overriding these defaults
* `[api:HTTP::set_cache_age()]` can be used to set the max-age component of the cache-control line, in seconds. * [api:HTTP::set_cache_age()] can be used to set the max-age component of the cache-control line, in seconds.
Set it to 0 to disable caching; the "no-cache" clause in `Cache-Control` and `Pragma` will be included. Set it to 0 to disable caching; the "no-cache" clause in `Cache-Control` and `Pragma` will be included.
* `[api:HTTP::register_modification_date()]` can be used to set the modification date to something more recent than the default. * [api:HTTP::register_modification_date()] can be used to set the modification date to something more recent than the default.
How it works: How it works:
* `[api:DataObject::__construct()]` calls `[api:HTTP::register_modification_date()]` whenever a record comes from the database * [api:DataObject::__construct()] calls [api:HTTP::register_modification_date()] whenever a record comes from the database
* `Controller::run()` calls `[api:HTTP::add_cache_headers()]` before outputting the page * [api:Controller::run()] calls [api:HTTP::add_cache_headers()] before outputting the page

View File

@ -26,7 +26,7 @@ Feature overview:
You can use the CsvBulkLoader without subclassing or other customizations, if the column names You can use the CsvBulkLoader without subclassing or other customizations, if the column names
in your CSV file match `$db` properties in your dataobject. E.g. a simple import for the in your CSV file match `$db` properties in your dataobject. E.g. a simple import for the
`[api:Member]` class could have this data in a file: [api:Member] class could have this data in a file:
FirstName,LastName,Email FirstName,LastName,Email
Donald,Duck,donald@disney.com Donald,Duck,donald@disney.com
@ -38,7 +38,7 @@ The loader would be triggered through the `load()` method:
$loader = new CsvBulkLoader('Member'); $loader = new CsvBulkLoader('Member');
$result = $loader->load('<my-file-path>'); $result = $loader->load('<my-file-path>');
By the way, you can import `[api:Member]` and `[api:Group]` data through `http://localhost/admin/security` By the way, you can import [api:Member] and [api:Group] data through `http://localhost/admin/security`
interface out of the box. interface out of the box.
## Import through ModelAdmin ## Import through ModelAdmin

View File

@ -2,7 +2,7 @@
The [api:DataObject::$defaults] array allows you to specify simple static values to be the default value for when a The [api:DataObject::$defaults] array allows you to specify simple static values to be the default value for when a
record is created, but in many situations default values needs to be dynamically calculated. In order to do this, the record is created, but in many situations default values needs to be dynamically calculated. In order to do this, the
[api:DataObjectSet->populateDefaults()] method will need to be overloaded. [api:DataObjectSet::populateDefaults()] method will need to be overloaded.
This method is called whenever a new record is instantiated, and you must be sure to call the method on the parent This method is called whenever a new record is instantiated, and you must be sure to call the method on the parent
object! object!

View File

@ -3,8 +3,8 @@
The [api:DataObjectSet] class has a number of methods useful for grouping objects by fields. Together with sorting this The [api:DataObjectSet] class has a number of methods useful for grouping objects by fields. Together with sorting this
can be used to break up long lists of data into more manageable sub-sections. can be used to break up long lists of data into more manageable sub-sections.
The [api:DataObjectSet->groupBy()] method takes a field name as the single argument, and breaks the set up into a number The [api:DataObjectSet::groupBy()] method takes a field name as the single argument, and breaks the set up into a number
of arrays, where each array contains only objects with the same value of that field. The [api:DataObjectSet->GroupedBy()] of arrays, where each array contains only objects with the same value of that field. The [api:DataObjectSet::GroupedBy()]
method builds on this and returns the same data in a template-friendly format. method builds on this and returns the same data in a template-friendly format.
## Grouping Sets By First Letter ## Grouping Sets By First Letter
@ -65,7 +65,7 @@ this example this will be a method on the Page class.
} }
The final step is to render this into a template. The [api:DataObjectSet->GroupedBy()] method breaks up the set into The final step is to render this into a template. The [api:DataObjectSet::GroupedBy()] method breaks up the set into
a number of sets, grouped by the field that is passed as the parameter. In this case, the getTitleFirstLetter method a number of sets, grouped by the field that is passed as the parameter. In this case, the getTitleFirstLetter method
defined earlier is used to break them up. defined earlier is used to break them up.
@ -84,7 +84,7 @@ defined earlier is used to break them up.
## Grouping Sets By Month ## Grouping Sets By Month
Grouping a set by month is a very similar process. The only difference would be to sort the records by month name, and Grouping a set by month is a very similar process. The only difference would be to sort the records by month name, and
then create a method on the DataObject that returns the month name, and pass that to the [api:DataObjectSet->GroupedBy()] then create a method on the DataObject that returns the month name, and pass that to the [api:DataObjectSet::GroupedBy()]
call. call.
Again, the first step is to create a method on the class in question that will be displayed in a list. For this example, Again, the first step is to create a method on the class in question that will be displayed in a list. For this example,
@ -128,7 +128,7 @@ January to December. This can be accomplshed by sorting by the Date field:
} }
The final step is the render this into the template using the [api:DataObjectSet->GroupedBy()] method. The final step is the render this into the template using the [api:DataObjectSet::GroupedBy()] method.
:::ss :::ss
// Modules list grouped by the Month Posted // Modules list grouped by the Month Posted

View File

@ -11,6 +11,3 @@ the language and functions which are used in the guides.
* [Grouping DataObjectSets](grouping-dataobjectsets). Group results in a [api:DataObjectSet] to create sub sections. * [Grouping DataObjectSets](grouping-dataobjectsets). Group results in a [api:DataObjectSet] to create sub sections.
* [PHPUnit Configuration](phpunit-configuration). How to setup your testing environment with PHPUnit * [PHPUnit Configuration](phpunit-configuration). How to setup your testing environment with PHPUnit
## Feedback
If you have a topic you would like covered in these how to's please ask for it on our [Bug Tracker] `http://open.silverstripe.org`

View File

@ -8,7 +8,7 @@ See "[Testing](/topics/testing)" for an overview on how to create unit tests.
Short answer: Both are valid ways. Short answer: Both are valid ways.
The `sake` executable that comes with SilverStripe can trigger a customized The `sake` executable that comes with SilverStripe can trigger a customized
"[api:TestRunner]" class that handles the PHPUnit configuration and output formatting. [api:TestRunner] class that handles the PHPUnit configuration and output formatting.
It's tyically invoked to run all tests through `sake dev/tests/all`, It's tyically invoked to run all tests through `sake dev/tests/all`,
a single test with `sake dev/tests/MyTestClass`, or tests for a module with `sake dev/tests/module/mymodulename`. a single test with `sake dev/tests/MyTestClass`, or tests for a module with `sake dev/tests/module/mymodulename`.
While the custom test runner a handy tool, its also more limited than using `phpunit` directly, While the custom test runner a handy tool, its also more limited than using `phpunit` directly,

View File

@ -4,9 +4,12 @@ Please read our [guide to contributing documentation](misc/contributing#writing-
### Overview ### Overview
* [Getting started](http://silverstripe.org/getting-started/) | [Feature Overview] `http://silverstripe.org/introduction/` | [Demo](http://demo.silverstripe.org/) * [Getting started](http://silverstripe.org/getting-started/) |
* [Download and Installation](installation/) | [Upgrading](/installation/upgrading) | [Requirements](/installation/server-requirements) | [Changelog] `http://open.silverstripe.org/wiki/ChangeLog` | [Roadmap] `http://open.silverstripe.com/roadmap` [CMS Overview](http://www.silverstripe.org/software/cms/) |
* [API documentation](http://api.silverstripe.org/current) | [Official english book] `http://www.silverstripe.org/silverstripe-book` | [Official german book] `http://www.silverstripe.org/das-silverstripe-buch` [Framework Overview](http://www.silverstripe.org/software/framework/) |
[Demo](http://demo.silverstripe.org/)
* [Download and Installation](installation/) | [Upgrading](/installation/upgrading) | [Requirements](/installation/server-requirements) | [Changelogs](changelogs)
* [API documentation](http://api.silverstripe.org/current) | [Books](http://www.silverstripe.org/learn/resources/books)
### Getting support ### Getting support
@ -16,7 +19,7 @@ Please read our [guide to contributing documentation](misc/contributing#writing-
### Level 1: Building your first SilverStripe website ### Level 1: Building your first SilverStripe website
* [Introduction to PHP5 (zend.com)] `http://devzone.zend.com/node/view/id/627` * [Introduction to PHP (codeacademy.com)](https://www.codecademy.com/learn/php)
* [Tutorials](tutorials) * [Tutorials](tutorials)
* [Building a basic site](tutorials/building-a-basic-site) * [Building a basic site](tutorials/building-a-basic-site)
* [Extending a basic site](tutorials/extending-a-basic-site) * [Extending a basic site](tutorials/extending-a-basic-site)
@ -58,6 +61,3 @@ Please read our [guide to contributing documentation](misc/contributing#writing-
* [Contributing](http://www.silverstripe.org/contributing-to-silverstripe/) * [Contributing](http://www.silverstripe.org/contributing-to-silverstripe/)
* [Coding Conventions](misc/coding-conventions) * [Coding Conventions](misc/coding-conventions)
<div class="hint" markdown="1">
Looking for the old DokuWiki installation? See [doc.silverstripe.org/old] `http://doc.silverstripe.org/old`.
</div>

View File

@ -55,7 +55,7 @@ every page on the site, if that's easier.
## I can see unparsed PHP output in my browser ## I can see unparsed PHP output in my browser
Please make sure all code inside `*.php` files is wrapped in classes. Due to the way `[api:ManifestBuilder]` Please make sure all code inside `*.php` files is wrapped in classes. Due to the way [api:ManifestBuilder]
includes all files with this extension, any **procedural code will be executed on every call**. Most common error here includes all files with this extension, any **procedural code will be executed on every call**. Most common error here
is putting a test.php/phpinfo.php file in the document root. See [datamodel](/topics/datamodel) and [controllers](/topics/controller) is putting a test.php/phpinfo.php file in the document root. See [datamodel](/topics/datamodel) and [controllers](/topics/controller)
for ways how to structure your code. for ways how to structure your code.

View File

@ -3,7 +3,7 @@
This topic covers setting up your Mac as a Web Server and installing SilverStripe. This topic covers setting up your Mac as a Web Server and installing SilverStripe.
While OSX Comes bundled with PHP and Apache (Thanks Apple!) Its not quite ideal for SilverStripe so for setting up a While OSX Comes bundled with PHP and Apache (Thanks Apple!) Its not quite ideal for SilverStripe so for setting up a
webserver on OSX we suggest using [MAMP](http://www.mamp.info/en/index.php) or using [MacPorts](http://www.macports.org/) webserver on OSX we suggest using [MAMP](https://www.mamp.info/en) or using [MacPorts](http://www.macports.org/)
to manage your packages. to manage your packages.
If you want to use the default OSX PHP version then you will need to recompile your own versions of PHP with GD. Providing instructions If you want to use the default OSX PHP version then you will need to recompile your own versions of PHP with GD. Providing instructions

View File

@ -122,7 +122,7 @@ When ready, hit **Install SilverStripe**.
SilverStripe should now be installed and you should have a basic site with three pages. SilverStripe should now be installed and you should have a basic site with three pages.
However, URLs will not look "nice", like this: http://localhost/index.php/about-us. In order to fix this problem, we need to install a third-party URL rewriting tool, as IIS 6 does not support this natively. However, URLs will not look "nice", like this: `http://localhost/index.php/about-us`. In order to fix this problem, we need to install a third-party URL rewriting tool, as IIS 6 does not support this natively.
Proceed to **Install IIRF** below to enable nice URLs. Proceed to **Install IIRF** below to enable nice URLs.

View File

@ -18,7 +18,7 @@
After you've installed SilverStripe on XP using WebPI. You'll need to make a configuration change to get it working. After you've installed SilverStripe on XP using WebPI. You'll need to make a configuration change to get it working.
Specifically, you need to configure XP not to check that a script file exists before executing the script. This is Specifically, you need to configure XP not to check that a script file exists before executing the script. This is
necessary for URLs of the form http://localhost/silverstripe/index.php/about-us/ to work. necessary for URLs of the form `http://localhost/silverstripe/index.php/about-us/` to work.
* Open IIS Administrator * Open IIS Administrator
* Expand the local computer tree node * Expand the local computer tree node

View File

@ -41,7 +41,7 @@ step.
* It's better to submit multiple patches with separate bits of functionality than a big patch containing lots of * It's better to submit multiple patches with separate bits of functionality than a big patch containing lots of
changes changes
* Document your code inline through [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) syntax. See our * Document your code inline through [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) syntax. See our
[API documentation] `http://api.silverstripe.org/trunk` for good examples. [API documentation](http://api.silverstripe.org) for examples and [SS Markdown](/misc/ss-markdown).
* Also check and update documentation on [doc.silverstripe.org](http://doc.silverstripe.org). Check for any references to functionality deprecated or extended through your patch. Documentation changes should be included in the patch. * Also check and update documentation on [doc.silverstripe.org](http://doc.silverstripe.org). Check for any references to functionality deprecated or extended through your patch. Documentation changes should be included in the patch.
* We will attribute the change to you whereever possible (git does this automatically for pull requests) * We will attribute the change to you whereever possible (git does this automatically for pull requests)
* If you get stuck, please post to the [forum](http://silverstripe.org/forum) or for deeper core problems, to the [core mailinglist](https://groups.google.com/forum/#!forum/silverstripe-dev) * If you get stuck, please post to the [forum](http://silverstripe.org/forum) or for deeper core problems, to the [core mailinglist](https://groups.google.com/forum/#!forum/silverstripe-dev)
@ -200,7 +200,7 @@ Contributing documentation is the same process as providing any other patch
should fit elsewhere. *Example: ModelAdmin* should fit elsewhere. *Example: ModelAdmin*
* **Misc**: "Meta" documentation like coding conventions that doesn't directly relate to a feature or API. * **Misc**: "Meta" documentation like coding conventions that doesn't directly relate to a feature or API.
See [What to write (jacobian.org)](http://jacobian.org/writing/great-documentation/what-to-write/) for an excellent See [What to write (jacobian.org)](http://jacobian.org/writing/what-to-write/) for an excellent
introduction to the different types of documentation, and [Producing OSS: "Documentation"](http://producingoss.com/en/getting-started.html#documentation) introduction to the different types of documentation, and [Producing OSS: "Documentation"](http://producingoss.com/en/getting-started.html#documentation)
for good rules of thumb for documenting opensource software. for good rules of thumb for documenting opensource software.
@ -280,7 +280,7 @@ The [sapphiredocs] `https://github.com/silverstripe/silverstripe-sapphiredocs` m
### Further reading ### Further reading
* [Writing great documentation (jacobian.org)](http://jacobian.org/writing/great-documentation/) * [Writing great documentation (jacobian.org)](https://jacobian.org/writing/great-documentation/)
* [How tech writing sucks: Five Sins](http://www.slash7.com/articles/2006/11/15/tech-writing-the-five-sins) * [How tech writing sucks: Five Sins](http://www.slash7.com/articles/2006/11/15/tech-writing-the-five-sins)
* [What is good documentation?](http://www.techscribe.co.uk/techw/whatis.htm) * [What is good documentation?](http://www.techscribe.co.uk/techw/whatis.htm)

View File

@ -75,10 +75,10 @@ In this example, `$A` and `$B` refer to `$obj->Property()->A()` and `$obj->Prope
<% end_control %> <% end_control %>
If the method/field returned is an iterator such as a `[api:DataObject]`, then the control block will be repeated for If the method/field returned is an iterator such as a [api:DataObject], then the control block will be repeated for
each element of that iterator. This is the cornerstone of all menu and list generation in SilverStripe. each element of that iterator. This is the cornerstone of all menu and list generation in SilverStripe.
In this example, `Menu(1)` returns a `[api:DataObjectSet]` listing each top level main menu item (for more info on `Menu(1)`: In this example, `Menu(1)` returns a [api:DataObjectSet] listing each top level main menu item (for more info on `Menu(1)`:
[Making a Navigation System](/tutorials/building-a-basic-site#Making-a-Navigation-System)). The `<a>` [Making a Navigation System](/tutorials/building-a-basic-site#Making-a-Navigation-System)). The `<a>`
tag is repeated once for each main menu item, and the `$Link` and `$Title` values for each menu item is substituted in. tag is repeated once for each main menu item, and the `$Link` and `$Title` values for each menu item is substituted in.
@ -165,7 +165,7 @@ for adding notes for other developers but for things you don't want published in
### Formatting Template Values ### Formatting Template Values
The following example takes the Title field of our object, casts it to a `[api:Varchar]` object, and then calls The following example takes the Title field of our object, casts it to a [api:Varchar] object, and then calls
the `$XML` object on that Varchar object. the `$XML` object on that Varchar object.
:::ss :::ss
@ -241,8 +241,8 @@ Will give you the ability to call `$MyCustomValue` from anywhere in your templat
// output "I've got one thing to say to you: <i>Hi, this is my site</i>" // output "I've got one thing to say to you: <i>Hi, this is my site</i>"
Your function could return a single value as above or it could be a subclass of `[api:ArrayData]` for example a Your function could return a single value as above or it could be a subclass of [api:ArrayData] for example a
`[api:DataObject]` with many values then each of these could be accessible via a control loop [api:DataObject] with many values then each of these could be accessible via a control loop
:::php :::php
.. ..
@ -298,9 +298,9 @@ This is all very well and good, but how do the templates actually get called?
Templates do nothing on their own. Rather, they are used to render *a particular object*. All of the `<% if %>`, `<%control %>`, Templates do nothing on their own. Rather, they are used to render *a particular object*. All of the `<% if %>`, `<%control %>`,
and variable codes are methods or parameters that are called *on that object*. All that is necessary is and variable codes are methods or parameters that are called *on that object*. All that is necessary is
that the object is an instance of `[api:ViewableData]` (or one of its subclasses). that the object is an instance of [api:ViewableData] (or one of its subclasses).
The key is `[api:ViewableData::renderWith()]`. This method is passed a For example, within the controller's default action, The key is [api:ViewableData::renderWith()]. This method is passed a For example, within the controller's default action,
there is an instruction of the following sort: there is an instruction of the following sort:
:::php :::php
@ -310,7 +310,7 @@ there is an instruction of the following sort:
Here's what this line does: Here's what this line does:
* First `renderWith()` constructs a new object: `$template = new SSViewer("TemplateName");` * First `renderWith()` constructs a new object: `$template = new SSViewer("TemplateName");`
* `[api:SSViewer]` will take the content of `TemplateName.ss`, and turn it into PHP code. * [api:SSViewer] will take the content of `TemplateName.ss`, and turn it into PHP code.
* Then `renderWith()` passes the controller to `$template->process($controller);` * Then `renderWith()` passes the controller to `$template->process($controller);`
* `SSViewer::process()` will execute the PHP code generated from `TemplateName.ss` and return the results. * `SSViewer::process()` will execute the PHP code generated from `TemplateName.ss` and return the results.
@ -320,7 +320,7 @@ Here's what this line does:
available template name. available template name.
Below is an example of how to implement renderWith. In the example below the page is rendered using the myAjaxTemplate Below is an example of how to implement renderWith. In the example below the page is rendered using the myAjaxTemplate
if the page is called by an ajax function (using `[api:Director::is_ajax()]`). Note that the index function is called by if the page is called by an ajax function (using [api:Director::is_ajax()]). Note that the index function is called by
default if it exists and there is no action in the url parameters. default if it exists and there is no action in the url parameters.
:::php :::php

View File

@ -4,7 +4,7 @@
Ever wonder when you use `$Title` and `<% Control Children %>` what else you can call in the templates?. This page is Ever wonder when you use `$Title` and `<% Control Children %>` what else you can call in the templates?. This page is
here to help with a guide on what template controls you can call. here to help with a guide on what template controls you can call.
**Note for advanced users:** These built-in page controls are defined in the `[api:SiteTree]` classes, which are the **Note for advanced users:** These built-in page controls are defined in the [api:SiteTree] classes, which are the
'root' data-object and controller classes for all the sites. So if you're dealing with something that isn't a sub-class 'root' data-object and controller classes for all the sites. So if you're dealing with something that isn't a sub-class
of one of these, our handy reference to 'built-in page controls' won't be so relevant. of one of these, our handy reference to 'built-in page controls' won't be so relevant.
@ -220,18 +220,18 @@ These controls detect the visitor's previous experience with the site:
#### $Now.Nice, $Now.Year #### $Now.Nice, $Now.Year
$Now returns the current date. You can call any of the methods from the `[api:Date]` class on $Now returns the current date. You can call any of the methods from the [api:Date] class on
it. it.
#### $Created.Nice, $Created.Ago #### $Created.Nice, $Created.Ago
$Created returns the time the page was created, $Created.Ago returns how long ago the page was created. You can also $Created returns the time the page was created, $Created.Ago returns how long ago the page was created. You can also
call any of methods of the `[api:Date]` class on it. call any of methods of the [api:Date] class on it.
#### $LastEdited.Nice, $LastEdited.Ago #### $LastEdited.Nice, $LastEdited.Ago
$LastEdited returns the time the page was modified, $LastEdited.Ago returns how long ago the page was modified.You can also $LastEdited returns the time the page was modified, $LastEdited.Ago returns how long ago the page was modified.You can also
call any of methods of the `[api:Date]` class on it. call any of methods of the [api:Date] class on it.
### DataObjectSet Options ### DataObjectSet Options

View File

@ -2,20 +2,20 @@
## Introduction ## Introduction
Shows a group of DataObjects as a (readonly) tabular list (similiar to `[api:TableListField]`.) Shows a group of DataObjects as a (readonly) tabular list (similiar to [api:TableListField].)
You can specify limits and filters for the resultset by customizing query-settings (mostly the ID-field on the other You can specify limits and filters for the resultset by customizing query-settings (mostly the ID-field on the other
side of a one-to-many-relationship). side of a one-to-many-relationship).
See `[api:TableListField]` for more documentation on the base-class See [api:TableListField] for more documentation on the base-class
## Source Input ## Source Input
See `[api:TableListField]`. See [api:TableListField].
## Setting Parent/Child-Relations ## Setting Parent/Child-Relations
`[api:ComplexTableField]` tries to determine the parent-relation automatically by looking at the $has_one property on the listed [api:ComplexTableField] tries to determine the parent-relation automatically by looking at the $has_one property on the listed
child, or the record loaded into the surrounding form (see getParentClass() and getParentIdName()). You can force a child, or the record loaded into the surrounding form (see getParentClass() and getParentIdName()). You can force a
specific parent relation: specific parent relation:
@ -65,7 +65,7 @@ If you don't want several functions to appear (e.g. no add-link), there's severa
* Use `ComplexTableField->setPermissions(array("show","edit"))` to limit the functionality without touching the template * Use `ComplexTableField->setPermissions(array("show","edit"))` to limit the functionality without touching the template
(more secure). Possible values are "show","edit", "delete" and "add". (more secure). Possible values are "show","edit", "delete" and "add".
* Subclass `[api:ComplexTableField]` and override the rendering-mechanism * Subclass [api:ComplexTableField] and override the rendering-mechanism
* Use `ComplexTableField->setTemplate()` and `ComplexTableField->setTemplatePopup()` to provide custom templates * Use `ComplexTableField->setTemplate()` and `ComplexTableField->setTemplatePopup()` to provide custom templates
### Customising fields and Requirements in the popup ### Customising fields and Requirements in the popup
@ -73,7 +73,7 @@ If you don't want several functions to appear (e.g. no add-link), there's severa
There are several ways to customise the fields in the popup. Often you would want to display more information in the There are several ways to customise the fields in the popup. Often you would want to display more information in the
popup as there is more real-estate for you to play with. popup as there is more real-estate for you to play with.
`[api:ComplexTableField]` gives you several options to do this. You can either [api:ComplexTableField] gives you several options to do this. You can either
* Pass a FieldSet in the constructor. * Pass a FieldSet in the constructor.
* Pass a String in the constructor. * Pass a String in the constructor.
@ -83,7 +83,7 @@ The second will call the String as a method on the source class (Which should re
Popup. Popup.
You can also customise Javascript which is loaded for the Lightbox. As Requirements::clear() is called when the popup is You can also customise Javascript which is loaded for the Lightbox. As Requirements::clear() is called when the popup is
instantiated, `[api:ComplexTableField]` will look for a function to gather any specific requirements that you might need on your instantiated, [api:ComplexTableField] will look for a function to gather any specific requirements that you might need on your
source class. (e.g. Inline Javascript or styling). source class. (e.g. Inline Javascript or styling).
For this, create a function called "getRequirementsForPopup". For this, create a function called "getRequirementsForPopup".
@ -116,7 +116,7 @@ You'll have to do something like this in your form:
You have to hack in an ID on the form, as the CMS forms have this, and front end forms usually do not. You have to hack in an ID on the form, as the CMS forms have this, and front end forms usually do not.
It's not a perfect solution, but it works relatively well to get a simple `[api:ComplexTableField]` up and running on the front It's not a perfect solution, but it works relatively well to get a simple [api:ComplexTableField] up and running on the front
end. end.
To come: Make it a lot more flexible so tables can be easily used on the front end. It also needs to be flexible enough To come: Make it a lot more flexible so tables can be easily used on the front end. It also needs to be flexible enough
@ -132,19 +132,19 @@ Most of the time, you need to override the following methods:
### Examples ### Examples
* `[api:AssetTableField]` * [api:AssetTableField]
* `[api:MemberTableField]` * [api:MemberTableField]
## API Documentation ## API Documentation
`[api:ComplexTableField]` [api:ComplexTableField]
## Todo ## Todo
* Find a less fragile solution for accessing this field through the main controller and ReferencedField, e.g. build a * Find a less fragile solution for accessing this field through the main controller and ReferencedField, e.g. build a
seperate CTF-instance (doesn't necessarly have to be connected to the original by ReferencedField) seperate CTF-instance (doesn't necessarly have to be connected to the original by ReferencedField)
* Control width/height of popup by constructor (hardcoded at the moment) * Control width/height of popup by constructor (hardcoded at the moment)
* Integrate search from MemberTableField.php directly on `[api:ComplexTableField]` * Integrate search from MemberTableField.php directly on [api:ComplexTableField]
* Less performance-hungry implementation of detail-view paging (don't return all items on a single view) * Less performance-hungry implementation of detail-view paging (don't return all items on a single view)
* Use automatic has-many and many-many functions to return a ComponentSet rather than building the join manually * Use automatic has-many and many-many functions to return a ComponentSet rather than building the join manually
* Javascript/Ajax-Sorting (see [http://www.activewidgets.com/grid/](http://www.activewidgets.com/grid/) and [http://openrico.org/rico/livegrid.page](http://openrico.org/rico/livegrid.page)) * Javascript/Ajax-Sorting (see [http://www.activewidgets.com/grid/](http://www.activewidgets.com/grid/) and [http://openrico.org/rico/livegrid.page](http://openrico.org/rico/livegrid.page))

View File

@ -5,7 +5,7 @@ opting for "convention over configuration". This page details what that databas
## Base tables ## Base tables
Each direct sub-class of `[api:DataObject]` will have its own table. Each direct sub-class of [api:DataObject] will have its own table.
The following fields are always created. The following fields are always created.
@ -36,21 +36,21 @@ data sub-classed objects across **multiple tables**.
For example, suppose we have the following set of classes: For example, suppose we have the following set of classes:
* Class `[api:SiteTree]` extends `[api:DataObject]`: Title, Content fields * Class [api:SiteTree] extends [api:DataObject]: Title, Content fields
* Class `[api:Page]` extends `[api:SiteTree]`: Abstract field * Class Page extends [api:SiteTree]: Abstract field
* Class NewsSection extends `[api:SiteTree]`: *No special fields* * Class NewsSection extends [api:SiteTree]: *No special fields*
* Class NewsArticle extend `[api:Page]`: ArticleDate field * Class NewsArticle extend Page: ArticleDate field
The data for the following classes would be stored across the following tables: The data for the following classes would be stored across the following tables:
* `[api:SiteTree]` * [api:SiteTree]
* ID: Int * ID: Int
* ClassName: Enum('SiteTree', 'Page', 'NewsArticle') * ClassName: Enum('SiteTree', 'Page', 'NewsArticle')
* Created: Datetime * Created: Datetime
* LastEdited: Datetime * LastEdited: Datetime
* Title: Varchar * Title: Varchar
* Content: Text * Content: Text
* `[api:Page]` * Page
* ID: Int * ID: Int
* Abstract: Text * Abstract: Text
* NewsArticle * NewsArticle
@ -59,16 +59,16 @@ The data for the following classes would be stored across the following tables:
The way it works is this: The way it works is this:
* "Base classes" are direct sub-classes of `[api:DataObject]`. They are always given a table, whether or not they have * "Base classes" are direct sub-classes of [api:DataObject]. They are always given a table, whether or not they have
special fields. This is called the "base table" special fields. This is called the "base table"
* The base table's ClassName field is set to class of the given record. It's an enumeration of all possible * The base table's ClassName field is set to class of the given record. It's an enumeration of all possible
sub-classes of the base class (including the base class itself) sub-classes of the base class (including the base class itself)
* Each sub-class of the base object will also be given its own table, *as long as it has custom fields*. In the * Each sub-class of the base object will also be given its own table, *as long as it has custom fields*. In the
example above, NewsSection didn't have its own data and so an extra table would be redundant. example above, NewsSection didn't have its own data and so an extra table would be redundant.
* In all the tables, ID is the primary key. A matching ID number is used for all parts of a particular record: * In all the tables, ID is the primary key. A matching ID number is used for all parts of a particular record:
record #2 in Page refers to the same object as record #2 in `[api:SiteTree]`. record #2 in Page refers to the same object as record #2 in [api:SiteTree].
To retrieve a news article, SilverStripe joins the `[api:SiteTree]`, `[api:Page]` and NewsArticle tables by their ID fields. We use a To retrieve a news article, SilverStripe joins the [api:SiteTree], Page and NewsArticle tables by their ID fields. We use a
left-join for robustness; if there is no matching record in Page, we can return a record with a blank Article field. left-join for robustness; if there is no matching record in Page, we can return a record with a blank Article field.
## Staging and versioning ## Staging and versioning
@ -102,15 +102,15 @@ It **won't** do any of the following
The information documented in this page is reflected in a few places in the code: The information documented in this page is reflected in a few places in the code:
* `[api:DataObject]` * [api:DataObject]
* requireTable() is responsible for specifying the required database schema * requireTable() is responsible for specifying the required database schema
* instance_get() and instance_get_one() are responsible for generating the database queries for selecting data. * instance_get() and instance_get_one() are responsible for generating the database queries for selecting data.
* write() is responsible for generating the database queries for writing data. * write() is responsible for generating the database queries for writing data.
* `[api:Versioned]` * [api:Versioned]
* augmentWrite() is responsible for altering the normal database writing operation to handle versions. * augmentWrite() is responsible for altering the normal database writing operation to handle versions.
* augmentQuery() is responsible for altering the normal data selection queries to support versions. * augmentQuery() is responsible for altering the normal data selection queries to support versions.
* augmentDatabase() is responsible for specifying the altered database schema to support versions. * augmentDatabase() is responsible for specifying the altered database schema to support versions.
* `[api:MySQLDatabase]`: getNextID() is used when creating new objects; it also handles the mechanics of * [api:MySQLDatabase]: getNextID() is used when creating new objects; it also handles the mechanics of
updating the database to have the required schema. updating the database to have the required schema.

View File

@ -8,12 +8,12 @@ A single database record & abstract class for the data-access-model.
* [datamodel](/topics/datamodel): The basic pricinples * [datamodel](/topics/datamodel): The basic pricinples
* [data-types](/topics/data-types): Casting and special property-parsing * [data-types](/topics/data-types): Casting and special property-parsing
* `[api:DataObject]`: A "container" for DataObjects * [api:DataObject]: A "container" for DataObjects
## Basics ## Basics
The call to `DataObject->getCMSFields()` is the centerpiece of every data administration interface in SilverStripe, The call to [api:DataObject::getCMSFields()] is the centerpiece of every data administration interface in SilverStripe,
which returns a `[api:FieldSet]`''. which returns a [api:FieldSet].
:::php :::php
class MyPage extends Page { class MyPage extends Page {
@ -27,7 +27,7 @@ which returns a `[api:FieldSet]`''.
## Scaffolding Formfields ## Scaffolding Formfields
These calls retrieve a `[api:FieldSet]` for the area where you intend to work with the scaffolded form. These calls retrieve a [api:FieldSet] for the area where you intend to work with the scaffolded form.
### For the CMS ### For the CMS
@ -39,8 +39,8 @@ These calls retrieve a `[api:FieldSet]` for the area where you intend to work wi
### For the Frontend ### For the Frontend
Used for simple frontend forms without relation editing or `[api:TabSet] behaviour. Uses `scaffoldFormFields()` by Used for simple frontend forms without relation editing or [api:TabSet] behaviour. Uses `scaffoldFormFields()` by
default. To customize, either overload this method in your subclass, or decorate it by `DataObjectDecorator->updateFormFields()`. default. To customize, either overload this method in your subclass, or decorate it by [api:DataObjectDecorator::updateFormFields()].
* Requirements: SilverStripe 2.3.* * Requirements: SilverStripe 2.3.*
@ -53,7 +53,7 @@ default. To customize, either overload this method in your subclass, or decorate
* Requirements: SilverStripe 2.3.* * Requirements: SilverStripe 2.3.*
This section covers how to enhance the default scaffolded form fields from above. It is particularly useful when used This section covers how to enhance the default scaffolded form fields from above. It is particularly useful when used
in conjunction with the `[api:ModelAdmin]` in the CMS to make relevant data administration interfaces. in conjunction with the [api:ModelAdmin] in the CMS to make relevant data administration interfaces.
### Searchable Fields ### Searchable Fields
@ -80,8 +80,8 @@ Example: Simple Definition
} }
Searchable fields will be appear in the search interface with a default form field (usually a `[api:TextField]`) and a default Searchable fields will be appear in the search interface with a default form field (usually a [api:TextField]) and a default
search filter assigned (usually an `[api:ExactMatchFilter]`). To override these defaults, you can specify additional information search filter assigned (usually an [api:ExactMatchFilter]). To override these defaults, you can specify additional information
on `$searchable_fields`: on `$searchable_fields`:
:::php :::php
@ -93,7 +93,7 @@ on `$searchable_fields`:
} }
If you assign a single string value, you can set it to be either a `[api:FormField]` or `[api:SearchFilter]`. To specify both, you can If you assign a single string value, you can set it to be either a [api:FormField] or [api:SearchFilter]. To specify both, you can
assign an array: assign an array:
:::php :::php
@ -142,8 +142,8 @@ To include relations (''$has_one'', `$has_many` and `$many_many`) in your search
* Requirements: SilverStripe 2.3.* * Requirements: SilverStripe 2.3.*
Summary fields can be used to show a quick overview of the data for a specific `[api:DataObject]` record. Most common use is Summary fields can be used to show a quick overview of the data for a specific [api:DataObject] record. Most common use is
their display as table columns, e.g. in the search results of a `[api:ModelAdmin]` CMS interface. their display as table columns, e.g. in the search results of a [api:ModelAdmin] CMS interface.
Example: Getting predefined summary fields Example: Getting predefined summary fields
@ -191,4 +191,4 @@ To include relations in your summaries, you can use a dot-notation.
## API Documentation ## API Documentation
`[api:DataObject]` [api:DataObject]

View File

@ -2,14 +2,14 @@
## Introduction ## Introduction
Extensions (also referred to as decorators) allow for adding additional functionality to a `[api:DataObject]`. Extensions (also referred to as decorators) allow for adding additional functionality to a [api:DataObject].
In some cases, it can be easier to completely replace the used class throughout the core with your custom In some cases, it can be easier to completely replace the used class throughout the core with your custom
implementation. Have a look at `[api:Object->useCustomClass()]`. implementation. Have a look at [api:Object::useCustomClass()].
## Usage ## Usage
Your Decorator will nee to be a subclass of `[api:DataObjectDecorator]` or the `[api:Extension]` class. Your Decorator will nee to be a subclass of [api:DataObjectDecorator] or the [api:Extension] class.
:::php :::php
<?php <?php
@ -27,7 +27,7 @@ class you want to extend.
### Adding a decorator to a built-in class ### Adding a decorator to a built-in class
Sometimes you will want to add decorators to classes that you didn't make. For example, you might want to add the Sometimes you will want to add decorators to classes that you didn't make. For example, you might want to add the
`[api:ForumRole]` decorator to the `[api:Member]` object. [api:ForumRole] decorator to the [api:Member] object.
:::php :::php
@ -98,7 +98,7 @@ The $fields parameter is passed by reference, as it is an object.
### Custom database generation ### Custom database generation
Some decorators are designed to transparently add more sophisticated data-collection capabilities to your data object. Some decorators are designed to transparently add more sophisticated data-collection capabilities to your data object.
For example, `[api:Versioned]` adds version tracking and staging to any data object that it is applied to. To do this, For example, [api:Versioned] adds version tracking and staging to any data object that it is applied to. To do this,
you need to be able to create additional database tables and fields to keep your state stored in. you need to be able to create additional database tables and fields to keep your state stored in.
To do this, define an **augmentDatabase()** method on your decorator. This will be called when db/build is visited. To do this, define an **augmentDatabase()** method on your decorator. This will be called when db/build is visited.
@ -110,7 +110,7 @@ care of creating, modifying, or leaving tables as required, based on your desire
### Custom write queries ### Custom write queries
If you have customised the generated database, then you probably want to change the way that writes happen. This is If you have customised the generated database, then you probably want to change the way that writes happen. This is
used by `[api:Versioned]` to get an entry written in ClassName_versions whenever an insert/update happens. used by [api:Versioned] to get an entry written in ClassName_versions whenever an insert/update happens.
To do this, define the **augmentWrite(&$manipulation)** method. This method is passed a manipulation array representing To do this, define the **augmentWrite(&$manipulation)** method. This method is passed a manipulation array representing
the write about to happen, and is able to amend this as desired, since it is passed by reference. the write about to happen, and is able to amend this as desired, since it is passed by reference.
@ -121,21 +121,21 @@ The other queries that you will want to customise are the selection queries, cal
Versioned object has code to redirect every request to ClassName_live, if you are browsing the live site. Versioned object has code to redirect every request to ClassName_live, if you are browsing the live site.
To do this, define the **augmentSQL(SQLQuery &$query)** method. Again, the $query object is passed by reference and can To do this, define the **augmentSQL(SQLQuery &$query)** method. Again, the $query object is passed by reference and can
be modified as needed by your method. Instead of a manipulation array, we have a `[api:SQLQuery]` object. be modified as needed by your method. Instead of a manipulation array, we have a [api:SQLQuery] object.
### Additional methods ### Additional methods
The other thing you may want to do with a decorator is provide a method that can be called on the `[api:DataObject]` that is The other thing you may want to do with a decorator is provide a method that can be called on the [api:DataObject] that is
being decorated. For instance, you may add a publish() method to every `[api:DataObject]` that is decorated with `[api:Versioned]`. being decorated. For instance, you may add a publish() method to every [api:DataObject] that is decorated with [api:Versioned].
This is as simple as defining a method called publish() on your decorator. Bear in mind, however, that instead of This is as simple as defining a method called publish() on your decorator. Bear in mind, however, that instead of
$this, you should be referring to $this->owner. $this, you should be referring to $this->owner.
* $this = The `[api:DataObjectDecorator]` object. * $this = The [api:DataObjectDecorator] object.
* $this->owner = The related `[api:DataObject]` object. * $this->owner = The related [api:DataObject] object.
If you want to add your own internal properties, you can add this to the `[api:DataObjectDecorator]`, and these will be referred If you want to add your own internal properties, you can add this to the [api:DataObjectDecorator], and these will be referred
to as `$this->propertyName`. Every `[api:DataObject]` has an associated `[api:DataObjectDecorator]` instance for each class that it is to as `$this->propertyName`. Every [api:DataObject] has an associated [api:DataObjectDecorator] instance for each class that it is
decorated by. decorated by.
:::php :::php
@ -169,4 +169,5 @@ decorated by.
## API Documentation ## API Documentation
`[api:DataObjectDecorator]`
[api:DataObjectDecorator]

View File

@ -2,11 +2,11 @@
## Introduction ## Introduction
This class represents a set of `[api:DataObject]`s, such as the results of a query. It is the base for all This class represents a set of [api:DataObject]'s, such as the results of a query. It is the base for all
[datamodel](/topics/datamodel)-related querying. It implements the [Iterator [datamodel](/topics/datamodel)-related querying. It implements the [Iterator
interface](http://php.net/manual/en/language.oop5.iterations.php) introduced in PHP5. interface](http://php.net/manual/en/language.oop5.iterations.php) introduced in PHP5.
Relations (`has_many`/`many_many`) are described in `[api:ComponentSet]`, a subclass of `[api:DataObjectSet]`. Relations (`has_many`/`many_many`) are described in [api:ComponentSet], a subclass of [api:DataObjectSet].
## Usage ## Usage
@ -37,7 +37,7 @@ Relations (`has_many`/`many_many`) are described in `[api:ComponentSet]`, a subc
### Grouping ### Grouping
You can group a set by a specific column. Consider using `[api:SQLQuery]` with a *GROUP BY* statement for enhanced You can group a set by a specific column. Consider using [api:SQLQuery] with a *GROUP BY* statement for enhanced
performance. performance.
:::php :::php
@ -56,7 +56,7 @@ This works on the object itself, so do NOT do something like this:
:::php :::php
$sortedSet = $mySet->sort('Lastname'); //ascending $sortedSet = $mySet->sort('Lastname'); //ascending
## Merge with other `[api:DataObjectSet]`s ## Merge with other [api:DataObjectSet]s
:::php :::php
$myFirstSet->merge($mySecondSet); $myFirstSet->merge($mySecondSet);
@ -65,7 +65,7 @@ This works on the object itself, so do NOT do something like this:
### Mapping for Dropdowns ### Mapping for Dropdowns
When using `[api:DropdownField]` and its numerous subclasses to select a value from a set, you can easily map When using [api:DropdownField] and its numerous subclasses to select a value from a set, you can easily map
the records to a compatible array: the records to a compatible array:
:::php :::php
@ -88,11 +88,11 @@ It is good practice to check for empty sets before doing any iteration.
### Paging ### Paging
`[api:DataObject]`s have native support for dealing with **pagination**. [api:DataObject]s have native support for dealing with **pagination**.
See *setPageLimits*, *setPageLength*, etc. See *setPageLimits*, *setPageLength*, etc.
FIXME Complete pagination documentation FIXME Complete pagination documentation
## API Documentation ## API Documentation
`[api:DataObjectSet]` [api:DataObjectSet]

View File

@ -2,7 +2,7 @@
## Introduction ## Introduction
`[api:Director]` is the first step in the "execution pipeline". It parses the URL, matching it to one of a number of patterns, [api:Director] is the first step in the "execution pipeline". It parses the URL, matching it to one of a number of patterns,
and determines the controller, action and any argument to be used. It then runs the controller, which will finally run and determines the controller, action and any argument to be used. It then runs the controller, which will finally run
the viewer and/or perform processing steps. the viewer and/or perform processing steps.
@ -12,7 +12,7 @@ the viewer and/or perform processing steps.
## Redirection ## Redirection
The `[api:Director]` class has a number of methods to facilitate 301 and 302 HTTP redirection. The [api:Director] class has a number of methods to facilitate 301 and 302 HTTP redirection.
* **Director::redirect("action-name")**: If there's no slash in the URL passed to redirect, then it is assumed that you * **Director::redirect("action-name")**: If there's no slash in the URL passed to redirect, then it is assumed that you
want to go to a different action on the current controller. want to go to a different action on the current controller.
@ -33,8 +33,8 @@ redirectBack().
You can influence the way URLs are resolved one of 2 ways You can influence the way URLs are resolved one of 2 ways
1. Adding rules to `[api:Director]` in `<yourproject>/_config.php` (See Default Rewrite Rules below for examples) 1. Adding rules to [api:Director] in `<yourproject>/_config.php` (See Default Rewrite Rules below for examples)
2. Adding rules in your extended `[api:Controller]` class via the *$url_handlers* static variable 2. Adding rules in your extended [api:Controller] class via the *$url_handlers* static variable
See [controller](/topics/controller) for examples and explanations on how the rules get processed for both 1 and 2 above. See [controller](/topics/controller) for examples and explanations on how the rules get processed for both 1 and 2 above.
@ -56,8 +56,8 @@ SilverStripe comes with certain rewrite rules (e.g. for *admin/assets*).
## Links ## Links
* See `[api:ModelAsController]` class for details on controller/model-coupling * See [api:ModelAsController] class for details on controller/model-coupling
* See [execution-pipeline](/reference/execution-pipeline) for custom routing * See [execution-pipeline](/reference/execution-pipeline) for custom routing
## API Documentation ## API Documentation
`[api:Director]` [api:Director]

View File

@ -50,13 +50,13 @@ mod_rewrite works.
All requests go through main.php, which sets up the environment and then hands control over to Director. All requests go through main.php, which sets up the environment and then hands control over to Director.
**See:** The API documentation of `[api:Main]` for information about how main.php processes requests. **See:** The API documentation of [api:Main] for information about how main.php processes requests.
## Director and URL patterns ## Director and URL patterns
main.php relies on `[api:Director]` to work out which controller should handle this request. `[api:Director]` will instantiate that main.php relies on [api:Director] to work out which controller should handle this request. [api:Director] will instantiate that
controller object and then call `[api:Controller::run()]`. controller object and then call [api:Controller::run()].
**See:** The API documentation of `[api:Director]` for information about how Director parses URLs and hands control over to a controller object. **See:** The API documentation of [api:Director] for information about how Director parses URLs and hands control over to a controller object.
In general, the URL is build up as follows: page/action/ID/otherID - e.g. `http://www.mysite.com/mypage/addToCart/12`. In general, the URL is build up as follows: page/action/ID/otherID - e.g. `http://www.mysite.com/mypage/addToCart/12`.
This will add an object with ID 12 to the cart. This will add an object with ID 12 to the cart.
@ -73,9 +73,9 @@ When you create a function, you can access the ID like this:
## Controllers and actions ## Controllers and actions
`[api:Controller]`s are the building blocks of your application. [api:Controller]s are the building blocks of your application.
**See:** The API documentation for `[api:Controller]` **See:** The API documentation for [api:Controller]
You can access the following controller-method with /team/signup You can access the following controller-method with /team/signup

View File

@ -1,85 +1,85 @@
# Form Field Types # Form Field Types
This is a highlevel overview of available `[apiFormField]` subclasses. An automatically generated list is available through our [API](api:FormField) This is a highlevel overview of available [api:FormField] subclasses. An automatically generated list is available through our [API](api:FormField)
## Formatted Input ## Formatted Input
* `[AjaxUniqueTextField](api:AjaxUniqueTextField)`: Text field that automatically checks that the value entered is unique for * [api:AjaxUniqueTextField]: Text field that automatically checks that the value entered is unique for
the given set of fields in a given set of tables the given set of fields in a given set of tables
* `[AutocompleteTextField](api:AutocompleteTextField)` * [api:AutocompleteTextField]
* `[ConfirmedPasswordField](api:ConfirmedPasswordField)`: Shows two password-fields, and checks for matching passwords. * [api:ConfirmedPasswordField]: Shows two password-fields, and checks for matching passwords.
* `[CreditCardField](api:CreditCardField)` * [api:CreditCardField]
* `[CurrencyField](api:CurrencyField)` * [api:CurrencyField]
* `[EmailField](api:EmailField)` * [api:EmailField]
* `[HTMLEditorField](api:HTMLEditorField)`: A WYSIWYG editor field, powered by tinymce. * [api:HTMLEditorField]: A WYSIWYG editor field, powered by tinymce.
* `[NumericField](api:NumericField)`: A Single Numeric field extending a typical TextField but with validation. * [api:NumericField]: A Single Numeric field extending a typical TextField but with validation.
* `[PasswordField](api:PasswordField)` * [api:PasswordField]
* `[UniqueRestrictedTextField](api:UniqueRestrictedTextField)`: Text field that automatically checks that the value entered * [api:UniqueRestrictedTextField]: Text field that automatically checks that the value entered
is unique for the given set of fields in a given set of tables is unique for the given set of fields in a given set of tables
* `[UniqueTextField](api:UniqueTextField)`: Text field that automatically checks that the value entered is unique for the * [api:UniqueTextField]: Text field that automatically checks that the value entered is unique for the
given set of fields in a given set of tables given set of fields in a given set of tables
## Date/Time ## Date/Time
* `[DateField](api:DateField)`: Represents a date in a textfield (New Zealand) * [api:DateField]: Represents a date in a textfield (New Zealand)
* `[DatetimeField](api:DatetimeField)`: Combined date- and time field * [api:DatetimeField]: Combined date- and time field
* `[TimeField](api:TimeField)`: Represents time in a textfield (New Zealand) * [api:TimeField]: Represents time in a textfield (New Zealand)
## Structure ## Structure
* `[CompositeField](api:CompositeField)`: Base class for all fields that contain other fields. Uses `<div>` in template, but * [api:CompositeField]: Base class for all fields that contain other fields. Uses `<div>` in template, but
doesn't necessarily have any visible styling. doesn't necessarily have any visible styling.
* `[FieldGroup](api:FieldGroup)`: Same as CompositeField, but has default styling (indentation) attached in CMS-context. * [api:FieldGroup]: Same as CompositeField, but has default styling (indentation) attached in CMS-context.
* `[api:FieldSet]`: Basic container for sequential fields, or nested fields through CompositeField. Does NOT render a * [api:FieldSet]: Basic container for sequential fields, or nested fields through CompositeField. Does NOT render a
`<fieldgroup>`. `<fieldgroup>`.
* `[TabSet](api:TabSet)` * [api:TabSet]
* `[Tab](api:Tab)` * [api:Tab]
## Actions ## Actions
* `[api:Form]` for more info * [api:Form] for more info
* `[InlineFormAction](api:InlineFormAction)`: Render a button that will act as If you want to add custom behaviour, please * [api:InlineFormAction]: Render a button that will act as If you want to add custom behaviour, please
set {inlcudeDefaultJS} to false and work with behaviour.js. set {inlcudeDefaultJS} to false and work with behaviour.js.
* `[api:Image]`: Action that uses an image instead of a button * [api:Image]: Action that uses an image instead of a button
* `[InlineFormAction](api:InlineFormAction)`: Prevents placement of a button in the CMS-button-bar. * [api:InlineFormAction]: Prevents placement of a button in the CMS-button-bar.
## Files ## Files
* `[FileField](api:FileField)`: Simple file upload dialog. * [api:FileField]: Simple file upload dialog.
* `[FileIFrameField](api:FileIFrameField)`: File uploads through an iframe * [api:FileIFrameField]: File uploads through an iframe
* `[api:ImageField]`: Image upload through an iframe, with thumbnails and file-selection from existing assets * [api:ImageField]: Image upload through an iframe, with thumbnails and file-selection from existing assets
* `[SimpleImageField](api:SimpleImageField)`: SimpleImageField provides an easy way of uploading images to Image has_one * [api:SimpleImageField]: SimpleImageField provides an easy way of uploading images to Image has_one
relationships. Unlike ImageField, it doesn't use an iframe. relationships. Unlike ImageField, it doesn't use an iframe.
## Relations ## Relations
* `[ComplexTableField](api:ComplexTableField)`: Provides a tabuar list in your form with view/edit/add/delete links to modify * [api:ComplexTableField]: Provides a tabuar list in your form with view/edit/add/delete links to modify
records with a "has-one"-relationship (in a lightbox-popup). records with a "has-one"-relationship (in a lightbox-popup).
* `[HasManyComplexTableField](api:HasManyComplexTableField)` * [api:HasManyComplexTableField]
* `[HasOneComplexTableField](api:HasOneComplexTableField)` * [api:HasOneComplexTableField]
* `[LanguageDropdownField](api:LanguageDropdownField)`: An extension to dropdown field, pre-configured to list languages. * [api:LanguageDropdownField]: An extension to dropdown field, pre-configured to list languages.
Tied into i18n. Tied into i18n.
* `[ManyManyComplexTableField](api:ManyManyComplexTableField)` * [api:ManyManyComplexTableField]
* `[TableField](api:TableField)` * [api:TableField]
* `[api:TableListField]` * [api:TableListField]
* `[TreeDropdownField](api:TreeDropdownField)` * [api:TreeDropdownField]
* `[TreeMultiselectField](api:TreeMultiselectField)`: represents many-many joins using a tree selector shown in a * [api:TreeMultiselectField]: represents many-many joins using a tree selector shown in a
dropdown-like element dropdown-like element
* `[api:WidgetArea]` * [api:WidgetArea]
## Dataless/Utility ## Dataless/Utility
* `[DatalessField](api:DatalessField)` - Base class for fields which add some HTML to the form but don't submit any data or * [api:DatalessField] - Base class for fields which add some HTML to the form but don't submit any data or
save it to the database save it to the database
* `[HeaderField](api:HeaderField)`: Renders a simple `<h1>`-`<h6>` header * [api:HeaderField]: Renders a simple `<h1>`-`<h6>` header
* `[HiddenField](api:HiddenField)` * [api:HiddenField]
* `[LabelField](api:LabelField)` * [api:LabelField]
* `[LiteralField](api:LiteralField)`: Renders arbitrary HTML into a form. * [api:LiteralField]: Renders arbitrary HTML into a form.
## CMS Field Editor ## CMS Field Editor
Please see `[api:HTMLEditorField]` for in-depth documentation about custom forms created through a GUI in the CMS. Please see [api:HTMLEditorField] for in-depth documentation about custom forms created through a GUI in the CMS.

View File

@ -2,15 +2,15 @@
## Introduction ## Introduction
Represents an image object, inheriting all base functionality from the [file](api:file) class with extra functionality Represents an image object, inheriting all base functionality from the [api:File] class with extra functionality
including resizing. including resizing.
## Usage ## Usage
### Form Fields ### Form Fields
* `[api:Image]`. Designed to provide a complex image uploader for the CMS. * [api:Image]. Designed to provide a complex image uploader for the CMS.
* `[api:SimpleImageField]`. A Simple Image Upload Form * [api:SimpleImageField]. A Simple Image Upload Form
### Resizing Images in PHP ### Resizing Images in PHP
@ -102,9 +102,9 @@ For output of an image tag with the image automatically resized to 80px width, y
### Form Upload ### Form Upload
For usage on a website form, see `[api:SimpleImageField]`. For usage on a website form, see [api:SimpleImageField].
If you want to upload images within the CMS, see `[api:ImageField]`. If you want to upload images within the CMS, see [api:ImageField].
### Clearing Thumbnail Cache ### Clearing Thumbnail Cache
@ -120,4 +120,4 @@ image cache.
## API Documentation ## API Documentation
`[api:Image]` [api:Image]

View File

@ -10,11 +10,11 @@ LeftAndMain is the base class of all the admin area controllers.
Please use LeftAndMain::ForceReload to reload the whole form-area after an Ajax-Request. If you just need to refresh Please use LeftAndMain::ForceReload to reload the whole form-area after an Ajax-Request. If you just need to refresh
parts of the form, please use javascript-replacement in the response of the original Ajax-Request. Consider using parts of the form, please use javascript-replacement in the response of the original Ajax-Request. Consider using
`[api:Form]` for compiling Ajax-Responses and automatic detection of Ajax/Non-Ajax-Calls. [api:Form] for compiling Ajax-Responses and automatic detection of Ajax/Non-Ajax-Calls.
### Custom Access Checking ### Custom Access Checking
You can customize access control in `[api:LeftAndMain]`. You can customize access control in [api:LeftAndMain].
:::php :::php
// mysite/_config.php // mysite/_config.php
@ -144,7 +144,7 @@ For example:
static $menu_priority = 60; static $menu_priority = 60;
See also `[api:CMSMenu]` See also [api:CMSMenu]
### Translatable Menu Titles ### Translatable Menu Titles
@ -181,10 +181,10 @@ See [Javascript in the CMS](/topics/javascript#javascript-cms)
## Related ## Related
* `[api:CMSMain]` * [api:CMSMain]
* `[api:AssetAdmin]` * [api:AssetAdmin]
* `[api:SecurityAdmin]` * [api:SecurityAdmin]
* `[api:ModelAdmin]` * [api:ModelAdmin]
## TODO ## TODO

View File

@ -2,11 +2,11 @@
## Introduction ## Introduction
The `[api:Member]` class is used to represent user accounts on a SilverStripe site (including newsletter recipients). The [api:Member] class is used to represent user accounts on a SilverStripe site (including newsletter recipients).
## Testing For Logged In Users ## Testing For Logged In Users
The `[api:Member]` class comes with 2 static methods for getting information about the current logged in user. The [api:Member] class comes with 2 static methods for getting information about the current logged in user.
**Member::currentUserID()** **Member::currentUserID()**
@ -38,11 +38,11 @@ Returns the full *Member* Object for the current user, returns *null* if user is
## Subclassing ## Subclassing
<div class="warning" markdown="1"> <div class="warning" markdown="1">
This is the least desirable way of extending the `[api:Member]` class. It's better to use `[api:DataObjectDecorator]` This is the least desirable way of extending the [api:Member] class. It's better to use [api:DataObjectDecorator]
(see below). (see below).
</div> </div>
You can defined subclasses of `[api:Member]` to add extra fields or functionality to the built-in membership system. You can defined subclasses of [api:Member] to add extra fields or functionality to the built-in membership system.
:::php :::php
class MyMember extends Member { class MyMember extends Member {
@ -53,7 +53,7 @@ You can defined subclasses of `[api:Member]` to add extra fields or functionalit
} }
To ensure that all new members are created using this class, put a call to `[api:Object::useCustomClass()]` in To ensure that all new members are created using this class, put a call to [api:Object::useCustomClass()] in
(project)/_config.php: (project)/_config.php:
:::php :::php
@ -64,8 +64,8 @@ Note that if you want to look this class-name up, you can call Object::getCustom
## Overloading getCMSFields() ## Overloading getCMSFields()
If you overload the built-in function getCMSFields(), then you can change the form that is used to view & edit member If you overload the built-in function getCMSFields(), then you can change the form that is used to view & edit member
details in the newsletter system. This function returns a `[api:FieldSet]` object. You should generally start by calling details in the newsletter system. This function returns a [api:FieldSet] object. You should generally start by calling
parent::getCMSFields() and manipulate the `[api:FieldSet]` from there. parent::getCMSFields() and manipulate the [api:FieldSet] from there.
:::php :::php
function getCMSFields() { function getCMSFields() {
@ -79,11 +79,11 @@ parent::getCMSFields() and manipulate the `[api:FieldSet]` from there.
## Extending Member or DataObject? ## Extending Member or DataObject?
Basic rule: Class `[api:Member]` should just be extended for entities who have some kind of login. Basic rule: Class [api:Member] should just be extended for entities who have some kind of login.
If you have different types of `[api:Member]`s in the system, you have to make sure that those with login-capabilities have If you have different types of [api:Member]s in the system, you have to make sure that those with login-capabilities have
unique email-addresses (as this is used for login-credentials). unique email-addresses (as this is used for login-credentials).
For persons without login-capabilities (e.g. for an address-database), you shouldn't extend `[api:Member]` to avoid conflicts For persons without login-capabilities (e.g. for an address-database), you shouldn't extend [api:Member] to avoid conflicts
with the Member-database. This enables us to have a different subclass of `[api:Member]` for an email-address with login-data, with the Member-database. This enables us to have a different subclass of [api:Member] for an email-address with login-data,
and another subclass for the same email-address in the address-database. and another subclass for the same email-address in the address-database.
## Member Role Decorator ## Member Role Decorator
@ -96,9 +96,9 @@ class. A better way is to use role decorators to add this behaviour.
// OR // OR
Member::add_role('ForumRole'); Member::add_role('ForumRole');
A role decorator is simply a subclass of `[api:DataObjectDecorator]` that is designed to be used to add behaviour to `[api:Member]`. A role decorator is simply a subclass of [api:DataObjectDecorator] that is designed to be used to add behaviour to [api:Member].
The roles affect the entire class - all members will get the additional behaviour. However, if you want to restrict The roles affect the entire class - all members will get the additional behaviour. However, if you want to restrict
things, you should add appropriate `[api:Permission::checkMember()]` calls to the role's methods. things, you should add appropriate [api:Permission::checkMember()] calls to the role's methods.
:::php :::php
class ForumRole extends DataObjectDecorator { class ForumRole extends DataObjectDecorator {
@ -125,4 +125,4 @@ things, you should add appropriate `[api:Permission::checkMember()]` calls to th
## API Documentation ## API Documentation
`[api:Member]` [api:Member]

View File

@ -5,10 +5,10 @@
*Replaces GenericDataAdmin in Silverstripe 2.3* *Replaces GenericDataAdmin in Silverstripe 2.3*
The ModelAdmin provides a simple way to utilize the SilverStripe CMS UI with your own custom data models. The The ModelAdmin provides a simple way to utilize the SilverStripe CMS UI with your own custom data models. The
ModelAdmin uses the `[api:DataObject]`'s Scaffolding to create the search fields, forms, and displayed data within the ModelAdmin uses the [api:DataObject]'s Scaffolding to create the search fields, forms, and displayed data within the
CMS. CMS.
In order to customize the ModelAdmin CMS interface you will need to understand how `[api:DataObject]` works. In order to customize the ModelAdmin CMS interface you will need to understand how [api:DataObject] works.
## Requirements ## Requirements
@ -35,11 +35,11 @@ data objects you want to scaffold an interface for:
To add the ModelAdmin to your CMS menu, you simply need to define a couple of statics on your ModelAdmin subclass. See To add the ModelAdmin to your CMS menu, you simply need to define a couple of statics on your ModelAdmin subclass. See
`[api:LeftAndMain]` on how to make your menu title translatable. [api:LeftAndMain] on how to make your menu title translatable.
### Step 2 ### Step 2
Add a `$searchable_fields` (See `[api:ModelAdmin::$searchable_fields]`) property to your data Add a `$searchable_fields` (See [api:ModelAdmin::$searchable_fields]) property to your data
models, to define the fields and filters for the search interface: models, to define the fields and filters for the search interface:
Datamodel `Product`: Datamodel `Product`:
@ -97,19 +97,19 @@ If you are seeing a list of ID#s when creating new objects, ensure you have one
You can customize the fields which are searchable for each managed DataObject class, as well as the ways in which the You can customize the fields which are searchable for each managed DataObject class, as well as the ways in which the
fields are searched (e.g. "partial match", "fulltext", etc.) using `$searchable_fields`. fields are searched (e.g. "partial match", "fulltext", etc.) using `$searchable_fields`.
* See `[api:DataObject]` * See [api:DataObject]
![](_images/modeladmin_search.png) ![](_images/modeladmin_search.png)
## Summary Fields ## Summary Fields
Summary Fields are the columns which are shown in the `[api:TableListField]` when viewing DataObjects. These can be Summary Fields are the columns which are shown in the [api:TableListField] when viewing DataObjects. These can be
customized for each `[api:DataObject]`'s search results using `$summary_fields`. customized for each [api:DataObject]'s search results using `$summary_fields`.
* See `[api:DataObject]` * See [api:DataObject]
## Related ## Related
* `[api:SearchContext]` * [api:SearchContext]
* [genericviews Module] `http://silverstripe.org/generic-views-module` * [genericviews Module] `http://silverstripe.org/generic-views-module`
* [Presentation about ModelAdmin at SupperHappyDevHouse Wellington](http://www.slideshare.net/chillu/modeladmin-in-silverstripe-23) * [Presentation about ModelAdmin at SupperHappyDevHouse Wellington](http://www.slideshare.net/chillu/modeladmin-in-silverstripe-23)

View File

@ -55,7 +55,7 @@ From a block that shows a summary of the page edits if administrator, nothing if
Often you want to invalidate a cache when any in a set of objects change, or when the objects in a relationship change. Often you want to invalidate a cache when any in a set of objects change, or when the objects in a relationship change.
To help do this, SilverStripe 2.4 also introduces the concept of Aggregates. These calculate and return SQL aggregates To help do this, SilverStripe 2.4 also introduces the concept of Aggregates. These calculate and return SQL aggregates
on sets of `[api:DataObject]`s - the most useful for us being the Max aggregate. on sets of [api:DataObject]s - the most useful for us being the Max aggregate.
For example, if we have a menu, we want that menu to update whenever _any_ page is edited, but would like to cache it For example, if we have a menu, we want that menu to update whenever _any_ page is edited, but would like to cache it
otherwise. By using aggregates, that's easy otherwise. By using aggregates, that's easy

View File

@ -22,7 +22,7 @@ You can use whatever codes you like, but for the sanity of developers and users,
## PermissionProvider ## PermissionProvider
`[api:PermissionProvider]` is an interface which lets you define a method *providePermissions()*. This method should return a [api:PermissionProvider] is an interface which lets you define a method *providePermissions()*. This method should return a
map of permission code names with a human readable explanation of its purpose (see map of permission code names with a human readable explanation of its purpose (see
[permissions:codes](/reference/permission)). [permissions:codes](/reference/permission)).
@ -71,4 +71,4 @@ information on request objects.
## API Documentation ## API Documentation
`[api:Permission]` [api:Permission]

View File

@ -8,7 +8,7 @@ hardcoding any references in the `<head>`-tag of your template, as it enables a
## Including inside PHP Code ## Including inside PHP Code
It is common practice to include most Requirements either in the *init()*-method of your [controller](/topics/controller), or It is common practice to include most Requirements either in the *init()*-method of your [controller](/topics/controller), or
as close to rendering as possible (e.g. in `[api:FormField]` as close to rendering as possible (e.g. in [api:FormField]
:::php :::php
Requirements::javascript("cms/javascript/LeftAndMain.js"); Requirements::javascript("cms/javascript/LeftAndMain.js");
@ -133,7 +133,7 @@ In your controller's init() function, add:
## CMS Requirements ## CMS Requirements
The SilverStripe core includes a lot of Requirements by itself. Most of these are collated in `[api:LeftAndMain]` first. The SilverStripe core includes a lot of Requirements by itself. Most of these are collated in [api:LeftAndMain] first.
## Motivation ## Motivation
@ -189,4 +189,4 @@ slightly different JS/CSS requirements, the whole lot will be refetched.
nature of an ajax-request. Needs some more research nature of an ajax-request. Needs some more research
## API Documentation ## API Documentation
`[api:Requirements]` [api:Requirements]

View File

@ -2,11 +2,11 @@
## Introduction ## Introduction
`[api:RestfulService]` enables connecting to remote web services which supports REST interface and consume those web services [api:RestfulService] enables connecting to remote web services which supports REST interface and consume those web services
(for example [Flickr](http://www.flickr.com/services/api/), [Youtube](http://code.google.com/apis/youtube/overview.html), Amazon and etc). `[api:RestfulService]` can parse the XML response (sorry no JSON support) (for example [Flickr](http://www.flickr.com/services/api/), [Youtube](http://code.google.com/apis/youtube/overview.html), Amazon and etc). [api:RestfulService] can parse the XML response (sorry no JSON support)
returned from the web service. Further it supports caching of the response, and you can customize the cache interval. returned from the web service. Further it supports caching of the response, and you can customize the cache interval.
To gain the functionality you can either create a new `[api:RestfulService]` object or create a class extending the To gain the functionality you can either create a new [api:RestfulService] object or create a class extending the
RestfulService (see [flickrservice] `http://silverstripe.org/flickr-module` and RestfulService (see [flickrservice] `http://silverstripe.org/flickr-module` and
[youtubeservice] `http://silverstripe.org/youtube-gallery-module/` modules). [youtubeservice] `http://silverstripe.org/youtube-gallery-module/` modules).
@ -113,7 +113,7 @@ to get the value of entry node with the namespace media, use:
### Handling Errors ### Handling Errors
If the web service returned an error (for example, API key not available or inadequate parameters) `[api:RestfulService]` If the web service returned an error (for example, API key not available or inadequate parameters) [api:RestfulService]
could delgate the error handling to it's descendant class. To handle the errors define a function called errorCatch could delgate the error handling to it's descendant class. To handle the errors define a function called errorCatch
:::php :::php
@ -143,9 +143,9 @@ If you want to bypass error handling on your sub-classes you could define that i
## Other Uses ## Other Uses
### How to use `[api:RestfulService]` to easily embed an RSS feed ### How to use [api:RestfulService] to easily embed an RSS feed
`[api:RestfulService]` can be used to easily embed an RSS feed (since it's also an xml response) from a site [api:RestfulService] can be used to easily embed an RSS feed (since it's also an xml response) from a site
such as del.icio.us such as del.icio.us
Put something like this code in mysite/code/Page.php inside class Page_Controller Put something like this code in mysite/code/Page.php inside class Page_Controller
@ -177,4 +177,4 @@ Put something like this code in mysite/templates/Layout/HomePage.ss:
## API Documentation ## API Documentation
`[api:RestfulService]` [api:RestfulService]

View File

@ -2,12 +2,12 @@
## Introduction ## Introduction
Generating RSS/Atom-feeds is just a matter of rendering a `[api:DataObject]` and the Page Comment Interface. Generating RSS/Atom-feeds is just a matter of rendering a [api:DataObject] and the Page Comment Interface.
Handled through the `[api:RSSFeed]` class. Handled through the [api:RSSFeed] class.
`[api:RSSFeed]` doesn't limit you to generating "article-based" feeds, it is just as easy to create a feed of your current [api:RSSFeed] doesn't limit you to generating "article-based" feeds, it is just as easy to create a feed of your current
staff-members. The only logical limitation here is that every item in the RSS-feed should be accessible through a URL on staff-members. The only logical limitation here is that every item in the RSS-feed should be accessible through a URL on
your website, so its advisable to just create feeds from subclasses of `[api:SiteTree]`. your website, so its advisable to just create feeds from subclasses of [api:SiteTree].
## Usage ## Usage
@ -31,7 +31,7 @@ your website, so its advisable to just create feeds from subclasses of `[api:Sit
### Example of showing the 10 most recently updated pages ### Example of showing the 10 most recently updated pages
You can use `[api:RSSFeed]` to easily create a feed showing your latest Page updates. Just change mysite/code/Page.php to You can use [api:RSSFeed] to easily create a feed showing your latest Page updates. Just change mysite/code/Page.php to
something like this: something like this:
:::php :::php
@ -72,7 +72,7 @@ can also do http://www.yoursite.com/PageComment/rss?pageid=46 where pageid is th
## External Sources ## External Sources
`[api:RSSFeed]` only creates feeds from your own data. We've included the [SimplePie](http://simplepie.org) RSS-parser for [api:RSSFeed] only creates feeds from your own data. We've included the [SimplePie](http://simplepie.org) RSS-parser for
accessing feeds from external sources. accessing feeds from external sources.
@ -81,4 +81,4 @@ accessing feeds from external sources.
* [blog module](http://silverstripe.org/blog-module) * [blog module](http://silverstripe.org/blog-module)
## API Documentation ## API Documentation
`[api:RSSFeed]` [api:RSSFeed]

View File

@ -2,17 +2,17 @@
## Introduction ## Introduction
Manages searching of properties on one or more `[api:DataObject]` types, based on a given set of input parameters. Manages searching of properties on one or more [api:DataObject] types, based on a given set of input parameters.
`[api:SearchContext]` is intentionally decoupled from any controller-logic, [api:SearchContext] is intentionally decoupled from any controller-logic,
it just receives a set of search parameters and an object class it acts on. it just receives a set of search parameters and an object class it acts on.
The default output of a `[api:SearchContext]` is either a `[api:SQLQuery]` object for further refinement, or a The default output of a [api:SearchContext] is either a [api:SQLQuery] object for further refinement, or a
`[api:DataObject]` instance. [api:DataObject] instance.
In case you need multiple contexts, consider namespacing your request parameters by using `FieldSet->namespace()` on In case you need multiple contexts, consider namespacing your request parameters by using `FieldSet->namespace()` on
the $fields constructor parameter. the $fields constructor parameter.
`[api:SearchContext]` is mainly used by `[api:ModelAdmin]`, our generic data administration interface. Another [api:SearchContext] is mainly used by [api:ModelAdmin], our generic data administration interface. Another
implementation can be found in generic frontend search forms through the [genericviews] `http://silverstripe.org/generic-views-module` module. implementation can be found in generic frontend search forms through the [genericviews] `http://silverstripe.org/generic-views-module` module.
## Requirements ## Requirements
@ -29,7 +29,7 @@ Getting results
### Defining fields on your DataObject ### Defining fields on your DataObject
See `[api:DataObject::$searchable_fields]`. See [api:DataObject::$searchable_fields].
### Customizing fields and filters ### Customizing fields and filters
@ -180,13 +180,13 @@ Results.PaginationSummary(4) defines how many pages the search will show in the
## Available SearchFilters ## Available SearchFilters
See `[api:SearchFilter]` API Documentation See [api:SearchFilter] API Documentation
## API Documentation ## API Documentation
`[api:SearchContext]` [api:SearchContext]
## Related ## Related
* `[api:ModelAdmin]` * [api:ModelAdmin]
* `[api:RestfulServer]` * [api:RestfulServer]
* [Tutorial: Site Search](/tutorials/site-search) * [Tutorial: Site Search](/tutorials/site-search)

View File

@ -91,4 +91,4 @@ file and add class's as you need them inside that for each report.
* More examples. * More examples.
## API Documentation ## API Documentation
`[api:ReportAdmin]` [api:ReportAdmin]

View File

@ -2,12 +2,12 @@
## Introduction ## Introduction
The `[api:SiteConfig]` panel was introduced in 2.4 for providing a generic interface for managing site wide settings or The [api:SiteConfig] panel was introduced in 2.4 for providing a generic interface for managing site wide settings or
functionality which is used throughout the site. Out of the box it provides 2 fields 'Site Name' and 'Site Tagline'. functionality which is used throughout the site. Out of the box it provides 2 fields 'Site Name' and 'Site Tagline'.
## Accessing `[api:SiteConfig]` Options ## Accessing [api:SiteConfig] Options
You can access `[api:SiteConfig]` options from any SS template by using the function $SiteConfig.FieldName You can access [api:SiteConfig] options from any SS template by using the function $SiteConfig.FieldName
:::ss :::ss
$SiteConfig.Title $SiteConfig.Title
@ -28,7 +28,7 @@ Or if you want to access variables in the PHP you can do
$config->Title $config->Title
## Extending `[api:SiteConfig]` ## Extending [api:SiteConfig]
To extend the options available in the panel you can define your own fields via an Extension. To extend the options available in the panel you can define your own fields via an Extension.
@ -58,13 +58,13 @@ Then add a link to your extension in the _config.php file like below.
Object::add_extension('SiteConfig', 'CustomSiteConfig'); Object::add_extension('SiteConfig', 'CustomSiteConfig');
This tells SilverStripe to add the CustomSiteConfig extension to the `[api:SiteConfig]` class. This tells SilverStripe to add the CustomSiteConfig extension to the [api:SiteConfig] class.
After adding those two pieces of code, rebuild your database by visiting http://yoursite.com/dev/build and then reload After adding those two pieces of code, rebuild your database by visiting http://yoursite.com/dev/build and then reload
the admin interface. You may need to reload it with a ?flush=1 on the end. the admin interface. You may need to reload it with a ?flush=1 on the end.
You can define as many extensions for `[api:SiteConfig]` as you need. For example if you are developing a module you can define You can define as many extensions for [api:SiteConfig] as you need. For example if you are developing a module you can define
your own global settings for the dashboard. your own global settings for the dashboard.
## API Documentation ## API Documentation
`[api:SiteConfig]` [api:SiteConfig]

View File

@ -144,7 +144,7 @@ it is a good starting point, for choosing your customisation.
### Automatic Child Selection ### Automatic Child Selection
By default, `[api:SiteTree]` class to build a tree using the ParentID field. However, sometimes, you want to change By default, [api:SiteTree] class to build a tree using the ParentID field. However, sometimes, you want to change
this default behaviour. this default behaviour.
For example, in our e-commerce module, we use a many-to-many join, Product::Parents, to let you put Products in multiple For example, in our e-commerce module, we use a many-to-many join, Product::Parents, to let you put Products in multiple
@ -154,7 +154,7 @@ groups. Here's how to implement such a change:
store parents. store parents.
* **Define stageChildren method:** This method should return the children of the current page, for the current version. * **Define stageChildren method:** This method should return the children of the current page, for the current version.
If you use DataObject::get, the `[api:Versioned]` class will rewrite your query to access the live site when If you use DataObject::get, the [api:Versioned] class will rewrite your query to access the live site when
appropriate. appropriate.
* **Define liveChildren method:** The method should return the children of the current page, for the live site. * **Define liveChildren method:** The method should return the children of the current page, for the live site.
@ -206,7 +206,7 @@ Example:
### Multiple parents in the tree ### Multiple parents in the tree
The `[api:LeftAndMain]` tree supports multiple parents. We overload CMSTreeClasses and make it include "manyparents" in The [api:LeftAndMain] tree supports multiple parents. We overload CMSTreeClasses and make it include "manyparents" in
the class list. the class list.
:::php :::php
@ -295,4 +295,4 @@ and the specific group.
Clean up this documentation Clean up this documentation
## API Documentation ## API Documentation
`[api:Sitetree]` [api:Sitetree]

View File

@ -3,7 +3,7 @@
## Introduction ## Introduction
An object representing a SQL query. It is easier to deal with object-wrappers than string-parsing a raw SQL-query. This An object representing a SQL query. It is easier to deal with object-wrappers than string-parsing a raw SQL-query. This
object is used by `[api:DataObject]`, though... object is used by [api:DataObject], though...
A word of caution: Dealing with low-level SQL is not encouraged in the SilverStripe [datamodel](/topics/datamodel) for various A word of caution: Dealing with low-level SQL is not encouraged in the SilverStripe [datamodel](/topics/datamodel) for various
reasons. You'll break the behaviour of: reasons. You'll break the behaviour of:
@ -12,7 +12,7 @@ reasons. You'll break the behaviour of:
* DataObject::onBeforeWrite/onBeforeDelete * DataObject::onBeforeWrite/onBeforeDelete
* Automatic casting * Automatic casting
* Default-setting through object-model * Default-setting through object-model
* `[api:DataObject]` * [api:DataObject]
* Database abstraction * Database abstraction
We'll explain some ways to use *SELECT* with the full power of SQL, but still maintain a connection to the SilverStripe We'll explain some ways to use *SELECT* with the full power of SQL, but still maintain a connection to the SilverStripe
@ -62,7 +62,7 @@ We'll explain some ways to use *SELECT* with the full power of SQL, but still ma
## Working with results ## Working with results
The result is an array lightly wrapped in a database-specific subclass of `[api:Query]`. This class implements the The result is an array lightly wrapped in a database-specific subclass of [api:Query]. This class implements the
*Iterator*-interface defined in PHP5, and provides convenience-methods for accessing the data. *Iterator*-interface defined in PHP5, and provides convenience-methods for accessing the data.
### Iterating ### Iterating
@ -87,7 +87,7 @@ Raw SQL is handy for performance-optimized calls.
return $sqlQuery->execute()->value(); return $sqlQuery->execute()->value();
} }
Way faster than dealing with `[api:DataObject]`s, but watch out for premature optimisation: Way faster than dealing with [api:DataObject]s, but watch out for premature optimisation:
:::php :::php
$players = $myTeam->Players(); $players = $myTeam->Players();
@ -142,10 +142,10 @@ This form of building a query has the following advantages:
* Selection of *ID*, *ClassName*, *RecordClassName*, which are necessary to use *buildDataObjectSet* later on * Selection of *ID*, *ClassName*, *RecordClassName*, which are necessary to use *buildDataObjectSet* later on
* Filtering records for correct *ClassName* * Filtering records for correct *ClassName*
### Transforming a result to `[api:DataObjectSet]` ### Transforming a result to [api:DataObjectSet]
This is a commonly used technique inside SilverStripe: Use raw SQL, but transfer the resulting rows back into This is a commonly used technique inside SilverStripe: Use raw SQL, but transfer the resulting rows back into
`[api:DataObject]`s. [api:DataObject]s.
:::php :::php
$sqlQuery = new SQLQuery(); $sqlQuery = new SQLQuery();
@ -188,21 +188,21 @@ This is a commonly used technique inside SilverStripe: Use raw SQL, but transfer
* Not all object-properties accessible: You need to take care of selecting the right stuff yourself * Not all object-properties accessible: You need to take care of selecting the right stuff yourself
* Overlayed object-properties: If you *LEFT JOIN* a table which also has a column 'Birthdate' and do a global select on * Overlayed object-properties: If you *LEFT JOIN* a table which also has a column 'Birthdate' and do a global select on
this table, you might not be able to access original object-properties. this table, you might not be able to access original object-properties.
* You can't create `[api:DataObject]`s where no scalar record-data is available, e.g. when using *GROUP BY* * You can't create [api:DataObject]s where no scalar record-data is available, e.g. when using *GROUP BY*
* Naming conflicts with custom getters: A getter like Player->getName() will overlay the column-data selected in the * Naming conflicts with custom getters: A getter like Player->getName() will overlay the column-data selected in the
above example above example
Be careful when saving back `[api:DataObject]`s created through *buildDataObjectSet*, you might get strange side-effects due to Be careful when saving back [api:DataObject]s created through *buildDataObjectSet*, you might get strange side-effects due to
the issues noted above. the issues noted above.
## Using FormFields with custom SQL ## Using FormFields with custom SQL
Some subclasses of `[api:FormField]` for ways to create sophisticated report-tables based on SQL. Some subclasses of [api:FormField] for ways to create sophisticated report-tables based on SQL.
## Related ## Related
* [datamodel](/topics/datamodel) * [datamodel](/topics/datamodel)
* `[api:DataObject]` * [api:DataObject]
* [database-structure](database-structure) * [database-structure](database-structure)
## API Documentation ## API Documentation
`[api:SQLQuery]` [api:SQLQuery]

View File

@ -5,7 +5,7 @@
Many sites get too much traffic to justify dynamically sending every request. Caching is needed. Static Publishing Many sites get too much traffic to justify dynamically sending every request. Caching is needed. Static Publishing
will generate static versions of your content (HTML) that can be served without ever hitting PHP or the Database. will generate static versions of your content (HTML) that can be served without ever hitting PHP or the Database.
See `[api:StaticExporter]` for a less flexible, but easier way of building a local static cache from all of See [api:StaticExporter] for a less flexible, but easier way of building a local static cache from all of
your pages. your pages.
See [Partial-Caching](partial-caching) for a much more flexible way of building in caching without statically delivering See [Partial-Caching](partial-caching) for a much more flexible way of building in caching without statically delivering
@ -262,7 +262,7 @@ example] `http://open.silverstripe.com/browser/modules/cms/trunk/code/staticpubl
## Deployment ## Deployment
Once you've set up your rewrite rules and defined which pages need caching, you can build the static HTML files. This is Once you've set up your rewrite rules and defined which pages need caching, you can build the static HTML files. This is
done by the `[api:RebuildStaticCacheTask]` done by the [api:RebuildStaticCacheTask]
Execution via URL Execution via URL
@ -281,8 +281,8 @@ the cache.
## Related ## Related
* `[api:StaticExporter]` * [api:StaticExporter]
* [Partial-Caching](partial-caching) * [Partial-Caching](partial-caching)
## API Documentation ## API Documentation
* `[api:StaticPublisher]` * [api:StaticPublisher]

View File

@ -2,10 +2,10 @@
## Introduction ## Introduction
`[api:TableField]` behaves in the same manner as `[api:TableListField]`, however allows the editing of existing and adding of [api:TableField] behaves in the same manner as [api:TableListField], however allows the editing of existing and adding of
new rows. The data is saved back by the surrounding form-saving (mostly EditForm->save). new rows. The data is saved back by the surrounding form-saving (mostly EditForm->save).
See `[api:TableListField]` for more documentation on the base-class See [api:TableListField] for more documentation on the base-class
## Usage ## Usage
@ -44,7 +44,7 @@ is created.
### Row Transformation ### Row Transformation
You can apply a `[api:FormTransformation]` to any given field, You can apply a [api:FormTransformation] to any given field,
based on a eval()ed php-rule. You can access all columns on the generated DataObjects here. based on a eval()ed php-rule. You can access all columns on the generated DataObjects here.
:::php :::php
@ -59,23 +59,23 @@ based on a eval()ed php-rule. You can access all columns on the generated DataOb
### Required Fields ### Required Fields
Due to the nested nature of this fields dataset, you can't set any required columns as usual with the Due to the nested nature of this fields dataset, you can't set any required columns as usual with the
`[api:RequiredFields]`** on the TableField-instance for this. [api:RequiredFields]** on the TableField-instance for this.
Note: You still have to attach some form of `[api:Validator]` to the form to trigger any validation on this field. Note: You still have to attach some form of [api:Validator] to the form to trigger any validation on this field.
### Nested Table Fields ### Nested Table Fields
When you have `[api:TableField]` inside a `[api:ComplexTableField]`, the parent ID may not be known in your When you have [api:TableField] inside a [api:ComplexTableField], the parent ID may not be known in your
getCMSFields() method. In these cases, you can set a value to '$RecordID' in your `[api:TableField]` extra data, and this getCMSFields() method. In these cases, you can set a value to '$RecordID' in your [api:TableField] extra data, and this
will be populated with the newly created record id upon save. will be populated with the newly created record id upon save.
## Known Issues ## Known Issues
* A `[api:TableField]` doesn't reload any submitted form-data if the saving is interrupted by a failed validation. After * A [api:TableField] doesn't reload any submitted form-data if the saving is interrupted by a failed validation. After
refreshing the form with the validation-errors, the `[api:TableField]` will be blank again. refreshing the form with the validation-errors, the [api:TableField] will be blank again.
* You can't add **visible default data** to columns in a `[api:TableField]`, please use *setExtraData* * You can't add **visible default data** to columns in a [api:TableField], please use *setExtraData*
## API Documentation ## API Documentation
`[api:TableField]` [api:TableField]

View File

@ -2,13 +2,13 @@
## Introduction ## Introduction
Form field that embeds a list of `[api:DataObject]`s into a form, such as a member list or a file list. Form field that embeds a list of [api:DataObject]s into a form, such as a member list or a file list.
Provides customizeable columns, record-deletion by ajax, paging, sorting, CSV-export, printing, input by Provides customizeable columns, record-deletion by ajax, paging, sorting, CSV-export, printing, input by
`[api:DataObject]` or raw SQL. [api:DataObject] or raw SQL.
## Example ## Example
Here's an example of a full featured `[api:TableListField]` implementation. It features editing members in the database Here's an example of a full featured [api:TableListField] implementation. It features editing members in the database
directly as a button on each record, as well as filtering, and sorting. It also makes use of the 'export' permission, directly as a button on each record, as well as filtering, and sorting. It also makes use of the 'export' permission,
allowing export of data as a CSV. allowing export of data as a CSV.
@ -90,7 +90,7 @@ For more information on each of the features used in the example, you can read b
$customCsvQuery->select[] = "CONCAT(col1,col2) AS MyCustomSQLColumn"; $customCsvQuery->select[] = "CONCAT(col1,col2) AS MyCustomSQLColumn";
$myTableListField->setCustomCsvQuery($customQuery); $myTableListField->setCustomCsvQuery($customQuery);
`[api:TableListField]` also tries to resolve Component-relations(has_one, has_many) and custom getters automatically: [api:TableListField] also tries to resolve Component-relations(has_one, has_many) and custom getters automatically:
:::php :::php
$myTableListField = new TableListField( $myTableListField = new TableListField(
@ -139,7 +139,7 @@ Example (sorting by "FirstName" column):
); );
If you want to sort by custom getters in your `[api:DataObject]`, please reformulate them to a custom SQL column. This If you want to sort by custom getters in your [api:DataObject], please reformulate them to a custom SQL column. This
restriction is needed to avoid performance-hits by caching and sorting potentially large datasets on PHP-level. restriction is needed to avoid performance-hits by caching and sorting potentially large datasets on PHP-level.
### Casting ### Casting
@ -155,7 +155,7 @@ Column-values can be casted, based on the casting-types available through DBObje
### Permissions ### Permissions
Permissions vary in different `[api:TableListField]`-implementations, and are evaluated in the template. Permissions vary in different [api:TableListField]-implementations, and are evaluated in the template.
By default, all listed permissions are enabled. By default, all listed permissions are enabled.
:::php :::php
@ -237,7 +237,7 @@ implement averages etc.
) )
); );
In `[api:TableListField]`-implementation, these summaries also react to changes in input-fields by javascript. In [api:TableListField]-implementation, these summaries also react to changes in input-fields by javascript.
Available methods: Available methods:
* sum * sum
@ -245,7 +245,7 @@ Available methods:
### Grouping ### Grouping
Used to group by a specific column in the `[api:DataObject]` and create partial summaries. Used to group by a specific column in the [api:DataObject] and create partial summaries.
Please use only together with addSummary(). Please use only together with addSummary().
(Automatically disables sorting). (Automatically disables sorting).
@ -257,7 +257,7 @@ Please use only together with addSummary().
### Custom Sorting ### Custom Sorting
Please subclass `[api:TableListField]` to implement custom sorting, following the naming-convention Please subclass [api:TableListField] to implement custom sorting, following the naming-convention
"`colFunction_<yourFunctionName>`". "`colFunction_<yourFunctionName>`".
:::php :::php
@ -285,4 +285,4 @@ You can exchange the used template, e.g. to change applied CSS-classes or the HT
## API Documentation ## API Documentation
`[api:TableListField]` [api:TableListField]

View File

@ -88,7 +88,7 @@ OtherContent:
### Removing the typography class ### Removing the typography class
Sometimes, it's not enough to add a class, you also want to remove the typography class. You can use the Sometimes, it's not enough to add a class, you also want to remove the typography class. You can use the
`[api:HTMLEditorField]` method setCSSClass. [api:HTMLEditorField] method setCSSClass.
This example sets another CSS class typographybis: This example sets another CSS class typographybis:

View File

@ -29,7 +29,7 @@ Append the option and corresponding value to your URL in your browser's address
| isDev | | 1 | | Put the site into [development mode](/topics/debugging), enabling debugging messages to the browser on a live server. For security, you'll be asked to log in with an administrator log-in | | isDev | | 1 | | Put the site into [development mode](/topics/debugging), enabling debugging messages to the browser on a live server. For security, you'll be asked to log in with an administrator log-in |
| isTest | | 1 | | Put the site into [test mode](/topics/debugging), enabling debugging messages to the admin email and generic errors to the browser on a live server | | isTest | | 1 | | Put the site into [test mode](/topics/debugging), enabling debugging messages to the admin email and generic errors to the browser on a live server |
| debug | | 1 | | Show a collection of debugging information about the director / controller operation | | debug | | 1 | | Show a collection of debugging information about the director / controller operation |
| debug_request | | 1 | | Show all steps of the request from initial `[api:HTTPRequest]` to `[api:Controller]` to Template Rendering | | debug_request | | 1 | | Show all steps of the request from initial [api:HTTPRequest] to [api:Controller] to Template Rendering |
## Classes and Objects ## Classes and Objects

View File

@ -1,6 +1,6 @@
# Versioned # Versioned
The Versioned class is a `[api:DataObject]` that adds versioning and staging capabilities to the objects. The Versioned class is a [api:DataObject] that adds versioning and staging capabilities to the objects.
## Trapping the publication event ## Trapping the publication event

View File

@ -35,7 +35,7 @@ privileges from its parent group.
## Permission checking is at class level ## Permission checking is at class level
SilverStripe provides a security mechanism via the *Permission::check* method (see `[api:LeftAndMain]` for examples on how SilverStripe provides a security mechanism via the *Permission::check* method (see [api:LeftAndMain] for examples on how
the admin screens work) the admin screens work)
(next step -- go from *Permission::checkMember*...) (next step -- go from *Permission::checkMember*...)
@ -48,14 +48,14 @@ works.
### Loading the admin page: looking at security ### Loading the admin page: looking at security
If you go to [your site]/admin *Director.php* maps the 'admin' URL request through a `[api:Director]` rule to the If you go to [your site]/admin *Director.php* maps the 'admin' URL request through a [api:Director] rule to the
`[api:CMSMain]` controller (see `[api:CMSMain]`, with no arguments). [api:CMSMain] controller.
*CMSMain.init()* calls its parent which, of all things is called `[api:LeftAndMain]`. It's in `[api:LeftAndMain]` that the *CMSMain.init()* calls its parent which, of all things is called [api:LeftAndMain]. It's in [api:LeftAndMain] that the
important security checks are made by calling *Permission::check*. important security checks are made by calling *Permission::check*.
`[api:Security::permissionFailure]` is the next utility function you can use to redirect to the login form. [api:Security::permissionFailure()] is the next utility function you can use to redirect to the login form.
### Customizing Access Checks in CMS Classes ### Customizing Access Checks in CMS Classes
see `[api:LeftAndMain]` see [api:LeftAndMain]

View File

@ -12,7 +12,7 @@ CMS"] `http://www.silverstripe.com/core-team-discussion/flat/2723` for further r
In addition to these principle, some settings are In addition to these principle, some settings are
* Author-level configuration like interface language or date/time formats can be performed in the CMS "My Profile" section (`admin/myprofile`). * Author-level configuration like interface language or date/time formats can be performed in the CMS "My Profile" section (`admin/myprofile`).
* Group-related configuration like `[api:HTMLEditorField]` settings can be found in the "Security" section (`admin/security`). * Group-related configuration like [api:HTMLEditorField] settings can be found in the "Security" section (`admin/security`).
* Site-wide settings like page titles can be set (and extended) on the root tree element in the CMS "Content" section (through the [siteconfig](/reference/siteconfig) API). * Site-wide settings like page titles can be set (and extended) on the root tree element in the CMS "Content" section (through the [siteconfig](/reference/siteconfig) API).
## _ss_environment.php ## _ss_environment.php
@ -21,7 +21,7 @@ See [environment-management](/topics/environment-management).
## mysite/_config.php ## mysite/_config.php
This file is detected in each folder by `[api:ManifestBuilder]`. This way, every toplevel-folder (=module) This file is detected in each folder by [api:ManifestBuilder]. This way, every toplevel-folder (=module)
can have independent configuration-rules. can have independent configuration-rules.
@ -66,8 +66,8 @@ Some constants are user-defineable within *_ss_environment.php*.
## User-level: Member-object ## User-level: Member-object
All user-related preferences are stored as a property of the `[api:Member]`-class (and as a database-column in the All user-related preferences are stored as a property of the [api:Member]-class (and as a database-column in the
*Member*-table). You can "mix in" your custom preferences by using `[api:DataObject]` for details. *Member*-table). You can "mix in" your custom preferences by using [api:DataObject] for details.
## Permissions ## Permissions

View File

@ -130,9 +130,9 @@ permission checks.
## URL Handling ## URL Handling
In the above example the URLs were configured using the `[api:Director]` rules in the **_config.php** file. In the above example the URLs were configured using the [api:Director] rules in the **_config.php** file.
Alternatively you can specify these in your Controller class via the **$url_handlers** static array (which gets Alternatively you can specify these in your Controller class via the **$url_handlers** static array (which gets
processed by the `[api:RequestHandler]`). processed by the [api:RequestHandler]).
This is useful when you want to subvert the fixed action mapping of `fastfood/order/*` to the function **order**. In This is useful when you want to subvert the fixed action mapping of `fastfood/order/*` to the function **order**. In
the case below we also want any orders coming through `/fastfood/drivethrough/` to use the same order function. the case below we also want any orders coming through `/fastfood/drivethrough/` to use the same order function.
@ -150,7 +150,7 @@ the case below we also want any orders coming through `/fastfood/drivethrough/`
## URL Patterns ## URL Patterns
The `[api:RequestHandler]` class will parse all rules you specify against the following patterns. The [api:RequestHandler] class will parse all rules you specify against the following patterns.
**A rule must always start with alphabetical ([A-Za-z]) characters or a $Variable declaration** **A rule must always start with alphabetical ([A-Za-z]) characters or a $Variable declaration**
@ -181,10 +181,10 @@ You can use the `debug_request=1` switch from the [urlvariabletools](/reference/
## API Documentation ## API Documentation
`[api:Controller]` [api:Controller]
## Links ## Links
* `[api:Director]` class * [api:Director] class
* [execution-pipeline](/reference/execution-pipeline) * [execution-pipeline](/reference/execution-pipeline)
* [URL Handling in Controllers](http://maetl.net/silverstripe-url-handling) by maetl * [URL Handling in Controllers](http://maetl.net/silverstripe-url-handling) by maetl

View File

@ -1,29 +1,29 @@
# Data Types # Data Types
These are the data-types that you can use when defining your data objects. They are all subclasses of `[api:DBField]` These are the data-types that you can use when defining your data objects. They are all subclasses of [api:DBField]
for introducing their usage. for introducing their usage.
## Types ## Types
* `[api:Varchar]`: A variable-length string of up to 255 characters, designed to store raw text * [api:Varchar]: A variable-length string of up to 255 characters, designed to store raw text
* `[api:Text]`: A variable-length string of up to 2 megabytes, designed to store raw text * [api:Text]: A variable-length string of up to 2 megabytes, designed to store raw text
* `[api:HTMLVarchar]`: A variable-length string of up to 255 characters, designed to store HTML * [api:HTMLVarchar]`: A variable-length string of up to 255 characters, designed to store HTML
* `[api:HTMLText]`: A variable-length string of up to 2 megabytes, designed to store HTML * [api:HTMLText]: A variable-length string of up to 2 megabytes, designed to store HTML
* `[api:Enum]`: An enumeration of a set of strings * [api:Enum]: An enumeration of a set of strings
* `[api:Boolean]`: A boolean field. * [api:Boolean]: A boolean field.
* `[api:Int]`: An integer field. * [api:Int]: An integer field.
* `[api:Decimal]`: A decimal number. * [api:Decimal]: A decimal number.
* `[api:Currency]`: A number with 2 decimal points of precision, designed to store currency values. * [api:Currency]: A number with 2 decimal points of precision, designed to store currency values.
* `[api:Percentage]`: A decimal number between 0 and 1 that represents a percentage. * [api:Percentage]: A decimal number between 0 and 1 that represents a percentage.
* `[api:Date]`: A date field * [api:Date]: A date field
* `[api:SS_Datetime]`: A date / time field * [api:SS_Datetime]: A date / time field
* `[api:Time]`: A time field * [api:Time]: A time field
## HTMLText vs. Text, and HTMLVarchar vs. Varchar ## HTMLText vs. Text, and HTMLVarchar vs. Varchar
The database field types `[api:HTMLVarchar]` and `[api:Varchar]` are exactly the same in the database. However, the The database field types [api:HTMLVarchar] and [api:Varchar] are exactly the same in the database. However, the
templating engine knows to escape the `[api:Varchar]` field and not the `[api:HTMLVarchar]` field. So, it's important you templating engine knows to escape the [api:Varchar] field and not the [api:HTMLVarchar] field. So, it's important you
use the right field if you don't want to be putting $FieldType.XML everywhere. use the right field if you don't want to be putting $FieldType.XML everywhere.
If you're going to put HTML content into the field, please use the field type with the HTML prefix. Otherwise, you're If you're going to put HTML content into the field, please use the field type with the HTML prefix. Otherwise, you're

View File

@ -7,13 +7,13 @@ following connections:
* Each database-row maps to a php-object * Each database-row maps to a php-object
* Each database-column maps to a property on a php-object * Each database-column maps to a property on a php-object
All data tables in SilverStripe are defined as subclasses of `[api:DataObject]`. Inheritance is supported in the data All data tables in SilverStripe are defined as subclasses of [api:DataObject]. Inheritance is supported in the data
model: seperate tables will be linked together, the data spread across these tables. The mapping and saving/loading model: seperate tables will be linked together, the data spread across these tables. The mapping and saving/loading
logic is handled by sapphire, you don't need to worry about writing SQL most of the time. logic is handled by sapphire, you don't need to worry about writing SQL most of the time.
The advanced object-relational layer in SilverStripe is one of the main reasons for requiring PHP5. Most of its The advanced object-relational layer in SilverStripe is one of the main reasons for requiring PHP5. Most of its
customizations are possible through [PHP5 Object customizations are possible through [PHP5 Object
Overloading](http://www.onlamp.com/pub/a/php/2005/06/16/overloading.html) handled in the `[api:Object]`-class. Overloading](http://www.onlamp.com/pub/a/php/2005/06/16/overloading.html) handled in the [api:Object]-class.
See [database-structure](/reference/database-structure) for in-depth information on the database-schema. See [database-structure](/reference/database-structure) for in-depth information on the database-schema.
@ -29,7 +29,7 @@ Note: You need to be logged in as an administrator to perform this command.
## Querying Data ## Querying Data
There are static methods available for querying data. They automatically compile the necessary SQL to query the database There are static methods available for querying data. They automatically compile the necessary SQL to query the database
so they are very helpful. In case you need to fall back to plain-jane SQL, have a look at `[api:SQLQuery]`. so they are very helpful. In case you need to fall back to plain-jane SQL, have a look at [api:SQLQuery].
:::php :::php
$records = DataObject::get($obj, $filter, $sort, $join, $limit); $records = DataObject::get($obj, $filter, $sort, $join, $limit);
@ -46,7 +46,7 @@ so they are very helpful. In case you need to fall back to plain-jane SQL, have
Passing a *$join* statement to DataObject::get will filter results further by the JOINs performed against the foreign Passing a *$join* statement to DataObject::get will filter results further by the JOINs performed against the foreign
table. **It will NOT return the additionally joined data.** The returned *$records* will always be a table. **It will NOT return the additionally joined data.** The returned *$records* will always be a
`[api:DataObject]`. [api:DataObject].
When using *$join* statements be sure the string is in the proper format for the respective database engine. In MySQL When using *$join* statements be sure the string is in the proper format for the respective database engine. In MySQL
the use of back-ticks may be necessary when referring Table Names and potentially Columns. (see [MySQL the use of back-ticks may be necessary when referring Table Names and potentially Columns. (see [MySQL
@ -188,7 +188,7 @@ on the "Player"-table.
); );
} }
SilverStripe's `[api:SiteTree]` base-class for content-pages uses a 1-to-1 relationship to link to its SilverStripe's [api:SiteTree] base-class for content-pages uses a 1-to-1 relationship to link to its
parent element in the tree: parent element in the tree:
:::php :::php
@ -285,7 +285,7 @@ accessors available on both ends.
### Adding relations ### Adding relations
Inside sapphire it doesn't matter if you're editing a *has_many*- or a *many_many*-relationship. You need to get a Inside sapphire it doesn't matter if you're editing a *has_many*- or a *many_many*-relationship. You need to get a
`[api:ComponentSet]`. [api:ComponentSet].
:::php :::php
class Team extends DataObject { class Team extends DataObject {
@ -315,7 +315,7 @@ Inside sapphire it doesn't matter if you're editing a *has_many*- or a *many_man
### Custom Relation Getters ### Custom Relation Getters
You can use the flexible datamodel to get a filtered result-list without writing any SQL. For example, this snippet gets You can use the flexible datamodel to get a filtered result-list without writing any SQL. For example, this snippet gets
you the "Players"-relation on a team, but only containing active players. (See `[api:DataObject::$has_many]` for more info on you the "Players"-relation on a team, but only containing active players. (See [api:DataObject::$has_many] for more info on
the described relations). the described relations).
:::php :::php
@ -448,16 +448,16 @@ See [forms](/topics/forms).
### Saving data with custom SQL ### Saving data with custom SQL
See `[api:SQLQuery]` for custom *INSERT*, *UPDATE*, *DELETE* queries. See [api:SQLQuery] for custom *INSERT*, *UPDATE*, *DELETE* queries.
## Decorating DataObjects ## Decorating DataObjects
You can add properties and methods to existing `[api:DataObjects]`s like `[api:Member]` (a core class) without hacking core You can add properties and methods to an existing [api:DataObjects] like [api:Member] (a core class) without hacking core
code or subclassing. code or subclassing.
Please see `[api:DataObjectDecorator]` for a general description, and `[api:Hierarchy]` for our most Please see [api:DataObjectDecorator] for a general description, and [api:Hierarchy] for our most
popular examples. popular examples.
@ -466,7 +466,7 @@ popular examples.
### Whats the difference between DataObject::get() and a relation-getter? ### Whats the difference between DataObject::get() and a relation-getter?
You can work with both in pretty much the same way, but relationship-getters return a special type of collection: You can work with both in pretty much the same way, but relationship-getters return a special type of collection:
A `[api:ComponentSet]` with relation-specific functionality. A [api:ComponentSet] with relation-specific functionality.
:::php :::php
$myTeam = DataObject::get_by_id('Team',$myPlayer->TeamID); // returns DataObject $myTeam = DataObject::get_by_id('Team',$myPlayer->TeamID); // returns DataObject

View File

@ -32,7 +32,7 @@ use devmode on a public server very very carefully
Test mode is designed for staging environments or other private collaboration sites before deploying a site live. You do Test mode is designed for staging environments or other private collaboration sites before deploying a site live. You do
not need to use test mode if you do not have a staging environment or a place for testing which is on a public server) not need to use test mode if you do not have a staging environment or a place for testing which is on a public server)
In this mode error messages are hidden from the user and it includes `[api:BasicAuth]` integration if you want to password In this mode error messages are hidden from the user and it includes [api:BasicAuth] integration if you want to password
protect the site. protect the site.
To set your site to test mode set this in your `mysite/_config.php` file To set your site to test mode set this in your `mysite/_config.php` file

View File

@ -55,7 +55,7 @@ Example Forum:
## PHP Include Paths ## PHP Include Paths
Due to the way `[api:ManifestBuilder]` recursively detects php-files and includes them through PHP5's Due to the way [api:ManifestBuilder] recursively detects php-files and includes them through PHP5's
*__autoload()*-feature, you don't need to worry about include paths. Feel free to structure your php-code into *__autoload()*-feature, you don't need to worry about include paths. Feel free to structure your php-code into
subdirectories inside the *code*-directory. subdirectories inside the *code*-directory.

View File

@ -150,4 +150,4 @@ The [newsletter module](http://silverstripe.org/newsletter-module) provides a UI
## API Documentation ## API Documentation
`[api:Email]` [api:Email]

View File

@ -36,11 +36,11 @@ warnings.
An HTTP 500 error will be sent when there has been a fatal error on either a test or production site. You can make this An HTTP 500 error will be sent when there has been a fatal error on either a test or production site. You can make this
friendlier - much like the 404 page, the error content can be edited within the CMS. friendlier - much like the 404 page, the error content can be edited within the CMS.
* Create a page of type `[api:ErrorPage]` * Create a page of type [api:ErrorPage]
* Set the error code to 500 * Set the error code to 500
* Publish the page. * Publish the page.
**HOW IT WORKS: **The publication script for `[api:ErrorPage]` will write the full HTML content, including the template styling, **HOW IT WORKS: **The publication script for [api:ErrorPage] will write the full HTML content, including the template styling,
to assets/error-500.html. The fatal error handler looks for the presence of this file, and if it exists, dumps the to assets/error-500.html. The fatal error handler looks for the presence of this file, and if it exists, dumps the
content. This means that database access isn't required to provide a 500 error page. content. This means that database access isn't required to provide a 500 error page.

View File

@ -49,12 +49,12 @@ where url is the relative link to the page (eg 'admin/categories'). You can chan
## Overloading EditForm ## Overloading EditForm
You may need to overload EditForm if your class does not use the `[api:Versioned]` extension. You may need to overload EditForm if your class does not use the [api:Versioned] extension.
## Overloading SiteTreeAsUL ## Overloading SiteTreeAsUL
The tree hints can sometimes cause problems when reorganising the tree, and the CMSMain::SiteTreeAsUL function uses The tree hints can sometimes cause problems when reorganising the tree, and the CMSMain::SiteTreeAsUL function uses
`[api:SiteTree]` explicitly. Use: [api:SiteTree] explicitly. Use:
:::php :::php
public function SiteTreeAsUL() { public function SiteTreeAsUL() {

View File

@ -6,8 +6,8 @@ Form validation is a combination of PHP and JavaScript
### Introduction ### Introduction
Validators are implemented as an argument to the `[api:Form]` constructor. You create a required fields validator like Validators are implemented as an argument to the [api:Form] constructor. You create a required fields validator like
so. In this case, we're creating a `[api:RequiredFields]` validator - the `[api:Validator]` class itself is an abstract so. In this case, we're creating a [api:RequiredFields] validator - the [api:Validator] class itself is an abstract
class. class.
@ -74,4 +74,4 @@ Disable for a specific form:
## Related ## Related
* Model Validation with [api:DataObject->validate()] * Model Validation with [api:DataObject::validate()]

View File

@ -14,9 +14,9 @@ constructor takes the following arguments:
* `$name`: This must be the name of the method on that controller that is called to return the form. The first two * `$name`: This must be the name of the method on that controller that is called to return the form. The first two
fields allow the form object to be re-created after submission. **It's vital that they are properly set - if you ever fields allow the form object to be re-created after submission. **It's vital that they are properly set - if you ever
have problems with form action handler not working, check that these values are correct.** have problems with form action handler not working, check that these values are correct.**
* `$fields`: A `[api:FieldSet]`s that make up the editable portion of the form. * `$fields`: A [api:FieldSet] that makes up the editable portion of the form.
* `$actions`: A `[api:FieldSet]`s that make up the control portion of the form - the buttons at the bottom. * `$actions`: A [api:FieldSet] that makes up the control portion of the form - the buttons at the bottom.
* `$validator`: An optional `[api:Validator]` for more information. * `$validator`: An optional [api:Validator] for more information.
Example: Example:
@ -60,16 +60,16 @@ The real difference, however, is that you can then define your controller method
## Form Field Types ## Form Field Types
There are many classes extending `[api:FormField]`. Some examples: There are many classes extending [api:FormField]. Some examples:
* `[api:TextField]` * [api:TextField]
* `[api:EmailField]` * [api:EmailField]
* `[api:NumericField]` * [api:NumericField]
* `[api:DateField]` * [api:DateField]
* `[api:CheckboxField]` * [api:CheckboxField]
* `[api:DropdownField]` * [api:DropdownField]
* `[api:OptionsetField]` * [api:OptionsetField]
* `[api:CheckboxSetField]` * [api:CheckboxSetField]
Full overview at [form-field-types](/reference/form-field-types) Full overview at [form-field-types](/reference/form-field-types)
@ -195,7 +195,7 @@ First of all, you need to create your form on it's own class, that way you can d
} }
`forTemplate()` tells the `[api:Form]` class to render with a template of return value of `$this->class`, which in this case `forTemplate()` tells the [api:Form] class to render with a template of return value of `$this->class`, which in this case
is *MyForm*, the name of the class. If the template doesn't exist, then it falls back to using Form.ss. is *MyForm*, the name of the class. If the template doesn't exist, then it falls back to using Form.ss.
*MyForm.ss* should then be placed into your *templates/Includes* directory for your project. Here is an example of *MyForm.ss* should then be placed into your *templates/Includes* directory for your project. Here is an example of
@ -235,7 +235,7 @@ this case `TextField->Field()` or `EmailField->Field()` which returns an `<input
for the type of field. Pass in the name of the field as the first parameter, as done above, to render it into the for the type of field. Pass in the name of the field as the first parameter, as done above, to render it into the
template. template.
To find more methods, have a look at the `[api:Form]` class, as there is a lot of different methods of customising the form To find more methods, have a look at the [api:Form] class, as there is a lot of different methods of customising the form
templates, for example, you could use `<% control Fields %>` instead of specifying each field manually, as we've done templates, for example, you could use `<% control Fields %>` instead of specifying each field manually, as we've done
above. above.
@ -274,9 +274,9 @@ Adds a new text field called FavouriteColour next to the Content field in the CM
## Related ## Related
* [form-field-types](/reference/form-field-types) * [form-field-types](/reference/form-field-types)
* `[api:FormField]` class * [api:FormField]
* [multiform module](http://silverstripe.org/multi-form-module) * [multiform module](http://silverstripe.org/multi-form-module)
## API Documentation ## API Documentation
`[api:Form]` [api:Form]

View File

@ -7,7 +7,7 @@ different languages based on your global settings and the preferences of your we
as l10n (short for "localization"). as l10n (short for "localization").
For translating any content managed through the CMS or stored in the database, please refer to the For translating any content managed through the CMS or stored in the database, please refer to the
[translation](/topics/translation) documentation (which explains the `[api:Translatable]` extension). [translation](/topics/translation) documentation (which explains the [api:Translatable] extension).
This page aims to describe the low-level functionality of the i18n-API. It targets developers who: This page aims to describe the low-level functionality of the i18n-API. It targets developers who:
@ -28,7 +28,7 @@ The i18n class is enabled by default.
### Setting the locale ### 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 you 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. want to set.
:::php :::php
@ -44,7 +44,7 @@ available locales.
### Getting the locale ### 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} ### Declaring the content language in HTML {#declaring_the_content_language_in_html}

View File

@ -9,9 +9,9 @@ practices can be applied to other libraries as well.
## File Inclusion ## File Inclusion
SilverStripe-driven code should use the `[api:Requirements]` class to manage clientside dependencies like CSS and JavaScript SilverStripe-driven code should use the [api:Requirements] class to manage clientside dependencies like CSS and JavaScript
files, rather than including `<script>` and `<link>` tags in your templates. This has the advantage that a registry files, rather than including `<script>` and `<link>` tags in your templates. This has the advantage that a registry
of requirements can be built up from different places outside of the main controller, for example included `[api:FormField]` of requirements can be built up from different places outside of the main controller, for example included [api:FormField]
instances. instances.
See [requirements](/reference/requirements) documentation. See [requirements](/reference/requirements) documentation.
@ -366,7 +366,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 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 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. this inflexible concept.
Example: Autocomplete input field loading page matches through AJAX Example: Autocomplete input field loading page matches through AJAX
@ -438,7 +438,7 @@ JavaScript:
Although they are the minority of cases, there are times when a simple HTML fragment isn't enough. For example, if you 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 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 [jQuery.getJSON()](http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback), as long as the HTTP content-type is
properly set. properly set.

View File

@ -6,14 +6,14 @@ A module is, quite simply, a collection of classes, templates, and other resourc
directory. In a default SilverStripe download, even resources in 'sapphire' and 'mysite' are treated in exactly the directory. In a default SilverStripe download, even resources in 'sapphire' and 'mysite' are treated in exactly the
same as every other module. same as every other module.
Sapphire's `[api:ManifestBuilder]` will find any class, css or template files anywhere under the site's main Sapphire's [api:ManifestBuilder] will find any class, css or template files anywhere under the site's main
directory. The _config.php file in the module directory can be used to define director rules, calls to directory. The _config.php file in the module directory can be used to define director rules, calls to
Object::useCustomClass(), and the like. So, by unpacking a module into site's main directory and viewing the site with Object::useCustomClass(), and the like. So, by unpacking a module into site's main directory and viewing the site with
?flush=1 on the end of the URL, all the module's new behaviour will be incorporated to your site: ?flush=1 on the end of the URL, all the module's new behaviour will be incorporated to your site:
* You can create subclasses of base classes such as SiteTree to extend behaviour. * You can create subclasses of base classes such as SiteTree to extend behaviour.
* You can use Object::useCustomClass() to replace a built in class with a class of your own. * You can use [api:Object::useCustomClass()] to replace a built in class with a class of your own.
* You can use [a decorator](api:DataObjectDecorator) to extend or alter the behaviour of a built-in class without replacing * You can use [api:DataObjectDecorator] to extend or alter the behaviour of a built-in class without replacing
it. it.
* You can provide additional director rules to define your own controller for particular URLs. * You can provide additional director rules to define your own controller for particular URLs.

View File

@ -78,8 +78,8 @@ See [form](/topics/forms) and [tutorial:extending-a-basic-site](/tutorials/exten
### removeFieldFromTab() ### removeFieldFromTab()
Overloading `getCMSFields()` you can call `removeFieldFromTab()` on a `[api:FieldSet]` object. For example, if you don't Overloading [api:SiteTree::getCMSFields()] you can call `removeFieldFromTab()` on a [api:FieldSet] object. For example, if you don't
want the MenuTitle field to show on your page, which is inherited from `[api:SiteTree]`. want the MenuTitle field to show on your page, which is inherited from [api:SiteTree].
:::php :::php
class StaffPage extends Page { class StaffPage extends Page {

View File

@ -7,23 +7,23 @@ See [Tutorial: Site Search](/tutorials/site-search) for details.
## Searching for DataObject's ## Searching for DataObject's
The `[api:SearchContext]` class provides a good base implementation that you can hook into your own controllers. The [api:SearchContext] class provides a good base implementation that you can hook into your own controllers.
A working implementation of searchable DataObjects can be seen in the `[api:ModelAdmin]` class. A working implementation of searchable DataObjects can be seen in the [api:ModelAdmin] class.
[SearchContext](/reference/searchcontext) goes into more detail about setting up a default search form for `[api:DataObject]`s. [SearchContext](/reference/searchcontext) goes into more detail about setting up a default search form for a [api:DataObject].
## Searching for Documents ## Searching for Documents
SilverStripe does not have a built-in method to search through file content (e.g. in PDF or DOC format). SilverStripe does not have a built-in method to search through file content (e.g. in PDF or DOC format).
You can either extract any textual file content into the `[File](api:File)->Content` property, or use a You can either extract any textual file content into the *Content* property, or use a
dedicated search service like the [sphinx module] `http://silverstripe.org/sphinx-module`. dedicated search service like the [sphinx module](https://github.com/silverstripe-labs/silverstripe-fulltextsearch/tree/2.4).
## Related ## Related
* `[api:ModelAdmin]` * [api:ModelAdmin]
* `[api:RestfulServer]` * [api:RestfulServer]
* [Tutorial: Site Search](/tutorials/site-search) * [Tutorial: Site Search](/tutorials/site-search)
* [SearchContext](/reference/searchcontext) * [SearchContext](/reference/searchcontext)
* [genericviews module] `http://silverstripe.org/generic-views-module` * [genericviews module] `http://silverstripe.org/generic-views-module`
* [sphinx module] `http://silverstripe.org/sphinx-module` * [sphinx module](https://github.com/silverstripe-labs/silverstripe-fulltextsearch/tree/2.4)
* [lucene module] `http://silverstripe.org/lucene-module` * [lucene module](https://code.google.com/archive/p/lucene-silverstripe-plugin)

View File

@ -16,9 +16,9 @@ See [http://shiflett.org/articles/sql-injection](http://shiflett.org/articles/sq
### Automatic escaping ### Automatic escaping
SilverStripe automatically escapes data in `[api:DataObject::write()]` wherever possible, SilverStripe automatically escapes data in [api:DataObject::write()] wherever possible,
through database-specific methods (see `[api:Database->addslashes()]`). through database-specific methods (see [api:MySQLDatabase::addslashes()]).
For `[api:MySQLDatabase]`, this will be `[mysql_real_escape_string()](http://de3.php.net/mysql_real_escape_string)`. For [api:MySQLDatabase], this will be [mysql_real_escape_string()](http://php.net/manual/en/function.mysql-real-escape-string.php).
Data is escaped when saving back to the database, not when writing to object-properties. Data is escaped when saving back to the database, not when writing to object-properties.
* DataObject::get_by_id() * DataObject::get_by_id()
@ -119,8 +119,8 @@ for in-depth information about "Cross-Site-Scripting".
### Escaping model properties ### Escaping model properties
`[api:SSViewer]` (the SilverStripe template engine) automatically takes care of escaping HTML tags from specific [api:SSViewer] (the SilverStripe template engine) automatically takes care of escaping HTML tags from specific
object-properties by [casting](/topics/datamodel#casting) its string value into a `[api:DBField]` object. object-properties by [casting](/topics/datamodel#casting) its string value into a [api:DBField] object.
PHP: PHP:
@ -203,7 +203,7 @@ presentation from business logic.
When using *customise()* or *renderWith()* calls in your controller, or otherwise forcing a custom context for your When using *customise()* or *renderWith()* calls in your controller, or otherwise forcing a custom context for your
template, you'll need to take care of casting and escaping yourself in PHP. template, you'll need to take care of casting and escaping yourself in PHP.
The `[api:Convert]` class has utilities for this, mainly *Convert::raw2xml()* and *Convert::raw2att()* (which is The [api:Convert] class has utilities for this, mainly [api:Convert::raw2xml()] and [api:Convert::raw2att()] (which are
also used by *XML* and *ATT* in template code). also used by *XML* and *ATT* in template code).
PHP: PHP:
@ -260,7 +260,7 @@ Template:
Some rules of thumb: Some rules of thumb:
* Don't concatenate URLs in a template. It only works in extremely simple cases that usually contain bugs. * Don't concatenate URLs in a template. It only works in extremely simple cases that usually contain bugs.
* Use *Controller::join_links()* to concatenate URLs. It deals with query strings and other such edge cases. * Use [api:Controller::join_links()] to concatenate URLs. It deals with query strings and other such edge cases.
## Cross-Site Request Forgery (CSRF) ## Cross-Site Request Forgery (CSRF)
@ -283,7 +283,7 @@ See
## Casting user input ## Casting user input
When working with `$_GET`, `$_POST` or `Director::urlParams` variables, and you know your variable has to be of a When working with `$_GET`, `$_POST` or [api:Director::urlParams()] variables, and you know your variable has to be of a
certain type, like an integer, then it's essential to cast it as one. *Why?* To be sure that any processing of your certain type, like an integer, then it's essential to cast it as one. *Why?* To be sure that any processing of your
given variable is done safely, with the assumption that it's an integer. given variable is done safely, with the assumption that it's an integer.

View File

@ -2,7 +2,7 @@
Functional tests test your controllers. The core of these are the same as unit tests: Functional tests test your controllers. The core of these are the same as unit tests:
* Create a subclass of `[api:SapphireTest]` in the `mysite/tests` or `(module)/tests` folder. * Create a subclass of [api:SapphireTest] in the `mysite/tests` or `(module)/tests` folder.
* Define static $fixture_file to point to a database YAML file. * Define static $fixture_file to point to a database YAML file.
* Create methods that start with "test" to create your tests. * Create methods that start with "test" to create your tests.
* Assertions are used to work out if a test passed or failed. * Assertions are used to work out if a test passed or failed.
@ -48,7 +48,7 @@ URLs. Here is an example from the subsites module:
We are using a new static method here: **Director::test($url, $postVars, $sessionObj)** We are using a new static method here: **Director::test($url, $postVars, $sessionObj)**
Director::test() lets us execute a URL and see what happens. It bypasses HTTP, instead relying on the cleanly Director::test() lets us execute a URL and see what happens. It bypasses HTTP, instead relying on the cleanly
encapsulated execution model of `[api:Controller]`. encapsulated execution model of [api:Controller].
It takes 3 arguments: It takes 3 arguments:
@ -56,7 +56,7 @@ It takes 3 arguments:
* $postVars: Post variables to pass to the URL * $postVars: Post variables to pass to the URL
* $sessionObj: A Session object representing the current session. * $sessionObj: A Session object representing the current session.
And it returns an `[api:HTTPResponse]` object, which will give you the response headers (including redirection), status code, And it returns an [api:HTTPResponse] object, which will give you the response headers (including redirection), status code,
and body. and body.
We can use string processing on the body of the response to then see if it fits with our expectations. We can use string processing on the body of the response to then see if it fits with our expectations.

View File

@ -1,6 +1,6 @@
# How To Create a Sapphire Test # How To Create a Sapphire Test
A unit test class will test the behaviour of one of your `[api:DataObjects]`. This simple fragment of `[api:SiteTreeTest]` A unit test class will test the behaviour of one of your [api:DataObjects]. This simple fragment of [api:SiteTreeTest]
provides us the basics of creating unit tests. provides us the basics of creating unit tests.
:::php :::php
@ -47,7 +47,7 @@ provides us the basics of creating unit tests.
There are a number of points to note in this code fragment: There are a number of points to note in this code fragment:
* Your test is a **subclass of SapphireTest**. Both unit tests and functional tests are a subclass of `[api:SapphireTest]`. * Your test is a **subclass of SapphireTest**. Both unit tests and functional tests are a subclass of [api:SapphireTest].
* **static $fixture_file** is defined. The testing framework will automatically set up a new database for **each** of * **static $fixture_file** is defined. The testing framework will automatically set up a new database for **each** of
your tests. The initial database content will be sourced from the YML file that you list in $fixture_file. You must your tests. The initial database content will be sourced from the YML file that you list in $fixture_file. You must
define this value. Note also that, for the time being, you can only point to one YML file for each test class. define this value. Note also that, for the time being, you can only point to one YML file for each test class.
@ -55,7 +55,7 @@ define this value. Note also that, for the time being, you can only point to on
database will be rebuilt for each of these. database will be rebuilt for each of these.
* **$this->objFromFixture($className, $identifier)** can be used to select one of the objects named in your fixture * **$this->objFromFixture($className, $identifier)** can be used to select one of the objects named in your fixture
file. To identify to the object, we provide a class name and an identifier. The identifier is specified in the YML file. To identify to the object, we provide a class name and an identifier. The identifier is specified in the YML
file but not saved in the database anywhere. objFromFixture() looks the `[api:DataObject]` up in memory rather than using the file but not saved in the database anywhere. objFromFixture() looks the [api:DataObject] up in memory rather than using the
database. This means that you can use it to test the functions responsible for looking up content in the database. database. This means that you can use it to test the functions responsible for looking up content in the database.
* **$this->assertEquals()** is one of the many assert... functions that PHPUnit provides us. See below for more * **$this->assertEquals()** is one of the many assert... functions that PHPUnit provides us. See below for more
information. information.
@ -78,7 +78,7 @@ if it starts with "/".
## The Database YAML file ## The Database YAML file
The main feature of `[api:SapphireTest]` over the raw PHPUnit classes is that SapphireTest will prepare a temporary database for The main feature of [api:SapphireTest] over the raw PHPUnit classes is that SapphireTest will prepare a temporary database for
you. The content of that database is provided in a special YAML file. YAML is a simple markup languages that uses tabs you. The content of that database is provided in a special YAML file. YAML is a simple markup languages that uses tabs
and colons instead of the more verbose XML tags, and because of this much better for developers creating files by hand. and colons instead of the more verbose XML tags, and because of this much better for developers creating files by hand.

View File

@ -15,7 +15,7 @@ send emails in your SilverStripe application. Here is a simple example of how y
$e->send(); $e->send();
Normally, the send() method would send an email using PHP's mail() function. However, if you are running a `[api:SapphireTest]` Normally, the send() method would send an email using PHP's mail() function. However, if you are running a [api:SapphireTest]
test, then it holds off actually sending the email, and instead lets you assert that an email was sent using this method. test, then it holds off actually sending the email, and instead lets you assert that an email was sent using this method.
:::php :::php

View File

@ -80,7 +80,7 @@ Skip certain tests
## Writing Tests ## Writing Tests
Tests are written by creating subclasses of `[api:SapphireTest]`. You should put tests for your site in the Tests are written by creating subclasses of [api:SapphireTest]. You should put tests for your site in the
`mysite/tests` directory. If you are writing tests for a module, put them in the `(modulename)/tests` directory. `mysite/tests` directory. If you are writing tests for a module, put them in the `(modulename)/tests` directory.
Generally speaking, there should be one test class for each application class. The name of the test class should be the Generally speaking, there should be one test class for each application class. The name of the test class should be the

View File

@ -245,7 +245,7 @@ Note: This only applies for CSS and template files. PHP files **do not** get ove
### Requirements ### Requirements
The `[api:Requirements::themedCSS()]` function will The [api:Requirements::themedCSS()] function will
do the search specified above. This avoids the need to type a full path to the css file, and also provides better do the search specified above. This avoids the need to type a full path to the css file, and also provides better
ambiguity for themes. ambiguity for themes.

View File

@ -7,7 +7,7 @@ This page introduces developers to using the CMS for creating content in multipl
Please see [i18n](/topics/i18n) for a internationalization, globalization and localization support of built-in datatypes as well Please see [i18n](/topics/i18n) for a internationalization, globalization and localization support of built-in datatypes as well
as translating templates and PHP code. as translating templates and PHP code.
Translations can be enabled for all subclasses of `[api:DataObject]`, so it can easily be implemented into existing code Translations can be enabled for all subclasses of [api:DataObject], so it can easily be implemented into existing code
with minimal interference. with minimal interference.
Warning: If you're upgrading from a SilverStripe version prior to 2.3.2, please migrate your datamodel before using the Warning: If you're upgrading from a SilverStripe version prior to 2.3.2, please migrate your datamodel before using the
@ -60,7 +60,7 @@ Enabling Translatable through *Object::add_extension()* in your *mysite/_config.
} }
Make sure to rebuild the database through /dev/build after enabling `[api:Translatable]`. Make sure to rebuild the database through /dev/build after enabling [api:Translatable].
Use the correct set_default_locale() before building the database Use the correct set_default_locale() before building the database
for the first time, as this locale will be written on all new records. for the first time, as this locale will be written on all new records.
@ -101,7 +101,7 @@ Getting a translation for an existing instance:
Getting translations through Translatable::set_reading_locale(). Getting translations through Translatable::set_reading_locale().
This is *not* a recommended approach, but sometimes unavoidable (e.g. for `[api:Versioned]` methods). This is *not* a recommended approach, but sometimes unavoidable (e.g. for [api:Versioned] methods).
:::php :::php
$origLocale = Translatable::get_reading_locale(); $origLocale = Translatable::get_reading_locale();
@ -120,7 +120,7 @@ Creating a translation:
### Usage for SiteTree ### Usage for SiteTree
`[api:Translatable]` can be used for subclasses of SiteTree as well. [api:Translatable] can be used for subclasses of SiteTree as well.
If a child page translation is requested without the parent If a child page translation is requested without the parent
page already having a translation in this language, the extension page already having a translation in this language, the extension
will recursively create translations up the tree. will recursively create translations up the tree.
@ -129,7 +129,7 @@ languages by auto-appending the language code at the end.
You'll need to ensure that the appropriate "reading language" is set You'll need to ensure that the appropriate "reading language" is set
before showing links to other pages on a website through $_GET['locale']. before showing links to other pages on a website through $_GET['locale'].
Pages in different languages can have different publication states Pages in different languages can have different publication states
through the `[api:Versioned]` extension. through the [api:Versioned] extension.
Note: You can't get Children() for a parent page in a different language Note: You can't get Children() for a parent page in a different language
through set_reading_locale(). Get the translated parent first. through set_reading_locale(). Get the translated parent first.
@ -148,11 +148,11 @@ through set_reading_locale(). Get the translated parent first.
### Translating custom properties ### Translating custom properties
Keep in mind that the `[api:Translatable]` extension currently doesn't support the exclusion of properties from being Keep in mind that the [api:Translatable] extension currently doesn't support the exclusion of properties from being
translated - all custom properties will automatically be fetched from their translated record on the database. This means translated - all custom properties will automatically be fetched from their translated record on the database. This means
you don't have to explicitly mark any custom properties as being translatable. you don't have to explicitly mark any custom properties as being translatable.
The `[api:Translatable]` decorator applies only to the getCMSFields() method on DataObject or SiteTree, not to any fields The [api:Translatable] decorator applies only to the getCMSFields() method on DataObject or SiteTree, not to any fields
added in overloaded getCMSFields() implementations. See Translatable->updateCMSFields() for details. By default, custom added in overloaded getCMSFields() implementations. See Translatable->updateCMSFields() for details. By default, custom
fields in the CMS won't show an original readonly value on a translated record, although they will save correctly. You can fields in the CMS won't show an original readonly value on a translated record, although they will save correctly. You can
attach this behaviour to custom fields by using Translatable_Transformation as shown below. attach this behaviour to custom fields by using Translatable_Transformation as shown below.
@ -354,11 +354,11 @@ files, you'll need to [set the i18n locale](/topics/translation#setting_the_i18n
(The reasoning is as follows: Translatable doesn't set the i18n locale. Historically these were two separate systems, (The reasoning is as follows: Translatable doesn't set the i18n locale. Historically these were two separate systems,
but they're reasonably interchangeable for a front-end website. The distinction is mainly valid for the CMS, because you but they're reasonably interchangeable for a front-end website. The distinction is mainly valid for the CMS, because you
want the CMS to be in English (`[api:i18n]`), but edit pages in different languages (`[api:Translatable]`).) want the CMS to be in English ([api:i18n]), but edit pages in different languages ([api:Translatable]).)
### Migrating from 2.1 datamodel ### Migrating from 2.1 datamodel
The datamodel of `[api:Translatable]` changed significantly between its original release in SilverStripe 2.1 and SilverStripe The datamodel of [api:Translatable] changed significantly between its original release in SilverStripe 2.1 and SilverStripe
2.3.2. See our [discussion on the 2.3.2. See our [discussion on the
mailinglist](http://groups.google.com/group/silverstripe-dev/browse_thread/thread/91e26e1f78d3c1b4/bd276dd5bbc56283?lnk=gst&q=translatable#bd276dd5bbc56283). mailinglist](http://groups.google.com/group/silverstripe-dev/browse_thread/thread/91e26e1f78d3c1b4/bd276dd5bbc56283?lnk=gst&q=translatable#bd276dd5bbc56283).
@ -370,13 +370,13 @@ To migrate a database that was built with SilverStripe 2.1.x or 2.2.x, follow th
* Run `http://mysite.com/dev/build` * Run `http://mysite.com/dev/build`
* Run `http://mysite.com/dev/tasks/MigrateTranslatableTask` * Run `http://mysite.com/dev/tasks/MigrateTranslatableTask`
Please see the `[api:MigrateTranslatableTask]` for Please see the [api:MigrateTranslatableTask] for
limitations of this migration task - not all your data will be preserved. limitations of this migration task - not all your data will be preserved.
### Setting the i18n locale ### Setting the i18n locale
You can set the `[api:i18n]` locale value which is used to format dates, currencies and other regionally different values to You can set the [api:i18n] locale value which is used to format dates, currencies and other regionally different values to
the same as your current page locale. the same as your current page locale.
:::php :::php
@ -393,7 +393,7 @@ the same as your current page locale.
### Adding a new locale ### Adding a new locale
The `[api:i18n]` logic has lookup tables for common locales in i18n::$common_locales, which is a subset of i18n::$all_locales. The [api:i18n] logic has lookup tables for common locales in i18n::$common_locales, which is a subset of i18n::$all_locales.
If your locale is not present here, you can simply add it through `mysite/_config.php`: If your locale is not present here, you can simply add it through `mysite/_config.php`:
:::php :::php
@ -406,6 +406,6 @@ This should e.g. enable you to use `$Locale.Nice` in template code.
* [translate.silverstripe.org] `http://translate.silverstripe.org`: Starting point for community-driven translation of the Silverstripe UI * [translate.silverstripe.org] `http://translate.silverstripe.org`: Starting point for community-driven translation of the Silverstripe UI
* [i18n](i18n): Developer-level documentation of Silverstripe's i18n capabilities * [i18n](i18n): Developer-level documentation of Silverstripe's i18n capabilities
* `[api:Translatable]`: DataObject-interface powering the website-content translations * [api:Translatable]: DataObject-interface powering the website-content translations
* ["Translatable ModelAdmin" module] `http://silverstripe.org/translatablemodeladmin-module/`: An extension which allows * ["Translatable ModelAdmin" module] `http://silverstripe.org/translatablemodeladmin-module/`: An extension which allows
translations of `[api:DataObject]`s inside `[api:ModelAdmin]` translations of a [api:DataObject] inside [api:ModelAdmin]

View File

@ -231,7 +231,7 @@ This returns the value inputted in the CMS, if it's set or what is in the $title
To implement a form inside a widget, you need to implement a custom controller for your widget to return this form. Make To implement a form inside a widget, you need to implement a custom controller for your widget to return this form. Make
sure that your controller follows the usual naming conventions, and it will be automatically picked up by the sure that your controller follows the usual naming conventions, and it will be automatically picked up by the
`[api:WidgetArea]` rendering in your *Page.ss* template. [api:WidgetArea] rendering in your *Page.ss* template.
**mysite/code/MyWidget.php** **mysite/code/MyWidget.php**
@ -276,7 +276,7 @@ To output this form, modify your widget template.
$MyFormName $MyFormName
<div class="notice" markdown='1'> <div class="notice" markdown='1'>
**Note:** The necessary controller actions are only present in subclasses of `[api:Page_Controller]`. To use **Note:** The necessary controller actions are only present in subclasses of [api:Page_Controller]. To use
widget forms in other controller subclasses, have a look at *ContentController->handleWidget()* and widget forms in other controller subclasses, have a look at *ContentController->handleWidget()* and
*ContentController::$url_handlers*. *ContentController::$url_handlers*.
</div> </div>

View File

@ -116,7 +116,7 @@ quickly between the CMS and the draft and published version of your page.
**Flushing the cache** **Flushing the cache**
Whenever we edit a template file, we need to append *?flush=1* onto the end of the URL, e.g. Whenever we edit a template file, we need to append *?flush=1* onto the end of the URL, e.g.
http://localhost/home/?flush=1. SilverStripe stores template files in a cache for quicker load times. Whenever there are `http://localhost/home/?flush=1`. SilverStripe stores template files in a cache for quicker load times. Whenever there are
changes to the template, we must flush the cache in order for the changes to take effect. changes to the template, we must flush the cache in order for the changes to take effect.
## Inserting the page title ## Inserting the page title
@ -332,7 +332,7 @@ Create a new file *HomePage.php* in *mysite/code*. Copy the following code into
Every page type also has a database table corresponding to it. Every time we modify the database, we need to rebuild it. Every page type also has a database table corresponding to it. Every time we modify the database, we need to rebuild it.
We can do this by going to [http://localhost/dev/build?flush=1](http://localhost/dev/build?flush=1). It may take a We can do this by going to `http://localhost/dev/build?flush=1`. It may take a
moment, so be patient. This add tables and fields needed by your site, and modifies any structures that have changed. It moment, so be patient. This add tables and fields needed by your site, and modifies any structures that have changed. It
does this non-destructively - it will never delete your data. does this non-destructively - it will never delete your data.

View File

@ -32,9 +32,9 @@ final page. Lets look at each one individually:
### Model ### Model
All content on your site is stored in a database. There is a table in the database corresponding for every class that is All content on your site is stored in a database. There is a table in the database corresponding for every class that is
a child of the `[api:DataObject]` class. Every object of that class corresponds to a row in that table - a child of the [api:DataObject] class. Every object of that class corresponds to a row in that table -
this is your "data object", the **"model"** of Model-View-Controller. A page type has a data object that represents all the data for your page - rather than inheriting this is your "data object", the **"model"** of Model-View-Controller. A page type has a data object that represents all the data for your page - rather than inheriting
directly from data object it inherits from `[api:SiteTree]`. We generally create a "Page" data object, and subclass this for directly from data object it inherits from [api:SiteTree]. We generally create a "Page" data object, and subclass this for
the rest of the page types. This allows us to define behavior that is consistent across all pages in our site. the rest of the page types. This allows us to define behavior that is consistent across all pages in our site.
### View ### View
@ -48,7 +48,7 @@ presentation of your site.
A page type also has a **"controller"**. A controller contains all the code used to manipulate your data before it is A page type also has a **"controller"**. A controller contains all the code used to manipulate your data before it is
rendered. For example, suppose you were making an auction site, and you only wanted to display the auctions closing in rendered. For example, suppose you were making an auction site, and you only wanted to display the auctions closing in
the next ten minutes. You would implement this in the controller. The controller for a page should inherit from the next ten minutes. You would implement this in the controller. The controller for a page should inherit from
`[api:ContentController]`. Just as we create a "Page" data object and subclass it for the rest of the [api:ContentController]. Just as we create a "Page" data object and subclass it for the rest of the
site, we also create a "Page_Controller" that is subclassed. site, we also create a "Page_Controller" that is subclassed.
Creating a new page type simply requires creating these three things. You can then have full control over presentation, Creating a new page type simply requires creating these three things. You can then have full control over presentation,
@ -126,7 +126,7 @@ to be children of the page in the site tree. As we only want news articles in th
*ArticlePage* pages for children. We can enforce this in the CMS by setting the *$allowed_children* field. *ArticlePage* pages for children. We can enforce this in the CMS by setting the *$allowed_children* field.
We will be introducing other fields like this as we progress; there is a full list in the documentation for We will be introducing other fields like this as we progress; there is a full list in the documentation for
`[api:SiteTree]`. [api:SiteTree].
Now that we have created our page types, we need to let SilverStripe rebuild the database. If we rebuild the database by Now that we have created our page types, we need to let SilverStripe rebuild the database. If we rebuild the database by
going to [http://localhost/dev/build?flush=1](http://localhost/dev/build?flush=1), SilverStripe will detect that there are two going to [http://localhost/dev/build?flush=1](http://localhost/dev/build?flush=1), SilverStripe will detect that there are two
@ -155,7 +155,7 @@ it. Change the *$db* array in the *ArticlePage* class so it looks like this:
Every entry in the array is a key-value pair. The key is the name of the field, and the value is the type. We have a Every entry in the array is a key-value pair. The key is the name of the field, and the value is the type. We have a
`[api:Date]` for a complete list of different data types. [api:Date] for a complete list of different data types.
> Note: The names chosen for the fields you add must not already be used. Be careful using field names such as Title, > Note: The names chosen for the fields you add must not already be used. Be careful using field names such as Title,
> Content etc. as these may already be defined in the page types your new page is extending from. > Content etc. as these may already be defined in the page types your new page is extending from.
@ -192,7 +192,7 @@ Let's walk through this method.
Firstly, we get the fields from the parent class; we want to add fields, not replace them. The *$fields* variable Firstly, we get the fields from the parent class; we want to add fields, not replace them. The *$fields* variable
returned is a `[api:FieldSet]` object. returned is a [api:FieldSet] object.
:::php :::php
$fields->addFieldToTab('Root.Content.Main', new DateField('Date'), 'Content'); $fields->addFieldToTab('Root.Content.Main', new DateField('Date'), 'Content');
@ -201,7 +201,7 @@ returned is a `[api:FieldSet]` object.
We can then add our new fields with *addFieldToTab*. The first argument is the tab on which we want to add the field to: We can then add our new fields with *addFieldToTab*. The first argument is the tab on which we want to add the field to:
"Root.Content.Main" is the tab which the content editor is on. The second argument is the field to add; this is not a "Root.Content.Main" is the tab which the content editor is on. The second argument is the field to add; this is not a
database field, but a `[api:FormField]` documentation for more details. database field, but a [api:FormField] documentation for more details.
:::php :::php
return $fields; return $fields;
@ -262,7 +262,7 @@ Set *showCalendar* to true to have a calendar appear underneath the Date field w
$fields->addFieldToTab('Root.Content.Main', new TextField('Author','Author Name'), 'Content'); $fields->addFieldToTab('Root.Content.Main', new TextField('Author','Author Name'), 'Content');
By default the first argument *'Date'* or *'Author'* is shown as the title, however this might not be that helpful so to change the title, By default the first argument *'Date'* or *'Author'* is shown as the title, however this might not be that helpful so to change the title,
add the new title as the second argument. See the `[api:DateField]` documentation for more details. add the new title as the second argument. See the [api:DateField] documentation for more details.
## Creating the templates ## Creating the templates
@ -307,7 +307,7 @@ how to remove these blocks of repetitive code in a bit.
We use *$Date* and *$Author* to access the new fields. In fact, all template variables and page controls come from We use *$Date* and *$Author* to access the new fields. In fact, all template variables and page controls come from
either the data object or the controller for the page being displayed. The *$Breadcrumbs* variable comes from the either the data object or the controller for the page being displayed. The *$Breadcrumbs* variable comes from the
*Breadcrumbs()* method of the `[api:SiteTree]` class. *$Date* and *$Author* come from the *Article* table through *Breadcrumbs()* method of the [api:SiteTree] class. *$Date* and *$Author* come from the *Article* table through
your data object. *$Content* comes from the *SiteTree* table through the same data object. The data for your page is your data object. *$Content* comes from the *SiteTree* table through the same data object. The data for your page is
spread across several tables in the database matched by id - e.g. *Content* is in the *SiteTree* table, and *Date* and spread across several tables in the database matched by id - e.g. *Content* is in the *SiteTree* table, and *Date* and
*Author* are in the *Article* table. SilverStripe matches these records by their ids and collates them into the single *Author* are in the *Article* table. SilverStripe matches these records by their ids and collates them into the single
@ -315,7 +315,7 @@ data object.
![](_images/data-collation.jpg) ![](_images/data-collation.jpg)
Rather than using *$Date* directly, we use *$Date.Nice*. If we look in the `[api:Date]` documentation, we can see Rather than using *$Date* directly, we use *$Date.Nice*. If we look in the [api:Date] documentation, we can see
that the *Nice* function returns the date in *dd/mm/yyyy* format, rather than the *yyyy-mm-dd* format stored in the that the *Nice* function returns the date in *dd/mm/yyyy* format, rather than the *yyyy-mm-dd* format stored in the
database. database.
@ -341,7 +341,7 @@ summary.
Here we use the page control *Children*. As the name suggests, this control allows you to iterate over the children of a Here we use the page control *Children*. As the name suggests, this control allows you to iterate over the children of a
page, which in this case is our news articles. The *$Link* variable will give the address of the article which we can page, which in this case is our news articles. The *$Link* variable will give the address of the article which we can
use to create a link, and the *FirstParagraph* function of the `[api:HTMLText]` field gives us a nice summary of the use to create a link, and the *FirstParagraph* function of the [api:HTMLText] field gives us a nice summary of the
article. article.
![](_images/articleholder.jpg) ![](_images/articleholder.jpg)
@ -480,7 +480,7 @@ control. We can get the data for the news articles by implementing our own funct
This function simply runs a database query that gets the latest news articles from the database. By default, this is This function simply runs a database query that gets the latest news articles from the database. By default, this is
five, but you can change it by passing a number to the function. See the `[api:DataObject]` documentation for five, but you can change it by passing a number to the function. See the [api:DataObject] documentation for
details. We can reference this function as a page control in our *HomePage* template: details. We can reference this function as a page control in our *HomePage* template:
**themes/tutorial/templates/Layout/Homepage.ss** **themes/tutorial/templates/Layout/Homepage.ss**
@ -514,7 +514,7 @@ the data object.
## Creating a RSS feed ## Creating a RSS feed
An RSS feed is something that no news section should be without. SilverStripe makes it easy to create RSS feeds by An RSS feed is something that no news section should be without. SilverStripe makes it easy to create RSS feeds by
providing an `[api:RSSFeed]` class to do all the hard work for you. Create the following function in the providing an [api:RSSFeed] class to do all the hard work for you. Create the following function in the
*ArticleHolder_Controller*: *ArticleHolder_Controller*:
:::php :::php
@ -525,7 +525,7 @@ providing an `[api:RSSFeed]` class to do all the hard work for you. Create the f
This function simply creates an RSS feed of all the news articles, and outputs it to the browser. If you go to This function simply creates an RSS feed of all the news articles, and outputs it to the browser. If you go to
[http://localhost/news/rss](http://localhost/news/rss) you will see our RSS feed. What happens here is that `http://localhost/news/rss` you will see our RSS feed. What happens here is that
when there is more to a URL after the page's base URL - "rss" in this case - SilverStripe will call the function with when there is more to a URL after the page's base URL - "rss" in this case - SilverStripe will call the function with
that name on the controller if it exists. that name on the controller if it exists.
@ -534,7 +534,7 @@ will most likely see the XML output instead.
![](_images/rss-feed.jpg) ![](_images/rss-feed.jpg)
Now all we need is to let the user know that our RSS feed exists. The `[api:RSSFeed]` in your controller, it will be Now all we need is to let the user know that our RSS feed exists. The [api:RSSFeed] in your controller, it will be
called when the page is requested. Add this function to *ArticleHolder_Controller*: called when the page is requested. Add this function to *ArticleHolder_Controller*:
:::php :::php
@ -627,7 +627,7 @@ a new *StaffHolder* called "Staff" in the "About Us" section, and create some *S
### Creating the staff section templates ### Creating the staff section templates
The staff section templates aren't too difficult to create, thanks to the utility methods provided by the `[api:Image]` class. The staff section templates aren't too difficult to create, thanks to the utility methods provided by the [api:Image] class.
**themes/tutorial/templates/Layout/StaffHolder.ss** **themes/tutorial/templates/Layout/StaffHolder.ss**
@ -650,7 +650,7 @@ The staff section templates aren't too difficult to create, thanks to the utilit
</div> </div>
This template is very similar to the *ArticleHolder* template. The *SetWidth* method of the `[api:Image]` class This template is very similar to the *ArticleHolder* template. The *SetWidth* method of the [api:Image] class
will resize the image before sending it to the browser. The resized image is cached, so the server doesn't have to will resize the image before sending it to the browser. The resized image is cached, so the server doesn't have to
resize the image every time the page is viewed. resize the image every time the page is viewed.

View File

@ -80,13 +80,13 @@ Let's step through this code.
First we create our form fields. First we create our form fields.
We do this by creating a `[api:FieldSet]` and passing our fields as arguments. The first field is a new We do this by creating a [api:FieldSet] and passing our fields as arguments. The first field is a new
`[api:TextField]` with the name 'Name'. [api:TextField] with the name 'Name'.
There is a second argument when creating a field which specifies the text on the label of the field. If no second There is a second argument when creating a field which specifies the text on the label of the field. If no second
argument is passed, as in this case, it is assumed the label is the same as the name of the field. argument is passed, as in this case, it is assumed the label is the same as the name of the field.
The second field we create is an `[api:OptionsetField]`. This is a dropdown, and takes a third argument - an The second field we create is an [api:OptionsetField]. This is a dropdown, and takes a third argument - an
array mapping the values to the options listed in the dropdown. array mapping the values to the options listed in the dropdown.
:::php :::php
@ -102,14 +102,14 @@ button.
Here we create a 'Submit' button which calls the 'doBrowserPoll' method, which we will create later. Here we create a 'Submit' button which calls the 'doBrowserPoll' method, which we will create later.
All the form actions (in this case only one) are collected into a `[api:FieldSet]` object the same way we did with All the form actions (in this case only one) are collected into a [api:FieldSet] object the same way we did with
the fields. the fields.
:::php :::php
return new Form($this, 'BrowserPollForm', $fields, $actions); return new Form($this, 'BrowserPollForm', $fields, $actions);
Finally we create the `[api:Form]` object and return it. Finally we create the [api:Form] object and return it.
The first argument is the controller that contains the form, in most cases '$this'. The second is the name of the method The first argument is the controller that contains the form, in most cases '$this'. The second is the name of the method
that returns the form, which is 'BrowserPollForm' in our case. The third and fourth arguments are the that returns the form, which is 'BrowserPollForm' in our case. The third and fourth arguments are the
@ -179,11 +179,11 @@ Great! We now have a browser poll form, but it doesn't actually do anything. In
implement the 'doBrowserPoll' method that we told it about. implement the 'doBrowserPoll' method that we told it about.
First, we need some way of saving the poll submissions to the database, so we can retrieve the results later. We can do First, we need some way of saving the poll submissions to the database, so we can retrieve the results later. We can do
this by creating a new object that extends from `[api:DataObject]`. this by creating a new object that extends from [api:DataObject].
If you recall, in tutorial two we said that all objects that inherit from DataObject and that add fields are stored in If you recall, in tutorial two we said that all objects that inherit from DataObject and that add fields are stored in
the database. Also recall that all pages extend DataObject indirectly through `[api:SiteTree]`. Here instead of the database. Also recall that all pages extend DataObject indirectly through [api:SiteTree]. Here instead of
extending SiteTree (or `[api:Page]`) to create a page type, we extend DataObject directly. extending SiteTree (or Page) to create a page type, we extend DataObject directly.
*mysite/code/BrowserPollSubmission.php* *mysite/code/BrowserPollSubmission.php*
@ -197,7 +197,7 @@ extending SiteTree (or `[api:Page]`) to create a page type, we extend DataObject
} }
If we then rebuild the database ([http://localhost/db/build?flush=1](http://localhost/db/build?flush=1)), we will see If we then rebuild the database (`http://localhost/db/build?flush=1`), we will see
that the *BrowserPollSubmission* table is created. Now we just need to define 'doBrowserPoll' on *HomePage_Controller*. that the *BrowserPollSubmission* table is created. Now we just need to define 'doBrowserPoll' on *HomePage_Controller*.
*mysite/code/HomePage.php* *mysite/code/HomePage.php*
@ -215,7 +215,7 @@ that the *BrowserPollSubmission* table is created. Now we just need to define 'd
A function that processes a form submission takes two arguments - the first is the data in the form, the second is the A function that processes a form submission takes two arguments - the first is the data in the form, the second is the
`[api:Form]` object. [api:Form] object.
In our function we create a new *BrowserPollSubmission* object. Since the name of our form fields and the name of the In our function we create a new *BrowserPollSubmission* object. Since the name of our form fields and the name of the
database fields are the same we can save the form directly into the data object. database fields are the same we can save the form directly into the data object.
@ -262,7 +262,7 @@ Now that we have a working form, we need some way of showing the results.
The first thing to do is make it so a user can only vote once per session. If the user hasn't voted, show the form, The first thing to do is make it so a user can only vote once per session. If the user hasn't voted, show the form,
otherwise show the results. otherwise show the results.
We can do this using a session variable. The `[api:Session]` class handles all session variables in SilverStripe. We can do this using a session variable. The [api:Session] class handles all session variables in SilverStripe.
First modify the 'doBrowserPoll' to set the session variable 'BrowserPollVoted' when a user votes. First modify the 'doBrowserPoll' to set the session variable 'BrowserPollVoted' when a user votes.
*mysite/code/HomePage.php* *mysite/code/HomePage.php*
@ -311,10 +311,10 @@ We now need some way of getting the data from the database into the template.
In the second tutorial we got the latest news articles for the home page by using the 'DataObject::get' function. We In the second tutorial we got the latest news articles for the home page by using the 'DataObject::get' function. We
can't use the 'DataObject::get' function here directly as we wish to count the total number of votes for each browser. can't use the 'DataObject::get' function here directly as we wish to count the total number of votes for each browser.
By looking at the documentation for 'DataObject::get', we can see that it returns a `[api:DataObjectSet]` By looking at the documentation for 'DataObject::get', we can see that it returns a [api:DataObjectSet]
object. In fact, all data that can be iterated over in a template with a page control is contained in a DataObjectSet. object. In fact, all data that can be iterated over in a template with a page control is contained in a DataObjectSet.
A `[api:DataObjectSet]` is a set of not just DataObjects, but of ViewableData, which the majority of A [api:DataObjectSet] is a set of not just DataObjects, but of ViewableData, which the majority of
SilverStripe's classes (including DataObject) inherit from. We can create a DataObjectSet, fill it with our data, and SilverStripe's classes (including DataObject) inherit from. We can create a DataObjectSet, fill it with our data, and
then create our graph using a page control in the template. Create the function 'BrowserPollResults' on the then create our graph using a page control in the template. Create the function 'BrowserPollResults' on the
*HomePage_Controller* class. *HomePage_Controller* class.
@ -370,7 +370,7 @@ We get the total number of submissions, which is needed to calculate the percent
Now we create an empty DataObjectSet to hold our data and then iterate over the 'Browser' submissions field. The 'groupBy' Now we create an empty DataObjectSet to hold our data and then iterate over the 'Browser' submissions field. The 'groupBy'
method of DataObjectSet splits our DataObjectSet by the 'Browser' field passed to it. The percentage of submissions for each method of DataObjectSet splits our DataObjectSet by the 'Browser' field passed to it. The percentage of submissions for each
browser is calculated using the size of the DataObjectSet. It puts these new DataObjectSets into an array indexed browser is calculated using the size of the DataObjectSet. It puts these new DataObjectSets into an array indexed
by the value of the field. The `[api:ArrayData]` class wraps an array into a ViewableData object, so we finally create a new by the value of the field. The [api:ArrayData] class wraps an array into a ViewableData object, so we finally create a new
ArrayData object, which we can add to our *$doSet* DataObjectSet of results. ArrayData object, which we can add to our *$doSet* DataObjectSet of results.
:::php :::php

View File

@ -172,7 +172,7 @@ Next we need to create the *results* function.
First we populate an array with the data we wish to pass to the template - the search results, query and title of the First we populate an array with the data we wish to pass to the template - the search results, query and title of the
page. The final line is a little more complicated. page. The final line is a little more complicated.
When we call a function by its url (eg http://localhost/home/results), SilverStripe will look for a template with the When we call a function by its url (eg `http://localhost/home/results`), SilverStripe will look for a template with the
name `PageType_function.ss`. As we are implementing the *results* function on the *Page* page type, we create our name `PageType_function.ss`. As we are implementing the *results* function on the *Page* page type, we create our
results page template as *Page_results.ss*. Unfortunately this doesn't work when we are using page types that are results page template as *Page_results.ss*. Unfortunately this doesn't work when we are using page types that are
children of the *Page* page type. For example, if someone used the search on the homepage, it would be rendered with children of the *Page* page type. For example, if someone used the search on the homepage, it would be rendered with
@ -193,7 +193,7 @@ function, and then attempt to render it with *Page_results.ss*, falling back to
## Creating the template ## Creating the template
Lastly we need to create the template for the search page. This template uses all the same techniques used in previous Lastly we need to create the template for the search page. This template uses all the same techniques used in previous
tutorials. It also uses a number of pagination variables, which are provided by the `[api:DataObjectSet]` tutorials. It also uses a number of pagination variables, which are provided by the [api:DataObjectSet]
class. class.
*themes/tutorial/templates/Layout/Page_results.ss* *themes/tutorial/templates/Layout/Page_results.ss*