Completed
Push — master ( 0930e8...f6a37f )
by Robbie
43:33 queued 39:03
created
tests/Tasks/PopulateThemeSampleDataTaskTest.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -10,46 +10,46 @@
 block discarded – undo
10 10
 
11 11
 class PopulateThemeSampleDataTaskTest extends SapphireTest
12 12
 {
13
-    protected $usesDatabase = true;
14
-
15
-    /**
16
-     * Ensure that the "contact" user form is only created once
17
-     */
18
-    public function testOnlyCreateContactFormOnce()
19
-    {
20
-        $createdMessage = 'Created "contact" UserDefinedForm';
21
-
22
-        $task = new PopulateThemeSampleDataTask;
23
-
24
-        // Run the task
25
-        $this->assertContains($createdMessage, $this->bufferedTask($task));
26
-
27
-        // Run a second time
28
-        $this->assertNotContains($createdMessage, $this->bufferedTask($task));
29
-
30
-        // Change the page name
31
-        $form = UserDefinedForm::get()->filter('URLSegment', 'contact')->first();
32
-        $form->URLSegment = 'testing';
33
-        $form->write();
34
-
35
-        // Ensure the old version is still detected in draft, so not recreated
36
-        $this->assertNotContains($createdMessage, $this->bufferedTask($task));
37
-
38
-        // Delete the page, then ensure it's recreated again (DataObject::delete will remove staged versions)
39
-        $form->delete();
40
-        $this->assertContains($createdMessage, $this->bufferedTask($task));
41
-    }
42
-
43
-    /**
44
-     * Run a BuildTask while buffering its output, and return the result
45
-     *
46
-     * @param  BuildTask $task
47
-     * @return string
48
-     */
49
-    protected function bufferedTask(BuildTask $task)
50
-    {
51
-        ob_start();
52
-        $task->run(new HTTPRequest('GET', '/'));
53
-        return ob_get_clean();
54
-    }
13
+	protected $usesDatabase = true;
14
+
15
+	/**
16
+	 * Ensure that the "contact" user form is only created once
17
+	 */
18
+	public function testOnlyCreateContactFormOnce()
19
+	{
20
+		$createdMessage = 'Created "contact" UserDefinedForm';
21
+
22
+		$task = new PopulateThemeSampleDataTask;
23
+
24
+		// Run the task
25
+		$this->assertContains($createdMessage, $this->bufferedTask($task));
26
+
27
+		// Run a second time
28
+		$this->assertNotContains($createdMessage, $this->bufferedTask($task));
29
+
30
+		// Change the page name
31
+		$form = UserDefinedForm::get()->filter('URLSegment', 'contact')->first();
32
+		$form->URLSegment = 'testing';
33
+		$form->write();
34
+
35
+		// Ensure the old version is still detected in draft, so not recreated
36
+		$this->assertNotContains($createdMessage, $this->bufferedTask($task));
37
+
38
+		// Delete the page, then ensure it's recreated again (DataObject::delete will remove staged versions)
39
+		$form->delete();
40
+		$this->assertContains($createdMessage, $this->bufferedTask($task));
41
+	}
42
+
43
+	/**
44
+	 * Run a BuildTask while buffering its output, and return the result
45
+	 *
46
+	 * @param  BuildTask $task
47
+	 * @return string
48
+	 */
49
+	protected function bufferedTask(BuildTask $task)
50
+	{
51
+		ob_start();
52
+		$task->run(new HTTPRequest('GET', '/'));
53
+		return ob_get_clean();
54
+	}
55 55
 }
Please login to merge, or discard this patch.
src/PageTypes/BasePageController.php 1 patch
Indentation   +345 added lines, -345 removed lines patch added patch discarded remove patch
@@ -22,355 +22,355 @@
 block discarded – undo
22 22
 
23 23
 class BasePageController extends ContentController
24 24
 {
25
-    private static $allowed_actions = [
26
-        'downloadpdf',
27
-        'SearchForm',
28
-        'results',
29
-    ];
30
-
31
-    /**
32
-     * How many search results should be shown per-page?
33
-     * @var int
34
-     */
35
-    public static $results_per_page = 10;
36
-
37
-    public static $search_index_class = CwpSolrIndex::class;
38
-
39
-    /**
40
-     * If spelling suggestions for searches are given, enable
41
-     * suggested searches to be followed immediately
42
-     *
43
-     * @config
44
-     * @var bool
45
-     */
46
-    private static $search_follow_suggestions = true;
47
-
48
-    /**
49
-     * Which classes should be queried when searching?
50
-     * @var array
51
-     */
52
-    public static $classes_to_search = [
53
-        [
54
-            'class' => 'Page',
55
-            'includeSubclasses' => true,
56
-        ]
57
-    ];
58
-
59
-    /**
60
-     * Serve the page rendered as PDF.
61
-     */
62
-    public function downloadpdf()
63
-    {
64
-        if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
65
-            return false;
66
-        }
67
-
68
-        // We only allow producing live pdf. There is no way to secure the draft files.
69
-        Versioned::set_stage(Versioned::LIVE);
70
-
71
-        $path = $this->dataRecord->getPdfFilename();
72
-        if (!file_exists($path)) {
73
-            $this->generatePDF();
74
-        }
75
-
76
-        return HTTPRequest::send_file(file_get_contents($path), basename($path), 'application/pdf');
77
-    }
78
-
79
-    /*
25
+	private static $allowed_actions = [
26
+		'downloadpdf',
27
+		'SearchForm',
28
+		'results',
29
+	];
30
+
31
+	/**
32
+	 * How many search results should be shown per-page?
33
+	 * @var int
34
+	 */
35
+	public static $results_per_page = 10;
36
+
37
+	public static $search_index_class = CwpSolrIndex::class;
38
+
39
+	/**
40
+	 * If spelling suggestions for searches are given, enable
41
+	 * suggested searches to be followed immediately
42
+	 *
43
+	 * @config
44
+	 * @var bool
45
+	 */
46
+	private static $search_follow_suggestions = true;
47
+
48
+	/**
49
+	 * Which classes should be queried when searching?
50
+	 * @var array
51
+	 */
52
+	public static $classes_to_search = [
53
+		[
54
+			'class' => 'Page',
55
+			'includeSubclasses' => true,
56
+		]
57
+	];
58
+
59
+	/**
60
+	 * Serve the page rendered as PDF.
61
+	 */
62
+	public function downloadpdf()
63
+	{
64
+		if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
65
+			return false;
66
+		}
67
+
68
+		// We only allow producing live pdf. There is no way to secure the draft files.
69
+		Versioned::set_stage(Versioned::LIVE);
70
+
71
+		$path = $this->dataRecord->getPdfFilename();
72
+		if (!file_exists($path)) {
73
+			$this->generatePDF();
74
+		}
75
+
76
+		return HTTPRequest::send_file(file_get_contents($path), basename($path), 'application/pdf');
77
+	}
78
+
79
+	/*
80 80
     * This will return either pdf_base_url from YML, CWP_SECURE_DOMAIN
81 81
     * from _ss_environment, or blank. In that order of importance.
82 82
     */
83
-    public function getPDFBaseURL()
84
-    {
85
-        //if base url YML is defined in YML, use that
86
-        if (Config::inst()->get(BasePage::class, 'pdf_base_url')) {
87
-            $pdfBaseUrl = Config::inst()->get(BasePage::class, 'pdf_base_url').'/';
88
-            //otherwise, if we are CWP use the secure domain
89
-        } elseif (Environment::getEnv('CWP_SECURE_DOMAIN')) {
90
-            $pdfBaseUrl = Environment::getEnv('CWP_SECURE_DOMAIN') . '/';
91
-            //or if neither, leave blank
92
-        } else {
93
-            $pdfBaseUrl = '';
94
-        }
95
-        return $pdfBaseUrl;
96
-    }
97
-
98
-    /*
83
+	public function getPDFBaseURL()
84
+	{
85
+		//if base url YML is defined in YML, use that
86
+		if (Config::inst()->get(BasePage::class, 'pdf_base_url')) {
87
+			$pdfBaseUrl = Config::inst()->get(BasePage::class, 'pdf_base_url').'/';
88
+			//otherwise, if we are CWP use the secure domain
89
+		} elseif (Environment::getEnv('CWP_SECURE_DOMAIN')) {
90
+			$pdfBaseUrl = Environment::getEnv('CWP_SECURE_DOMAIN') . '/';
91
+			//or if neither, leave blank
92
+		} else {
93
+			$pdfBaseUrl = '';
94
+		}
95
+		return $pdfBaseUrl;
96
+	}
97
+
98
+	/*
99 99
     * Don't use the proxy if the pdf domain is the CWP secure domain
100 100
     * Or if we aren't on a CWP server
101 101
     */
