dataRecord. Any unrecognised method calls, for example, Title()
* and Content(), will be passed along to the data record,
*
* Subclasses of ContentController are generally instantiated by ModelAsController; this will create
* a controller based on the URLSegment action variable, by looking in the SiteTree table.
*
* @todo Can this be used for anything other than SiteTree controllers?
*
* @package cms
* @subpackage control
*/
class ContentController extends Controller {
protected $dataRecord;
static $url_handlers = array(
'widget/$ID!' => 'handleWidget'
);
public static $allowed_actions = array(
'successfullyinstalled',
'deleteinstallfiles' // secured through custom code
);
/**
* The ContentController will take the URLSegment parameter from the URL and use that to look
* up a SiteTree record.
*/
public function __construct($dataRecord = null) {
if(!$dataRecord) {
$dataRecord = new Page();
if($this->hasMethod("Title")) $dataRecord->Title = $this->Title();
$dataRecord->URLSegment = get_class($this);
$dataRecord->ID = -1;
}
$this->dataRecord = $dataRecord;
$this->failover = $this->dataRecord;
parent::__construct();
}
/**
* Return the link to this controller, but force the expanded link to be returned so that form methods and
* similar will function properly.
*
* @return string
*/
public function Link($action = null) {
return $this->data()->Link(($action ? $action : true));
}
//----------------------------------------------------------------------------------//
// These flexible data methods remove the need for custom code to do simple stuff
/**
* Return the children of a given page. The parent reference can either be a page link or an ID.
*
* @param string|int $parentRef
* @return SS_List
*/
public function ChildrenOf($parentRef) {
$parent = SiteTree::get_by_link($parentRef);
if(!$parent && is_numeric($parentRef)) {
$parent = DataObject::get_by_id('SiteTree', Convert::raw2sql($parentRef));
}
if($parent) return $parent->Children();
}
/**
* @return SS_List
*/
public function Page($link) {
return SiteTree::get_by_link($link);
}
public function init() {
parent::init();
// If we've accessed the homepage as /home/, then we should redirect to /.
if($this->dataRecord && $this->dataRecord instanceof SiteTree
&& RootURLController::should_be_on_root($this->dataRecord) && (!isset($this->urlParams['Action']) || !$this->urlParams['Action'] )
&& !$_POST && !$_FILES && !Director::redirected_to() ) {
$getVars = $_GET;
unset($getVars['url']);
if($getVars) $url = "?" . http_build_query($getVars);
else $url = "";
Director::redirect($url, 301);
return;
}
if($this->dataRecord) $this->dataRecord->extend('contentcontrollerInit', $this);
else singleton('SiteTree')->extend('contentcontrollerInit', $this);
if(Director::redirected_to()) return;
// Check page permissions
if($this->dataRecord && $this->URLSegment != 'Security' && !$this->dataRecord->canView()) {
return Security::permissionFailure($this);
}
// Draft/Archive security check - only CMS users should be able to look at stage/archived content
if($this->URLSegment != 'Security' && !Session::get('unsecuredDraftSite') && (Versioned::current_archived_date() || (Versioned::current_stage() && Versioned::current_stage() != 'Live'))) {
if(!$this->dataRecord->canViewStage(Versioned::current_stage())) {
$link = $this->Link();
$message = _t("ContentController.DRAFT_SITE_ACCESS_RESTRICTION", 'You must log in with your CMS password in order to view the draft or archived content. Click here to go back to the published site.');
Session::clear('currentStage');
Session::clear('archiveDate');
return Security::permissionFailure($this, sprintf($message, Controller::join_links($link, "?stage=Live")));
}
}
// Use theme from the site config
if(($config = SiteConfig::current_site_config()) && $config->Theme) {
SSViewer::set_theme($config->Theme);
}
}
/**
* This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
* fall over to a child controller in order to provide functionality for nested URLs.
*
* @return SS_HTTPResponse
*/
public function handleRequest(SS_HTTPRequest $request, DataModel $model) {
$child = null;
$action = $request->param('Action');
$this->setModel($model);
// If nested URLs are enabled, and there is no action handler for the current request then attempt to pass
// control to a child controller. This allows for the creation of chains of controllers which correspond to a
// nested URL.
if($action && SiteTree::nested_urls() && !$this->hasAction($action)) {
// See ModelAdController->getNestedController() for similar logic
if(class_exists('Translatable')) Translatable::disable_locale_filter();
// look for a page with this URLSegment
$child = $this->model->SiteTree->where(sprintf (
"\"ParentID\" = %s AND \"URLSegment\" = '%s'", $this->ID, Convert::raw2sql($action)
))->First();
if(class_exists('Translatable')) Translatable::enable_locale_filter();
// if we can't find a page with this URLSegment try to find one that used to have
// that URLSegment but changed. See ModelAsController->getNestedController() for similiar logic.
if(!$child){
$child = ModelAsController::find_old_page($action,$this->ID);
if($child){
$response = new SS_HTTPResponse();
$params = $request->getVars();
if(isset($params['url'])) unset($params['url']);
$response->redirect(
Controller::join_links(
$child->Link(
Controller::join_links(
$request->param('ID'), // 'ID' is the new 'URLSegment', everything shifts up one position
$request->param('OtherID')
)
),
// Needs to be in separate join links to avoid urlencoding
($params) ? '?' . http_build_query($params) : null
),
301
);
return $response;
}
}
}
// we found a page with this URLSegment.
if($child) {
$request->shiftAllParams();
$request->shift();
$response = ModelAsController::controller_for($child)->handleRequest($request, $model);
} else {
// If a specific locale is requested, and it doesn't match the page found by URLSegment,
// look for a translation and redirect (see #5001). Only happens on the last child in
// a potentially nested URL chain.
if(class_exists('Translatable')) {
if($request->getVar('locale') && $this->dataRecord && $this->dataRecord->Locale != $request->getVar('locale')) {
$translation = $this->dataRecord->getTranslation($request->getVar('locale'));
if($translation) {
$response = new SS_HTTPResponse();
$response->redirect($translation->Link(), 301);
throw new SS_HTTPResponse_Exception($response);
}
}
}
Director::set_current_page($this->data());
$response = parent::handleRequest($request, $model);
Director::set_current_page(null);
}
return $response;
}
/**
* @uses ErrorPage::response_for()
*/
public function httpError($code, $message = null) {
if($this->request->isMedia() || !$response = ErrorPage::response_for($code)) {
parent::httpError($code, $message);
} else {
throw new SS_HTTPResponse_Exception($response);
}
}
/**
* Handles widgets attached to a page through one or more {@link WidgetArea} elements.
* Iterated through each $has_one relation with a {@link WidgetArea}
* and looks for connected widgets by their database identifier.
* Assumes URLs in the following format: This website is a simplistic version of a SilverStripe 2 site. To extend this, please take a look at our new tutorials.
You can start editing your site's content by opening the CMS.
Email: $username
Password: $password
For security reasons you should now delete the install files, unless you are planning to reinstall later (requires admin login, see above). The web server also now only needs write access to the "assets" folder, you can remove write access from all other folders. Click here to delete the install files.
Unable to delete installation files. Please delete the files below manually: