1
0
mirror of https://github.com/silverstripe/silverstripe-framework synced 2024-10-22 14:05:37 +02:00

NEW: Update docs to be compliant with Gatsby site ()

* First cut

* Temporarily disable composer.json for netlify build

* POC

* New recursive directory query, various refinements

* Fix flexbox

* new styled components plugin

* Apply frontmatter delimiters

* Mobile styles, animation

* Search

* Redesign, clean up

* Nuke the cache, try again

* fix file casing

* Remove production env file

* ID headers

* Move app to new repo

* Add frontmatter universally

* Hide children changelogs

* Add how to title

* New callout tags

* Revert inline code block change

* Replace note callouts

* Fix icons

* Repalce images

* Fix icon

* Fix image links

* Use proper SQL icon
This commit is contained in:
Aaron Carlino 2019-11-18 17:58:33 +13:00 committed by GitHub
parent 77ccadd663
commit 6888901468
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
260 changed files with 1064 additions and 1048 deletions
_composer.json
docs/en
00_Getting_Started
01_Lessons
02_Developer_Guides
00_Model
01_Templates
02_Controllers
03_Forms
04_Configuration
05_Extending
06_Testing
07_Debugging
08_Performance
09_Security
10_Email
11_Integration
12_Search
13_i18n
14_Files
15_Customising_the_Admin_Interface
16_Execution_Pipeline
17_CLI
18_Cookies_And_Sessions
index.md
03_Upgrading
04_Changelogs
05_Contributing
_images
asset-admin-demo.pngassets.pngassets_editform.pngassets_sync.pngassets_up.pngbasicfiles.gif.pngbasicfilestructure.gifbasicfilestructure.gif.pngcomments.jpgcontrollers-and-dataobjects.pnglayout.cssmodeladmin_edit.pngmodeladmin_results.pngmodeladmin_search.pngnavigator.jpgnews-comments.jpgpage_node_deleted_as_normal.pngpage_node_removed.pngpage_node_scheduled.pngpagetype-inheritance.pngrss.jpgsearch-file.gifsearch-file.jpgsearchresults.jpgsss.png
treeicons
tutorial1_2nd_level-cut.jpgtutorial1_addpage.jpgtutorial1_cms-basic.jpgtutorial1_cms-numbered-3.jpgtutorial1_cms-numbered-5.jpgtutorial1_cms-numbered.jpgtutorial1_home-small.jpgtutorial1_home-template.jpgtutorial1_homepage-type.jpgtutorial1_menu-two-level-small.jpgtutorial1_menu-two-level.jpgtutorial1_menu.jpgtutorial1_subtemplates-diagram.jpgtutorial1_url.jpgtutorial2_articleholder.jpgtutorial2_create-staff.jpgtutorial2_data-collation.jpgtutorial2_einstein.jpgtutorial2_homepage-news.jpgtutorial2_icons2.jpgtutorial2_news-cms.jpgtutorial2_news.jpgtutorial2_newslist.jpgtutorial2_pagetype-inheritance.jpgtutorial2_photo.jpgtutorial2_rss-feed.jpgtutorial2_staff-section.jpgtutorial3_pollform.jpgtutorial3_pollresults.jpgtutorial3_validation.jpgtutorial4_search.jpgtutorial4_searchbox.jpgtutorial5-completecode-blackcandy.ziptutorial5-completecode.ziptutorial5_addNew.jpgtutorial5_mentor.jpgtutorial5_mentor_creation.jpgtutorial5_mentor_students.jpgtutorial5_module_creation.jpgtutorial5_module_selection.jpgtutorial5_project.jpgtutorial5_project_creation.jpgtutorial5_projects_table.jpgtutorial5_student_tab.jpgtutorial5_students.jpgupload-field.pngwebpi-2-a-silverstripe-choice.jpgwebpi-2-b-dependencies.jpgwebpi-2-c-downloading-and-installaing.jpgwebpi-2-d-installer-questions-step1.jpgwebpi-2-e-installer-questions-step2.jpgwebpi-2-f-success-message.jpgwebpi-2-g-silverstripe-homepage.jpgwebpi-2-h-cms-interface-working.jpgwidget_demo.gifwidget_demo.gif.png
index.md

View File

@ -1,6 +1,13 @@
---
title: Server Requirements
icon: server
summary: What you will need to run Silverstripe CMS on a web server
---
# Requirements
SilverStripe CMS needs to be installed on a web server. Content authors and website administrators use their web browser
Silverstripe CMS needs to be installed on a web server. Content authors and website administrators use their web browser
to access a web-based GUI to do their day-to-day work. Website designers and developers require access to the files on
the server to update templates, website logic, and perform upgrades or maintenance.

View File

@ -1,3 +1,8 @@
---
title: Composer
summary: What is composer and how to use it with Silverstripe CMS
---
# Installing and Upgrading with Composer
Composer is a package management tool for PHP that lets you install and upgrade SilverStripe and its modules. Although installing Composer is one extra step, it will give you much more flexibility than just downloading the file from silverstripe.org. This is our recommended way of downloading SilverStripe and managing your code.
@ -19,9 +24,9 @@ You can then run Composer commands by calling `composer`. For example:
composer help
```
<div class="hint" markdown="1">
[hint]
It is also possible to keep `composer.phar` out of your path, for example, to put it in your project root. Every command would then start with `php composer.phar` instead of `composer`. This is handy if need to keep your installation isolated from the rest of your computer's set-up, but we recommend putting composer into the path for most people.
</div>
[/hint]
#### Updating composer
@ -99,9 +104,9 @@ composer search silverstripe
This will return a list of package names of the forum `vendor/package`. If you prefer, you can search for packages on [packagist.org](https://packagist.org/search/?q=silverstripe).
<div class="warning" markdown="1">
[warning]
**Version constraints:** `master` is not a legal version string - it's a branch name. These are different things. The version string that would get you the branch is `dev-master`. The version string that would get you a numeric branch is a little different. The version string for the `4` branch is `4.x-dev`.
</div>
[/warning]
## Updating dependencies

View File

@ -1,3 +1,8 @@
---
title: Environment Management
summary: How to configure your server environment for Silverstripe CMS
---
# Environment management
As part of website development and hosting it is natural for our sites to be hosted on several different environments.
@ -59,9 +64,9 @@ SilverStripe\Core\Injector\Injector:
MyProperty: '`ENV_VAR_HERE`'
```
<div class="info">
[info]
<p>Environment variables cannot be used outside of Injector config as of version 4.2.</p>
</div>
[/info]
## Including an extra `.env` file

View File

@ -1,3 +1,9 @@
---
title: Directory Structure
summary: An overview of what each directory contains in a Silverstripe CMS installation
icon: sitemap
---
# Directory Structure
## Introduction

View File

