Small text changes, added api links, cont. updating images for tutorials, fixed tutorials from member feedback
@ -406,7 +406,7 @@ to debug.
|
||||
## Related
|
||||
* [Templates](/topics/templates)
|
||||
* [Themes](/topics/themes)
|
||||
* [Developing Themes](theme-development)
|
||||
* [Developing Themes](/topics/theme-development)
|
||||
* [Widgets](/topics/widgets)
|
||||
* [Images](/reference/image)
|
||||
* [Built in page controls](/reference/built-in-page-controls)
|
||||
|
@ -9,7 +9,7 @@ BBCode is used by default in the [blog](http://silverstripe.org/blog-module) and
|
||||
|
||||
To add bbcode parsing to a template, instead of $Content use:
|
||||
|
||||
:::php
|
||||
:::ss
|
||||
$Content.Parse(BBCodeParser)
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ SilverStripe supports a simple set of conditional logic
|
||||
<% end_if %>
|
||||
|
||||
|
||||
See more information on conditional logic on [templates](templates).
|
||||
See more information on conditional logic on [templates](/topics/templates).
|
||||
|
||||
### Site wide settings
|
||||
|
||||
|
@ -15,7 +15,7 @@ See `[api:TableListField]`.
|
||||
|
||||
## Setting Parent/Child-Relations
|
||||
|
||||
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
|
||||
specific parent relation:
|
||||
|
||||
@ -62,18 +62,18 @@ You can override this behaviour in various ways:
|
||||
|
||||
If you don't want several functions to appear (e.g. no add-link), there's several ways:
|
||||
|
||||
* 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".
|
||||
|
||||
* Subclass ComplexTableField and override the rendering-mechanism
|
||||
* Use ComplexTableField->setTemplate() and ComplexTableField->setTemplatePopup() to provide custom templates
|
||||
* Subclass `[api:ComplexTableField]` and override the rendering-mechanism
|
||||
* Use `ComplexTableField->setTemplate()` and `ComplexTableField->setTemplatePopup()` to provide custom templates
|
||||
|
||||
### Customising fields and Requirements in the popup
|
||||
|
||||
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.
|
||||
|
||||
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 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.
|
||||
|
||||
You can also customise Javascript which is loaded for the Lightbox. As Requirements::clear() is called when the popup is
|
||||
instantiated, 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).
|
||||
|
||||
For this, create a function called "getRequirementsForPopup".
|
||||
@ -116,11 +116,11 @@ 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.
|
||||
|
||||
It's not a perfect solution, but it works relatively well to get a simple 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.
|
||||
|
||||
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 use a popup as well, out of the box.
|
||||
to use a popup as well, out of the box.
|
||||
|
||||
## Subclassing
|
||||
|
||||
@ -144,7 +144,7 @@ Most of the time, you need to override the following methods:
|
||||
* 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)
|
||||
* Control width/height of popup by constructor (hardcoded at the moment)
|
||||
* Integrate search from MemberTableField.php directly on 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)
|
||||
* 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/ and 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))
|
||||
|
@ -5,7 +5,7 @@ opting for "convention over configuration". This page details what that databas
|
||||
|
||||
## Base tables
|
||||
|
||||
Each direct sub-class of DataObject will have its own table.
|
||||
Each direct sub-class of `[api:DataObject]` will have its own table.
|
||||
|
||||
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:
|
||||
|
||||
* Class SiteTree extends DataObject: Title, Content fields
|
||||
* Class Page extends SiteTree: Abstract field
|
||||
* Class NewsSection extends SiteTree: *No special fields*
|
||||
* Class NewsArticle extend Page: ArticleDate field
|
||||
* Class `[api:SiteTree]` extends `[api:DataObject]`: Title, Content fields
|
||||
* Class `[api:Page]` extends `[api:SiteTree]`: Abstract field
|
||||
* Class NewsSection extends `[api:SiteTree]`: *No special fields*
|
||||
* Class NewsArticle extend `[api:Page]`: ArticleDate field
|
||||
|
||||
The data for the following classes would be stored across the following tables:
|
||||
|
||||
* SiteTree
|
||||
* `[api:SiteTree]`
|
||||
* ID: Int
|
||||
* ClassName: Enum('SiteTree', 'Page', 'NewsArticle')
|
||||
* Created: Datetime
|
||||
* LastEdited: Datetime
|
||||
* Title: Varchar
|
||||
* Content: Text
|
||||
* Page
|
||||
* `[api:Page]`
|
||||
* ID: Int
|
||||
* Abstract: Text
|
||||
* NewsArticle
|
||||
@ -59,16 +59,16 @@ The data for the following classes would be stored across the following tables:
|
||||
|
||||
The way it works is this:
|
||||
|
||||
* "Base classes" are direct sub-classes of DataObject. They are always given a table, whether or not they have special
|
||||
fields. This is called the "base table"
|
||||
* "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"
|
||||
* 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)
|
||||
* 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.
|
||||
* 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 SiteTree.
|
||||
record #2 in Page refers to the same object as record #2 in `[api:SiteTree]`.
|
||||
|
||||
To retrieve a news article, SilverStripe joins the SiteTree, Page and NewsArticle tables by their ID fields. We use a
|
||||
To retrieve a news article, SilverStripe joins the `[api:SiteTree]`, `[api: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.
|
||||
|
||||
## Staging and versioning
|
||||
@ -126,4 +126,4 @@ other database platforms if we chose to support them.
|
||||
* We'd like to support more than just MySQL, however, there needs to be a pretty good reason for doing so since it will
|
||||
become something that needs to be supported for the rest of SilverStripe's life and could easily become an albatross.
|
||||
On the cards are MS SQL, PostgreSQL and SQLite.
|
||||
* It could be desireable to implement a non-repeating auto-numbering system.
|
||||
* It could be desirable to implement a non-repeating auto-numbering system.
|
||||
|
@ -12,7 +12,7 @@ A single database record & abstract class for the data-access-model.
|
||||
|
||||
## Basics
|
||||
|
||||
The call to `DataObject->getCMSFields()` is the centerpiece of every data administration interface in Silverstripe,
|
||||
The call to `DataObject->getCMSFields()` is the centerpiece of every data administration interface in SilverStripe,
|
||||
which returns a `[api:FieldSet]`''.
|
||||
|
||||
:::php
|
||||
@ -33,8 +33,6 @@ These calls retrieve a `[api:FieldSet]` for the area where you intend to work wi
|
||||
|
||||
* Requirements: SilverStripe 2.3.*
|
||||
|
||||
// bla
|
||||
|
||||
:::php
|
||||
$fields = singleton('MyDataObject')->getCMSFields();
|
||||
|
||||
@ -82,8 +80,8 @@ Example: Simple Definition
|
||||
}
|
||||
|
||||
|
||||
Searchable fields will be appear in the search interface with a default form field (usually a TextField) and a default
|
||||
search filter assigned (usually an ExactMatchFilter). To override these defaults, you can specify additional information
|
||||
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
|
||||
on `$searchable_fields`:
|
||||
|
||||
:::php
|
||||
@ -95,7 +93,7 @@ on `$searchable_fields`:
|
||||
}
|
||||
|
||||
|
||||
If you assign a single string value, you can set it to be either a FormField or 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:
|
||||
|
||||
:::php
|
||||
@ -144,7 +142,7 @@ To include relations (''$has_one'', `$has_many` and `$many_many`) in your search
|
||||
|
||||
* Requirements: SilverStripe 2.3.*
|
||||
|
||||
Summary fields can be used to show a quick overview of the data for a specific 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.
|
||||
|
||||
Example: Getting predefined summary fields
|
||||
|
@ -9,7 +9,7 @@ implementation. Have a look at `[api:Object->useCustomClass()]`.
|
||||
|
||||
## Usage
|
||||
|
||||
Your Decorator will nee to be a subclass of DataObjectDecorator or the Extension class.
|
||||
Your Decorator will nee to be a subclass of `[api:DataObjectDecorator]` or the `[api:Extension]` class.
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -27,7 +27,7 @@ class you want to extend.
|
||||
### 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
|
||||
ForumRole decorator to the Member object.
|
||||
`[api:ForumRole]` decorator to the `[api:Member]` object.
|
||||
|
||||
|
||||
:::php
|
||||
@ -97,20 +97,20 @@ The $fields parameter is passed by reference, as it is an object.
|
||||
|
||||
### Custom database generation
|
||||
|
||||
Some decorators are designed to transparently add more sophisticated data-collection capabilities to your data object.
|
||||
For example, 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.
|
||||
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,
|
||||
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.
|
||||
|
||||
* You can query $this->owner for information about the data object, such as the fields it has
|
||||
* You can query ``$this->owner`` for information about the data object, such as the fields it has
|
||||
* You can use **DB::requireTable($tableName, $fieldList, $indexList)** to set up your new tables. This function takes
|
||||
care of creating, modifying, or leaving tables as required, based on your desired schema.
|
||||
|
||||
### Custom write queries
|
||||
|
||||
If you have customised the generated database, then you probably want to change the way that writes happen. This is
|
||||
used by 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
|
||||
the write about to happen, and is able to amend this as desired, since it is passed by reference.
|
||||
@ -125,17 +125,17 @@ be modified as needed by your method. Instead of a manipulation array, we have
|
||||
|
||||
### Additional methods
|
||||
|
||||
The other thing you may want to do with a decorator is provide a method that can be called on the DataObject that is
|
||||
being decorated. For instance, you may add a publish() method to every DataObject that is decorated with Versioned.
|
||||
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]`.
|
||||
|
||||
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 = The DataObjectDecorator object.
|
||||
* $this->owner = The related DataObject object.
|
||||
* $this = The `[api:DataObjectDecorator]` object.
|
||||
* $this->owner = The related `[api:DataObject]` object.
|
||||
|
||||
If you want to add your own internal properties, you can add this to the DataObjectDecorator, and these will be referred
|
||||
to as $this->propertyName. Every DataObject has an associated DataObjectDecorator instance for each class that it is
|
||||
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
|
||||
decorated by.
|
||||
|
||||
:::php
|
||||
|
@ -6,7 +6,7 @@ This class represents a set of `[api:DataObject]`s, such as the results of a que
|
||||
[datamodel](/topics/datamodel)-related querying. It implements the [Iterator
|
||||
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 DataObjectSet.
|
||||
Relations (`has_many`/`many_many`) are described in `[api:ComponentSet]`, a subclass of `[api:DataObjectSet]`.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -56,7 +56,7 @@ This works on the object itself, so do NOT do something like this:
|
||||
:::php
|
||||
$sortedSet = $mySet->sort('Lastname'); //ascending
|
||||
|
||||
## Merge with other DataObjectSets
|
||||
## Merge with other `[api:DataObjectSet]`s
|
||||
|
||||
:::php
|
||||
$myFirstSet->merge($mySecondSet);
|
||||
@ -88,7 +88,7 @@ It is good practice to check for empty sets before doing any iteration.
|
||||
|
||||
### Paging
|
||||
|
||||
DataObjects have native support for dealing with **pagination**.
|
||||
`[api:DataObject]`s have native support for dealing with **pagination**.
|
||||
See *setPageLimits*, *setPageLength*, etc.
|
||||
|
||||
FIXME Complete pagination documentation
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
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
|
||||
the viewer and/or perform processing steps.
|
||||
|
||||
@ -12,7 +12,7 @@ the viewer and/or perform processing steps.
|
||||
|
||||
## Redirection
|
||||
|
||||
The 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
|
||||
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
|
||||
|
||||
1. Adding rules to Director in `<yourproject>/_config.php` (See Default Rewrite Rules below for examples)
|
||||
2. Adding rules in your extended Controller class via the *$url_handlers* static variable
|
||||
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
|
||||
|
||||
See [controller](/topics/controller) for examples and explanations on how the rules get processed for both 1 and 2 above.
|
||||
|
||||
@ -56,7 +56,7 @@ SilverStripe comes with certain rewrite rules (e.g. for *admin/assets*).
|
||||
|
||||
## Links
|
||||
|
||||
* See 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
|
||||
|
||||
## API Documentation
|
||||
|
@ -53,7 +53,7 @@ All requests go through main.php, which sets up the environment and then hands c
|
||||
**See:** The API documentation of `[api:Main]` for information about how main.php processes requests.
|
||||
## Director and URL patterns
|
||||
|
||||
main.php relies on Director to work out which controller should handle this request. 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()]`.
|
||||
|
||||
**See:** The API documentation of `[api:Director]` for information about how Director parses URLs and hands control over to a controller object.
|
||||
@ -73,7 +73,7 @@ When you create a function, you can access the ID like this:
|
||||
|
||||
## Controllers and actions
|
||||
|
||||
Controllers are the building blocks of your application.
|
||||
`[api:Controller]`s are the building blocks of your application.
|
||||
|
||||
**See:** The API documentation for `[api:Controller]`
|
||||
|
||||
|
@ -48,7 +48,7 @@ set {inlcudeDefaultJS} to false and work with behaviour.js.
|
||||
|
||||
* `[FileField](api:FileField)`: Simple file upload dialog.
|
||||
* `[FileIFrameField](api:FileIFrameField)`: File uploads through an iframe
|
||||
* `[api:Image]`: 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
|
||||
relationships. Unlike ImageField, it doesn't use an iframe.
|
||||
|
||||
|
@ -111,8 +111,8 @@ and whenever you upload or modify an Image through SilverStripe.
|
||||
|
||||
If you encounter problems with images not appearing, or have mysteriously disappeared, you can try manually flushing the
|
||||
image cache.
|
||||
|
||||
|
||||
http://www.mysite.com/images/flush
|
||||
|
||||
|
||||
## API Documentation
|
||||
`[api:Image]`
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
Reference articles complement our auto-generated [API docs](http://api.silverstripe.org) in providing deeper introduction into a specific API.
|
||||
|
||||
* [Advanced templates](advanced-templates): Advanced SilverStripe template syntax
|
||||
* [BBCode](bbcode): Extensible shortcode syntax
|
||||
* [Built-in page controls](built-in-page-controls): Explains the template syntax and available variables/placeholders
|
||||
* [ComplexTableField](complextablefield): Manage records and their relations inside the CMS
|
||||
@ -29,7 +30,6 @@ Reference articles complement our auto-generated [API docs](http://api.silverstr
|
||||
* [StaticPublisher](staticpublisher): Export a page tree as static HTML for better performance and portability
|
||||
* [TableField](tablefield): Add and edit records with inline edits in this form field
|
||||
* [TableListField](tablelistfield): View and delete records in the CMS
|
||||
* [Templates](templates): Process our data for output in HTML and other formats
|
||||
* [Typography](typography): CSS file to enable WYSIWYG previews in the CMS
|
||||
* [urlvariabletools](urlvariabletools): Debug and maintenance switches
|
||||
* [Versioned](versioned): Extension for SiteTree and other classes to store old versions and provide "staging"
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
The 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
|
||||
|
||||
The 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()**
|
||||
|
||||
@ -38,10 +38,11 @@ Returns the full *Member* Object for the current user, returns *null* if user is
|
||||
## Subclassing
|
||||
|
||||
<div class="warning" markdown="1">
|
||||
This is the least desirable way of extending the Member class. It's better to use DataObjectDecorator (see below).
|
||||
This is the least desirable way of extending the `[api:Member]` class. It's better to use `[api:DataObjectDecorator]`
|
||||
(see below).
|
||||
</div>
|
||||
|
||||
You can defined subclasses of 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
|
||||
class MyMember extends Member {
|
||||
@ -63,8 +64,8 @@ Note that if you want to look this class-name up, you can call Object::getCustom
|
||||
## Overloading getCMSFields()
|
||||
|
||||
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 FieldSet object. You should generally start by calling
|
||||
parent::getCMSFields() and manipulate the FieldSet from there.
|
||||
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.
|
||||
|
||||
:::php
|
||||
function getCMSFields() {
|
||||
@ -78,11 +79,11 @@ parent::getCMSFields() and manipulate the FieldSet from there.
|
||||
|
||||
## Extending Member or DataObject?
|
||||
|
||||
Basic rule: Class "Member" should just be extended for entities who have some kind of login.
|
||||
If you have different types of Members in the system, you have to make sure that those with login-capabilities have
|
||||
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
|
||||
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 member to avoid conflicts
|
||||
with the Member-database. This enables us to have a different subclass of Member for an email-address with login-data,
|
||||
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,
|
||||
and another subclass for the same email-address in the address-database.
|
||||
|
||||
## Member Role Decorator
|
||||
@ -95,7 +96,7 @@ class. A better way is to use role decorators to add this behaviour.
|
||||
// OR
|
||||
Member::add_role('ForumRole');
|
||||
|
||||
A role decorator is simply a subclass of `[api:DataObjectDecorator]` that is designed to be used to add behaviour to 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
|
||||
things, you should add appropriate `[api:Permission::checkMember()]` calls to the role's methods.
|
||||
|
||||
|
@ -104,7 +104,7 @@ fields are searched (e.g. "partial match", "fulltext", etc.) using `$searchable_
|
||||
## Summary Fields
|
||||
|
||||
Summary Fields are the columns which are shown in the `[api:TableListField]` when viewing DataObjects. These can be
|
||||
customized for each DataObject's search results using `$summary_fields`.
|
||||
customized for each `[api:DataObject]`'s search results using `$summary_fields`.
|
||||
|
||||
* See `[api:DataObject]`
|
||||
|
||||
|
@ -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.
|
||||
To help do this, SilverStripe 2.4 also introduces the concept of Aggregates. These calculate and return SQL aggregates
|
||||
on sets of DataObjects - 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
|
||||
otherwise. By using aggregates, that's easy
|
||||
@ -236,6 +236,4 @@ Can be re-written as:
|
||||
<% end_control %>
|
||||
<% end_cached %>
|
||||
|
||||
<% end_cached %>
|
||||
|
||||
|
||||
<% end_cached %>
|
@ -12,7 +12,7 @@ and then select the permissions tab, and add that permission to the list.
|
||||
The simple usage, Permission::check("PERM_CODE") will detect if the currently logged in member has the given permission.
|
||||
See the API docs for more options.
|
||||
|
||||
** Group ACLs **
|
||||
**Group ACLs**
|
||||
|
||||
* Call **Permission::check("MY_PERMISSION_CODE")** to see if the current user has MY_PERMISSION_CODE.
|
||||
* MY_PERMISSION_CODE can be loaded into the Security admin on the appropriate group, using the "Permissions" tab.
|
||||
@ -22,9 +22,9 @@ You can use whatever codes you like, but for the sanity of developers and users,
|
||||
|
||||
## PermissionProvider
|
||||
|
||||
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
|
||||
[:permission:codes](/reference/permission)).
|
||||
[permissions:codes](/reference/permission)).
|
||||
|
||||
:::php
|
||||
class Page_Controller implements PermissionProvider {
|
||||
|
@ -133,8 +133,7 @@ In your controller's init() function, add:
|
||||
|
||||
## 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
|
||||
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
RestfulService enables connecting to remote web services which supports REST interface and consume those web services
|
||||
(for example Flickr, Youtube, Amazon and etc). RestfulService can parse the XML response (sorry no JSON support)
|
||||
`[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)
|
||||
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 RestfulService object or create a class extending the
|
||||
RestfulService (see `flickrservice` and `youtubeservice` modules).
|
||||
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
|
||||
[youtubeservice](http://silverstripe.org/youtube-gallery-module/) modules).
|
||||
|
||||
|
||||
## Examples
|
||||
@ -112,8 +113,8 @@ to get the value of entry node with the namespace media, use:
|
||||
|
||||
### Handling Errors
|
||||
|
||||
If the web service returned an error (for example, API key not available or inadequate parameters) RestfulService could
|
||||
delgate the error handling to it's descendant class. To handle the errors define a function called errorCatch
|
||||
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
|
||||
|
||||
:::php
|
||||
/*
|
||||
@ -142,7 +143,7 @@ If you want to bypass error handling on your sub-classes you could define that i
|
||||
|
||||
## Other Uses
|
||||
|
||||
### How to use 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
|
||||
such as del.icio.us
|
||||
|
@ -5,7 +5,7 @@
|
||||
Generating RSS/Atom-feeds is just a matter of rendering a `[api:DataObject]` and the Page Comment Interface.
|
||||
Handled through the `[api:RSSFeed]` class.
|
||||
|
||||
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
|
||||
your website, so its advisable to just create feeds from subclasses of `[api:SiteTree]`.
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
You can use 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:
|
||||
|
||||
:::php
|
||||
@ -44,7 +44,7 @@ something like this:
|
||||
}
|
||||
|
||||
class Page_Controller extends ContentController {
|
||||
|
||||
|
||||
function init() {
|
||||
RSSFeed::linkToFeed($this->Link() . "rss", "10 Most Recently Updated Pages");
|
||||
parent::init();
|
||||
@ -72,7 +72,7 @@ can also do http://www.yoursite.com/PageComment/rss?pageid=46 where pageid is th
|
||||
|
||||
## External Sources
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
@ -3,16 +3,16 @@
|
||||
## Introduction
|
||||
|
||||
Manages searching of properties on one or more `[api:DataObject]` types, based on a given set of input parameters.
|
||||
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.
|
||||
|
||||
The default output of a 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.
|
||||
|
||||
In case you need multiple contexts, consider namespacing your request parameters by using `FieldSet->namespace()` on
|
||||
the $fields constructor parameter.
|
||||
|
||||
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.
|
||||
|
||||
## Requirements
|
||||
@ -33,9 +33,10 @@ See `[api:DataObject::$searchable_fields]`.
|
||||
|
||||
### Customizing fields and filters
|
||||
|
||||
In this example we're defining three attributes on our MyDataObject subclasss: `PublicProperty`, `HiddenProperty`
|
||||
In this example we're defining three attributes on our MyDataObject subclass: `PublicProperty`, `HiddenProperty`
|
||||
and `MyDate`. The attribute `HiddenProperty` should not be searchable, and `MyDate` should only search for dates
|
||||
*after* the search entry (with a `GreaterThanFilter`). Similiar to the built-in `DataObject->getDefaultSearchContext()` method, we're building our own `getCustomSearchContext()` variant.
|
||||
*after* the search entry (with a `GreaterThanFilter`). Similiar to the built-in `DataObject->getDefaultSearchContext()`
|
||||
method, we're building our own `getCustomSearchContext()` variant.
|
||||
|
||||
:::php
|
||||
class MyDataObject extends DataObject {
|
||||
@ -86,11 +87,6 @@ and `MyDate`. The attribute `HiddenProperty` should not be searchable, and `MyDa
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Pagination
|
||||
|
||||
For paginating records on multiple pages, you need to get the generated `SQLQuery` before firing off the actual
|
||||
@ -184,7 +180,7 @@ Results.PaginationSummary(4) defines how many pages the search will show in the
|
||||
|
||||
## Available SearchFilters
|
||||
|
||||
See SearchFilter API Documentation `[api:SearchFilter]`
|
||||
See `[api:SearchFilter]` API Documentation
|
||||
|
||||
## API Documentation
|
||||
`[api:SearchContext]`
|
||||
|
@ -6,23 +6,23 @@ the site reports by clicking "Site Reports" in the left hand side bar and select
|
||||
|
||||
![](_images/sitereport.png)
|
||||
|
||||
By default the CMS ships with a couple basic reports -
|
||||
By default the CMS ships with a couple of basic reports -
|
||||
|
||||
## Default Reports
|
||||
|
||||
* "Empty Pages" which will generate a list of pages without content
|
||||
* "Pages edited in the last 2 weeks" which will list all the pages edited in the last 2 weeks in order of most recently
|
||||
edited.
|
||||
* "To Do" which displays all the ToDo notes you have added to each page and a link to the page. This is in 2.2.2 and
|
||||
* "To Do" which displays all the ToDo notes you have added to each page and a link to the page. Note: This is in 2.2.2 and
|
||||
later
|
||||
* Also the Ecommerce module provides 2 or 3 reports out of box. Such as All Products, Orders...
|
||||
|
||||
## Creating Custom Reports
|
||||
|
||||
You can create reports for you own data quickly and easily. A general knowledge of Silverstripe's
|
||||
You can create reports for you own data quickly and easily. A general knowledge of SilverStripe's
|
||||
[Datamodel](/topics/datamodel) would help before you attempt this.
|
||||
|
||||
Inside the Mysite/Code folder - your projects code, create a file called CustomSideReport or MyProjectSiteReport and
|
||||
Inside the Mysite/Code folder - your projects code, create a file called `CustomSideReport` or `MyProjectSiteReport` and
|
||||
inside this file we can add our site reports.
|
||||
|
||||
CustomSideReport.php
|
||||
@ -91,6 +91,4 @@ file and add class's as you need them inside that for each report.
|
||||
* More examples.
|
||||
|
||||
## API Documentation
|
||||
`[api:ReportAdmin]`
|
||||
|
||||
|
||||
`[api:ReportAdmin]`
|
@ -2,12 +2,12 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
The 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'.
|
||||
|
||||
## Accessing SiteConfig Options
|
||||
## Accessing `[api:SiteConfig]` Options
|
||||
|
||||
You can access 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
|
||||
$SiteConfig.Title
|
||||
@ -28,8 +28,7 @@ Or if you want to access variables in the PHP you can do
|
||||
$config->Title
|
||||
|
||||
|
||||
|
||||
## Extending SiteConfig
|
||||
## Extending `[api:SiteConfig]`
|
||||
|
||||
To extend the options available in the panel you can define your own fields via an Extension.
|
||||
|
||||
@ -59,13 +58,13 @@ Then add a link to your extension in the _config.php file like below.
|
||||
Object::add_extension('SiteConfig', 'CustomSiteConfig');
|
||||
|
||||
|
||||
This tells SilverStripe to add the CustomSiteConfig extension to the 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
|
||||
the admin interface. You may need to reload it with a ?flush=1 on the end.
|
||||
|
||||
You can define as many extensions for 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.
|
||||
|
||||
## API Documentation
|
||||
`[api:SiteConfig]`
|
||||
`[api:SiteConfig]`
|
@ -5,7 +5,7 @@
|
||||
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...
|
||||
|
||||
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:
|
||||
|
||||
* Custom getters/setters
|
||||
@ -15,7 +15,7 @@ reasons. You'll break the behaviour of:
|
||||
* `[api:DataObject]`
|
||||
* 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
|
||||
[datamodel](/topics/datamodel).
|
||||
|
||||
## Usage
|
||||
@ -109,7 +109,7 @@ Useful for creating dropdowns.
|
||||
|
||||
### "Raw" SQL with DB::query()
|
||||
|
||||
This is not recommended for most cases, but you can also use the Silverstripe database-layer to fire off a raw query:
|
||||
This is not recommended for most cases, but you can also use the SilverStripe database-layer to fire off a raw query:
|
||||
|
||||
:::php
|
||||
DB::query("UPDATE Player SET Status='Active'");
|
||||
@ -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
|
||||
* Filtering records for correct *ClassName*
|
||||
|
||||
### Transforming a result to 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
|
||||
DataObjects.
|
||||
This is a commonly used technique inside SilverStripe: Use raw SQL, but transfer the resulting rows back into
|
||||
`[api:DataObject]`s.
|
||||
|
||||
:::php
|
||||
$sqlQuery = new SQLQuery();
|
||||
@ -183,16 +183,16 @@ DataObjects.
|
||||
var_dump($myFirstPlayer->Status); // undefined, as we didn't LEFT JOIN the BasePlayer-table
|
||||
|
||||
|
||||
CAUTION: Depending on the selected columns in your query, you might get into one of the following scenarios:
|
||||
**CAUTION:** Depending on the selected columns in your query, you might get into one of the following scenarios:
|
||||
|
||||
* 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
|
||||
this table, you might not be able to access original object-properties.
|
||||
* You can't create DataObjects 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
|
||||
above example
|
||||
|
||||
Be careful when saving back DataObjects 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.
|
||||
## Using FormFields with custom SQL
|
||||
|
||||
|
@ -83,17 +83,17 @@ you can also add an exclusion
|
||||
function allPagesToCache() {
|
||||
$urls = array();
|
||||
$pages = DataObject::get("SiteTree");
|
||||
|
||||
|
||||
// ignored page types
|
||||
$ignored = array('UserDefinedForm');
|
||||
|
||||
|
||||
foreach($pages as $page) {
|
||||
// check to make sure this page is not in the classname
|
||||
if(!in_array($page->ClassName, $ignored)) {
|
||||
$urls = array_merge($urls, (array)$page->subPagesToCache());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $urls;
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ example](http://open.silverstripe.com/browser/modules/cms/trunk/code/staticpubli
|
||||
.htaccess update simpler.
|
||||
|
||||
Just look for this line:
|
||||
|
||||
|
||||
RewriteRule .* sapphire/main.php?url=%1&%{QUERY_STRING} [L]
|
||||
|
||||
|
||||
|
@ -2,9 +2,8 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
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).
|
||||
`[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).
|
||||
|
||||
See `[api:TableListField]` for more documentation on the base-class
|
||||
|
||||
@ -66,15 +65,15 @@ Note: You still have to attach some form of `[api:Validator]` to the form to tri
|
||||
|
||||
### Nested Table Fields
|
||||
|
||||
When you have 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 TableField extra data, and this will
|
||||
be populated with the newly created record id upon save.
|
||||
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
|
||||
will be populated with the newly created record id upon save.
|
||||
|
||||
## Known Issues
|
||||
|
||||
* A 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 TableField will be blank again.
|
||||
* You can't add **visible default data** to columns in a TableField, please use *setExtraData*
|
||||
* 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.
|
||||
* You can't add **visible default data** to columns in a `[api:TableField]`, please use *setExtraData*
|
||||
|
||||
|
||||
## API Documentation
|
||||
|
@ -8,9 +8,9 @@ Provides customizeable columns, record-deletion by ajax, paging, sorting, CSV-ex
|
||||
|
||||
## Example
|
||||
|
||||
Here's an example of a full featured 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, allowing
|
||||
export of data as a CSV.
|
||||
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,
|
||||
allowing export of data as a CSV.
|
||||
|
||||
:::php
|
||||
function getReportField() {
|
||||
@ -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";
|
||||
$myTableListField->setCustomCsvQuery($customQuery);
|
||||
|
||||
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
|
||||
$myTableListField = new TableListField(
|
||||
@ -139,12 +139,12 @@ Example (sorting by "FirstName" column):
|
||||
);
|
||||
|
||||
|
||||
If you want to sort by custom getters in your 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.
|
||||
|
||||
### Casting
|
||||
|
||||
Column-values can be casted, based on the casting-types available through DBObject (sapphire/core/model/fieldtypes).
|
||||
Column-values can be casted, based on the casting-types available through DBObject (sapphire/core/model/fieldtypes).
|
||||
|
||||
:::php
|
||||
$myTableListField->setFieldCasting(array(
|
||||
@ -155,7 +155,7 @@ Column-values can be casted, based on the casting-types available through DBObje
|
||||
|
||||
### Permissions
|
||||
|
||||
Permissions vary in different 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.
|
||||
|
||||
:::php
|
||||
@ -237,7 +237,7 @@ implement averages etc.
|
||||
)
|
||||
);
|
||||
|
||||
In TableField-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:
|
||||
|
||||
* sum
|
||||
@ -245,7 +245,7 @@ Available methods:
|
||||
|
||||
### Grouping
|
||||
|
||||
Used to group by a specific column in the 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().
|
||||
(Automatically disables sorting).
|
||||
|
||||
@ -257,7 +257,7 @@ Please use only together with addSummary().
|
||||
|
||||
### Custom Sorting
|
||||
|
||||
Please subclass TableListField to implement custom sorting, following the naming-convention
|
||||
Please subclass `[api:TableListField]` to implement custom sorting, following the naming-convention
|
||||
"`colFunction_<yourFunctionName>`".
|
||||
|
||||
:::php
|
||||
@ -274,7 +274,7 @@ Please subclass TableListField to implement custom sorting, following the naming
|
||||
In case you want to perform utility-functions like "export" or "print" through action-buttons,
|
||||
make sure to subclass Utility() which collates all possible actions.
|
||||
|
||||
### Customizing Look&Feel
|
||||
### Customizing Look & Feel
|
||||
|
||||
You can exchange the used template, e.g. to change applied CSS-classes or the HTML-markup:
|
||||
|
||||
@ -285,4 +285,4 @@ You can exchange the used template, e.g. to change applied CSS-classes or the HT
|
||||
|
||||
## API Documentation
|
||||
|
||||
[api:TableListField]
|
||||
`[api:TableListField]`
|
||||
|
@ -4,8 +4,7 @@
|
||||
SilverStripe lets you customise the style of content in the CMS.
|
||||
|
||||
## Usage
|
||||
This is done by setting up a CSS file called
|
||||
(projectname)/css/typography.css
|
||||
This is done by setting up a CSS file called (projectname)/css/typography.css.
|
||||
|
||||
You also need to create a file called (projectname)/css/editor.css with the following content:
|
||||
|
||||
@ -40,8 +39,8 @@ It's important to realise that this CSS file is included directly into the CMS s
|
||||
can alter the styling of other parts of the interface. While this is novel, it can be dangerous and is probably not
|
||||
what you're after.
|
||||
|
||||
The way around this is to limit all your styling selectors to elements inside something with class="typography". The
|
||||
other half of this is to put class="typography" onto any area in your template where you would like the styling to be
|
||||
The way around this is to limit all your styling selectors to elements inside something with `class="typography"`. The
|
||||
other half of this is to put `class="typography"` onto any area in your template where you would like the styling to be
|
||||
applied.
|
||||
|
||||
**WRONG**
|
||||
@ -73,7 +72,7 @@ applied.
|
||||
|
||||
|
||||
If you would to include different styles for different sections of your site, you can use class names the same as the
|
||||
name of the data fields. This example sets up different paragraph styles for 2 HTML editor fieldsc alled Content and
|
||||
name of the data fields. This example sets up different paragraph styles for 2 HTML editor fields called Content and
|
||||
OtherContent:
|
||||
|
||||
:::css
|
||||
@ -89,7 +88,7 @@ OtherContent:
|
||||
### 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
|
||||
HTMLEditorField method setCSSClass.
|
||||
`[api:HTMLEditorField]` method setCSSClass.
|
||||
|
||||
This example sets another CSS class typographybis:
|
||||
|
||||
@ -104,5 +103,4 @@ This example sets another CSS class typographybis:
|
||||
}
|
||||
|
||||
|
||||
This functionality will be available in the version 2.0.2 of the CMS.
|
||||
|
||||
**Note:** This functionality will be available in the version 2.0.2 of the CMS.
|
@ -3,7 +3,7 @@
|
||||
## Introduction
|
||||
|
||||
This page lists a number of "page options" , "rendering tools" or "special URL variables" that you can use to debug your
|
||||
sapphire applications. These are consumed in PHP using the $_REQUEST or $_GET superglobals throughout the Sapphire
|
||||
sapphire applications. These are consumed in PHP using the $_REQUEST or $_GET super globals throughout the Sapphire
|
||||
core.
|
||||
|
||||
**General Usage**
|
||||
@ -18,8 +18,8 @@ Append the option and corresponding value to your URL in your browser's address
|
||||
| URL Variable | | Values | | Description |
|
||||
| ------------ | | ------ | | ----------- |
|
||||
| flush | | 1,all | | This will clear out all cached information about the page. This is used frequently during development - for example, when adding new PHP or SS files. See below for value descriptions. |
|
||||
| showtemplate | | 1 | | Show the compiled version of all the templates used, including line numbers. Good when you have a syntax error in a template. Cannot be used on a Live site without **isDev** **flush** can be used with the following values: |
|
||||
| ?flush=1 | | | | | Flushes the current page and included templates |
|
||||
| showtemplate | | 1 | | Show the compiled version of all the templates used, including line numbers. Good when you have a syntax error in a template. Cannot be used on a Live site without **isDev**. **flush** can be used with the following values: |
|
||||
| ?flush=1 | | | | Flushes the current page and included templates |
|
||||
| ?flush=all | | | | Flushes the entire template cache |
|
||||
|
||||
## General Testing
|
||||
@ -29,13 +29,13 @@ 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 |
|
||||
| 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_request | | 1 | | Show all steps of the request from initial HTTPRequest to 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
|
||||
|
||||
| URL Variable | | Values | | Description |
|
||||
| ------------ | | ------ | | ----------- |
|
||||
| debugmanifest | | 1 | | Show the entire Sapphire manifest as currently built (Use /dev/build to rebuild) |
|
||||
| debugmanifest | | 1 | | Show the entire Sapphire manifest as currently built (Use `/dev/build` to rebuild) |
|
||||
| usetestmanifest | | 1 | | Force use of the default test manifest |
|
||||
| debugmethods | | 1 | | Shows all methods available when an object is constructed (useful when extending classes or using object decorators) |
|
||||
| debugfailover | | 1 | | Shows failover methods from classes extended |
|
||||
@ -52,7 +52,7 @@ Append the option and corresponding value to your URL in your browser's address
|
||||
| URL Variable | | Values | | Description |
|
||||
| ------------ | | ------ | | ----------- |
|
||||
| debug_memory | | 1 | | Output the number of bytes of memory used for this request |
|
||||
| debug_profile | | 1 | | Enable the [profiler](/topics/debugging) for the duration of the request |
|
||||
| debug_profile | | 1 | | Enable the [profiler](/topics/debugging) for the duration of the request |
|
||||
| profile_trace | | 1 | | Includes full stack traces, must be used with **debug_profile** |
|
||||
| debug_behaviour | | 1 | | Get profiling of [Behaviour.js](http://bennolan.com/behaviour) performance (Firebug recommended) |
|
||||
| debug_javascript | | 1 | | Force debug-output on live-sites |
|
||||
@ -79,9 +79,9 @@ Redirections](security#redirect_back_to_another_page_after_login) for more infor
|
||||
|
||||
| Site URL | | Action |
|
||||
| -------- | | ------ |
|
||||
| %%http://yoursite.com%%**/dev/build** | | Rebuild the entire database and manifest, see below for additional URL Variables |
|
||||
| %%http://yoursite.com%%**/admin/publishall/** | | Publish all pages on the site |
|
||||
| %%http://yoursite.com%%**/anypage/images/flush** | | Creates new images for the page by deleting the resized ones and going back to the original to create new resized one |
|
||||
| http://yoursite.com**/dev/build** | | Rebuild the entire database and manifest, see below for additional URL Variables |
|
||||
| http://yoursite.com**/admin/publishall/** | | Publish all pages on the site |
|
||||
| http://yoursite.com**/anypage/images/flush** | | Creates new images for the page by deleting the resized ones and going back to the original to create new resized one |
|
||||
|
||||
### /dev/build
|
||||
|
||||
|
@ -28,6 +28,4 @@ whenever a blog entry has been published.
|
||||
mail("sam@silverstripe.com", "Blog published", "The blog has been published");
|
||||
parent::onAfterPublish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -19,22 +19,26 @@ It is unclear how this works for data-objects that are not pages.
|
||||
|
||||
In the security tab you can make groups for security. The way this was intended was as follows (this may be a counter
|
||||
intuitive):
|
||||
- employees
|
||||
1. marketing
|
||||
- marketing executive
|
||||
|
||||
* employees
|
||||
* marketing
|
||||
* marketing executive
|
||||
|
||||
Thus, the further up the hierarchy you go the MORE privileges you can get. Similarly, you could have:
|
||||
- members
|
||||
1. coordinators
|
||||
- admins
|
||||
|
||||
* members
|
||||
* coordinators
|
||||
* admins
|
||||
|
||||
Where members have some privileges, coordinators slightly more and administrators the most; having each group inheriting
|
||||
privileges from its parent group.
|
||||
|
||||
## Permission checking is at class level
|
||||
|
||||
SilverStripe provides a security mechanism via the *Permission::check* method (see *LeftAndMain.php* 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)
|
||||
|
||||
(next step -- go from *Permission::checkMember*...
|
||||
(next step -- go from *Permission::checkMember*...)
|
||||
|
||||
### Nuts and bolts -- figuring it out
|
||||
|
||||
@ -44,14 +48,14 @@ works.
|
||||
|
||||
### Loading the admin page: looking at security
|
||||
|
||||
If you go to [your site]/admin -- how does that work?
|
||||
*Director.php* maps the 'admin' URL request through a *Director* rule to the CMSMain controller (see `[api:CMSMain]`, with no arguments.
|
||||
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).
|
||||
|
||||
*CMSMain.init()* calls its parent which, of all things is called *LeftAndMain*. It's in *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*.
|
||||
|
||||
`[api:Security::permissionFailure]` is the next utility function you can use to redirect to the login form.
|
||||
|
||||
### Customizing Access Checks in CMS Classes
|
||||
|
||||
see `[api:LeftAndMain]`
|
||||
see `[api:LeftAndMain]`
|
@ -1,9 +1,9 @@
|
||||
# Common Configuration through _config.php
|
||||
# Common configuration through _config.php
|
||||
|
||||
## Introduction
|
||||
|
||||
Silverstripe doesn't have a global configuration-array or an interface with all available configuration-options. As all
|
||||
Silverstripe logic is contained in classes, the appropriate place to configure their behaviour is directly in the class
|
||||
SilverStripe doesn't have a global configuration-array or an interface with all available configuration-options. As all
|
||||
SilverStripe logic is contained in classes, the appropriate place to configure their behaviour is directly in the class
|
||||
itself.
|
||||
|
||||
This lack of a configuration-GUI is on purpose, as we'd like to keep developer-level options where they belong (into
|
||||
@ -12,7 +12,7 @@ CMS"](http://www.silverstripe.com/core-team-discussion/flat/2723) for further re
|
||||
|
||||
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`).
|
||||
* 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).
|
||||
|
||||
## _ss_environment.php
|
||||
@ -24,8 +24,9 @@ See [environment-management](/topics/environment-management).
|
||||
This file is detected in each folder by `[api:ManifestBuilder]`. This way, every toplevel-folder (=module)
|
||||
can have independent configuration-rules.
|
||||
|
||||
//Please note that this is the only place where you can put in procedural code - all other functionality is wrapped in
|
||||
classes (see [common-problems](/installation/common-problems)).//
|
||||
|
||||
Please note that this is the only place where you can put in procedural code - all other functionality is wrapped in
|
||||
classes (see [common-problems](/installation/common-problems)).
|
||||
|
||||
You can call most static methods from _config.php - classes will be loaded as required. Here's a list - **this is
|
||||
incomplete - please add to it** *Try to keep it in alphabetical order too! :)*
|
||||
|
@ -6,7 +6,7 @@ your SilverStripe site.
|
||||
|
||||
## Example
|
||||
|
||||
mysite/code/Controllers/FastFood.php
|
||||
`mysite/code/Controllers/FastFood.php`
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -20,14 +20,14 @@ mysite/code/Controllers/FastFood.php
|
||||
?>
|
||||
|
||||
|
||||
mysite/_config.php
|
||||
`mysite/_config.php`
|
||||
|
||||
:::php
|
||||
Director::addRules(50, array('fastfood/$Action/$ID/$Name' => 'FastFood_Controller'));
|
||||
|
||||
|
||||
Request for '/fastfood/order/24/cheesefries' would result in the following to the $arguments above. If needed, use
|
||||
"?flush=1" on the end of request after making any code changes to your controller.
|
||||
Request for `/fastfood/order/24/cheesefries` would result in the following to the $arguments above. If needed, use
|
||||
`?flush=1` on the end of request after making any code changes to your controller.
|
||||
|
||||
:::ss
|
||||
Array
|
||||
@ -42,12 +42,12 @@ Request for '/fastfood/order/24/cheesefries' would result in the following to th
|
||||
|
||||
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
|
||||
processed by the 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
|
||||
the case below we also want any orders coming through '/fastfood/drivethrough/' to use the same order function.
|
||||
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.
|
||||
|
||||
mysite/code/Controllers/FastFood.php
|
||||
`mysite/code/Controllers/FastFood.php`
|
||||
|
||||
:::php
|
||||
class FastFood_Controller extends Controller {
|
||||
@ -59,15 +59,15 @@ mysite/code/Controllers/FastFood.php
|
||||
|
||||
## URL Patterns
|
||||
|
||||
The 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**
|
||||
|
||||
| Pattern | | Description |
|
||||
| ----------- | | --------------- |
|
||||
| `$` | | **Param Variable** - Starts the name of a paramater variable, it is optional to match this unless ! is used |
|
||||
| `!` | | **Require Variable** - Placing this after a parameter variable requires data to be present for the rule to match |
|
||||
| `//` | | **Shift Point** - Declares that only variables denoted with a $ are parsed into the $params AFTER this point in the regex |
|
||||
| Pattern | Description |
|
||||
| ----------- | --------------- |
|
||||
| `$` | **Param Variable** - Starts the name of a paramater variable, it is optional to match this unless ! is used |
|
||||
| `!` | **Require Variable** - Placing this after a parameter variable requires data to be present for the rule to match |
|
||||
| `//` | **Shift Point** - Declares that only variables denoted with a $ are parsed into the $params AFTER this point in the regex |
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -30,8 +30,9 @@ Or in your template (e.g. `themes/yourtheme/templates/Page.ss`):
|
||||
:::ss
|
||||
<% require css(mymodule/css/my.css) %>
|
||||
|
||||
Management through the `Requirements` class has the advantage that modules can include their own CSS files without modifying your template.
|
||||
On the other hand, you as a template developer can "block" or change certain CSS files that are included from thirdparty code.
|
||||
Management through the `Requirements` class has the advantage that modules can include their own CSS files without modifying
|
||||
your template. On the other hand, you as a template developer can "block" or change certain CSS files that are included from
|
||||
thirdparty code.
|
||||
|
||||
## WYSIWYG editor: typography.css and editor.css
|
||||
|
||||
|
@ -22,9 +22,9 @@ for introducing their usage.
|
||||
|
||||
## HTMLText vs. Text, and HTMLVarchar vs. Varchar
|
||||
|
||||
The database field types HTMLVarchar and Varchar are exactly the same in the database. However, the templating engine
|
||||
knows to escape the Varchar field and not the HTMLVarchar field. So, it's important you use the right field if you
|
||||
don't want to be putting $FieldType.XML everywhere.
|
||||
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
|
||||
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
|
||||
going to risk double-escaping your data, forgetting to escape your data, and generally creating a confusing situation.
|
||||
|
@ -20,9 +20,11 @@ See [database-structure](/reference/database-structure) for in-depth information
|
||||
## Generating the database-schema
|
||||
|
||||
The SilverStripe database-schema is generated automatically by visiting the URL.
|
||||
`http://`<mysite>`/dev/build`
|
||||
`http://<mysite>/dev/build`
|
||||
|
||||
> Note: You need to be logged in as an administrator to perform this command.
|
||||
<div class="notice" markdown='1'>
|
||||
Note: You need to be logged in as an administrator to perform this command.
|
||||
</div>
|
||||
|
||||
## Querying Data
|
||||
|
||||
@ -46,8 +48,8 @@ Passing a *$join* statement to DataObject::get will filter results further by th
|
||||
table. **It will NOT return the additionally joined data.** The returned *$records* will always be a
|
||||
`[api:DataObject]`.
|
||||
|
||||
When using *$join* statements be sure the string is in the proper format for the respective database engine. In MySQL
|
||||
the use of backticks may be necessary when referring Table Names and potentially Columns. (see [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
|
||||
Identifiers](http://dev.mysql.com/doc/refman/5.0/en/identifiers.html)):
|
||||
|
||||
:::php
|
||||
@ -60,7 +62,6 @@ Identifiers](http://dev.mysql.com/doc/refman/5.0/en/identifiers.html)):
|
||||
"0, 10");
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
|
||||
@ -121,11 +122,15 @@ Here we combined a Player's first name and surname, accessible through $myPlayer
|
||||
}
|
||||
}
|
||||
|
||||
**CAUTION: It is common practice to make sure that pairs of custom getters/setter deal with the same data, in a consistent
|
||||
format.**
|
||||
<div class="warning" markdown='1'>
|
||||
**CAUTION:** It is common practice to make sure that pairs of custom getters/setter deal with the same data, in a consistent
|
||||
format.
|
||||
</div>
|
||||
|
||||
**CAUTION: Custom setters can be hard to debug: Please double check if you could transform your data in more
|
||||
straight-forward logic embedded to your custom controller or form-saving.**
|
||||
<div class="warning" markdown='1'>
|
||||
**CAUTION:** Custom setters can be hard to debug: Please double check if you could transform your data in more
|
||||
straight-forward logic embedded to your custom controller or form-saving.
|
||||
</div>
|
||||
|
||||
### Default Values
|
||||
|
||||
@ -139,15 +144,17 @@ new object is created.
|
||||
);
|
||||
}
|
||||
|
||||
> Note: Alternatively you can set defaults directly in the database-schema (rather than the object-model). See
|
||||
<div class="notice" markdown='1'>
|
||||
Note: Alternatively you can set defaults directly in the database-schema (rather than the object-model). See
|
||||
[data-types](data-types) for details.
|
||||
</div>
|
||||
|
||||
### Casting
|
||||
|
||||
Properties defined in *static $db* are automatically casted to their [data-types](data-types) when used in templates.
|
||||
You can also cast the return-values of your custom functions (e.g. your "virtual properties").
|
||||
Calling those functions directly will still return whatever type your php-code generates,
|
||||
but using the *obj()*-method or accessing through a template will cast the value accordig to the $casting-definition.
|
||||
but using the *obj()*-method or accessing through a template will cast the value according to the $casting-definition.
|
||||
|
||||
:::php
|
||||
class Player extends DataObject {
|
||||
@ -164,15 +171,9 @@ but using the *obj()*-method or accessing through a template will cast the value
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Relations
|
||||
|
||||
Relations are built through static array definitions on a class, in the format:\\
|
||||
`<relationship-name>` => `<classname>`{php}
|
||||
Relations are built through static array definitions on a class, in the format `<relationship-name> => <classname>`
|
||||
|
||||
### has_one
|
||||
|
||||
@ -202,8 +203,10 @@ parent element in the tree:
|
||||
|
||||
Defines 1-to-many joins. A database-column named ""`<relationship-name>`ID"" will to be created in the child-class.
|
||||
|
||||
**CAUTION: Please specify a $has_one-relationship on the related child-class as well, in order to have the necessary
|
||||
accessors available on both ends.**
|
||||
<div class="warning" markdown='1'>
|
||||
**CAUTION:** Please specify a $has_one-relationship on the related child-class as well, in order to have the necessary
|
||||
accessors available on both ends.
|
||||
</div>
|
||||
|
||||
:::php
|
||||
// access with $myTeam->Players() or $player->Team()
|
||||
@ -219,7 +222,7 @@ accessors available on both ends.**
|
||||
}
|
||||
|
||||
|
||||
To specify multiple has_manys to the same object you can use dot notation to distinguish them like below
|
||||
To specify multiple $has_manys to the same object you can use dot notation to distinguish them like below
|
||||
|
||||
:::php
|
||||
class Person {
|
||||
@ -241,7 +244,6 @@ Multiple $has_one relationships are okay if they aren't linking to the same obje
|
||||
|
||||
:::php
|
||||
/**
|
||||
|
||||
* THIS IS BAD
|
||||
*/
|
||||
class Team extends DataObject {
|
||||
@ -261,8 +263,10 @@ Multiple $has_one relationships are okay if they aren't linking to the same obje
|
||||
|
||||
Defines many-to-many joins. A new table, (this-class)_(relationship-name), will be created with a pair of ID fields.
|
||||
|
||||
**CAUTION: Please specify a $belongs_many_many-relationship on the related class as well, in order to have the necessary
|
||||
accessors available on both ends.**
|
||||
<div class="warning" markdown='1'>
|
||||
**CAUTION:** Please specify a $belongs_many_many-relationship on the related class as well, in order to have the necessary
|
||||
accessors available on both ends.
|
||||
</div>
|
||||
|
||||
:::php
|
||||
// access with $myTeam->Categories() or $myCategory->Teams()
|
||||
@ -372,10 +376,6 @@ casting data before saving.
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### onBeforeWrite
|
||||
|
||||
You can customize saving-behaviour for each DataObject, e.g. for adding security. These functions are private, obviously
|
||||
@ -411,8 +411,10 @@ Example: Disallow creation of new players if the currently logged-in player is n
|
||||
}
|
||||
|
||||
|
||||
> Note: There are no separate methods for *onBeforeCreate* and *onBeforeUpdate*. Please check for the existence of
|
||||
<div class="notice" markdown='1'>
|
||||
Note: There are no separate methods for *onBeforeCreate* and *onBeforeUpdate*. Please check for the existence of
|
||||
$this->ID to toggle these two modes, as shown in the example above.
|
||||
</div>
|
||||
|
||||
### onBeforeDelete
|
||||
|
||||
@ -453,17 +455,13 @@ See `[api:SQLQuery]` for custom *INSERT*, *UPDATE*, *DELETE* queries.
|
||||
|
||||
## Decorating DataObjects
|
||||
|
||||
You can add properties and methods to existing DataObjects like `[api:Member]` (a core class) without hacking core
|
||||
You can add properties and methods to existing `[api:DataObjects]`s like `[api:Member]` (a core class) without hacking core
|
||||
code or subclassing.
|
||||
Please see `[api:DataObjectDecorator]` for a general description, and `[api:Hierarchy]` for our most
|
||||
popular examples.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### Whats the difference between DataObject::get() and a relation-getter?
|
||||
@ -471,7 +469,7 @@ You can work with both in pretty much the same way, but relationship-getters ret
|
||||
A `[api:ComponentSet]` with relation-specific functionality.
|
||||
|
||||
:::php
|
||||
$myTeam = DataObject::get_by_id('Team',$myPlayer->TeamID); // returns DataObjectSet
|
||||
$myTeam = DataObject::get_by_id('Team',$myPlayer->TeamID); // returns DataObject
|
||||
$myTeam->add(new Player()); // fails
|
||||
|
||||
$myTeam = $myPlayer->Team(); // returns Componentset
|
||||
|
@ -32,17 +32,17 @@ 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
|
||||
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 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.
|
||||
|
||||
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
|
||||
|
||||
:::php
|
||||
Director::set_environment_type("test");
|
||||
|
||||
|
||||
A common situation is to enable password protected site viewing on your test site only. You can enable that but adding
|
||||
this to your mysite/_config file
|
||||
this to your `mysite/_config` file
|
||||
|
||||
:::php
|
||||
if(Director::isTest()) BasicAuth::protect_entire_site();
|
||||
@ -54,7 +54,7 @@ Live sites should always run in live mode. Error messages are suppressed from th
|
||||
to email the developers. This enables near real time reporting of any fatal errors or warnings on the site and can help
|
||||
find any bugs users run into.
|
||||
|
||||
To set your site to live mode set this in your mysite/_config.php file
|
||||
To set your site to live mode set this in your `mysite/_config.php` file
|
||||
|
||||
:::php
|
||||
Director::set_environment_type("live");
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
The directory-structure in Silverstripe it built on "convention over configuration", so the placement of some files and
|
||||
The directory-structure in SilverStripe it built on "convention over configuration", so the placement of some files and
|
||||
directories is meaningful to its logic.
|
||||
|
||||
## Core Structure
|
||||
@ -16,7 +16,7 @@ Directory | Description
|
||||
## Custom Code Structure
|
||||
|
||||
We're using `<mysite>` as an example - arbitrary directory-names are allowed, as long as they don't collide with
|
||||
existing modules or the directories listes in "Core Structure".
|
||||
existing modules or the directories lists in "Core Structure".
|
||||
|
||||
| Directory | Description |
|
||||
| --------- | ----------- |
|
||||
@ -30,7 +30,7 @@ existing modules or the directories listes in "Core Structure".
|
||||
## Themes Structure
|
||||
|
||||
| `themes/blackcandy/` | Standard "blackcandy" theme |
|
||||
| ------------------ | --------------------------- |
|
||||
| ------------------ | --------------------------- |
|
||||
| `themes/blackcandy_blog/` | Theme additions for the blog module |
|
||||
| `themes/yourtheme/` | The themes folder can contain more than one theme - here's your own |
|
||||
|
||||
|
@ -15,7 +15,7 @@ an external SMTP server (see [PHP documentation for mail()](http://php.net/mail)
|
||||
|
||||
By default, emails are sent in both HTML and Plaintext format.
|
||||
A plaintext representation is automatically generated from the system
|
||||
by stripping HTML markup, or transformining it where possible
|
||||
by stripping HTML markup, or transforming it where possible
|
||||
(e.g. `<strong>text</strong>` is converted to `*text*`).
|
||||
|
||||
:::php
|
||||
@ -35,7 +35,7 @@ The default HTML template is located in `sapphire/templates/email/GenericEmail.s
|
||||
|
||||
**Requirements: SilverStripe 2.3+**
|
||||
|
||||
* Create a SS-template file called, in this example we will use 'MyEmail.ss' inside mysite/templates/email.
|
||||
* Create a SS-template file called, in this example we will use 'MyEmail.ss' inside `mysite/templates/email`.
|
||||
* Fill this out with the body text for your email. You can use any [SS-template syntax](/topics/templates) (e.g. `<% control %>`,
|
||||
`<% if %>`, $FirstName etc)
|
||||
* Choose your template with **setTemplate()**
|
||||
@ -86,14 +86,14 @@ Usage:
|
||||
|
||||
### Administrator Emails
|
||||
|
||||
The static function `Email::setAdminEmail()` can be called from a _config.php file to set the address that these
|
||||
The static function `Email::setAdminEmail()` can be called from a `_config.php` file to set the address that these
|
||||
emails should originate from. This address is used if the `from` field is empty.
|
||||
|
||||
### Redirecting Emails
|
||||
|
||||
* Email::send_all_emails_to($address) will redirect all emails sent to the given address. Handy for testing!
|
||||
* Email::cc_all_emails_to() and Email::bcc_all_emails_to() will keep the email going to its original recipients, but
|
||||
add an additional receipient in the BCC/CC header. Good for monitoring system-generated correspondence on the live
|
||||
* `Email::send_all_emails_to($address)` will redirect all emails sent to the given address. Handy for testing!
|
||||
* `Email::cc_all_emails_to()` and `Email::bcc_all_emails_to()` will keep the email going to its original recipients, but
|
||||
add an additional recipient in the BCC/CC header. Good for monitoring system-generated correspondence on the live
|
||||
systems.
|
||||
|
||||
:::php
|
||||
@ -112,7 +112,7 @@ $value)**
|
||||
..
|
||||
|
||||
|
||||
See http://en.wikipedia.org/wiki/E-mail#Message_header for a list of header names.
|
||||
See [Wikipedia E-mail Message header](http://en.wikipedia.org/wiki/E-mail#Message_header) for a list of header names.
|
||||
|
||||
### Newsletters
|
||||
|
||||
@ -120,4 +120,4 @@ The [newsletter module](http://silverstripe.org/newsletter-module) provides a UI
|
||||
|
||||
## API Documentation
|
||||
|
||||
`[api:Email]`
|
||||
`[api:Email]`
|
@ -8,17 +8,17 @@ them. Why should we have to go through the installation process and re-enter th
|
||||
when we deploy them to our servers. Additionally, our production host's database connection details will likely be
|
||||
different than our local server.
|
||||
|
||||
SilverStripe comes with a solution to this: the "_ss_environment.php" file. You can put a single _ss_environment.php
|
||||
SilverStripe comes with a solution to this: the `_ss_environment.php` file. You can put a single `_ss_environment.php`
|
||||
file in your "projects" folder on your development box, and it will be used by each of your development sites.
|
||||
|
||||
## Setting up your development machine with _ss_environment.php
|
||||
|
||||
In this example, we assume that you are managing multiple projects as subfolders of "~/Sites/", and that you can visit
|
||||
these at "http://localhost/". For example, you might have a project at "~/Sites/myproject/", and visit it at
|
||||
"http://localhost/myproject/".
|
||||
In this example, we assume that you are managing multiple projects as subfolders of `~/Sites/`, and that you can visit
|
||||
these at `http://localhost/`. For example, you might have a project at `~/Sites/myproject/`, and visit it at
|
||||
`http://localhost/myproject/`.
|
||||
|
||||
Create a new file, ~/Sites/_ss_environment.php. Put the following content in it, editing the values of the
|
||||
"SS_DATABASE_..."" and "SS_DEFAULT_ADMIN_..." defines as appropriate.
|
||||
Create a new file, `~/Sites/_ss_environment.php`. Put the following content in it, editing the values of the
|
||||
"SS_DATABASE_..." and "SS_DEFAULT_ADMIN_..." defines as appropriate.
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -53,21 +53,21 @@ of `$databaseConfig` and `Director::set_dev_servers`, and instead make sure that
|
||||
|
||||
## How it works
|
||||
|
||||
The mechanism by which the "_ss_environment.php" files work is quite simple. Here's how it works:
|
||||
The mechanism by which the `_ss_environment.php` files work is quite simple. Here's how it works:
|
||||
|
||||
* At the beginning of SilverStripe's execution, the _ss_environment.php file is searched for, and if it is found, it's
|
||||
* At the beginning of SilverStripe's execution, the `_ss_environment.php` file is searched for, and if it is found, it's
|
||||
included. SilverStripe looks in 3 places for the file:
|
||||
* The site's base folder (ie, a sibling of sapphire, jsparty, and cms)
|
||||
* The parent of the base folder
|
||||
* The grandparent of the base folder
|
||||
* The "_ss_environment.php" file sets a number of "define()".
|
||||
* "conf/ConfigureFromEnv.php" is included from within your "mysite/_config.php". This file has a number of regular
|
||||
* The `_ss_environment.php` file sets a number of "define()".
|
||||
* "conf/ConfigureFromEnv.php" is included from within your `mysite/_config.php`. This file has a number of regular
|
||||
configuration commands that use those defines as their arguments. If you are curious, open up
|
||||
"sapphire/conf/ConfigureFromEnv.php" and see for yourself!
|
||||
`sapphire/conf/ConfigureFromEnv.php` and see for yourself!
|
||||
|
||||
### An Example
|
||||
|
||||
This is my '_ss_environment.php' file. I have it placed in '/var', as each of the sites are in a subfolder of '/var'.
|
||||
This is my `_ss_environment.php` file. I have it placed in `/var`, as each of the sites are in a subfolder of `/var`.
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -98,7 +98,7 @@ This is my '_ss_environment.php' file. I have it placed in '/var', as each of th
|
||||
// This causes errors to be written to the silverstripe.log file in the same directory as this file, so /var.
|
||||
// Before PHP 5.3.0, you'll need to use dirname(__FILE__) instead of __DIR__
|
||||
define('SS_ERROR_LOG', __DIR__ . '/silverstripe.log');
|
||||
|
||||
|
||||
// This is used by sake to know which directory points to which URL
|
||||
global $_FILE_TO_URL_MAPPING;
|
||||
$_FILE_TO_URL_MAPPING['/var/www'] = 'http://simon.geek.nz';
|
||||
$_FILE_TO_URL_MAPPING['/var/www'] = 'http://simon.geek.nz';
|
||||
|
@ -40,7 +40,7 @@ friendlier - much like the 404 page, the error content can be edited within the
|
||||
* Set the error code to 500
|
||||
* Publish the page.
|
||||
|
||||
**HOW IT WORKS: **The publication script for 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
|
||||
content. This means that database access isn't required to provide a 500 error page.
|
||||
|
||||
@ -55,7 +55,7 @@ You can indicate a log file relative to the site root. The named file will have
|
||||
(an encoded file containing backtraces and things) will go to a file of a similar name, but with the suffix ".full"
|
||||
added.
|
||||
|
||||
<mysite>/_config.php:
|
||||
`<mysite>/_config.php`:
|
||||
|
||||
:::php
|
||||
// log errors and warnings
|
||||
@ -66,7 +66,7 @@ added.
|
||||
|
||||
#### Deprecated method (SS 2.3 ?)
|
||||
|
||||
<mysite>/_config.php:
|
||||
`<mysite>/_config.php`:
|
||||
|
||||
:::php
|
||||
Debug::log_errors_to("/my/logfile/path");
|
||||
@ -77,7 +77,7 @@ added.
|
||||
In addition to SilverStripe-integrated logging, it is adviseable to fall back to PHPs native logging functionality. A
|
||||
script might terminate before it reaches the SilverStripe errorhandling, for example in the case of a fatal error.
|
||||
|
||||
<mysite>/_config.php:
|
||||
`<mysite>/_config.php`:
|
||||
|
||||
:::php
|
||||
ini_set("log_errors", "On");
|
||||
@ -88,7 +88,8 @@ script might terminate before it reaches the SilverStripe errorhandling, for exa
|
||||
## Email Logs
|
||||
|
||||
You can send both fatal errors and warnings in your code to a specified email-address.
|
||||
<mysite>/_config.php:
|
||||
|
||||
`<mysite>/_config.php`:
|
||||
|
||||
:::php
|
||||
// log errors and warnings
|
||||
|
@ -5,14 +5,13 @@ CMSMain is part of the CMS. It is the controller for the content editor.
|
||||
## Creating another hierarchical editor by subclassing CMSMain
|
||||
|
||||
Sometimes you'll want to provide an administration interface that is pretty much exactly what CMSMain provides, but it's
|
||||
not appropriate to include your data in with the site content. For example, Hayden developed a hierarchical category
|
||||
administrator on the Guano application.
|
||||
not appropriate to include your data in with the site content.
|
||||
|
||||
Here's how you can do this:
|
||||
Here's how you can do this:
|
||||
|
||||
## Using classes other than SiteTree in the site tree
|
||||
|
||||
It is possible to use to different classes in two separate site trees. In Guano for example, there is the usual site
|
||||
It is possible to use to different classes in two separate site trees. For example, there is the usual site
|
||||
content tree and a category tree. To change that find:
|
||||
|
||||
:::php
|
||||
@ -50,12 +49,12 @@ where url is the relative link to the page (eg 'admin/categories'). You can chan
|
||||
|
||||
## Overloading EditForm
|
||||
|
||||
You may need to overload EditForm if your class does not use the Versioned extension.
|
||||
You may need to overload EditForm if your class does not use the `[api:Versioned]` extension.
|
||||
|
||||
## Overloading SiteTreeAsUL
|
||||
|
||||
The tree hints can sometimes cause problems when reorganising the tree, and the CMSMain::SiteTreeAsUL function uses
|
||||
SiteTree explicitly. Use:
|
||||
`[api:SiteTree]` explicitly. Use:
|
||||
|
||||
:::php
|
||||
public function SiteTreeAsUL() {
|
||||
@ -64,4 +63,3 @@ SiteTree explicitly. Use:
|
||||
|
||||
return $this->getSiteTreeFor( $this->stat('tree_class') );
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@ Form validation is a combination of PHP and JavaScript
|
||||
|
||||
### Introduction
|
||||
|
||||
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
|
||||
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
|
||||
class.
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ Example:
|
||||
|
||||
## Subclassing a form
|
||||
|
||||
It's the reponsibility of your subclass' constructor to call
|
||||
It's the responsibility of your subclass' constructor to call
|
||||
|
||||
:::php
|
||||
parent::__construct()
|
||||
@ -56,6 +56,8 @@ $name must be passed - their values depend on where the form is instantiated.
|
||||
|
||||
|
||||
The real difference, however, is that you can then define your controller methods within the form class itself.
|
||||
|
||||
|
||||
## Form Field Types
|
||||
|
||||
There are many classes extending `[api:FormField]`. Some examples:
|
||||
@ -71,6 +73,7 @@ There are many classes extending `[api:FormField]`. Some examples:
|
||||
|
||||
Full overview at [form-field-types](/reference/form-field-types)
|
||||
|
||||
|
||||
### Using Form Fields
|
||||
|
||||
To get these fields automatically rendered into a form element, all you need to do is create a new instance of the
|
||||
@ -192,8 +195,8 @@ First of all, you need to create your form on it's own class, that way you can d
|
||||
|
||||
}
|
||||
|
||||
`forTemplate()` tells the 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
|
||||
`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.
|
||||
|
||||
*MyForm.ss* should then be placed into your *templates/Includes* directory for your project. Here is an example of
|
||||
basic customisation:
|
||||
@ -232,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
|
||||
template.
|
||||
|
||||
To find more methods, have a look at the 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
|
||||
above.
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
The i18n class (short for "internationalization") in Silverstripe enables you to display templates and PHP code in
|
||||
The i18n class (short for "internationalization") in SilverStripe enables you to display templates and PHP code in
|
||||
different languages based on your global settings and the preferences of your website users. This process is also known
|
||||
as l10n (short for "localization").
|
||||
|
||||
@ -28,8 +28,8 @@ The i18n class is enabled by default.
|
||||
|
||||
### Setting the locale
|
||||
|
||||
To set the locale you just need to call `[api:i18n::set_locale()]` passing, as a parameter, the name of the locale that you want to
|
||||
set.
|
||||
To set the locale you just need to call `[api:i18n::set_locale()]` passing, as a parameter, the name of the locale that you
|
||||
want to set.
|
||||
|
||||
:::php
|
||||
//Example 1: setting the locale
|
||||
@ -53,7 +53,7 @@ To let browsers know which language they're displaying a document in, you can de
|
||||
:::html
|
||||
//'Page.ss' (HTML)
|
||||
<html lang="$ContentLocale">
|
||||
|
||||
|
||||
//'Page.ss' (XHTML)
|
||||
<html lang="$ContentLocale" xml:lang="$ContentLocale" xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
@ -197,9 +197,10 @@ Sprintf enables us to dynamically replace parts of a translated string, e.g. by
|
||||
$title
|
||||
)
|
||||
|
||||
|
||||
<div class="warning" markdown='1'>
|
||||
**Caution**: In templates (*.ss)-files you can only use ONE argument for your sprintf-support, and can't use spaces
|
||||
between parameters.
|
||||
</div>
|
||||
|
||||
:::php
|
||||
// in SS-template ($title must be available in the current template-scope)
|
||||
@ -219,7 +220,9 @@ If you want to run the text collector for just one module you can use the 'modul
|
||||
|
||||
`http://<mysite>/dev/tasks/i18nTextCollectorTask/?module=cms`
|
||||
|
||||
<div class="notice" markdown='1'>
|
||||
**Note**: You'll need to install PHPUnit to run the text collector (see [testing-guide](/topics/testing)).
|
||||
</div>
|
||||
|
||||
## Language tables in PHP
|
||||
|
||||
@ -317,8 +320,9 @@ Example Translation Table (mymodule/javascript/lang/de_DE.js)
|
||||
* No detecting/conversion of character encodings (we rely fully on UTF-8)
|
||||
* Translation of graphics/assets
|
||||
* Usage of gettext (too clumsy, too many requirements)
|
||||
* Displaying multipe languages/encodings on the same page
|
||||
* Displaying multiple languages/encodings on the same page
|
||||
|
||||
## Links
|
||||
|
||||
* [http://www.i18nguy.com/](http://www.i18nguy.com/)
|
||||
* [balbus.tk i18n notes](http://www.balbus.tk/internationalize)
|
||||
|
@ -10,7 +10,7 @@ It is where most documentation should live, and is the natural "second step" aft
|
||||
* [Data Types](data-types): Types that properties on `DataObject` can have (e.g. `Text` or `Date`)
|
||||
* [Datamodel](datamodel): How we use an "Object-relational model" to expose database information in a useful way
|
||||
* [Debugging](debugging): Tracking down errors via logs, URL parameters and profiling
|
||||
* [Directory Structure](directory-structure): Whats core files, where do modules and my own project files go?
|
||||
* [Directory Structure](directory-structure): What are core files, where do modules and my own project files go?
|
||||
* [Emails](email): Configuring and sending emails
|
||||
* [Environment management](environment-management): Sharing configuration details (e.g. database login, passwords) with multiple websites via a `_ss_environment.php` file
|
||||
* [Error Handling](error-handling): Error messages and filesystem logs
|
||||
@ -20,7 +20,7 @@ It is where most documentation should live, and is the natural "second step" aft
|
||||
* [Forms](forms): Create your own form, add fields and create your own form template using the existing `Form` class
|
||||
* [Internationalization (i18n)](i18n): Displaying templates and PHP code in different languages using i18n
|
||||
* [Javascript](javascript): Best practices for developing with JavaScript in SilverStripe
|
||||
* [Module Development](module-development): Creating a module (also known as "extension" or "plugin") to contain reuseable functionality
|
||||
* [Module Development](module-development): Creating a module (also known as "extension" or "plugin") to contain reusable functionality
|
||||
* [Modules](modules): Introduction, how to download and install a module (e.g. with blog or forum functionality)
|
||||
* [Page Types](page-types): What is a "page type" and how do you create one?
|
||||
* [Search](search): Searching for properties in the database as well as other documents
|
||||
@ -29,7 +29,7 @@ It is where most documentation should live, and is the natural "second step" aft
|
||||
* [Testing](testing): Functional and Unit Testing with PHPUnit and SilverStripe's testing framework
|
||||
* [Developing Themes](theme-development): Package templates, images and CSS to a reusable theme
|
||||
* [Translation](translation): Creating content in multiple languages
|
||||
* [Widgets](widgets): Small feature blocks which can be placed on a page by the CMS editor
|
||||
* [Widgets](widgets): Small feature blocks which can be placed on a page by the CMS editor, also outlines how to create and add widgets
|
||||
|
||||
## Feedback
|
||||
|
||||
|
@ -9,9 +9,9 @@ practices can be applied to other libraries as well.
|
||||
|
||||
## File Inclusion
|
||||
|
||||
SilverStripe-driven code should use the `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
|
||||
of requirements can be built up from different places outside of the main controller, for example included `FormField`
|
||||
of requirements can be built up from different places outside of the main controller, for example included `[api:FormField]`
|
||||
instances.
|
||||
|
||||
See [requirements](/reference/requirements) documentation.
|
||||
@ -27,10 +27,12 @@ SilverStripe CMS uses [jQuery UI](http://ui.jquery.com) on top of jQuery.
|
||||
For any custom code developed with jQuery, you have four choices to structure it: Custom jQuery Code, a jQuery Plugin, a
|
||||
jQuery UI Widget, or a `jQuery.entwine` behaviour. We'll detail below where each solution is appropriate.
|
||||
|
||||
<div class="hint" markdown='1'>
|
||||
**Important**: Historically we have been using [PrototypeJS](http://prototypejs.com), which is now discouraged. SilverStripe as a framework doesn't impose a choice of library. It
|
||||
tries to generate meaningful markup which you can alter with other JavaScript libraries as well. Only the CMS itself and
|
||||
certain form widgets require jQuery to function correctly. You can also use jQuery in parallel with other libraries, see
|
||||
[here](http://docs.jquery.com/Using_jQuery_with_Other_Libraries).
|
||||
</div>
|
||||
|
||||
### Custom jQuery Code
|
||||
|
||||
@ -229,7 +231,7 @@ jQuery with a few lines of code. Your jQuery code will normally end up as a ser
|
||||
|
||||
### Don't claim global properties
|
||||
|
||||
Global properties are evil. They are accesible by other scripts, might be overwritten or mis-used. A popular case is the `$` shortcut in different libraries: in PrototypeJS it stands for `document.getElementByID()`, in jQuery for `jQuery()`.
|
||||
Global properties are evil. They are accessible by other scripts, might be overwritten or misused. A popular case is the `$` shortcut in different libraries: in PrototypeJS it stands for `document.getElementByID()`, in jQuery for `jQuery()`.
|
||||
|
||||
:::js
|
||||
// you can't rely on '$' being defined outside of the closure
|
||||
@ -506,7 +508,7 @@ To generate documentation for SilverStripe code, use [JSDoc toolkit](http://code
|
||||
JavaScript, take a look at the [jsdoc cookbook](http://code.google.com/p/jsdoc-toolkit/wiki/CookBook). The `@lends`
|
||||
and `@borrows` properties are particularly useful for documenting jQuery-style code.
|
||||
|
||||
JSDoc-toolkit is a commandline utility, see [usage](http://code.google.com/p/jsdoc-toolkit/wiki/CommandlineOptions).
|
||||
JSDoc-toolkit is a command line utility, see [usage](http://code.google.com/p/jsdoc-toolkit/wiki/CommandlineOptions).
|
||||
|
||||
Example: jQuery.entwine
|
||||
|
||||
@ -619,11 +621,11 @@ Here's an example of hooking the 'PageLoaded' and 'BeforeSave' methods:
|
||||
this.observeMethod('BeforeSave', this.beforeSave);
|
||||
this.pageLoaded(); // call pageload initially too.
|
||||
},
|
||||
|
||||
|
||||
pageLoaded : function() {
|
||||
alert("You loaded a page");
|
||||
},
|
||||
|
||||
|
||||
beforeSave: function() {
|
||||
alert("You clicked save");
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ init() function on your module controller classes:
|
||||
}
|
||||
|
||||
|
||||
This will use your_project/css/forum.css if it exists, otherwise it falls back to using forum/css/forum.css.
|
||||
This will use `<projectname>/css/forum.css` if it exists, otherwise it falls back to using `forum/css/forum.css`.
|
||||
|
||||
## Publication
|
||||
|
||||
@ -46,10 +46,13 @@ adherence to conventions, writing documentation, and releasing updates. See [con
|
||||
## Reference
|
||||
|
||||
**How To:**
|
||||
* [Add a link to your module in the main SilverStripe Admin Menu](/reference/leftandmain)
|
||||
**
|
||||
Useful Links:**
|
||||
|
||||
* [Add a link to your module in the main SilverStripe Admin Menu](/reference/leftandmain)
|
||||
|
||||
**Useful Links:**
|
||||
|
||||
* [Modules](modules)
|
||||
* [Module Release Process](module-release-process)
|
||||
* [Debugging methods](/topics/debugging)
|
||||
* [URL Variable Tools](/reference/urlvariabletools) - Lists a number of “page options” , “rendering tools” or “special
|
||||
URL variables” that you can use to debug your sapphire applications
|
||||
|
@ -86,3 +86,8 @@ Exit the editor and then run
|
||||
|
||||
svn up
|
||||
|
||||
|
||||
**Useful Links:**
|
||||
|
||||
* [Modules](module-developement)
|
||||
* [Module Release Process](module-release-process)
|
@ -17,9 +17,9 @@ and use this template to lay out the basic design elements that don’t change.
|
||||
It contains standard HTML markup, with some differences. We’ll go over these later, but for now, you can see that this
|
||||
file only generates some of the content – it sets up the `<html>` tags, deals with the `<head>` section, creates the
|
||||
first-level navigation, and then closes it all off again. See $Layout? That’s what is doing most of the work when you
|
||||
visit a page. Now take a look at mysite/templates/Layout/Page.ss. This as you can see has a lot more markup in it –
|
||||
visit a page. Now take a look at `mysite/templates/Layout/Page.ss`. This as you can see has a lot more markup in it –
|
||||
it’s what is included into $Layout when the ‘Page’ page type is rendered. Similarly,
|
||||
mysite/templates/Layout/HomePage.ss would be rendered into $Layout when the ‘HomePage’ page type is selected for the
|
||||
`mysite/templates/Layout/HomePage.ss` would be rendered into $Layout when the ‘HomePage’ page type is selected for the
|
||||
current page you’re viewing.
|
||||
|
||||
Why do we sub-class Page for everything? The easiest way to explain this is to use the example of a search form. If we
|
||||
@ -39,7 +39,7 @@ we want to do to the CMS for this page type in here.
|
||||
Page types are created using PHP classes. If you’re not sure about how these work, [click here for a gentler
|
||||
introduction to PHP classes](http://www-128.ibm.com/developerworks/opensource/library/os-phpobj/).
|
||||
|
||||
We put the Page class into a file called Page.php inside mysite/code. We also put Page_Controller in here. Any other
|
||||
We put the Page class into a file called Page.php inside `mysite/code`. We also put Page_Controller in here. Any other
|
||||
classes that are based on Page – for example, the class Page_AnythingElse will also go into Page.php. Likewise, the
|
||||
StaffPage_Image class will go into StaffPage.php.
|
||||
|
||||
@ -78,8 +78,8 @@ See [form](/topics/forms) and [tutorial:2-extending-a-basic-site](/tutorials/2-e
|
||||
|
||||
### removeFieldFromTab()
|
||||
|
||||
Overloading `getCMSFields()` you can call `removeFieldFromTab()` on a `FieldSet` object. For example, if you don't
|
||||
want the MenuTitle field to show on your page, which is inherited from SiteTree.
|
||||
Overloading `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]`.
|
||||
|
||||
:::php
|
||||
class StaffPage extends Page {
|
||||
@ -157,4 +157,5 @@ and [tutorial:3-forms](/tutorials/3-forms).
|
||||
$stageRecord = Versioned::get_one_by_stage('SiteTree', 'Stage', "SiteTree.ID = $pageID");
|
||||
if ($stageRecord) $stageRecord->delete();
|
||||
$liveRecord = Versioned::get_one_by_stage('SiteTree', 'Live', "SiteTree_Live.ID = $pageID");
|
||||
if ($liveRecord) $liveRecord->delete();
|
||||
if ($liveRecord) $liveRecord->delete();
|
||||
|
@ -5,10 +5,12 @@
|
||||
Fulltext search for page content (and other attributes like "Title" or "MetaTags") can be easily added to SilverStripe.
|
||||
See [Tutorial: Site Search](/tutorials/4-site-search) for details.
|
||||
|
||||
## Searching for DataObjects
|
||||
## Searching for DataObject's
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
[SearchContext](/reference/searchcontext) goes into more detail about setting up a default search form for `[api:DataObject]`s.
|
||||
|
||||
## Searching for Documents
|
||||
|
||||
@ -21,6 +23,7 @@ dedicated search service like the [sphinx module](http://silverstripe.org/sphinx
|
||||
* `[api:ModelAdmin]`
|
||||
* `[api:RestfulServer]`
|
||||
* [Tutorial: Site Search](/tutorials/4-site-search)
|
||||
* [SearchContext](/reference/searchcontext)
|
||||
* [genericviews module](http://silverstripe.org/generic-views-module)
|
||||
* [sphinx module](http://silverstripe.org/sphinx-module)
|
||||
* [lucene module](http://silverstripe.org/lucene-module)
|
@ -2,22 +2,21 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
This page details notes on how to ensure that we develop secure SilverStripe applications. See [security](/topics/security) for
|
||||
the Silverstripe-class as a starting-point for most security-related functionality.
|
||||
This page details notes on how to ensure that we develop secure SilverStripe applications. See [security](/topics/security)
|
||||
for the Silverstripe-class as a starting-point for most security-related functionality.
|
||||
|
||||
See our [contributing guidelines](/misc/contributing#reporting-security-issues) on how
|
||||
to report security issues.
|
||||
See our [contributing guidelines](/misc/contributing#reporting-security-issues) on how to report security issues.
|
||||
|
||||
## SQL Injection
|
||||
|
||||
The [coding-conventions](/misc/coding-conventions) help guard against SQL injection attacks but still require developer
|
||||
dilligence: ensure that any variable you insert into a filter / sort / join clause has been escaped.
|
||||
diligence: ensure that any variable you insert into a filter / sort / join clause has been escaped.
|
||||
|
||||
See [http://shiflett.org/articles/sql-injection](http://shiflett.org/articles/sql-injection).
|
||||
|
||||
### Automatic escaping
|
||||
|
||||
Silverstripe automatically runs [addslashes()](http://php.net/addslashes) in DataObject::write() wherever possible. Data
|
||||
SilverStripe automatically runs [addslashes()](http://php.net/addslashes) in DataObject::write() wherever possible. Data
|
||||
is escaped when saving back to the database, not when writing to object-properties.
|
||||
|
||||
* DataObject::get_by_id()
|
||||
@ -29,8 +28,10 @@ is escaped when saving back to the database, not when writing to object-properti
|
||||
* FormField->saveInto()
|
||||
* DBField->saveInto()
|
||||
|
||||
Note: It is NOT good practice to "be sure" and convert the data passed to the functions below manually. This might
|
||||
<div class="warning" markdown='1'>
|
||||
It is NOT good practice to "be sure" and convert the data passed to the functions below manually. This might
|
||||
result in *double escaping* and alters the actually saved data (e.g. by adding slashes to your content).
|
||||
</div>
|
||||
|
||||
### Manual escaping
|
||||
|
||||
@ -106,8 +107,10 @@ XSS (Cross-Site-Scripting). With some basic guidelines, you can ensure your outp
|
||||
displaying a blog post in HTML from a trusted author, or escaping a search parameter from an untrusted visitor before
|
||||
redisplaying it).
|
||||
|
||||
<div class="notice" markdown='1'>
|
||||
Note: SilverStripe templates do not remove tags, please use [strip_tags()](http://php.net/strip_tags) for this purpose
|
||||
or [sanitize](http://htmlpurifier.org/) it correctly.
|
||||
</div>
|
||||
|
||||
See [http://shiflett.org/articles/foiling-cross-site-attacks](http://shiflett.org/articles/foiling-cross-site-attacks)
|
||||
for in-depth information about "Cross-Site-Scripting".
|
||||
@ -253,7 +256,7 @@ Template:
|
||||
Some rules of thumb:
|
||||
|
||||
* 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 querystrings and other such edge cases.
|
||||
* Use *Controller::join_links()* to concatenate URLs. It deals with query strings and other such edge cases.
|
||||
|
||||
|
||||
## Cross-Site Request Forgery (CSRF)
|
||||
@ -292,7 +295,7 @@ Below is an example with different ways you would use this casting technique:
|
||||
function CaseStudies() {
|
||||
|
||||
// cast an ID from URL parameters e.g. (mysite.com/home/action/ID)
|
||||
$anotherID = (int)Director::urlParams['ID'];
|
||||
$anotherID = (int)Director::urlParam['ID'];
|
||||
|
||||
// perform a calculation, the prerequisite being $anotherID must be an integer
|
||||
$calc = $anotherID + (5 - 2) / 2;
|
||||
@ -331,7 +334,6 @@ disallow certain filetypes.
|
||||
|
||||
Example configuration for Apache2:
|
||||
|
||||
|
||||
<VirtualHost *:80>
|
||||
...
|
||||
<LocationMatch assets/>
|
||||
@ -346,7 +348,6 @@ file in the assets directory. This requires PHP to be loaded as an Apache modul
|
||||
|
||||
**/assets/.htaccess**
|
||||
|
||||
|
||||
php_flag engine off
|
||||
Options -ExecCGI -Includes -Indexes
|
||||
|
||||
|
@ -93,7 +93,7 @@ by using the `$Layout` variable so it makes sense to add the .typography style a
|
||||
$Layout
|
||||
</div>
|
||||
|
||||
## Designing reuseable templates
|
||||
## Designing reusable templates
|
||||
|
||||
Although SilverStripe is ultimately flexible in how you create your templates, there's a couple of best practices. These
|
||||
will help you to design templates for modules, and make it easier for other site developers to integrate them into their
|
||||
@ -101,7 +101,7 @@ own base templates.
|
||||
|
||||
* Most of your templates should be Layout templates
|
||||
* Build your templates as a [Theme](/topics/themes) so you can easily re-use and exchange them
|
||||
* Your layout template should include a standard markup structure (`<div id="Layout">`$Layout`</div>`)
|
||||
* Your layout template should include a standard markup structure (`<div id="Layout">$Layout</div>`)
|
||||
* Layout templates only include content that could be completely replaced by another module (e.g. a forum thread). It
|
||||
might be infeasible to do this 100%, but remember that every piece of navigation that needs to appear inside `$Layout`
|
||||
will mean that you have to customise templates when integrating the module.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Functional tests test your controllers. The core of these are the same as unit tests:
|
||||
|
||||
* Create a subclass of 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.
|
||||
* Create methods that start with "test" to create your tests.
|
||||
* Assertions are used to work out if a test passed or failed.
|
||||
@ -15,7 +15,6 @@ URLs. Here is an example from the subsites module:
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
/**
|
||||
|
||||
* Return a session that has a user logged in as an administrator
|
||||
*/
|
||||
function adminLoggedInSession() {
|
||||
@ -25,7 +24,6 @@ URLs. Here is an example from the subsites module:
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Test generation of the view
|
||||
*/
|
||||
function testBasicView() {
|
||||
@ -50,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)**
|
||||
|
||||
Director::test() lets us execute a URL and see what happens. It bypasses HTTP, instead relying on the cleanly
|
||||
encapsulated execution model of Controller.
|
||||
encapsulated execution model of `[api:Controller]`.
|
||||
|
||||
It takes 3 arguments:
|
||||
|
||||
@ -58,7 +56,7 @@ It takes 3 arguments:
|
||||
* $postVars: Post variables to pass to the URL
|
||||
* $sessionObj: A Session object representing the current session.
|
||||
|
||||
And it returns an 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.
|
||||
|
||||
We can use string processing on the body of the response to then see if it fits with our expectations.
|
||||
|
@ -1,7 +1,7 @@
|
||||
# How To Create a Sapphire Test
|
||||
|
||||
A unit test class will test the behaviour of one of your DataObjects. This simple fragment of SiteTreeTest provides us
|
||||
the basics of creating unit tests.
|
||||
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.
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -47,7 +47,7 @@ the basics of creating unit tests.
|
||||
|
||||
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 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
|
||||
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.
|
||||
@ -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.
|
||||
* **$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 but not saved in the database anywhere. objFromFixture() looks the 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.
|
||||
* **$this->assertEquals()** is one of the many assert... functions that PHPUnit provides us. See below for more
|
||||
information.
|
||||
@ -78,7 +78,7 @@ if it starts with "/".
|
||||
|
||||
## The Database YAML file
|
||||
|
||||
The main feature of 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
|
||||
and colons instead of the more verbose XML tags, and because of this much better for developers creating files by hand.
|
||||
|
||||
|
@ -15,8 +15,8 @@ send emails in your SilverStripe application. Here is a simple example of how y
|
||||
$e->send();
|
||||
|
||||
|
||||
Normally, the send() method would send an email using PHP's mail() function. However, if you are running a `SapphireTest` test, then it holds off actually sending the email, and instead lets you assert that an email was sent
|
||||
using this method.
|
||||
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.
|
||||
|
||||
:::php
|
||||
$this->assertEmailSent("someone@example.com", null, "/th.*e$/");
|
||||
@ -25,7 +25,7 @@ using this method.
|
||||
The arguments are `$to`, `$from`, `$subject`, `$body`, and can be take one of the following three forms:
|
||||
|
||||
* A string: match exactly that string
|
||||
* `null`/''false'': match anything
|
||||
* `null/false`: match anything
|
||||
* A PERL regular expression (starting with '/'): match that regular expression
|
||||
|
||||
## How to use it
|
||||
|
@ -217,28 +217,31 @@ Maybe even a nice link saying Website Powered by SilverStripe to show your suppo
|
||||
|
||||
A bunch of resources feel free to use to make your template awesome
|
||||
|
||||
* http://kuler.adobe.com - Kuler is a great color scheming tool
|
||||
* http://blog.html.it/layoutgala/ - 40 super cool CSS layouts for you to use
|
||||
* http://designmeltdown.com - Great gallery of websites. Browse through and get inspired.
|
||||
* http://validator.w3.org/ - Your template must pass 'or get near' validation.
|
||||
* http://famfamfam.com/lab/icons/ - free, beautiful icons.
|
||||
* http://cssremix.com - Another CSS site gallery for inspiration.
|
||||
* http://www.maxdesign.com.au/presentation/process/ - a good process for creating a design
|
||||
* [http://kuler.adobe.com](http://kuler.adobe.com) - Kuler is a great color scheming tool
|
||||
* [http://blog.html.it/layoutgala/](http://blog.html.it/layoutgala/) - 40 super cool CSS layouts for you to use
|
||||
* [http://designmeltdown.com](http://designmeltdown.com) - Great gallery of websites. Browse through and get inspired.
|
||||
* [http://validator.w3.org/](http://validator.w3.org/) - Your template must pass 'or get near' validation.
|
||||
* [http://famfamfam.com/lab/icons/](http://famfamfam.com/lab/icons/) - free, beautiful icons.
|
||||
* [http://cssremix.com](http://cssremix.com) - Another CSS site gallery for inspiration.
|
||||
* [http://www.maxdesign.com.au/presentation/process/](http://www.maxdesign.com.au/presentation/process/) - a good process for creating a design
|
||||
|
||||
## Reference
|
||||
|
||||
### Overriding
|
||||
|
||||
The templating system will search for the appropriate files in the following order:
|
||||
1. mysite (or other name given to site folder)
|
||||
2. themes
|
||||
3. module (eg blog)
|
||||
|
||||
1. mysite (or other name given to site folder)
|
||||
2. themes
|
||||
3. module (eg blog)
|
||||
|
||||
So if, for example, you had a typography.css file for a module in the module folder (eg blog/css/), in the theme module
|
||||
directory (eg themes/blackcandy_blog/css/), and in your site folder (eg mysite/css/), the system would use the file
|
||||
mysite/css/typography.css
|
||||
|
||||
<div class="notice" markdown='1'>
|
||||
Note: This only applies for CSS and template files. PHP files **do not** get overridden!
|
||||
</div>
|
||||
|
||||
### Requirements
|
||||
|
||||
|
@ -24,7 +24,7 @@ See [Developing Themes](theme-development) to get an idea of how themes actually
|
||||
|
||||
## Submitting your theme to SilverStripe
|
||||
|
||||
If you want to submit your theme to the silverstripe directory then check
|
||||
If you want to submit your theme to the SilverStripe directory then check
|
||||
|
||||
* You should ensure your templates are well structured, modular and commented so it's easy for other people to
|
||||
customise them.
|
||||
|
@ -60,15 +60,18 @@ Enabling Translatable through *Object::add_extension()* in your *mysite/_config.
|
||||
}
|
||||
|
||||
|
||||
Make sure to rebuild the database through /dev/build after enabling translatable.
|
||||
Make sure to rebuild the database through /dev/build after enabling `[api:Translatable]`.
|
||||
Use the correct set_default_locale() before building the database
|
||||
for the first time, as this locale will be written on all new records.
|
||||
|
||||
#### Setting the default locale
|
||||
|
||||
Important: If the "default language" of your site is not english (en_US),
|
||||
please ensure to set the appropriate default language for
|
||||
your content before building the database with Translatable enabled:
|
||||
<div class="notice" markdown='1'>
|
||||
**Important:** If the "default language" of your site is not english (en_US), please ensure to set the appropriate default
|
||||
language for your content before building the database with Translatable enabled
|
||||
</div>
|
||||
|
||||
Example:
|
||||
|
||||
:::php
|
||||
Translatable::set_default_locale(<locale>);
|
||||
@ -98,7 +101,7 @@ Getting a translation for an existing instance:
|
||||
|
||||
|
||||
Getting translations through Translatable::set_reading_locale().
|
||||
This is *not* a recommended approach, but sometimes inavoidable (e.g. for Versioned methods).
|
||||
This is *not* a recommended approach, but sometimes unavoidable (e.g. for `[api:Versioned]` methods).
|
||||
|
||||
:::php
|
||||
$origLocale = Translatable::get_reading_locale();
|
||||
@ -117,7 +120,7 @@ Creating a translation:
|
||||
|
||||
### Usage for SiteTree
|
||||
|
||||
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
|
||||
page already having a translation in this language, the extension
|
||||
will recursively create translations up the tree.
|
||||
@ -126,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
|
||||
before showing links to other pages on a website through $_GET['locale'].
|
||||
Pages in different languages can have different publication states
|
||||
through the Versioned extension.
|
||||
through the `[api:Versioned]` extension.
|
||||
|
||||
Note: You can't get Children() for a parent page in a different language
|
||||
through set_reading_locale(). Get the translated parent first.
|
||||
@ -145,13 +148,13 @@ through set_reading_locale(). Get the translated parent first.
|
||||
|
||||
### Translating custom properties
|
||||
|
||||
Keep in mind that the 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 you don't
|
||||
have to explicitly mark any custom properties as being translatable.
|
||||
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
|
||||
you don't have to explicitly mark any custom properties as being translatable.
|
||||
|
||||
The 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 fields
|
||||
in the CMS won't show an original readonly value on a translated record, although they will save correctly. You can
|
||||
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
|
||||
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.
|
||||
|
||||
:::php
|
||||
@ -195,7 +198,7 @@ URL, add a "locale" GET parameter. The German homepage would also be accessible
|
||||
For this to work, please ensure that the translated homepage is a direct translation of the default homepage, and not a
|
||||
new page created through "Create page...".
|
||||
|
||||
### Translationgroups
|
||||
### Translation groups
|
||||
|
||||
Each translation can have an associated "master" object in another language which it is based on,
|
||||
as defined by the "MasterTranslationID" property. This relation is optional, meaning you can
|
||||
@ -223,26 +226,33 @@ SiteTree_translationgroups database table
|
||||
|
||||
### CharacterSets
|
||||
|
||||
Caution: Does not apply any character-set conversion, it is assumed that all content
|
||||
<div class="warning" markdown='1'>
|
||||
**Caution:** Does not apply any character-set conversion, it is assumed that all content
|
||||
is stored and represented in UTF-8 (Unicode). Please make sure your database and
|
||||
HTML-templates adjust to this.
|
||||
</div>
|
||||
|
||||
### "Default"languages
|
||||
### "Default" languages
|
||||
|
||||
Important: If the "default language" of your site is not english (en_US),
|
||||
<div class="warning" markdown='1'>
|
||||
**Important:** If the "default language" of your site is not english (en_US),
|
||||
please ensure to set the appropriate default language for
|
||||
your content before building the database with Translatable enabled:
|
||||
your content before building the database with Translatable enabled
|
||||
</div>
|
||||
|
||||
Example:
|
||||
|
||||
:::php
|
||||
Translatable::set_default_locale(<locale>);
|
||||
|
||||
|
||||
|
||||
### Locales and languagetags
|
||||
### Locales and language tags
|
||||
|
||||
For the Translatable class, a "locale" consists of a language code plus a region code separated by an underscore,
|
||||
for example "de_AT" for German language ("de") in the region Austria ("AT").
|
||||
See http://www.w3.org/International/articles/language-tags/ for a detailed description.
|
||||
See [http://www.w3.org/International/articles/language-tags/](http://www.w3.org/International/articles/language-tags/)
|
||||
for a detailed description.
|
||||
|
||||
Uninstalling/Disabling
|
||||
|
||||
@ -257,9 +267,9 @@ in the database.
|
||||
|
||||
### Switching languages
|
||||
|
||||
A widget now exists to switch between languages, and is [available
|
||||
here](http://www.silverstripe.org/Language-Chooser-Widget/). You can easily make your own switchers with the following
|
||||
basic tools. To stay friendly to caches and search engines, each translation of a page must have a unique URL
|
||||
A widget now exists to switch between languages, and is [available here](http://www.silverstripe.org/Language-Chooser-Widget/).
|
||||
You can easily make your own switchers with the following basic tools. To stay friendly to caches and search engines, each
|
||||
translation of a page must have a unique URL.
|
||||
|
||||
By URL:
|
||||
|
||||
@ -284,7 +294,7 @@ By default, SilverStripe core doesn't provide any switching of languages through
|
||||
SEO-friendly CMS, it contains all this information in the URL. Each page in SilverStripe is aware of its translations
|
||||
through the *getTranslations()* method. We can use this method in our template to build a simple language switcher. It
|
||||
shows all available translations in an unordered list with links to the same page in a different language. The example
|
||||
below can be inserted in any of your templates, for example *themes/blackcandy/templates/Layout/Page.ss*.
|
||||
below can be inserted in any of your templates, for example `themes/blackcandy/templates/Layout/Page.ss`.
|
||||
|
||||
:::php
|
||||
<% if Translations %>
|
||||
@ -306,9 +316,10 @@ just work if your locale value is registered in i18n::get_common_locales().
|
||||
|
||||
### Page-control
|
||||
|
||||
If you want to put static links in your template, which link to a site by their url, normally you can use the <% control
|
||||
Page(page-url) %>. For sites which use Translatable, this is not possible for more than one language, because the url's
|
||||
If you want to put static links in your template, which link to a site by their url, normally you can use the `<% control
|
||||
Page(page-url) %>`. For sites which use Translatable, this is not possible for more than one language, because the url's
|
||||
of different pages differ.
|
||||
|
||||
For this case place the following function in your Page_Controller:
|
||||
|
||||
:::php
|
||||
@ -328,7 +339,8 @@ So, for example if you have a german page "Kontakt", which should be translated
|
||||
|
||||
<% control PageByLang(Kontakt,de_DE) %>
|
||||
|
||||
The control displays the link in the right language, depending on the current locale.\\
|
||||
The control displays the link in the right language, depending on the current locale.
|
||||
|
||||
Example:
|
||||
|
||||
<% control PageByLang(Kontakt,de_DE) %>
|
||||
@ -349,11 +361,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,
|
||||
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 (i18n), but edit pages in different languages (Translatable).)
|
||||
want the CMS to be in English (`[api:i18n]`), but edit pages in different languages (`[api:Translatable]`).)
|
||||
|
||||
### Migrating from 2.1 datamodel
|
||||
|
||||
The datamodel of 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
|
||||
mailinglist](http://groups.google.com/group/silverstripe-dev/browse_thread/thread/91e26e1f78d3c1b4/bd276dd5bbc56283?lnk=gst&q=translatable#bd276dd5bbc56283).
|
||||
|
||||
@ -362,8 +374,8 @@ To migrate a database that was built with SilverStripe 2.1.x or 2.2.x, follow th
|
||||
* Upgrade your SilverStripe installation to at least 2.3.2 (see [upgrading](/installation/upgrading))
|
||||
* Backup your database content
|
||||
* Login as an administrator
|
||||
* Run http://mysite.com/dev/build
|
||||
* Run http://mysite.com/dev/tasks/MigrateTranslatableTask
|
||||
* Run `http://mysite.com/dev/build`
|
||||
* Run `http://mysite.com/dev/tasks/MigrateTranslatableTask`
|
||||
|
||||
Please see the `[api:MigrateTranslatableTask]` for
|
||||
limitations of this migration task - not all your data will be preserved.
|
||||
@ -371,8 +383,8 @@ limitations of this migration task - not all your data will be preserved.
|
||||
|
||||
### Setting the i18n locale
|
||||
|
||||
You can set the i18n locale value which is used to format dates, currencies and other regionally different values to the
|
||||
same as your current page locale.
|
||||
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.
|
||||
|
||||
:::php
|
||||
class Page_Controller extends ContentController {
|
||||
@ -388,8 +400,8 @@ same as your current page locale.
|
||||
|
||||
### Adding a new locale
|
||||
|
||||
The 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:
|
||||
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`:
|
||||
|
||||
:::php
|
||||
i18n::$common_locales['de_AT'] = 'Deutsch (Oestereich)';
|
||||
@ -403,4 +415,4 @@ This should e.g. enable you to use `$Locale.Nice` in template code.
|
||||
* [i18n](i18n): Developer-level documentation of Silverstripe's i18n capabilities
|
||||
* `[api:Translatable]`: DataObject-interface powering the website-content translations
|
||||
* ["Translatable ModelAdmin" module](http://silverstripe.org/translatablemodeladmin-module/): An extension which allows
|
||||
translations of DataObjects inside `[api:ModelAdmin]`
|
||||
translations of `[api:DataObject]`s inside `[api:ModelAdmin]`
|
||||
|
@ -2,39 +2,46 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
Widgets are small pieces of functionality such as showing the latest Comments or Flickr Photos. They normally display on
|
||||
the sidebar of your website. To check out a what a Widget can do watch the video http://silverstripe.org/widgets and try
|
||||
out the demo site http://silverstripe.com/assets/screencasts/SilverStripe-Blog-DragDrop-Widgets.swf
|
||||
[Widgets](http://silverstripe.org/widgets) are small pieces of functionality such as showing the latest Comments or Flickr Photos. They normally display on
|
||||
the sidebar of your website. To check out a what a [Widget](http://silverstripe.org/widgets) can do watch the
|
||||
[Widget video](http://silverstripe.com/assets/screencasts/SilverStripe-Blog-DragDrop-Widgets.swf) and try out the
|
||||
[demo site](http://demo.silverstripe.org/)
|
||||
|
||||
|
||||
## How to Use A Widget
|
||||
|
||||
|
||||
### Downloading and Contributing Widgets
|
||||
|
||||
* To download widgets visit [Widgets section](http://silverstripe.org/widgets)
|
||||
* Upload widgets you want to share to
|
||||
[http://silverstripe.org/widgets/manage/add](http://silverstripe.org/widgets/manage/add). Make sure you read the
|
||||
packaging instructions at the bottom of the page about how to make your widget package.
|
||||
|
||||
|
||||
### Installing a widget
|
||||
|
||||
By following the "Packaging" rules below, widgets are easily installed.
|
||||
|
||||
* Download the file and unzip to the main folder of your SilverStripe website, e.g. to "/widget_twitter/". The folder
|
||||
* Install the [blog module](http://www.silverstripe.org/blog-module/) (by default only the Blog has widgets enabled)
|
||||
* Download the file and unzip to the main folder of your SilverStripe website, e.g. to `/widget_<widget-name>/`. The folder
|
||||
will contain a few files, which generally won't need editing or reading.
|
||||
* Run dev/build
|
||||
* Login to the CMS and go to the 'Blog' page. Choose the "widgets" tab and drag n drop the new widget to activate it.
|
||||
* Your blog will now have the widget shown.
|
||||
* Run `http://my-website.com/dev/build`
|
||||
* Login to the CMS and go to the 'Blog' page. Choose the "widgets" tab and drag n drop the new widget to activate it.
|
||||
* Your blog will now have the widget shown
|
||||
|
||||
### Adding widgets to other pages
|
||||
|
||||
As of 2.2.1 this is this is a way to add widgets to other pages (by default only the Blog has widgets enabled). In the
|
||||
future releases we will hopefully make widgets part of SiteTree therefore available on every page. In the mean time you
|
||||
have to do a couple things to get a Widget to work on a page.
|
||||
<div class="notice" markdown='1'>
|
||||
As of version 2.2.1 there is a way to add widgets to other pages. In future releases we will hopefully make widgets part
|
||||
of SiteTree therefore available on every page.
|
||||
</div>
|
||||
|
||||
You have to do a couple things to get a Widget to work on a page.
|
||||
|
||||
First step is to add an WidgetArea to the Database to store the widget details. Then you have to edit the CMS to add a
|
||||
Widget Form to manage the widgets. An example of this is below
|
||||
|
||||
** mysite/code/Page.php **
|
||||
**mysite/code/Page.php**
|
||||
|
||||
:::php
|
||||
class Page extends SiteTree {
|
||||
@ -53,18 +60,16 @@ Widget Form to manage the widgets. An example of this is below
|
||||
}
|
||||
|
||||
|
||||
Then in your Template you need to call $SideBar whereever you want to render the widget
|
||||
Then in your Template you need to call $SideBar wherever you want to render the widget
|
||||
|
||||
Eg for blackcandy I put this above the closing `</div>`
|
||||
For example: using the blackcandy theme I put this piece of code above the closing `</div>`
|
||||
|
||||
** themes/myThemeName/templates/Includes/Sidebar.ss **
|
||||
**themes/blackcandy/templates/Includes/Sidebar.ss**
|
||||
|
||||
:::ss
|
||||
$Sidebar
|
||||
|
||||
|
||||
|
||||
|
||||
## Writing your own widgets
|
||||
|
||||
To create a Widget you need at least three files - a php file containing the class, a template file of the same name and
|
||||
@ -180,7 +185,7 @@ To render the widget, simply include $SilverStripeFeed in your template:
|
||||
|
||||
|
||||
As directed in the definition of SilverStripeFeed(), the Widget will be rendered through the WidgetHolder template. This
|
||||
is pre-defined at /sapphire/templates/WidgetHolder.ss and simply consists of:
|
||||
is pre-defined at `/sapphire/templates/WidgetHolder.ss` and simply consists of:
|
||||
|
||||
:::ss
|
||||
<div class="WidgetHolder">
|
||||
@ -190,14 +195,14 @@ is pre-defined at /sapphire/templates/WidgetHolder.ss and simply consists of:
|
||||
|
||||
|
||||
You can override the WidgetHolder.ss and Widget.ss templates in your theme too by adding WidgetHolder and Widget
|
||||
templates to ** themes/myThemeName/templates/Includes/ **
|
||||
templates to `themes/myThemeName/templates/Includes/`
|
||||
|
||||
### Changing the title of your widget
|
||||
|
||||
To change the title of your widget, you need to override the Title() method. By default, this simply returns the $title
|
||||
variable. For example, to set your widgets title to 'Hello World!', you could use:
|
||||
|
||||
** widgets_yourWidget/YourWidgetWidget.php **
|
||||
**widgets_yourWidget/YourWidgetWidget.php**
|
||||
|
||||
:::php
|
||||
function Title() {
|
||||
@ -221,13 +226,13 @@ This returns the value inputted in the CMS, if it's set or what is in the $title
|
||||
|
||||
### Forms within Widgets
|
||||
|
||||
*Requires SilverStripe 2.4 or newer*
|
||||
**Requires SilverStripe 2.4 or newer**
|
||||
|
||||
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
|
||||
`[api:WidgetArea]` rendering in your *Page.ss* template.
|
||||
|
||||
*mysite/code/MyWidget.php*
|
||||
**mysite/code/MyWidget.php**
|
||||
|
||||
:::php
|
||||
class MyWidget extends Widget {
|
||||
@ -258,26 +263,27 @@ sure that your controller follows the usual naming conventions, and it will be a
|
||||
|
||||
To output this form, modify your widget template.
|
||||
|
||||
*mysite/templates/MyWidget.ss*
|
||||
**mysite/templates/MyWidget.ss**
|
||||
|
||||
:::ss
|
||||
$Content
|
||||
$MyFormName
|
||||
|
||||
|
||||
Note: The necessary controller actions are only present in subclasses of `[api:Page_Controller]`. To use
|
||||
<div class="notice" markdown='1'>
|
||||
**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
|
||||
*ContentController::$url_handlers*.
|
||||
</div>
|
||||
|
||||
See an [alternative recipe for SilverStripe 2.3 or earlier](http://doc.silverstripe.org/old/recipes/widget-forms-2.3).
|
||||
|
||||
## But what if I have widgets on my blog currently??
|
||||
## But what if I have widgets on my blog currently??
|
||||
|
||||
If you currently have a blog installed, the widget fields are going to double up on those pages (as the blog extends the
|
||||
Page class). One way to fix this is to comment out line 30 in BlogHolder.php and remove the DB entry by running a
|
||||
/db/build.
|
||||
`http://www.mysite.com/db/build`.
|
||||
|
||||
** blog/code/BlogHolder.php **
|
||||
**blog/code/BlogHolder.php**
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -304,7 +310,7 @@ Then you can use the Widget area you defined on Page.php
|
||||
### Packaging
|
||||
|
||||
For a widget to be put in our official widget database they must follow this convention - If the name of your widget was
|
||||
"TwitterWidget" then:
|
||||
"YourName" then:
|
||||
|
||||
#### File Structure for your widget
|
||||
|
||||
@ -323,19 +329,21 @@ would understand, then make it configurable in the _config.php file.
|
||||
|
||||
This way, the CMS remains an application designed for content authors, and not developers.
|
||||
|
||||
** widget_name/_config.php **
|
||||
*widget_name/_config.php*
|
||||
|
||||
:::php
|
||||
<?php /* */ ?>
|
||||
|
||||
|
||||
** Example Widget Structure **
|
||||
**Example Widget Structure**
|
||||
|
||||
![](_images/widget_demo.gif)
|
||||
|
||||
|
||||
#### How to make the Package
|
||||
|
||||
* Make a tar.gz file called widgets_flickr-0.1.tar.gz (where 0.1 is the version number).
|
||||
* Ensure when you "unzip" the compressed file it has everything the "widgets_flickr" folder with everything inside
|
||||
* Make a tar.gz file called widgets_YourName-0.1.tar.gz (where 0.1 is the version number).
|
||||
* Ensure when you "unzip" the compressed file it has everything the "widgets_YourName" folder with everything inside
|
||||
it.
|
||||
* If made official, it will be given these locations at silverstripe.com:
|
||||
* SVN location: http://svn.silverstripe.com/open/modules/widgets/flickr/trunk
|
||||
|
@ -627,7 +627,7 @@ a new *StaffHolder* called "Staff" in the "About Us" section, and create some *S
|
||||
|
||||
### Creating the staff section templates
|
||||
|
||||
The staff section templates aren't too difficult to create, thanks to the utility methods provided by the *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**
|
||||
|
||||
@ -650,7 +650,7 @@ The staff section templates aren't too difficult to create, thanks to the utilit
|
||||
</div>
|
||||
|
||||
|
||||
This template is very similar to the *ArticleHolder* template. The *FirstSentence* method of the `[api:Text]` 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
|
||||
resize the image every time the page is viewed.
|
||||
|
||||
|
@ -47,7 +47,7 @@ instructions below as well.
|
||||
|
||||
If you are using SilverStripe 2.2 or earlier then you need to define your own code. The first step in implementing
|
||||
search on your site is to create a form for the user to type their query. Create a function named *SearchForm* on the
|
||||
*Page_Controller* class (//mysite/code/Page.php//).
|
||||
*Page_Controller* class (/mysite/code/Page.php).
|
||||
|
||||
:::php
|
||||
class Page_Controller extends ContentController {
|
||||
@ -66,6 +66,69 @@ search on your site is to create a form for the user to type their query. Create
|
||||
}
|
||||
}
|
||||
|
||||
### Custom CSS code
|
||||
|
||||
Add the following css code to the *themes/tutorial/css/layout.css* file. This will style the header form and search
|
||||
results page.
|
||||
|
||||
:::css
|
||||
#Header form {
|
||||
float:right;
|
||||
width:160px;
|
||||
margin:25px 25px 0px 25px;
|
||||
}
|
||||
#Header form * {
|
||||
display:inline !important;
|
||||
}
|
||||
#Header form div {
|
||||
}
|
||||
#Header form input.text {
|
||||
width:110px;
|
||||
color:#000;
|
||||
background:#f0f0f0;
|
||||
border:1px solid #aaa;
|
||||
padding:3px;
|
||||
}
|
||||
#Header form input.action {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.searchResults h2 {
|
||||
font-size:2.2em;
|
||||
font-weight:normal;
|
||||
color:#0083C8;
|
||||
margin-bottom:15px;
|
||||
}
|
||||
.searchResults p.searchQuery {
|
||||
color:#333;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.searchResults ul#SearchResults li {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
ul#SearchResults p {
|
||||
font-size:1.1em;
|
||||
font-weight:normal;
|
||||
line-height:2em;
|
||||
color:#333;
|
||||
}
|
||||
ul#SearchResults a.searchResultHeader {
|
||||
font-size:1.3em;
|
||||
font-weight:bold;
|
||||
color:#0083C8;
|
||||
text-decoration:none;
|
||||
margin:20px 0 8px 0;
|
||||
padding-left:20px;
|
||||
background:url(../images/treeicons/search-file.gif) no-repeat left center;
|
||||
}
|
||||
ul#SearchResults a {
|
||||
text-decoration:none;
|
||||
color:#0083C8;
|
||||
}
|
||||
ul#SearchResults a:hover {
|
||||
border-bottom:1px dotted #0083C8;
|
||||
}
|
||||
|
||||
## Adding the search form
|
||||
|
||||
|
@ -7,6 +7,11 @@ to the *$db* array and how to add an image using the *$has_one* array and so cre
|
||||
the *Image* table by storing the id of the respective *Image* in the first table. This tutorial explores all this
|
||||
relations between [DataObjects](/topics/datamodel#relations) and the way to manage them easily.
|
||||
|
||||
<div class="notice" markdown='1'>
|
||||
I'm using the default tutorial theme in the following examples so the templates may vary or you may need to change
|
||||
the template code in this example to fit your theme
|
||||
</div>
|
||||
|
||||
## What are we working towards?
|
||||
|
||||
To simulate these relations between objects, we are going to simulate the management via the CMS of the **[Google Summer
|
||||
@ -79,9 +84,11 @@ The first step is to create the student and project objects.
|
||||
|
||||
function getCMSFields_forPopup() {
|
||||
$fields = new FieldSet();
|
||||
|
||||
$fields->push( new TextField( 'FirstName', 'First Name' ) );
|
||||
$fields->push( new TextField( 'Lastname' ) );
|
||||
$fields->push( new TextField( 'Nationality' ) );
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
@ -262,6 +269,8 @@ The first step is to create the mentor object and set the relation with the *Stu
|
||||
}
|
||||
class Mentor_Controller extends Page_Controller {}
|
||||
|
||||
*tutorial/code/Student.php*
|
||||
|
||||
:::php
|
||||
class Student extends DataObject {
|
||||
|
||||
@ -279,6 +288,8 @@ respective *Mentor* in the *Student* table.
|
||||
|
||||
The second step is to add the table in the method *getCMSFields* which will allow you to manage the *has_many* relation.
|
||||
|
||||
*tutorial/code/Mentor.php*
|
||||
|
||||
:::php
|
||||
class Mentor extends Page {
|
||||
|
||||
@ -308,6 +319,7 @@ The second step is to add the table in the method *getCMSFields* which will allo
|
||||
}
|
||||
|
||||
}
|
||||
class Mentor_Controller extends Page_Controller {}
|
||||
|
||||
To know more about the parameters of the *HasManyComplexTableField* constructor, [check](#project_-_student_relation)
|
||||
those of the *HasOneComplexTableField* constructor.
|
||||
@ -356,6 +368,8 @@ The first step is to create the module object and set the relation with the *Pro
|
||||
*tutorial/code/Module.php*
|
||||
|
||||
:::php
|
||||
<?php
|
||||
|
||||
class Module extends DataObject {
|
||||
|
||||
static $db = array(
|
||||
@ -374,6 +388,8 @@ The first step is to create the module object and set the relation with the *Pro
|
||||
|
||||
}
|
||||
|
||||
*tutorial/code/Project.php*
|
||||
|
||||
:::php
|
||||
class Project extends Page {
|
||||
|
||||
@ -424,9 +440,10 @@ To know more about the parameters of the *ManyManyComplexTableField* constructor
|
||||
[check](#project_-_student_relation) those of the *HasOneComplexTableField*
|
||||
constructor.
|
||||
|
||||
Don't forget to rebuild the database using
|
||||
[http://localhost:3000/db/build?flush=1](http://localhost:3000/db/build?flush=1) before you proceed to the next part of
|
||||
this tutorial.
|
||||
<div class="tip" markdown='1'>
|
||||
Don't forget to rebuild the database using *dev/build?flush=1* before you
|
||||
proceed to the next part of this tutorial.
|
||||
</div>
|
||||
|
||||
Select now one of the *Project* page, go in the tab panel *Modules* and add all the modules listed
|
||||
[above](#what-are-we-working-towards) by clicking on the link **Add A
|
||||
@ -459,7 +476,7 @@ We will see in this section how to display all these relations but also how to c
|
||||
|
||||
For every kind of *Page* or *DataObject*, you can access to their relations thanks to the **control** loop.
|
||||
|
||||
**__1. GSOC Projects__**
|
||||
**1. GSOC Projects**
|
||||
|
||||
Let's start with the *ProjectsHolder* page created before. For this template, we are will display the same table than
|
||||
[above](#what-are-we-working-towards).
|
||||
@ -469,94 +486,79 @@ Let's start with the *ProjectsHolder* page created before. For this template, we
|
||||
*tutorial/templates/Layout/ProjectsHolder.ss*
|
||||
|
||||
:::ss
|
||||
<div class="typography">
|
||||
<% if Menu(2) %>
|
||||
<% include SideBar %>
|
||||
<div id="Content">
|
||||
<% end_if %>
|
||||
|
||||
<% if Level(2) %>
|
||||
<% include Menu2 %>
|
||||
|
||||
<div id="Content" class="typography">
|
||||
<% if Level(2) %>
|
||||
<% include BreadCrumbs %>
|
||||
<% end_if %>
|
||||
|
||||
<h2>$Title</h2>
|
||||
|
||||
$Content
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
|
||||
$Content
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Project</th>
|
||||
<th>Student</th>
|
||||
<th>Mentor</th>
|
||||
<th>Modules</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% control Children %>
|
||||
<tr>
|
||||
<th>Project</th>
|
||||
<th>Student</th>
|
||||
<th>Mentor</th>
|
||||
<th>Modules</th>
|
||||
<td>$Title</td>
|
||||
<td>
|
||||
<% if MyStudent %>
|
||||
<% control MyStudent %>
|
||||
$FirstName $Lastname
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Student
|
||||
<% end_if %>
|
||||
</td>
|
||||
<td>
|
||||
<% if MyStudent %>
|
||||
<% control MyStudent %>
|
||||
<% if MyMentor %>
|
||||
<% control MyMentor %>
|
||||
$FirstName $Lastname
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Mentor
|
||||
<% end_if %>
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Mentor
|
||||
<% end_if %>
|
||||
</td>
|
||||
<td>
|
||||
<% if Modules %>
|
||||
<% control Modules %>
|
||||
$Name
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Modules
|
||||
<% end_if %>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% control Children %>
|
||||
<tr>
|
||||
<td>$Title</td>
|
||||
<td>
|
||||
<% if MyStudent %>
|
||||
<% control MyStudent %>
|
||||
$FirstName $Lastname
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Student
|
||||
<% end_if %>
|
||||
</td>
|
||||
<td>
|
||||
<% if MyStudent %>
|
||||
<% control MyStudent %>
|
||||
<% if MyMentor %>
|
||||
<% control MyMentor %>
|
||||
$FirstName $Lastname
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Mentor
|
||||
<% end_if %>
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Mentor
|
||||
<% end_if %>
|
||||
</td>
|
||||
<td>
|
||||
<% if Modules %>
|
||||
<% control Modules %>
|
||||
$Name
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Modules
|
||||
<% end_if %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end_control %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
$Form
|
||||
$PageComments
|
||||
|
||||
<% if Menu(2) %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
<% end_control %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
$Form
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
*tutorial/templates/Includes/SideBar.ss*
|
||||
You might want to move the include above the typography div in your layouts to get rid of the bullets.
|
||||
|
||||
:::ss
|
||||
<% if Menu(2) %>
|
||||
<ul id="Menu2">
|
||||
<% control Menu(2) %>
|
||||
<li class="$LinkingMode"><a href="$Link" title="Go to the "{$Title}" page">$MenuTitle</a></li>
|
||||
<% end_control %>
|
||||
</ul>
|
||||
<% end_if %>
|
||||
<div class="notice" markdown='1'>
|
||||
If you are using the blackcandy template: You might want to move the `<% include Sidebar %>`
|
||||
(tutorial/templates/Includes/SideBar.ss) include in the *tutorial/templates/Layout/Page.ss* template above
|
||||
the typography div to get rid of the bullets
|
||||
</div>
|
||||
|
||||
|
||||
**__2. Project__**
|
||||
**2. Project**
|
||||
|
||||
We know now how to easily access and show [relations](../topics/datamodel#relations) between *DataObject* in a template.
|
||||
|
||||
@ -567,62 +569,51 @@ We can now do the same for every *Project* page by creating its own template.
|
||||
*tutorial/templates/Layout/Project.ss*
|
||||
|
||||
:::ss
|
||||
<div class="typography">
|
||||
<% if Menu(2) %>
|
||||
<% include SideBar %>
|
||||
<div id="Content">
|
||||
<% end_if %>
|
||||
|
||||
<% if Level(2) %>
|
||||
<% include Menu2 %>
|
||||
|
||||
<div id="Content" class="typography">
|
||||
<% if Level(2) %>
|
||||
<% include BreadCrumbs %>
|
||||
<% end_if %>
|
||||
|
||||
<h2>$Title</h2>
|
||||
|
||||
$Content
|
||||
|
||||
<h3>Student</h3>
|
||||
|
||||
<% if MyStudent %>
|
||||
<% control MyStudent %>
|
||||
<p>First Name: <strong>$FirstName</strong></p>
|
||||
<p>Lastname: <strong>$Lastname</strong></p>
|
||||
<p>Nationality: <strong>$Nationality</strong></p>
|
||||
|
||||
<h3>Mentor</h3>
|
||||
|
||||
<% if MyMentor %>
|
||||
<% control MyMentor %>
|
||||
<p>First Name: <strong>$FirstName</strong></p>
|
||||
<p>Lastname: <strong>$Lastname</strong></p>
|
||||
<p>Nationality: <strong>$Nationality</strong></p>
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
<p>This student doesn't have any mentor.</p>
|
||||
<% end_if %>
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
<p>There is no any student working on this project.</p>
|
||||
<% end_if %>
|
||||
|
||||
<h3>Modules</h3>
|
||||
|
||||
<% if Modules %>
|
||||
<ul>
|
||||
<% control Modules %>
|
||||
<li>$Name</li>
|
||||
|
||||
$Content
|
||||
|
||||
<% if MyStudent %>
|
||||
<% control MyStudent %>
|
||||
<p>First Name: <strong>$FirstName</strong></p>
|
||||
<p>Lastname: <strong>$Lastname</strong></p>
|
||||
<p>Nationality: <strong>$Nationality</strong></p>
|
||||
|
||||
<h3>Mentor</h3>
|
||||
|
||||
<% if MyMentor %>
|
||||
<% control MyMentor %>
|
||||
<p>First Name: <strong>$FirstName</strong></p>
|
||||
<p>Lastname: <strong>$Lastname</strong></p>
|
||||
<p>Nationality: <strong>$Nationality</strong></p>
|
||||
<% end_control %>
|
||||
</ul>
|
||||
<% else %>
|
||||
<p>This project has not used any modules.</p>
|
||||
<% end_if %>
|
||||
|
||||
$Form
|
||||
$PageComments
|
||||
|
||||
<% if Menu(2) %>
|
||||
</div>
|
||||
<% else %>
|
||||
<p>This student doesn't have any mentor.</p>
|
||||
<% end_if %>
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
<p>There is no any student working on this project.</p>
|
||||
<% end_if %>
|
||||
|
||||
<h3>Modules</h3>
|
||||
|
||||
<% if Modules %>
|
||||
<ul>
|
||||
<% control Modules %>
|
||||
<li>$Name</li>
|
||||
<% end_control %>
|
||||
</ul>
|
||||
<% else %>
|
||||
<p>This project has not used any modules.</p>
|
||||
<% end_if %>
|
||||
|
||||
$Form
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -647,37 +638,39 @@ from templates either within a control block or dot notation.
|
||||
*tutorial/code/Student.php, tutorial/code/Mentor.php*
|
||||
|
||||
:::php
|
||||
function PersonalInfo() {
|
||||
$template = 'GSOCPerson';
|
||||
return $this->renderWith( $template );
|
||||
}
|
||||
function PersonalInfo() {
|
||||
$template = 'GSOCPerson';
|
||||
return $this->renderWith( $template );
|
||||
}
|
||||
|
||||
|
||||
We can now modify the *Project* template.
|
||||
We can now modify the *Project.ss* template.
|
||||
|
||||
:::ss
|
||||
|
||||
...
|
||||
...
|
||||
|
||||
<% if MyStudent %>
|
||||
$MyStudent.PersonalInfo
|
||||
<% if MyStudent %>
|
||||
$MyStudent.PersonalInfo
|
||||
|
||||
<h3>Mentor</h3>
|
||||
<h3>Mentor</h3>
|
||||
|
||||
<% control MyStudent %>
|
||||
<% if MyMentor %>
|
||||
$MyMentor.PersonalInfo
|
||||
<% else %>
|
||||
<p>This student doesn't have any mentor.</p>
|
||||
<% end_if %>
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
<p>There is no any student working on this project.</p>
|
||||
<% end_if %>
|
||||
|
||||
...
|
||||
<% control MyStudent %>
|
||||
<% if MyMentor %>
|
||||
$MyMentor.PersonalInfo
|
||||
<% else %>
|
||||
<p>This student doesn't have any mentor.</p>
|
||||
<% end_if %>
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
<p>There is no any student working on this project.</p>
|
||||
<% end_if %>
|
||||
|
||||
...
|
||||
|
||||
<div class="notice" markdown='1'>
|
||||
Remember to add `?flush=1` to the url when refreshing the project page or otherwise you will get a template error
|
||||
</div>
|
||||
|
||||
In the *Project* template, it has been really easy to display the **1-to-1** relation with a *Student* object just by
|
||||
calling the variable **$MyStudent**. This has been made possible thanks to the code below present in the *Project*
|
||||
@ -692,7 +685,7 @@ class.
|
||||
However, in the *Student* class, there is no any code relating to the **1-to-1** relation with a *Project* *Page*. So
|
||||
how to access it from a *Student* *DataObject* ?
|
||||
|
||||
**__3. Mentor__**
|
||||
**3. Mentor**
|
||||
|
||||
In this template, we are gonna try to access the *Project* details from a *Student* *DataObject*.
|
||||
|
||||
@ -707,11 +700,11 @@ it *MyProject* for instance.
|
||||
:::php
|
||||
class Student extends DataObject {
|
||||
|
||||
...
|
||||
...
|
||||
|
||||
function MyProject() {
|
||||
return DataObject::get( 'Project', "`MyStudentID` = '{$this->ID}'" );
|
||||
}
|
||||
function MyProject() {
|
||||
return DataObject::get( 'Project', "`MyStudentID` = '{$this->ID}'" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -722,65 +715,51 @@ That's how we can use this function in the *Mentor* template.
|
||||
*tutorial/templates/Layout/Mentor.ss*
|
||||
|
||||
:::ss
|
||||
<div class="typography">
|
||||
<% if Menu(2) %>
|
||||
<% include SideBar %>
|
||||
<div id="Content">
|
||||
<% end_if %>
|
||||
|
||||
<% if Level(2) %>
|
||||
<% include BreadCrumbs %>
|
||||
<% end_if %>
|
||||
|
||||
<h2>$Title</h2>
|
||||
|
||||
$Content
|
||||
|
||||
<h3>Personal Details</h3>
|
||||
|
||||
<p>First Name: <strong>$FirstName</strong></p>
|
||||
<p>Lastname: <strong>$Lastname</strong></p>
|
||||
<p>Nationality: <strong>$Nationality</strong></p>
|
||||
|
||||
<h3>Students</h3>
|
||||
|
||||
<% if Students %>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Student</th>
|
||||
<th>Project</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% control Students %>
|
||||
<tr>
|
||||
<td>$FirstName $Lastname</td>
|
||||
<td>
|
||||
<% if MyProject %>
|
||||
<% control MyProject %>
|
||||
$Title
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Project
|
||||
<% end_if %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end_control %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% else %>
|
||||
<p>There is no any student working with this mentor.</p>
|
||||
<% end_if %>
|
||||
|
||||
$Form
|
||||
$PageComments
|
||||
|
||||
<% if Menu(2) %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
</div>
|
||||
<% include Menu2 %>
|
||||
|
||||
<div id="Content" class="typography">
|
||||
<% include Breadcrumbs %>
|
||||
$Content
|
||||
|
||||
<h3>Personal Details</h3>
|
||||
|
||||
<p>First Name: <strong>$FirstName</strong></p>
|
||||
<p>Lastname: <strong>$Lastname</strong></p>
|
||||
<p>Nationality: <strong>$Nationality</strong></p>
|
||||
|
||||
<h3>Students</h3>
|
||||
|
||||
<% if Students %>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Student</th>
|
||||
<th>Project</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% control Students %>
|
||||
<tr>
|
||||
<td>$FirstName $Lastname</td>
|
||||
<td>
|
||||
<% if MyProject %>
|
||||
<% control MyProject %>
|
||||
$Title
|
||||
<% end_control %>
|
||||
<% else %>
|
||||
No Project
|
||||
<% end_if %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end_control %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% else %>
|
||||
<p>There is no any student working with this mentor.</p>
|
||||
<% end_if %>
|
||||
|
||||
$Form
|
||||
</div>
|
||||
|
||||
|
||||
## Summary
|
||||
@ -791,4 +770,6 @@ CMS and how to display them on the website.
|
||||
|
||||
## Download the code
|
||||
|
||||
You can download all the [complete code](http://doc.silverstripe.org/src/github/master/sapphire/docs/en/tutorials/_images/tutorial5-completecode.zip) of this tutorial.
|
||||
Download all the [code](http://doc.silverstripe.org/src/github/master/sapphire/docs/en/tutorials/_images/tutorial5-completecode.zip) for this tutorial.
|
||||
|
||||
You can also download the [code](http://doc.silverstripe.org/src/github/master/sapphire/docs/en/tutorials/_images/tutorial5-completecode-blackcandy.zip) for use in the blackcandy template.
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 50 KiB |