102
-    public function getPDFProxy($pdfBaseUrl)
103
-    {
104
-        if (!defined('CWP_SECURE_DOMAIN') || $pdfBaseUrl == CWP_SECURE_DOMAIN.'/') {
105
-            $proxy = '';
106
-        } else {
107
-            $proxy = ' --proxy ' . SS_OUTBOUND_PROXY . ':' . SS_OUTBOUND_PROXY_PORT;
108
-        }
109
-        return $proxy;
110
-    }
111
-
112
-    /**
113
-     * Render the page as PDF using wkhtmltopdf.
114
-     */
115
-    public function generatePDF()
116
-    {
117
-        if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
118
-            return false;
119
-        }
120
-
121
-        $binaryPath = Config::inst()->get(BasePage::class, 'wkhtmltopdf_binary');
122
-        if (!$binaryPath || !is_executable($binaryPath)) {
123
-            if (defined('WKHTMLTOPDF_BINARY') && is_executable(WKHTMLTOPDF_BINARY)) {
124
-                $binaryPath = WKHTMLTOPDF_BINARY;
125
-            }
126
-        }
127
-
128
-        if (!$binaryPath) {
129
-            user_error('Neither WKHTMLTOPDF_BINARY nor BasePage.wkhtmltopdf_binary are defined', E_USER_ERROR);
130
-        }
131
-
132
-        if (Versioned::get_reading_mode() == 'Stage.Stage') {
133
-            user_error('Generating PDFs on draft is not supported', E_USER_ERROR);
134
-        }
135
-
136
-        set_time_limit(60);
137
-
138
-        // prepare the paths
139
-        $pdfFile = $this->dataRecord->getPdfFilename();
140
-        $bodyFile = str_replace('.pdf', '_pdf.html', $pdfFile);
141
-        $footerFile = str_replace('.pdf', '_pdffooter.html', $pdfFile);
142
-
143
-        // make sure the work directory exists
144
-        if (!file_exists(dirname($pdfFile))) {
145
-            Filesystem::makeFolder(dirname($pdfFile));
146
-        }
147
-
148
-        //decide the domain to use in generation
149
-        $pdfBaseUrl = $this->getPDFBaseURL();
150
-
151
-        // Force http protocol on CWP - fetching from localhost without using the proxy, SSL terminates on gateway.
152
-        if (defined('CWP_ENVIRONMENT')) {
153
-            Config::inst()->nest();
154
-            Config::inst()->update(Director::class, 'alternate_protocol', 'http');
155
-            //only set alternate protocol if CWP_SECURE_DOMAIN is defined OR pdf_base_url is
156
-            if ($pdfBaseUrl) {
157
-                Config::inst()->update(Director::class, 'alternate_base_url', 'http://'.$pdfBaseUrl);
158
-            }
159
-        }
160
-
161
-        $bodyViewer = $this->getViewer('pdf');
162
-
163
-        // write the output of this page to HTML, ready for conversion to PDF
164
-        file_put_contents($bodyFile, $bodyViewer->process($this));
165
-
166
-        // get the viewer for the current template with _pdffooter
167
-        $footerViewer = $this->getViewer('pdffooter');
168
-
169
-        // write the output of the footer template to HTML, ready for conversion to PDF
170
-        file_put_contents($footerFile, $footerViewer->process($this));
171
-
172
-        if (defined('CWP_ENVIRONMENT')) {
173
-            Config::inst()->unnest();
174
-        }
175
-
176
-        //decide what the proxy should look like
177
-        $proxy = $this->getPDFProxy($pdfBaseUrl);
178
-
179
-        // finally, generate the PDF
180
-        $command = $binaryPath . $proxy . ' --outline -B 40pt -L 20pt -R 20pt -T 20pt --encoding utf-8 '
181
-            . '--orientation Portrait --disable-javascript --quiet --print-media-type ';
182
-        $retVal = 0;
183
-        $output = array();
184
-        exec(
185
-            $command . " --footer-html \"$footerFile\" \"$bodyFile\" \"$pdfFile\" &> /dev/stdout",
186
-            $output,
187
-            $retVal
188
-        );
189
-
190
-        // remove temporary file
191
-        unlink($bodyFile);
192
-        unlink($footerFile);
193
-
194
-        // output any errors
195
-        if ($retVal != 0) {
196
-            user_error('wkhtmltopdf failed: ' . implode("\n", $output), E_USER_ERROR);
197
-        }
198
-
199
-        // serve the generated file
200
-        return HTTPRequest::send_file(file_get_contents($pdfFile), basename($pdfFile), 'application/pdf');
201
-    }
202
-
203
-    /**
204
-     * Site search form
205
-     */
206
-    public function SearchForm()
207
-    {
208
-        $searchText = $this->getRequest()->getVar('Search');
209
-
210
-        $fields = FieldList::create(
211
-            TextField::create('Search', false, $searchText)
212
-        );
213
-        $actions = FieldList::create(
214
-            FormAction::create('results', _t('SearchForm.GO', 'Go'))
215
-        );
216
-
217
-        $form = SearchForm::create($this, SearchForm::class, $fields, $actions);
218
-        $form->setFormAction('search/SearchForm');
219
-
220
-        return $form;
221
-    }
222
-
223
-    /**
224
-     * Get search form with _header suffix
225
-     *
226
-     * @return SearchForm
227
-     */
228
-    public function HeaderSearchForm()
229
-    {
230
-        return $this->SearchForm()->setTemplate('SearchForm_header');
231
-    }
232
-
233
-    /**
234
-     * Process and render search results.
235
-     *
236
-     * @param array $data The raw request data submitted by user
237
-     * @param SearchForm $form The form instance that was submitted
238
-     * @param HTTPRequest $request Request generated for this action
239
-     * @return DBHTMLText
240
-     */
241
-    public function results($data, $form, $request)
242
-    {
243
-        // Check parameters for terms, pagination, and if we should follow suggestions
244
-        $keywords = empty($data['Search']) ? '' : $data['Search'];
245
-        $start = isset($data['start']) ? $data['start'] : 0;
246
-        $suggestions = isset($data['suggestions'])
247
-            ? $data['suggestions']
248
-            : $this->config()->search_follow_suggestions;
249
-
250
-        $results = CwpSearchEngine::create()
251
-            ->search(
252
-                $keywords,
253
-                $this->getClassesToSearch(),
254
-                $this->getSearchIndex(),
255
-                $this->getSearchPageSize(),
256
-                $start,
257
-                $suggestions
258
-            );
259
-
260
-        // Customise content with these results
261
-        $properties = array(
262
-            'MetaTitle' => _t('CWP_Search.MetaTitle', 'Search {keywords}', array('keywords' => $keywords)),
263
-            'NoSearchResults' => _t('CWP_Search.NoResult', 'Sorry, your search query did not return any results.'),
264
-            'EmptySearch' => _t('CWP_Search.EmptySearch', 'Search field empty, please enter your search query.'),
265
-            'PdfLink' => '',
266
-            'Title' => _t('SearchForm.SearchResults', 'Search Results'),
267
-        );
268
-        $this->extend('updateSearchResults', $results, $properties);
269
-
270
-        // Customise page
271
-        $response = $this->customise($properties);
272
-        if ($results) {
273
-            $response = $response
274
-                ->customise($results)
275
-                ->customise(array( 'Results' => $results->getResults() ));
276
-        }
277
-
278
-        // Render
279
-        $templates = $this->getResultsTemplate($request);
280
-        return $response->renderWith($templates);
281
-    }
282
-
283
-    /**
284
-     * Select the template to render search results with
285
-     *
286
-     * @param HTTPRequest $request
287
-     * @return array
288
-     */
289
-    protected function getResultsTemplate($request)
290
-    {
291
-        $templates = array('Page_results', 'Page');
292
-        if ($request->getVar('format') == 'rss') {
293
-            array_unshift($templates, 'Page_results_rss');
294
-        }
295
-        if ($request->getVar('format') == 'atom') {
296
-            array_unshift($templates, 'Page_results_atom');
297
-        }
298
-        return $templates;
299
-    }
300
-
301
-    /**
302
-     * Provide scripts as needed by the *default* theme.
303
-     * Override this function if you are using a custom theme based on the *default*.
304
-     *
305
-     * @deprecated 1.6..2.0 Use "starter" theme instead
306
-     */
307
-    public function getBaseScripts()
308
-    {
309
-        $scripts = array();
310
-        $this->extend('updateBaseScripts', $scripts);
311
-        return $scripts;
312
-    }
313
-
314
-    /**
315
-     * Provide stylesheets, as needed by the *default* theme assumed by this recipe.
316
-     * Override this function if you are using a custom theme based on the *default*.
317
-     *
318
-     * @deprecated 1.6..2.0 Use "starter" theme instead
319
-     */
320
-    public function getBaseStyles()
321
-    {
322
-        $styles = array();
323
-        $this->extend('updateBaseStyles', $styles);
324
-        return $styles;
325
-    }
326
-
327
-    /**
328
-     * Provide current year.
329
-     */
330
-    public function CurrentDatetime()
331
-    {
332
-        return DBDatetime::now();
333
-    }
334
-
335
-    public function getRSSLink()
336
-    {
337
-    }
338
-
339
-    /**
340
-     * Get the search index registered for this application
341
-     *
342
-     * @return CwpSearchIndex
343
-     */
344
-    protected function getSearchIndex()
345
-    {
346
-        // Will be a service name in 2.0 and returned via injector
347
-        /** @var CwpSearchIndex $index */
348
-        $index = null;
349
-        if (self::$search_index_class) {
350
-            $index = Injector::inst()->get(self::$search_index_class);
351
-        }
352
-        return $index;
353
-    }
354
-
355
-    /**
356
-     * Gets the list of configured classes to search
357
-     *
358
-     * @return array
359
-     */
360
-    protected function getClassesToSearch()
361
-    {
362
-        // Will be private static config in 2.0
363
-        return self::$classes_to_search;
364
-    }
365
-
366
-    /**
367
-     * Get page size for search
368
-     *
369
-     * @return int
370
-     */
371
-    protected function getSearchPageSize()
372
-    {
373
-        // Will be private static config in 2.0
374
-        return self::$results_per_page;
375
-    }
102
+	public function getPDFProxy($pdfBaseUrl)
103
+	{
104
+		if (!defined('CWP_SECURE_DOMAIN') || $pdfBaseUrl == CWP_SECURE_DOMAIN.'/') {
105
+			$proxy = '';
106
+		} else {
107
+			$proxy = ' --proxy ' . SS_OUTBOUND_PROXY . ':' . SS_OUTBOUND_PROXY_PORT;
108
+		}
109
+		return $proxy;
110
+	}
111
+
112
+	/**
113
+	 * Render the page as PDF using wkhtmltopdf.
114
+	 */
115
+	public function generatePDF()
116
+	{
117
+		if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
118
+			return false;
119
+		}
120
+
121
+		$binaryPath = Config::inst()->get(BasePage::class, 'wkhtmltopdf_binary');
122
+		if (!$binaryPath || !is_executable($binaryPath)) {
123
+			if (defined('WKHTMLTOPDF_BINARY') && is_executable(WKHTMLTOPDF_BINARY)) {
124
+				$binaryPath = WKHTMLTOPDF_BINARY;
125
+			}
126
+		}
127
+
128
+		if (!$binaryPath) {
129
+			user_error('Neither WKHTMLTOPDF_BINARY nor BasePage.wkhtmltopdf_binary are defined', E_USER_ERROR);
130
+		}
131
+
132
+		if (Versioned::get_reading_mode() == 'Stage.Stage') {
133
+			user_error('Generating PDFs on draft is not supported', E_USER_ERROR);
134
+		}
135
+
136
+		set_time_limit(60);
137
+
138
+		// prepare the paths
139
+		$pdfFile = $this->dataRecord->getPdfFilename();
140
+		$bodyFile = str_replace('.pdf', '_pdf.html', $pdfFile);
141
+		$footerFile = str_replace('.pdf', '_pdffooter.html', $pdfFile);
142
+
143
+		// make sure the work directory exists
144
+		if (!file_exists(dirname($pdfFile))) {
145
+			Filesystem::makeFolder(dirname($pdfFile));
146
+		}
147
+
148
+		//decide the domain to use in generation
149
+		$pdfBaseUrl = $this->getPDFBaseURL();
150
+
151
+		// Force http protocol on CWP - fetching from localhost without using the proxy, SSL terminates on gateway.
152
+		if (defined('CWP_ENVIRONMENT')) {
153
+			Config::inst()->nest();
154
+			Config::inst()->update(Director::class, 'alternate_protocol', 'http');
155
+			//only set alternate protocol if CWP_SECURE_DOMAIN is defined OR pdf_base_url is
156
+			if ($pdfBaseUrl) {
157
+				Config::inst()->update(Director::class, 'alternate_base_url', 'http://'.$pdfBaseUrl);
158
+			}
159
+		}
160
+
161
+		$bodyViewer = $this->getViewer('pdf');
162
+
163
+		// write the output of this page to HTML, ready for conversion to PDF
164
+		file_put_contents($bodyFile, $bodyViewer->process($this));
165
+
166
+		// get the viewer for the current template with _pdffooter
167
+		$footerViewer = $this->getViewer('pdffooter');
168
+
169
+		// write the output of the footer template to HTML, ready for conversion to PDF
170
+		file_put_contents($footerFile, $footerViewer->process($this));
171
+
172
+		if (defined('CWP_ENVIRONMENT')) {
173
+			Config::inst()->unnest();
174
+		}
175
+
176
+		//decide what the proxy should look like
177
+		$proxy = $this->getPDFProxy($pdfBaseUrl);
178
+
179
+		// finally, generate the PDF
180
+		$command = $binaryPath . $proxy . ' --outline -B 40pt -L 20pt -R 20pt -T 20pt --encoding utf-8 '
181
+			. '--orientation Portrait --disable-javascript --quiet --print-media-type ';
182
+		$retVal = 0;
183
+		$output = array();
184
+		exec(
185
+			$command . " --footer-html \"$footerFile\" \"$bodyFile\" \"$pdfFile\" &> /dev/stdout",
186
+			$output,
187
+			$retVal
188
+		);
189
+
190
+		// remove temporary file
191
+		unlink($bodyFile);
192
+		unlink($footerFile);
193
+
194
+		// output any errors
195
+		if ($retVal != 0) {
196
+			user_error('wkhtmltopdf failed: ' . implode("\n", $output), E_USER_ERROR);
197
+		}
198
+
199
+		// serve the generated file
200
+		return HTTPRequest::send_file(file_get_contents($pdfFile), basename($pdfFile), 'application/pdf');
201
+	}
202
+
203
+	/**
204
+	 * Site search form
205
+	 */
206
+	public function SearchForm()
207
+	{
208
+		$searchText = $this->getRequest()->getVar('Search');
209
+
210
+		$fields = FieldList::create(
211
+			TextField::create('Search', false, $searchText)
212
+		);
213
+		$actions = FieldList::create(
214
+			FormAction::create('results', _t('SearchForm.GO', 'Go'))
215
+		);
216
+
217
+		$form = SearchForm::create($this, SearchForm::class, $fields, $actions);
218
+		$form->setFormAction('search/SearchForm');
219
+
220
+		return $form;
221
+	}
222
+
223
+	/**
224
+	 * Get search form with _header suffix
225
+	 *
226
+	 * @return SearchForm
227
+	 */
228
+	public function HeaderSearchForm()
229
+	{
230
+		return $this->SearchForm()->setTemplate('SearchForm_header');
231
+	}
232
+
233
+	/**
234
+	 * Process and render search results.
235
+	 *
236
+	 * @param array $data The raw request data submitted by user
237
+	 * @param SearchForm $form The form instance that was submitted
238
+	 * @param HTTPRequest $request Request generated for this action
239
+	 * @return DBHTMLText
240
+	 */
241
+	public function results($data, $form, $request)
242
+	{
243
+		// Check parameters for terms, pagination, and if we should follow suggestions
244
+		$keywords = empty($data['Search']) ? '' : $data['Search'];
245
+		$start = isset($data['start']) ? $data['start'] : 0;
246
+		$suggestions = isset($data['suggestions'])
247
+			? $data['suggestions']
248
+			: $this->config()->search_follow_suggestions;
249
+
250
+		$results = CwpSearchEngine::create()
251
+			->search(
252
+				$keywords,
253
+				$this->getClassesToSearch(),
254
+				$this->getSearchIndex(),
255
+				$this->getSearchPageSize(),
256
+				$start,
257
+				$suggestions
258
+			);
259
+
260
+		// Customise content with these results
261
+		$properties = array(
262
+			'MetaTitle' => _t('CWP_Search.MetaTitle', 'Search {keywords}', array('keywords' => $keywords)),
263
+			'NoSearchResults' => _t('CWP_Search.NoResult', 'Sorry, your search query did not return any results.'),
264
+			'EmptySearch' => _t('CWP_Search.EmptySearch', 'Search field empty, please enter your search query.'),
265
+			'PdfLink' => '',
266
+			'Title' => _t('SearchForm.SearchResults', 'Search Results'),
267
+		);
268
+		$this->extend('updateSearchResults', $results, $properties);
269
+
270
+		// Customise page
271
+		$response = $this->customise($properties);
272
+		if ($results) {
273
+			$response = $response
274
+				->customise($results)
275
+				->customise(array( 'Results' => $results->getResults() ));
276
+		}
277
+
278
+		// Render
279
+		$templates = $this->getResultsTemplate($request);
280
+		return $response->renderWith($templates);
281
+	}
282
+
283
+	/**
284
+	 * Select the template to render search results with
285
+	 *
286
+	 * @param HTTPRequest $request
287
+	 * @return array
288
+	 */
289
+	protected function getResultsTemplate($request)
290
+	{
291
+		$templates = array('Page_results', 'Page');
292
+		if ($request->getVar('format') == 'rss') {
293
+			array_unshift($templates, 'Page_results_rss');
294
+		}
295
+		if ($request->getVar('format') == 'atom') {
296
+			array_unshift($templates, 'Page_results_atom');
297
+		}
298
+		return $templates;
299
+	}
300
+
301
+	/**
302
+	 * Provide scripts as needed by the *default* theme.
303
+	 * Override this function if you are using a custom theme based on the *default*.
304
+	 *
305
+	 * @deprecated 1.6..2.0 Use "starter" theme instead
306
+	 */
307
+	public function getBaseScripts()
308
+	{
309
+		$scripts = array();
310
+		$this->extend('updateBaseScripts', $scripts);
311
+		return $scripts;
312
+	}
313
+
314
+	/**
315
+	 * Provide stylesheets, as needed by the *default* theme assumed by this recipe.
316
+	 * Override this function if you are using a custom theme based on the *default*.
317
+	 *
318
+	 * @deprecated 1.6..2.0 Use "starter" theme instead
319
+	 */
320
+	public function getBaseStyles()
321
+	{
322
+		$styles = array();
323
+		$this->extend('updateBaseStyles', $styles);
324
+		return $styles;
325
+	}
326
+
327
+	/**
328
+	 * Provide current year.
329
+	 */
330
+	public function CurrentDatetime()
331
+	{
332
+		return DBDatetime::now();
333
+	}
334
+
335
+	public function getRSSLink()
336
+	{
337
+	}
338
+
339
+	/**
340
+	 * Get the search index registered for this application
341
+	 *
342
+	 * @return CwpSearchIndex
343
+	 */
344
+	protected function getSearchIndex()
345
+	{
346
+		// Will be a service name in 2.0 and returned via injector
347
+		/** @var CwpSearchIndex $index */
348
+		$index = null;
349
+		if (self::$search_index_class) {
350
+			$index = Injector::inst()->get(self::$search_index_class);
351
+		}
352
+		return $index;
353
+	}
354
+
355
+	/**
356
+	 * Gets the list of configured classes to search
357
+	 *
358
+	 * @return array
359
+	 */
360
+	protected function getClassesToSearch()
361
+	{
362
+		// Will be private static config in 2.0
363
+		return self::$classes_to_search;
364
+	}
365
+
366
+	/**
367
+	 * Get page size for search
368
+	 *
369
+	 * @return int
370
+	 */
371
+	protected function getSearchPageSize()
372
+	{
373
+		// Will be private static config in 2.0
374
+		return self::$results_per_page;
375
+	}
376 376
 }