@ -1,155 +0,0 @@
# Common Problems
From time to time, things will go wrong. Here's a few things to try when you're confused.
## The output shows only "Website Error"
This first and foremost means that your environment is set to "live mode" (see [environment-management]), which disallows
detailed error messages for security reasons. You'll typically need to get your environment into "dev mode" to see more
information.
If you can log-in to the CMS as an administrator, append `?isDev=1` to any URL to temporarily set your browsing session into
"dev mode". If you can't log-in in the first place because of the error, please
configure an `SS_ENVIRONMENT_TYPE` through [environment-management] (don't forget to remove it afterwards!).
<div class="warning" markdown='1'>
On "live" environments, the `?isDev=1` solution is preferred, as it means that your other visitors don't see ugly
(and potentially security sensitive) PHP errors as well.
</div>
## mod_rewrite isn't working but it's installed (prior to SilverStripe 3.1.11)
Due to some changes to `mod_dir` in [Apache 2.4](http://httpd.apache.org/docs/current/mod/mod_dir.html#DirectoryCheckHandler)
(precedence of handlers), index.php gets added to the URLs as soon as you navigate to the homepage of your site.
To fix this place the following within the `mod_rewrite` section of your .htaccess file:
```
<IfModule mod_rewrite.c>
# Turn off index.php handling requests to the homepage fixes issue in apache >=2.4
<IfModule mod_dir.c>
DirectoryIndex disabled
</IfModule>
# ------ #
</IfModule>
```
## My templates don't update on page refresh
Putting ?flush=1 on the end of any SilverStripe URL will clear out all cached content; this is a pretty common solution
to a lot of development problems. Here are some specifics situations:
* You've created a new SS or PHP file
* You've edited a nested template (one inserted with the `<% include %>` tag)
* You've published a new copy of your site
* You've upgraded your version of SilverStripe
## A SQL query fails with "Column not found" or "Table not found"
Whenever you change the model definitions in PHP (e.g. when adding a property to the [$db](api:SilverStripe\ORM\DataObject::$db) array,
creating a new page type), SilverStripe will need to update the database. Visiting `http://localhost/dev/build` in
your browser runs a script that will check the database schema and update it as necessary. Putting `?flush=1` on the
end makes sure that nothing that's linked to the old database structure will be carried over. If things aren't saving,
pages aren't loading, or other random things aren't working it's possible that the database hasn't been updated to
handle the new code. Here are some specifics situations:
* You've created a new page type / other data object type
* You've change the type of one of your database fields
* You've published a new copy of your site
* You've upgraded your version of SilverStripe
## My edited CMS content doesn't show on the website
If you've set up your site and it used to be working, but now it's suddenly totally broken, you may have forgotten to
publish your draft content. Go to the CMS and use the "publish" button. You can visit `admin/pages/publishall` to publish
every page on the site, if that's easier. Note that this will only work on smaller websites.
## I can see unparsed PHP output in my browser
Please make sure all code inside `*.php` files is wrapped in classes. Due to the way [ClassManifest](api:SilverStripe\Core\Manifest\ClassManifest)
includes all files with this extension, any **procedural code will be executed on every call**. The most common error here
is putting a test.php/phpinfo.php file in the document root. See [datamodel](/developer_guides/model/data_model_and_orm) and [controllers](/developer_guides/controllers)
for ways how to structure your code.
Also, please check that you have PHP enabled on the webserver, and you're running PHP 5.1 or later.
The web-based [SilverStripe installer](/getting_started/installation) can help you with this.
## I've got file permission problems during installation
The php installer needs to be able to write files during installation, which should be restricted again afterwards. It
needs to create/have write-access to:
* The main installation directory (for creating .htaccess file and assets directory)
* The `app/` folder (to create _config.php)
* After the install, the assets directory is the only directory that needs write access.
* Image thumbnails will not show in the CMS if permission is not given
If you are running on a server instance where users other than the webserver user will need
read / write access to files in the assets folder, then you should do one of the below:
- Ensure that all server users that modify this file belong to the same group
- Modify the permissions that SilverStripe uses to write to a more permissive setting (see below)
It may be necessary to manually set the original permissions, and owner user/group of your assets folder on
initial deployment.
For more information on understanding and determining file permissions, please see
[wikipedia](https://en.wikipedia.org/wiki/File_system_permissions#Traditional_Unix_permissions)
on unix permissions.
### Modifying write permissions of files
By default all files and `.htaccess` are written with permission `0664`.
You could enable other users to access these files with the below config.
Note: Please adjust the values below to those appropriate for your server configuration.
You may require `0666` for combined files generated during requests where they are cleared or refreshed only during a flush.
*app/_config/assetperms.yml*
```yaml
---
Name: myassetperms
---
SilverStripe\Assets\Flysystem\AssetAdapter:
file_permissions:
file:
public: 0666 # Replace with your desired permission for files
dir:
public: 0777 # Replace with your desired permission for folders
```
Note: `public` key applies to all files whether they are protected or public; This is a flag internal to
Flysystem, and file protection is applied by SilverStripe on top of these permissions.
## I have whitespace before my HTML output, triggering quirks mode or preventing cookies from being set
SilverStripe only uses class declarations in PHP files, and doesn't output any content
directly outside of these declarations. It's easy to accidentally add whitespace
or any other characters before the `<?php` opening bracket at the start of the document,
or after the `?>` closing braket at the end of the document.
Since we're dealing with hundreds of included files, identifying these mistakes manually can be tiresome.
The best way to detect whitespace is to look through your version control system for any uncommitted changes.
If that doesn't work out, here's a little script to run checks in all relevant PHP files.
Save it as `check.php` into your webroot, and run it as `php check.php` (or open it in your browser).
After using the script (and fixing errors afterwards), please remember to remove it again.
```php
// Check for whitespace around PHP brackets which show in output,
// and hence can break HTML rendering and HTTP operations.
$path = dirname(__FILE__);
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
$matched = false;
foreach($files as $name => $file){
if($file->getExtension() != 'php') continue;
if(preg_match('/thirdparty|vendor/',$file->getPathname())) continue;
$content = file_get_contents($file->getPathname());
if(preg_match('/^[[:blank:]]+<\?' . 'php/', $content)) {
echo sprintf("%s: Space before opening bracket\n", $file->getPathname());
$matched = true;
}
if(preg_match('/^\?' . '>\n?[[:blank:]]+/m', $content)) {
echo sprintf("%s: Space after closing bracket\n", $file->getPathname());
$matched = true;
}
}
```

View File

@ -1,5 +1,8 @@
---
title: Getting Started
introduction: SilverStripe is a web application. This means that you will need to have a webserver and database. We will take you through the setup of the server environment as well the application itself.
icon: rocket
---
## Server Requirements
@ -45,6 +48,11 @@ Webserver setup is covered in
[Lesson 4: Setting up a local dev environment](https://www.silverstripe.org/learn/lessons/v4/up-and-running-setting-up-a-local-silverstripe-dev-environment-1)
## Keep learning
[CHILDREN]
## Troubleshooting
If you run into trouble, see [common-problems](common_problems) or

View File

@ -1,5 +1,8 @@
---
title: Lessons
introduction: The lessons take a step by step look at how to build a SilverStripe application.
icon: graduation-cap
---
* [How to set up a local development environment in SilverStripe](https://www.silverstripe.org/learn/lessons/v4/up-and-running-setting-up-a-local-silverstripe-dev-environment-1)
* [Lesson 1: Creating your first project](https://www.silverstripe.org/learn/lessons/v4/creating-your-first-project)

View File

@ -1,5 +1,8 @@
---
title: Introduction to the Data Model and ORM
summary: Introduction to creating and querying a database records through the ORM (object-relational model)
icon: database
---
# Introduction to the Data Model and ORM
@ -60,10 +63,10 @@ It **won't** do any of the following
their table names don't match a SilverStripe data class.
<div class="notice" markdown='1'>
[notice]
You need to be logged in as an administrator to perform this command, unless your site is in [dev mode](../debugging),
or the command is run through [CLI](../cli).
</div>
[/notice]
When rebuilding the database schema through the [ClassLoader](api:SilverStripe\Core\Manifest\ClassLoader) the following additional properties are
automatically set on the `DataObject`.
@ -121,9 +124,9 @@ Or, a better way is to use the `create` method.
$player = Player::create();
```
<div class="notice" markdown='1'>
[notice]
Using the `create()` method provides chainability, which can add elegance and brevity to your code, e.g. `Player::create()->write()`. More importantly, however, it will look up the class in the [Injector](../extending/injector) so that the class can be overriden by [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection).
</div>
[/notice]
Database columns and properties can be set as class properties on the object. The SilverStripe ORM handles the saving
@ -179,9 +182,9 @@ $members = Player::get()->filter([
```
<div class="info" markdown="1">
[info]
Provided `filter` values are automatically escaped and do not require any escaping.
</div>
[/info]
## Lazy Loading
@ -440,11 +443,11 @@ $teams = Team::get()->filter('Players.Sum(PointsScored):LessThan', 300);
It is also possible to filter by a PHP callback, this will force the data model to fetch all records and loop them in
PHP, thus `filter()` or `filterAny()` are to be preferred over `filterByCallback()`.
<div class="notice" markdown="1">
[notice]
Because `filterByCallback()` has to run in PHP, it has a significant performance tradeoff, and should not be used on large recordsets.
`filterByCallback()` will always return an `ArrayList`.
</div>
[/notice]
The first parameter to the callback is the item, the second parameter is the list itself. The callback will run once
for each record, if the callback returns true, this record will be added to the list of returned items.
@ -552,9 +555,9 @@ offset, if not provided as an argument, will default to 0.
$members = Member::get()->sort('Surname')->limit(10, 4);
```
<div class="alert">
[alert]
Note that the `limit` argument order is different from a MySQL LIMIT clause.
</div>
[/alert]
### Mapping classes to tables with DataObjectSchema
@ -653,10 +656,10 @@ $members = Member::get()
->innerJoin("Group_Members", "\"Rel\".\"MemberID\" = \"Member\".\"ID\"", "Rel");
```
<div class="alert" markdown="1">
[alert]
Passing a *$join* statement to will filter results further by the JOINs performed against the foreign table. It will
**not** return the additionally joined data.
</div>
[/alert]
### Default Values
@ -675,10 +678,10 @@ class Player extends DataObject
}
```
<div class="notice" markdown='1'>
[notice]
Note: Alternatively you can set defaults directly in the database-schema (rather than the object-model). See
[Data Types and Casting](/developer_guides/model/data_types_and_casting) for details.
</div>
[/notice]
## Subclasses

View File

@ -1,5 +1,8 @@
---
title: Relations between Records
summary: Relate models together using the ORM using has_one, has_many, and many_many.
icon: link
---
# Relations between Records
@ -115,19 +118,19 @@ class Fan extends DataObject
}
```
<div class="warning" markdown='1'>
[warning]
Note: The use of polymorphic relationships can affect query performance, especially
on joins, and also increases the complexity of the database and necessary user code.
They should be used sparingly, and only where additional complexity would otherwise
be necessary. E.g. Additional parent classes for each respective relationship, or
duplication of code.
</div>
[/warning]
## has_many
Defines 1-to-many joins. As you can see from the previous example, `$has_many` goes hand in hand with `$has_one`.
<div class="alert" markdown='1'>
[alert]
Please specify a $has_one-relationship on the related child-class as well, in order to have the necessary accessors
available on both ends. To add a $has_one-relationship on core classes, yml config settings can be used:
```yml
@ -135,7 +138,7 @@ SilverStripe\Assets\Image:
has_one:
MyDataObject: MyDataObject
```
</div>
[/alert]
```php
use SilverStripe\ORM\DataObject;
@ -246,10 +249,10 @@ Defines many-to-many joins, which uses a third table created between the two to
There are two ways in which this can be declared, which are described below, depending on
how the developer wishes to manage this join table.
<div class="warning" markdown='1'>
[warning]
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>
[/warning]
Much like the `has_one` relationship, `many_many` can be navigated through the `ORM` as well.
The only difference being you will get an instance of [ManyManyList](api:SilverStripe\ORM\ManyManyList) or
@ -511,10 +514,10 @@ If your object is versioned, cascade_deletes will also act as "cascade unpublish
on a parent object will trigger unpublish on the child, similarly to how `owns` causes triggered publishing.
See the [versioning docs](/developer_guides/model/versioning) for more information on ownership.
<div class="alert" markdown="1">
[alert]
Declaring cascade_deletes implies delete permissions on the listed objects.
Built-in controllers using delete operations check canDelete() on the owner, but not on the owned object.
</div>
[/alert]
## Cascading duplications
@ -597,10 +600,10 @@ class Team extends DataObject
```
<div class="notice" markdown="1">
[notice]
Adding new records to a filtered `RelationList` like in the example above doesn't automatically set the filtered
criteria on the added record.
</div>
[/notice]
## Relations on Unsaved Objects

View File

@ -1,5 +1,8 @@
---
title: Managing Lists
summary: The SS_List interface allows you to iterate through and manipulate a list of objects.
icon: list
---
# Managing Lists

View File

@ -1,5 +1,8 @@
---
title: Data Types, Overloading and Casting
summary: Learn how how data is stored going in and coming out of the ORM and how to modify it.
icon: code
---
# Data Types and Casting

View File

@ -1,5 +1,7 @@
---
title: Extending DataObjects
summary: Modify the data model without using subclasses.
---
# Extending DataObjects
@ -85,10 +87,10 @@ class Player extends DataObject
}
```
<div class="notice" markdown='1'>
[notice]
Note: There are no separate methods for *onBeforeCreate* and *onBeforeUpdate*. Please check `$this->isInDb()` to toggle
these two modes, as shown in the example above.
</div>
[/notice]
## Related Lessons
* [Working with data relationships - $has_many](https://www.silverstripe.org/learn/lessons/v4/working-with-data-relationships-has-many-1)

View File

@ -1,5 +1,8 @@
---
title: SearchFilter Modifiers
summary: Use suffixes on your ORM queries.
icon: search
---
# SearchFilter Modifiers

View File

@ -1,5 +1,8 @@
---
title: Model-Level Permissions
summary: Reduce risk by securing models.
icon: lock
---
# Model-Level Permissions
@ -11,10 +14,10 @@ The API provides four methods for this purpose: `canEdit()`, `canCreate()`, `can
Since they're PHP methods, they can contain arbitrary logic matching your own requirements. They can optionally receive
a `$member` argument, and default to the currently logged in member (through `Security::getCurrentUser()`).
<div class="notice" markdown="1">
[notice]
By default, all `DataObject` subclasses can only be edited, created and viewed by users with the 'ADMIN' permission
code.
</div>
[/notice]
```php
use SilverStripe\Security\Permission;
@ -44,11 +47,11 @@ class MyDataObject extends DataObject
}
```
<div class="alert" markdown="1">
[alert]
These checks are not enforced on low-level ORM operations such as `write()` or `delete()`, but rather rely on being
checked in the invoking code. The CMS default sections as well as custom interfaces like [ModelAdmin](api:SilverStripe\Admin\ModelAdmin) or
[GridField](api:SilverStripe\Forms\GridField\GridField) already enforce these permissions.
</div>
[/alert]
## API Documentation

View File

@ -1,5 +1,8 @@
---
title: SQL Queries
summary: Write and modify direct database queries through SQLExpression subclasses.
iconBrand: searchengin
---
# SQLSelect
@ -46,10 +49,10 @@ various assumptions the ORM and code based on it have:
We'll explain some ways to use *SELECT* with the full power of SQL,
but still maintain a connection to the ORM where possible.
<div class="warning" markdown="1">
[warning]
Please read our [security topic](/developer_guides/security) to find out
how to properly prepare user input and variables for use in queries
</div>
[/warning]
## Usage

View File

@ -1,5 +1,8 @@
---
title: Model Validation and Constraints
summary: Validate your data at the model level
icon: check-square
---
# Validation and Constraints

View File

@ -1,5 +1,7 @@
---
title: Versioning
summary: Add versioning to your database content through the Versioned extension.
---
# Versioning
@ -11,7 +13,7 @@ from published content shown to your website visitors.
Versioning in SilverStripe is handled through the [Versioned](api:SilverStripe\Versioned\Versioned) class. As a [DataExtension](api:SilverStripe\ORM\DataExtension) it is possible to be applied to any [DataObject](api:SilverStripe\ORM\DataObject) subclass. The extension class will automatically update read and write operations done via the ORM via the `augmentSQL` database hook.
<div class="notice" markdown="1">
[notice]
There are two complementary modules that improve content editor experience around "owned" nested objects (e.g. elemental blocks).
Those are in experimental status right now, but we would appreciate any feedback and contributions.
@ -25,7 +27,7 @@ The second module extends CMS History UI adding control over nested objects.
![](../../_images/snapshot-admin.png)
*Example screenshot from versioned-snapshot-admin*
</div>
[/notice]
## Understanding versioning concepts
@ -63,11 +65,11 @@ SilverStripe makes this possible by using the concept of _cascade publishing_. Y
A non-recursive publish operation is also available if you want to publish a new version of a object without cascade publishing all its children.
<div class="alert" markdown="1">
[alert]
Declaring ownership implies publish permissions on owned objects.
Built-in controllers using cascading publish operations check canPublish()
on the owner, but not on the owned object.
</div>
[/alert]
#### Ownership of unversioned object
@ -92,11 +94,11 @@ Changes to many objects can be grouped together using the [`ChangeSet`](api:Silv
Records can be added to a changeset in the CMS by using the "Add to campaign" button
that is available on the edit forms of all pages and files. Programmatically, this is done by creating a `SilverStripe\Versioned\ChangeSet` object and invoking its `addObject(DataObject $record)` method.
<div class="info" markdown="1">
[info]
DataObjects can be added to more than one ChangeSet.
Most of the time, these objects contain changes.
A ChangeSet can contain unchanged objects as well.
</div>
[/info]
#### Implicit vs. Explicit inclusions
@ -144,15 +146,15 @@ class VersionedModel extends DataObject
}
```
<div class="notice" markdown="1">
[notice]
The extension is automatically applied to `SiteTree` class. For more information on extensions see
[Extending](../extending) and the [Configuration](../configuration) documentation.
</div>
<a href="../extending">extending</a> and the <a href="../configuration">Configuration</a> documentation.
[/notice]
<div class="warning" markdown="1">
[warning]
Versioning only works if you are adding the extension to the base class. That is, the first subclass
of `DataObject`. Adding this extension to children of the base class will have unpredictable behaviour.
</div>
[/warning]
### Defining ownership between related versioned DataObjects
@ -344,10 +346,10 @@ use SilverStripe\Versioned\Versioned;
$historicalRecord = Versioned::get_version('MyRecord', <record-id>, <version-id>);
```
<div class="alert" markdown="1">
[alert]
The record is retrieved as a `DataObject`, but saving back modifications via `write()` will create a new version,
rather than modifying the existing one.
</div>
[/alert]
In order to get a list of all versions for a specific record, we need to generate specialized [Versioned_Version](api:SilverStripe\Versioned\Versioned_Version)
objects, which expose the same database information as a `DataObject`, but also include information about when and how
@ -512,10 +514,10 @@ Depending on whether staging is enabled, one or more new tables will be created
is always created to track historic versions for your model. If staging is enabled this will also create a new
`<class>_Live` table once you've rebuilt the database.
<div class="notice" markdown="1">
[notice]
Note that the "Stage" naming has a special meaning here, it will leave the original table name unchanged, rather than
adding a suffix.
</div>
[/notice]
* `MyRecord` table: Contains staged data
* `MyRecord_Live` table: Contains live data
@ -682,22 +684,22 @@ SilverStripe\Control\Director:
'my-objects/$ID': 'MyObjectController'
```
<div class="alert" markdown="1">
[alert]
The `choose_site_stage()` call only deals with setting the default stage, and doesn't check if the user is
authenticated to view it. As with any other controller logic, please use `DataObject->canView()` to determine
permissions, and avoid exposing unpublished content to your users.
</div>
[/alert]
### Controlling permissions to versioned DataObjects
By default, `Versioned` will come out of the box with security extensions which restrict the visibility of objects in Draft (stage) or Archive viewing mode.
<div class="alert" markdown="1">
[alert]
As is standard practice, user code should always invoke `canView()` on any object before
rendering it. DataLists do not filter on `canView()` automatically, so this must be
done via user code. This be be achieved either by wrapping `<% if $canView %>` in
done via user code. This be be achieved either by wrapping `<% if $canView %>;` in
your template, or by implementing your visibility check in PHP.
</div>
[/alert]
#### Version specific _can_ methods
@ -845,7 +847,7 @@ public function init()
SilverStripe will usually call these low level methods for you when you. However if you have specialised needs, you may call them directly.
To move a saved version from one stage to another, call [writeToStage(<stage>)](api:SilverStripe\Versioned\Versioned::writeToStage()) on the object. This is used internally to publish DataObjects.
To move a saved version from one stage to another, call [writeToStage(stage)](api:SilverStripe\Versioned\Versioned::writeToStage()) on the object. This is used internally to publish DataObjects.
`copyVersionToStage($versionID, $stage)` allow you to restore a previous version to a specific stage. This is used internally when performing a rollback.

View File

@ -1,5 +1,8 @@
---
title: Building Model and Search Interfaces around Scaffolding
summary: A Model-driven approach to defining your application UI.
icon: hammer
---
# Scaffolding

View File

@ -1,5 +1,8 @@
---
title: Indexes
summary: Add Indexes to your Data Model to optimize database queries.
icon: database
---
# Indexes
Indexes are a great way to improve performance in your application, especially as it grows. By adding indexes to your
@ -69,10 +72,10 @@ class MyTestObject extends DataObject
}
```
<div class="alert" markdown="1">
[alert]
Please note that if you have previously used the removed `value` key to define an index's contents, SilverStripe will
now throw an error. Use `columns` instead.
</div>
[/alert]
## Complex/Composite Indexes
For complex queries it may be necessary to define a complex or composite index on the supporting object. To create a

View File

@ -1,3 +1,8 @@
---
title: Dynamic Default Fields
summary: Learn how to add default values to your models
---
# Default Values and Records
## Static Default Values

View File

@ -1,3 +1,8 @@
---
title: Grouping DataObject sets
summary: Learn how to split the results of a query into subgroups
---
# Grouping lists of records
The [SS_List](api:SilverStripe\ORM\SS_List) class is designed to return a flat list of records.

View File

@ -0,0 +1,6 @@
---
title: How To's
---
# How To's: Model and Databases
[CHILDREN]

View File

@ -1,6 +1,9 @@
---
title: Model and Databases
summary: Learn how SilverStripe manages database tables, ways to query your database and how to publish data.
introduction: This guide will cover how to create and manipulate data within SilverStripe and how to use the ORM (Object Relational Model) to query data.
icon: database
---
In SilverStripe, application data will be represented by a [DataObject](api:SilverStripe\ORM\DataObject) class. A `DataObject` subclass defines the
data columns, relationships and properties of a particular data record. For example, [Member](api:SilverStripe\Security\Member) is a `DataObject`

View File

@ -1,5 +1,8 @@
---
title: Template Syntax
summary: A look at the operations, variables and language controls you can use within templates.
icon: code
---
# Template Syntax
@ -40,10 +43,10 @@ An example of a SilverStripe template is below:
</html>
```
<div class="note">
[note]
Templates can be used for more than HTML output. You can use them to output your data as JSON, XML, CSV or any other
text-based format.
</div>
[/note]
## Template file location
@ -91,10 +94,10 @@ If a variable returns a string, that string will be inserted into the template.
the system will attempt to render the object through its `forTemplate()` method. If the `forTemplate()` method has not
been defined, the system will return an error.
<div class="note" markdown="1">
[note]
For more detail around how variables are inserted and formatted into a template see
[Formating, Modifying and Casting Variables](casting)
</div>
[/note]
Variables can come from your database fields, or custom methods you define on your objects.
@ -113,9 +116,9 @@ public function UsersIpAddress()
<p>You are coming from $UsersIpAddress.</p>
```
<div class="node" markdown="1">
[note]
Method names that begin with `get` will automatically be resolved when their prefix is excluded. For example, the above method call `$UsersIpAddress` would also invoke a method named `getUsersIpAddress()`.
</div>
[/note]
The variables that can be used in a template vary based on the object currently in [scope](#scope). Scope defines what
object the methods get called on. For the standard `Page.ss` template the scope is the current [PageController](api:SilverStripe\CMS\Controllers\ContentController\PageController)
@ -150,9 +153,9 @@ A conditional can also check for a value other than falsy.
<% end_if %>
```
<div class="notice" markdown="1">
[notice]
When inside template tags variables should have a '$' prefix, and literals should have quotes.
</div>
[/notice]
Conditionals can also provide the `else` case.
@ -280,13 +283,13 @@ collection.
This snippet loops over the children of a page, and generates an unordered list showing the `Title` property from each
page.
<div class="notice" markdown="1">
[notice]
$Title inside the loop refers to the Title property on each object that is looped over, not the current page like
the reference of `$Title` outside the loop.
This demonstrates the concept of [Scope](#scope). When inside a <% loop %> the scope of the template has changed to the
object that is being looped over.
</div>
[/notice]
### Altering the list
@ -370,10 +373,10 @@ iteration.
</ul>
```
<div class="info" markdown="1">
[info]
A common task is to paginate your lists. See the [Pagination](how_tos/pagination) how to for a tutorial on adding
pagination.
</div>
[/info]
### Modulus and MultipleOf
@ -395,10 +398,10 @@ $MultipleOf(factor, offset)
// returns <div class="column-3">, <div class="column-2">,
```
<div class="hint" markdown="1">
[hint]
`$Modulus` is useful for floated grid CSS layouts. If you want 3 rows across, put $Modulus(3) as a class and add a
`clear: both` to `.column-1`.
</div>
[/hint]
$MultipleOf(value, offset) can also be utilized to build column and grid layouts. In this case we want to add a `<br>`
after every 3rd item.
@ -434,9 +437,9 @@ $Foo // returns "3"
\$Foo // returns "$Foo"
```
<div class="hint" markdown="1">
[hint]
For more information on formatting and casting variables see [Formating, Modifying and Casting Variables](casting)
</div>
[/hint]
## Scope
@ -473,7 +476,7 @@ When in a particular scope, `$Up` takes the scope back to the previous level.
```
Given the following structure, it will output the text.
```
My Page
|
+-+ Child 1
@ -487,10 +490,10 @@ Given the following structure, it will output the text.
Page 'Child 1' is a child of 'My Page'
Page 'Grandchild 1' is a grandchild of 'My Page'
Page 'Child 2' is a child of 'MyPage'
<div class="notice" markdown="1">
```
[notice]
Additional selectors implicitely change the scope so you need to put additional `$Up` to get what you expect.
</div>
[/notice]
```ss
<h1>Children of '$Title'</h1>

View File

@ -1,5 +1,7 @@
---
title: Common Variables
summary: Some of the common variables and methods your templates can use, including Menu, SiteConfig, and more.
---
# Common Variables
@ -12,20 +14,20 @@ explained in more detail on the [syntax](syntax#scope) page. Many of the methods
scope, and you can specify additional static methods to be available globally in templates by implementing the
[TemplateGlobalProvider](api:SilverStripe\View\TemplateGlobalProvider) interface.
<div class="notice" markdown="1">
[notice]
Want a quick way of knowing what scope you're in? Try putting `$ClassName` in your template. You should see a string
such as `Page` of the object that's in scope. The methods you can call on that object then are any functions, database
properties or relations on the `Page` class, `PageController` class as well as anything from their subclasses **or**
extensions.
</div>
[/notice]
Outputting these variables is only the start, if you want to format or manipulate them before adding them to the template
have a read of the [Formating, Modifying and Casting Variables](casting) documentation.
<div class="alert" markdown="1">
[alert]
Some of the following only apply when you have the `CMS` module installed. If you're using the `Framework` alone, this
functionality may not be included.
</div>
[/alert]
## Base Tag
@ -38,15 +40,15 @@ functionality may not be included.
</head>
```
The `<% base_tag %>` placeholder is replaced with the HTML base element. Relative links within a document (such as <img
The `<% base_tag %>` placeholder is replaced with the HTML base element. Relative links within a document (such as `<img
src="someimage.jpg" />) will become relative to the URI specified in the base tag. This ensures the browser knows where
to locate your sites images and css files.
It renders in the template as `<base href="http://www.yoursite.com" /><!--[if lte IE 6]></base><![endif]-->`
<div class="alert" markdown="1">
A `<% base_tag %>` is nearly always required or assumed by SilverStripe to exist.
</div>
[alert]
A `<% base_tag %>;` is nearly always required or assumed by SilverStripe to exist.
[/alert]
## CurrentMember
@ -71,9 +73,9 @@ Most objects within SilverStripe will respond to `$Title` (i.e they should have
The CMS module in particular provides two fields to label a page: `Title` and `MenuTitle`. `Title` is the title
displayed on the web page, while `MenuTitle` can be a shorter version suitable for size-constrained menus.
<div class="notice" markdown="1">
[notice]
If `MenuTitle` is left blank by the CMS author, it'll just default to the value in `Title`.
</div>
[/notice]
## Page Content
@ -84,21 +86,21 @@ $Content
It returns the database content of the `Content` property. With the CMS Module, this is the value of the WYSIWYG editor
but it is also the standard for any object that has a body of content to output.
<div class="info" markdown="1">
Please note that this database content can be `versioned`, meaning that draft content edited in the CMS can be different
[info]
Please note that this database content can be "versioned", meaning that draft content edited in the CMS can be different
from published content shown to your website visitors. In templates, you don't need to worry about this distinction.
The `$Content` variable contains the published content by default,and only preview draft content if explicitly
requested (e.g. by the "preview" feature in the CMS) (see the [versioning documentation](/../model/versioning) for
more details).
</div>
[/info]
### SiteConfig: Global settings
<div class="notice" markdown="1">
`SiteConfig` is a module that is bundled with the `CMS`. If you wish to include `SiteConfig` in your framework only
web pages. You'll need to install it via `composer`.
</div>
[notice]
`SiteConfig` is a module that is bundled with the CMS. If you wish to include `SiteConfig` in your framework only
web pages. You'll need to install it via composer.
[/notice]
```ss
$SiteConfig.Title
@ -117,9 +119,9 @@ The `$MetaTags` placeholder in a template returns a segment of HTML appropriate
will set up title, keywords and description meta-tags, based on the CMS content and is editable in the 'Meta-data' tab
on a per-page basis.
<div class="notice" markdown="1">
[notice]
If you dont want to include the title tag use `$MetaTags(false)`.
</div>
[/notice]
By default `$MetaTags` renders:
@ -255,10 +257,10 @@ behavior based on the page type used:
Will loop over all Children records of the current object context. Children are pages that sit under the current page in
the `CMS` or a custom list of data. This originates in the `Versioned` extension's `getChildren` method.
<div class="alert" markdown="1">
[alert]
For doing your website navigation most likely you'll want to use `$Menu` since its independent of the page
context.
</div>
[/alert]
### ChildrenOf
@ -295,9 +297,9 @@ preference, `AllChildren` does not filter by `ShowInMenus`.
`$Menu(1)` returns the top-level menu of the website. You can also create a sub-menu using `$Menu(2)`, and so forth.
<div class="notice" markdown="1">
[notice]
Pages with the `ShowInMenus` property set to `false` will be filtered out.
</div>
[/notice]
## Access to a specific Page
@ -367,11 +369,11 @@ of the `silverstripe/cms` module.
<% end_if %>
```
<div class="info" markdown="1">
[info]
To customise the markup that the `$Breadcrumbs` generates, copy `templates/BreadcrumbsTemplate.ss`
from the `silverstripe/cms` module to
`app/templates/BreadcrumbsTemplate.ss`, modify the newly copied template and flush your SilverStripe cache.
</div>
[/info]
## Forms

View File

@ -1,5 +1,8 @@
---
title: Requirements
summary: How to include and require other assets in your templates such as javascript and CSS files.
iconBrand: js
---
# Requirements
@ -85,9 +88,9 @@ When rendered in HTML code, these URLs will be rewritten to their matching path
<% require javascript("<my-module-dir>/javascript/some_file.js") %>
```
<div class="alert" markdown="1">
[alert]
Requiring assets from the template is restricted compared to the PHP API.
</div>
[/alert]
## PHP Requirements API
@ -206,10 +209,10 @@ Requirements::combine_files(
);
```
<div class="alert" markdown='1'>
[alert]
To make debugging easier in your local environment, combined files is disabled when running your application in `dev`
mode. You can re-enable dev combination by setting `Requirements_Backend.combine_in_dev` to true.
</div>
[/alert]
### Configuring combined file storage
@ -305,10 +308,10 @@ SilverStripe\View\Requirements::combine_files('print.css', $printStylesheets, 'p
By default, all requirements files are flushed (deleted) when ?flush querystring parameter is set.
This can be disabled by setting the `Requirements.disable_flush_combined` config to `true`.
<div class="alert" markdown='1'>
[alert]
When combining CSS files, take care of relative urls, as these will not be re-written to match
the destination location of the resulting combined CSS.
</div>
[/alert]
### Combined JS Files
@ -366,10 +369,10 @@ SilverStripe\Core\Injector\Injector:
Minifier: %$MyProject\MyMinifier
```
<div class="alert" markdown='1'>
[alert]
While the framework does afford you the option of minification at runtime, we recommend using one of many frontend build
tools to do this for you, e.g. [Webpack](https://webpack.github.io/), [Gulp](http://gulpjs.com/), or [Grunt](https://gruntjs.com/).
</div>
[/alert]
## Clearing assets
@ -384,9 +387,9 @@ Clears all defined requirements. You can also clear specific requirements.
Requirements::clear('modulename/javascript/some-lib.js');
```
<div class="alert" markdown="1">
[alert]
Depending on where you call this command, a Requirement might be *re-included* afterwards.
</div>
[/alert]
## Blocking
@ -401,20 +404,20 @@ version in a custom location. This assumes you have tested your application with
Requirements::block('silverstripe/admin:thirdparty/jquery/jquery.js');
```
<div class="alert" markdown="1">
[alert]
The CMS also uses the `Requirements` system, and its operation can be affected by `block()` calls. Avoid this by
limiting the scope of your blocking operations, e.g. in `init()` of your controller.
</div>
[/alert]
## Inclusion Order
Requirements acts like a stack, where everything is rendered sequentially in the order it was included. There is no way
to change inclusion-order, other than using *Requirements::clear* and rebuilding the whole set of requirements.
<div class="alert" markdown="1">
[alert]
Inclusion order is both relevant for CSS and Javascript files in terms of dependencies, inheritance and overlays - be
careful when messing with the order of requirements.
</div>
[/alert]
## Javascript placement

View File

@ -1,5 +1,8 @@
---
title: Rendering data to a template
summary: Call and render SilverStripe templates manually.
icon: code
---
# Rendering data to a template
@ -33,10 +36,10 @@ echo $arrayData->renderWith('Coach_Message');
```
<div class="info" markdown="1">
[info]
Most classes in SilverStripe you want in your template extend `ViewableData` and allow you to call `renderWith`. This
includes [Controller](api:SilverStripe\Control\Controller), [FormField](api:SilverStripe\Forms\FormField) and [DataObject](api:SilverStripe\ORM\DataObject) instances.
</div>
[/info]
```php
$controller->renderWith(['MyController', 'MyBaseController']);

View File

@ -1,5 +1,8 @@
---
title: Template Inheritance
summary: Override and extend module and core markup templates from your application code.
icon: sitemap
---
# Template Inheritance

View File

@ -1,5 +1,8 @@
---
title: Themes
summary: What makes up a SilverStripe Theme. How to install one or write your own theme.
icon: paint-brush
---
# Themes
@ -24,10 +27,10 @@ composer require author/theme_name [version]
*Note:* `[version]` should be replaced with a version constraint if you know it, otherwise leave it blank to pull the latest version compatible with your project.
<div class="alert" markdown="1">
[alert]
As you've added new files to your SilverStripe installation, make sure you clear the SilverStripe cache by appending
`?flush=1` to your website URL (e.g http://yoursite.com/?flush=1).
</div>
[/alert]
### Configuring themes

View File

@ -1,5 +1,8 @@
---
title: Caching
summary: Reduce rendering time with cached templates and understand the limitations of the ViewableData object caching.
icon: rocket
---
# Caching

View File

@ -1,5 +1,8 @@
---
title: Translations
summary: Definition of the syntax for writing i18n compatible templates.
icon: globe
---
# Translations

View File

@ -1,5 +1,8 @@
---
title: Formatting, Modifying and Casting Variables
summary: Information on casting, security, modifying data before it's displayed to the user and how to format data within the template.
icon: code
---
# Formatting and Casting
@ -34,10 +37,10 @@ $Content.FirstParagraph.NoHTML
<!-- <div class="about-us"> -->
```
<div class="notice" markdown="1">
[notice]
See the API documentation for [DBHtmlText](api:SilverStripe\ORM\FieldType\DBHtmlText), [FieldType](api:SilverStripe\ORM\FieldType), [DBText](api:SilverStripe\ORM\FieldType\DBText) for all the methods you can use to format
your text instances. For other objects such as [DBDatetime](api:SilverStripe\ORM\FieldType\DBDatetime) objects see their respective API documentation pages.
</div>
[/notice]
## forTemplate
@ -92,10 +95,10 @@ class Page extends SiteTree
When calling `$MyCustomMethod` SilverStripe now has the context that this method will contain HTML and escape the data
accordingly.
<div class="note" markdown="1">
[note]
By default, all content without a type explicitly defined in a `$casting` array will be assumed to be `Text` content
and HTML characters encoded.
</div>
[/note]
## Escaping
@ -103,9 +106,9 @@ Properties are usually auto-escaped in templates to ensure consistent representa
displaying un-escaped ampersands in HTML. By default, values are escaped as `XML`, which is equivalent to `HTML` for
this purpose.
<div class="note" markdown="1">
[note]
There's some exceptions to this rule, see the ["security" guide](../security).
</div>
[/note]
For every field used in templates, a casting helper will be applied. This will first check for any
`casting` helper on your model specific to that field, and will fall back to the `default_cast` config
@ -148,11 +151,11 @@ See [DBField](api:SilverStripe\ORM\FieldType\DBField) for the specific implement
E.g. `<element>$Field.CDATA</element>` will ensure that the `<element>` body is safely escaped
as a string.
<div class="warning" markdown="1">
[warning]
Note: Take care when using `.XML` on `HTMLText` fields, as this will result in double-encoded
html. To ensure that the correct encoding is used for that field in a template, simply use
`$Field` by itself to allow the casting helper to determine the best encoding itself.
</div>
[/warning]
## Cast summary methods

View File

@ -1,4 +1,7 @@
---
title: How to Create a Navigation Menu
summary: Build a multi-tiered navigation UI.
---
# How to Create a Navigation Menu

View File

@ -1,4 +1,7 @@
---
title: How to Create a Paginated List
summary: Break up the result of a database query into multiple pages
---
# How to Create a Paginated List
@ -24,10 +27,10 @@ public function PaginatedPages()
}
```
<div class="notice" markdown="1">
[notice]
Note that the concept of "pages" used in pagination does not necessarily mean that we're dealing with `Page` classes,
it's just a term to describe a sub-collection of the list.
</div>
[/notice]
There are two ways to generate pagination controls: [PaginatedList::Pages()](api:SilverStripe\ORM\PaginatedList::Pages()) and
[PaginatedList::PaginationSummary()](api:SilverStripe\ORM\PaginatedList::PaginationSummary()). In this example we will use `PaginationSummary()`.

View File

@ -1,4 +1,7 @@
---
title: Disable Anchor Rewriting
summary: Get more control over how hash links are rendered.
---
# Disable Anchor Rewriting

View File

@ -0,0 +1,6 @@
---
title: How To's
---
# How To's: Templates and Views
[CHILDREN]

View File

@ -1,6 +1,9 @@
---
title: Templates and Views
summary: This guide showcases the SilverStripe template engine and learn how to build your own themes.
introduction: SilverStripe comes with it's own templating engine. This guide walks you through the features of the template engine, how to create custom templates and ways to customise your data output.
icon: file-code
---
Most of what will be public on your website comes from template files that are defined in SilverStripe. Either in the
core framework, the modules or themes you install, and your own custom templates.

View File

@ -1,5 +1,7 @@
---
title: Introduction to a Controller
summary: A brief look at the definition of a Controller, creating actions and how to respond to requests.
---
# Introduction to Controllers
@ -37,15 +39,15 @@ class TeamController extends Controller
We need to define the URL that this controller can be accessed on. In our case, the `TeamsController` should be visible
at http://yoursite.com/teams/ and the `players` custom action is at http://yoursite.com/team/players/.
<div class="info" markdown="1">
[info]
If you're using the `cms` module with and dealing with `Page` objects then for your custom `Page Type` controllers you
would extend `ContentController` or `PageController`. You don't need to define the routes value as the `cms` handles
routing.
</div>
[/info]
<div class="alert" markdown="1">
[alert]
Make sure that after you have modified the `routes.yml` file, that you clear your SilverStripe caches using `?flush=1`.
</div>
[/alert]
**app/_config/routes.yml**
@ -66,9 +68,9 @@ For more information about creating custom routes, see the [Routing](routing) do
Controllers respond by default to an `index` method. You don't need to define this method (as it's assumed) but you
can override the `index()` response to provide custom data back to the [Template and Views](../templates).
<div class="notice" markdown="1">
[notice]
It is standard in SilverStripe for your controller actions to be `lowercasewithnospaces`
</div>
[/notice]
Action methods can return one of four main things:

View File

@ -1,16 +1,18 @@
---
title: Routing
summary: A more in depth look at how to map requests to particular controllers and actions.
---
# Routing
Routing is the process of mapping URL's to [Controller](api:SilverStripe\Control\Controller) and actions. In the introduction we defined a new custom route
for our `TeamController` mapping any `teams` URL to our `TeamController`
<div class="info" markdown="1">
[info]
If you're using the `cms` module with and dealing with `Page` objects then for your custom `Page Type` controllers you
would extend `ContentController` or `PageController`. You don't need to define the routes value as the `cms` handles
routing.
</div>
[/info]
These routes by standard, go into a `routes.yml` file in your applications `_config` folder alongside your other
[Configuration](../configuration) information.
@ -31,9 +33,9 @@ SilverStripe\Control\Director:
'': 'HomeController'
```
<div class="notice" markdown="1">
[notice]
To understand the syntax for the `routes.yml` file better, read the [Configuration](../configuration) documentation.
</div>
[/notice]
## Parameters
@ -47,9 +49,9 @@ It also contains 3 `parameters` or `params` for short. `$Action`, `$ID` and `$Na
which will be filled when the user makes their request. Request parameters are available on the `HTTPRequest` object
and able to be pulled out from a controller using `$this->getRequest()->param($name)`.
<div class="info" markdown="1">
[info]
All Controllers have access to `$this->getRequest()` for the request object and `$this->getResponse()` for the response.
</div>
[/info]
Here is what those parameters would look like for certain requests
@ -103,9 +105,9 @@ echo $this->getRequest()->param('ID');
The [RequestHandler](api:SilverStripe\Control\RequestHandler) class will parse all rules you specify against the following patterns. The most specific rule
will be the one followed for the response.
<div class="alert">
[alert]
A rule must always start with alphabetical ([A-Za-z]) characters or a $Variable declaration
</div>
[/alert]
| Pattern | Description |
| ----------- | --------------- |
@ -143,13 +145,13 @@ start parsing variables and the appropriate controller action AFTER the `//`).
## URL Handlers
<div class="alert" markdown="1">
[alert]
You **must** use the **$url_handlers** static array described here if your URL
pattern does not use the Controller class's default pattern of
`$Action//$ID/$OtherID`. If you fail to do so, and your pattern has more than
2 parameters, your controller will throw the error "I can't handle sub-URLs of
a *class name* object" with HTTP status 404.
</div>
[/alert]
In the above example the URLs were configured using the [Director](api:SilverStripe\Control\Director) rules in the **routes.yml** file. Alternatively
you can specify these in your Controller class via the **$url_handlers** static array. This array is processed by the

View File

@ -1,5 +1,8 @@
---
title: Access Control
summary: Define allowed behavior and add permission based checks to your Controllers.
icon: user-lock
---
# Access Control
@ -39,9 +42,9 @@ class MyController extends Controller
}
```
<div class="info">
[info]
If the permission check fails, SilverStripe will return a `403` Forbidden HTTP status.
</div>
[/info]
An action named "index" is white listed by default, unless `allowed_actions` is defined as an empty array, or the action
is specifically restricted.
@ -130,9 +133,9 @@ class MyChildController extends MyController
```
<div class="notice" markdown="1">
[notice]
Access checks on parent classes need to be overwritten via the [Configuration API](../configuration).
</div>
[/notice]
## Forms
@ -190,10 +193,10 @@ class MyController extends Controller
```
<div class="notice" markdown="1">
[notice]
This is recommended as an addition for `$allowed_actions`, in order to handle more complex checks, rather than a
replacement.
</div>
[/notice]
## Controller Level Checks
@ -201,9 +204,9 @@ After checking for allowed_actions, each controller invokes its `init()` method,
common state, If an `init()` method returns a `HTTPResponse` with either a 3xx or 4xx HTTP status code, it'll abort
execution. This behavior can be used to implement permission checks.
<div class="info" markdown="1">
[info]
`init` is called for any possible action on the controller and before any specific method such as `index`.
</div>
[/info]
```php
use SilverStripe\Security\Permission;

View File

@ -1,5 +1,8 @@
---
title: Redirection
summary: Move users around your site using automatic redirection.
icon: reply
---
# Redirection

View File

@ -1,5 +1,7 @@
---
title: HTTP Middlewares
summary: Create objects for modifying request and response objects across controllers.
---
# HTTP Middlewares

View File

@ -1,5 +1,7 @@
---
title: Built-in Middleware
summary: Middleware components that come with SilverStripe Framework
---
# Built-in Middleware

View File

@ -1,6 +1,8 @@
---
title: Controllers
summary: Controllers form the backbone of your SilverStripe application. They handle routing URLs to your templates.
introduction: In this guide you will learn how to define a Controller class and how they fit into the SilverStripe response and request cycle.
---
The [Controller](api:SilverStripe\Control\Controller) class handles the responsibility of delivering the correct outgoing [HTTPResponse](api:SilverStripe\Control\HTTPResponse) for a
given incoming [HTTPRequest](api:SilverStripe\Control\HTTPRequest). A request is along the lines of a user requesting the homepage and contains

View File

@ -1,14 +1,17 @@
---
title: Introduction to Forms
summary: An introduction to creating a Form instance and handling submissions.
iconBrand: wpforms
---
# Forms
The HTML `Form` is the most used way to interact with a user. SilverStripe provides classes to generate forms through
the [Form](api:SilverStripe\Forms\Form) class, [FormField](api:SilverStripe\Forms\FormField) instances to capture data and submissions through [FormAction](api:SilverStripe\Forms\FormAction).
<div class="notice" markdown="1">
[notice]
See the [Introduction to frontend forms](https://www.silverstripe.org/learn/lessons/v4/introduction-to-frontend-forms-1) lesson for a step by step process of creating a `Form`
</div>
[/notice]
## Creating a Form
@ -79,11 +82,11 @@ class PageController extends ContentController
$HelloForm
```
<div class="info" markdown="1">
[info]
The examples above use `FormField::create()` instead of the `new` operator (`new FormField()`). These are functionally
equivalent, but allows PHP to chain operations like `setTitle()` without assigning the field instance to a temporary
variable.
</div>
[/info]
When constructing the `Form` instance (`new Form($controller, $name)`) both controller and name are required. The
`$controller` and `$name` are used to allow SilverStripe to calculate the origin of the `Form object`. When a user
@ -101,10 +104,10 @@ private static $allowed_actions = [
```
<div class="notice" markdown="1">
[notice]
Form actions (`doSayHello`), on the other hand, should _not_ be included in `$allowed_actions`; these are handled
separately through [Form::httpSubmission()](api:SilverStripe\Forms\Form::httpSubmission()).
</div>
[/notice]
## Adding FormFields
@ -116,9 +119,9 @@ Some common examples are [TextField](api:SilverStripe\Forms\TextField) or [Dropd
SilverStripe\Forms\TextField::create($name, $title, $value);
```
<div class="info" markdown='1'>
[info]
A list of the common FormField subclasses is available on the [Common Subclasses](field_types/common_subclasses/) page.
</div>
[/info]
The fields are added to the [FieldList](api:SilverStripe\Forms\FieldList) `fields` property on the `Form` and can be modified at up to the point the
`Form` is rendered.
@ -170,20 +173,20 @@ Fields can be removed from the form.
$form->getFields()->removeByName('Email');
```
<div class="alert" markdown="1">
[alert]
Forms can be tabbed (such as the CMS interface). In these cases, there are additional functions such as `addFieldToTab`
and `removeFieldByTab` to ensure the fields are on the correct interface. See [Tabbed Forms](tabbed_forms) for more
information on the CMS interface.
</div>
[/alert]
## Modifying FormFields
Each [FormField](api:SilverStripe\Forms\FormField) subclass has a number of methods you can call on it to customise its' behavior or HTML markup. The
default `FormField` object has several methods for doing common operations.
<div class="notice" markdown="1">
[notice]
Most of the `set` operations will return the object back so methods can be chained.
</div>
[/notice]
```php
$field = new TextField(..);
@ -270,10 +273,10 @@ with the particular button. In the previous example, clicking the 'Another Butto
* The `Form` instance.
* The `Controller` instance.
<div class="notice" markdown="1">
[notice]
If the `$action` method cannot be found on any of those or is marked as `private` or `protected`, an error will be
thrown.
</div>
[/notice]
The `$action` method takes two arguments:

View File

@ -1,5 +1,8 @@
---
title: Form Validation
summary: Validate form data through the server side validation API.
icon: check-square
---
# Form Validation
@ -57,11 +60,11 @@ class PageController extends ContentController
In this example we will be required to input a value for `Name` and a valid email address for `Email` before the
`doSubmitForm` method is called.
<div class="info" markdown="1">
[info]
Each individual [FormField](api:SilverStripe\Forms\FormField) instance is responsible for validating the submitted content through the
[FormField::validate()](api:SilverStripe\Forms\FormField::validate()) method. By default, this just checks the value exists. Fields like `EmailField` override
`validate` to check for a specific format.
</div>
[/info]
Subclasses of `FormField` can define their own version of `validate` to provide custom validation rules such as the
above example with the `Email` validation. The `validate` method on `FormField` takes a single argument of the current
@ -82,9 +85,9 @@ public function validate($validator)
The `validate` method should return `true` if the value passes any validation and `false` if SilverStripe should trigger
a validation error on the page. In addition a useful error message must be set on the given validator.
<div class="notice" markdown="1">
[notice]
You can also override the entire `Form` validation by subclassing `Form` and defining a `validate` method on the form.
</div>
[/notice]
Say we need a custom `FormField` which requires the user input a value in a `TextField` between 2 and 5. There would be
two ways to go about this:
@ -273,9 +276,9 @@ call `setValidator` easily. However, a `DataObject` can provide its' own `Valida
`getCMSValidator()` method. The CMS interfaces such as [LeftAndMain](api:SilverStripe\Admin\LeftAndMain), [ModelAdmin](api:SilverStripe\Admin\ModelAdmin) and [GridField](api:SilverStripe\Forms\GridField\GridField) will
respect the provided `Validator` and handle displaying error and success responses to the user.
<div class="info" markdown="1">
[info]
Again, custom error messages can be provided through the `FormField`
</div>
[/info]
```php
use SilverStripe\CMS\Model\SiteTree;

View File

@ -1,5 +1,8 @@
---
title: Form Templates
summary: Customize the generated HTML for a FormField or an entire Form.
icon: file-code
---
# Form Templates
@ -18,22 +21,22 @@ $field->setTemplate('MyCustomTextField');
To override the template for CMS forms, the custom templates should be located in **/app/templates**. Front-end form templates can be located in **/app/templates** or in the active theme's **/templates** directory.
<div class="notice" markdown="1">
[notice]
It's recommended to copy the contents of the template you're going to replace and use that as a start. For instance, if
you want to create a `MyCustomFormTemplate` copy the contents of `Form.ss` to a `MyCustomFormTemplate.ss` file and
modify as you need.
*The default Form.ss can be found in `/vendor/silverstripe/framework/templates/SilverStripe/Forms/Includes/`*
</div>
[/notice]
By default, Form and Fields follow the SilverStripe Template convention and are rendered into templates of the same
class name (i.e EmailField will attempt to render into `EmailField.ss` and if that isn't found, `TextField.ss` or
finally `FormField.ss`).
<div class="alert" markdown="1">
[alert]
While you can override all templates using normal view inheritance (i.e defining a `Form.ss`) other modules may rely on
the core template structure. It is recommended to use `setTemplate` and unique templates for specific forms.
</div>
[/alert]
For [FormField](api:SilverStripe\Forms\FormField) instances, there are several other templates that are used on top of the main `setTemplate`.

View File

@ -1,5 +1,8 @@
---
title: Form Security
summary: Ensure Forms are secure against Cross-Site Request Forgery attacks, bots and other malicious intent.
icon: shield-alt
---
# Form Security
@ -13,10 +16,10 @@ SilverStripe protect users against [Cross-Site Request Forgery](https://www.owas
random string generated by [SecurityToken](api:SilverStripe\Security\SecurityToken) to identify the particular user request vs a third-party forging fake
requests.
<div class="info" markdown="1">
[info]
For more information on Cross-Site Request Forgery, consult the [OWASP](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
website.
</div>
[/info]
The `SecurityToken` automatically added looks something like:
@ -47,10 +50,10 @@ $form = new Form(..);
$form->disableSecurityToken();
```
<div class="alert" markdown="1">
[alert]
Do not disable the SecurityID for forms that perform some modification to the users session. This will open your
application up to `CSRF` security holes.
</div>
[/alert]
## Strict Form Submission

View File

@ -1,5 +1,8 @@
---
title: Form Transformations
summary: Provide read-only and disabled views of your Form data.
icon: random
---
# Read-only and Disabled Forms

View File

@ -1,5 +1,7 @@
---
title: Tabbed Forms
summary: Find out how CMS interfaces use jQuery UI tabs to provide nested FormFields.
---
# Tabbed Forms
@ -7,17 +9,17 @@ SilverStripe's [FormScaffolder](api:SilverStripe\Forms\FormScaffolder) can autom
CMS and other scaffolded interfaces, it will output [TabSet](api:SilverStripe\Forms\TabSet) and [Tab](api:SilverStripe\Forms\Tab) objects and use jQuery Tabs to split
parts of the data model.
<div class="notice" markdown="1">
[notice]
All interfaces within the CMS such as [ModelAdmin](api:SilverStripe\Admin\ModelAdmin) and [LeftAndMain](api:SilverStripe\Admin\LeftAndMain) use tabbed interfaces by default.
</div>
[/notice]
When dealing with tabbed forms, modifying the fields in the form has a few differences. Each [Tab](api:SilverStripe\Forms\Tab) will be given a
name, and normally they all exist under the `Root` [TabSet](api:SilverStripe\Forms\TabSet).
<div class="notice" markdown="1">
[notice]
[TabSet](api:SilverStripe\Forms\TabSet) instances can contain child [Tab](api:SilverStripe\Forms\Tab) and further [TabSet](api:SilverStripe\Forms\TabSet) instances, however the CMS UI will only
display up to two levels of tabs in the interface.
</div>
[/notice]
## Adding a field to a tab

View File

@ -1,5 +1,7 @@
---
title: Common FormField type subclasses
summary: A table containing a list of the common FormField subclasses.
---
# Common FormField type subclasses

View File

@ -1,5 +1,7 @@
---
title: DateField
summary: How to format and use the DateField class.
---
# DateField
@ -52,9 +54,9 @@ DateField::create('MyDate')
->setDateFormat('dd/MM/yyyy');
```
<div class="info" markdown="1">
[info]
The formats are based on [ICU format](http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details).
</div>
[/info]
## Min and Max Dates
@ -90,9 +92,9 @@ $dateField->setDescription(_t(
$dateField->setAttribute('placeholder', $dateField->getDateFormat());
```
<div class="notice" markdown="1">
[notice]
Fields scaffolded through [DataObject::scaffoldCMSFields()](api:SilverStripe\ORM\DataObject::scaffoldCMSFields()) automatically have a description attached to them.
</div>
[/notice]
## API Documentation

View File

@ -1,5 +1,8 @@
---
title: Rich-text editing (WYSIWYG)
summary: SilverStripe's use and configuration of TinyMCE html editor.
summary: Silverstripe CMS's use and configuration of TinyMCE html editor.
icon: file-code
---
# Rich-text editing (WYSIWYG)
@ -83,14 +86,14 @@ in the framework (and the `cms` module in case you've got that installed).
There can be multiple configs, which should always be created / accessed using [HtmlEditorConfig::get()](api:SilverStripe\Forms\HTMLEditor\HtmlEditorConfig::get()). You can
then set the currently active config using `set_active()`.
<div class="info" markdown="1">
</div>
[info]
[/info]
<div class="notice" markdown='1'>
[notice]
Currently the order in which the `_config.php` files are executed depends on the module directory names. Execution
order is alphabetical, so if you set a TinyMCE option in the `aardvark/_config.php`, this will be overridden in
`vendor/silverstripe/framework/admin/_config.php` and your modification will disappear.
</div>
[/notice]
## Adding and removing capabilities
@ -107,11 +110,11 @@ use SilverStripe\Forms\HTMLEditor\HtmlEditorConfig;
HtmlEditorConfig::get('cms')->enablePlugins('media');
```
<div class="notice" markdown="1">
[notice]
This utilities the TinyMCE's `PluginManager::load` function under the hood (check the
[TinyMCE documentation on plugin loading](http://www.tinymce.com/wiki.php/API3:method.tinymce.AddOnManager.load) for
details).
</div>
[/notice]
Plugins and advanced themes can provide additional buttons that can be added (or removed) through the
configuration. Here is an example of adding a `ssmacron` button after the `charmap` button:
@ -130,11 +133,11 @@ Buttons can also be removed:
HtmlEditorConfig::get('cms')->removeButtons('tablecontrols', 'blockquote', 'hr');
```
<div class="notice" markdown="1">
[notice]
Internally [HtmlEditorConfig](api:SilverStripe\Forms\HTMLEditor\HtmlEditorConfig) uses the TinyMCE's `theme_advanced_buttons` option to configure these. See the
[TinyMCE documentation of this option](http://www.tinymce.com/wiki.php/Configuration:theme_advanced_buttons_1_n)
for more details.
</div>
[/notice]
### Setting options
@ -162,10 +165,10 @@ HtmlEditorConfig::get('cms')->setOption(
);
```
<div class="notice" markdown="1">
[notice]
The default setting for the CMS's `extended_valid_elements` we are overriding here can be found in
`vendor/silverstripe/admin/_config.php`.
</div>
[/notice]
## Writing custom plugins

View File

@ -1,5 +1,8 @@
---
title: GridField
summary: How to use the GridField class for managing tabular data.
icon: table
---
# GridField
@ -13,14 +16,14 @@ use SilverStripe\Forms\GridField\GridField;
$field = new GridField($name, $title, $list);
```
<div class="hint" markdown='1'>
[hint]
GridField can only be used with `$list` data sets that are of the type `SS_List` such as `DataList` or `ArrayList`.
</div>
[/hint]
<div class="notice" markdown="1">
[notice]
[GridField](api:SilverStripe\Forms\GridField\GridField) powers the automated data UI of [ModelAdmin](api:SilverStripe\Admin\ModelAdmin). For more information about `ModelAdmin` see the
[Customizing the CMS](/developer_guides/customising_the_admin_interface) guide.
</div>
[/notice]
Each `GridField` is built from a number of components grouped into the [GridFieldConfig](api:SilverStripe\Forms\GridField\GridFieldConfig). Without any components,
a `GridField` has almost no functionality. The `GridFieldConfig` instance and the attached [GridFieldComponent](api:SilverStripe\Forms\GridField\GridFieldComponent) are
@ -201,15 +204,15 @@ $gridField->setConfig($config);
Similar to `GridFieldConfig_Base` with the addition support of the ability to view a `GridFieldDetailForm` containing
a read-only view of the data record.
<div class="info" markdown="1">
[info]
The data row show must be a `DataObject` subclass. The fields displayed in the read-only view come from
`DataObject::getCMSFields()`.
</div>
[/info]
<div class="alert" markdown="1">
[alert]
The `DataObject` class displayed must define a `canView()` method that returns a boolean on whether the user can view
this record.
</div>
[/alert]
```php
@ -228,15 +231,15 @@ $gridField->setConfig($config);
Similar to `GridFieldConfig_RecordViewer` with the addition support to edit or delete each of the records.
<div class="info" markdown="1">
[info]
The data row show must be a `DataObject` subclass. The fields displayed in the edit view come from
`DataObject::getCMSFields()`.
</div>
[/info]
<div class="alert" markdown="1">
[alert]
Permission control for editing and deleting the record uses the `canEdit()` and `canDelete()` methods on the
`DataObject` object.
</div>
[/alert]
```php
@ -428,10 +431,10 @@ class MyAreaComponent implements GridField_HTMLProvider
```
<div class="notice" markdown="1">
[notice]
Please note that in templates, you'll need to escape the dollar sign on `\$DefineFragment`. These are specially
processed placeholders as opposed to native template syntax.
</div>
[/notice]
Now you can add other components into this area by returning them as an array from your
[GridFieldComponent::getHTMLFragments()](api:SilverStripe\Forms\GridField\GridFieldComponent::getHTMLFragments()) implementation:

View File

@ -0,0 +1,7 @@
---
title: Field Types
summary: More information about some of the core form fields
---
# Field Types
[CHILDREN]

View File

@ -1,4 +1,8 @@
---
title: How to Encapsulate Forms
summary: Learn how to move a form from a controller into its own class definition.
iconBrand: wpforms
---
# How to Encapsulate Forms

View File

@ -1,4 +1,8 @@
---
title: How to Create Lightweight Form
summary: Create a simple search form with Silverstripe CMS
iconBrand: wpforms
---
# How to Create Lightweight Form
@ -48,8 +52,8 @@ public function SearchForm()
`SearchForm.ss` will be executed within the scope of the `Form` object so has access to any of the methods and
properties on [Form](api:SilverStripe\Forms\Form) such as `$Fields` and `$Actions`.
<div class="notice">
[notice]
To understand more about Scope or the syntax for custom templates, read the [Templates](../../templates) guide.
</div>
[/notice]

View File

@ -1,4 +1,8 @@
---
title: Create a GridField Component
summary: Customise your GridField with a variety of add-ons.
icon: table
---
A single component often uses a number of interfaces.
### GridField_HTMLProvider

View File

@ -1,3 +1,7 @@
---
title: Create a GridField action provider
summary: Handle custom actions on your GridField
---
# How to add a custom action to a GridField row
You can add an action to the row(s) of a [GridField](/developer_guides/forms/field_types/gridfield), such as the built in edit or delete actions.

View File

@ -1,3 +1,9 @@
---
title: Simple contact form
summary: Create a form that submits a message via email
iconBrand: wpforms
---
# How to make a simple contact form
In this how-to, we'll explain how to set up a specific page type
@ -119,12 +125,12 @@ class ContactPageController extends PageController
```
<div class="hint" markdown="1">
[hint]
Caution: This form is prone to abuse by spammers,
since it doesn't enforce a rate limitation, or checks for bots.
We recommend to use a validation service like the ["recaptcha" module](http://www.silverstripe.org/recaptcha-module/)
for better security.
</div>
[/hint]
Any function that receives a form submission takes two arguments: the data passed to the form as an indexed array, and the form itself. In order to extract the data, you can either use functions on the form object to get the fields and query their values, or just use the raw data in the array. In the example above, we used the array, as it's the easiest way to get data without requiring the form fields to perform any special transformations.

View File

@ -0,0 +1,6 @@
---
title: How To's
---
# How To's: Forms
[CHILDREN]

View File

@ -1,6 +1,9 @@
---
title: Forms
summary: Capture user information through Forms. This guide will work through how to create SilverStripe forms, adding and modifying fields and how to handle form submissions.
introduction: This guide will work through how to create SilverStripe forms, adding and modifying fields and how to handle form submissions.
iconBrand: wpforms
---
The [Form](api:SilverStripe\Forms\Form) class provides a way to create interactive forms in your web application with very little effort.
SilverStripe handles generating the correct semantic HTML markup for the form and each of the fields, as well as the
@ -10,7 +13,7 @@ framework for dealing with submissions and validation.
## FormField Documentation
[CHILDREN Folder="Fields"]
[CHILDREN Folder="Field_types"]
## How to's

View File

@ -1,5 +1,8 @@
---
title: Configuration API
summary: SilverStripe's YAML based Configuration API for setting runtime configuration.
summary: Silverstripe CMS's YAML based Configuration API for setting runtime configuration.
icon: laptop-code
---
# Configuration API
@ -15,9 +18,9 @@ properties API:
- Configuration is normally set once during initialization and then not changed.
- Configuration is normally set by a knowledgeable technical user, such as a developer, not the end user.
<div class="notice" markdown="1">
[notice]
For providing content editors or CMS users a place to manage configuration see the [SiteConfig](siteconfig) module.
</div>
[/notice]
## Configuration Properties
@ -139,10 +142,10 @@ echo implode(', ', MyClass::config()->option_one);
```
<div class="notice" markdown="1">
[notice]
There is no way currently to restrict read or write access to any configuration property, or influence/check the values
being read or written.
</div>
[/notice]
## Configuration Values
@ -173,11 +176,11 @@ Class\With\Array\Config:
- If the value is not an array, the highest priority value is used without any attempt to merge
<div class="alert" markdown="1">
[alert]
The exception to this is "false-ish" values - empty arrays, empty strings, etc. When merging a non-false-ish value with
a false-ish value, the result will be the non-false-ish value regardless of priority. When merging two false-ish values
the result will be the higher priority false-ish value.
</div>
[/alert]
The locations that configuration values are taken from in highest -> lowest priority order are:
@ -188,10 +191,10 @@ order, where the item that is latest is highest priority)
- The composite configuration value of the parent class of this class
- Any static set on an "additional static source" class (such as an extension) named the same as the name of the property
<div class="notice">
[notice]
It is an error to have mixed types of the same named property in different locations. An error will not necessarily
be raised due to optimizations in the lookup code.
</div>
[/notice]
## Configuration Masks
@ -214,18 +217,18 @@ bitwise `|` operator.
## Configuration YAML Syntax and Rules
<div class="alert" markdown="1">
[alert]
As of Silverstripe 4, YAML files can no longer be placed any deeper than 2 directories deep. As this was an unintended bug, this change will only affect you if you nest your modules deeper than the top level of your project.
</div>
[/alert]
Each module can have a directory immediately underneath the main module directory called `_config/`. Inside this
directory you can add YAML files that contain values for the configuration system.
<div class="info" markdown="1">
[info]
The name of the files within the applications `_config` directly are arbitrary. Our examples use
`app/_config/app.yml` but you can break this file down into smaller files, or clearer patterns like `extensions.yml`,
`email.yml` if you want. For add-on's and modules, it is recommended that you name them with `<module_name>.yml`.
</div>
[/info]
The structure of each YAML file is a series of headers and values separated by YAML document separators.
@ -242,9 +245,9 @@ SilverStripe\Control\Director:
---
```
<div class="info">
[info]
If there is only one set of values the header can be omitted.
</div>
[/info]
Each value section of a YAML file has:
@ -311,10 +314,10 @@ after value sections with a name of `rootroutes`. However because `\*` has three
In this case `\*` means "every value section _except_ ones that have a fragment name of rootroutes".
<div class="alert" markdown="1">
[alert]
It is possible to create chains that are unsolvable. For instance, A must be before B, B must be before C, C must be
before A. In this case you will get an error when accessing your site.
</div>
[/alert]
## Exclusionary rules
@ -371,11 +374,11 @@ Only:
---
```
<div class="alert" markdown="1">
[alert]
When you have more than one rule for a nested fragment, they're joined like
`FRAGMENT_INCLUDED = (ONLY && ONLY) && !(EXCEPT && EXCEPT)`.
That is, the fragment will be included if all Only rules match, except if all Except rules match.
</div>
[/alert]
## Unit tests

View File

@ -1,5 +1,8 @@
---
title: SiteConfig
summary: Content author configuration through the SiteConfig module.
icon: laptop-code
---
# SiteConfig
@ -72,10 +75,10 @@ Silverstripe\SiteConfig\SiteConfig:
- CustomSiteConfig
```
<div class="notice" markdown="1">
[notice]
After adding the class and the YAML change, make sure to rebuild your database by visiting http://example.com/dev/build.
You may also need to reload the screen with a `?flush=1` i.e http://example.com/admin/settings?flush=1.
</div>
[/notice]
You can define as many extensions for `SiteConfig` as you need. For example, if you're developing a module and want to
provide the users a place to configure settings then the `SiteConfig` panel is the place to go it.

View File

@ -1,5 +1,8 @@
---
title: Environment Variables
summary: Site configuration variables such as database connection details, environment type and remote login information.
icon: dollar-sign
---
# Environment Variables

View File

@ -1,5 +1,8 @@
---
title: Configuration
summary: SilverStripe provides several ways to store and modify your application settings. Learn about site wide settings and the YAML based configuration system.
introduction: SilverStripe provides several ways to store and modify your application settings. Learn about site wide settings and the YAML based configuration system.
icon: laptop-code
---
[CHILDREN]

View File

@ -1,5 +1,8 @@
---
title: Modules
summary: Extend core functionality with modules.
icon: code
---
# Modules
@ -63,9 +66,9 @@ Composer is using [version constraints](https://getcomposer.org/doc/articles/ver
To lock down to a specific version, branch or commit, read up on
["lock" files](http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file).
<div class="notice" markdown="1">
[notice]
After you add or remove modules, make sure you rebuild the database, class and configuration manifests by going to http://yoursite.com/dev/build?flush=1
</div>
[/notice]
## Publishing your own SilverStripe module

View File

@ -1,5 +1,8 @@
---
title: Extensions
summary: Extensions and DataExtensions let you modify and augment objects transparently.
icon: code
---
# Extensions and DataExtensions
@ -10,10 +13,10 @@ trait applied within core, modules or even their own code to make it more reusab
Extensions are defined as subclasses of either [DataExtension](api:SilverStripe\ORM\DataExtension) for extending a [DataObject](api:SilverStripe\ORM\DataObject) subclass or
the [Extension](api:SilverStripe\Core\Extension) class for non DataObject subclasses (such as [Controller](api:SilverStripe\Control\Controller))
<div class="info" markdown="1">
[info]
For performance reasons a few classes are excluded from receiving extensions, including `ViewableData`
and `RequestHandler`. You can still apply extensions to descendants of these classes.
</div>
[/info]
**app/code/extensions/MyMemberExtension.php**
@ -36,9 +39,9 @@ class MyMemberExtension extends DataExtension
}
```
<div class="info" markdown="1">
[info]
Convention is for extension class names to end in `Extension`. This isn't a requirement but makes it clearer
</div>
[/info]
After this class has been created, it does not yet apply it to any object. We need to tell SilverStripe what classes
we want to add the `MyMemberExtension` too. To activate this extension, add the following via the [Configuration API](../configuration).
@ -173,9 +176,9 @@ class MyMemberExtension extends DataExtension
}
```
<div class="info" markdown="1">
[info]
The `$validator` parameter is passed by reference, as it is an object.
</div>
[/info]
Another common example of when you will want to modify a method is to update the default CMS fields for an object in an
extension. The `CMS` provides a `updateCMSFields` Extension Hook to tie into.
@ -207,10 +210,10 @@ class MyMemberExtension extends DataExtension
}
```
<div class="notice" markdown="1">
[notice]
If you're providing a module or working on code that may need to be extended by other code, it should provide a *hook*
which allows an Extension to modify the results.
</div>
[/notice]
```php
@ -269,10 +272,10 @@ callback to be executed immediately before and after `extend()` is called on ext
This is useful in many cases where working with modules such as `Translatable` which operate on `DataObject` fields
that must exist in the `FieldList` at the time that `$this->extend('UpdateCMSFields')` is called.
<div class="notice" markdown='1'>
[notice]
Please note that each callback is only ever called once, and then cleared, so multiple extensions to the same function
require that a callback is registered each time, if necessary.
</div>
[/notice]
Example: A class that wants to control default values during object initialization. The code needs to assign a value
if not specified in `self::$defaults`, but before extensions have been called:
@ -293,9 +296,9 @@ public function __construct()
Example 2: User code can intervene in the process of extending cms fields.
<div class="notice" markdown="1">
[notice]
This method is preferred to disabling, enabling, and calling field extensions manually.
</div>
[/notice]
```php
@ -341,12 +344,12 @@ class CustomisedSomeExtension extends SomeExtension
}
```
<div class="notice" markdown="1">
[notice]
Please note that modifications such as this should be done in YAML configuration only. It is not recommended
to use `Config::modify()->set()` to adjust the implementation class name of an extension after the configuration
manifest has been loaded, and may not work consistently due to the "extra methods" cache having already been
populated.
</div>
[/notice]
## Related Lessons

View File

@ -1,5 +1,8 @@
---
title: Shortcodes
summary: Flexible content embedding
icon: code
---
# Shortcodes

View File

@ -1,5 +1,8 @@
---
title: Injector
summary: Introduction to using Dependency Injection within SilverStripe.
icon: code
---
# Injector

View File

@ -1,5 +1,8 @@
---
title: Aspects
summary: Introduction to using aspect-oriented programming with SilverStripe.
icon: code
---
# Aspects
@ -10,9 +13,9 @@ Aspect oriented programming is the idea that some logic abstractions can be appl
> functions from the main program's business logic. It aims to increase modularity by allowing the separation of
> cross-cutting concerns, forming a basis for aspect-oriented software development.
<div class="notice" markdown="1">
[notice]
[Wikipedia](http://en.wikipedia.org/wiki/Aspect-oriented_programming) provides a much more in-depth explanation.
</div>
[/notice]
In the context of the SilverStripe [Dependency Injector](injector), Aspects are achieved thanks to PHP's `__call` magic
method combined with the `Proxy` Design Pattern.
@ -38,10 +41,10 @@ specific database server, whereas all read queries can be handled by slave serve
A simplified implementation might look like the following.
<div class="notice" markdown="1">
[notice]
This doesn't cover all cases used by SilverStripe so is not a complete solution, more just a guide to how it would be
used.
</div>
[/notice]
**app/code/MySQLWriteDbAspect.php**

View File

@ -1,5 +1,8 @@
---
title: Custom Templates
summary: Override templates from core and modules in your application
icon: code
---
# Custom Templates

View File

@ -1,4 +1,8 @@
---
title: How to Publish a SilverStripe module
summary: Have you created some work you think others can use? Turn it into a module and share it.
icon: rocket
---
# How to Publish a SilverStripe module.
@ -86,9 +90,9 @@ Say you have a module which supports SilverStripe 3.0. A new release of this mod
in SilverStripe 3.1. In this case, you would create a new branch for the 3.0 compatible code base of your module. This
allows you to continue fixing bugs on this older release branch.
<div class="info" markdown="1">
[info]
As a convention, the `master` branch of your module should always work with the `master` branch of SilverStripe.
</div>
[/info]
Other branches should be created on your module as needed if they're required to support specific SilverStripe releases.

View File

@ -1,4 +1,8 @@
---
title: How to Create a Google Maps Shortcode
summary: Learn how to embed a Google map in the WYSIWYG editor with a simple shortcode
icon: map
---
# How to Create a Google Maps Shortcode

View File

@ -1,3 +1,8 @@
---
title: Track member logins
summary: Keep a log in the database of who logs in and when
icon: user-friends
---
# Howto: Track Member Logins
Sometimes its good to know how active your users are,

View File

@ -0,0 +1,6 @@
---
title: How To's
---
# How To's: Extending Silverstripe
[CHILDREN]

View File

@ -1,6 +1,9 @@
---
title: Extending SilverStripe
summary: Understand the ways to modify the built-in functionality through Extensions, Subclassing and Dependency Injection.
introduction: SilverStripe is easily extensible to meet custom application requirements. This guide covers the wide range of API's to modify built-in functionality and make your own code easily extensible.
icon: code
---
No two applications are ever going to be the same and SilverStripe is built with this in mind. The core framework
includes common functionality and default behaviors easily complemented with add-ons such as modules, widgets and

View File

@ -1,5 +1,7 @@
---
title: Unit and Integration Testing
summary: Test models, database logic and your object methods.
---
# Unit and Integration Testing
@ -36,28 +38,28 @@ class PageTest extends SapphireTest
}
```
<div class="info" markdown="1">
[info]
Tests for your application should be stored in the `app/tests` directory. Test cases for add-ons should be stored in
the `(modulename)/tests` directory.
Test case classes should end with `Test` (e.g `PageTest`) and test methods must start with `test` (e.g `testMyMethod`).
Ensure you [import](http://php.net/manual/en/language.namespaces.importing.php#example-252) any classes you need for the test, including `SilverStripe\Dev\SapphireTest` or `SilverStripe\Dev\FunctionalTest`.
</div>
[/info]
A SilverStripe unit test is created by extending one of two classes, [SapphireTest](api:SilverStripe\Dev\SapphireTest) or [FunctionalTest](api:SilverStripe\Dev\FunctionalTest).
[SapphireTest](api:SilverStripe\Dev\SapphireTest) is used to test your model logic (such as a `DataObject`), and [FunctionalTest](api:SilverStripe\Dev\FunctionalTest) is used when
you want to test a `Controller`, `Form` or anything that requires a web page.
<div class="info" markdown="1">
[info]
`FunctionalTest` is a subclass of `SapphireTest` so will inherit all of the behaviors. By subclassing `FunctionalTest`
you gain the ability to load and test web pages on the site.
`SapphireTest` in turn, extends `PHPUnit_Framework_TestCase`. For more information on `PHPUnit_Framework_TestCase` see
the [PHPUnit](http://www.phpunit.de) documentation. It provides a lot of fundamental concepts that we build on in this
documentation.
</div>
[/info]
## Test Databases and Fixtures
@ -65,15 +67,15 @@ SilverStripe tests create their own database when the test starts and fixture fi
connection details you provide for the main website. The new `ss_tmp` database does not copy what is currently in your
application database. To provide seed data use a [Fixture](fixtures) file.
<div class="alert" markdown="1">
[alert]
As the test runner will create new databases for the tests to run, the database user should have the appropriate
permissions to create new databases on your server.
</div>
[/alert]
<div class="notice" markdown="1">
[notice]
The test database is rebuilt every time one of the test methods is run and is removed afterwards. If the test is interrupted, the database will not be removed. Over time, you may have several hundred test
databases on your machine. To get rid of them, run `sake dev/tasks/CleanupTestDatabasesTask`.
</div>
[/notice]
## Custom PHPUnit Configuration

View File

@ -1,5 +1,7 @@
---
title: Functional Testing
summary: Test controllers, forms and HTTP responses.
---
# Functional Testing
@ -90,9 +92,9 @@ Assert that the most recently queried page contains a number of content tags spe
selector will be applied to the HTML of the most recent page. The content of every matching tag will be examined. The
assertion fails if one of the expectedMatches fails to appear.
<div class="notice" markdown="1">
[notice]
`&amp;nbsp;` characters are stripped from the content; make sure that your assertions take this into account.
</div>
[/notice]
### assertExactHTMLMatchBySelector
```php
@ -105,9 +107,9 @@ Assert that the most recently queried page contains a number of content tags spe
selector will be applied to the HTML of the most recent page. The full HTML of every matching tag will be examined. The
assertion fails if one of the expectedMatches fails to appear.
<div class="notice" markdown="1">
[notice]
`&amp;nbsp;` characters are stripped from the content; make sure that your assertions take this into account.
</div>
[/notice]
## Related Documentation

View File

@ -1,5 +1,7 @@
---
title: Behavior Testing
summary: Describe how your application should behave in plain text and run tests in a browser.
---
# Behavior Testing

View File

@ -1,5 +1,7 @@
---
title: Fixtures
summary: Populate test databases with fake seed data.
---
# Fixtures
@ -126,19 +128,19 @@ seen by the fields prefixed with `=>`.
Each one of our Players has a relationship to a Team, this is shown with the `Team` field for each `Player` being set
to `=>Team.` followed by a team name.
<div class="info" markdown="1">
[info]
Take the player John in our example YAML, his team is the Hurricanes which is represented by `=>Team.hurricanes`. This
sets the `has_one` relationship for John with with the `Team` object `hurricanes`.
</div>
[/info]
<div class="hint" markdown='1'>
[hint]
Note that we use the name of the relationship (Team), and not the name of the
database field (TeamID).
</div>
[/hint]
<div class="hint" markdown='1'>
[hint]
Also be aware the target of a relationship must be defined before it is referenced, for example the `hurricanes` team must appear in the fixture file before the line `Team: =>Team.hurricanes`.
</div>
[/hint]
This style of relationship declaration can be used for any type of relationship (i.e `has_one`, `has_many`, `many_many`).
@ -180,10 +182,10 @@ $team->write();
$team->Players()->add($john);
```
<div class="notice" markdown="1">
[notice]
As the YAML fixtures will call `write`, any `onBeforeWrite()` or default value logic will be executed as part of the
test.
</div>
[/notice]
### Fixtures for namespaced classes
@ -201,9 +203,9 @@ MyProject\Model\Team:
Players: =>MyProject\Model\Player.john
```
<div class="notice" markdown="1">
[notice]
If your tests are failing and your database has table names that follow the fully qualified class names, you've probably forgotten to implement `private static $table_name = 'Player';` on your namespaced class. This property was introduced in SilverStripe 4 to reduce data migration work. See [DataObject](api:SilverStripe\ORM\DataObject) for an example.
</div>
[/notice]
### Defining many_many_extraFields
@ -277,9 +279,9 @@ While manually defined fixtures provide full flexibility, they offer very little
Alternatively, you can use the [FixtureFactory](api:SilverStripe\Dev\FixtureFactory) class, which allows you to set default values, callbacks on object
creation, and dynamic/lazy value setting.
<div class="hint" markdown='1'>
[hint]
`SapphireTest` uses `FixtureFactory` under the hood when it is provided with YAML based fixtures.
</div>
[/hint]
The idea is that rather than instantiating objects directly, we'll have a factory class for them. This factory can have
*blueprints* defined on it, which tells the factory how to instantiate an object of a specific type. Blueprints need a
@ -306,10 +308,10 @@ $obj = $factory->createObject('Team', 'hurricanes', [
]);
```
<div class="warning" markdown="1">
[warning]
It is important to remember that fixtures are referenced by arbitrary identifiers ('hurricanes'). These are internally
mapped to their database identifiers.
</div>
[/warning]
After we've created this object in the factory, `getId` is used to retrieve it by the identifier.

View File

@ -1,4 +1,7 @@
---
title: Testing Glossary
summary: All the jargon you need to be a bonafide testing guru
---
<dl>
<dt>Assertion<dd>A predicate statement that must be true when a test runs.

View File

@ -1,4 +1,7 @@
---
title: How to write a SapphireTest
summary: Learn the basics of unit testing in Silverstripe
---
# How to write a SapphireTest
@ -48,17 +51,17 @@ Firstly we define a static `$fixture_file`, this should point to a file that rep
represented as a YAML [Fixture](../fixtures). When our test is run, the data from this file will be loaded into a test
database and discarded at the end of the test.
<div class="notice" markdown="1">
[notice]
The `fixture_file` property can be path to a file, or an array of strings pointing to many files. The path must be
absolute from your website's root folder.
</div>
[/notice]
The second part of our class is the `testURLGeneration` method. This method is our test. When the test is executed,
methods prefixed with the word `test` will be run.
<div class="notice" markdown="1">
[notice]
The test database is rebuilt every time one of these methods is run.
</div>
[/notice]
Inside our test method is the `objFromFixture` method that will generate an object for us based on data from our fixture
file. To identify to the object, we provide a class name and an identifier. The identifier is specified in the YAML file
@ -69,9 +72,9 @@ The final part of our test is an assertion command, `assertEquals`. An assertion
in our test methods (in this case we are testing if two values are equal). A test method can have more than one
assertion command, and if any one of these assertions fail, so will the test method.
<div class="info" markdown="1">
[info]
For more information on PHPUnit's assertions see the [PHPUnit manual](http://www.phpunit.de/manual/current/en/api.html#api.assert).
</div>
[/info]
## Related Documentation

View File

@ -1,4 +1,7 @@
---
title: How to write a FunctionalTest
summary: Expand your testing capabilities with integrations tests
---
# How to Write a FunctionalTest

View File

@ -1,4 +1,8 @@
---
title: How to use a FixtureFactory
summary: Provide context to your tests with database fixtures
icon: industry
---
# How to use a FixtureFactory

View File

@ -1,4 +1,8 @@
---
title: How to test emails within unit tests
summary: Test email functionality without ever hitting an inbox
icon: envelope
---
# Testing Email within Unit Tests

View File

@ -0,0 +1,6 @@
---
title: How To's
---
# How To's: Testing
[CHILDREN]

View File

@ -1,4 +1,7 @@
---
title: Testing
summary: Deploy robust applications by bundling Unit and Behavior tests with your application code and modules.
---
# Unit and Integration Testing

View File

@ -1,5 +1,8 @@
---
title: Environment Types
summary: Configure your SilverStripe environment to define how your web application behaves.
icon: exclamation-circle
---
# Environment Types
@ -14,11 +17,11 @@ When developing your websites, adding page types or installing modules you shoul
you will see full error back traces and view the development tools without having to be logged in as an administrator
user.
<div class="alert" markdown="1">
[alert]
**dev mode should not be enabled long term on live sites for security reasons**. In dev mode by outputting back traces
of function calls a hacker can gain information about your environment (including passwords) so you should use dev mode
on a public server very carefully.
</div>
[/alert]
### Test Mode
@ -48,9 +51,9 @@ When using CGI/FastCGI with Apache, you will have to add the `RewriteRule .* - [
All error messages are suppressed from the user and the application is in it's most *secure* state.
<div class="alert">
[alert]
Live sites should always run in live mode. You should not run production websites in dev mode.
</div>
[/alert]
## Checking Environment Type

View File

@ -1,5 +1,8 @@
---
title: Logging and Error Handling
summary: Trap, fire and report diagnostic logs, user exceptions, warnings and errors.
icon: exclamation-circle
---
# Logging and Error Handling
@ -249,11 +252,11 @@ SilverStripe\Core\Injector\Injector:
Body: "The website server has not been able to respond to your request"
```
<div class="info" markdown="1">
[info]
In addition to SilverStripe-integrated logging, it is advisable to fall back to PHP's native logging functionality. A
script might terminate before it reaches the SilverStripe error handling, for example in the case of a fatal error. Make
sure `log_errors` and `error_log` in your PHP ini file are configured.
</div>
[/info]
## Replacing default implementations

View File

@ -1,3 +1,7 @@
---
title: URL Variable tools
summary: Useful debugging tools you can use right in the browser
---
# URL Variable Tools
## Introduction

View File

@ -1,5 +1,8 @@
---
title: Template debugging
summary: Track down which template rendered a piece of html
icon: bug
---
# Debugging templates

View File

@ -1,5 +1,8 @@
---
title: Debugging
summary: Learn how to identify errors in your application and best practice for logging application errors.
icon: bug
---
# Debugging
SilverStripe can be a large and complex framework to debug, but there are ways to make debugging less painful. In this

View File

@ -1,5 +1,8 @@
---
title: Partial Caching
summary: Cache SilverStripe templates to reduce database queries.
icon: tachometer-alt
---
# Partial Caching
@ -76,10 +79,10 @@ or edited:
<% cached 'categorylist', $List('Category').max('LastEdited'), $List('Category').count() %>
```
<div class="notice" markdown="1">
[notice]
Note the use of both `.max('LastEdited')` and `.count()` - this takes care of both the case where an object has been
edited since the cache was last built, and also when an object has been deleted since the cache was last built.
</div>
[/notice]
We can also calculate aggregates on relationships. The logic for that can get a bit complex, so we can extract that on
to the controller so it's not cluttering up our template.
@ -231,10 +234,10 @@ could also write the last example as:
<% end_cached %>
```
<div class="warning" markdown="1">
[warning]
Currently a nested cache block can not be contained within an if or loop block. The template engine will throw an error
letting you know if you've done this. You can often get around this using aggregates or by un-nesting the block.
</div>
[/warning]
Failing example:

View File

@ -1,3 +1,8 @@
---
title: Caching
summary: Optimise performance by caching expensive processes
icon: tachometer-alt
---
# Caching
## Overview
@ -39,12 +44,12 @@ SilverStripe\Core\Injector\Injector:
namespace: "myCache"
```
<div class="alert" markdown="1">
[alert]
Please note that if you have the `silverstripe/versioned` module installed (automatically installed by the
`silverstripe/cms` module), caches will automatically be segmented by current “stage”. This ensures that
any content written to the cache in the _draft_ reading mode isnt accidentally exposed in the _live_ reading mode.
Please read the [versioned cache segmentation](#versioned-cache-segmentation) section for more information.
</div>
[/alert]
Cache objects are instantiated through a [CacheFactory](SilverStripe\Core\Cache\CacheFactory),
which determines which cache adapter is used (see "Adapters" below for details).

View File

@ -1,5 +1,8 @@
---
title: HTTP Cache Headers
summary: Set the correct HTTP cache headers for your responses.
icon: tachometer-alt
---
# HTTP Cache Headers

View File

@ -1,5 +1,8 @@
---
title: Profiling
summary: Identify bottlenecks within your application.
icon: tachometer-alt
---
# Profiling

View File

@ -1,5 +1,7 @@
---
title: Static Publishing
summary: Export your web pages as static HTML and serve the web like it's 1999.
---
# Static Publishing
@ -7,10 +9,10 @@ One of the best ways to get the top performance out of SilverStripe is to bypass
time, connecting to the database and formatting your templates. This is only appropriate approach on web pages that
have completely static content.
<div class="info" markdown="1">
[info]
If you want to cache part of a page, or your site has interactive elements such as forms, then
[Partial Caching](partial_caching) is more suitable.
</div>
[/info]
By publishing the page as HTML it's possible to run SilverStripe from behind a corporate firewall, on a low performance
server or serve millions of hits an hour without expensive hardware.

View File

@ -1,5 +1,8 @@
---
title: Resource Usage
summary: Manage SilverStripe's memory footprint and CPU usage.
icon: tachometer-alt
---
# Resource Usage
@ -10,18 +13,18 @@ These limits are defined through `memory_limit` and `max_execution_time` in the
overwritten through `ini_set()`, unless PHP is running with the [Suhoshin Patches](http://www.hardened-php.net/)
or in "[safe mode](http://php.net/manual/en/features.safe-mode.php)".
<div class="alert" markdown="1">
[alert]
Most shared hosting providers will have maximum values that can't be altered.
</div>
[/alert]
For certain tasks like synchronizing a large `assets/` folder with all file and folder entries in the database, more
resources are required temporarily. In general, we recommend running resource intensive tasks through the
[command line](../cli), where configuration defaults for these settings are higher or even unlimited.
<div class="info" markdown="1">
[info]
SilverStripe can request more resources through `Environment::increaseMemoryLimitTo()` and
`Environment::increaseTimeLimitTo()` functions.
</div>
[/info]
```php
use SilverStripe\Core\Environment;

View File

@ -1,6 +1,9 @@
---
title: Performance
summary: Make your applications faster by learning how to write more scalable code and ways to cache your important information.
introduction: Make your applications faster by learning how to write more scalable code and ways to cache your important information.
icon: tachometer-alt
---
The following guide describes the common ways to speed your SilverStripe website up. The general rules for getting
the best performance out of SilverStripe include running the latest versions of PHP alongside a

View File

@ -1,4 +1,8 @@
---
title: Members
summary: Learn how logged in users are managed in Silverstripe CMS
icon: user
---
# Member
@ -26,10 +30,10 @@ if( $member = Security::getCurrentUser() ) {
## Subclassing
<div class="warning" markdown="1">
[warning]
This is the least desirable way of extending the [Member](api:SilverStripe\Security\Member) class. It's better to use [DataExtension](api:SilverStripe\ORM\DataExtension)
(see below).
</div>
[/warning]
You can define subclasses of [Member](api:SilverStripe\Security\Member) to add extra fields or functionality to the built-in membership system.

View File

@ -1,3 +1,8 @@
---
title: Access Control
summary: Restrict CMS access to specific groups of users
icon: user-lock
---
# Access Control and Page Security
There is a fairly comprehensive security mechanism in place for SilverStripe. If you want to add premium content to your

View File

@ -1,3 +1,8 @@
---
title: Permissions
summary: Customise the permission system in Silverstripe
icon: lock
---
# User Permissions
## Introduction

View File

@ -1,5 +1,8 @@
---
title: Authentication
summary: Explains SilverStripe's Authentication options and custom authenticators.
icon: users-cog
---
# Authentication

View File

@ -1,3 +1,8 @@
---
title: Security
summary: Learn how to minimise vulnerabilities in your code
icon: user-secret
---
# Security
## Introduction
@ -99,10 +104,10 @@ $members = Member::get()->where(['"Name" = ?' => $_GET['name']]);
$members = Member::get()->where(sprintf('"Name" = %s', Convert::raw2sql($_GET['name'], true)));
```
<div class="warning" markdown='1'>
[warning]
It is NOT good practice to "be sure" and convert the data passed to the functions above manually. This might
result in *double escaping* and alters the actually saved data (e.g. by adding slashes to your content).
</div>
[/warning]
### Manual escaping
@ -201,10 +206,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'>
[notice]
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>
[/notice]
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".

View File

@ -1,5 +1,8 @@
---
title: Rate Limiting
summary: SilverStripe's in built rate limiting features
icon: tachometer-alt
---
# Rate Limiting

View File

@ -1,5 +1,8 @@
---
title: Personal Data
summary: How the SilverStripe CMS deals with data privacy
icon: user-ninja
---
# Personal Data

View File

@ -1,4 +1,8 @@
---
title: Security
summary: This guide covers user authentication, the permission system and how to secure your code against malicious behaviors
icon: user-shield
---
# Security and User Authentication

View File

@ -1,4 +1,8 @@
---
title: Email
summary: Send HTML and plain text email from your SilverStripe application.
icon: envelope-open
---
# Email
@ -65,11 +69,11 @@ $email = new Email($from, $to, $subject, $body);
$email->send();
```
<div class="info" markdown="1">
[info]
The default HTML template for emails is named `GenericEmail` and is located in `vendor/silverstripe/framework/templates/SilverStripe/Email/`.
To customise this template, copy it to the `app/templates/Email/` folder or use `setHTMLTemplate` when you create the
`Email` instance.
</div>
[/info]
### Templates
@ -106,10 +110,10 @@ if ($email->send()) {
```
<div class="alert" markdown="1">
[alert]
As we've added a new template file (`MyCustomEmail`) make sure you clear the SilverStripe cache for your changes to
take affect.
</div>
[/alert]
#### Custom plain templates
@ -143,10 +147,10 @@ SilverStripe\Control\Email\Email:
support@example.com: 'Support team'
```
<div class="alert" markdown="1">
[alert]
Remember, setting a `from` address that doesn't come from your domain (such as the users email) will likely see your
email marked as spam. If you want to send from another address think about using the `setReplyTo` method.
</div>
[/alert]
## Redirecting Emails
@ -196,9 +200,9 @@ $email = new Email(...);
$email->getSwiftMessage()->getHeaders()->addTextHeader('HeaderName', 'HeaderValue');
```
<div class="info" markdown="1">
[info]
See this [Wikipedia](http://en.wikipedia.org/wiki/E-mail#Message_header) entry for a list of header names.
</div>
[/info]
## Disabling Emails

View File

@ -1,3 +1,8 @@
---
title: CSV Import
summary: Load data into your Silverstripe database in bulk
icon: upload
---
# Import CSV data
## Introduction

View File

@ -1,5 +1,8 @@
---
title: RSS Feed
summary: Output records from your database as an RSS Feed.
icon: rss
---
# RSS Feed
@ -10,10 +13,10 @@ your current staff members, comments or any other custom [DataObject](api:Silver
logical limitation here is that every item in the RSS-feed should be accessible through a URL on your website, so it's
advisable to just create feeds from subclasses of [SiteTree](api:SilverStripe\CMS\Model\SiteTree).
<div class="warning" markdown="1">
[warning]
If you wish to generate an RSS feed that contains a [DataObject](api:SilverStripe\ORM\DataObject), ensure you define a `AbsoluteLink` method on
the object.
</div>
[/warning]
## Usage
@ -99,9 +102,9 @@ class PageController extends ContentController
DataObjects can be rendered in the feed as well, however, since they aren't explicitly [SiteTree](api:SilverStripe\CMS\Model\SiteTree) subclasses we
need to include a function `AbsoluteLink` to allow the RSS feed to link through to the item.
<div class="info">
[info]
If the items are all displayed on a single page you may simply hard code the link to point to a particular page.
</div>
[/info]
Take an example, we want to create an RSS feed of all the `Players` objects in our site. We make sure the `AbsoluteLink`
method is defined and returns a string to the full website URL.
@ -211,9 +214,9 @@ public function players()
}
```
<div class="warning">
[warning]
As we've added a new template (PlayersRss.ss) make sure you clear your SilverStripe cache.
</div>
[/warning]
## API Documentation

View File

@ -1,4 +1,8 @@
---
title: Import CSV Data through a Controller
summary: Data importing through the frontend
icon: upload
---
# Import CSV Data through a Controller
@ -75,7 +79,7 @@ class MyController extends Controller
}
```
<div class="alert" markdown="1">
[alert]
This interface is not secured, consider using [Permission::check()](api:SilverStripe\Security\Permission::check()) to limit the controller to users with certain
access rights.
</div>
[/alert]

View File

@ -1,4 +1,8 @@
---
title: A custom CSVBulkLoader instance
summary: Customise your data importing
icon: upload
---
# How to: A custom CSVBulkLoader instance

View File

@ -0,0 +1,6 @@
---
title: How To's
---
# How To's: Integration and Web Services
[CHILDREN]

View File

@ -1,5 +1,7 @@
---
summary: Integrate other web services within your application or make your SilverStripe data available.
introduction: Integrate other web services within your application or make your SilverStripe data available.
title: Integration and Web Services
---
[CHILDREN]

View File

@ -1,5 +1,8 @@
---
title: Scaffolding with SearchContext
summary: Configure the search form within ModelAdmin using the SearchContext class.
icon: search
---
# SearchContext
@ -10,9 +13,9 @@ search parameters and an object class it acts on.
The default output of a [SearchContext](api:SilverStripe\ORM\Search\SearchContext) is either a [SQLSelect](api:SilverStripe\ORM\Queries\SQLSelect) object for further refinement, or a
[DataObject](api:SilverStripe\ORM\DataObject) instance.
<div class="notice" markdown="1">
[notice]
[SearchContext](api:SilverStripe\ORM\Search\SearchContext) is mainly used by [ModelAdmin](/developer_guides/customising_the_admin_interface/modeladmin).
</div>
[/notice]
## Usage
@ -74,15 +77,15 @@ class MyDataObject extends DataObject
}
```
<div class="notice" markdown="1">
[notice]
See the [SearchFilter](../model/searchfilters) documentation for more information about filters to use such as the
`GreaterThanFilter`.
</div>
[/notice]
<div class="notice" markdown="1">
[notice]
In case you need multiple contexts, consider name-spacing your request parameters by using `FieldList->namespace()` on
the `$fields` constructor parameter.
</div>
[/notice]
### Generating a search form from the context

View File

@ -1,5 +1,8 @@
---
title: Fulltext Search
summary: Fulltext search allows sophisticated searching on text content.
icon: search
---
# FulltextSearchable
@ -7,11 +10,11 @@ Fulltext search allows advanced search criteria for searching words within a tex
Fulltext search can be achieved using the built-in [MySQLDatabase](api:SilverStripe\ORM\Connect\MySQLDatabase) class a more powerful wrapper for Fulltext
search is provided through a module.
<div class="notice" markdown="1">
[notice]
See the [FulltextSearch Module](https://github.com/silverstripe-labs/silverstripe-fulltextsearch/). This module provides
a high level wrapper for running advanced search services such as Solr, Lucene or Sphinx in the backend rather than
`MySQL` search.
</div>
[/notice]
## Adding Fulltext Support to MySQLDatabase
@ -36,11 +39,11 @@ class MyDataObject extends DataObject
The [FulltextSearchable](api:SilverStripe\ORM\Search\FulltextSearchable) extension will add the correct `Fulltext` indexes to the data model.
<div class="alert" markdown="1">
[alert]
The [SearchForm](api:SilverStripe\CMS\Search\SearchForm) and [FulltextSearchable](api:SilverStripe\ORM\Search\FulltextSearchable) API's are currently hard coded to be specific to `Page` and `File`
records and cannot easily be adapted to include custom `DataObject` instances. To include your custom objects in the
default site search, have a look at those extensions and modify as required.
</div>
[/alert]
### Fulltext Filter

View File

@ -1,5 +1,7 @@
---
title: Search
summary: Provide your users with advanced search functionality.
introduction: Give users the ability to search your applications. Fulltext search for Page Content (and other attributes like "Title") can be easily added to SilverStripe.
---
[CHILDREN]

View File

@ -1,5 +1,7 @@
---
title: i18n
summary: Display templates and PHP code in different languages based on the preferences of your website users.
---
# i18n
@ -272,9 +274,9 @@ _t(__CLASS__ . '.GREETING', 'Welcome!');
#### Usage in Template Files
<div class="hint" markdown='1'>
[hint]
The preferred template syntax has changed somewhat since [version 2.x](http://doc.silverstripe.org/framework/en/2.4/topics/i18n#usage-2).
</div>
[/hint]
In `.ss` template files, instead of `_t(params)` the syntax `<%t params %>` is used. The syntax for passing parameters to the function is quite different to
the PHP version of the function.
@ -318,9 +320,9 @@ underscore function, and tell you about the created files and any possible entit
If you want to run the text collector for just one module you can use the 'module' parameter:
`http://localhost/dev/tasks/i18nTextCollectorTask/?module=cms`
<div class="hint" markdown='1'>
[hint]
You'll need to install PHPUnit to run the text collector (see [testing-guide](/developer_guides/testing)).
</div>
[/hint]
## Module Priority

View File

@ -1,5 +1,8 @@
---
title: File management
summary: Learn how to work with File and Image records
icon: file-signature
---
# File management
@ -9,14 +12,14 @@ Management of files within the CMS is provided via the [silverstripe/asset-admin
module. This is a rich and user friendly interface supporting most basic file operations, as well as
control over the publishing and security of files.
![asset admin](_images/asset-admin-demo.png)
![asset admin](/_images/asset-admin-demo.png)
## UploadField
If you have the [silverstripe/asset-admin](https://github.com/silverstripe/silverstripe-asset-admin)
module installed then this provides a powerful component [api:SilverStripe\AssetAdmin\Forms\UploadField].
![upload field](_images/upload-field.png)
![upload field](/_images/upload-field.png)
You can add it to a page as below:
@ -250,7 +253,7 @@ class Page extends SiteTree
}
```
See [Versioned: Ownership](/developer_guides/model/versioned#ownership) for details.
See [Versioned: Ownership](/developer_guides/model/versioning#ownership) for details.
### Avoid exclusive relationships

View File

@ -1,4 +1,6 @@
---
summary: Learn how to crop and resize images in templates and PHP code
---
# Image

View File

@ -1,4 +1,8 @@
---
title: File security
summary: Manage access permission to assets
icon: lock
---
# File Security
@ -72,12 +76,12 @@ Most commonly this is through the "Access to Files section" permission.
Custom implementations (e.g. APIs or custom file viewers) can have
further restrictions in your project.
<div class="warning" markdown="1">
[warning]
When implenting your own `canView()` logic through [extensions](/developer_guides/extending/extensions),
existing unprotected files are not retroactively moved to the protected asset store.
While those new permissions are honoured in the CMS, protected files through custom `canView()`
can still be downloaded through a public URL until a `write()` operation is triggered on them.
</div>
[/warning]
## Asset stores
@ -214,10 +218,10 @@ $object->SecretFile->protectFile();
$object->PublicFile->publishFile();
```
<div class="notice" markdown="1">
[notice]
One thing to note is that all variants of a single file will be treated as
a single entity for access control, so specific variants cannot be individually controlled.
</div>
[/notice]
## How file access is protected
@ -327,11 +331,11 @@ SilverStripe\Assets\File:
- xzip
```
<div class="warning" markdown="1">
[warning]
Any file not included in this config, or in the default list of extensions, will be blocked from
any requests to the assets directory. Invalid files will be blocked regardless of whether they
exist or not, and will not invoke any PHP processes.
</div>
[/warning]
### Configuring: Protected file headers {#protected_file_headers}

View File

@ -1,5 +1,8 @@
---
title: File storage
summary: Describes the persistence layer of files
icon: hdd
---
# File storage

View File

@ -1,5 +1,8 @@
---
title: File migration
summary: Manage migration of legacy files to the new database structure
icon: compress-arrows-alt
---
# File migration

View File

@ -1,6 +1,9 @@
---
title: Files
summary: Upload, manage and manipulate files and images.
introduction: Upload, manage and manipulate files and images.
icon: folder-open
---
# Files

View File

@ -1,5 +1,7 @@
---
title: ModelAdmin
summary: Create admin UI's for managing your data records.
---
# ModelAdmin
@ -9,10 +11,10 @@ searchables list and edit views of [DataObject](api:SilverStripe\ORM\DataObject)
It uses the framework's knowledge about the model to provide sensible defaults, allowing you to get started in a couple
of lines of code, while still providing a solid base for customization.
<div class="info" markdown="1">
[info]
The interface is mainly powered by the [GridField](api:SilverStripe\Forms\GridField\GridField) class ([documentation](../forms/field_types/gridfield)), which can
also be used in other areas of your application.
</div>
[/info]
Let's assume we want to manage a simple product listing as a sample data model: A product can have a name, price, and
a category.
@ -85,9 +87,9 @@ class MyAdmin extends ModelAdmin
This will automatically add a new menu entry to the SilverStripe Admin UI entitled `My Product Admin` and logged in
users will be able to upload and manage `Product` and `Category` instances through http://yoursite.com/admin/products.
<div class="alert" markdown="1">
[alert]
After defining these classes, make sure you have rebuilt your SilverStripe database and flushed your cache.
</div>
[/alert]
## Permissions
@ -95,9 +97,9 @@ Each new `ModelAdmin` subclass creates its' own [permission code](../security),
`CMS_ACCESS_MyAdmin`. Users with access to the Admin UI will need to have this permission assigned through
`admin/security/` or have the `ADMIN` permission code in order to gain access to the controller.
<div class="notice" markdown="1">
[notice]
For more information on the security and permission system see the [Security Documentation](../security)
</div>
[/notice]
The [DataObject](api:SilverStripe\ORM\DataObject) API has more granular permission control, which is enforced in [ModelAdmin](api:SilverStripe\Admin\ModelAdmin) by default.
Available checks are `canEdit()`, `canCreate()`, `canView()` and `canDelete()`. Models check for administrator
@ -172,9 +174,9 @@ class Product extends DataObject
}
```
<div class="hint" markdown="1">
[hint]
[SearchContext](../search/searchcontext) documentation has more information on providing the search functionality.
</div>
[/hint]
## Displaying Results

View File

@ -1,3 +1,8 @@
---
title: CMS Architecture
summary: An overview of the code architecture of the CMS
icon: sitemap
---
# CMS Architecture
## Introduction

View File

@ -1,4 +1,7 @@
---
title: Admin Layout
summary: Add interactivity enhancements to the admin with Javascript
---
# CMS layout
@ -34,17 +37,17 @@ This causes the framework to:
to the layout manager)
* trigger `redraw` on children which also cascades deeper into the hierarchy (this is framework activity)
<div class="notice" markdown='1'>
[notice]
Caveat: `layout` is also triggered when a DOM element is replaced with AJAX in `LeftAndMain::handleAjaxResponse`. In
this case it is triggered on the parent of the element being replaced so jLayout has a chance to rebuild its algorithms.
Calling the top level `layout` is not enough as it will wrongly descend down the detached element's hierarchy.
</div>
[/notice]
<div class="notice" markdown='1'>
[notice]
Caveat: invocation order of the `redraws` is crucial here, generally going from innermost to outermost elements. For
example, the tab panels have be applied in the CMS form before the form itself is layouted with its sibling panels to
avoid incorrect dimensions.
</div>
[/notice]
![Layout variations](../../_images/cms-architecture.png)

View File

@ -1,3 +1,8 @@
---
title: Preview
summary: How content previews work in the CMS
---
# CMS preview
## Overview
@ -26,12 +31,12 @@ first segment has to match current _LeftAndMain_-derived class (e.g.
We use `ss.preview` entwine namespace for all preview-related entwines.
<div class="notice" markdown='1'>
[notice]
Caveat: `SilverStripeNavigator` and `CMSPreviewable` interface currently only
support SiteTree objects that are _Versioned_. They are not general enough for
using on any other DataObject. That pretty much limits the extendability of the
feature.
</div>
[/notice]
## Configuration and Defaults
@ -170,13 +175,13 @@ internal states of the layout. You can reach it by calling:
$('.cms-container').entwine('.ss').getLayoutOptions().mode;
```
<div class="notice" markdown='1'>
[notice]
Caveat: the `.preview-mode-selector` appears twice, once in the preview and
second time in the CMS actions area as `#preview-mode-dropdown-in-cms`. This is
done because the user should still have access to the mode selector even if
preview is not visible. Currently CMS Actions are a separate area to the preview
option selectors, even if they try to appear as one horizontal bar.
</div>
[/notice]
## Preview API

View File

@ -1,5 +1,8 @@
---
title: WYSIWYG Styles
summary: Add custom CSS properties to the rich-text editor.
icon: text-width
---
# WYSIWYG Styles

View File

@ -1,5 +1,8 @@
---
title: Javascript Development
summary: Advanced documentation about writing and customizing javascript within SilverStripe.
iconBrand: js
---
# Javascript Development

View File

@ -1,5 +1,8 @@
---
title: React, Redux, and GraphQL
summary: Learn how to extend and customise the technologies we use for application state and client-rendered UI.
iconBrand: react
---
# Introduction to the "React" layer
@ -15,12 +18,12 @@ There are some several members of this ecosystem that all work together to provi
All of these pillars of the frontend application can be customised, giving you more control over how the admin interface looks, feels, and behaves.
<div class="alert" markdown="1">
[alert]
These technologies underpin the future of SilverStripe CMS development, but their current implementation is
_experimental_. Our APIs are not expected to change drastically between releases, but they are excluded from
our [semantic versioning](https://semver.org) commitments for the time being. Any breaking changes will be
clearly signalled in release notes.
</div>
[/alert]
First, a brief summary of what each of these are:
@ -241,16 +244,16 @@ Services can then be fetched using their respective `.get()` methods.
const MyComponent = Injector.component.get('MyComponent');
```
<div class="notice" markdown="1">
[notice]
Because of the unique structure of the `form` middleware, you cannot register new services to `Injector.form`.
</div>
[/notice]
<div class="alert" markdown="1">
[alert]
Overwriting components by calling `register()` multiple times for the same
service name is discouraged, and will throw an error. Should you really need to do this,
you can pass `{ force: true }` as the third argument to the `register()` function.
</div>
[/alert]
## Transforming services using middleware
@ -337,12 +340,12 @@ Injector.transform(
{ after: '*' }
);
```
<div class="info" markdown="1">
[info]
This flag can only be used once per transformation.
The following are not allowed:
* `{ before: ['*', 'something-else'] }`
* `{ after: '*', before: 'something-else' }`
</div>
[/info]
## Injector context
@ -598,14 +601,14 @@ API using several helper methods, including:
* `addFieldClass(fieldName:string, cssClassName:string)`
* `removeFieldClass(fieldName:string, cssClassName:string)`
<div class="info" markdown="1">
[info]
For a complete list of props that are available to update on a `Field` object,
see http://redux-form.com/6.8.0/docs/api/Field.md/#props-you-can-pass-to-field-
</div>
[/info]
<div class="notice" markdown="1">
[notice]
It is critical that you end series of mutation calls with `getState()`.
</div>
[/notice]
In addition to mutation methods, several readonly methods are available on `FormSchemaManager` to read the current form state, including:

View File

@ -1,3 +1,8 @@
---
title: CMS alternating button
summary: Add an "active" and "neutral" state to the CMS buttons
---
# How to implement an alternating button
## Introduction

View File

@ -1,3 +1,8 @@
---
title: CMS form field help text
summary: Add help text to the form fields in the CMS
icon: question
---
# How to Show Help Text on CMS Form Fields
Sometimes you need to express more context for a form field

View File

@ -1,3 +1,7 @@
---
title: Customise the CMS Menu
summary: Make custom changes to the left hand menu in the CMS
---
# How to customise the CMS Menu
## Adding an administration panel

View File

@ -1,3 +1,6 @@
---
title: Customise the CMS pages list
---
# Howto: Customize the Pages List in the CMS
The pages "list" view in the CMS is a powerful alternative to visualizing

View File

@ -1,3 +1,9 @@
---
title: Customise the CMS tree
summary: Learn how to add custom UI elements to the CMS page navigation
icon: sitemap
---
# How to customise the CMS tree
## Overview

View File

@ -1,3 +1,7 @@
---
title: Customising React components
summary: Learn how to use Injector to override React-rendered form fields
---
# Customising React Components
In this tutorial, we'll customise some form elements rendered with React to have some new features.

View File

@ -1,3 +1,8 @@
---
title: Customising React forms
summary: Use Injector to add customisations to React-rendered forms
---
# Customising React Forms
Forms that are rendered with React use the [ReduxForm](http://redux-form.com) library and are based on schema definitions that come from the server. To customise these forms, you can apply middleware that updates the schema or applies validation.

View File

@ -1,5 +1,8 @@
---
title: Customise site reports
summary: Creating your own custom data or content reports.
---
# Customise site reports
## Introduction

View File

@ -1,3 +1,8 @@
---
title: Extend the CMS interface
summary: Customise the UI of the CMS backend
---
# How to extend the CMS interface
## Introduction
@ -232,9 +237,9 @@ We can also easily create new drop-up menus by defining new tabs within the
$fields->addFieldToTab('ActionMenus.MyDropUp', FormAction::create('minor', 'Minor action in a new drop-up'));
```
<div class="hint" markdown='1'>
[hint]
Empty tabs will be automatically removed from the `FieldList` to prevent clutter.
</div>
[/hint]
To make the actions more user-friendly you can also use alternating buttons as
detailed in the [CMS Alternating Button](cms_alternating_button)

View File

@ -1,3 +1,7 @@
---
title: Extending an existing ModelAdmin
summary: ModelAdmin interfaces that come with the core can be customised easily
---
## Extending existing ModelAdmin
Sometimes you'll work with ModelAdmins from other modules. To customise these interfaces, you can always subclass. But there's

View File

@ -0,0 +1,6 @@
---
title: How To's
---
# How To's: Customising the Admin Interface
[CHILDREN]

View File

@ -1,6 +1,9 @@
---
title: Customising the Admin Interface
summary: Extend the admin view to provide custom behavior or new features for CMS and admin users.
introduction: The Admin interface can be extended to provide additional functionality to users and custom interfaces for managing data.
iconBrand: react
---
The Admin interface is bundled within the SilverStripe Framework but is most commonly used in conjunction with the `cms`
module. The main class for displaying the interface is a specialized [Controller](api:SilverStripe\Control\Controller) called [LeftAndMain](api:SilverStripe\Admin\LeftAndMain), named

View File

@ -1,5 +1,7 @@
---
title: Flushable
summary: Allows a class to define it's own flush functionality.
---
# Flushable
@ -10,11 +12,11 @@ Allows a class to define it's own flush functionality, which is triggered when `
implementors of [Flushable](api:SilverStripe\Core\Flushable).
<div class="notice">
[notice]
Flushable implementers might also be triggered automatically on deploy if you have `SS_FLUSH_ON_DEPLOY` [environment
variable](../configuration/environment_variables) defined. In that case even if you don't manually pass `flush=1` parameter, the first request after deploy
will still be calling `Flushable::flush` on those entities.
</div>
[/notice]
## Usage

View File

@ -1,5 +1,7 @@
---
title: Manifests
summary: Manage caches of file path maps and other expensive information
---
# Manifests

View File

@ -1,5 +1,7 @@
---
title: App Object and Kernel
summary: Provides bootstrapping and entrypoint to the SilverStripe application
---
# Kernel

View File

@ -1,4 +1,8 @@
---
title: Execution pipeline
summary: An overview of the steps involved in delivering a SilverStripe web page.
icon: route
---
# Execution Pipeline

View File

@ -1,6 +1,9 @@
---
title: Command Line Interface
summary: Automate SilverStripe, run Cron Jobs or sync with other platforms through the Command Line Interface.
introduction: Automate SilverStripe, run Cron Jobs or sync with other platforms through the Command Line Interface.
icon: terminal
---
SilverStripe can call [Controllers](../controllers) through a command line interface (CLI) just as easily as through a
web browser. This functionality can be used to automate tasks with cron jobs, run unit tests, or anything else that
@ -14,21 +17,21 @@ cd your-webroot/
php vendor/silverstripe/framework/cli-script.php dev/build
```
<div class="notice">
[notice]
Your command line php version is likely to use a different configuration as your webserver (run `php -i` to find out
more). This can be a good thing, your CLI can be configured to use higher memory limits than you would want your website
to have.
</div>
[/notice]
## Sake - SilverStripe Make
Sake is a simple wrapper around `cli-script.php`. It also tries to detect which `php` executable to use if more than one
are available. It is accessible via `vendor/bin/sake`.
<div class="info" markdown='1'>
[info]
If you are using a Debian server: Check you have the php-cli package installed for sake to work. If you get an error
when running the command php -v, then you may not have php-cli installed so sake won't work.
</div>
[/info]
### Installation
@ -39,9 +42,9 @@ cd your-webroot/
sudo ./vendor/bin/sake installsake
```
<div class="warning">
[warning]
This currently only works on UNIX like systems, not on Windows.
</div>
[/warning]
### Configuration
@ -74,10 +77,10 @@ sake dev/
sake dev/build "flush=1"
```
<div class="alert" markdown="1">
[alert]
You have to run "sake" with the same system user that runs your web server,
otherwise "flush" won't be able to clean the cache properly.
</div>
[/alert]
It can also be handy if you have a long running script..
@ -130,9 +133,9 @@ sake -start MyProcess
sake -stop MyProcess
```
<div class="notice">
[notice]
`sake` stores `pid` and log files in the site root directory.
</div>
[/notice]
## Arguments

View File

@ -1,5 +1,8 @@
---
title: Cookies
summary: A set of static methods for manipulating PHP cookies.
icon: cookie-bite
---
# Cookies
## Accessing and Manipulating Cookies

View File

@ -1,5 +1,8 @@
---
title: Sessions
summary: A set of static methods for manipulating PHP sessions.
icon: user
---
# Sessions

View File

@ -1,6 +1,9 @@
---
title: Cookies and Sessions
summary: Save state information using the Cookie class and the Session class.
introduction: Both the Cookie and Session classes can be used to preserve certain data across subsequent page requests.
icon: cookie
---
[CHILDREN]

View File

@ -1,5 +1,7 @@
---
title: Developer Guides
introduction: The following guides take a more detailed look into the core concepts and code examples for building SilverStripe applications.
---
In each guide you'll find reference documentation followed by a collection of short and informal How-to's which contain
snippets of code to use in your own projects.

View File

@ -1,5 +1,7 @@
---
title: Upgrading to SilverStripe 4
introduction: Upgrade your project SilverStripe 4 and keep it up to date with the latest fixes, security patches and new features.
summary: Upgrade your project SilverStripe 4 and keep it up to date with the latest fixes, security patches and new features.
---
# Upgrading a SilverStripe 3 project to SilverStripe 4
@ -74,9 +76,9 @@ Before you begin the upgrade process, make sure you meet these pre-requisites.
* Backup your database content.
* Backup your codebase (use version control if possible).
<div class="warning" markdown="1">
[warning]
Never update a website on the live server. Get it working on a development copy first!
</div>
[/warning]
### Install composer
@ -121,9 +123,9 @@ Each command in the upgrader has somewhat different arguments. However, most of
* `--write` which tells the upgrader to apply changes to your code base
* `--root-dir` which can be use to explicitly specify the root of your project. If this is not specified then the current working directory is assumed to be the root of the project.
<div class="info" markdown="1">
[info]
Sample upgrader commands in this guide assume your working directory is the root of your SilverStripe project. You'll need to use the `--root-dir` flag if that's not the case.
</div>
[/info]
#### Install the upgrader globally with composer
@ -906,9 +908,9 @@ class ProductService
}
```
<div class="warning" markdown="1">
[warning]
Avoid using `static::class` or `parent::class` to retrieve translated string. It will retrieve unpredictable values bases on the class inheritance.
</div>
[/warning]
If your template files contain translatable strings, they also need to be updated to referenced the namespaced classes.
For example, `<%t Member.SINGULARNAME 'Member' %>` would become `<%t SilverStripe\Security\Member.SINGULARNAME 'Member' %>`.

View File

@ -1,5 +1,7 @@
---
title: Upgrading a module
introduction: Upgrade your module to be compatible with SilverStripe 4 and make it easy for your users to upgrade.
summary: Upgrade your module to be compatible with SilverStripe 4 and make it easy for your users to upgrade.
---
# Upgrading a module to be compatible with SilverStripe 4

View File

@ -1,5 +1,7 @@
---
title: Upgrading
introduction: The following guides will help you upgrade your project or module to SilverStripe 4.
summary: The following guides will help you upgrade your project or module to SilverStripe 4.
---
The following guides will help you upgrade your project or module to SilverStripe 4. Upgrading a module is very similar to upgrading a Project. The module upgrade guide assumes familiarity with the project upgrade guide.
@ -64,9 +66,9 @@ Before you begin the upgrade process, make sure you meet these pre-requisites.
* Backup your database content.
* Backup your codebase (use version control if possible).
<div class="warning" markdown="1">
[warning]
Never update a website on the live server. Get it working on a development copy first!
</div>
[/warning]
### Install composer
@ -111,9 +113,9 @@ Each command in the upgrader has somewhat different arguments. However, most of
You can run `upgrade-code help` to get more information about the upgrader or `upgrade-code help command-name` to information about a specific command.
<div class="info" markdown="1">
[info]
Sample upgrader commands in this guide assume your working directory is the root of your SilverStripe project. You'll need to use the `--root-dir` flag if that's not the case.
</div>
[/info]
#### Install the upgrader globally with composer
@ -339,7 +341,7 @@ The most typical reason for a conflict is that the maintainer of a module hasn't
If the maintainer of the module is in the process of upgrading to SilverStripe 4, a development version of the module might be available. In some cases, it can be worthwhile to look up the repository of the module or to reach out to the maintainer.
<div class="info" markdown="1">
[info]
If you're going to install development version of third party modules, you should consider adding the following entries to your `composer.json` file.
```json
@ -350,7 +352,7 @@ If you're going to install development version of third party modules, you shoul
// ...
}
```
</div>
[/info]
To resolve a conflict you can either:
* fork the affected module and upgrade it yourself. Don't forget to send a pull request to the original module!
@ -359,11 +361,11 @@ To resolve a conflict you can either:
To integrate a third party module in your project, remove it from your `composer.json` file and from your `.gitignore` file. Then track the module's codebase in your project source control. You'll need to upgrade the module's code to be compatible with SilverStripe 4.
<div class="info" markdown="1">
[info]
If you're taking the time to upgrade a third party module, consider doing a pull request against the original project so other developers can benefit from your work or releasing your fork as a seperate module.
[Learn about how to publish a SilverStripe module](/developer_guides/extending/how_tos/publish_a_module)
</div>
[/info]
### Finalising your dependency upgrade
@ -814,6 +816,7 @@ $translation = _t(CMSMain::class .'.ACCESS', "Access to ''{title}'' section", ['
```
If you're calling `_t()` to retrieve a translation for the current class, you can also use `__CLASS__` or `self::class`. For example:
```php
<?php
namespace App\Web\Services;
@ -830,9 +833,9 @@ class ProductService
}
```
<div class="warning" markdown="1">
[warning]
Avoid using `static::class` or `parent::class` to retrieve translated string. It will retrieve unpredictable values bases on the class inheritance.
</div>
[/warning]
If your template files contain translatable strings, they also need to be updated to referenced the namespaced classes.
For example, `<%t Member.SINGULARNAME 'Member' %>` would become `<%t SilverStripe\Security\Member.SINGULARNAME 'Member' %>`.

View File

@ -371,7 +371,7 @@ version generates its own manifest cache. However, if that's not the case, you m
time with cache generation timestamp. This effectively eliminates the possibility for the manifest cache to be incompatible
with the deployed app.
<div class="alert" markdown="1">
[alert]
WARNING! If you do not deploy your application as a whole, but rather update its files in place with `rsync`, `ssh`
or `FTP`, you should consider triggering CLI based `flush` manually on every such deploy (e.g. with sake).
Otherwise, you may end up with your application cache to be incompatible with its source code, which would make things
@ -381,7 +381,7 @@ In that case you may consider using `SS_FLUSH_ON_DEPLOY`. Depending on your depl
that gets modified on every deploy update so that the framework will automatically perform `flush` for you.
<br />
The best practice is not to reuse the application manifest cache between deploys.
</div>
[/alert]
### New GridField detail form actions {#better-buttons}

View File

@ -1,5 +1,8 @@
---
title: Changelogs
introduction: Key information on new features and improvements in each version.
hideChildren: true
---
Keep up to date with new releases by reading [SilverStripe Forums](https://forum.silverstripe.org/c/releases),
and our [blog posts](http://silverstripe.org/blog/tag/release).

View File

@ -1,5 +1,8 @@
---
title: Bug Reports
summary: Report bugs or problems with SilverStripe, feature requests or other issues.
icon: bug
---
# Contributing Issues and Opinions
@ -38,13 +41,13 @@ problem can collaborate with you to develop a fix.
## Feature Requests
<div class="warning" markdown='1'>
[warning]
Please don't file "feature requests" as Github issues. If there's a new feature
you'd like to see in SilverStripe, you either need to write it yourself (and
[submit a pull request](/contributing/code/#step-by-step-from-forking-to-sending-the-pull-request) or convince somebody else to
write it for you. Any "wishlist" type issues without code attached can be
expected to be closed as soon as they're reviewed.
</div>
[/warning]
In order to gain interest and feedback in your feature, we encourage you to
present it to the community through the [community channels](https://www.silverstripe.org/community).

View File

@ -1,5 +1,8 @@
---
title: Contributing Code
summary: Fix bugs and add new features to help make SilverStripe better.
icon: code
---
# Contributing Code - Submitting Bugfixes and Enhancements
@ -14,17 +17,17 @@ For other modules, our [add-ons site](https://addons.silverstripe.org/add-ons/)
If you are modifying CSS or JavaScript files in core modules, you'll need to regenerate some files.
Please check out our [client-side build tooling](build_tooling) guide for details.
<div class="hint" markdown="1">
[hint]
Note: By supplying code to the SilverStripe core team in patches, tickets and pull requests, you agree to assign copyright of that code to SilverStripe Limited, on the condition that SilverStripe Limited releases that code under the BSD license.
We ask for this so that the ownership in the license is clear and unambiguous, and so that community involvement doesn't stop us from being able to continue supporting these projects. By releasing this code under a permissive license, this copyright assignment won't prevent you from using the code in any way you see fit.
</div>
[/hint]
## Step-by-step: From forking to sending the pull request
<div class="notice" markdown='1'>
[notice]
**Note:** Please adjust the commands below to the version of SilverStripe that you're targeting.
</div>
[/notice]
1. Create a [fork](https://help.github.com/articles/about-forks/) of the module you want to contribute to (listed on [github.com/silverstripe/](https://github.com/silverstripe/)).

View File

@ -1,3 +1,9 @@
---
title: Build tooling
summary: The tools we use to compile our frontend code
icon: tools
---
# Client-side build tooling
Core JavaScript, CSS, and thirdparty dependencies are managed with the build tooling

View File

@ -1,3 +1,9 @@
---
title: Request for comment
summary: Our approach to decision-making around impactful changes to the product
icon: comments
---
# Request for comment (RFC)
## Why RFCs?

View File

@ -1,4 +1,8 @@
---
title: Release process
summary: Describes the process followed for "core" releases.
iconBrand: git-alt
---
# Release Process

View File

@ -1,5 +1,8 @@
---
title: Making a SilverStripe core release
summary: Development guide for core contributors to build and publish a new release
iconBrand: github-alt
---
# Making a SilverStripe core release
@ -99,10 +102,10 @@ exactly the same for these.
Standard practice is to produce a pre-release for any patched modules on the security
forks, e.g. for cms and framework (see [silverstripe-security](https://github.com/silverstripe-security)).
<div class="warning" markdown="1">
[warning]
Security issues are never disclosed until a public stable release containing this fix
is available, or within a reasonable period of time of such a release.
</div>
[/warning]
### When receiving a report
@ -203,10 +206,10 @@ Note:
* Test you can view the satis home page at `http://localhost/satis-security/public/`
* When performing the release ensure you use `--repository=http://localhost/satis-security/public` (below)
<div class="warning" markdown="1">
[warning]
It's important that you re-run `satis build` step after EVERY change that is pushed upstream; E.g. between
each release, if making multiple releases.
</div>
[/warning]
### Detailed CVE and CVSS Guidance

View File

@ -1,5 +1,8 @@
---
title: Documentation
summary: Writing guide for contributing to SilverStripe developer and CMS user help documentation.
icon: file-alt
---
# Contributing documentation
@ -18,9 +21,9 @@ page you want to edit. Alternatively, locate the appropriate .md file in the
* After editing the documentation, describe your changes in the "commit summary" and "extended description" fields below then press "Commit Changes".
* After committing you changes, you will see a form to submit a Pull Request: "[pull requests](http://help.github.com/pull-requests/)". You should be able to adjust the version to which your documentation changes apply before submitting the form. Any changes submitted in a pull request will be sent to the core committers for approval.
<div class="warning" markdown='1'>
[warning]
You should make your changes in the lowest branch they apply to. For instance, if you fix a spelling issue that you found in the 3.2 documentation, submit your fix to that branch in Github and it'll be copied to the master (4.0) version of the documentation automatically. *Don't submit multiple pull requests*.
</div>
[/warning]
## Editing on your computer
@ -30,9 +33,9 @@ If you prefer to edit content on your local machine, you can "[fork](http://help
The documentation is kept alongside the source code in the `docs/` subfolder of any SilverStripe module, framework or CMS folder.
<div class="warning" markdown='1'>
[warning]
If you submit a new feature or an API change, we strongly recommend that your patch includes updates to the necessary documentation. This helps prevent our documentation from getting out of date.
</div>
[/warning]
## Repositories
@ -85,40 +88,40 @@ documenting, there shouldn't be any "frequently asked questions" left.
There are several built-in block styles for highlighting a paragraph of text. Please use these graphical elements
sparingly.
<div class="hint" markdown='1'>
[hint]
"Tip box": A tip box is great for adding, deepening or accenting information in the main text. They can be used for background knowledge, or to provide links to further information (ie, a "see also" link).
</div>
[/hint]
Code for a Tip box:
```
<div class="hint" markdown='1'>
[hint]
...
</div>
[/hint]
```
<div class="notice" markdown='1'>
[notice]
"Notification box": A notification box is good for technical notifications relating to the main text. For example, notifying users about a deprecated feature.
</div>
[/notice]
Code for a Notification box:
```
<div class="notice" markdown='1'>
[notice]
...
</div>
[/notice]
```
<div class="warning" markdown='1'>
[warning]
"Warning box": A warning box is useful for highlighting a severe bug or a technical issue requiring a user's attention. For example, suppose a rare edge case sometimes leads to a variable being overwritten incorrectly. A warning box can be used to alert the user to this case so they can write their own code to handle it.
</div>
[/warning]
Code for a Warning box:
```
<div class="warning" markdown='1'>
[warning]
...
</div>
[/warning]
```
See [markdown extra documentation](http://michelf.com/projects/php-markdown/extra/#html) for more restrictions

View File

@ -1,5 +1,8 @@
---
title: Translations
summary: Translate interface components like button labels into multiple languages.
icon: globe
---
# Contributing Translations

View File

@ -1,5 +1,8 @@
---
title: Implement Internationalisation
summary: Implement SilverStripe's internationalisation system in your own modules.
icon: globe
---
# Implementing Internationalisation
@ -80,9 +83,9 @@ git add lang/*
git commit -m "Updated translations"
```
<div class="notice" markdown="1">
[notice]
You can download your work right from Transifex in order to speed up the process for your desired language.
</div>
[/notice]
## JavaScript Translations

View File

@ -1,3 +1,9 @@
---
title: Core committers
summary: The team of contributors that has merge access to our open source repositories
icon: users
---
# Core Committers
The Core Committers team is reviewed approximately annually, new members are added based on quality contributions to SilverStipe code and outstanding community participation.

View File

@ -1,3 +1,8 @@
---
title: Code of conduct
summary: How to be a high-performing, helpful member of our community
icon: handshake
---
# SilverStripe community code of conduct
These guidelines aim to be an aspirational ideal for how we should behave when interacting in the SilverStripe developer community and to aid in building great open source software.

View File

@ -1,3 +1,8 @@
---
title: Coding conventions
summary: The style guidelines we follow in all of our open source code
icon: code
---
# Coding Conventions
* [PHP Coding Conventions](php_coding_conventions)

View File

@ -1,3 +1,9 @@
---
title: Javascript coding conventions
summary: The Javascript style guidelines we follow in our open source software
iconBrand: js
---
# JavaScript Coding Conventions
## Overview

View File

@ -1,3 +1,8 @@
---
title: CSS coding conventions
summary: The CSS style guidelines we follow in our open source software
iconBrand: css3
---
# CSS and SCSS Coding Conventions
## Overview

View File

@ -1,3 +1,8 @@
---
title: PHP coding conventions
summary: The code style guidelines we use in our open source software
iconBrand: php
---
# PHP Coding Conventions
This document provides guidelines for code formatting and documentation

View File

@ -1,5 +1,8 @@
---
title: Contributing
introduction: Any open source product is only as good as the community behind it. You can participate by sharing code, ideas, or simply helping others. No matter what your skill level is, every contribution counts.
summary: Any open source product is only as good as the community behind it. You can participate by sharing code, ideas, or simply helping others. No matter what your skill level is, every contribution counts.
icon: heart
---
## House rules for everybody contributing to SilverStripe
* Read over the SilverStripe Community [Code of Conduct](code_of_conduct)

View File

Before

(image error) Size: 327 KiB

After

(image error) Size: 327 KiB

Binary file not shown.

Before

(image error) Size: 88 KiB

Binary file not shown.

Before

(image error) Size: 140 KiB

Binary file not shown.

Before

(image error) Size: 33 KiB

Binary file not shown.

Before

(image error) Size: 109 KiB

Binary file not shown.

Before

(image error) Size: 5.0 KiB

Binary file not shown.

Before

(image error) Size: 4.4 KiB

Binary file not shown.

Before

(image error) Size: 3.5 KiB

Binary file not shown.

Before

(image error) Size: 36 KiB

Binary file not shown.

Before

(image error) Size: 35 KiB

View File

@ -1,435 +0,0 @@
/* Global Resetting */
html{
width: 100%;
height: 100%;
background:url(../images/body_bg.gif) repeat;
}
body {
width: 100%;
height: 100%;
font-size: 62.5%;
/* reset font-sizes to 1em == 10px */
}
* {
font-size: 1em;
/* reset font-sizes to 1em == 10px */
padding: 0;
margin: 0;
font-family:Verdana,Helvetica,sans-serif;
list-style:none;
}
a img{
border:0;
}
.clear{
clear:both;
}
/* Layout CSS */
#Main {
margin:20px auto;
width:900px;
}
#Header {
background:url(../images/blueback.gif) bottom left repeat-x;
border-left:1px solid #ccc;
border-right:1px solid #ccc;
clear:left;
}
#Header h1 {
color:#fff;
font-size:1.5em;
line-height:4.5em;
padding-left:20px;
}
#Menu1 {
padding:10px 50px 0;
}
#Menu1 li {
float:left;
margin-left:2px;
background:url(../images/menu1_right.gif) no-repeat right top;
}
#Menu1 li.current,
#Menu1 li.section {
background:url(../images/menu1_right_on.gif) no-repeat right top;
}
#Menu1 li a {
display:block;
color:#fff;
font-weight:bold;
font-size:1.1em;
text-decoration:none;
padding:5px 15px;
background:url(../images/menu1_left.gif) no-repeat left top;
}
#Menu1 li a:hover {
color:#d2ebff;
}
#Menu1 li.current a,
#Menu1 li.section a {
background:url(../images/menu1_left_on.gif) no-repeat left top;
color:#d2ebff;
}
#ContentContainer {
background:#f5f5f5 url(../images/ss_watermark.gif) bottom left no-repeat;
padding-top:20px;
padding-bottom:20px;
overflow: auto;
}
#Banner {
text-align: center;
}
#Menu2 {
margin-left: 20px;
width: 17em;
float:left;
background:#f0f0f0;
border:1px solid #ddd;
padding:10px 10px 10px 10px;
}
#Menu2 li {
padding-left:15px;
background:url(../images/menu2_arrow.gif) no-repeat left center;
}
#Menu2 a {
color:#333;
font-weight:bold;
font-size:1.1em;
line-height:1.6em;
text-decoration:none;
}
#Menu2 a:hover {
text-decoration:underline;
}
#Menu2 li.current a,
#Menu2 li.section a {
color:#0083C8;
}
#Content {
float: left;
margin: 0px 20px;
width:70%;
}
div.breadcrumbs {
margin-bottom:10px;
font-size:1em;
color:#666;
}
div.breadcrumbs a {
text-decoration:none;
}
#Footer {
background:#015581;
clear:both;
text-align:right;
padding-right:20px;
border:1px solid #ccc;
border-top:0;
}
#Footer span {
color:#ccc;
font-size:1.1em;
line-height:2em;
font-weight:bold;
padding-left:20px;
background:url(../images/ss_logo.gif) no-repeat;
}
#Footer a {
color:#fff;
}
#Footer a:hover {
text-decoration:none;
}
/* The rest of this file is for the second tutorial */
#NewsList,
#StaffList {
background:#f0f0f0;
border:1px dotted #ccc;
padding:10px;
}
#NewsList li,
#StaffList li {
margin: 0;
list-style-type: none;
}
#NewsList li.newsDateTitle span {
color:#666;
line-height:2em;
}
#NewsList li.newsDateTitle a {
font-size:1.3em;
font-weight:bold;
color:#0083C8;
text-decoration:none;
padding-left:20px;
background:url(../images/treeicons/news-file.gif) no-repeat left center;
}
#NewsList li.newsDateTitle a:hover {
border-bottom:1px dotted #0083C8;
}
#NewsList li.newsSummary {
margin-bottom:20px;
}
#NewsList li.newsSummary span {
font-size:1.1em;
line-height:1.5em;
color:#333;
}
#NewsList li.newsSummary a.readMoreLink {
color:#0083C8;
text-decoration:none;
}
#NewsList li.newsSummary a.readMoreLink:hover {
border-bottom:1px dotted #0083C8;
}
div.newsDetails {
margin-bottom:10px;
}
div.newsDetails p {
color:#666;
margin:0;
font-size:1em;
}
div.pageComments {
background:#f0f0f0;
border:1px dotted #ccc;
padding:10px;
}
#StaffList .staffname {
clear: both;
padding-left: 60px;
height: 1.2em;
}
#StaffList .staffphoto {
float: left;
margin-left: 3px;
margin-top: -1.2em;
}
#StaffList .staffphoto img {
border:1px solid #AAA;
}
#StaffList .staffdescription {
margin-left: 60px;
margin-bottom:30px;
}
#StaffPhoto {
float: left;
margin-right: 10px;
}
#StaffPhoto img {
border:1px solid #AAA;
}
#PageComments {
list-style:none;
background:#e9e9e9;
border:1px solid #ccc;
border-bottom:0;
padding:0;
margin:0;
}
#PageComments li {
list-style:none;
padding:5px;
margin:0;
font-size:1em;
border-bottom:1px dotted #bbb;
}
#PageComments li p span {
font-style:italic;
}
#PageComments a.deletelink {
font-weight:bold;
}
#PageNumbers {
font-weight:bold;
color:#333;
font-size:1.1em;
text-align:center;
padding:5px;
border:1px solid #ddd;
background:#e9e9e9;
}
#PageNumbers * {
padding:0 5px;
line-height:1.5em;
}
#PageNumbers a {
color:#0083C8;
text-decoration:none;
}
#PageNumbers a:hover {
text-decoration:underline;
}
#BrowserPoll {
width: 200px;
float: right;
margin-right: 20px;
margin-top: 20px;
}
#BrowserPoll h2 {
color:#0083C8;
font-size:1.2em;
}
#BrowserPoll ul {
margin: 0;
}
#BrowserPoll li {
list-style-type: none;
margin: 0;
}
#BrowserPoll .browser {
color:#333;
line-height:1.5em;
font-size:1.1em;
}
#BrowserPoll .bar {
background-color: #015581;
}
#BrowserPoll form {
width:100%;
}
#BrowserPoll form fieldset{
border:0;
}
#BrowserPoll .message {
color:red;
background:#ddd;
border:1px solid #ccc;
padding:5px;
margin:5px;
}
#BrowserPoll span.message {
width: 100%;
}
#BrowserPoll form div {
margin-top:10px;
width:100%;
}
#BrowserPoll form label {
font-size:1.1em;
color:#333;
}
#BrowserPoll form label.left {
float:left;
}
#BrowserPoll form label.FormHeading {
font-size:1.3em;
color:#ff7200;
font-weight:bold;
}
#BrowserPoll form input.text,
#BrowserPoll form textarea,
#BrowserPoll form select {
width:100%;
color:#000;
background:#f8f8f8;
border:1px solid #aaa;
padding:3px;
}
#BrowserPoll form input.numeric {
width:20px;
background:#f0f0f0;
border:1px solid #aaa;
padding:3px;
color:#000;
margin-right:4px;
}
#BrowserPoll form input.year {
width:35px;
}
#BrowserPoll form p.btn-toolbar {
text-align:right;
padding:0 22px 15px 0;
}
#BrowserPoll form p.btn-toolbar input {
padding:2px;
}
#BrowserPoll form ul.optionset {
padding-top: 15px;
padding-left: 15px;
}
#BrowserPoll form ul.optionset li {
list-style-type: none;
}
#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;
}

