Completed
Push — master ( 25a8fb...29fc7a )
by Hamish
12s
created

ContentController::Link()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace SilverStripe\CMS\Controllers;
4
5
use SilverStripe\ORM\DataObject;
6
use SilverStripe\ORM\DataModel;
7
use SilverStripe\ORM\ArrayList;
8
use SilverStripe\ORM\FieldType\DBDatetime;
9
use SilverStripe\ORM\FieldType\DBField;
10
use SilverStripe\ORM\SS_List;
11
use SilverStripe\ORM\Versioning\Versioned;
12
use SilverStripe\ORM\FieldType\DBVarchar;
13
use SilverStripe\ORM\FieldType\DBHTMLText;
14
use SilverStripe\Security\Security;
15
use SilverStripe\Security\MemberAuthenticator;
16
use SilverStripe\Security\Member;
17
use SilverStripe\Security\Permission;
18
use Controller;
19
use Page;
20
21
use SiteConfig;
22
use Config;
23
use SS_HTTPRequest;
24
use Translatable;
25
use i18n;
26
use SS_HTTPResponse;
27
use SS_HTTPResponse_Exception;
28
use Director;
29
use Requirements;
30
use Convert;
31
use SSViewer;
32
use ArrayData;
33
use Session;
34
use SilverStripe\CMS\Model\SiteTree;
35
36
37
/**
38
 * The most common kind of controller; effectively a controller linked to a {@link DataObject}.
39
 *
40
 * ContentControllers are most useful in the content-focused areas of a site.  This is generally
41
 * the bulk of a site; however, they may be less appropriate in, for example, the user management
42
 * section of an application.
43
 *
44
 * On its own, content controller does very little.  Its constructor is passed a {@link DataObject}
45
 * which is stored in $this->dataRecord.  Any unrecognised method calls, for example, Title()
46
 * and Content(), will be passed along to the data record,
47
 *
48
 * Subclasses of ContentController are generally instantiated by ModelAsController; this will create
49
 * a controller based on the URLSegment action variable, by looking in the SiteTree table.
50
 *
51
 * @todo Can this be used for anything other than SiteTree controllers?
52
 *
53
 * @package cms
54
 * @subpackage control
55
 */
56
class ContentController extends Controller {
57
58
	protected $dataRecord;
59
60
	private static $extensions = array('SilverStripe\\CMS\\Controllers\\OldPageRedirector');
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
61
62
	private static $allowed_actions = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
63
		'successfullyinstalled',
64
		'deleteinstallfiles', // secured through custom code
65
		'LoginForm'
66
	);
67
68
	/**
69
	 * The ContentController will take the URLSegment parameter from the URL and use that to look
70
	 * up a SiteTree record.
71
	 *
72
	 * @param SiteTree $dataRecord
73
	 */
74
	public function __construct($dataRecord = null) {
75
		if(!$dataRecord) {
76
			$dataRecord = new Page();
77
			if($this->hasMethod("Title")) {
78
				$dataRecord->Title = $this->Title();
0 ignored issues
show
Documentation Bug introduced by
The method Title does not exist on object<SilverStripe\CMS\...lers\ContentController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
79
			}
80
			$dataRecord->URLSegment = get_class($this);
81
			$dataRecord->ID = -1;
82
		}
83
84
		$this->dataRecord = $dataRecord;
85
86
		parent::__construct();
87
88
		$this->setFailover($this->dataRecord);
89
	}
90
91
	/**
92
	 * Return the link to this controller, but force the expanded link to be returned so that form methods and
93
	 * similar will function properly.
94
	 *
95
	 * @param string|null $action Action to link to.
96
	 * @return string
97
	 */
98
	public function Link($action = null) {
99
		return $this->data()->Link(($action ? $action : true));
0 ignored issues
show
Bug introduced by
It seems like $action ? $action : true can also be of type boolean; however, SilverStripe\CMS\Model\SiteTree::Link() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
100
	}
