Skip to content
This repository
Browse code

Tutorial 2/3 and some howto tweaks

  • Loading branch information...
commit 0308cc20054c242a1e67e849f7fc96b225f638ce 1 parent 6d8976e
Ingo Schommer authored
56  docs/en/howto/navigation-menu.md
Source Rendered
... ...
@@ -1,11 +1,16 @@
1  
-#How to create a navigation menu
  1
+# How to create a navigation menu
2 2
 
3  
-To create a navigation menu, we will create a new template file: Navigation.ss. Put this file inside the templates/Includes folder in your theme.
  3
+In this how-to, we'll create a simple menu which
  4
+you can use as the primary navigation for your website.
  5
+
  6
+Add the following code to your main template,
  7
+most likely the "Page" template in your theme,
  8
+located in `themes/<mytheme>/templates/Page.ss`.
4 9
 
5 10
     :::ss
6 11
     <ul> 
7 12
     	<% loop Menu(1) %>	  
8  
-    		<li>
  13
+    	<li>
9 14
           <a href="$Link" title="Go to the $Title page" class="$LinkingMode">
10 15
            <span>$MenuTitle</span>
11 16
           </a>
@@ -13,47 +18,4 @@ To create a navigation menu, we will create a new template file: Navigation.ss.
13 18
      	<% end_loop %> 
14 19
     </ul>
15 20
 
16  
-To include this file in your main template, use the 'include' control code. The include control code will insert a template from the Includes folder into your template. The code for including our navigation menu looks like this:
17  
-
18  
-    :::ss
19  
-    <% include Navigation %>
20  
-
21  
-Add this to the templates/Page.ss file where you want the menu to render. The template code in Menu1.ss is rendered as an unordered list in HTML; let's break down this file to see how this works.
22  
-
23  
-The first and last lines of the file are HTML tags to open and close an unordered list. 
24  
-
25  
-    :::ss
26  
-    <ul> 
27  
-    	<% loop Menu(1) %>	  
28  
-    		<li>
29  
-                <a href="$Link" title="Go to the $Title page" class="$LinkingMode">
30  
-                    <span>$MenuTitle</span>
31  
-                </a>
32  
-            </li> 
33  
-        <% end_loop %> 
34  
-    </ul>
35  
-
36  
-Line 2 and 4 use a template code called a loop. A loop iterates over a DataObjectSet; for each DataObject inside the set, everything between the <% loop %> and <% end_loop %> tags are repeated. Here we iterate over the Menu(1) DataObjectSet and this returns the set of all pages at the top level. (For a list of other controls you can use in your templates, see the [templates page](../reference/templates) .)
37  
-
38  
-    :::ss
39  
-    <ul> 
40  
-     	<% loop Menu(1) %>	  
41  
-      		<li>
42  
-                <a href="$Link" title="Go to the $Title page" class="$LinkingMode">
43  
-                    <span>$MenuTitle</span>
44  
-                </a>
45  
-            </li> 
46  
-       	<% end_loop %> 
47  
-    </ul>
48  
-
49  
-Line 3 is where we insert the list item for each menu item. It is sandwiched by the list item opening and closing tags, <li> and </li>. Inside we have a link, using some template codes to fill in the information for each page:
50  
-
51  
-* $Link – the link to the page  
52  
-* $Title – the full title of the page (this is a field in the CMS)  
53  
-* $MenuTitle – the menu title of the page (this is a field in the CMS)  
54  
-* $LinkingMode – which returns one of three things used as a CSS class to style each scenario differently.  
55  
-    * current – this is the page that is currently being rendered
56  
-    * section – this page is a child of the page currently being rendered
57  
-    * link – this page is neither current nor section  
58  
-
59  
-
  21
+More details on creating a menu are explained as part of ["Tutorial 1: Building a basic site"](/tutorials/1-building-a-basic-site), as well as ["Page type templates" topic](/topics/page-type-templates).
106  docs/en/howto/simple-contact-form.md
Source Rendered
... ...
@@ -1,56 +1,51 @@
1 1
 # How to make a simple contact form
2 2
 
3  
-To make a contact form, begin by making a page type for the form to live on – we don't want to see the contact form on every page. Here we have the skeleton code for a ContactPage page type:
  3
+In this how-to, we'll explain how to set up a specific page type
  4