Binary file not shown.

Before

(image error) Size: 37 KiB

Binary file not shown.

Before

(image error) Size: 13 KiB

Binary file not shown.

Before

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 6.3 KiB

Binary file not shown.

Before

(image error) Size: 32 KiB

Binary file not shown.

Before

(image error) Size: 7.0 KiB

Binary file not shown.

Before

(image error) Size: 9.2 KiB

Binary file not shown.

Before

(image error) Size: 9.2 KiB

Binary file not shown.

Before

(image error) Size: 65 KiB

Binary file not shown.

Before

(image error) Size: 15 KiB

Binary file not shown.

Before

(image error) Size: 170 B

Binary file not shown.

Before

(image error) Size: 782 B

Binary file not shown.

Before

(image error) Size: 50 KiB

Binary file not shown.

Before

(image error) Size: 7.2 KiB

Binary file not shown.

Before

(image error) Size: 173 B

Binary file not shown.

Before

(image error) Size: 176 B

Binary file not shown.

Before

(image error) Size: 170 B

Binary file not shown.

Before

(image error) Size: 34 KiB

Binary file not shown.

Before

(image error) Size: 52 KiB

Binary file not shown.

Before

(image error) Size: 33 KiB

Binary file not shown.

Before

(image error) Size: 21 KiB