Please login to merge, or discard this patch.
src/PageTypes/FooterHolder.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -14,54 +14,54 @@
 block discarded – undo
14 14
 class FooterHolder extends RedirectorPage
15 15
 {
16 16
 
17
-    private static $description = 'Holder page that displays all child pages as links in the footer';
17
+	private static $description = 'Holder page that displays all child pages as links in the footer';
18 18
 
19
-    private static $singular_name = 'Footer Holder';
19
+	private static $singular_name = 'Footer Holder';
20 20
 
21
-    private static $plural_name = 'Footer Holders';
21
+	private static $plural_name = 'Footer Holders';
22 22
 
23
-    private static $defaults = [
24
-        'ShowInMenus' => 0,
25
-        'ShowInSearch' => 0,
26
-    ];
23
+	private static $defaults = [
24
+		'ShowInMenus' => 0,
25
+		'ShowInSearch' => 0,
26
+	];
27 27
 
28
-    private static $table_name = 'FooterHolder';
28
+	private static $table_name = 'FooterHolder';
29 29
 
30
-    public function getCMSFields()
31
-    {
32
-        $this->beforeUpdateCMSFields(function (FieldList $fields) {
33
-            $fields->removeByName('RedirectorDescHeader');
34
-            $fields->removeByName('RedirectionType');
35
-            $fields->removeByName('LinkToID');
36
-            $fields->removeByName('ExternalURL');
37
-        });
38
-        return parent::getCMSFields();
39
-    }
30
+	public function getCMSFields()
31
+	{
32
+		$this->beforeUpdateCMSFields(function (FieldList $fields) {
33
+			$fields->removeByName('RedirectorDescHeader');
34
+			$fields->removeByName('RedirectionType');
35
+			$fields->removeByName('LinkToID');
36
+			$fields->removeByName('ExternalURL');
37
+		});
38
+		return parent::getCMSFields();
39
+	}
40 40
 
41
-    /**
42
-     * Return the link to the first child page.
43
-     */
44
-    public function redirectionLink()
45
-    {
46
-        $childPage = $this->Children()->first();
41
+	/**
42
+	 * Return the link to the first child page.
43
+	 */
44
+	public function redirectionLink()
45
+	{
46
+		$childPage = $this->Children()->first();
47 47
 
48
-        if ($childPage) {
49
-            // If we're linking to another redirectorpage then just return the URLSegment, to prevent a cycle of
50
-            // redirector pages from causing an infinite loop.  Instead, they will cause a 30x redirection loop in
51
-            // the browser, but this can be handled sufficiently gracefully by the browser.
52
-            if ($childPage instanceof RedirectorPage) {
53
-                return $childPage->regularLink();
54
-            }
55
-            // For all other pages, just return the link of the page.
56
-            return $childPage->Link();
57
-        }
58
-    }
48
+		if ($childPage) {
49
+			// If we're linking to another redirectorpage then just return the URLSegment, to prevent a cycle of
50
+			// redirector pages from causing an infinite loop.  Instead, they will cause a 30x redirection loop in
51
+			// the browser, but this can be handled sufficiently gracefully by the browser.
52
+			if ($childPage instanceof RedirectorPage) {
53
+				return $childPage->regularLink();
54
+			}
55
+			// For all other pages, just return the link of the page.
56
+			return $childPage->Link();
57
+		}
58
+	}
59 59
 
60
-    public function syncLinkTracking()
61
-    {
62
-        // If we don't have anything to link to, then we have a broken link.
63
-        if (!$this->Children()) {
64
-            $this->HasBrokenLink = true;
65
-        }
66
-    }
60
+	public function syncLinkTracking()
61
+	{
62
+		// If we don't have anything to link to, then we have a broken link.
63
+		if (!$this->Children()) {
64
+			$this->HasBrokenLink = true;
65
+		}
66
+	}
67 67
 }
Please login to merge, or discard this patch.
src/PageTypes/DatedUpdateHolderController.php 1 patch
Indentation   +332 added lines, -332 removed lines patch added patch discarded remove patch
@@ -32,347 +32,347 @@
 block discarded – undo
32 32
  */
33 33
 class DatedUpdateHolderController extends PageController
34 34
 {
35
-    private static $allowed_actions = [
36
-        'rss',
37
-        'atom',
38
-        'DateRangeForm',
39
-    ];
40
-
41
-    private static $casting = [
42
-        'MetaTitle' => 'Text',
43
-        'FilterDescription' => 'Text',
44
-    ];
45
-
46
-    /**
47
-     * Get the meta title for the current action
48
-     *
49
-     * @return string
50
-     */
51
-    public function getMetaTitle()
52
-    {
53
-        $title = $this->data()->getTitle();
54
-        $filter = $this->FilterDescription();
55
-        if ($filter) {
56
-            $title = "{$title} - {$filter}";
57
-        }
58
-
59
-        $this->extend('updateMetaTitle', $title);
60
-        return $title;
61
-    }
62
-
63
-    /**
64
-     * Returns a description of the current filter
65
-     *
66
-     * @return string
67
-     */
68
-    public function FilterDescription()
69
-    {
70
-        $params = $this->parseParams();
71
-
72
-        $filters = array();
73
-        if ($params['tag']) {
74
-            $term = TaxonomyTerm::get_by_id(TaxonomyTerm::class, $params['tag']);
75
-            if ($term) {
76
-                $filters[] = _t('DatedUpdateHolder.FILTER_WITHIN', 'within') . ' "' . $term->Name . '"';
77
-            }
78
-        }
79
-
80
-        if ($params['from'] || $params['to']) {
81
-            if ($params['from']) {
82
-                $from = strtotime($params['from']);
83
-                if ($params['to']) {
84
-                    $to = strtotime($params['to']);
85
-                    $filters[] = _t('DatedUpdateHolder.FILTER_BETWEEN', 'between') . ' '
86
-                        . date('j/m/Y', $from) . ' and ' . date('j/m/Y', $to);
87
-                } else {
88
-                    $filters[] = _t('DatedUpdateHolder.FILTER_ON', 'on') . ' ' . date('j/m/Y', $from);
89
-                }
90
-            } else {
91
-                $to = strtotime($params['to']);
92
-                $filters[] = _t('DatedUpdateHolder.FILTER_ON', 'on') . ' ' . date('j/m/Y', $to);
93
-            }
94
-        }
95
-
96
-        if ($params['year'] && $params['month']) {
97
-            $timestamp = mktime(1, 1, 1, $params['month'], 1, $params['year']);
98
-            $filters[] = _t('DatedUpdateHolder.FILTER_IN', 'in') . ' ' . date('F', $timestamp) . ' ' . $params['year'];
99
-        }
100
-
101
-        if ($filters) {
102
-            return $this->getUpdateName() . ' ' . implode(' ', $filters);
103
-        }
104
-    }
105
-
106
-    public function getUpdateName()
107
-    {
108
-        return Config::inst()->get($this->data()->ClassName, 'update_name');
109
-    }
110
-
111
-    protected function init()
112
-    {
113
-        parent::init();
114
-        RSSFeed::linkToFeed($this->Link() . 'rss', $this->getSubscriptionTitle());
115
-    }
116
-
117
-    /**
118
-     * Parse URL parameters.
119
-     *
120
-     * @param bool $produceErrorMessages Set to false to omit session messages.
121
-     */
122
-    public function parseParams($produceErrorMessages = true)
123
-    {
124
-        $tag = $this->request->getVar('tag');
125
-        $from = $this->request->getVar('from');
126
-        $to = $this->request->getVar('to');
127
-        $year = $this->request->getVar('year');
128
-        $month = $this->request->getVar('month');
129
-
130
-        if ($tag == '') {
131
-            $tag = null;
132
-        }
133
-        if ($from == '') {
134
-            $from = null;
135
-        }
136
-        if ($to == '') {
137
-            $to = null;
138
-        }
139
-        if ($year == '') {
140
-            $year = null;
141
-        }
142
-        if ($month == '') {
143
-            $month = null;
144
-        }
145
-
146
-        if (isset($tag)) {
147
-            $tag = (int)$tag;
148
-        }
149
-        if (isset($from)) {
150
-            $from = urldecode($from);
151
-            $parser = DBDatetime::create();
152
-            $parser->setValue($from);
153
-            $from = $parser->Format('y-MM-dd');
154
-        }
155
-        if (isset($to)) {
156
-            $to = urldecode($to);
157
-            $parser = DBDatetime::create();
158
-            $parser->setValue($to);
159
-            $to = $parser->Format('y-MM-dd');
160
-        }
161
-        if (isset($year)) {
162
-            $year = (int)$year;
163
-        }
164
-        if (isset($month)) {
165
-            $month = (int)$month;
166
-        }
167
-
168
-        // If only "To" has been provided filter by single date. Normalise by swapping with "From".
169
-        if (isset($to) && !isset($from)) {
170
-            list($to, $from) = array($from, $to);
171
-        }
172
-
173
-        // Flip the dates if the order is wrong.
174
-        if (isset($to) && isset($from) && strtotime($from)>strtotime($to)) {
175
-            list($to, $from) = array($from, $to);
176
-
177
-            if ($produceErrorMessages) {
178
-                // @todo replace
35
+	private static $allowed_actions = [
36
+		'rss',
37
+		'atom',
38
+		'DateRangeForm',
39
+	];
40
+
41
+	private static $casting = [
42
+		'MetaTitle' => 'Text',
43
+		'FilterDescription' => 'Text',
44
+	];
45
+
46
+	/**
47
+	 * Get the meta title for the current action
48
+	 *
49
+	 * @return string
50
+	 */
51
+	public function getMetaTitle()
52
+	{
53
+		$title = $this->data()->getTitle();
54
+		$filter = $this->FilterDescription();
55
+		if ($filter) {
56
+			$title = "{$title} - {$filter}";
57
+		}
58
+
59
+		$this->extend('updateMetaTitle', $title);
60
+		return $title;
61
+	}
62
+
63
+	/**
64
+	 * Returns a description of the current filter
65
+	 *
66
+	 * @return string
67
+	 */
68
+	public function FilterDescription()
69
+	{
70
+		$params = $this->parseParams();
71
+
72
+		$filters = array();
73
+		if ($params['tag']) {
74
+			$term = TaxonomyTerm::get_by_id(TaxonomyTerm::class, $params['tag']);
75
+			if ($term) {
76
+				$filters[] = _t('DatedUpdateHolder.FILTER_WITHIN', 'within') . ' "' . $term->Name . '"';
77
+			}
78
+		}
79
+
80
+		if ($params['from'] || $params['to']) {
81
+			if ($params['from']) {
82
+				$from = strtotime($params['from']);
83
+				if ($params['to']) {
84
+					$to = strtotime($params['to']);
85
+					$filters[] = _t('DatedUpdateHolder.FILTER_BETWEEN', 'between') . ' '
86
+						. date('j/m/Y', $from) . ' and ' . date('j/m/Y', $to);
87
+				} else {
88
+					$filters[] = _t('DatedUpdateHolder.FILTER_ON', 'on') . ' ' . date('j/m/Y', $from);
89
+				}
90
+			} else {
91
+				$to = strtotime($params['to']);
92
+				$filters[] = _t('DatedUpdateHolder.FILTER_ON', 'on') . ' ' . date('j/m/Y', $to);
93
+			}
94
+		}
95
+
96
+		if ($params['year'] && $params['month']) {
97
+			$timestamp = mktime(1, 1, 1, $params['month'], 1, $params['year']);
98
+			$filters[] = _t('DatedUpdateHolder.FILTER_IN', 'in') . ' ' . date('F', $timestamp) . ' ' . $params['year'];
99
+		}
100
+
101
+		if ($filters) {
102
+			return $this->getUpdateName() . ' ' . implode(' ', $filters);
103
+		}
104
+	}
105
+
106
+	public function getUpdateName()
107
+	{
108
+		return Config::inst()->get($this->data()->ClassName, 'update_name');
109
+	}
110
+
111
+	protected function init()
112
+	{
113
+		parent::init();
114
+		RSSFeed::linkToFeed($this->Link() . 'rss', $this->getSubscriptionTitle());
115
+	}
116
+
117
+	/**
118
+	 * Parse URL parameters.
119
+	 *
120
+	 * @param bool $produceErrorMessages Set to false to omit session messages.
121
+	 */
122
+	public function parseParams($produceErrorMessages = true)
123
+	{
124
+		$tag = $this->request->getVar('tag');
125
+		$from = $this->request->getVar('from');
126
+		$to = $this->request->getVar('to');
127
+		$year = $this->request->getVar('year');
128
+		$month = $this->request->getVar('month');
129
+
130
+		if ($tag == '') {
131
+			$tag = null;
132
+		}
133
+		if ($from == '') {
134
+			$from = null;
135
+		}
136
+		if ($to == '') {
137
+			$to = null;
138
+		}
139
+		if ($year == '') {
140
+			$year = null;
141
+		}
142
+		if ($month == '') {
143
+			$month = null;
144
+		}
145
+
146
+		if (isset($tag)) {
147
+			$tag = (int)$tag;
148
+		}
149
+		if (isset($from)) {
150
+			$from = urldecode($from);
151
+			$parser = DBDatetime::create();
152
+			$parser->setValue($from);
153
+			$from = $parser->Format('y-MM-dd');
154
+		}
155
+		if (isset($to)) {
156
+			$to = urldecode($to);
157
+			$parser = DBDatetime::create();
158
+			$parser->setValue($to);
159
+			$to = $parser->Format('y-MM-dd');
160
+		}
161
+		if (isset($year)) {
162
+			$year = (int)$year;
163
+		}
164
+		if (isset($month)) {
165
+			$month = (int)$month;
166
+		}
167
+
168
+		// If only "To" has been provided filter by single date. Normalise by swapping with "From".
169
+		if (isset($to) && !isset($from)) {
170
+			list($to, $from) = array($from, $to);
171
+		}
172
+
173
+		// Flip the dates if the order is wrong.
174
+		if (isset($to) && isset($from) && strtotime($from)>strtotime($to)) {
175
+			list($to, $from) = array($from, $to);
176
+
177
+			if ($produceErrorMessages) {
178
+				// @todo replace
179 179
 //                Session::setFormMessage(
180 180
 //                    'Form_DateRangeForm',
181 181
 //                    _t('DateUpdateHolder.FilterAppliedMessage', 'Filter has been applied with the dates reversed.'),
182 182
 //                    'warning'
183 183
 //                );
184
-            }
185
-        }
184
+			}
185
+		}
186 186
 
187
-        // Notify the user that filtering by single date is taking place.
188
-        if (isset($from) && !isset($to)) {
189
-            if ($produceErrorMessages) {
190
-                // @todo replace
187
+		// Notify the user that filtering by single date is taking place.
188
+		if (isset($from) && !isset($to)) {
189
+			if ($produceErrorMessages) {
190
+				// @todo replace
191 191
 //                Session::setFormMessage(
192 192
 //                    'Form_DateRangeForm',
193 193
 //                    _t('DateUpdateHolder.DateRangeFilterMessage', 'Filtered by a single date.'),
194 194
 //                    'warning'
195 195
 //                );
196
-            }
197
-        }
198
-
199
-        return [
200
-            'tag' => $tag,
201
-            'from' => $from,
202
-            'to' => $to,
203
-            'year' => $year,
204
-            'month' => $month,
205
-        ];
206
-    }
207
-
208
-    /**
209
-     * Build the link - keep the date range, reset the rest.
210
-     */
211
-    public function AllTagsLink()
212
-    {
213
-        $link = HTTP::setGetVar('tag', null, null, '&');
214
-        $link = HTTP::setGetVar('month', null, $link, '&');
215
-        $link = HTTP::setGetVar('year', null, $link, '&');
216
-        $link = HTTP::setGetVar('start', null, $link, '&');
217
-
218
-        return $link;
219
-    }
220
-
221
-    /**
222
-     * List tags and attach links.
223
-     */
224
-    public function UpdateTagsWithLinks()
225
-    {
226
-        $tags = $this->UpdateTags();
227
-
228
-        $processed = ArrayList::create();
229
-
230
-        foreach ($tags as $tag) {
231
-            // Build the link - keep the tag, and date range, but reset month, year and pagination.
232
-            $link = HTTP::setGetVar('tag', $tag->ID, null, '&');
233
-            $link = HTTP::setGetVar('month', null, $link, '&');
234
-            $link = HTTP::setGetVar('year', null, $link, '&');
235
-            $link = HTTP::setGetVar('start', null, $link, '&');
236
-
237
-            $tag->Link = $link;
238
-            $processed->push($tag);
239
-        }
240
-
241
-        return $processed;
242
-    }
243
-
244
-    /**
245
-     * Get the TaxonomyTerm related to the current tag GET parameter.
246
-     */
247
-    public function CurrentTag()
248
-    {
249
-        $tagID = $this->request->getVar('tag');
250
-
251
-        if (isset($tagID)) {
252
-            return TaxonomyTerm::get_by_id(TaxonomyTerm::class, (int)$tagID);
253
-        }
254
-    }
255
-
256
-    /**
257
-     * Extract the available months based on the current query.
258
-     * Only tag is respected. Pagination and months are ignored.
259
-     */
260
-    public function AvailableMonths()
261
-    {
262
-        $params = $this->parseParams();
263
-
264
-        return DatedUpdateHolder::ExtractMonths(
265
-            $this->Updates($params['tag'], $params['from'], $params['to']),
266
-            Director::makeRelative($_SERVER['REQUEST_URI']),
267
-            $params['year'],
268
-            $params['month']
269
-        );
270
-    }
271
-
272
-    /**
273
-     * Get the updates based on the current query.
274
-     */
275
-    public function FilteredUpdates($pageSize = 20)
276
-    {
277
-        $params = $this->parseParams();
278
-
279
-        $items = $this->Updates(
280
-            $params['tag'],
281
-            $params['from'],
282
-            $params['to'],
283
-            $params['year'],
284
-            $params['month']
285
-        );
286
-
287
-        // Apply pagination
288
-        $list = PaginatedList::create($items, $this->getRequest());
289
-        $list->setPageLength($pageSize);
290
-        return $list;
291
-    }
292
-
293
-    /**
294
-     * @return Form
295
-     */
296
-    public function DateRangeForm()
297
-    {
298
-        $dateFromTitle = DBField::create_field('HTMLText', sprintf(
299
-            '%s <span class="field-note">%s</span>',
300
-            _t('DatedUpdateHolder.FROM_DATE', 'From date'),
301
-            _t('DatedUpdateHolder.DATE_EXAMPLE', '(example: 2017/12/30)')
302
-        ));
303
-        $dateToTitle = DBField::create_field('HTMLText', sprintf(
304
-            '%s <span class="field-note">%s</span>',
305
-            _t('DatedUpdateHolder.TO_DATE', 'To date'),
306
-            _t('DatedUpdateHolder.DATE_EXAMPLE', '(example: 2017/12/30)')
307
-        ));
308
-
309
-        $fields = FieldList::create(
310
-            DateField::create('from', $dateFromTitle),
311
-            DateField::create('to', $dateToTitle),
312
-            HiddenField::create('tag')
313
-        );
314
-
315
-        $actions = FieldList::create(
316
-            FormAction::create("doDateFilter")->setTitle("Filter")->addExtraClass('btn btn-primary primary'),
317
-            FormAction::create("doDateReset")->setTitle("Clear")->addExtraClass('btn')
318
-        );
319
-
320
-        $form = Form::create($this, 'DateRangeForm', $fields, $actions);
321
-        $form->loadDataFrom($this->request->getVars());
322
-        $form->setFormMethod('get');
323
-
324
-        // Manually extract the message so we can clear it.
325
-        $form->ErrorMessage = $form->getMessage();
326
-        $form->ErrorMessageType = $form->getMessageType();
327
-        $form->clearMessage();
328
-
329
-        return $form;
330
-    }
331
-
332
-    public function doDateFilter()
333
-    {
334
-        $params = $this->parseParams();
335
-
336
-        // Build the link - keep the tag, but reset month, year and pagination.
337
-        $link = HTTP::setGetVar('from', $params['from'], $this->AbsoluteLink(), '&');
338
-        $link = HTTP::setGetVar('to', $params['to'], $link, '&');
339
-        if (isset($params['tag'])) {
340
-            $link = HTTP::setGetVar('tag', $params['tag'], $link, '&');
341
-        }
342
-
343
-        $this->redirect($link);
344
-    }
345
-
346
-    public function doDateReset()
347
-    {
348
-        $params = $this->parseParams(false);
349
-
350
-        // Reset the link - only include the tag.
351
-        $link = $this->AbsoluteLink();
352
-        if (isset($params['tag'])) {
353
-            $link = HTTP::setGetVar('tag', $params['tag'], $link, '&');
354
-        }
355
-
356
-        $this->redirect($link);
357
-    }
358
-
359
-    public function rss()
360
-    {
361
-        $rss = RSSFeed::create(
362
-            $this->Updates()->sort('Created DESC')->limit(20),
363
-            $this->Link('rss'),
364
-            $this->getSubscriptionTitle()
365
-        );
366
-        return $rss->outputToBrowser();
367
-    }
368
-
369
-    public function atom()
370
-    {
371
-        $atom = CwpAtomFeed::create(
372
-            $this->Updates()->sort('Created DESC')->limit(20),
373
-            $this->Link('atom'),
374
-            $this->getSubscriptionTitle()
375
-        );
376
-        return $atom->outputToBrowser();
377
-    }
196
+			}
197
+		}
198
+
199
+		return [
200
+			'tag' => $tag,
201
+			'from' => $from,
202
+			'to' => $to,
203
+			'year' => $year,
204
+			'month' => $month,
205
+		];
206
+	}
207
+
208
+	/**
209
+	 * Build the link - keep the date range, reset the rest.
210
+	 */
211
+	public function AllTagsLink()
212
+	{
213
+		$link = HTTP::setGetVar('tag', null, null, '&');
214
+		$link = HTTP::setGetVar('month', null, $link, '&');
215
+		$link = HTTP::setGetVar('year', null, $link, '&');
216
+		$link = HTTP::setGetVar('start', null, $link, '&');
217
+
218
+		return $link;
219
+	}
220
+
221
+	/**
222
+	 * List tags and attach links.
223
+	 */
224
+	public function UpdateTagsWithLinks()
225
+	{
226
+		$tags = $this->UpdateTags();
227
+
228
+		$processed = ArrayList::create();
229
+
230
+		foreach ($tags as $tag) {
231
+			// Build the link - keep the tag, and date range, but reset month, year and pagination.
232
+			$link = HTTP::setGetVar('tag', $tag->ID, null, '&');
233
+			$link = HTTP::setGetVar('month', null, $link, '&');
234
+			$link = HTTP::setGetVar('year', null, $link, '&');
235
+			$link = HTTP::setGetVar('start', null, $link, '&');
236
+
237
+			$tag->Link = $link;
238
+			$processed->push($tag);
239
+		}
240
+
241
+		return $processed;
242
+	}
243
+
244
+	/**
245
+	 * Get the TaxonomyTerm related to the current tag GET parameter.
246
+	 */
247
+	public function CurrentTag()
248
+	{
249
+		$tagID = $this->request->getVar('tag');
250
+
251
+		if (isset($tagID)) {
252
+			return TaxonomyTerm::get_by_id(TaxonomyTerm::class, (int)$tagID);
253
+		}
254
+	}
255
+
256
+	/**
257
+	 * Extract the available months based on the current query.
258
+	 * Only tag is respected. Pagination and months are ignored.
259
+	 */
260
+	public function AvailableMonths()
261
+	{
262
+		$params = $this->parseParams();
263
+
264
+		return DatedUpdateHolder::ExtractMonths(
265
+			$this->Updates($params['tag'], $params['from'], $params['to']),
266
+			Director::makeRelative($_SERVER['REQUEST_URI']),
267
+			$params['year'],
268
+			$params['month']
269
+		);
270
+	}
271
+
272
+	/**
273
+	 * Get the updates based on the current query.
274
+	 */
275
+	public function FilteredUpdates($pageSize = 20)
276
+	{
277
+		$params = $this->parseParams();
278
+
279
+		$items = $this->Updates(
280
+			$params['tag'],
281
+			$params['from'],
282
+			$params['to'],
283
+			$params['year'],
284
+			$params['month']
285
+		);
286
+
287
+		// Apply pagination
288
+		$list = PaginatedList::create($items, $this->getRequest());
289
+		$list->setPageLength($pageSize);
290
+		return $list;
291
+	}
292
+
293
+	/**
294
+	 * @return Form
295
+	 */
296
+	public function DateRangeForm()
297
+	{
298
+		$dateFromTitle = DBField::create_field('HTMLText', sprintf(
299
+			'%s <span class="field-note">%s</span>',
300
+			_t('DatedUpdateHolder.FROM_DATE', 'From date'),
301
+			_t('DatedUpdateHolder.DATE_EXAMPLE', '(example: 2017/12/30)')
302
+		));
303
+		$dateToTitle = DBField::create_field('HTMLText', sprintf(
304
+			'%s <span class="field-note">%s</span>',
305
+			_t('DatedUpdateHolder.TO_DATE', 'To date'),
306
+			_t('DatedUpdateHolder.DATE_EXAMPLE', '(example: 2017/12/30)')
307
+		));
308
+
309
+		$fields = FieldList::create(
310
+			DateField::create('from', $dateFromTitle),
311
+			DateField::create('to', $dateToTitle),
312
+			HiddenField::create('tag')
313
+		);
314
+
315
+		$actions = FieldList::create(
316
+			FormAction::create("doDateFilter")->setTitle("Filter")->addExtraClass('btn btn-primary primary'),
317
+			FormAction::create("doDateReset")->setTitle("Clear")->addExtraClass('btn')
318
+		);
319
+
320
+		$form = Form::create($this, 'DateRangeForm', $fields, $actions);
321
+		$form->loadDataFrom($this->request->getVars());
322
+		$form->setFormMethod('get');
323
+
324
+		// Manually extract the message so we can clear it.
325
+		$form->ErrorMessage = $form->getMessage();
326
+		$form->ErrorMessageType = $form->getMessageType();
327
+		$form->clearMessage();
328
+
329
+		return $form;
330
+	}
331
+
332
+	public function doDateFilter()
333
+	{
334
+		$params = $this->parseParams();
335
+
336
+		// Build the link - keep the tag, but reset month, year and pagination.
337
+		$link = HTTP::setGetVar('from', $params['from'], $this->AbsoluteLink(), '&');
338
+		$link = HTTP::setGetVar('to', $params['to'], $link, '&');
339
+		if (isset($params['tag'])) {
340
+			$link = HTTP::setGetVar('tag', $params['tag'], $link, '&');
341
+		}
342
+
343
+		$this->redirect($link);
344
+	}
345
+
346
+	public function doDateReset()
347
+	{
348
+		$params = $this->parseParams(false);
349
+
350
+		// Reset the link - only include the tag.
351
+		$link = $this->AbsoluteLink();
352
+		if (isset($params['tag'])) {
353
+			$link = HTTP::setGetVar('tag', $params['tag'], $link, '&');
354
+		}
355
+
356
+		$this->redirect($link);
357
+	}
358
+
359
+	public function rss()
360
+	{
361
+		$rss = RSSFeed::create(
362
+			$this->Updates()->sort('Created DESC')->limit(20),
363
+			$this->Link('rss'),
364
+			$this->getSubscriptionTitle()
365
+		);
366
+		return $rss->outputToBrowser();
367
+	}
368
+
369
+	public function atom()
370
+	{
371
+		$atom = CwpAtomFeed::create(
372
+			$this->Updates()->sort('Created DESC')->limit(20),
373
+			$this->Link('atom'),
374
+			$this->getSubscriptionTitle()
375
+		);
376
+		return $atom->outputToBrowser();
377
+	}
378 378
 }
Please login to merge, or discard this patch.
src/PageTypes/EventHolderController.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -19,53 +19,53 @@
 block discarded – undo
19 19
  */
20 20
 class EventHolderController extends DatedUpdateHolderController
21 21
 {
22
-    public function getUpdateName()
23
-    {
24
-        $params = $this->parseParams();
25
-        if ($params['upcomingOnly']) {
26
-            return _t('EventHolder.Upcoming', 'Upcoming events');
27
-        }
22
+	public function getUpdateName()
23
+	{
24
+		$params = $this->parseParams();
25
+		if ($params['upcomingOnly']) {
26
+			return _t('EventHolder.Upcoming', 'Upcoming events');
27
+		}
28 28
 
29
-        return 'Events';
30
-    }
29
+		return 'Events';
30
+	}
31 31
 
32
-    /**
33
-     * Parse URL parameters.
34
-     *
35
-     * @param boolean $produceErrorMessages Set to false to omit session messages.
36
-     */
37
-    public function parseParams($produceErrorMessages = true)
38
-    {
39
-        $params = parent::parseParams($produceErrorMessages);
32
+	/**
33
+	 * Parse URL parameters.
34
+	 *
35
+	 * @param boolean $produceErrorMessages Set to false to omit session messages.
36
+	 */
37
+	public function parseParams($produceErrorMessages = true)
38
+	{
39
+		$params = parent::parseParams($produceErrorMessages);
40 40
 
41
-        // We need to set whether or not we're supposed to be displaying only upcoming events or all events.
42
-        $params['upcomingOnly'] = !($params['from'] || $params['to'] || $params['year'] || $params['month']);
41
+		// We need to set whether or not we're supposed to be displaying only upcoming events or all events.
42
+		$params['upcomingOnly'] = !($params['from'] || $params['to'] || $params['year'] || $params['month']);
43 43
 
44
-        return $params;
45
-    }
44
+		return $params;
45
+	}
46 46
 
47
-    /**
48
-     * Get the events based on the current query.
49
-     */
50
-    public function FilteredUpdates($pageSize = 20)
51
-    {
52
-        $params = $this->parseParams();
47
+	/**
48
+	 * Get the events based on the current query.
49
+	 */
50
+	public function FilteredUpdates($pageSize = 20)
51
+	{
52
+		$params = $this->parseParams();
53 53
 
54
-        $items = $this->Updates(
55
-            $params['tag'],
56
-            $params['from'],
57
-            $params['to'],
58
-            $params['year'],
59
-            $params['month']
60
-        );
54
+		$items = $this->Updates(
55
+			$params['tag'],
56
+			$params['from'],
57
+			$params['to'],
58
+			$params['year'],
59
+			$params['month']
60
+		);
61 61
 
62
-        if ($params['upcomingOnly']) {
63
-            $items = $items->filter(['Date:LessThan:Not' => DBDatetime::now()->Format('y-MM-dd')]);
64
-        }
62
+		if ($params['upcomingOnly']) {
63
+			$items = $items->filter(['Date:LessThan:Not' => DBDatetime::now()->Format('y-MM-dd')]);
64
+		}
65 65
 
66
-        // Apply pagination
67
-        $list = PaginatedList::create($items, $this->getRequest());
68
-        $list->setPageLength($pageSize);
69
-        return $list;
70
-    }
66
+		// Apply pagination
67
+		$list = PaginatedList::create($items, $this->getRequest());
68
+		$list->setPageLength($pageSize);
69
+		return $list;
70
+	}
71 71
 }
Please login to merge, or discard this patch.
src/PageTypes/SitemapPage.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -6,11 +6,11 @@
 block discarded – undo
6 6
 
7 7
 class SitemapPage extends Page
8 8
 {
9
-    private static $description = 'Lists all pages on the site';
9
+	private static $description = 'Lists all pages on the site';
10 10
 
11
-    private static $singular_name = 'Sitemap Page';
11
+	private static $singular_name = 'Sitemap Page';
12 12
 
13
-    private static $plural_name = 'Sitemap Pages';
13
+	private static $plural_name = 'Sitemap Pages';
14 14
 
15
-    private static $table_name = 'SitemapPage';
15
+	private static $table_name = 'SitemapPage';
16 16
 }
Please login to merge, or discard this patch.
src/PageTypes/DatedUpdatePage.php 1 patch
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -10,70 +10,70 @@
 block discarded – undo
10 10
 
11 11
 class DatedUpdatePage extends Page
12 12
 {
13
-    /**
14
-     * Meant as an abstract base class.
15
-     *
16
-     * {@inheritDoc}
17
-     */
18
-    private static $hide_ancestor = DatedUpdatePage::class;
13
+	/**
14
+	 * Meant as an abstract base class.
15
+	 *
16
+	 * {@inheritDoc}
17
+	 */
18
+	private static $hide_ancestor = DatedUpdatePage::class;
19 19
 
20
-    private static $singular_name = 'Dated Update Page';
20
+	private static $singular_name = 'Dated Update Page';
21 21
 
22
-    private static $plural_name = 'Dated Update Pages';
22
+	private static $plural_name = 'Dated Update Pages';
23 23
 
24
-    private static $table_name = 'DatedUpdatePage';
24
+	private static $table_name = 'DatedUpdatePage';
25 25
 
26
-    private static $defaults = [
27
-        'ShowInMenus' => false,
28
-    ];
26
+	private static $defaults = [
27
+		'ShowInMenus' => false,
28
+	];
29 29
 
30
-    private static $db = [
31
-        'Abstract' => 'Text',
32
-        'Date' => 'Datetime',
33
-    ];
30
+	private static $db = [
31
+		'Abstract' => 'Text',
32
+		'Date' => 'Datetime',
33
+	];
34 34
 
35
-    /**
36
-     * Add the default for the Date being the current day.
37
-     */
38
-    public function populateDefaults()
39
-    {
40
-        parent::populateDefaults();
35
+	/**
36
+	 * Add the default for the Date being the current day.
37
+	 */
38
+	public function populateDefaults()
39
+	{
40
+		parent::populateDefaults();
41 41
 
42
-        if (!isset($this->Date) || $this->Date === null) {
43
-            $this->Date = DBDatetime::now()->Format('y-MM-dd 09:00:00');
44
-        }
45
-    }
42
+		if (!isset($this->Date) || $this->Date === null) {
43
+			$this->Date = DBDatetime::now()->Format('y-MM-dd 09:00:00');
44
+		}
45
+	}
46 46
 
47
-    public function fieldLabels($includerelations = true)
48
-    {
49
-        $labels = parent::fieldLabels($includerelations);
50
-        $labels['Date'] = _t('DateUpdatePage.DateLabel', 'Date');
51
-        $labels['Abstract'] = _t('DateUpdatePage.AbstractTextFieldLabel', 'Abstract');
47
+	public function fieldLabels($includerelations = true)
48
+	{
49
+		$labels = parent::fieldLabels($includerelations);
50
+		$labels['Date'] = _t('DateUpdatePage.DateLabel', 'Date');
51
+		$labels['Abstract'] = _t('DateUpdatePage.AbstractTextFieldLabel', 'Abstract');
52 52
 
53
-        return $labels;
54
-    }
53
+		return $labels;
54
+	}
55 55
 
56
-    public function getCMSFields()
57
-    {
58
-        $this->beforeUpdateCMSFields(function (FieldList $fields) {
59
-            $fields->addFieldToTab(
60
-                'Root.Main',
61
-                $dateTimeField = DatetimeField::create('Date', $this->fieldLabel('Date')),
62
-                'Content'
63
-            );
56
+	public function getCMSFields()
57
+	{
58
+		$this->beforeUpdateCMSFields(function (FieldList $fields) {
59
+			$fields->addFieldToTab(
60
+				'Root.Main',
61
+				$dateTimeField = DatetimeField::create('Date', $this->fieldLabel('Date')),
62
+				'Content'
63
+			);
64 64
 
65
-            $fields->addfieldToTab(
66
-                'Root.Main',
67
-                $abstractField = TextareaField::create('Abstract', $this->fieldLabel('Abstract')),
68
-                'Content'
69
-            );
70
-            $abstractField->setAttribute('maxlength', '160');
71
-            $abstractField->setRightTitle(_t(
72
-                'DateUpdatePage.AbstractDesc',
73
-                'The abstract is used as a summary on the listing pages. It is limited to 160 characters.'
74
-            ));
75
-            $abstractField->setRows(6);
76
-        });
77
-        return parent::getCMSFields();
78
-    }
65
+			$fields->addfieldToTab(
66
+				'Root.Main',
67
+				$abstractField = TextareaField::create('Abstract', $this->fieldLabel('Abstract')),
68
+				'Content'
69
+			);
70
+			$abstractField->setAttribute('maxlength', '160');
71
+			$abstractField->setRightTitle(_t(
72
+				'DateUpdatePage.AbstractDesc',
73
+				'The abstract is used as a summary on the listing pages. It is limited to 160 characters.'
74
+			));
75
+			$abstractField->setRows(6);
76
+		});
77
+		return parent::getCMSFields();
78
+	}
79 79
 }
