-...
-```
-
-In order to make the graphs render correctly,
-we need to add some CSS styling.
-Add the following code to the existing `form.css` file:
-
-**themes/simple/css/form.css**
-
-```css
-/* BROWSER POLL */
-#BrowserPoll {
- float: right;
- margin: 20px 10px 0 0;
- width: 20%;
-}
-form FieldList {
- border: 0;
-}
-
-#BrowserPoll .message {
- float: left;
- display: block;
- color: red;
- background: #efefef;
- border: 1px solid #ccc;
- padding: 5px;
- margin: 5px;
-}
-
-#BrowserPoll h2 {
- font-size: 1.5em;
- line-height:2em;
- color: #0083C8;
-}
-
-#BrowserPoll .field {
- padding:3px 0;
-}
-
-#BrowserPoll input.text {
- padding: 0;
- font-size:1em;
-}
-
-#BrowserPoll .btn-toolbar {
- padding: 5px 0;
-}
-
-#BrowserPoll .bar {
- background-color: #015581;
-}
-```
-
-
-All going according to plan, if you visit [http://localhost/your_site_name/home/?flush=1](http://localhost/your_site_name/home/?flush=1) it should look something like this:
-
-![](../_images/tutorial3_pollform.jpg)
-
-
-## Processing the form
-
-Great! We now have a browser poll form, but it doesn't actually do anything. In order to make the form work, we have to implement the 'doBrowserPoll()' method that we told it about.
-
-First, we need some way of saving the poll submissions to the database, so we can retrieve the results later. We can do this by creating a new object that extends from [DataObject](api:SilverStripe\ORM\DataObject).
-If you recall, in the [second tutorial](/tutorials/extending_a_basic_site) we said that all objects that inherit from DataObject and have their own fields are stored in tables the database. Also recall that all pages extend DataObject indirectly through [SiteTree](api:SilverStripe\CMS\Model\SiteTree). Here instead of extending SiteTree (or [Page](api:SilverStripe\CMS\Model\SiteTree\Page)) to create a page type, we will extend [DataObject](api:SilverStripe\ORM\DataObject) directly:
-
-**mysite/code/BrowserPollSubmission.php**
-
-```php
-use SilverStripe\ORM\DataObject;
-
-class BrowserPollSubmission extends DataObject
-{
- private static $db = [
- 'Name' => 'Text',
- 'Browser' => 'Text'
- ];
-}
-
-```
-If we then rebuild the database ([http://localhost/your_site_name/dev/build](http://localhost/your_site_name/dev/build)), we will see that the *BrowserPollSubmission* table is created. Now we just need to define 'doBrowserPoll' on *HomePageController*:
-
-**mysite/code/HomePageController.php**
-
-```php
-use BrowserPollSubmission;
-use PageController;
-
-class HomePageController extends PageController
-{
- // ...
- public function doBrowserPoll($data, $form)
- {
- $submission = new BrowserPollSubmission();
- $form->saveInto($submission);
- $submission->write();
- return $this->redirectBack();
- }
-}
-```
-
-A function that processes a form submission takes two arguments - the first is the data in the form, the second is the [Form](api:SilverStripe\Forms\Form) object.
-In our function we create a new *BrowserPollSubmission* object. Since the name of our form fields, and the name of the database fields, are the same we can save the form directly into the data object.
-We call the 'write' method to write our data to the database, and '$this->redirectBack()' will redirect the user back to the home page.
-
-## Form validation
-
-SilverStripe forms all have automatic validation on fields where it is logical. For example, all email fields check that they contain a valid email address. You can write your own validation by subclassing the *Validator* class.
-
-SilverStripe provides the *RequiredFields* validator, which ensures that the fields specified are filled in before the form is submitted. To use it we create a new *RequiredFields* object with the name of the fields we wish to be required as the arguments, then pass this as a fifth argument to the Form constructor.
-
-Add a namespace import for `SilverStripe\Forms\RequiredFields`, then change the end of the 'BrowserPollForm' function so it looks like this:
-
-**mysite/code/HomePage.php**
-
-```php
-use SilverStripe\Forms\Form;
-use SilverStripe\Forms\RequiredFields;
-
-public function BrowserPollForm()
-{
- // ...
- $validator = new RequiredFields('Name', 'Browser');
- return new Form($this, 'BrowserPollForm', $fields, $actions, $validator);
-}
-```
-
-If we then open the homepage and attempt to submit the form without filling in the required fields errors should appear.
-
-![](../_images/tutorial3_validation.jpg)
-
-
-## Showing the poll results
-
-Now that we have a working form, we need some way of showing the results.
-The first thing to do is make it so a user can only vote once per session. If the user hasn't voted, show the form, otherwise show the results.
-
-We can do this using a session variable. The [Session](api:SilverStripe\Control\Session) class handles all session variables in SilverStripe. First modify the 'doBrowserPoll' to set the session variable 'BrowserPollVoted' when a user votes.
-
-**mysite/code/HomePageController.php**
-
-```php
-use SilverStripe\Control\Session;
-use PageController;
-
-// ...
-class HomePageController extends PageController
-{
- // ...
- public function doBrowserPoll($data, $form)
- {
- $submission = new BrowserPollSubmission();
- $form->saveInto($submission);
- $submission->write();
- $this->getRequest()->getSession()->set('BrowserPollVoted', true);
- return $this->redirectBack();
- }
-}
-```
-
-Then we simply need to check if the session variable has been set in 'BrowserPollForm()', and to not return the form if
-it is.
-
-```php
-use PageController;
-
-// ...
-class HomePageController extends PageController
-{
- // ...
- public function BrowserPollForm()
- {
- if ($this->getRequest()->getSession()->get('BrowserPollVoted')) {
- return false;
- }
- // ...
- }
-}
-```
-
-If you visit the home page now you will see you can only vote once per session; after that the form won't be shown. You can start a new session by closing and reopening your browser,
-or clearing your browsing session through your browsers preferences.
-
-Although the form is not shown, you'll still see the 'Browser Poll' heading. We'll leave this for now: after we've built the bar graph of the results, we'll modify the template to show the graph instead of the form if the user has already voted.
-
-Now that we're collecting data, it would be nice to show the results on the website as well. We could simply output every vote, but that's boring. Let's group the results by browser, through the SilverStripe data model.
-
-In the [second tutorial](/tutorials/extending_a_basic_site), we got a collection of news articles for the home page by using the 'ArticleHolder::get()' function, which returns a [DataList](api:SilverStripe\ORM\DataList). We can get all submissions in the same fashion, through `BrowserPollSubmission::get()`. This list will be the starting point for our result aggregation.
-
-Add the appropriate namespace imports, then create the function 'BrowserPollResults' on the *HomePageController* class.
-
-**mysite/code/HomePageController.php**
-
-```php
-use SilverStripe\ORM\GroupedList;
-use SilverStripe\ORM\ArrayList;
-use SilverStripe\View\ArrayData;
-
-public function BrowserPollResults()
-{
- $submissions = new GroupedList(BrowserPollSubmission::get());
- $total = $submissions->Count();
-
- $list = new ArrayList();
- foreach($submissions->groupBy('Browser') as $browserName => $browserSubmissions) {
- $percentage = (int) ($browserSubmissions->Count() / $total * 100);
- $list->push(new ArrayData([
- 'Browser' => $browserName,
- 'Percentage' => $percentage
- ]));
- }
- return $list;
-}
-
-```
-This code introduces a few new concepts, so let's step through it.
-
-```php
-$submissions = new GroupedList(BrowserPollSubmission::get());
-```
-
-First we get all of the `BrowserPollSubmission` records from the database. This returns the submissions as a [DataList](api:SilverStripe\ORM\DataList). Then we wrap it inside a [GroupedList](api:SilverStripe\ORM\GroupedList), which adds the ability to group those records. The resulting object will behave just like the original `DataList`, though (with the addition of a `groupBy()` method).
-
-```php
-$total = $submissions->Count();
-```
-We get the total number of submissions, which is needed to calculate the percentages.
-
-```php
-$list = new ArrayList();
-foreach ($submissions->groupBy('Browser') as $browserName => $browserSubmissions) {
- $percentage = (int) ($browserSubmissions->Count() / $total * 100);
- $list->push(new ArrayData([
- 'Browser' => $browserName,
- 'Percentage' => $percentage
- ]));
-}
-
-```
-
-Now we create an empty [ArrayList](api:SilverStripe\ORM\ArrayList) to hold the data we'll pass to the template. Its similar to [DataList](api:SilverStripe\ORM\DataList), but can hold arbitrary objects rather than just DataObject` instances. Then we iterate over the 'Browser' submissions field.
-
-The `groupBy()` method splits our list by the 'Browser' field passed to it, creating new lists with submissions just for a specific browser. Each of those lists is keyed by the browser name. The aggregated result is then contained in an [ArrayData](api:SilverStripe\View\ArrayData) object, which behaves much like a standard PHP array, but allows us to use it in SilverStripe templates.
-
-
-The final step is to create the template to display our data. Change the 'BrowserPoll' div to the below.
-
-**themes/simple/templates/Layout/HomePage.ss**
-
-```ss
-
-
Browser Poll
- <% if $BrowserPollForm %>
- $BrowserPollForm
- <% else %>
-
- <% loop $BrowserPollResults %>
- -
-
$Browser: $Percentage%
-
-
- <% end_loop %>
-
- <% end_if %>
-
-```
-
-Here we first check if the *BrowserPollForm* is returned, and if it is display it. Otherwise the user has already voted,
-and the poll results need to be displayed.
-
-We use the normal tactic of putting the data into an unordered list and using CSS to style it, except here we use inline styles to display a bar that is sized proportionate to the number of votes the browser has received. You should now have a complete poll.
-
-![](../_images/tutorial3_pollresults.jpg)
-
-## Summary
-
-In this tutorial we have explored custom php forms, and displayed result sets through Grouped Lists. We have briefly covered the different approaches to creating and using forms. Whether you decide to use the [userforms module](http://addons.silverstripe.org/add-ons/silverstripe/userforms) or create a form in PHP depends on the situation and flexibility required.
-
-[Next Tutorial >>](/tutorials/site_search)
\ No newline at end of file
diff --git a/docs/en/01_Tutorials/04_Site_Search.md b/docs/en/01_Tutorials/04_Site_Search.md
deleted file mode 100644
index 0a127ab54..000000000
--- a/docs/en/01_Tutorials/04_Site_Search.md
+++ /dev/null
@@ -1,165 +0,0 @@
-title: Site Search
-summary: Enable website search. How to handle paged result sets and the SearchForm class.
-
-# Tutorial 4 - Site Search
-
-## Overview
-
-This is a short tutorial demonstrating how to add search functionality to a SilverStripe site. It is recommended that you have completed the earlier tutorials ([Building a basic site](/tutorials/building_a_basic_site), [Extending a basic site](/tutorials/extending_a_basic_site), [Forms](/tutorials/forms)), especially the tutorial on forms, before attempting this tutorial. While this tutorial will add search functionality to the site built in the previous tutorials, it should be straight forward to follow this tutorial on any site of your own.
-
-## What are we working towards?
-
-We are going to add a search box on the top of the page. When a user types something in the box, they are taken to a results page.
-
-![](../_images/tutorial4_search.jpg)
-
-## Creating the search form
-
-To enable the search engine you need to include the following code in your `mysite/_config.php` file.
-This will enable fulltext search on page content as well as names of all files in the `/assets` folder.
-
-```php
-FulltextSearchable::enable();
-```
-
-After including that in your `_config.php` you will need to rebuild the database by visiting [http://localhost/your_site_name/dev/build](http://localhost/your_site_name/dev/build) in your web browser (replace localhost/your_site_name with a domain if applicable). This will add fulltext search columns.
-
-The actual search form code is already provided in FulltextSearchable so when you add the enable line above to your `_config.php` you can add your form as `$SearchForm`.
-
-In the simple theme, the SearchForm is already added to the header. We will go through the code and explain it.
-
-
-## Adding the search form
-
-To add the search form, we can add `$SearchForm` anywhere in our templates. In the simple theme, this is in *themes/simple/templates/Includes/Header.ss*
-
-**themes/simple/templates/Includes/Header.ss**
-
-```ss
-<% if $SearchForm %>
-
L
-
- $SearchForm
-
-<% end_if %>
-<% include Navigation %>
-```
-
-This displays as:
-
-![](../_images/tutorial4_searchbox.jpg)
-
-## Showing the results
-
-The results function is already included in the `ContentControllerSearchExtension` which
-is applied via `FulltextSearchable::enable()`
-
-**cms/code/search/ContentControllerSearchExtension.php**
-
-```php
-use SilverStripe\Core\Extension;
-
-class ContentControllerSearchExtension extends Extension
-{
- public function results($data, $form, $request)
- {
- $data = [
- 'Results' => $form->getResults(),
- 'Query' => $form->getSearchQuery(),
- 'Title' => _t('SearchForm.SearchResults', 'Search Results')
- ];
- return $this->owner->customise($data)->renderWith(['Page_results', 'Page']);
- }
-}
-```
-
-The code populates an array with the data we wish to pass to the template - the search results, query and title of the page. The final line is a little more complicated.
-
-When we call a function by its url (eg http://localhost/home/results), SilverStripe will look for a template with the name `PageType_function.ss`. As we are implementing the *results* function on the *Page* page type, we create our
-results page template as *Page_results.ss*. Unfortunately this doesn't work when we are using page types that are
-children of the *Page* page type. For example, if someone used the search on the homepage, it would be rendered with
-*Homepage.ss* rather than *Page_results.ss*. SilverStripe always looks for the template from the most specific page type
-first, so in this case it would use the first template it finds in this list:
-
-* HomePage_results.ss
-* HomePage.ss
-* Page_results.ss
-* Page.ss
-
-We can override this list by using the *renderWith* function. The *renderWith* function takes an array of the names of
-the templates you wish to render the page with. Here we first add the data to the page by using the 'customise'
-function, and then attempt to render it with *Page_results.ss*, falling back to *Page.ss* if there is no
-*Page_results.ss*.
-
-
-## Creating the template
-
-Lastly we need the template for the search page. This template uses all the same techniques used in previous
-tutorials. It also uses a number of pagination variables, which are provided by the [PaginatedList](api:SilverStripe\ORM\PaginatedList)
-class.
-
-*themes/simple/templates/Layout/Page_results.ss*
-
-```ss
-
-
$Title
-
- <% if $Query %>
-
You searched for "{$Query}"
- <% end_if %>
-
- <% if $Results %>
-
- <% else %>
-
Sorry, your search query did not return any results.
- <% end_if %>
-
- <% if $Results.MoreThanOnePage %>
-
- <% if $Results.NotLastPage %>
-
Next
- <% end_if %>
- <% if $Results.NotFirstPage %>
-
Prev
- <% end_if %>
-
- <% loop $Results.Pages %>
- <% if $CurrentBool %>
- $PageNum
- <% else %>
- $PageNum
- <% end_if %>
- <% end_loop %>
-
-
Page $Results.CurrentPage of $Results.TotalPages
-
- <% end_if %>
-
-```
-
-Then finally add ?flush=1 to the URL and you should see the new template.
-
-
-![](../_images/tutorial4_search.jpg)
-
-## Summary
-
-This tutorial has demonstrated how easy it is to have full text searching on your site. To add search to a SilverStripe site add a search form, a results page, and you're done!
-
-[Next Tutorial >>](/tutorials/dataobject_relationship_management)
diff --git a/docs/en/01_Tutorials/05_Dataobject_Relationship_Management.md b/docs/en/01_Tutorials/05_Dataobject_Relationship_Management.md
deleted file mode 100644
index 2e29fb21f..000000000
--- a/docs/en/01_Tutorials/05_Dataobject_Relationship_Management.md
+++ /dev/null
@@ -1,495 +0,0 @@
-title: DataObject Relationship Management
-summary: Learn how to create custom DataObjects and how to build interfaces for managing that data.
-
-
-This tutorial is deprecated, and has been replaced by Lessons 7, 8, 9, and 10 in the [Lessons section](http://www.silverstripe.org/learn/lessons)
-
-
-# Tutorial 5 - Dataobject Relationship Management
-
-## Overview
-
-This tutorial explores the relationship and management of [DataObjects](api:SilverStripe\ORM\DataObject). It builds on the [second tutorial](/tutorials/extending_a_basic_site) where we learnt how to define
-additional fields on our models, and attach images to them.
-
-## What are we working towards?
-
-To demonstrate relationships between objects,
-we are going to use the example of students working on various projects.
-Each student has a single project, and each project has one or more
-mentors supervising their progress. We'll create these objects,
-make them editable in the CMS, and render them on the website.
-
-This table shows some example data we'll be using:
-
- | Project | Student | Mentor |
- | ------- | ------- | ------- |
- | Developer Toolbar | Jakob,Ofir | Mark,Sean |
- | Behaviour Testing | Michal,Wojtek | Ingo, Sean |
- | Content Personalization | Yuki | Philipp |
- | Module Management | Andrew | Marcus,Sam |
-
-### Has-One and Has-Many Relationships: Project and Student
-
-A student can have only one project, it'll keep them busy enough.
-But each project can be done by one or more students.
-This is called a **one-to-many** relationship.
-Let's create the `Student` and `Project` objects.
-
-**mysite/code/Student.php**
-
-```php
-use SilverStripe\ORM\DataObject;
-
-class Student extends DataObject
-{
- private static $db = [
- 'Name' => 'Varchar',
- 'University' => 'Varchar',
- ];
- private static $has_one = [
- 'Project' => 'Project'
- ];
-}
-
-```
-
-**mysite/code/Project.php**
-
-```php
-use Page;
-
-class Project extends Page
-{
- private static $has_many = [
- 'Students' => 'Student'
- ];
-}
-
-```
-
-**mysite/code/ProjectController.php**
-
-```php
-use PageController;
-
-class ProjectController extends PageController
-{
-
-}
-```
-
-The relationships are defined through the `$has_one`
-and `$has_many` properties on the objects.
-The array keys declares the name of the relationship,
-the array values contain the class name
-(see the ["datamodel"](/developer_guides/model/data_model_and_orm)
-topic for more information).
-
-As you can see, only the `Project` model extends `Page`,
-while `Student` is a plain `DataObject` subclass.
-This allows us to view projects through the standard
-theme setup, just like any other page.
-It would be possible to render students separately as well,
-but for now we'll assume they're just listed as part of their `Project` page.
-Since `Project` inherits all properties (e.g. a title) from its parent class,
-we don't need to define any additional ones for our purposes.
-
-Now that we have our models defined in PHP code,
-we need to tell the database to create the related tables.
-Trigger a rebuild through *dev/build* before you
-proceed to the next part of this tutorial.
-
-### Organizing pages: ProjectHolder
-
-A `Project` is just a page, so we could create it anywhere in the CMS.
-In order to list and organize them, it makes sense to collect them under a common parent page.
-We'll create a new page type called `ProjectsHolder` for this purpose,
-which is a common pattern in SilverStripe's page types. Holders
-are useful for listing their children, and usually restrict these children to a specific class,
-in our case pages of type `Project`.
-The restriction is enforced through the `$allowed_children` directive.
-
-**mysite/code/ProjectsHolder.php**
-
-```php
-use Page;
-
-class ProjectsHolder extends Page
-{
- private static $allowed_children = [
- 'Project'
- ];
-}
-
-```
-
-**mysite/code/ProjectsHolderController.php
-
-```php
-use PageController;
-
-class ProjectsHolderController extends PageController
-{
-
-}
-```
-
-You might have noticed that we don't specify the relationship
-to a project. That's because it's already inherited from the parent implementation,
-as part of the normal page hierarchy in the CMS.
-
-Now that we have created our `ProjectsHolder` and `Project` page types, we'll add some content.
-Go into the CMS and create a `ProjectsHolder` page named **Projects**.
-Then create one `Project` page for each project listed [above](/tutorials/dataobject_relationship_management#what-are-we-working-towards).
-
-### Data Management Interface: GridField
-
-So we have our models, and can create pages of type
-`Project` through the standard CMS interface,
-and collect those within a `ProjectsHolder`.
-But what about creating `Student` records?
-
-Since students are related to a single project, we will
-allow editing them right on the CMS interface in the `Project` page type.
-We do this through a powerful field called `[GridField](/reference/grid-field)`.
-All customization to fields for a page type are managed through a method called
-`getCMSFields()`, so let's add it there:
-
-**mysite/code/Project.php**
-
-```php
-use Page;
-use SilverStripe\Forms\GridField;
-use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
-
-class Project extends Page
-{
- // ...
- public function getCMSFields()
- {
- // Get the fields from the parent implementation
- $fields = parent::getCMSFields();
- // Create a default configuration for the new GridField, allowing record editing
- $config = GridFieldConfig_RelationEditor::create();
- // Set the names and data for our gridfield columns
- $config
- ->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns')
- ->setDisplayFields([
- 'Name' => 'Name',
- 'Project.Title'=> 'Project' // Retrieve from a has-one relationship
- ]);
- // Create a gridfield to hold the student relationship
- $studentsField = new GridField(
- 'Students', // Field name
- 'Student', // Field title
- $this->Students(), // List of all related students
- $config
- );
- // Create a tab named "Students" and add our field to it
- $fields->addFieldToTab('Root.Students', $studentsField);
- return $fields;
- }
-}
-
-```
-
-This creates a tabular field, which lists related student records, one row at a time.
-It's empty by default, but you can add new students as required,
-or relate them to the project by typing in the box above the table.
-
-In our case, we want to manage those records, edit their details, and add new ones.
-To accomplish this, we have added a specific [GridFieldConfig](api:SilverStripe\Forms\GridField\GridFieldConfig).
-While we could've built the config from scratch, there's several
-preconfigured instances. The `GridFieldConfig_RecordEditor` default configures
-the field to edit records, rather than just viewing them.
-The GridField API is composed of "components", which makes it very flexible.
-One example of this is the configuration of column names on our table:
-We call `setDisplayFields()` directly on the component responsible for their rendering.
-
-
- Adding a `GridField` to a page type is a popular way to manage data,
- but not the only one. If your data requires a dedicated interface
- with more sophisticated search and management logic, consider
- using the [ModelAdmin](/developer_guides/customising_the_admin_interface/modeladmin)
- interface instead.
-
-
-![tutorial:tutorial5_project_creation.jpg](../_images/tutorial5_project_creation.jpg)
-
-Select each `Project` page you have created before,
-go in the tab panel called "Students", and add all students as required,
-by clicking on the link **Add Student** of your *GridField* table.
-
-![tutorial:tutorial5_addNew.jpg](../_images/tutorial5_addNew.jpg)
-
-Once you have added all the students, and selected their projects, it should look a little like this:
-
-![tutorial:tutorial5_students.jpg](../_images/tutorial5_students.jpg)
-
-### Many-many relationships: Mentor
-
-Now we have a fairly good picture of how students relate to their projects.
-But students generally have somebody looking them over the shoulder.
-In our case, that's the "mentor". Each project can have many of them,
-and each mentor can have one or more projects. They're busy guys!
-This is called a *many-many* relationship.
-
-The first step is to create the `Mentor` object and set the relation with the `Project` page type.
-
-**mysite/code/Mentor.php**
-
-```php
-use SilverStripe\ORM\DataObject;
-
-class Mentor extends DataObject
-{
- private static $db = [
- 'Name' => 'Varchar',
- ];
- private static $belongs_many_many = [
- 'Projects' => 'Project'
- ];
-}
-
-```
-
-**mysite/code/Project.php**
-
-```php
-use Page;
-
-class Project extends Page
-{
- // ...
- private static $many_many = [
- 'Mentors' => 'Mentor'
- ];
-}
-
-```
-
-This code will create a relationship between the `Project` table and the `Mentor` table by storing the ids of the respective `Project` and `Mentor` in a another table named "Project_Mentors"
-(after you've performed a `dev/build` command, of course).
-
-The second step is to add the table in the method `getCMSFields()`,
-which will allow you to manage the *many_many* relation.
-Again, GridField will come in handy here, we just have
-to configure it a bit differently.
-
-**mysite/code/Project.php**
-
-```php
-use Page;
-use SilverStripe\Forms\GridField;
-use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
-
-class Project extends Page
-{
- // ...
- public function getCMSFields()
- {
- $fields = parent::getCMSFields();
- // ...
- // Same setup, but for mentors
- $mentorsField = new GridField(
- 'Mentors',
- 'Mentors',
- $this->Mentors(),
- GridFieldConfig_RelationEditor::create()
- );
- $fields->addFieldToTab('Root.Mentors', $mentorsField);
- return $fields;
- }
-}
-```
-
-The important difference to our student management UI is the usage
-of `$this->Mentor()` (rather than `Mentor::get()`). It will limit
-the list of records to those related through the many-many relationship.
-
-In the CMS, open one of your `Project` pages and select the "Mentors" tab.
-Add all the mentors listed [above](#what-are-we-working-towards)
-by clicking on the **Add Mentor** button.
-
-![tutorial:tutorial5_module_creation.jpg](../_images/tutorial5_module_creation.jpg)
-
-To associate the mentor with a project, select one of the mentors, and click on the projects tab. Add all the projects a mentor is associated with (see the [list](/tutorials/dataobject_relationship_management#What_are_we_working_towards?)), by typing the name in "Find Projects by Page name" and clicking the "Link Existing" button.
-You will notice that you are able to select the same `Project` for multiple mentors.
-This is the definition of a **many-to-many** relation.
-
-![tutorial:tutorial5_module_selection.jpg](../_images/tutorial5_module_selection.jpg)
-
-
-## Website Display
-
-Now that we have created all the *Page* and *DataObject* classes necessary and the relational tables to manage the [relations](/developer_guides/model/data_model_and_orm#relations) between them, we would like to see these relations on the website. We will see in this section how to display all these relations,
-but also how to create a template for a *DataObject*.
-
-For every kind of *Page* or *DataObject*, you can access to their relations thanks to the **control** loop.
-
-### Projects Overview Template
-
-We'll start by creating a `ProjectsHolder` template,
-which lists all projects, and condenses their
-student and mentor relationships into a single line.
-You'll notice that there's no difference between
-accessing a "has-many" and "many-many" relationship
-in the template loops: to the template, it's just
-a named list of object.
-
-![tutorial:tutorial5_projects_table.jpg](../_images/tutorial5_projects_table.jpg)
-
-**themes/simple/templates/Layout/ProjectsHolder.ss**
-
-```ss
-<% include SideBar %>
-
-
- $Title
-
- $Content
-
-
-
- Project |
- Students |
- Mentors |
-
-
-
- <% loop $Children %>
-
-
- $Title
- |
-
- <% loop $Students %>
- $Name ($University)<% if not $Last %>, <% end_if %>
- <% end_loop %>
- |
-
- <% loop $Mentors %>
- $Name<% if not $Last %>, <% end_if %>
- <% end_loop %>
- |
-
- <% end_loop %>
-
-
-
-
-
-```
-
-Navigate to the holder page through your website navigation,
-or the "Preview" feature in the CMS. You should see a list of all projects now.
-Add `?flush=1` to the page URL to force a refresh of the template cache.
-
-To get a list of all projects, we've looped through the "Children" list,
-which is a relationship we didn't define explicitly.
-It is provided to us by the parent implementation,
-since projects are nothing other than children pages in the standard page hierarchy.
-
-### Project Detail Template
-
-Creating the detail view for each `Project` page works in a very similar way.
-Given that we're in the context of a single project,
-we can access the "Students" and "Mentors" relationships directly in the template.
-
-![tutorial:tutorial5_project.jpg](../_images/tutorial5_project.jpg)
-
-**themes/simple/templates/Layout/Project.ss**
-
-```ss
-<% include SideBar %>
-
-
- $Title
-
- $Content
-
Students
- <% if $Students %>
-
- <% loop $Students %>
- - $Name ($University)
- <% end_loop %>
-
- <% else %>
-
No students found
- <% end_if %>
-
Mentors
- <% if $Mentors %>
-
- <% loop $Mentors %>
- - $Name
- <% end_loop %>
-
- <% else %>
-
No mentors found
- <% end_if %>
-
-
-
-```
-
-Follow the link to a project detail from from your holder page,
-or navigate to it through the submenu provided by the theme.
-
-### Student Detail Template
-
-You might have noticed that we duplicate the same template code
-between both views when it comes to displaying the details
-on students and mentors. We'll fix this for students,
-by introducing a new template for them.
-
-**themes/simple/templates/Includes/StudentInfo.ss**
-
-```ss
-$Name ($University)
-```
-
-To use this template, we need to add a new method to our student class:
-
-```php
-use SilverStripe\ORM\DataObject;
-
-class Student extends DataObject
-{
- public function getInfo()
- {
- return $this->renderWith('StudentInfo');
- }
-}
-```
-
-Replace the student template code in both `Project.ss`
-and `ProjectHolder.ss` templates with the new placeholder, `$Info`.
-That's the code enclosed in `<% loop $Students %>` and `<% end_loop %>`.
-With this pattern, you can increase code reuse across templates.
-
-## Summary
-
-This tutorial has demonstrated how you can manage data with
-different types of relations between in the CMS,
-and how you can display this data on your website.
-We illustrated how the powerful `Page` class can be useful to structure
-your own content, and how we can correlate it to more
-lightweight `DataObject` classes. The transition between
-the two classes is intentionally fluent in the CMS, you can
-manage them depending on your needs.
-`DataObject` gives you a no-frills solution to data storage,
-but `Page` allows for built-in WYSIWYG editing, versioning,
-publication and hierarchical organization.
-
-## Exercises
-
-This is a simplified example, so there's naturally room for improvement.
-In order to challenge your knowledge gained in the tutorials so far,
-we suggest some excercises to make the solution more flexible:
-
- * Refactor the `Student` and `Mentor` classes to inherit from a common parent class `Person`,
- and avoid any duplication between the two subclasses.
- * Render mentor details in their own template
- * Change the `GridField` to list only five records per page (the default is 20).
- This configuration is stored in the [GridFieldPaginator](api:SilverStripe\Forms\GridField\GridFieldPaginator) component
diff --git a/docs/en/02_Developer_Guides/01_Templates/02_Common_Variables.md b/docs/en/02_Developer_Guides/01_Templates/02_Common_Variables.md
index f1260eaf6..b298580eb 100644
--- a/docs/en/02_Developer_Guides/01_Templates/02_Common_Variables.md
+++ b/docs/en/02_Developer_Guides/01_Templates/02_Common_Variables.md
@@ -362,8 +362,6 @@ A page will normally contain some content and potentially a form of some kind. F
SilverStripe log-in form. If you are on such a page, the `$Form` variable will contain the HTML content of the form.
Placing it just below `$Content` is a good default.
-You can add your own forms by implementing new form instances (see the [Forms tutorial](/tutorials/forms)).
-
## Related Lessons
* [Adding dynamic content](https://www.silverstripe.org/learn/lessons/v4/adding-dynamic-content-1)
diff --git a/docs/en/02_Developer_Guides/01_Templates/06_Themes.md b/docs/en/02_Developer_Guides/01_Templates/06_Themes.md
index e2850e74e..c60a33ca9 100644
--- a/docs/en/02_Developer_Guides/01_Templates/06_Themes.md
+++ b/docs/en/02_Developer_Guides/01_Templates/06_Themes.md
@@ -101,7 +101,6 @@ The final step is to [submit your theme to Packagist](https://packagist.org/abou
## Links
* [Themes Listing on silverstripe.org](http://addons.silverstripe.org/add-ons?search=&type=theme)
- * [Themes Forum on silverstripe.org](https://www.silverstripe.org/community/forums/themes-2/)
* [Themes repositories on github.com](http://github.com/silverstripe-themes)
## Related Lessons
diff --git a/docs/en/02_Developer_Guides/03_Forms/How_Tos/04_Create_a_GridField_ActionProvider.md b/docs/en/02_Developer_Guides/03_Forms/How_Tos/04_Create_a_GridField_ActionProvider.md
index 02f04124c..a8d469d25 100644
--- a/docs/en/02_Developer_Guides/03_Forms/How_Tos/04_Create_a_GridField_ActionProvider.md
+++ b/docs/en/02_Developer_Guides/03_Forms/How_Tos/04_Create_a_GridField_ActionProvider.md
@@ -157,4 +157,3 @@ message to the user interface indicating a successful message.
* [GridField Reference](/developer_guides/forms/field_types/gridfield)
* [ModelAdmin: A UI driven by GridField](/developer_guides/customising_the_admin_interface/modeladmin)
- * [Tutorial 5: Dataobject Relationship Management](/tutorials/dataobject_relationship_management)
diff --git a/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md b/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md
index e9ff60eb9..8ff9c290d 100644
--- a/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md
+++ b/docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md
@@ -175,8 +175,6 @@ The change is in **$results = $this->getResults($data);**, because you are using
Another thing you cant forget is to check the name of the singleton you are using in your project. the example uses
**MyDataObject**, you need to change it for the one you are using
-For more information on how to paginate your results within the template, see [Tutorial: Site Search](/tutorials/4-site-search).
-
### The Pagination Template
@@ -233,7 +231,6 @@ See [SearchFilter](api:SilverStripe\ORM\Filters\SearchFilter) API Documentation
## Related Documentation
* [ModelAdmin](/developer_guides/customising_the_admin_interface/modeladmin)
-* [Site Search](/tutorials/site_search)
## API Documentation
diff --git a/docs/en/02_Developer_Guides/12_Search/index.md b/docs/en/02_Developer_Guides/12_Search/index.md
index fac71a014..01caad9ed 100644
--- a/docs/en/02_Developer_Guides/12_Search/index.md
+++ b/docs/en/02_Developer_Guides/12_Search/index.md
@@ -2,7 +2,4 @@ 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.
-See the [Site Search Tutorial](/tutorials/site_search) for a detailed walk through of adding basic Search to your
-website.
-
[CHILDREN]
\ No newline at end of file
diff --git a/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md b/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md
index 9dd42c2c1..5c09c1c81 100644
--- a/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md
+++ b/docs/en/05_Contributing/05_Making_A_SilverStripe_Core_Release.md
@@ -67,13 +67,12 @@ the [core committers](core_committers), who will assist with setting up your cre
* Write permissions on the [silverstripe](https://github.com/silverstripe) and
[silverstripe-labs](https://github.com/silverstripe-labs) organisations.
-* Moderator permissions on the [community forum](http://www.silverstripe.org/community/forums/releases-and-announcements/).
* Admin permissions on [transifex](https://www.transifex.com/silverstripe/).
Set up a [~/.transifexrc](https://docs.transifex.com/client/client-configuration) with your credentials.
* AWS write permissions on the `silverstripe-ssorg-releases` s3 bucket
([add credentials](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) via `aws configure`).
* Permission on [silverstripe release announcement](https://groups.google.com/forum/#!forum/silverstripe-announce).
-* Moderator permissions in the #silverstripe [IRC channel](http://www.silverstripe.org/community/contributing-to-silverstripe/irc-channel/)
+* Moderator permissions in the [Slack channel](https://www.silverstripe.org/community/slack-signup/)
* Administrator account on [docs.silverstripe.org](https://docs.silverstripe.org) and
[userhelp.silverstripe.org](https://userhelp.silverstripe.org).
@@ -353,10 +352,7 @@ will need to be regularly updated.
[https://docs.silverstripe.org/en/3.2/changelogs/3.2.1/](https://docs.silverstripe.org/en/3.2/changelogs/3.2.1/)
* Post a release announcement on the [silverstripe release announcement](https://groups.google.com/forum/#!forum/silverstripe-announce)
google group.
-* Create a release announcement forum sticky on the
- [releases and announcements](http://www.silverstripe.org/community/forums/releases-and-announcements/)
- forum category. Make this a global read-only sticky, and un-sticky any older release.
-* Update the #silverstripe [IRC](https://www.silverstripe.org/community/contributing-to-silverstripe/irc-channel/) topic to include the new release version.
+* Update the [Slack](https://www.silverstripe.org/community/slack-signup/) topic to include the new release version.
## See also
diff --git a/docs/en/index.md b/docs/en/index.md
index 12d168631..89e4064b9 100644
--- a/docs/en/index.md
+++ b/docs/en/index.md
@@ -13,16 +13,15 @@ and play with the interactive [demo website](http://demo.silverstripe.org/).
## Getting support
-SilverStripe has an wide range of options for getting support. The [forums](http://www.silverstripe.org/community/forums/)
-and [IRC channel](http://irc.silverstripe.org/) are the best places to talk and discuss questions and problems with the
-community. There are also several other websites with SilverStripe documentation to make use of.
+SilverStripe has an wide range of options for getting support:
-* The [API Documentation](http://api.silverstripe.org/) contains technical reference and class information.
-* The [User Help](http://userhelp.silverstripe.com) website contains documentation related to working within the CMS.
-
-New features, API changes and the development [roadmap](http://www.silverstripe.org/software/roadmap/) for the product are
-discussed on the [core mailinglist](https://groups.google.com/forum/#!forum/silverstripe-dev) along with
-[UserVoice](http://silverstripe.uservoice.com/forums/251266-new-features).
+* Ask technical questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/silverstripe)
+* Get help on our [Slack channel](https://www.silverstripe.org/community/slack-signup/)
+* Read the technical reference in our [API Documentation](http://api.silverstripe.org/)
+* Get a user-focused overview of the CMS features in our [User Help](http://userhelp.silverstripe.com)
+* Discuss new features, API changes and the development [roadmap](http://www.silverstripe.org/software/roadmap/)
+ on [UserVoice](http://silverstripe.uservoice.com/forums/251266-new-features)
+* Join our [core mailinglist](https://groups.google.com/forum/#!forum/silverstripe-dev)
## Building your first SilverStripe Web application