Binary file not shown.

Before

(image error) Size: 32 KiB

Binary file not shown.

Before

(image error) Size: 43 KiB

Binary file not shown.

Before

(image error) Size: 15 KiB

Binary file not shown.

Before

(image error) Size: 21 KiB

Binary file not shown.

Before

(image error) Size: 26 KiB

Binary file not shown.

Before

(image error) Size: 8.7 KiB

Binary file not shown.

Before

(image error) Size: 17 KiB

Binary file not shown.

Before

(image error) Size: 4.7 KiB

Binary file not shown.

Before

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 9.8 KiB

Binary file not shown.

Before

(image error) Size: 62 KiB

Binary file not shown.

Before

(image error) Size: 104 KiB

Binary file not shown.

Before

(image error) Size: 36 KiB

Binary file not shown.

Before

(image error) Size: 60 KiB

Binary file not shown.

Before

(image error) Size: 44 KiB

Binary file not shown.

Before

(image error) Size: 30 KiB

Binary file not shown.

Before

(image error) Size: 82 KiB

Binary file not shown.

Before

(image error) Size: 83 KiB

Binary file not shown.

Before

(image error) Size: 75 KiB

Binary file not shown.

Before

(image error) Size: 32 KiB

Binary file not shown.

Before

(image error) Size: 16 KiB