+holding a contact form, which submits a message via email.
  5
+Let's start by defining a new `ContactPage` page type:
4 6
 
5 7
 	:::php
6 8
 	<?php
7 9
 	class ContactPage extends Page {
8  
-		static $db = array(
9  
-		);
10 10
 	}
11 11
 	class ContactPage_Controller extends Page_Controller {
12  
-
  12
+		function Form() { 
  13
+			$fields = new FieldList( 
  14
+				new TextField('Name'), 
  15
+				new EmailField('Email'), 
  16
+				new TextareaField('Message')
  17
+			); 
  18
+			$actions = new FieldList( 
  19
+				new FormAction('submit', 'Submit') 
  20
+			); 
  21
+			return new Form($this, 'Form', $fields, $actions); 
  22
+		}
13 23
 	}
14 24
 
15  
-To create a form, we create a Form object on a function on our page controller. We'll call this function 'Form()' on our ContactPage_Controller class. It doesn't matter what you call your function, but it's standard practice to name the function Form() if there's only a single form on the page. Below is the function to create our contact form:
16  
-
17  
-	:::php
18  
-	function Form() { 
19  
-		$fields = new FieldSet( 
20  
-			new TextField('Name'), 
21  
-			new EmailField('Email'), 
22  
-			new TextareaField('Message')
23  
-		); 
24  
-		 
25  
-		$actions = new FieldSet( 
26  
-			new FormAction('submit', 'Submit') 
27  
-		); 
28  
-		 
29  
-		return new Form($this, 'Form', $fields, $actions); 
30  
-	}
  25
+To create a form, we instanciate a `Form` object on a function on our page controller. We'll call this function `Form()`. You're free to choose this name, but it's standard practice to name the function `Form()` if there's only a single form on the page.
31 26
 
32 27
 There's quite a bit in this function, so we'll step through one piece at a time.
33 28
 
34 29
 	:::php
