2014-05-14 23:24:20 +10:00
|
|
|
<?php namespace Backend\Classes;
|
|
|
|
|
2014-07-01 17:17:53 +10:00
|
|
|
use App;
|
2014-05-14 23:24:20 +10:00
|
|
|
use Log;
|
|
|
|
use Lang;
|
2014-06-16 22:46:11 +02:00
|
|
|
use View;
|
2014-05-14 23:24:20 +10:00
|
|
|
use Flash;
|
2015-01-18 15:30:09 +11:00
|
|
|
use Event;
|
2014-05-14 23:24:20 +10:00
|
|
|
use Request;
|
|
|
|
use Backend;
|
2014-07-01 17:17:53 +10:00
|
|
|
use Session;
|
2014-05-14 23:24:20 +10:00
|
|
|
use Redirect;
|
|
|
|
use Response;
|
|
|
|
use Exception;
|
|
|
|
use BackendAuth;
|
2014-07-11 18:50:11 +10:00
|
|
|
use Backend\Models\UserPreferences;
|
2014-07-01 17:17:53 +10:00
|
|
|
use Backend\Models\BackendPreferences;
|
2015-02-16 21:16:43 +11:00
|
|
|
use System\Classes\ErrorHandler;
|
2015-02-11 18:35:39 +11:00
|
|
|
use October\Rain\Exception\SystemException;
|
|
|
|
use October\Rain\Exception\ValidationException;
|
|
|
|
use October\Rain\Exception\ApplicationException;
|
2014-05-14 23:24:20 +10:00
|
|
|
use October\Rain\Extension\Extendable;
|
2014-06-20 19:30:50 +10:00
|
|
|
use Illuminate\Database\Eloquent\MassAssignmentException;
|
2014-05-14 23:24:20 +10:00
|
|
|
use Illuminate\Http\RedirectResponse;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The Backend base controller class, used by Backend controllers.
|
|
|
|
* The base controller services back end pages.
|
|
|
|
*
|
|
|
|
* @package october\backend
|
|
|
|
* @author Alexey Bobkov, Samuel Georges
|
|
|
|
*/
|
|
|
|
class Controller extends Extendable
|
|
|
|
{
|
|
|
|
use \System\Traits\AssetMaker;
|
|
|
|
use \System\Traits\ConfigMaker;
|
2014-09-29 12:19:19 +10:00
|
|
|
use \System\Traits\ViewMaker;
|
2014-05-14 23:24:20 +10:00
|
|
|
use \Backend\Traits\WidgetMaker;
|
2014-07-15 08:14:59 +10:00
|
|
|
use \October\Rain\Support\Traits\Emitter;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string Object used for storing a fatal error.
|
|
|
|
*/
|
|
|
|
protected $fatalError;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var object Reference the logged in admin user.
|
|
|
|
*/
|
|
|
|
protected $user;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array Collection of WidgetBase objects used on this page.
|
|
|
|
*/
|
|
|
|
public $widget;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var bool Prevents the automatic view display.
|
|
|
|
*/
|
|
|
|
public $suppressView = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array Routed parameters.
|
|
|
|
*/
|
|
|
|
protected $params;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string Page action being called.
|
|
|
|
*/
|
|
|
|
protected $action;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array Defines a collection of actions available without authentication.
|
|
|
|
*/
|
|
|
|
protected $publicActions = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array Permissions required to view this page.
|
|
|
|
*/
|
|
|
|
protected $requiredPermissions = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string Page title
|
|
|
|
*/
|
|
|
|
public $pageTitle;
|
|
|
|
|
2014-06-26 15:29:38 +11:00
|
|
|
/**
|
|
|
|
* @var string Page title template
|
|
|
|
*/
|
|
|
|
public $pageTitleTemplate;
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
|
|
|
* @var string Body class property used for customising the layout on a controller basis.
|
|
|
|
*/
|
|
|
|
public $bodyClass;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array Default methods which cannot be called as actions.
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
public $hiddenActions = [
|
|
|
|
'run',
|
|
|
|
'actionExists',
|
|
|
|
'pageAction',
|
|
|
|
'getId',
|
|
|
|
'setStatusCode',
|
|
|
|
'handleError',
|
|
|
|
'makeHintPartial'
|
|
|
|
];
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array Controller specified methods which cannot be called as actions.
|
|
|
|
*/
|
|
|
|
protected $guarded = [];
|
|
|
|
|
2014-06-17 21:00:26 +10:00
|
|
|
/**
|
|
|
|
* @var int Response status code
|
|
|
|
*/
|
|
|
|
protected $statusCode = 200;
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
*/
|
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Allow early access to route data.
|
|
|
|
*/
|
|
|
|
$this->action = BackendController::$action;
|
|
|
|
$this->params = BackendController::$params;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Apply $guarded methods to hidden actions
|
|
|
|
*/
|
|
|
|
$this->hiddenActions = array_merge($this->hiddenActions, $this->guarded);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Define layout and view paths
|
|
|
|
*/
|
|
|
|
$this->layout = 'default';
|
2014-09-20 11:25:57 +10:00
|
|
|
$this->layoutPath = Skin::getActive()->getLayoutPaths();
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
// Option A: (@todo Determine which is faster by benchmark)
|
|
|
|
// $relativePath = strtolower(str_replace('\\', '/', get_called_class()));
|
|
|
|
// $this->viewPath = $this->configPath = ['modules/' . $relativePath, 'plugins/' . $relativePath];
|
|
|
|
|
|
|
|
// Option B:
|
|
|
|
$this->viewPath = $this->configPath = $this->guessViewPath();
|
|
|
|
|
|
|
|
parent::__construct();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Execute the controller action.
|
|
|
|
* @param string $action The action name.
|
|
|
|
* @param array $params Routing parameters to pass to the action.
|
|
|
|
* @return mixed The action result.
|
|
|
|
*/
|
|
|
|
public function run($action = null, $params = [])
|
|
|
|
{
|
|
|
|
$this->action = $action;
|
|
|
|
$this->params = $params;
|
|
|
|
|
2015-01-18 15:23:19 +11:00
|
|
|
/*
|
|
|
|
* Extensibility
|
|
|
|
*/
|
|
|
|
if (
|
|
|
|
($event = $this->fireEvent('page.beforeDisplay', [$action, $params], true)) ||
|
|
|
|
($event = Event::fire('backend.page.beforeDisplay', [$this, $action, $params], true))
|
|
|
|
) {
|
|
|
|
return $event;
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
|
|
|
* Determine if this request is a public action.
|
|
|
|
*/
|
|
|
|
$isPublicAction = in_array($action, $this->publicActions);
|
|
|
|
|
2014-07-03 20:14:02 +11:00
|
|
|
// Create a new instance of the admin user
|
|
|
|
$this->user = BackendAuth::getUser();
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
|
|
|
* Check that user is logged in and has permission to view this page
|
|
|
|
*/
|
|
|
|
if (!$isPublicAction) {
|
|
|
|
|
2015-01-18 13:16:18 +11:00
|
|
|
/*
|
|
|
|
* Not logged in, redirect to login screen or show ajax error.
|
|
|
|
*/
|
2014-05-14 23:24:20 +10:00
|
|
|
if (!BackendAuth::check()) {
|
2014-10-12 13:43:50 +02:00
|
|
|
return Request::ajax()
|
2014-06-17 19:13:25 +10:00
|
|
|
? Response::make(Lang::get('backend::lang.page.access_denied.label'), 403)
|
2015-02-11 18:35:39 +11:00
|
|
|
: Backend::redirectGuest('backend/auth');
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2015-01-18 13:16:18 +11:00
|
|
|
/*
|
|
|
|
* Check access groups against the page definition
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
if ($this->requiredPermissions && !$this->user->hasAnyAccess($this->requiredPermissions)) {
|
2014-06-17 19:13:25 +10:00
|
|
|
return Response::make(View::make('backend::access_denied'), 403);
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2014-07-01 17:17:53 +10:00
|
|
|
/*
|
|
|
|
* Set the admin preference locale
|
|
|
|
*/
|
|
|
|
if (Session::has('locale')) {
|
|
|
|
App::setLocale(Session::get('locale'));
|
2014-11-04 17:41:48 +11:00
|
|
|
}
|
2014-11-07 19:38:05 +11:00
|
|
|
elseif ($this->user && ($locale = BackendPreferences::get('locale'))) {
|
2014-07-01 17:17:53 +10:00
|
|
|
Session::put('locale', $locale);
|
|
|
|
App::setLocale($locale);
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
|
|
|
* Execute AJAX event
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
if ($ajaxResponse = $this->execAjaxHandlers()) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return $ajaxResponse;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Execute postback handler
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
if (
|
|
|
|
($handler = post('_handler')) &&
|
|
|
|
($handlerResponse = $this->runAjaxHandler($handler)) &&
|
|
|
|
$handlerResponse !== true
|
|
|
|
) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return $handlerResponse;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Execute page action
|
|
|
|
*/
|
2014-06-17 21:00:26 +10:00
|
|
|
$result = $this->execPageAction($action, $params);
|
|
|
|
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!is_string($result)) {
|
2014-06-17 21:00:26 +10:00
|
|
|
return $result;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-06-17 21:00:26 +10:00
|
|
|
|
|
|
|
return Response::make($result, $this->statusCode);
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method is used internally.
|
|
|
|
* Determines whether an action with the specified name exists.
|
|
|
|
* Action must be a class public method. Action name can not be prefixed with the underscore character.
|
|
|
|
* @param string $name Specifies the action name.
|
|
|
|
* @param bool $internal Allow protected actions.
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
public function actionExists($name, $internal = false)
|
|
|
|
{
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!strlen($name) || substr($name, 0, 1) == '_' || !$this->methodExists($name)) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return false;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
foreach ($this->hiddenActions as $method) {
|
2014-10-10 23:12:50 +02:00
|
|
|
if (strtolower($name) == strtolower($method)) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return false;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
$ownMethod = method_exists($this, $name);
|
|
|
|
|
|
|
|
if ($ownMethod) {
|
|
|
|
$methodInfo = new \ReflectionMethod($this, $name);
|
|
|
|
$public = $methodInfo->isPublic();
|
2014-10-10 23:12:50 +02:00
|
|
|
if ($public) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return true;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2014-10-10 23:12:50 +02:00
|
|
|
if ($internal && (($ownMethod && $methodInfo->isProtected()) || !$ownMethod)) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return true;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!$ownMethod) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return true;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invokes the current controller action without rendering a view,
|
2014-08-23 17:23:29 +10:00
|
|
|
* used by AJAX handler that may rely on the logic inside the action.
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
public function pageAction()
|
|
|
|
{
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!$this->action) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
$this->suppressView = true;
|
|
|
|
$this->execPageAction($this->action, $this->params);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method is used internally.
|
|
|
|
* Invokes the controller action and loads the corresponding view.
|
|
|
|
* @param string $actionName Specifies a action name to execute.
|
|
|
|
* @param array $parameters A list of the action parameters.
|
|
|
|
*/
|
|
|
|
protected function execPageAction($actionName, $parameters)
|
|
|
|
{
|
|
|
|
$result = null;
|
|
|
|
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!$this->actionExists($actionName)) {
|
|
|
|
throw new SystemException(sprintf(
|
|
|
|
"Action %s is not found in the controller %s",
|
|
|
|
$actionName,
|
|
|
|
get_class($this)
|
|
|
|
));
|
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
// Execute the action
|
|
|
|
$result = call_user_func_array([$this, $actionName], $parameters);
|
|
|
|
|
2014-10-10 23:12:50 +02:00
|
|
|
if ($result instanceof RedirectResponse) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return $result;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2014-10-15 19:53:44 +11:00
|
|
|
// No page title
|
2014-10-18 11:06:54 +02:00
|
|
|
if (!$this->pageTitle) {
|
2014-10-15 19:53:44 +11:00
|
|
|
$this->pageTitle = 'backend::lang.page.untitled';
|
2014-10-18 11:06:54 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
// Load the view
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!$this->suppressView && is_null($result)) {
|
2014-05-14 23:24:20 +10:00
|
|
|
return $this->makeView($actionName);
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
return $this->makeViewContent($result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method is used internally.
|
|
|
|
* Invokes a controller event handler and loads the supplied partials.
|
|
|
|
*/
|
|
|
|
protected function execAjaxHandlers()
|
|
|
|
{
|
|
|
|
if ($handler = trim(Request::header('X_OCTOBER_REQUEST_HANDLER'))) {
|
|
|
|
try {
|
|
|
|
/*
|
|
|
|
* Validate the handler name
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!preg_match('/^(?:\w+\:{2})?on[A-Z]{1}[\w+]*$/', $handler)) {
|
2014-05-14 23:24:20 +10:00
|
|
|
throw new SystemException(Lang::get('cms::lang.ajax_handler.invalid_name', ['name'=>$handler]));
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate the handler partial list
|
|
|
|
*/
|
|
|
|
if ($partialList = trim(Request::header('X_OCTOBER_REQUEST_PARTIALS'))) {
|
|
|
|
$partialList = explode('&', $partialList);
|
|
|
|
|
|
|
|
// @todo Do we need to validate backend partials?
|
|
|
|
// foreach ($partialList as $partial) {
|
2014-10-10 23:12:50 +02:00
|
|
|
// if (!preg_match('/^(?:\w+\:{2}|@)?[a-z0-9\_\-\.\/]+$/i', $partial)) {
|
|
|
|
// throw new SystemException(Lang::get(
|
|
|
|
// 'cms::lang.partial.invalid_name',
|
|
|
|
// ['name' => $partial]
|
|
|
|
// ));
|
|
|
|
// }
|
2014-05-14 23:24:20 +10:00
|
|
|
// }
|
2014-11-01 12:00:45 +11:00
|
|
|
}
|
|
|
|
else {
|
2014-05-14 23:24:20 +10:00
|
|
|
$partialList = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
$responseContents = [];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Execute the handler
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!$result = $this->runAjaxHandler($handler)) {
|
2014-08-13 07:52:14 +10:00
|
|
|
throw new ApplicationException(Lang::get('cms::lang.ajax_handler.not_found', ['name'=>$handler]));
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the handler returned an array, we should add it to output for rendering.
|
|
|
|
* If it is a string, add it to the array with the key "result".
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
if (is_array($result)) {
|
2014-05-14 23:24:20 +10:00
|
|
|
$responseContents = array_merge($responseContents, $result);
|
2014-11-04 17:41:48 +11:00
|
|
|
}
|
|
|
|
elseif (is_string($result)) {
|
2014-05-14 23:24:20 +10:00
|
|
|
$responseContents['result'] = $result;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Render partials and return the response as array that will be converted to JSON automatically.
|
|
|
|
*/
|
2014-10-10 23:12:50 +02:00
|
|
|
foreach ($partialList as $partial) {
|
2014-05-14 23:24:20 +10:00
|
|
|
$responseContents[$partial] = $this->makePartial($partial);
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the handler returned a redirect, process it so framework.js knows to redirect
|
|
|
|
* the browser and not the request!
|
|
|
|
*/
|
|
|
|
if ($result instanceof RedirectResponse) {
|
|
|
|
$responseContents['X_OCTOBER_REDIRECT'] = $result->getTargetUrl();
|
|
|
|
/*
|
|
|
|
* No redirect is used, look for any flash messages
|
|
|
|
*/
|
2014-11-01 12:00:45 +11:00
|
|
|
}
|
|
|
|
elseif (Flash::check()) {
|
2014-05-14 23:24:20 +10:00
|
|
|
$responseContents['#layout-flash-messages'] = $this->makeLayoutPartial('flash_messages');
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Detect assets
|
|
|
|
*/
|
|
|
|
if ($this->hasAssetsDefined()) {
|
2014-05-16 16:10:29 +10:00
|
|
|
$responseContents['X_OCTOBER_ASSETS'] = $this->getAssetPaths();
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
return Response::make()->setContent($responseContents);
|
2014-11-01 12:00:45 +11:00
|
|
|
}
|
|
|
|
catch (ValidationException $ex) {
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
|
|
|
* Handle validation error gracefully
|
|
|
|
*/
|
|
|
|
Flash::error($ex->getMessage());
|
|
|
|
$responseContents = [];
|
|
|
|
$responseContents['#layout-flash-messages'] = $this->makeLayoutPartial('flash_messages');
|
|
|
|
$responseContents['X_OCTOBER_ERROR_FIELDS'] = $ex->getFields();
|
2014-06-02 18:16:39 +10:00
|
|
|
return Response::make($responseContents, 406);
|
2014-11-01 12:00:45 +11:00
|
|
|
}
|
|
|
|
catch (MassAssignmentException $ex) {
|
2014-10-10 23:12:50 +02:00
|
|
|
return Response::make(
|
|
|
|
Lang::get('backend::lang.model.mass_assignment_failed', ['attribute' => $ex->getMessage()]),
|
|
|
|
500
|
|
|
|
);
|
2014-11-01 12:00:45 +11:00
|
|
|
}
|
|
|
|
catch (Exception $ex) {
|
2015-02-16 21:16:43 +11:00
|
|
|
throw $ex;
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tries to find and run an AJAX handler in the page action.
|
|
|
|
* The method stops as soon as the handler is found.
|
|
|
|
* @return boolean Returns true if the handler was found. Returns false otherwise.
|
|
|
|
*/
|
|
|
|
protected function runAjaxHandler($handler)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Process Widget handler
|
|
|
|
*/
|
|
|
|
if (strpos($handler, '::')) {
|
|
|
|
list($widgetName, $handlerName) = explode('::', $handler);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Execute the page action so widgets are initialized
|
|
|
|
*/
|
|
|
|
$this->pageAction();
|
|
|
|
|
2014-10-10 23:12:50 +02:00
|
|
|
if ($this->fatalError) {
|
2014-07-03 18:35:35 +10:00
|
|
|
throw new SystemException($this->fatalError);
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-07-03 18:35:35 +10:00
|
|
|
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!isset($this->widget->{$widgetName})) {
|
2014-05-14 23:24:20 +10:00
|
|
|
throw new SystemException(Lang::get('backend::lang.widget.not_bound', ['name'=>$widgetName]));
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
if (($widget = $this->widget->{$widgetName}) && method_exists($widget, $handlerName)) {
|
|
|
|
$result = call_user_func_array([$widget, $handlerName], $this->params);
|
|
|
|
return ($result) ?: true;
|
|
|
|
}
|
2014-11-01 12:00:45 +11:00
|
|
|
}
|
|
|
|
else {
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
2014-10-19 10:58:18 +11:00
|
|
|
* Process page specific handler (index_onSomething)
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
$pageHandler = $this->action . '_' . $handler;
|
|
|
|
|
|
|
|
if ($this->methodExists($pageHandler)) {
|
|
|
|
$result = call_user_func_array([$this, $pageHandler], $this->params);
|
|
|
|
return ($result) ?: true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-10-19 10:58:18 +11:00
|
|
|
* Process page global handler (onSomething)
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
if ($this->methodExists($handler)) {
|
|
|
|
$result = call_user_func_array([$this, $handler], $this->params);
|
|
|
|
return ($result) ?: true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cycle each widget to locate a usable handler (widget::onSomething)
|
|
|
|
*/
|
|
|
|
$this->suppressView = true;
|
|
|
|
$this->execPageAction($this->action, $this->params);
|
|
|
|
|
|
|
|
foreach ($this->widget as $widget) {
|
|
|
|
if (method_exists($widget, $handler)) {
|
|
|
|
$result = call_user_func_array([$widget, $handler], $this->params);
|
|
|
|
return ($result) ?: true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a unique ID for the controller and route. Useful in creating HTML markup.
|
|
|
|
*/
|
|
|
|
public function getId($suffix = null)
|
|
|
|
{
|
2014-09-29 13:12:34 +10:00
|
|
|
$id = class_basename(get_called_class()) . '-' . $this->action;
|
2014-10-10 23:12:50 +02:00
|
|
|
if ($suffix !== null) {
|
2014-05-14 23:24:20 +10:00
|
|
|
$id .= '-' . $suffix;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
return $id;
|
|
|
|
}
|
|
|
|
|
2014-06-17 21:00:26 +10:00
|
|
|
/**
|
|
|
|
* Sets the status code for the current web response.
|
|
|
|
* @param int $code Status code
|
|
|
|
*/
|
|
|
|
public function setStatusCode($code)
|
|
|
|
{
|
|
|
|
$this->statusCode = (int) $code;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
|
|
|
* Sets standard page variables in the case of a controller error.
|
|
|
|
*/
|
|
|
|
public function handleError($exception)
|
|
|
|
{
|
2015-02-16 21:16:43 +11:00
|
|
|
$errorMessage = ErrorHandler::getDetailedMessage($exception);
|
2014-12-16 12:21:55 +11:00
|
|
|
$this->fatalError = $errorMessage;
|
|
|
|
$this->vars['fatalError'] = $errorMessage;
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
2014-07-11 18:50:11 +10:00
|
|
|
|
|
|
|
//
|
|
|
|
// Hints
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a hint partial, used for displaying informative information that
|
|
|
|
* can be hidden by the user.
|
|
|
|
* @param string $name Unique key name
|
|
|
|
* @param string $partial Reference to content (partial name)
|
|
|
|
* @param array $params Extra parameters
|
|
|
|
* @return string
|
|
|
|
*/
|
2014-07-17 18:42:12 +10:00
|
|
|
public function makeHintPartial($name, $partial = null, array $params = [])
|
2014-07-11 18:50:11 +10:00
|
|
|
{
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!$partial) {
|
2014-07-17 18:42:12 +10:00
|
|
|
$partial = $name;
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-07-17 18:42:12 +10:00
|
|
|
|
2014-07-11 18:50:11 +10:00
|
|
|
return $this->makeLayoutPartial('hint', [
|
|
|
|
'hintName' => $name,
|
|
|
|
'hintPartial' => $partial,
|
|
|
|
'hintParams' => $params
|
|
|
|
] + $params);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ajax handler to hide a backend hint, once hidden the partial
|
|
|
|
* will no longer display for the user.
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function onHideBackendHint()
|
|
|
|
{
|
2014-10-10 23:12:50 +02:00
|
|
|
if (!$name = post('name')) {
|
2014-07-11 18:50:11 +10:00
|
|
|
throw new ApplicationException('Missing a hint name.');
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|
2014-07-11 18:50:11 +10:00
|
|
|
|
|
|
|
$preferences = UserPreferences::forUser();
|
|
|
|
$hiddenHints = $preferences->get('backend::hints.hidden', []);
|
|
|
|
$hiddenHints[$name] = 1;
|
|
|
|
|
|
|
|
$preferences->set('backend::hints.hidden', $hiddenHints);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if a hint has been hidden by the user.
|
|
|
|
* @param string $name Unique key name
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
public function isBackendHintHidden($name)
|
|
|
|
{
|
|
|
|
$hiddenHints = UserPreferences::forUser()->get('backend::hints.hidden', []);
|
|
|
|
return array_key_exists($name, $hiddenHints);
|
|
|
|
}
|
2014-10-10 23:12:50 +02:00
|
|
|
}
|