Merge branch 'develop' of github.com:octobercms/october into develop
This commit is contained in:
commit
d562e68b91
|
|
@ -2,6 +2,17 @@
|
|||
|
||||
return array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Specifies the default CMS theme
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This parameter value can be overridden by the CMS back-end settings.
|
||||
|
|
||||
*/
|
||||
|
||||
'activeTheme' => 'test',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Plugins directory
|
||||
|
|
@ -66,14 +77,16 @@ return array(
|
|||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Specifies the default CMS theme
|
||||
| Determines if a friendly error page should be used.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This parameter value can be overridden by the CMS back-end settings.
|
||||
| If this value is set to true, a friendly error page is used when an
|
||||
| exception is encountered. You must create a CMS page with route "/error"
|
||||
| to set the contents of this page. Otherwise the default error page is shown.
|
||||
|
|
||||
*/
|
||||
|
||||
'activeTheme' => 'test',
|
||||
'customErrorPage' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
@ -88,7 +101,7 @@ return array(
|
|||
*/
|
||||
|
||||
'enableAssetCache' => false,
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Disables Twig caching for unit tests
|
||||
|
|
|
|||
|
|
@ -104,6 +104,15 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
'context' => 'mysettings',
|
||||
'keywords' => 'backend::lang.myaccount.menu_keywords',
|
||||
],
|
||||
'access_logs' => [
|
||||
'label' => 'backend::lang.access_log.menu_label',
|
||||
'description' => 'backend::lang.access_log.menu_description',
|
||||
'category' => 'Logs',
|
||||
'icon' => 'icon-lock',
|
||||
'url' => Backend::url('backend/accesslogs'),
|
||||
'permissions' => ['backend.access_admin_logs'],
|
||||
'order' => 800
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -9178,151 +9178,151 @@ table.table.data .list-tree a.list-expand-collapse {
|
|||
table.table.data tr.list-tree-level-1 a.list-expand-collapse {
|
||||
left: 30px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-1 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-1 td.list-cell-index-1 {
|
||||
padding-left: 35px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-2 a.list-expand-collapse {
|
||||
left: 40px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-2 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-2 td.list-cell-index-1 {
|
||||
padding-left: 45px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-3 a.list-expand-collapse {
|
||||
left: 50px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-3 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-3 td.list-cell-index-1 {
|
||||
padding-left: 55px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-4 a.list-expand-collapse {
|
||||
left: 60px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-4 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-4 td.list-cell-index-1 {
|
||||
padding-left: 65px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-5 a.list-expand-collapse {
|
||||
left: 70px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-5 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-5 td.list-cell-index-1 {
|
||||
padding-left: 75px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-6 a.list-expand-collapse {
|
||||
left: 80px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-6 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-6 td.list-cell-index-1 {
|
||||
padding-left: 85px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-7 a.list-expand-collapse {
|
||||
left: 90px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-7 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-7 td.list-cell-index-1 {
|
||||
padding-left: 95px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-8 a.list-expand-collapse {
|
||||
left: 100px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-8 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-8 td.list-cell-index-1 {
|
||||
padding-left: 105px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-9 a.list-expand-collapse {
|
||||
left: 110px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-9 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-9 td.list-cell-index-1 {
|
||||
padding-left: 115px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-10 a.list-expand-collapse {
|
||||
left: 120px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-10 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-10 td.list-cell-index-1 {
|
||||
padding-left: 125px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-11 a.list-expand-collapse {
|
||||
left: 130px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-11 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-11 td.list-cell-index-1 {
|
||||
padding-left: 135px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-12 a.list-expand-collapse {
|
||||
left: 140px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-12 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-12 td.list-cell-index-1 {
|
||||
padding-left: 145px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-13 a.list-expand-collapse {
|
||||
left: 150px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-13 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-13 td.list-cell-index-1 {
|
||||
padding-left: 155px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-14 a.list-expand-collapse {
|
||||
left: 160px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-14 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-14 td.list-cell-index-1 {
|
||||
padding-left: 165px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-15 a.list-expand-collapse {
|
||||
left: 170px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-15 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-15 td.list-cell-index-1 {
|
||||
padding-left: 175px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-16 a.list-expand-collapse {
|
||||
left: 180px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-16 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-16 td.list-cell-index-1 {
|
||||
padding-left: 185px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-17 a.list-expand-collapse {
|
||||
left: 190px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-17 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-17 td.list-cell-index-1 {
|
||||
padding-left: 195px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-18 a.list-expand-collapse {
|
||||
left: 200px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-18 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-18 td.list-cell-index-1 {
|
||||
padding-left: 205px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-19 a.list-expand-collapse {
|
||||
left: 210px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-19 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-19 td.list-cell-index-1 {
|
||||
padding-left: 215px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-20 a.list-expand-collapse {
|
||||
left: 220px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-20 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-20 td.list-cell-index-1 {
|
||||
padding-left: 225px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-21 a.list-expand-collapse {
|
||||
left: 230px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-21 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-21 td.list-cell-index-1 {
|
||||
padding-left: 235px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-22 a.list-expand-collapse {
|
||||
left: 240px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-22 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-22 td.list-cell-index-1 {
|
||||
padding-left: 245px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-23 a.list-expand-collapse {
|
||||
left: 250px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-23 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-23 td.list-cell-index-1 {
|
||||
padding-left: 255px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-24 a.list-expand-collapse {
|
||||
left: 260px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-24 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-24 td.list-cell-index-1 {
|
||||
padding-left: 265px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-25 a.list-expand-collapse {
|
||||
left: 270px;
|
||||
}
|
||||
table.table.data tr.list-tree-level-25 td.list-data-column-1 {
|
||||
table.table.data tr.list-tree-level-25 td.list-cell-index-1 {
|
||||
padding-left: 275px;
|
||||
}
|
||||
.list-preview {
|
||||
|
|
@ -9499,6 +9499,13 @@ table.table.data tr.list-tree-level-25 td.list-data-column-1 {
|
|||
.control-simplelist ul {
|
||||
padding-left: 15px;
|
||||
}
|
||||
.control-simplelist.form-control ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.control-simplelist.form-control li {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.control-simplelist.with-icons ul,
|
||||
.control-simplelist.with-checkboxes ul,
|
||||
.control-simplelist.is-selectable ul {
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ table.table.data {
|
|||
.makeTreeLevel(@count) when (@count < 26) {
|
||||
tr.list-tree-level-@{count} {
|
||||
a.list-expand-collapse { left: 20px + (10 * @count); }
|
||||
td.list-data-column-1 { padding-left: 25px + (10 * @count); }
|
||||
td.list-cell-index-1 { padding-left: 25px + (10 * @count); }
|
||||
}
|
||||
.makeTreeLevel(@count + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@
|
|||
|
||||
ul { padding-left: 15px; }
|
||||
|
||||
&.form-control {
|
||||
ul { margin-bottom: 0; }
|
||||
li {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
&.with-icons, &.with-checkboxes, &.is-selectable {
|
||||
ul {
|
||||
list-style-type: none;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class FormController extends ControllerBehavior
|
|||
/**
|
||||
* @var Backend\Classes\WidgetBase Reference to the widget object.
|
||||
*/
|
||||
private $formWidget;
|
||||
protected $formWidget;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
@ -47,7 +47,7 @@ class FormController extends ControllerBehavior
|
|||
/**
|
||||
* @var array List of prepared models that require saving.
|
||||
*/
|
||||
private $modelsToSave = [];
|
||||
protected $modelsToSave = [];
|
||||
|
||||
/**
|
||||
* Behavior constructor
|
||||
|
|
@ -349,7 +349,7 @@ class FormController extends ControllerBehavior
|
|||
* @param array $extras Any extra params to include in the language string variables
|
||||
* @return string The translated string.
|
||||
*/
|
||||
private function getLang($name, $default = null, $extras = [])
|
||||
protected function getLang($name, $default = null, $extras = [])
|
||||
{
|
||||
$name = $this->getConfig($name, $default);
|
||||
$vars = [
|
||||
|
|
@ -567,7 +567,7 @@ class FormController extends ControllerBehavior
|
|||
// Internals
|
||||
//
|
||||
|
||||
private function prepareModelsToSave($model, $saveData)
|
||||
protected function prepareModelsToSave($model, $saveData)
|
||||
{
|
||||
$this->modelsToSave = [];
|
||||
$this->setModelAttributes($model, $saveData);
|
||||
|
|
@ -580,7 +580,7 @@ class FormController extends ControllerBehavior
|
|||
* @param Model $model Model to save to
|
||||
* @return array The collection of models to save.
|
||||
*/
|
||||
private function setModelAttributes($model, $saveData)
|
||||
protected function setModelAttributes($model, $saveData)
|
||||
{
|
||||
$this->modelsToSave[] = $model;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,22 +19,22 @@ class ListController extends ControllerBehavior
|
|||
/**
|
||||
* @var array List definitions, keys for alias and value for configuration.
|
||||
*/
|
||||
private $listDefinitions;
|
||||
protected $listDefinitions;
|
||||
|
||||
/**
|
||||
* @var string The primary list alias to use. Default: list
|
||||
*/
|
||||
private $primaryDefinition;
|
||||
protected $primaryDefinition;
|
||||
|
||||
/**
|
||||
* @var Backend\Classes\WidgetBase Reference to the list widget object.
|
||||
*/
|
||||
private $listWidgets = [];
|
||||
protected $listWidgets = [];
|
||||
|
||||
/**
|
||||
* @var WidgetBase Reference to the toolbar widget objects.
|
||||
*/
|
||||
private $toolbarWidgets = [];
|
||||
protected $toolbarWidgets = [];
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -26,22 +26,22 @@ class RelationController extends ControllerBehavior
|
|||
/**
|
||||
* @var Backend\Classes\WidgetBase Reference to the toolbar widget object.
|
||||
*/
|
||||
private $toolbarWidget;
|
||||
protected $toolbarWidget;
|
||||
|
||||
/**
|
||||
* @var Backend\Classes\WidgetBase Reference to the widget used for viewing (list or form).
|
||||
*/
|
||||
private $viewWidget;
|
||||
protected $viewWidget;
|
||||
|
||||
/**
|
||||
* @var Backend\Classes\WidgetBase Reference to the widget used for relation management.
|
||||
*/
|
||||
private $manageWidget;
|
||||
protected $manageWidget;
|
||||
|
||||
/**
|
||||
* @var Backend\Classes\WidgetBase Reference to widget for relations with pivot data.
|
||||
*/
|
||||
private $pivotWidget;
|
||||
protected $pivotWidget;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
@ -61,12 +61,12 @@ class RelationController extends ControllerBehavior
|
|||
/**
|
||||
* @var array Original configuration values
|
||||
*/
|
||||
private $originalConfig;
|
||||
protected $originalConfig;
|
||||
|
||||
/**
|
||||
* @var bool Has the behavior been initialized.
|
||||
*/
|
||||
private $initialized = false;
|
||||
protected $initialized = false;
|
||||
|
||||
/**
|
||||
* @var string Relationship type
|
||||
|
|
@ -154,6 +154,9 @@ class RelationController extends ControllerBehavior
|
|||
*/
|
||||
public function initRelation($model, $field = null)
|
||||
{
|
||||
if ($field == null)
|
||||
$field = post(self::PARAM_FIELD);
|
||||
|
||||
$this->config = $this->originalConfig;
|
||||
$this->model = $model;
|
||||
$this->field = $field;
|
||||
|
|
@ -323,7 +326,7 @@ class RelationController extends ControllerBehavior
|
|||
* @param string $field The relationship field.
|
||||
* @return string The active field name.
|
||||
*/
|
||||
private function validateField($field = null)
|
||||
protected function validateField($field = null)
|
||||
{
|
||||
$field = $field ?: post(self::PARAM_FIELD);
|
||||
|
||||
|
|
@ -403,7 +406,7 @@ class RelationController extends ControllerBehavior
|
|||
/**
|
||||
* Returns the existing record IDs for the relation.
|
||||
*/
|
||||
private function findExistingRelationIds($checkIds = null)
|
||||
protected function findExistingRelationIds($checkIds = null)
|
||||
{
|
||||
$results = $this->relationObject
|
||||
->getBaseQuery()
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class UserPreferencesModel extends SettingsModel
|
|||
* Checks if a key is legitimate or should be added to
|
||||
* the field value collection
|
||||
*/
|
||||
private function isKeyAllowed($key)
|
||||
protected function isKeyAllowed($key)
|
||||
{
|
||||
/*
|
||||
* Let the core columns through
|
||||
|
|
|
|||
|
|
@ -37,17 +37,17 @@ class AuthManager extends RainAuthManager
|
|||
/**
|
||||
* @var array Cache of registration callbacks.
|
||||
*/
|
||||
private $callbacks = [];
|
||||
protected $callbacks = [];
|
||||
|
||||
/**
|
||||
* @var array List of registered permissions.
|
||||
*/
|
||||
private $permissions = [];
|
||||
protected $permissions = [];
|
||||
|
||||
/**
|
||||
* @var array Cache of registered permissions.
|
||||
*/
|
||||
private $permissionCache = false;
|
||||
protected $permissionCache = false;
|
||||
|
||||
/**
|
||||
* Registers a callback function that defines authentication permissions.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class BackendController extends ControllerBase
|
|||
* @param string $action Specifies a method name to execute.
|
||||
* @return ControllerBase Returns the backend controller object
|
||||
*/
|
||||
private function findController($controller, $action, $dirPrefix = null)
|
||||
protected function findController($controller, $action, $dirPrefix = null)
|
||||
{
|
||||
/*
|
||||
* Workaround: Composer does not support case insensitivity.
|
||||
|
|
|
|||
|
|
@ -53,12 +53,12 @@ class FormField
|
|||
public $options;
|
||||
|
||||
/**
|
||||
* @var string Specifies a side. Possible values: auto, left, right, full
|
||||
* @var string Specifies a side. Possible values: auto, left, right, full.
|
||||
*/
|
||||
public $span = 'full';
|
||||
|
||||
/**
|
||||
* @var string Specifies a size. Possible values: tiny, small, large, huge, giant
|
||||
* @var string Specifies a size. Possible values: tiny, small, large, huge, giant.
|
||||
*/
|
||||
public $size = 'large';
|
||||
|
||||
|
|
@ -88,12 +88,12 @@ class FormField
|
|||
public $comment;
|
||||
|
||||
/**
|
||||
* @var string Specifies the comment position
|
||||
* @var string Specifies the comment position.
|
||||
*/
|
||||
public $commentPosition = 'below';
|
||||
|
||||
/**
|
||||
* @var string Specifies if the comment is in HTML format
|
||||
* @var string Specifies if the comment is in HTML format.
|
||||
*/
|
||||
public $commentHtml = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,15 +51,25 @@ class ListColumn
|
|||
public $relation;
|
||||
|
||||
/**
|
||||
* @var string Specify a CSS class to attach to the list row element.
|
||||
* @var string Specify a CSS class to attach to the list cell element.
|
||||
*/
|
||||
public $cssClass;
|
||||
|
||||
/**
|
||||
* @var string Specify a format or style for the column value, such as a Date
|
||||
* @var string Specify a format or style for the column value, such as a Date.
|
||||
*/
|
||||
public $format;
|
||||
|
||||
/**
|
||||
* @var string Specifies a path for partial-type fields.
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* @var array Raw field configuration.
|
||||
*/
|
||||
public $config;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
|
@ -75,19 +85,30 @@ class ListColumn
|
|||
* - number - numeric column, aligned right
|
||||
* @param string $type Specifies a render mode as described above
|
||||
*/
|
||||
public function displayAs($type)
|
||||
public function displayAs($type, $config)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->type = strtolower($type) ?: $this->type;
|
||||
$this->config = $this->evalConfig($config);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies CSS classes to apply to the table row element.
|
||||
* Process options and apply them to this object.
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
public function cssClass($class)
|
||||
protected function evalConfig($config)
|
||||
{
|
||||
$this->cssClass = $class;
|
||||
return $this;
|
||||
if (isset($config['cssClass'])) $this->cssClass = $config['cssClass'];
|
||||
if (isset($config['searchable'])) $this->searchable = $config['searchable'];
|
||||
if (isset($config['sortable'])) $this->sortable = $config['sortable'];
|
||||
if (isset($config['invisible'])) $this->invisible = $config['invisible'];
|
||||
if (isset($config['select'])) $this->sqlSelect = $config['select'];
|
||||
if (isset($config['relation'])) $this->relation = $config['relation'];
|
||||
if (isset($config['format'])) $this->format = $config['format'];
|
||||
if (isset($config['path'])) $this->path = $config['path'];
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -17,18 +17,18 @@ class NavigationManager
|
|||
/**
|
||||
* @var array Cache of registration callbacks.
|
||||
*/
|
||||
private $callbacks = [];
|
||||
protected $callbacks = [];
|
||||
|
||||
/**
|
||||
* @var array List of registered items.
|
||||
*/
|
||||
private $items;
|
||||
protected $items;
|
||||
|
||||
private $contextSidenavPartials = [];
|
||||
protected $contextSidenavPartials = [];
|
||||
|
||||
private $contextOwner;
|
||||
private $contextMainMenuItemCode;
|
||||
private $contextSideMenuItemCode;
|
||||
protected $contextOwner;
|
||||
protected $contextMainMenuItemCode;
|
||||
protected $contextSideMenuItemCode;
|
||||
|
||||
static $mainItemDefaults = [
|
||||
'code' => null,
|
||||
|
|
@ -419,7 +419,7 @@ class NavigationManager
|
|||
* @param array $items A collection of menu items
|
||||
* @return array The filtered menu items
|
||||
*/
|
||||
private function filterItemPermissions($user, array $items)
|
||||
protected function filterItemPermissions($user, array $items)
|
||||
{
|
||||
$items = array_filter($items, function($item) use ($user) {
|
||||
if (!$item->permissions || !count($item->permissions))
|
||||
|
|
@ -436,7 +436,7 @@ class NavigationManager
|
|||
* @param object $item
|
||||
* @return string
|
||||
*/
|
||||
private function makeItemKey($owner, $code)
|
||||
protected function makeItemKey($owner, $code)
|
||||
{
|
||||
return strtoupper($owner).'.'.strtoupper($code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class WidgetManager
|
|||
/**
|
||||
* @var array Cache of report widget registration callbacks.
|
||||
*/
|
||||
private $formWidgetCallbacks = [];
|
||||
protected $formWidgetCallbacks = [];
|
||||
|
||||
/**
|
||||
* @var array An array of report widgets.
|
||||
|
|
@ -42,7 +42,7 @@ class WidgetManager
|
|||
/**
|
||||
* @var array Cache of report widget registration callbacks.
|
||||
*/
|
||||
private $reportWidgetCallbacks = [];
|
||||
protected $reportWidgetCallbacks = [];
|
||||
|
||||
/**
|
||||
* @var array An array where keys are aliases and values are class names.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
<?php namespace Backend\Controllers;
|
||||
|
||||
use Str;
|
||||
use Lang;
|
||||
use File;
|
||||
use Flash;
|
||||
use Backend;
|
||||
use Redirect;
|
||||
use BackendMenu;
|
||||
use Backend\Classes\Controller;
|
||||
use System\Classes\ApplicationException;
|
||||
use System\Classes\SettingsManager;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Access Logs controller
|
||||
*
|
||||
* @package october\system
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*
|
||||
*/
|
||||
class AccessLogs extends Controller
|
||||
{
|
||||
|
||||
public $implement = [
|
||||
'Backend.Behaviors.ListController'
|
||||
];
|
||||
|
||||
public $requiredPermissions = ['system.access_access_logs'];
|
||||
|
||||
public $listConfig = 'config_list.yaml';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
BackendMenu::setContext('October.System', 'system', 'settings');
|
||||
SettingsManager::setContext('October.Backend', 'access_logs');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ use Redirect;
|
|||
use Validator;
|
||||
use BackendAuth;
|
||||
use Backend\Models\User;
|
||||
use Backend\Models\AccessLog;
|
||||
use Backend\Classes\Controller;
|
||||
use System\Classes\VersionManager;
|
||||
use System\Classes\ApplicationException;
|
||||
|
|
@ -73,6 +74,9 @@ class Auth extends Controller
|
|||
'password' => post('password')
|
||||
], true);
|
||||
|
||||
// Log the sign in event
|
||||
AccessLog::add($user);
|
||||
|
||||
// Load version updates
|
||||
VersionManager::instance()->updateAll();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
<p>
|
||||
<?= e(trans('backend::lang.access_log.hint', ['days' => 60])) ?>
|
||||
</p>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div data-control="toolbar">
|
||||
|
||||
</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# ===================================
|
||||
# List Behavior Config
|
||||
# ===================================
|
||||
|
||||
title: backend::lang.access_log.menu_label
|
||||
list: @/modules/backend/models/accesslog/columns.yaml
|
||||
modelClass: Backend\Models\AccessLog
|
||||
noRecordsMessage: backend::lang.list.no_records
|
||||
showSetup: true
|
||||
|
||||
toolbar:
|
||||
buttons: list_toolbar
|
||||
search:
|
||||
prompt: backend::lang.list.search_prompt
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<div class="padded-container list-header">
|
||||
<?= $this->makeHintPartial('backend_accesslogs_hint', 'hint') ?>
|
||||
</div>
|
||||
|
||||
<?= $this->listRender() ?>
|
||||
|
|
@ -52,10 +52,10 @@
|
|||
<?php Block::endPut() ?>
|
||||
|
||||
<?php else: ?>
|
||||
<div class="control-breadcrumb">
|
||||
<?= Block::placeholder('breadcrumb') ?>
|
||||
</div>
|
||||
<div class="padded-container">
|
||||
<div class="control-breadcrumb">
|
||||
<?= Block::placeholder('breadcrumb') ?>
|
||||
</div>
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
<p><a href="<?= Backend::url('backend/users') ?>" class="btn btn-default"><?= e(trans('backend::lang.user.return')) ?></a></p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@
|
|||
<?php Block::endPut() ?>
|
||||
|
||||
<?php else: ?>
|
||||
<div class="control-breadcrumb">
|
||||
<?= Block::placeholder('breadcrumb') ?>
|
||||
</div>
|
||||
<div class="padded-container">
|
||||
<div class="control-breadcrumb">
|
||||
<?= Block::placeholder('breadcrumb') ?>
|
||||
</div>
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
<p><a href="<?= Backend::url('backend/users') ?>" class="btn btn-default"><?= e(trans('backend::lang.user.return')) ?></a></p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@
|
|||
<?php Block::endPut() ?>
|
||||
|
||||
<?php else: ?>
|
||||
<div class="control-breadcrumb">
|
||||
<?= Block::placeholder('breadcrumb') ?>
|
||||
</div>
|
||||
<div class="padded-container">
|
||||
<div class="control-breadcrumb">
|
||||
<?= Block::placeholder('breadcrumb') ?>
|
||||
</div>
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
<p><a href="<?= Backend::url('backend/users') ?>" class="btn btn-default"><?= e(trans('backend::lang.user.return')) ?></a></p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DbBackendAccessLog extends Migration
|
||||
{
|
||||
|
||||
public function up()
|
||||
{
|
||||
Schema::create('backend_access_log', function(Blueprint $table)
|
||||
{
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->string('ip_address')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('backend_access_log');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -38,6 +38,14 @@ class DataGrid extends FormWidgetBase
|
|||
$this->grid->bindToController();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Backend\Widgets\Grid The grid to be displayed.
|
||||
*/
|
||||
public function getGrid()
|
||||
{
|
||||
return $this->grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
@ -74,19 +82,57 @@ class DataGrid extends FormWidgetBase
|
|||
$grid = new Grid($this->controller, $config);
|
||||
$grid->alias = $this->alias . 'Grid';
|
||||
$grid->bindEvent('grid.autocomplete', [$this, 'getAutocompleteValues']);
|
||||
$grid->bindEvent('grid.dataSource', [$this, 'getDataSourceValues']);
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks at the model for getXXXAutocompleteValues or getGridAutocompleteValues methods
|
||||
* to obtain values for autocomplete field types.
|
||||
* @param string $field Grid field name
|
||||
* @param string $value Current value
|
||||
* @param string $data Data for the entire grid
|
||||
* @return array
|
||||
*/
|
||||
public function getAutocompleteValues($field, $value, $data)
|
||||
{
|
||||
if (!$this->model->methodExists('getGridAutocompleteValues'))
|
||||
$methodName = 'get'.studly_case($this->columnName).'AutocompleteValues';
|
||||
|
||||
if (!$this->model->methodExists($methodName) && !$this->model->methodExists('getGridAutocompleteValues'))
|
||||
throw new ApplicationException('Model :model does not contain a method getGridAutocompleteValues()');
|
||||
|
||||
$result = $this->model->getGridAutocompleteValues($field, $value, $data);
|
||||
if ($this->model->methodExists($methodName))
|
||||
$result = $this->model->$methodName($field, $value, $data);
|
||||
else
|
||||
$result = $this->model->getGridAutocompleteValues($this->columnName, $field, $value, $data);
|
||||
|
||||
if (!is_array($result))
|
||||
$result = [];
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks at the model for getXXXDataSourceValues or getGridDataSourceValues methods
|
||||
* to obtain the starting values for the grid.
|
||||
* @return array
|
||||
*/
|
||||
public function getDataSourceValues()
|
||||
{
|
||||
$methodName = 'get'.studly_case($this->columnName).'DataSourceValues';
|
||||
|
||||
if (!$this->model->methodExists($methodName) && !$this->model->methodExists('getGridDataSourceValues'))
|
||||
throw new ApplicationException('Model :model does not contain a method getGridDataSourceValues()');
|
||||
|
||||
if ($this->model->methodExists($methodName))
|
||||
$result = $this->model->$methodName();
|
||||
else
|
||||
$result = $this->model->getGridDataSourceValues($this->columnName);
|
||||
|
||||
if (!is_array($result))
|
||||
$result = [];
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,10 +68,13 @@ class FileUpload extends FormWidgetBase
|
|||
$columnName = $this->columnName;
|
||||
$list = $this->model->$columnName()->withDeferred($this->sessionKey)->orderBy('sort_order')->get();
|
||||
|
||||
// Set the thumb for each file
|
||||
/*
|
||||
* Set the thumb for each file
|
||||
*/
|
||||
foreach ($list as $file) {
|
||||
$file->thumb = $file->getThumb($this->imageWidth, $this->imageHeight, ['mode' => 'crop']);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
<?php namespace Backend\FormWidgets;
|
||||
|
||||
use Lang;
|
||||
use Backend\Classes\FormWidgetBase;
|
||||
use System\Classes\SystemException;
|
||||
|
||||
/**
|
||||
* Date picker
|
||||
* Record Finder
|
||||
* Renders a record finder field.
|
||||
*
|
||||
* user:
|
||||
|
|
|
|||
|
|
@ -187,4 +187,15 @@ return [
|
|||
'locale' => 'Language',
|
||||
'locale_comment' => 'Select your desired locale for language use.',
|
||||
],
|
||||
'access_log' => [
|
||||
'hint' => 'This log displays a list of successful sign in attempts by administrators. Records are kept for a total of :days days.',
|
||||
'menu_label' => 'Access Log',
|
||||
'menu_description' => 'View a list of successful back-end user sign ins.',
|
||||
'created_at' => 'Date & Time',
|
||||
'login' => 'Login',
|
||||
'ip_address' => 'IP address',
|
||||
'first_name' => 'First name',
|
||||
'last_name' => 'Last name',
|
||||
'email' => 'Email',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
<div class="layout responsive-sidebar">
|
||||
<div class="layout-cell">
|
||||
<!-- Breadcrumb -->
|
||||
<?php if ($breadcrumbContent = Block::placeholder('breadcrumb')): ?>
|
||||
<div class="control-breadcrumb">
|
||||
<?= $breadcrumbContent ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="padded-container">
|
||||
|
||||
<!-- Breadcrumb -->
|
||||
<?php if ($breadcrumbContent = Block::placeholder('breadcrumb')): ?>
|
||||
<div class="control-breadcrumb">
|
||||
<?= $breadcrumbContent ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?= Block::placeholder('form-contents') ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
<?php namespace Backend\Models;
|
||||
|
||||
use Model;
|
||||
use Request;
|
||||
|
||||
/**
|
||||
* Model for logging access to the back-end
|
||||
*/
|
||||
class AccessLog extends Model
|
||||
{
|
||||
/**
|
||||
* @var string The database table used by the model.
|
||||
*/
|
||||
protected $table = 'backend_access_log';
|
||||
|
||||
/**
|
||||
* @var array Relations
|
||||
*/
|
||||
public $belongsTo = [
|
||||
'user' => ['Backend\Models\User']
|
||||
];
|
||||
|
||||
/**
|
||||
* Creates a log record
|
||||
* @param Backend\Models\User $user Admin user
|
||||
* @return self
|
||||
*/
|
||||
public static function add($user)
|
||||
{
|
||||
$record = new static;
|
||||
$record->user = $user;
|
||||
$record->ip_address = Request::getClientIp();
|
||||
$record->save();
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# ===================================
|
||||
# Column Definitions
|
||||
# ===================================
|
||||
|
||||
columns:
|
||||
created_at:
|
||||
label: backend::lang.access_log.created_at
|
||||
searchable: yes
|
||||
|
||||
login:
|
||||
label: backend::lang.access_log.login
|
||||
relation: user
|
||||
select: @login
|
||||
searchable: yes
|
||||
|
||||
ip_address:
|
||||
label: backend::lang.access_log.ip_address
|
||||
searchable: yes
|
||||
|
||||
first_name:
|
||||
label: backend::lang.access_log.first_name
|
||||
relation: user
|
||||
select: @first_name
|
||||
searchable: yes
|
||||
|
||||
last_name:
|
||||
label: backend::lang.access_log.last_name
|
||||
relation: user
|
||||
select: @first_name
|
||||
searchable: yes
|
||||
|
||||
email:
|
||||
label: backend::lang.access_log.email
|
||||
relation: user
|
||||
select: @email
|
||||
searchable: yes
|
||||
|
|
@ -45,8 +45,8 @@ trait ViewMaker
|
|||
* Render a partial file contents located in the views folder.
|
||||
* @param string $partial The view to load.
|
||||
* @param array $params Parameter variables to pass to the view.
|
||||
* @param bool $throwException Throw an exception if the partial is not found
|
||||
* @return string The view contents.
|
||||
* @param bool $throwException Throw an exception if the partial is not found.
|
||||
* @return mixed Partial contents or false if not throwing an exception.
|
||||
*/
|
||||
public function makePartial($partial, $params = [], $throwException = true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@ class Form extends WidgetBase
|
|||
/**
|
||||
* @var boolean Determines if field definitions have been created.
|
||||
*/
|
||||
private $fieldsDefined = false;
|
||||
protected $fieldsDefined = false;
|
||||
|
||||
/**
|
||||
* @var array Collection of all fields used in this form.
|
||||
*/
|
||||
public $allFields = [];
|
||||
|
||||
/**
|
||||
/**
|
||||
* @var array Collection of all form widgets used in this form.
|
||||
*/
|
||||
public $formWidgets = [];
|
||||
|
|
@ -218,7 +218,7 @@ class Form extends WidgetBase
|
|||
/**
|
||||
* Prepares the list data
|
||||
*/
|
||||
public function prepareVars()
|
||||
protected function prepareVars()
|
||||
{
|
||||
$this->defineFormFields();
|
||||
$this->vars['sessionKey'] = $this->getSessionKey();
|
||||
|
|
@ -517,7 +517,7 @@ class Form extends WidgetBase
|
|||
* @param string $fieldType
|
||||
* @return boolean
|
||||
*/
|
||||
private function isFormWidget($fieldType)
|
||||
protected function isFormWidget($fieldType)
|
||||
{
|
||||
if ($fieldType === null)
|
||||
return false;
|
||||
|
|
@ -539,7 +539,7 @@ class Form extends WidgetBase
|
|||
/**
|
||||
* Makes a widget object from a form field object.
|
||||
*/
|
||||
public function makeFormWidget($field)
|
||||
protected function makeFormWidget($field)
|
||||
{
|
||||
if ($field->type != 'widget')
|
||||
return null;
|
||||
|
|
@ -687,7 +687,7 @@ class Form extends WidgetBase
|
|||
/**
|
||||
* Looks at the model for defined options.
|
||||
*/
|
||||
private function getOptionsFromModel($field, $fieldOptions)
|
||||
protected function getOptionsFromModel($field, $fieldOptions)
|
||||
{
|
||||
/*
|
||||
* Advanced usage, supplied options are callable
|
||||
|
|
@ -751,7 +751,7 @@ class Form extends WidgetBase
|
|||
* @param string $method
|
||||
* @return boolean
|
||||
*/
|
||||
private function methodExists($object, $method)
|
||||
protected function methodExists($object, $method)
|
||||
{
|
||||
if (method_exists($object, 'methodExists'))
|
||||
return $object->methodExists($method);
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ class Grid extends WidgetBase
|
|||
|
||||
case 'currency':
|
||||
$item['type'] = 'numeric';
|
||||
$item['format'] = '$0,0.00';
|
||||
$item['format'] = isset($column['format']) ? $column['format'] : '$0,0.00';
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
|
|
@ -258,4 +258,4 @@ class Grid extends WidgetBase
|
|||
$this->addJs('js/datagrid.js', 'core');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ class Lists extends WidgetBase
|
|||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
private function parseTableName($sql, $table)
|
||||
protected function parseTableName($sql, $table)
|
||||
{
|
||||
return str_replace('@', $table.'.', $sql);
|
||||
}
|
||||
|
|
@ -502,18 +502,10 @@ class Lists extends WidgetBase
|
|||
else
|
||||
$label = studly_case($name);
|
||||
|
||||
$column = new ListColumn($name, $label);
|
||||
$columnType = isset($config['type']) ? $config['type'] : null;
|
||||
|
||||
/*
|
||||
* Process options
|
||||
*/
|
||||
if (isset($config['type'])) $column->type = $config['type'];
|
||||
if (isset($config['searchable'])) $column->searchable = $config['searchable'];
|
||||
if (isset($config['sortable'])) $column->sortable = $config['sortable'];
|
||||
if (isset($config['invisible'])) $column->invisible = $config['invisible'];
|
||||
if (isset($config['select'])) $column->sqlSelect = $config['select'];
|
||||
if (isset($config['relation'])) $column->relation = $config['relation'];
|
||||
if (isset($config['format'])) $column->format = $config['format'];
|
||||
$column = new ListColumn($name, $label);
|
||||
$column->displayAs($columnType, $config);
|
||||
|
||||
return $column;
|
||||
}
|
||||
|
|
@ -606,6 +598,14 @@ class Lists extends WidgetBase
|
|||
// Value processing
|
||||
//
|
||||
|
||||
/**
|
||||
* Process as boolean switch
|
||||
*/
|
||||
public function evalPartialTypeValue($value, $column)
|
||||
{
|
||||
return $this->controller->makePartial($column->path ?: $column->columnName, ['value' => $value, 'column' => $column]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process as boolean switch
|
||||
*/
|
||||
|
|
@ -679,7 +679,7 @@ class Lists extends WidgetBase
|
|||
/**
|
||||
* Validates a column type as a date
|
||||
*/
|
||||
private function validateDateTimeValue($value, $column)
|
||||
protected function validateDateTimeValue($value, $column)
|
||||
{
|
||||
if ($value instanceof DateTime)
|
||||
$value = Carbon::instance($value);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class Toolbar extends WidgetBase
|
|||
/**
|
||||
* @var WidgetBase Reference to the search widget object.
|
||||
*/
|
||||
private $searchWidget;
|
||||
protected $searchWidget;
|
||||
|
||||
/**
|
||||
* @var string Name of partial containing control panel.
|
||||
|
|
|
|||
|
|
@ -73,6 +73,12 @@
|
|||
if (this.options.data) {
|
||||
handsontableOptions.data = this.options.data
|
||||
}
|
||||
/*
|
||||
* Data from an AJAX data source
|
||||
*/
|
||||
else if (this.options.sourceHandler) {
|
||||
self.refreshDataSource()
|
||||
}
|
||||
/*
|
||||
* Data from a data locker
|
||||
*/
|
||||
|
|
@ -96,12 +102,6 @@
|
|||
delete handsontableOptions.data
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Data from an AJAX data source
|
||||
*/
|
||||
else if (this.options.sourceHandler) {
|
||||
self.refreshDataSource()
|
||||
}
|
||||
|
||||
/*
|
||||
* Monitor for data changes
|
||||
|
|
@ -454,4 +454,4 @@
|
|||
Handsontable.PluginHooks.add('afterUpdateSettings', function () {
|
||||
init.call(this)
|
||||
});
|
||||
})(Handsontable, jQuery);
|
||||
})(Handsontable, jQuery);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<?php $index = 0; foreach ($columns as $key => $column): ?>
|
||||
<?php $index++; ?>
|
||||
<td data-title="<?= e(trans($column->label)) ?>" class="list-data-column-<?= $index ?> list-data-column-<?= $column->columnName ?>">
|
||||
<td data-title="<?= e(trans($column->label)) ?>" class="list-cell-index-<?= $index ?> list-cell-name-<?= $column->columnName ?> list-cell-type-<?= $column->type ?> <?= $column->cssClass ?>">
|
||||
<?php if ($index == 1 && ($url = $this->getRecordUrl($record))): ?>
|
||||
<a <?= $this->getRecordOnClick($record) ?> href="<?= $url ?>">
|
||||
<?= $this->getColumnValue($record, $column) ?>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<?php foreach ($columns as $key => $column): ?>
|
||||
<?php if ($showSorting && $column->sortable): ?>
|
||||
<th class="<?= $this->sortColumn==$column->columnName?'sort-'.$this->sortDirection.' active':'sort-desc' ?> list-data-column-<?= $column->columnName ?>"">
|
||||
<th class="<?= $this->sortColumn==$column->columnName?'sort-'.$this->sortDirection.' active':'sort-desc' ?> list-cell-name-<?= $column->columnName ?>">
|
||||
<a
|
||||
href="javascript:;"
|
||||
data-request="<?= $this->getEventHandler('onSort') ?>"
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
</a>
|
||||
</th>
|
||||
<?php else: ?>
|
||||
<th class="list-data-column-<?= $column->columnName ?>">
|
||||
<th class="list-cell-name-<?= $column->columnName ?>">
|
||||
<span><?= $this->getHeaderValue($column) ?></span>
|
||||
</th>
|
||||
<?php endif ?>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class CmsException extends ApplicationException
|
|||
/**
|
||||
* @var Cms\Classes\CmsCompoundObject A reference to a CMS object used for masking errors.
|
||||
*/
|
||||
private $compoundObject;
|
||||
protected $compoundObject;
|
||||
|
||||
/**
|
||||
* @var array Collection of error codes for each error distinction.
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ use Validator;
|
|||
use System\Classes\SystemException;
|
||||
use System\Classes\ApplicationException;
|
||||
use October\Rain\Support\ValidationException;
|
||||
use Exception;
|
||||
use RecursiveIteratorIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use ArrayAccess;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* This is a base class for all CMS objects - content files, pages, partials and layouts.
|
||||
|
|
|
|||
|
|
@ -17,22 +17,22 @@ class CodeParser
|
|||
/**
|
||||
* @var \Cms\Classes\CmsCompoundObject A reference to the CMS object being parsed.
|
||||
*/
|
||||
private $object;
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* @var string Contains a path to the CMS object's file being parsed.
|
||||
*/
|
||||
private $filePath;
|
||||
protected $filePath;
|
||||
|
||||
/**
|
||||
* @var mixed The internal cache, keeps parsed object information during a request.
|
||||
*/
|
||||
static private $cache = [];
|
||||
static protected $cache = [];
|
||||
|
||||
/**
|
||||
* @var string Key for the parsed PHP file information cache.
|
||||
*/
|
||||
private $dataCacheKey = 'cms-php-file-data';
|
||||
protected $dataCacheKey = 'cms-php-file-data';
|
||||
|
||||
/**
|
||||
* Creates the class instance
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class ComponentManager
|
|||
/**
|
||||
* @var array Cache of registration callbacks.
|
||||
*/
|
||||
private $callbacks = [];
|
||||
protected $callbacks = [];
|
||||
|
||||
/**
|
||||
* @var array An array where keys are codes and values are class names.
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@ use Twig_Environment;
|
|||
use Controller as BaseController;
|
||||
use Cms\Twig\Loader as TwigLoader;
|
||||
use Cms\Twig\Extension as CmsTwigExtension;
|
||||
use System\Twig\Extension as SystemTwigExtension;
|
||||
use Cms\Classes\FileHelper as CmsFileHelper;
|
||||
use System\Models\RequestLog;
|
||||
use System\Classes\ErrorHandler;
|
||||
use System\Twig\Extension as SystemTwigExtension;
|
||||
use October\Rain\Support\Markdown;
|
||||
use October\Rain\Support\ValidationException;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
|
@ -141,6 +142,9 @@ class Controller extends BaseController
|
|||
if (!$page) {
|
||||
$this->setStatusCode(404);
|
||||
|
||||
// Log the 404 request
|
||||
RequestLog::add();
|
||||
|
||||
if (!$page = $this->router->findByUrl('/404'))
|
||||
return Response::make(View::make('cms::404'), $this->statusCode);
|
||||
}
|
||||
|
|
@ -535,8 +539,12 @@ class Controller extends BaseController
|
|||
/**
|
||||
* Renders a requested partial.
|
||||
* The framework uses this method internally.
|
||||
* @param string $partial The view to load.
|
||||
* @param array $params Parameter variables to pass to the view.
|
||||
* @param bool $throwException Throw an exception if the partial is not found.
|
||||
* @return mixed Partial contents or false if not throwing an exception.
|
||||
*/
|
||||
public function renderPartial($name, $parameters = [])
|
||||
public function renderPartial($name, $parameters = [], $throwException = true)
|
||||
{
|
||||
/*
|
||||
* Alias @ symbol for ::
|
||||
|
|
@ -555,18 +563,26 @@ class Controller extends BaseController
|
|||
* Component alias not supplied
|
||||
*/
|
||||
if (!strlen($componentAlias)) {
|
||||
if ($this->componentContext !== null)
|
||||
if ($this->componentContext !== null) {
|
||||
$componentObj = $this->componentContext;
|
||||
|
||||
elseif (($componentObj = $this->findComponentByPartial($partialName)) === null)
|
||||
throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$name]));
|
||||
}
|
||||
elseif (($componentObj = $this->findComponentByPartial($partialName)) === null) {
|
||||
if ($throwException)
|
||||
throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$name]));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Component alias is supplied
|
||||
*/
|
||||
else {
|
||||
if (($componentObj = $this->findComponentByName($componentAlias)) === null)
|
||||
throw new CmsException(Lang::get('cms::lang.component.not_found', ['name'=>$componentAlias]));
|
||||
if (($componentObj = $this->findComponentByName($componentAlias)) === null) {
|
||||
if ($throwException)
|
||||
throw new CmsException(Lang::get('cms::lang.component.not_found', ['name'=>$componentAlias]));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$partial = null;
|
||||
|
|
@ -587,8 +603,12 @@ class Controller extends BaseController
|
|||
$partial = ComponentPartial::loadCached($componentObj, $partialName);
|
||||
|
||||
|
||||
if ($partial === null)
|
||||
throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$name]));
|
||||
if ($partial === null) {
|
||||
if ($throwException)
|
||||
throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$name]));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set context for self access
|
||||
|
|
@ -599,8 +619,12 @@ class Controller extends BaseController
|
|||
/*
|
||||
* Process theme partial
|
||||
*/
|
||||
if (($partial = Partial::loadCached($this->theme, $name)) === null)
|
||||
throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$name]));
|
||||
if (($partial = Partial::loadCached($this->theme, $name)) === null) {
|
||||
if ($throwException)
|
||||
throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$name]));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CmsException::mask($partial, 400);
|
||||
|
|
@ -665,7 +689,7 @@ class Controller extends BaseController
|
|||
return $result;
|
||||
}
|
||||
|
||||
return $this->renderPartial($name.'::default');
|
||||
return $this->renderPartial($name.'::default', [], false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -797,7 +821,7 @@ class Controller extends BaseController
|
|||
* Searches the layout and page components by an alias
|
||||
* @return ComponentBase The component object, if found
|
||||
*/
|
||||
private function findComponentByName($name)
|
||||
protected function findComponentByName($name)
|
||||
{
|
||||
if (isset($this->page->components[$name]))
|
||||
return $this->page->components[$name];
|
||||
|
|
@ -812,7 +836,7 @@ class Controller extends BaseController
|
|||
* Searches the layout and page components by an AJAX handler
|
||||
* @return ComponentBase The component object, if found
|
||||
*/
|
||||
private function findComponentByHandler($handler)
|
||||
protected function findComponentByHandler($handler)
|
||||
{
|
||||
foreach ($this->page->components as $component) {
|
||||
if (method_exists($component, $handler))
|
||||
|
|
@ -831,7 +855,7 @@ class Controller extends BaseController
|
|||
* Searches the layout and page components by a partial file
|
||||
* @return ComponentBase The component object, if found
|
||||
*/
|
||||
private function findComponentByPartial($partial)
|
||||
protected function findComponentByPartial($partial)
|
||||
{
|
||||
foreach ($this->page->components as $component) {
|
||||
$fileName = ComponentPartial::getFilePath($component, $partial);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class Router
|
|||
/**
|
||||
* @var array A list of parameters names and values extracted from the URL pattern and URL string.
|
||||
*/
|
||||
private $parameters = [];
|
||||
protected $parameters = [];
|
||||
|
||||
/**
|
||||
* @var array Contains the URL map - the list of page file names and corresponding URL patterns.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use Lang;
|
|||
use Cache;
|
||||
use Event;
|
||||
use Config;
|
||||
use DbDongle;
|
||||
use October\Rain\Support\Yaml;
|
||||
use System\Models\Parameters;
|
||||
use System\Classes\SystemException;
|
||||
|
|
@ -97,13 +98,15 @@ class Theme
|
|||
$paramKey = 'cms::theme.active';
|
||||
$activeTheme = Config::get('cms.activeTheme');
|
||||
|
||||
$dbResult = Parameters::findRecord($paramKey)
|
||||
->remember(1440, $paramKey)
|
||||
->pluck('value')
|
||||
;
|
||||
if (DbDongle::hasDatabase()) {
|
||||
$dbResult = Parameters::findRecord($paramKey)
|
||||
->remember(1440, $paramKey)
|
||||
->pluck('value')
|
||||
;
|
||||
|
||||
if ($dbResult !== null)
|
||||
$activeTheme = $dbResult;
|
||||
if ($dbResult !== null)
|
||||
$activeTheme = $dbResult;
|
||||
}
|
||||
|
||||
$apiResult = Event::fire('cms.activeTheme', [], true);
|
||||
if ($apiResult !== null)
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ class Index extends Controller
|
|||
* @param string $markup The markup to convert to unix style endings
|
||||
* @return string
|
||||
*/
|
||||
private function convertLineEndings($markup)
|
||||
protected function convertLineEndings($markup)
|
||||
{
|
||||
$markup = str_replace("\r\n", "\n", $markup);
|
||||
$markup = str_replace("\r", "\n", $markup);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class Extension extends Twig_Extension
|
|||
/**
|
||||
* @var \Cms\Classes\Controller A reference to the CMS controller.
|
||||
*/
|
||||
private $controller;
|
||||
protected $controller;
|
||||
|
||||
/**
|
||||
* Creates the extension instance.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Lang;
|
|||
use Event;
|
||||
use Config;
|
||||
use Backend;
|
||||
use DbDongle;
|
||||
use BackendMenu;
|
||||
use BackendAuth;
|
||||
use Twig_Environment;
|
||||
|
|
@ -16,6 +17,7 @@ use System\Classes\SettingsManager;
|
|||
use System\Twig\Engine as TwigEngine;
|
||||
use System\Twig\Loader as TwigLoader;
|
||||
use System\Twig\Extension as TwigExtension;
|
||||
use System\Models\EventLog;
|
||||
use System\Models\MailSettings;
|
||||
use System\Models\MailTemplate;
|
||||
use Backend\Classes\WidgetManager;
|
||||
|
|
@ -73,6 +75,16 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
return $handler->handleException($exception, $httpCode, $isConsole);
|
||||
});
|
||||
|
||||
/*
|
||||
* Write all log events to the database
|
||||
*/
|
||||
Event::listen('illuminate.log', function($level, $message, $context){
|
||||
if (!DbDongle::hasDatabase())
|
||||
return;
|
||||
|
||||
EventLog::add($message, $level);
|
||||
});
|
||||
|
||||
/*
|
||||
* Register basic Twig
|
||||
*/
|
||||
|
|
@ -99,7 +111,7 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
});
|
||||
|
||||
/*
|
||||
* Override system email with email settings
|
||||
* Override system mailer with mail settings
|
||||
*/
|
||||
Event::listen('mailer.beforeRegister', function() {
|
||||
if (MailSettings::isConfigured())
|
||||
|
|
@ -202,7 +214,7 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
*/
|
||||
SettingsManager::instance()->registerCallback(function($manager){
|
||||
$manager->registerSettingItems('October.System', [
|
||||
'email_settings' => [
|
||||
'mail_settings' => [
|
||||
'label' => 'system::lang.mail.menu_label',
|
||||
'description' => 'system::lang.mail.menu_description',
|
||||
'category' => 'System',
|
||||
|
|
@ -235,8 +247,25 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
'url' => Backend::url('system/updates'),
|
||||
'permissions' => ['system.manage_updates'],
|
||||
'order' => 700
|
||||
]
|
||||
|
||||
],
|
||||
'event_logs' => [
|
||||
'label' => 'system::lang.event_log.menu_label',
|
||||
'description' => 'system::lang.event_log.menu_description',
|
||||
'category' => 'Logs',
|
||||
'icon' => 'icon-exclamation-triangle',
|
||||
'url' => Backend::url('system/eventlogs'),
|
||||
'permissions' => ['system.access_event_logs'],
|
||||
'order' => 800
|
||||
],
|
||||
'request_logs' => [
|
||||
'label' => 'system::lang.request_log.menu_label',
|
||||
'description' => 'system::lang.request_log.menu_description',
|
||||
'category' => 'Logs',
|
||||
'icon' => 'icon-file-o',
|
||||
'url' => Backend::url('system/requestlogs'),
|
||||
'permissions' => ['system.access_request_logs'],
|
||||
'order' => 800
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -261,7 +290,6 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
/*
|
||||
* Register the sidebar for the System main menu
|
||||
*/
|
||||
|
||||
BackendMenu::registerContextSidenavPartial('October.System', 'system', '@/modules/system/partials/_system_sidebar.htm');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ class SettingsModel extends ModelBehavior
|
|||
* Checks if a key is legitimate or should be added to
|
||||
* the field value collection
|
||||
*/
|
||||
private function isKeyAllowed($key)
|
||||
protected function isKeyAllowed($key)
|
||||
{
|
||||
/*
|
||||
* Let the core columns through
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class ExceptionBase extends Exception
|
|||
/**
|
||||
* @var Exception If this exception is acting as a mask, this property stores the face exception.
|
||||
*/
|
||||
private $mask;
|
||||
protected $mask;
|
||||
|
||||
/**
|
||||
* @var string Hint Message to help the user with troubleshooting the error (optional).
|
||||
|
|
@ -43,7 +43,7 @@ class ExceptionBase extends Exception
|
|||
/**
|
||||
* @var stdObject Cached code information for highlighting code.
|
||||
*/
|
||||
private $highlight;
|
||||
protected $highlight;
|
||||
|
||||
/**
|
||||
* CMS base exception class constructor. Inherits the native PHP Exception.
|
||||
|
|
@ -254,7 +254,7 @@ class ExceptionBase extends Exception
|
|||
* @param array $traceInfo The trace information from getTrace() or debug_backtrace().
|
||||
* @return array The filtered array containing the trace information.
|
||||
*/
|
||||
private function filterCallStack($traceInfo)
|
||||
protected function filterCallStack($traceInfo)
|
||||
{
|
||||
/*
|
||||
* Determine if filter should be used at all.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class MarkupManager
|
|||
/**
|
||||
* @var array Cache of registration callbacks.
|
||||
*/
|
||||
private $callbacks = [];
|
||||
protected $callbacks = [];
|
||||
|
||||
/**
|
||||
* @var array Registered extension items
|
||||
|
|
|
|||
|
|
@ -17,20 +17,20 @@ class SettingsManager
|
|||
/**
|
||||
* @var array Cache of registration callbacks.
|
||||
*/
|
||||
private $callbacks = [];
|
||||
protected $callbacks = [];
|
||||
|
||||
/**
|
||||
* @var array List of registered items.
|
||||
*/
|
||||
private $items;
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* @var array Flat collection of all items.
|
||||
*/
|
||||
private $allItems;
|
||||
protected $allItems;
|
||||
|
||||
private $contextOwner;
|
||||
private $contextItemCode;
|
||||
protected $contextOwner;
|
||||
protected $contextItemCode;
|
||||
|
||||
static $itemDefaults = [
|
||||
'code' => null,
|
||||
|
|
@ -270,7 +270,7 @@ class SettingsManager
|
|||
* @param array $items A collection of setting items
|
||||
* @return array The filtered settings items
|
||||
*/
|
||||
private function filterItemPermissions($user, array $items)
|
||||
protected function filterItemPermissions($user, array $items)
|
||||
{
|
||||
array_filter($items, function($item) use ($user) {
|
||||
if (!$item->permissions || !count($item->permissions))
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ class UpdateManager
|
|||
* @param string $fileCode A unique file code
|
||||
* @return string Full path on the disk
|
||||
*/
|
||||
private function getFilePath($fileCode)
|
||||
protected function getFilePath($fileCode)
|
||||
{
|
||||
$name = md5($fileCode) . '.arc';
|
||||
return $this->tempDirectory . '/' . $name;
|
||||
|
|
@ -628,7 +628,7 @@ class UpdateManager
|
|||
* @param string $uri URI
|
||||
* @return string URL
|
||||
*/
|
||||
private function createServerUrl($uri)
|
||||
protected function createServerUrl($uri)
|
||||
{
|
||||
$gateway = Config::get('cms.updateServer', 'http://octobercms.com/api');
|
||||
if (substr($gateway, -1) != '/')
|
||||
|
|
@ -643,7 +643,7 @@ class UpdateManager
|
|||
* @param array $postData Post data
|
||||
* @return void
|
||||
*/
|
||||
private function applyHttpAttributes($http, $postData)
|
||||
protected function applyHttpAttributes($http, $postData)
|
||||
{
|
||||
$postData['url'] = base64_encode(URL::to('/'));
|
||||
|
||||
|
|
@ -664,7 +664,7 @@ class UpdateManager
|
|||
* Create a nonce based on millisecond time
|
||||
* @return int
|
||||
*/
|
||||
private function createNonce()
|
||||
protected function createNonce()
|
||||
{
|
||||
$mt = explode(' ', microtime());
|
||||
return $mt[1] . substr($mt[0], 2, 6);
|
||||
|
|
@ -674,7 +674,7 @@ class UpdateManager
|
|||
* Create a unique signature for transmission.
|
||||
* @return string
|
||||
*/
|
||||
private function createSignature($data, $secret)
|
||||
protected function createSignature($data, $secret)
|
||||
{
|
||||
return base64_encode(hash_hmac('sha512', http_build_query($data, '', '&'), base64_decode($secret), true));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ class VersionManager
|
|||
/**
|
||||
* Returns the absolute path to a version file for a plugin.
|
||||
*/
|
||||
private function getVersionFile($code)
|
||||
protected function getVersionFile($code)
|
||||
{
|
||||
$versionFile = $this->pluginManager->getPluginPath($code) . '/updates/version.yaml';
|
||||
return $versionFile;
|
||||
|
|
@ -252,7 +252,7 @@ class VersionManager
|
|||
/**
|
||||
* Checks if a plugin has a version file.
|
||||
*/
|
||||
private function hasVersionFile($code)
|
||||
protected function hasVersionFile($code)
|
||||
{
|
||||
$versionFile = $this->getVersionFile($code);
|
||||
return File::isFile($versionFile);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
<?php namespace System\Controllers;
|
||||
|
||||
use Str;
|
||||
use Lang;
|
||||
use File;
|
||||
use Flash;
|
||||
use Backend;
|
||||
use Redirect;
|
||||
use BackendMenu;
|
||||
use Backend\Classes\Controller;
|
||||
use System\Classes\ApplicationException;
|
||||
use System\Classes\SettingsManager;
|
||||
use System\Models\EventLog;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Event Logs controller
|
||||
*
|
||||
* @package october\system
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*
|
||||
*/
|
||||
class EventLogs extends Controller
|
||||
{
|
||||
|
||||
public $implement = [
|
||||
'Backend.Behaviors.FormController',
|
||||
'Backend.Behaviors.ListController'
|
||||
];
|
||||
|
||||
public $requiredPermissions = ['system.access_event_logs'];
|
||||
|
||||
public $formConfig = 'config_form.yaml';
|
||||
|
||||
public $listConfig = 'config_list.yaml';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
BackendMenu::setContext('October.System', 'system', 'settings');
|
||||
SettingsManager::setContext('October.System', 'event_logs');
|
||||
}
|
||||
|
||||
public function onEmptyLog()
|
||||
{
|
||||
EventLog::truncate();
|
||||
Flash::success(Lang::get('system::lang.event_log.empty_success'));
|
||||
return $this->listRefresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?php namespace System\Controllers;
|
||||
|
||||
use Str;
|
||||
use Lang;
|
||||
use File;
|
||||
use Flash;
|
||||
use Backend;
|
||||
use Redirect;
|
||||
use BackendMenu;
|
||||
use Backend\Classes\Controller;
|
||||
use System\Classes\ApplicationException;
|
||||
use System\Classes\SettingsManager;
|
||||
use System\Models\RequestLog;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Request Logs controller
|
||||
*
|
||||
* @package october\system
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*
|
||||
*/
|
||||
class RequestLogs extends Controller
|
||||
{
|
||||
|
||||
public $implement = [
|
||||
'Backend.Behaviors.FormController',
|
||||
'Backend.Behaviors.ListController'
|
||||
];
|
||||
|
||||
public $requiredPermissions = ['system.access_request_logs'];
|
||||
|
||||
public $formConfig = 'config_form.yaml';
|
||||
|
||||
public $listConfig = 'config_list.yaml';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
BackendMenu::setContext('October.System', 'system', 'settings');
|
||||
SettingsManager::setContext('October.System', 'request_logs');
|
||||
}
|
||||
|
||||
public function onEmptyLog()
|
||||
{
|
||||
RequestLog::truncate();
|
||||
Flash::success(Lang::get('system::lang.event_log.empty_success'));
|
||||
return $this->listRefresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ class Settings extends Controller
|
|||
/**
|
||||
* @var WidgetBase Reference to the widget object.
|
||||
*/
|
||||
private $formWidget;
|
||||
protected $formWidget;
|
||||
|
||||
public $requiredPermissions = ['system.manage_settings'];
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ class Settings extends Controller
|
|||
/**
|
||||
* Locates a setting item for a module or plugin
|
||||
*/
|
||||
private function findSettingItem($author, $plugin, $code)
|
||||
protected function findSettingItem($author, $plugin, $code)
|
||||
{
|
||||
$manager = SettingsManager::instance();
|
||||
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ class Updates extends Controller
|
|||
return $this->makePartial('execute');
|
||||
}
|
||||
|
||||
private function buildUpdateSteps($core, $plugins, $themes)
|
||||
protected function buildUpdateSteps($core, $plugins, $themes)
|
||||
{
|
||||
if (!is_array($core))
|
||||
$core = [null, null];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
<p>
|
||||
<?= e(trans('system::lang.event_log.hint')) ?>
|
||||
</p>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<div data-control="toolbar" class="loading-indicator-container">
|
||||
<a
|
||||
href="javascript:;"
|
||||
data-request="onEmptyLog"
|
||||
data-load-indicator="<?= e(trans('system::lang.event_log.empty_loading')) ?>"
|
||||
class="btn btn-default oc-icon-trash-o">
|
||||
<?= e(trans('system::lang.event_log.empty_link')) ?>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<?= Str::limit($value, 100) ?>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# ===================================
|
||||
# Form Behavior Config
|
||||
# ===================================
|
||||
|
||||
# Record name
|
||||
name: Log
|
||||
|
||||
# Model Form Field configuration
|
||||
form: @/modules/system/models/eventlog/fields.yaml
|
||||
|
||||
# Model Class name
|
||||
modelClass: System\Models\EventLog
|
||||
|
||||
# Default redirect location
|
||||
defaultRedirect: system/eventlogs
|
||||
|
||||
# Preview page
|
||||
preview:
|
||||
title: Event
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# ===================================
|
||||
# List Behavior Config
|
||||
# ===================================
|
||||
|
||||
title: system::lang.event_log.menu_label
|
||||
list: @/modules/system/models/eventlog/columns.yaml
|
||||
modelClass: System\Models\EventLog
|
||||
recordUrl: system/eventlogs/preview/:id
|
||||
noRecordsMessage: backend::lang.list.no_records
|
||||
showSetup: true
|
||||
|
||||
toolbar:
|
||||
buttons: list_toolbar
|
||||
search:
|
||||
prompt: backend::lang.list.search_prompt
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<div class="padded-container list-header">
|
||||
<?= $this->makeHintPartial('system_eventlogs_hint', 'hint') ?>
|
||||
</div>
|
||||
|
||||
<?= $this->listRender() ?>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?php Block::put('breadcrumb') ?>
|
||||
<ul>
|
||||
<li><a href="<?= Backend::url('system/eventlogs') ?>"><?= e(trans('system::lang.event_log.menu_label')) ?></a></li>
|
||||
<li><?= e($this->pageTitle) ?></li>
|
||||
</ul>
|
||||
<?php Block::endPut() ?>
|
||||
|
||||
<?php if (!$this->fatalError): ?>
|
||||
|
||||
<div class="scoreboard">
|
||||
<div data-control="toolbar">
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.event_log.id_label')) ?></h4>
|
||||
<p>#<?= $formModel->id ?></p>
|
||||
</div>
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.event_log.level')) ?></h4>
|
||||
<p><?= $formModel->level ?></p>
|
||||
</div>
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.event_log.created_at')) ?></h4>
|
||||
<p><?= $formModel->created_at->toDayDateTimeString() ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-item stretch layout-column">
|
||||
<?= $this->formRenderPreview() ?>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
<p>
|
||||
<a href="<?= Backend::url('system/eventlogs') ?>" class="btn btn-default oc-icon-chevron-left">
|
||||
<?= e(trans('system::lang.event_log.return_link')) ?>
|
||||
</a>
|
||||
</p>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
<p>
|
||||
<?= e(trans('system::lang.request_log.hint')) ?>
|
||||
</p>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<div data-control="toolbar" class="loading-indicator-container">
|
||||
<a
|
||||
href="javascript:;"
|
||||
data-request="onEmptyLog"
|
||||
data-load-indicator="<?= e(trans('system::lang.request_log.empty_loading')) ?>"
|
||||
class="btn btn-default oc-icon-trash-o">
|
||||
<?= e(trans('system::lang.request_log.empty_link')) ?>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php if (count($formModel->referer) > 0): ?>
|
||||
<div class="form-control control-simplelist with-icons">
|
||||
<ul>
|
||||
<?php foreach ((array) $formModel->referer as $referer): ?>
|
||||
<li class="oc-icon-file-o"><?= $referer ?></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="form-control"><em>There were no detected referers to this URL.</em></div>
|
||||
<?php endif ?>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# ===================================
|
||||
# Form Behavior Config
|
||||
# ===================================
|
||||
|
||||
# Record name
|
||||
name: Log
|
||||
|
||||
# Model Form Field configuration
|
||||
form: @/modules/system/models/requestlog/fields.yaml
|
||||
|
||||
# Model Class name
|
||||
modelClass: System\Models\RequestLog
|
||||
|
||||
# Default redirect location
|
||||
defaultRedirect: system/requestlogs
|
||||
|
||||
# Preview page
|
||||
preview:
|
||||
title: Request
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# ===================================
|
||||
# List Behavior Config
|
||||
# ===================================
|
||||
|
||||
title: system::lang.request_log.menu_label
|
||||
list: @/modules/system/models/requestlog/columns.yaml
|
||||
modelClass: System\Models\RequestLog
|
||||
recordUrl: system/requestlogs/preview/:id
|
||||
noRecordsMessage: backend::lang.list.no_records
|
||||
showSetup: true
|
||||
|
||||
toolbar:
|
||||
buttons: list_toolbar
|
||||
search:
|
||||
prompt: backend::lang.list.search_prompt
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<div class="padded-container list-header">
|
||||
<?= $this->makeHintPartial('system_requestlogs_hint', 'hint') ?>
|
||||
</div>
|
||||
|
||||
<?= $this->listRender() ?>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php Block::put('breadcrumb') ?>
|
||||
<ul>
|
||||
<li><a href="<?= Backend::url('system/requestlogs') ?>"><?= e(trans('system::lang.request_log.menu_label')) ?></a></li>
|
||||
<li><?= e($this->pageTitle) ?></li>
|
||||
</ul>
|
||||
<?php Block::endPut() ?>
|
||||
|
||||
<?php if (!$this->fatalError): ?>
|
||||
|
||||
<div class="scoreboard">
|
||||
<div data-control="toolbar">
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.request_log.id_label')) ?></h4>
|
||||
<p>#<?= $formModel->id ?></p>
|
||||
</div>
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.request_log.status_code')) ?></h4>
|
||||
<p><?= $formModel->status_code ?></p>
|
||||
</div>
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.request_log.count')) ?></h4>
|
||||
<p><?= $formModel->count ?></p>
|
||||
</div>
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.request_log.referer')) ?></h4>
|
||||
<p><?= $formModel->referer ? count($formModel->referer) : 0 ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-item stretch layout-column">
|
||||
<?= $this->formRenderPreview() ?>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
<p>
|
||||
<a href="<?= Backend::url('system/requestlogs') ?>" class="btn btn-default oc-icon-chevron-left">
|
||||
<?= e(trans('system::lang.request_log.return_link')) ?>
|
||||
</a>
|
||||
</p>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DbSystemEventLogs extends Migration
|
||||
{
|
||||
|
||||
public function up()
|
||||
{
|
||||
Schema::create('system_event_logs', function(Blueprint $table)
|
||||
{
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->string('level')->nullable()->index();
|
||||
$table->text('message')->nullable();
|
||||
$table->mediumtext('details')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('system_event_logs');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DbSystemRequestLogs extends Migration
|
||||
{
|
||||
|
||||
public function up()
|
||||
{
|
||||
Schema::create('system_request_logs', function(Blueprint $table)
|
||||
{
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->integer('status_code')->nullable();
|
||||
$table->string('url')->nullable();
|
||||
$table->text('referer')->nullable();
|
||||
$table->integer('count')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('system_request_logs');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -176,4 +176,33 @@ return [
|
|||
'zip' => [
|
||||
'extract_failed' => "Unable to extract core file ':file'.",
|
||||
],
|
||||
'event_log' => [
|
||||
'hint' => 'This log displays a list of potential errors that occur in the application, such as exceptions and debugging information.',
|
||||
'menu_label' => 'Event Log',
|
||||
'menu_description' => 'View system log messages with their recorded time and details.',
|
||||
'empty_link' => 'Empty event log',
|
||||
'empty_loading' => 'Emptying event log...',
|
||||
'empty_success' => 'Successfully emptied the event log.',
|
||||
'return_link' => 'Return to event log',
|
||||
'id' => 'ID',
|
||||
'id_label' => 'Event ID',
|
||||
'created_at' => 'Date & Time',
|
||||
'message' => 'Message',
|
||||
'level' => 'Level',
|
||||
],
|
||||
'request_log' => [
|
||||
'hint' => 'This log displays a list of browser requests that may require attention. For example, if a visitor opens a CMS page that cannot be found, a record is created with the status code 404.',
|
||||
'menu_label' => 'Request Log',
|
||||
'menu_description' => 'View bad or redirected requests, such as Page not found (404).',
|
||||
'empty_link' => 'Empty request log',
|
||||
'empty_loading' => 'Emptying request log...',
|
||||
'empty_success' => 'Successfully emptied the request log.',
|
||||
'return_link' => 'Return to request log',
|
||||
'id' => 'ID',
|
||||
'id_label' => 'Log ID',
|
||||
'count' => 'Counter',
|
||||
'referer' => 'Referers',
|
||||
'url' => 'URL',
|
||||
'status_code' => 'Status',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
<?php namespace System\Models;
|
||||
|
||||
use Model;
|
||||
|
||||
/**
|
||||
* Model for logging system errors and debug trace messages
|
||||
*/
|
||||
class EventLog extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string The database table used by the model.
|
||||
*/
|
||||
protected $table = 'system_event_logs';
|
||||
|
||||
/**
|
||||
* @var array List of attribute names which are json encoded and decoded from the database.
|
||||
*/
|
||||
protected $jsonable = ['details'];
|
||||
|
||||
/**
|
||||
* Creates a log record
|
||||
* @param string $message Specifies the message text
|
||||
* @param string $level Specifies the logging level
|
||||
* @param string $details Specifies the error details string
|
||||
* @return self
|
||||
*/
|
||||
public static function add($message, $level = 'info', $details = null)
|
||||
{
|
||||
$record = new static;
|
||||
$record->message = $message;
|
||||
$record->level = $level;
|
||||
|
||||
if ($details !== null)
|
||||
$record->details = (array) $details;
|
||||
|
||||
$record->save();
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Beautify level value.
|
||||
* @param string $level
|
||||
* @return string
|
||||
*/
|
||||
public function getLevelAttribute($level)
|
||||
{
|
||||
return ucfirst($level);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php namespace System\Models;
|
||||
|
||||
use Model;
|
||||
use Request;
|
||||
|
||||
/**
|
||||
* Model for logging 404 errors
|
||||
*/
|
||||
class RequestLog extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string The database table used by the model.
|
||||
*/
|
||||
protected $table = 'system_request_logs';
|
||||
|
||||
/**
|
||||
* @var array The attributes that aren't mass assignable.
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* @var array List of attribute names which are json encoded and decoded from the database.
|
||||
*/
|
||||
protected $jsonable = ['referer'];
|
||||
|
||||
/**
|
||||
* Creates a log record
|
||||
* @return self
|
||||
*/
|
||||
public static function add($statusCode = 404)
|
||||
{
|
||||
$record = static::firstOrNew([
|
||||
'url' => Request::fullUrl(),
|
||||
'status_code' => $statusCode,
|
||||
]);
|
||||
|
||||
if ($referer = Request::header('referer')) {
|
||||
$referers = (array) $record->referer ?: [];
|
||||
$referers[] = $referer;
|
||||
$record->referer = $referers;
|
||||
}
|
||||
|
||||
if (!$record->exists) {
|
||||
$record->count = 1;
|
||||
$record->save();
|
||||
}
|
||||
else {
|
||||
$record->increment('count');
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# ===================================
|
||||
# Column Definitions
|
||||
# ===================================
|
||||
|
||||
columns:
|
||||
id:
|
||||
label: system::lang.event_log.id
|
||||
searchable: yes
|
||||
|
||||
created_at:
|
||||
label: system::lang.event_log.created_at
|
||||
searchable: yes
|
||||
|
||||
message:
|
||||
label: system::lang.event_log.message
|
||||
searchable: yes
|
||||
type: partial
|
||||
path: message_column
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# ===================================
|
||||
# Field Definitions
|
||||
# ===================================
|
||||
|
||||
fields:
|
||||
|
||||
message:
|
||||
type: textarea
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# ===================================
|
||||
# Column Definitions
|
||||
# ===================================
|
||||
|
||||
columns:
|
||||
status_code:
|
||||
label: system::lang.request_log.status_code
|
||||
searchable: yes
|
||||
|
||||
url:
|
||||
label: system::lang.request_log.url
|
||||
searchable: yes
|
||||
|
||||
count:
|
||||
label: system::lang.request_log.count
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# ===================================
|
||||
# Field Definitions
|
||||
# ===================================
|
||||
|
||||
fields:
|
||||
|
||||
url:
|
||||
label: system::lang.request_log.url
|
||||
|
||||
referer:
|
||||
label: system::lang.request_log.referer
|
||||
type: partial
|
||||
path: referer_field
|
||||
|
|
@ -212,7 +212,7 @@ trait AssetMaker
|
|||
* @param array $asset Stored asset array
|
||||
* @return string
|
||||
*/
|
||||
private function getAssetEntryBuildPath($asset)
|
||||
protected function getAssetEntryBuildPath($asset)
|
||||
{
|
||||
$path = $asset['path'];
|
||||
if (isset($asset['attributes']['build'])) {
|
||||
|
|
@ -234,7 +234,7 @@ trait AssetMaker
|
|||
* @param string $asset Specifies a path (URL) to the asset.
|
||||
* @return string
|
||||
*/
|
||||
private function getAssetScheme($asset)
|
||||
protected function getAssetScheme($asset)
|
||||
{
|
||||
if (preg_match("/(\/\/|http|https)/", $asset))
|
||||
return $asset;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class Extension extends Twig_Extension
|
|||
/**
|
||||
* @var \System\Classes\MarkupManager A reference to the markup manager instance.
|
||||
*/
|
||||
private $markupManager;
|
||||
protected $markupManager;
|
||||
|
||||
/**
|
||||
* Creates the extension instance.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Cms\Classes\Controller;
|
||||
use Cms\Classes\Theme;
|
||||
use Cms\Classes\Controller;
|
||||
|
||||
class ControllerTest extends TestCase
|
||||
{
|
||||
|
|
@ -10,7 +10,6 @@ class ControllerTest extends TestCase
|
|||
/*
|
||||
* Test the built-in 404 page
|
||||
*/
|
||||
|
||||
$theme = new Theme();
|
||||
$theme->load('apitest');
|
||||
$controller = new Controller($theme);
|
||||
|
|
@ -26,7 +25,6 @@ class ControllerTest extends TestCase
|
|||
/*
|
||||
* Test the theme 404 page
|
||||
*/
|
||||
|
||||
$theme = new Theme();
|
||||
$theme->load('test');
|
||||
$controller = new Controller($theme);
|
||||
|
|
|
|||
Loading…
Reference in New Issue