101
102
	//----------------------------------------------------------------------------------//
103
	// These flexible data methods remove the need for custom code to do simple stuff
104
105
	/**
106
	 * Return the children of a given page. The parent reference can either be a page link or an ID.
107
	 *
108
	 * @param string|int $parentRef
109
	 * @return SS_List
110
	 */
111
	public function ChildrenOf($parentRef) {
112
		$parent = SiteTree::get_by_link($parentRef);
113
114
		if(!$parent && is_numeric($parentRef)) {
115
			$parent = DataObject::get_by_id('SilverStripe\\CMS\\Model\\SiteTree', $parentRef);
116
		}
117
118
		if($parent) {
119
			return $parent->Children();
120
		}
121
		return null;
122
	}
123
124
	/**
125
	 * @param string $link
126
	 * @return SiteTree
127
	 */
128
	public function Page($link) {
129
		return SiteTree::get_by_link($link);
130
	}
131
132
	public function init() {
133
		parent::init();
134
135
		// If we've accessed the homepage as /home/, then we should redirect to /.
136
		if( $this->dataRecord instanceof SiteTree
137
			&& RootURLController::should_be_on_root($this->dataRecord)
138
			&& (!isset($this->urlParams['Action']) || !$this->urlParams['Action'] )
139
			&& !$_POST && !$_FILES && !$this->redirectedTo()
140
		) {
141
			$getVars = $_GET;
142
			unset($getVars['url']);
143
			if($getVars) $url = "?" . http_build_query($getVars);
144
			else $url = "";
145
			$this->redirect($url, 301);
146
			return;
147
		}
148
149
		if($this->dataRecord) {
150
			$this->dataRecord->extend('contentcontrollerInit', $this);
151
		} else {
152
			SiteTree::singleton()->extend('contentcontrollerInit', $this);
153
		}
154
155
		if($this->redirectedTo()) return;
156
157
		// Check page permissions
158
		/** @skipUpgrade */
159
		if($this->dataRecord && $this->URLSegment != 'Security' && !$this->dataRecord->canView()) {
0 ignored issues
show
Documentation introduced by
The property URLSegment does not exist on object<SilverStripe\CMS\...lers\ContentController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
160
			Security::permissionFailure($this);
161
			return;
162
		}
163
	}
164
165
	/**
166
	 * This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
167
	 * fall over to a child controller in order to provide functionality for nested URLs.
168
	 *
169
	 * @param SS_HTTPRequest $request
170
	 * @param DataModel $model
171
	 * @return SS_HTTPResponse
172
	 * @throws SS_HTTPResponse_Exception
173
	 */