Please login to merge, or discard this patch.
src/PageTypes/BaseHomePageController.php 1 patch
Indentation   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -6,20 +6,20 @@
 block discarded – undo
6 6
 
7 7
 class BaseHomePageController extends PageController
8 8
 {
9
-    public function getNewsPage()
10
-    {
11
-        return NewsHolder::get_one(NewsHolder::class);
12
-    }
9
+	public function getNewsPage()
10
+	{
11
+		return NewsHolder::get_one(NewsHolder::class);
12
+	}
13 13
 
14
-    /**
15
-     * @param int $amount The amount of items to provide.
16
-     */
17
-    public function getNewsItems($amount = 2)
18
-    {
19
-        $newsHolder = $this->getNewsPage();
20
-        if ($newsHolder) {
21
-            $controller = NewsHolderController::create($newsHolder);
22
-            return $controller->Updates()->limit($amount);
23
-        }
24
-    }
14
+	/**
15
+	 * @param int $amount The amount of items to provide.
16
+	 */
17
+	public function getNewsItems($amount = 2)
18
+	{
19
+		$newsHolder = $this->getNewsPage();
20
+		if ($newsHolder) {
21
+			$controller = NewsHolderController::create($newsHolder);
22
+			return $controller->Updates()->limit($amount);
23
+		}
24
+	}
25 25
 }
Please login to merge, or discard this patch.
src/PageTypes/DatedUpdateHolder.php 1 patch
Indentation   +243 added lines, -243 removed lines patch added patch discarded remove patch
@@ -17,247 +17,247 @@
 block discarded – undo
17 17
 
18 18
 class DatedUpdateHolder extends Page