Binary file not shown.

Before

(image error) Size: 120 KiB

Binary file not shown.

Before

(image error) Size: 40 KiB

Binary file not shown.

Before

(image error) Size: 46 KiB

Binary file not shown.

Before

(image error) Size: 47 KiB

Binary file not shown.

Before

(image error) Size: 26 KiB

Binary file not shown.

Before

(image error) Size: 44 KiB

Binary file not shown.

Before

(image error) Size: 15 KiB

Binary file not shown.

Before

(image error) Size: 70 KiB

Binary file not shown.

Before

(image error) Size: 37 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

Binary file not shown.

Before

(image error) Size: 34 KiB

Binary file not shown.

Before

(image error) Size: 78 KiB

Binary file not shown.

Before

(image error) Size: 32 KiB

Binary file not shown.

Before

(image error) Size: 48 KiB

Binary file not shown.

Before

(image error) Size: 86 KiB

Binary file not shown.

Before

(image error) Size: 65 KiB

Binary file not shown.

Before

(image error) Size: 47 KiB

Binary file not shown.

Before

(image error) Size: 86 KiB

View File

Before

(image error) Size: 27 KiB

After

(image error) Size: 27 KiB

Binary file not shown.

Before

(image error) Size: 108 KiB

Binary file not shown.

Before

(image error) Size: 142 KiB

Binary file not shown.

Before

(image error) Size: 106 KiB

Binary file not shown.

Before

(image error) Size: 101 KiB

Binary file not shown.

Before

(image error) Size: 109 KiB

Binary file not shown.

Before

(image error) Size: 102 KiB

Binary file not shown.

Before

(image error) Size: 116 KiB

Binary file not shown.

Before

(image error) Size: 154 KiB

Binary file not shown.

Before

(image error) Size: 5.3 KiB

Binary file not shown.

Before

(image error) Size: 4.3 KiB

View File

@ -1,5 +1,7 @@
---
title: SilverStripe Documentation
introduction: Welcome to the SilverStripe Developer Documentation. This website is aimed at website developers looking to learn how to build and manage web applications with the SilverStripe Framework.
summary: Welcome to the SilverStripe Developer Documentation. This website is aimed at website developers looking to learn how to build and manage web applications with the SilverStripe Framework.
---
## Getting Started with SilverStripe