174
	public function handleRequest(SS_HTTPRequest $request, DataModel $model) {
175
		/** @var SiteTree $child */
176
		$child  = null;
177
		$action = $request->param('Action');
178
		$this->setDataModel($model);
179
180
		// If nested URLs are enabled, and there is no action handler for the current request then attempt to pass
181
		// control to a child controller. This allows for the creation of chains of controllers which correspond to a
182
		// nested URL.
183
		if($action && SiteTree::config()->nested_urls && !$this->hasAction($action)) {
184
			// See ModelAdController->getNestedController() for similar logic
185
			if(class_exists('Translatable')) Translatable::disable_locale_filter();
186
			// look for a page with this URLSegment
187
			$child = SiteTree::get()->filter(array(
188
				'ParentID' => $this->ID,
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<SilverStripe\CMS\...lers\ContentController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
189
				'URLSegment' => rawurlencode($action)
190
			))->first();
191
			if(class_exists('Translatable')) Translatable::enable_locale_filter();
192
		}
193
194
		// we found a page with this URLSegment.
195
		if($child) {
196
			$request->shiftAllParams();
197
			$request->shift();
198
199
			$response = ModelAsController::controller_for($child)->handleRequest($request, $model);
200
		} else {
201
			// If a specific locale is requested, and it doesn't match the page found by URLSegment,
202
			// look for a translation and redirect (see #5001). Only happens on the last child in
203
			// a potentially nested URL chain.
204
			if(class_exists('Translatable')) {
205
				$locale = $request->getVar('locale');
206
				if( $locale
207
					&& i18n::validate_locale($locale)
208
					&& $this->dataRecord
209
					&& $this->dataRecord->Locale != $locale
210
				) {
211
					$translation = $this->dataRecord->getTranslation($locale);
0 ignored issues
show
Documentation Bug introduced by
The method getTranslation does not exist on object<SilverStripe\CMS\Model\SiteTree>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
212
					if($translation) {
213
						$response = new SS_HTTPResponse();
214
						$response->redirect($translation->Link(), 301);
215
						throw new SS_HTTPResponse_Exception($response);
216
					}
217
				}
218
			}
219
220
			Director::set_current_page($this->data());
0 ignored issues
show
Bug introduced by
It seems like $this->data() targeting SilverStripe\CMS\Control...ntentController::data() can also be of type object<SilverStripe\CMS\Model\SiteTree>; however, Director::set_current_page() does only seem to accept object<SiteTree>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
221
222
			try {
223
				$response = parent::handleRequest($request, $model);
224
225
				Director::set_current_page(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<SiteTree>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
226
			} catch(SS_HTTPResponse_Exception $e) {
227
				$this->popCurrent();
228
229
				Director::set_current_page(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<SiteTree>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
230
231
				throw $e;
232
			}
233
		}
234
235
		return $response;
236
	}
237
238
	/**
239
	 * Get the project name
240
	 *
241
	 * @return string
242
	 */
243
	public function project() {
244
		global $project;
245
		return $project;
246
	}
247
248
	/**
249
	 * Returns the associated database record
250
	 */
251
	public function data() {
252
		return $this->dataRecord;
253
	}
254
255
	/*--------------------------------------------------------------------------------*/
256
257
	/**
258
	 * Returns a fixed navigation menu of the given level.
259
	 * @param int $level Menu level to return.
260
	 * @return ArrayList
261
	 */
262
	public function getMenu($level = 1) {
263
		if($level == 1) {
264
			$result = SiteTree::get()->filter(array(
265
				"ShowInMenus" => 1,
266
				"ParentID" => 0
267
			));
268
269
		} else {
270
			$parent = $this->data();
271
			$stack = array($parent);
272
273
			if($parent) {
274
				while(($parent = $parent->Parent()) && $parent->exists()) {
275
					array_unshift($stack, $parent);
276
				}
277
			}
278
279
			if(isset($stack[$level-2])) $result = $stack[$level-2]->Children();
280
		}
281
282
		$visible = array();
283
284
		// Remove all entries the can not be viewed by the current user
285
		// We might need to create a show in menu permission
286
 		if(isset($result)) {
287
			foreach($result as $page) {
288
				if($page->canView()) {
289
					$visible[] = $page;
290
				}
291
			}
292
		}
293
294
		return new ArrayList($visible);
295
	}
296
297
	public function Menu($level) {
298
		return $this->getMenu($level);
299
	}
300
301
	/**
302
	 * Returns the default log-in form.
303
	 *
304
	 * @todo Check if here should be returned just the default log-in form or
305
	 *       all available log-in forms (also OpenID...)
306
	 */
307
	public function LoginForm() {
308
		return MemberAuthenticator::get_login_form($this);
309
	}
310
311
	public function SilverStripeNavigator() {
312
		$member = Member::currentUser();
313
		$items = '';
314
		$message = '';
315
316
		if(Director::isDev() || Permission::check('CMS_ACCESS_CMSMain') || Permission::check('VIEW_DRAFT_CONTENT')) {
317
			if($this->dataRecord) {
318
				Requirements::css(CMS_DIR . '/client/dist/styles/SilverStripeNavigator.css');
319
				Requirements::javascript(FRAMEWORK_DIR . '/thirdparty/jquery/jquery.js');
320
				Requirements::javascript(CMS_DIR . '/client/dist/js/SilverStripeNavigator.js');
321
322
				$return = $nav = SilverStripeNavigator::get_for_record($this->dataRecord);
0 ignored issues
show
Unused Code introduced by
$nav is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
323
				$items = $return['items'];
324
				$message = $return['message'];
325
			}
326
327
			if($member) {
328
				$firstname = Convert::raw2xml($member->FirstName);
329
				$surname = Convert::raw2xml($member->Surname);
330
				$logInMessage = _t('ContentController.LOGGEDINAS', 'Logged in as') ." {$firstname} {$surname} - <a href=\"Security/logout\">". _t('ContentController.LOGOUT', 'Log out'). "</a>";
331
			} else {
332
				$logInMessage = sprintf(
333
					'%s - <a href="%s">%s</a>' ,
334
					_t('ContentController.NOTLOGGEDIN', 'Not logged in') ,
335
					Security::config()->login_url,
336
					_t('ContentController.LOGIN', 'Login') ."</a>"
337
				);
338
			}
339
			$viewPageIn = _t('ContentController.VIEWPAGEIN', 'View Page in:');
340
341
			return <<<HTML
342
				<div id="SilverStripeNavigator">
343
					<div class="holder">
344
					<div id="logInStatus">
345
						$logInMessage
346
					</div>
347
348
					<div id="switchView" class="bottomTabs">
349
						$viewPageIn
350
						$items
351
					</div>
352
					</div>
353
				</div>
354
					$message
355
HTML;
356
357
		// On live sites we should still see the archived message
358
		} else {
359
			if($date = Versioned::current_archived_date()) {
360
				Requirements::css(CMS_DIR . '/client/dist/styles/SilverStripeNavigator.css');
361
				/** @var DBDatetime $dateObj */
362
				$dateObj = DBField::create_field('Datetime', $date);
363
				// $dateObj->setVal($date);
364
				return "<div id=\"SilverStripeNavigatorMessage\">" .
365
					_t('ContentController.ARCHIVEDSITEFROM') .
366
					"<br>" . $dateObj->Nice() . "</div>";
367
			}
368
		}
369
		return null;
370
	}
371
372
	public function SiteConfig() {
373
		if(method_exists($this->dataRecord, 'getSiteConfig')) {
374
			return $this->dataRecord->getSiteConfig();
375
		} else {
376
			return SiteConfig::current_site_config();
377
		}
378
	}
379
380
	/**
381
	 * Returns an RFC1766 compliant locale string, e.g. 'fr-CA'.
382
	 * Inspects the associated {@link dataRecord} for a {@link SiteTree->Locale} value if present,
383
	 * and falls back to {@link Translatable::get_current_locale()} or {@link i18n::default_locale()},
384
	 * depending if Translatable is enabled.
385
	 *
386
	 * Suitable for insertion into lang= and xml:lang=
387
	 * attributes in HTML or XHTML output.
388
	 *
389
	 * @return string
390
	 */
391
	public function ContentLocale() {
392
		if($this->dataRecord && $this->dataRecord->hasExtension('Translatable')) {
393
			$locale = $this->dataRecord->Locale;
394
		} elseif(class_exists('Translatable') && SiteTree::has_extension('Translatable')) {
395
			$locale = Translatable::get_current_locale();
396
		} else {
397
			$locale = i18n::get_locale();
398
		}
399
400
		return i18n::convert_rfc1766($locale);
401
	}
402
403
404
	/**
405
	 * Return an SSViewer object to render the template for the current page.
406
	 *
407
	 * @param $action string
408
	 *
409
	 * @return SSViewer
410
	 */
411
	public function getViewer($action) {
412
		// Manually set templates should be dealt with by Controller::getViewer()
413
		if(isset($this->templates[$action]) && $this->templates[$action]
0 ignored issues
show
Documentation introduced by
The property templates does not exist on object<SilverStripe\CMS\...lers\ContentController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
414
			|| (isset($this->templates['index']) && $this->templates['index'])
0 ignored issues
show
Documentation introduced by
The property templates does not exist on object<SilverStripe\CMS\...lers\ContentController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
415
			|| $this->template
0 ignored issues
show
Documentation introduced by
The property template does not exist on object<SilverStripe\CMS\...lers\ContentController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
416
		) {
417
			return parent::getViewer($action);
418
		}
419
420
		// Prepare action for template search
421
		if($action == "index") $action = "";
422
		else $action = '_' . $action;
423
424
		$templates = array_merge(
425
			// Find templates by dataRecord
426
			SSViewer::get_templates_by_class(get_class($this->dataRecord), $action, "SilverStripe\\CMS\\Model\\SiteTree"),
427
			// Next, we need to add templates for all controllers
428
			SSViewer::get_templates_by_class(get_class($this), $action, "Controller"),
429
			// Fail-over to the same for the "index" action
430
			SSViewer::get_templates_by_class(get_class($this->dataRecord), "", "SilverStripe\\CMS\\Model\\SiteTree"),
431
			SSViewer::get_templates_by_class(get_class($this), "", "Controller")
432
		);
433
434
		return new SSViewer($templates);
435
	}
436
437
438
	/**
439
	 * This action is called by the installation system
440
	 */
441
	public function successfullyinstalled() {
442
		// Return 410 Gone if this site is not actually a fresh installation
443
		if (!file_exists(BASE_PATH . '/install.php')) {
444
			$this->httpError(410);
445
		}
446
447
		// TODO Allow this to work when allow_url_fopen=0
448
		if(isset($_SESSION['StatsID']) && $_SESSION['StatsID']) {
449
			$url = 'http://ss2stat.silverstripe.com/Installation/installed?ID=' . $_SESSION['StatsID'];
450
			@file_get_contents($url);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
451
		}
452
453
		global $project;
454
		$data = new ArrayData(array(
455
			'Project' => Convert::raw2xml($project),
456
			'Username' => Convert::raw2xml(Session::get('username')),
457
			'Password' => Convert::raw2xml(Session::get('password')),
458
		));
459
460
		return array(
461
			"Title" =>  _t("ContentController.INSTALL_SUCCESS", "Installation Successful!"),
462
			"Content" => $data->renderWith('Install_successfullyinstalled'),
463
		);
464
	}
465
466
	public function deleteinstallfiles() {
467
		if(!Permission::check("ADMIN")) return Security::permissionFailure($this);
468
469
		$title = new DBVarchar("Title");
470
		$content = new DBHTMLText('Content');
471
472
		// We can't delete index.php as it might be necessary for URL routing without mod_rewrite.
473
		// There's no safe way to detect usage of mod_rewrite across webservers,
474
		// so we have to assume the file is required.
475
		$installfiles = array(
476
			'install.php',
477
			'config-form.css',
478
			'config-form.html',
479
			'index.html'
480
		);
481
482
		$unsuccessful = new ArrayList();
483
		foreach($installfiles as $installfile) {
484
			if(file_exists(BASE_PATH . '/' . $installfile)) {
485
				@unlink(BASE_PATH . '/' . $installfile);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
486
			}
487
488
			if(file_exists(BASE_PATH . '/' . $installfile)) {
489
				$unsuccessful->push(new ArrayData(array('File' => $installfile)));
490
			}
491
		}
492
493
		$data = new ArrayData(array(
494
			'Username' => Convert::raw2xml(Session::get('username')),
495
			'Password' => Convert::raw2xml(Session::get('password')),
496
			'UnsuccessfulFiles' => $unsuccessful
497
		));
498
		$content->setValue($data->renderWith('Install_deleteinstallfiles'));
499
500
		return array(
501
			"Title" => $title,
502
			"Content" => $content,
503
		);
504
	}
505
}
506