19 19
 {
20
-    /**
21
-     * Meant as an abstract base class.
22
-     *
23
-     * {@inheritDoc}
24
-     */
25
-    private static $hide_ancestor = DatedUpdateHolder::class;
26
-
27
-    private static $update_name = 'Updates';
28
-
29
-    private static $update_class = DatedUpdatePage::class;
30
-
31
-    private static $singular_name = 'Dated Update Holder';
32
-
33
-    private static $plural_name = 'Dated Update Holders';
34
-
35
-    private static $table_name = 'DatedUpdateHolder';
36
-
37
-    /**
38
-     * Find all distinct tags (TaxonomyTerms) associated with the DatedUpdatePages under this holder.
39
-     */
40
-    public function UpdateTags()
41
-    {
42
-        $siteTree = DataObject::getSchema()->tableName(SiteTree::class);
43
-        $taxonomy = DataObject::getSchema()->tableName(TaxonomyTerm::class);
44
-
45
-        $tags = TaxonomyTerm::get()
46
-            ->innerJoin('BasePage_Terms', sprintf('"%s"."ID"="BasePage_Terms"."TaxonomyTermID"', $taxonomy))
47
-            ->innerJoin(
48
-                $siteTree,
49
-                sprintf(
50
-                    '"%s"."ID" = "BasePage_Terms"."BasePageID" AND "%s"."ParentID" = \'%d\'',
51
-                    $siteTree,
52
-                    $siteTree,
53
-                    $this->ID
54
-                )
55
-            )
56
-            ->sort('Name');
57
-
58
-        return $tags;
59
-    }
60
-
61
-    /**
62
-     * Wrapper to find all updates belonging to this holder, based on some filters.
63
-     */
64
-    public function Updates($tagID = null, $dateFrom = null, $dateTo = null, $year = null, $monthNumber = null)
65
-    {
66
-        $className = Config::inst()->get($this->ClassName, 'update_class');
67
-        return static::AllUpdates($className, $this->ID, $tagID, $dateFrom, $dateTo, $year, $monthNumber);
68
-    }
69
-
70
-    /**
71
-     * Find all site's updates, based on some filters.
72
-     * Omitting parameters will prevent relevant filters from being applied. The filters are ANDed together.
73
-     *
74
-     * @param string $className The name of the class to fetch.
75
-     * @param int|null $parentID The ID of the holder to extract the updates from.
76
-     * @param int|null $tagID The ID of the tag to filter the updates by.
77
-     * @param string|null $dateFrom The beginning of a date filter range.
78
-     * @param string|null $dateTo The end of the date filter range. If empty, only one day will be searched for.
79
-     * @param int|null $year Numeric value of the year to show.
80
-     * @param int|null $monthNumber Numeric value of the month to show.
81
-     *
82
-     * @returns DataList | PaginatedList
83
-     */
84
-    public static function AllUpdates(
85
-        $className = DatedUpdatePage::class,
86
-        $parentID = null,
87
-        $tagID = null,
88
-        $dateFrom = null,
89
-        $dateTo = null,
90
-        $year = null,
91
-        $monthNumber = null
92
-    ) {
93
-
94
-        $items = $className::get();
95
-        $dbTableName = DataObject::getSchema()->tableForField($className, 'Date');
96
-        if (!$dbTableName) {
97
-            $dbTableName = DatedUpdatePage::class;
98
-        }
99
-
100
-        // Filter by parent holder.
101
-        if (isset($parentID)) {
102
-            $items = $items->filter(['ParentID'=>$parentID]);
103
-        }
104
-
105
-        // Filter down to a single tag.
106
-        if (isset($tagID)) {
107
-            $taxonomy = DataObject::getSchema()->tableName(TaxonomyTerm::class);
108
-            $tableName = DataObject::getSchema()->tableName($className);
109
-
110
-            $items = $items->innerJoin(
111
-                'BasePage_Terms',
112
-                sprintf('"%s"."ID" = "BasePage_Terms"."BasePageID"', $tableName)
113
-            )->innerJoin(
114
-                $taxonomy,
115
-                sprintf(
116
-                    '"BasePage_Terms"."TaxonomyTermID" = "%s"."ID" AND "TaxonomyTerm"."ID" = \'%d\'',
117
-                    $taxonomy,
118
-                    $tagID
119
-                )
120
-            );
121
-        }
122
-
123
-        // Filter by date
124
-        if (isset($dateFrom)) {
125
-            if (!isset($dateTo)) {
126
-                $dateTo = $dateFrom;
127
-            }
128
-
129
-            $items = $items->where([
130
-                sprintf('"%s"."Date" >= \'%s\'', $dbTableName, Convert::raw2sql("$dateFrom 00:00:00")),
131
-                sprintf('"%s"."Date" <= \'%s\'', $dbTableName, Convert::raw2sql("$dateTo 23:59:59"))
132
-            ]);
133
-        }
134
-
135
-        // Filter down to single month.
136
-        if (isset($year) && isset($monthNumber)) {
137
-            $year = (int)$year;
138
-            $monthNumber = (int)$monthNumber;
139
-
140
-            $beginDate = sprintf("%04d-%02d-01 00:00:00", $year, $monthNumber);
141
-            $endDate = date('Y-m-d H:i:s', strtotime("{$beginDate} +1 month"));
142
-
143
-            $items = $items->where(array(
144
-                sprintf('"%s"."Date" >= \'%s\'', $dbTableName, Convert::raw2sql($beginDate)),
145
-                sprintf('"%s"."Date" < \'%s\'', $dbTableName, Convert::raw2sql($endDate))
146
-            ));
147
-        }
148
-
149
-        // Unpaginated DataList.
150
-        return $items;
151
-    }
152
-
153
-    /**
154
-     * Produce an ArrayList of available months out of the updates contained in the DataList.
155
-     *
156
-     * Here is an example of the returned structure:
157
-     * ArrayList:
158
-     *   ArrayData:
159
-     *     YearName => 2013
160
-     *     Months => ArrayList:
161
-     *       MonthName => Jan
162
-     *       MonthNumber => 1
163
-     *       MonthLink => (page URL)year=2012&month=1
164
-     *       Active => true
165
-     *   ArrayData:
166
-     *     YearName => 2012
167
-     *     Months => ArrayList:
168
-     *     ...
169
-     *
170
-     * @param DataList $updates DataList DataList to extract months from.
171
-     * @param string $link Link used as abase to construct the MonthLink.
172
-     * @param int $currentYear Currently selected year, for computing the link active state.
173
-     * @param int $currentMonthNumber Currently selected month, for computing the link active state.
174
-     *
175
-     * @returns ArrayList
176
-     */
177
-    public static function ExtractMonths(
178
-        DataList $updates,
179
-        $link = null,
180
-        $currentYear = null,
181
-        $currentMonthNumber = null
182
-    ) {
183
-        // Set the link to current URL in the same way the HTTP::setGetVar does it.
184
-        if (!isset($link)) {
185
-            $link = Director::makeRelative($_SERVER['REQUEST_URI']);
186
-        }
187
-
188
-        $dates = $updates->dataQuery()
189
-            ->groupby('YEAR("Date")')
190
-            ->groupby('MONTH("Date")')
191
-            ->query()
192
-            ->setSelect([
193
-                'Year' => 'YEAR("Date")',
194
-                'Month' => 'MONTH("Date")',
195
-            ])
196
-            ->addWhere('"Date" IS NOT NULL')
197
-            ->setOrderBy([
198
-                'YEAR("Date")' => 'DESC',
199
-                'MONTH("Date")' => 'DESC',
200
-            ])
201
-            ->execute();
202
-
203
-        $years = [];
204
-        foreach ($dates as $date) {
205
-            $monthNumber = $date['Month'];
206
-            $year = $date['Year'];
207
-            $dateObj = new DateTime(implode('-', [$year, $monthNumber, 1]));
208
-            $monthName = $dateObj->Format('M');
209
-
210
-            // Set up the relevant year array, if not yet available.
211
-            if (!isset($years[$year])) {
212
-                $years[$year] = ['YearName'=>$year, 'Months' => []];
213
-            }
214
-
215
-            // Check if the currently processed month is the one that is selected via GET params.
216
-            $active = false;
217
-            if (isset($year) && isset($monthNumber)) {
218
-                $active = (((int)$currentYear)==$year && ((int)$currentMonthNumber)==$monthNumber);
219
-            }
220
-
221
-            // Build the link - keep the tag and date filter, but reset the pagination.
222
-            if ($active) {
223
-                // Allow clicking to deselect the month.
224
-                $link = HTTP::setGetVar('month', null, $link, '&');
225
-                $link = HTTP::setGetVar('year', null, $link, '&');
226
-            } else {
227
-                $link = HTTP::setGetVar('month', $monthNumber, $link, '&');
228
-                $link = HTTP::setGetVar('year', $year, $link, '&');
229
-            }
230
-            $link = HTTP::setGetVar('start', null, $link, '&');
231
-
232
-            $years[$year]['Months'][$monthNumber] = array(
233
-                'MonthName'=>$monthName,
234
-                'MonthNumber'=>$monthNumber,
235
-                'MonthLink'=>$link,
236
-                'Active'=>$active
237
-            );
238
-        }
239
-
240
-        // ArrayList will not recursively walk through the supplied array, so manually build nested ArrayLists.
241
-        foreach ($years as &$year) {
242
-            $year['Months'] = new ArrayList($year['Months']);
243
-        }
244
-
245
-        // Reverse the list so the most recent years appear first.
246
-        return new ArrayList($years);
247
-    }
248
-
249
-    public function getDefaultRSSLink()
250
-    {
251
-        return $this->Link('rss');
252
-    }
253
-
254
-    public function getDefaultAtomLink()
255
-    {
256
-        return $this->Link('atom');
257
-    }
258
-
259
-    public function getSubscriptionTitle()
260
-    {
261
-        return $this->Title;
262
-    }
20
+	/**
21
+	 * Meant as an abstract base class.
22
+	 *
23
+	 * {@inheritDoc}
24
+	 */
25
+	private static $hide_ancestor = DatedUpdateHolder::class;
26
+
27
+	private static $update_name = 'Updates';
28
+
29
+	private static $update_class = DatedUpdatePage::class;
30
+
31
+	private static $singular_name = 'Dated Update Holder';
32
+
33
+	private static $plural_name = 'Dated Update Holders';
34
+
35
+	private static $table_name = 'DatedUpdateHolder';
36
+
37
+	/**
38
+	 * Find all distinct tags (TaxonomyTerms) associated with the DatedUpdatePages under this holder.
39
+	 */
40
+	public function UpdateTags()
41
+	{
42
+		$siteTree = DataObject::getSchema()->tableName(SiteTree::class);
43
+		$taxonomy = DataObject::getSchema()->tableName(TaxonomyTerm::class);
44
+
45
+		$tags = TaxonomyTerm::get()
46
+			->innerJoin('BasePage_Terms', sprintf('"%s"."ID"="BasePage_Terms"."TaxonomyTermID"', $taxonomy))
47
+			->innerJoin(
48
+				$siteTree,
49
+				sprintf(
50
+					'"%s"."ID" = "BasePage_Terms"."BasePageID" AND "%s"."ParentID" = \'%d\'',
51
+					$siteTree,
52
+					$siteTree,
53
+					$this->ID
54
+				)
55
+			)
56
+			->sort('Name');
57
+
58
+		return $tags;
59
+	}
60
+
61
+	/**
62
+	 * Wrapper to find all updates belonging to this holder, based on some filters.
63
+	 */
64
+	public function Updates($tagID = null, $dateFrom = null, $dateTo = null, $year = null, $monthNumber = null)
65
+	{
66
+		$className = Config::inst()->get($this->ClassName, 'update_class');
67
+		return static::AllUpdates($className, $this->ID, $tagID, $dateFrom, $dateTo, $year, $monthNumber);
68
+	}
69
+
70
+	/**
71
+	 * Find all site's updates, based on some filters.
72
+	 * Omitting parameters will prevent relevant filters from being applied. The filters are ANDed together.
73
+	 *
74
+	 * @param string $className The name of the class to fetch.
75
+	 * @param int|null $parentID The ID of the holder to extract the updates from.
76
+	 * @param int|null $tagID The ID of the tag to filter the updates by.
77
+	 * @param string|null $dateFrom The beginning of a date filter range.
78
+	 * @param string|null $dateTo The end of the date filter range. If empty, only one day will be searched for.
79
+	 * @param int|null $year Numeric value of the year to show.
80
+	 * @param int|null $monthNumber Numeric value of the month to show.
81
+	 *
82
+	 * @returns DataList | PaginatedList
83
+	 */
84
+	public static function AllUpdates(
85
+		$className = DatedUpdatePage::class,
86
+		$parentID = null,
87
+		$tagID = null,
88
+		$dateFrom = null,
89
+		$dateTo = null,
90
+		$year = null,
91
+		$monthNumber = null
92
+	) {
93
+
94
+		$items = $className::get();
95
+		$dbTableName = DataObject::getSchema()->tableForField($className, 'Date');
96
+		if (!$dbTableName) {
97
+			$dbTableName = DatedUpdatePage::class;
98
+		}
99
+
100
+		// Filter by parent holder.
101
+		if (isset($parentID)) {
102
+			$items = $items->filter(['ParentID'=>$parentID]);
103
+		}
104
+
105
+		// Filter down to a single tag.
106
+		if (isset($tagID)) {
107
+			$taxonomy = DataObject::getSchema()->tableName(TaxonomyTerm::class);
108
+			$tableName = DataObject::getSchema()->tableName($className);
109
+
110
+			$items = $items->innerJoin(
111
+				'BasePage_Terms',
112
+				sprintf('"%s"."ID" = "BasePage_Terms"."BasePageID"', $tableName)
113
+			)->innerJoin(
114
+				$taxonomy,
115
+				sprintf(
116
+					'"BasePage_Terms"."TaxonomyTermID" = "%s"."ID" AND "TaxonomyTerm"."ID" = \'%d\'',
117
+					$taxonomy,
118
+					$tagID
119
+				)
120
+			);
121
+		}
122
+
123
+		// Filter by date
124
+		if (isset($dateFrom)) {
125
+			if (!isset($dateTo)) {
126
+				$dateTo = $dateFrom;
127
+			}
128
+
129
+			$items = $items->where([
130
+				sprintf('"%s"."Date" >= \'%s\'', $dbTableName, Convert::raw2sql("$dateFrom 00:00:00")),
131
+				sprintf('"%s"."Date" <= \'%s\'', $dbTableName, Convert::raw2sql("$dateTo 23:59:59"))
132
+			]);
133
+		}
134
+
135
+		// Filter down to single month.
136
+		if (isset($year) && isset($monthNumber)) {
137
+			$year = (int)$year;
138
+			$monthNumber = (int)$monthNumber;
139
+
140
+			$beginDate = sprintf("%04d-%02d-01 00:00:00", $year, $monthNumber);
141
+			$endDate = date('Y-m-d H:i:s', strtotime("{$beginDate} +1 month"));
142
+
143
+			$items = $items->where(array(
144
+				sprintf('"%s"."Date" >= \'%s\'', $dbTableName, Convert::raw2sql($beginDate)),
145
+				sprintf('"%s"."Date" < \'%s\'', $dbTableName, Convert::raw2sql($endDate))
146
+			));
147
+		}
148
+
149
+		// Unpaginated DataList.
150
+		return $items;
151
+	}
152
+
153
+	/**
154
+	 * Produce an ArrayList of available months out of the updates contained in the DataList.
155
+	 *
156
+	 * Here is an example of the returned structure:
157
+	 * ArrayList:
158
+	 *   ArrayData:
159
+	 *     YearName => 2013
160
+	 *     Months => ArrayList:
161
+	 *       MonthName => Jan
162
+	 *       MonthNumber => 1
163
+	 *       MonthLink => (page URL)year=2012&month=1
164
+	 *       Active => true
165
+	 *   ArrayData:
166
+	 *     YearName => 2012
167
+	 *     Months => ArrayList:
168
+	 *     ...
169
+	 *
170
+	 * @param DataList $updates DataList DataList to extract months from.
171
+	 * @param string $link Link used as abase to construct the MonthLink.
172
+	 * @param int $currentYear Currently selected year, for computing the link active state.
173
+	 * @param int $currentMonthNumber Currently selected month, for computing the link active state.
174
+	 *
175
+	 * @returns ArrayList
176
+	 */
177
+	public static function ExtractMonths(
178
+		DataList $updates,
179
+		$link = null,
180
+		$currentYear = null,
181
+		$currentMonthNumber = null
182
+	) {
183
+		// Set the link to current URL in the same way the HTTP::setGetVar does it.
184
+		if (!isset($link)) {
185
+			$link = Director::makeRelative($_SERVER['REQUEST_URI']);
186
+		}
187
+
188
+		$dates = $updates->dataQuery()
189
+			->groupby('YEAR("Date")')
190
+			->groupby('MONTH("Date")')
191
+			->query()
192
+			->setSelect([
193
+				'Year' => 'YEAR("Date")',
194
+				'Month' => 'MONTH("Date")',
195
+			])
196
+			->addWhere('"Date" IS NOT NULL')
197
+			->setOrderBy([
198
+				'YEAR("Date")' => 'DESC',
199
+				'MONTH("Date")' => 'DESC',
200
+			])
201
+			->execute();
202
+
203
+		$years = [];
204
+		foreach ($dates as $date) {
205
+			$monthNumber = $date['Month'];
206
+			$year = $date['Year'];
207
+			$dateObj = new DateTime(implode('-', [$year, $monthNumber, 1]));
208
+			$monthName = $dateObj->Format('M');
209
+
210
+			// Set up the relevant year array, if not yet available.
211
+			if (!isset($years[$year])) {
212
+				$years[$year] = ['YearName'=>$year, 'Months' => []];
213
+			}
214
+
215
+			// Check if the currently processed month is the one that is selected via GET params.
216
+			$active = false;
217
+			if (isset($year) && isset($monthNumber)) {
218
+				$active = (((int)$currentYear)==$year && ((int)$currentMonthNumber)==$monthNumber);
219
+			}
220
+
221
+			// Build the link - keep the tag and date filter, but reset the pagination.
222
+			if ($active) {
223
+				// Allow clicking to deselect the month.
224
+				$link = HTTP::setGetVar('month', null, $link, '&');
225
+				$link = HTTP::setGetVar('year', null, $link, '&');
226
+			} else {
227
+				$link = HTTP::setGetVar('month', $monthNumber, $link, '&');
228
+				$link = HTTP::setGetVar('year', $year, $link, '&');
229
+			}
230
+			$link = HTTP::setGetVar('start', null, $link, '&');
231
+
232
+			$years[$year]['Months'][$monthNumber] = array(
233
+				'MonthName'=>$monthName,
234
+				'MonthNumber'=>$monthNumber,
235
+				'MonthLink'=>$link,
236
+				'Active'=>$active
237
+			);
238
+		}
239
+
240
+		// ArrayList will not recursively walk through the supplied array, so manually build nested ArrayLists.
241
+		foreach ($years as &$year) {
242
+			$year['Months'] = new ArrayList($year['Months']);
243
+		}
244
+
245
+		// Reverse the list so the most recent years appear first.
246
+		return new ArrayList($years);
247
+	}
248
+
249
+	public function getDefaultRSSLink()
250
+	{
251
+		return $this->Link('rss');
252
+	}
253
+
254
+	public function getDefaultAtomLink()
255
+	{
256
+		return $this->Link('atom');
257
+	}
258
+
259
+	public function getSubscriptionTitle()
260
+	{
261
+		return $this->Title;
262
+	}
263 263
 }
Please login to merge, or discard this patch.