35  
-	$fields = new FieldSet(
  30
+	$fields = new FieldList(
36 31
 		new TextField('Name'),
37 32
 		new EmailField('Email'),
38 33
 		new TextareaField('Message')
39 34
 	);
40 35
 
41  
-First we create all the fields we want in the contact form, and put them inside a FieldSet. You can find a list of form fields available on the `[api:FormField]` page.   
  36
+First we create all the fields we want in the contact form, and put them inside a FieldList. You can find a list of form fields available on the `[api:FormField]` page.   
42 37
 
43 38
 	:::php
44  
-	$actions = FieldSet(
  39
+	$actions = FieldList(
45 40
 		new FormAction('submit', 'Submit')
46 41
 	);
47 42
 
48  
-We then create a `[api:FieldSet]` of the form actions, or the buttons that submit the form. Here we add a single form action, with the name 'submit', and the label 'Submit'. We'll use the name of the form action later.
  43
+We then create a `[api:FieldList]` of the form actions, or the buttons that submit the form. Here we add a single form action, with the name 'submit', and the label 'Submit'. We'll use the name of the form action later.
49 44
 
50 45
 	:::php
51 46
 	return new Form('Form', $this, $fields, $actions);
52 47
 
53  
-Finally we create the Form object and return it. The first argument is the name of the form – this has to be the same as the name of the function that creates the form, so we've used 'Form'. The second argument is the controller that the form is on – this is almost always $this. The third and fourth arguments are the fields and actions we created earlier.
  48
+Finally we create the `Form` object and return it. The first argument is the name of the form – this has to be the same as the name of the function that creates the form, so we've used 'Form'. The second argument is the controller that the form is on – this is almost always $this. The third and fourth arguments are the fields and actions we created earlier.
54 49
 
55 50
 To show the form on the page, we need to render it in our template. We do this by appending $ to the name of the form – so for the form we just created we need to add $Form. Add $Form to the themes/currenttheme/Layout/Page.ss template, below $Content.
56 51
 
@@ -64,26 +59,38 @@ If you now create a ContactPage in the CMS (making sure you have rebuilt the dat
64 59
 Now that we have a contact form, we need some way of collecting the data submitted. We do this by creating a function on the controller with the same name as the form action. In this case, we create the function 'submit' on the ContactPage_Controller class.
65 60
 
66 61
 	:::php
67  
-	function submit($data, $form) { 
68  
-		$email = new Email(); 
69  
-		 
70  
-		$email->setTo('siteowner@mysite.com'); 
71  
-		$email->setFrom($data['Email']); 
72  
-		$email->setSubject("Contact Message from {$data["Name"]}"); 
73  
-		 
74  
-		$messageBody = " 
75  
-			<p><strong>Name:</strong> {$data['Name']}</p> 
76  
-			<p><strong>Website:</strong> {$data['Website']}</p> 
77  
-			<p><strong>Message:</strong> {$data['Message']}</p> 
78  
-		"; 
79  
-		$email->setBody($messageBody); 
80  
-		$email->send(); 
81  
-		return array(
82  
-			'Content' => '<p>Thank you for your feedback.</p>',
83  
-			'Form' => ''
84  
-		);
  62
+	class ContactPage_Controller extends Page_Controller {
  63
+		function Form() {
  64
+			// ...
  65
+		}
  66
+		function submit($data, $form) { 
  67
+			$email = new Email(); 
  68
+			 
  69
+			$email->setTo('siteowner@mysite.com'); 
  70
+			$email->setFrom($data['Email']); 
  71
+			$email->setSubject("Contact Message from {$data["Name"]}"); 
  72
+			 
  73
+			$messageBody = " 
  74
+				<p><strong>Name:</strong> {$data['Name']}</p> 
  75
+				<p><strong>Website:</strong> {$data['Website']}</p> 
  76
+				<p><strong>Message:</strong> {$data['Message']}</p> 
  77
+			"; 
  78
+			$email->setBody($messageBody); 
  79
+			$email->send(); 
  80
+			return array(
  81
+				'Content' => '<p>Thank you for your feedback.</p>',
  82
+				'Form' => ''
  83
+			);
  84
+		}
85 85
 	}
86 86
 
  87
+<div class="hint" markdown="1">
  88
+	Caution: This form is prone to abuse by spammers,
  89
+	since it doesn't enforce a rate limitation, or checks for bots.
  90
+	We recommend to use a validation service like the ["recaptcha" module](http://www.silverstripe.org/recaptcha-module/)
  91
+	for better security.
  92
+</div>
  93
+
87 94
 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.
88 95
 
89 96
 This data is used to create an email, which you then send to the address you choose.
@@ -95,20 +102,11 @@ The final thing we do is return a 'thank you for your feedback' message to the u
95 102
 
96 103
 All forms have some basic validation built in – email fields will only let the user enter email addresses, number fields will only accept numbers, and so on. Sometimes you need more complicated validation, so you can define your own validation by extending the Validator class.
97 104
 
98  
-The Sapphire framework comes with a predefined validator called 'RequiredFields', which performs the common task of making sure particular fields are filled out. Below is the code to add validation to a contact form:
  105
+The framework comes with a predefined validator called `[api:RequiredFields]`, which performs the common task of making sure particular fields are filled out. Below is the code to add validation to a contact form:
99 106
 
100 107
 	function Form() { 
101  
-		$fields = new FieldSet( 
102  
-			new TextField('Name'), 
103  
-			new EmailField('Email'), 
104  
-			new TextareaField('Message')
105  
-		); 
106  
-		 
107  
-		$actions = new FieldSet( 
108  
-			new FormAction('submit', 'Submit') 
109  
-		); 
  108
+		// ...
110 109
 		$validator = new RequiredFields('Name', 'Message');
111  
-		 
112 110
 		return new Form($this, 'Form', $fields, $actions, $validator); 
113 111
 	}
114 112
 
13  docs/en/reference/database-structure.md
Source Rendered
@@ -111,15 +111,4 @@ The information documented in this page is reflected in a few places in the code
111 111
     * augmentQuery() is responsible for altering the normal data selection queries to support versions.
112 112
     * augmentDatabase() is responsible for specifying the altered database schema to support versions.
113 113
 *  `[api:MySQLDatabase]`: getNextID() is used when creating new objects; it also handles the mechanics of
114  
-updating the database to have the required schema.
115  
-
116  
-
117  
-## Future work
118  
-
119  
-*  We realise that a fixed mapping between the database and object-model isn't appropriate in all cases.  In particular,
120  
-it could be beneficial to set up a SilverStripe data-object as an interface layer to the databases of other
121  
-applications.  This kind of configuration support is on the cards for development once we start looking more seriously
122  
-at providing avenues for clean integration between systems.
123  
-*  Some developers have commented that the the database layer could be used to maintain the relational integrity of this
124  
-database structure.
125  
-*  It could be desirable to implement a non-repeating auto-numbering system.
  114
+updating the database to have the required schema.
6  docs/en/tutorials/2-extending-a-basic-site.md
Source Rendered
@@ -236,7 +236,7 @@ By default the field name *'Date'* or *'Author'* is shown as the title, however
236 236
 
237 237
 Because our new pages inherit their templates from *Page*, we can view anything entered in the content area when navigating to these pages on our site. However, as there is no reference to the date or author fields in the *Page* template this data is not being displayed.
238 238
 
239  
-To fix this we will create a template for each of our new page types. We'll put these in *themes/tutorial/templates/Layout* so we only have to define the page specific parts: SilverStripe will use *themes/tutorial/templates/Page.ss* for the basic
  239
+To fix this we will create a template for each of our new page types. We'll put these in *themes/simple/templates/Layout* so we only have to define the page specific parts: SilverStripe will use *themes/simple/templates/Page.ss* for the basic
240 240
 page layout.
241 241
 
242 242
 ### ArticlePage Template
@@ -366,7 +366,7 @@ It would be nice to greet page visitors with a summary of the latest news when t
366 366
 
367 367
 This function simply runs a database query that gets the latest news articles from the database. By default, this is five, but you can change it by passing a number to the function. See the [Data Model](../topics/datamodel) documentation for details. We can reference this function as a page control in our *HomePage* template:
368 368
 
369  
-**themes/tutorial/templates/Layout/Homepage.ss**
  369
+**themes/simple/templates/Layout/Homepage.ss**
370 370
 
371 371
 	:::ss
372 372
 	...
@@ -514,7 +514,7 @@ resize the image every time the page is viewed.
514 514
 
515 515
 The *StaffPage* template is also very straight forward.
516 516
 
517  
-**themes/tutorial/templates/Layout/StaffPage.ss**
  517
+**themes/simple/templates/Layout/StaffPage.ss**
518 518
 
519 519
 	:::ss
520 520
 	<div class="content-container"> 
101  docs/en/tutorials/3-forms.md
Source Rendered
@@ -4,7 +4,7 @@
4 4
 
5 5
 This tutorial is intended to be a continuation of the first two tutorials ([first tutorial](1-building-a-basic-site), [second tutorial](2-extending-a-basic-site)). In this tutorial we will build on the site we developed in the earlier tutorials and explore forms in SilverStripe. We will look at custom coded forms: forms which need to be written in PHP.
6 6
 
7  
-Instead of using a custom coded form, we could use the [userforms module](http://silverstripe.org/user-forms-module). This module allows users to construct forms via the CMS. A UserDefinedForm is much quicker to implement, but lacks the flexibility of a coded form. 
  7
+Instead of using a custom coded form, we could use the [userforms module](http://silverstripe.org/user-forms-module). This module allows users to construct forms via the CMS. A form created this way is much quicker to implement, but also lacks the flexibility of a coded form. 
8 8
 
9 9
 ## What are we working towards?
10 10
 
@@ -55,27 +55,24 @@ Let's step through this code.
55 55
 
56 56
 	:::php
57 57
 	// Create fields
58  
-		$fields = new FieldList(
59  
-			new TextField('Name'),
60  
-			new OptionsetField('Browser', 'Your Favourite Browser', array(
61  
-				'Firefox' => 'Firefox',
62  
-				'Chrome' => 'Chrome',
63  
-				'Internet Explorer' => 'Internet Explorer',
64  
-				'Safari' => 'Safari',
65  
-				'Opera' => 'Opera',
66  
-				'Lynx' => 'Lynx'
67  
-			))
68  
-		);
69  
-
70  
-
71  
-First we create our form fields.
  58
+	$fields = new FieldList(
  59
+		new TextField('Name'),
  60
+		new OptionsetField('Browser', 'Your Favourite Browser', array(
  61
+			'Firefox' => 'Firefox',
  62
+			'Chrome' => 'Chrome',
  63
+			'Internet Explorer' => 'Internet Explorer',
  64
+			'Safari' => 'Safari',
  65
+			'Opera' => 'Opera',
  66
+			'Lynx' => 'Lynx'
  67
+		))
  68
+	);
72 69
 
73  
-We do this by creating a `[api:FieldList]` and passing our fields as arguments. The first field is a  
74  
-`[api:TextField]` with the name 'Name'.
75 70
 
  71
+First we create our form fields. 
  72
+We do this by creating a `[api:FieldList]` and passing our fields as arguments. 
  73
+The first field is a `[api:TextField]` with the name 'Name'.
76 74
 There is a second argument when creating a field which specifies the text on the label of the field. If no second
77 75
 argument is passed, as in this case, it is assumed the label is the same as the name of the field.
78  
-
79 76
 The second field we create is an `[api:OptionsetField]`. This is a dropdown, and takes a third argument - an
80 77
 array mapping the values to the options listed in the dropdown.
81 78
 
@@ -85,13 +82,9 @@ array mapping the values to the options listed in the dropdown.
85 82
 	);
86 83
 
87 84
 
88  
-After creating the fields, we create the form actions. Form actions appear as buttons at the bottom of the form.
89  
-
90  
-The first argument is the name of the function to call when the button is pressed, and the second is the label of the
91  
-button.
92  
-
  85
+After creating the fields, we create the form actions. Form actions appear as buttons at the bottom of the form. 
  86
+The first argument is the name of the function to call when the button is pressed, and the second is the label of the button.
93 87
 Here we create a 'Submit' button which calls the 'doBrowserPoll' method, which we will create later.
94  
-
95 88
 All the form actions (in this case only one) are collected into a `[api:FieldList]` object the same way we did with
96 89
 the fields.
97 90
 
@@ -100,16 +93,14 @@ the fields.
100 93
 
101 94
 
102 95
 Finally we create the `[api:Form]` object and return it.
103  
-
104 96
 The first argument is the controller that contains the form, in most cases '$this'. The second is the name of the method
105 97
 that returns the form, which is 'BrowserPollForm' in our case. The third and fourth arguments are the
106 98
 FieldLists containing the fields and form actions respectively.
107 99
 
108 100
 After creating the form function, we need to add the form to our home page template.
  101
+Add the following code to the top of your home page template, just before `<div class="Content">`:
109 102
 
110  
-Add the following code to the top of your home page template, just before the first Content `<div>`:
111  
-
112  
-**themes/tutorial/templates/Layout/HomePage.ss**
  103
+**themes/simple/templates/Layout/HomePage.ss**
113 104
 
114 105
 	:::ss
115 106
 	...
@@ -120,28 +111,11 @@ Add the following code to the top of your home page template, just before the fi
120 111
 	<div class="Content">
121 112
 	...
122 113
 
123  
-your HomePage.ss file should now look like this:
124  
-	:::ss
125  
-	<div id="BrowserPoll">
126  
-		<h2>Browser Poll</h2>
127  
-		 $BrowserPollForm
128  
-	</div>
  114
+In order to make the graphs render correctly,
  115
+we need to add some CSS styling.
  116
+Add the following code to the existing `form.css` file:
129 117
 
130  
-	<div class="content-container typography">	
131  
-		<article>
132  
-			<div id="Banner">
133  
-	  			<img src="http://www.silverstripe.org/themes/silverstripe/images/sslogo.png" alt="Homepage image" />
134  
-			</div>
135  
-			
136  
-			<div class="content">$Content</div>
137  
-		</article>
138  
-		$Form
139  
-		$PageComments
140  
-	</div>	
141  
-
142  
-Add the following code to the form style sheet:
143  
-
144  
-**themes/tutorial/css/form.css**
  118
+**themes/simple/css/form.css**
145 119
 
146 120
 	:::css
147 121
 	/* BROWSER POLL */
@@ -182,18 +156,17 @@ Add the following code to the form style sheet:
182 156
 		}
183 157
 
184 158
 
185  
-This CSS code will ensure that the form is formatted and positioned correctly. All going according to plan, if you visit [http://localhost/your_site_name/home?flush=all](http://localhost/your_site_name/home?flush=all) it should look something like this:
  159
+All going according to plan, if you visit [http://localhost/your_site_name/home?flush=all](http://localhost/your_site_name/home?flush=all) it should look something like this:
186 160
 
187 161
 ![](_images/tutorial3_pollform.jpg)
188 162
 
189 163
 
190 164
 ## Processing the form
191 165
 
192  
-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.
  166
+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.
193 167
 
194 168
 First, we need some way of saving the poll submissions to the database, so we can retrieve the results later. We can do this by creating a new object that extends from `[api:DataObject]`.
195  
-
196  
-If you recall, in the [second tutorial](2-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 `[api:SiteTree]`. Here instead of extending SiteTree (or `[api:Page]`) to create a page type, we will extend DataObject directly:
  169
+If you recall, in the [second tutorial](2-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 `[api:SiteTree]`. Here instead of extending SiteTree (or `[api:Page]`) to create a page type, we will extend `[api:DataObject]` directly:
197 170
 
198 171
 **mysite/code/BrowserPollSubmission.php**
199 172
 
@@ -206,7 +179,6 @@ If you recall, in the [second tutorial](2-extending-a-basic-site) we said that a
206 179
 		);
207 180
 	}
208 181
 
209  
-
210 182
 If we then rebuild the database ([http://localhost/your_site_name/dev/build?flush=all](http://localhost/your_site_name/dev/build?flush=all)), we will see that the *BrowserPollSubmission* table is created. Now we just need to define 'doBrowserPoll' on *HomePage_Controller*:
211 183
 
212 184
 **mysite/code/HomePage.php**
@@ -224,9 +196,7 @@ If we then rebuild the database ([http://localhost/your_site_name/dev/build?flus
224 196
 
225 197
 
226 198
 A function that processes a form submission takes two arguments - the first is the data in the form, the second is the `[api:Form]` object.
227  
-
228 199
 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.
229  
-
230 200
 We call the 'write' method to write our data to the database, and '$this->redirectBack()' will redirect the user back to the home page.
231 201
 
232 202
 ## Form validation
@@ -255,7 +225,6 @@ If we then open the homepage and attempt to submit the form without filling in t
255 225
 ## Showing the poll results
256 226
 
257 227
 Now that we have a working form, we need some way of showing the results.
258  
-
259 228
 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.
260 229
 
261 230
 We can do this using a session variable. The `[api:Session]` class handles all session variables in SilverStripe. First modify the 'doBrowserPoll' to set the session variable 'BrowserPollVoted' when a user votes.
@@ -280,21 +249,23 @@ Then we simply need to check if the session variable has been set in 'BrowserPol
280 249
 it is.
281 250
 
282 251
 	:::php
283  
-	public function BrowserPollForm() {
284  
-		if(Session::get('BrowserPollVoted')) {
285  
-			return false;
286  
-		}
  252
+	// ...
  253
+	class HomePage_Controller extends Page_Controller {
287 254
 		// ...
288  
-	}	
  255
+		public function BrowserPollForm() {
  256
+			if(Session::get('BrowserPollVoted')) return false;
  257
+			// ...
  258
+		}	
  259
+	}
289 260
 
290 261
 
291  
-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 if you're using Firefox and have installed the [Web Developer](http://chrispederick.com/work/web-developer/) extension, you can use its Clear Session Cookies command).
  262
+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,
  263
+or clearing your browsing session through your browsers preferences.
292 264
 
293 265
 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.
294 266
 
295 267
 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.
296 268
 
297  
-
298 269
 In the [second tutorial](/tutorials/2-extending-a-basic-site), we got a collection of news articles for the home page by using the 'ArticleHolder::get()' function, which returns a `[api:DataList]`. We can get all submissions in the same fashion, through `BrowserPollSubmission::get()`. This list will be the starting point for our result aggregation.
299 270
 
300 271
 Create the function 'BrowserPollResults' on the *HomePage_Controller* class.
@@ -347,7 +318,7 @@ The `groupBy()` method splits our list by the 'Browser' field passed to it, crea
347 318
 
348 319
 The final step is to create the template to display our data. Change the 'BrowserPoll' div to the below.
349 320
 
350  
-**themes/tutorial/templates/Layout/HomePage.ss** 
  321
+**themes/simple/templates/Layout/HomePage.ss** 
351 322
 
352 323
 	:::ss
353 324
 	<div id="BrowserPoll">

0 notes on commit 0308cc2

Please sign in to comment.
Something went wrong with that request. Please try again.