This commit is contained in:
Kerim 2022-12-14 20:55:13 +05:00
parent ddcd5a8d9a
commit d6e4c9171b
6187 changed files with 127177 additions and 264106 deletions

BIN
dump.rdb Normal file

Binary file not shown.

View File

@ -80,6 +80,7 @@ class ServiceProvider extends ModuleServiceProvider
$combiner->registerBundle('~/modules/backend/formwidgets/colorpicker/assets/less/colorpicker.less');
$combiner->registerBundle('~/modules/backend/formwidgets/permissioneditor/assets/less/permissioneditor.less');
$combiner->registerBundle('~/modules/backend/formwidgets/markdowneditor/assets/less/markdowneditor.less');
$combiner->registerBundle('~/modules/backend/formwidgets/sensitive/assets/less/sensitive.less');
/*
* Rich Editor is protected by DRM
@ -164,10 +165,16 @@ class ServiceProvider extends ModuleServiceProvider
'backend.manage_editor' => [
'label' => 'system::lang.permissions.manage_editor',
'tab' => 'system::lang.permissions.name',
'roles' => UserRole::CODE_DEVELOPER,
],
'backend.manage_own_editor' => [
'label' => 'system::lang.permissions.manage_own_editor',
'tab' => 'system::lang.permissions.name',
],
'backend.manage_branding' => [
'label' => 'system::lang.permissions.manage_branding',
'tab' => 'system::lang.permissions.name',
'roles' => UserRole::CODE_DEVELOPER,
],
'media.manage_media' => [
'label' => 'backend::lang.permissions.manage_media',
@ -202,6 +209,7 @@ class ServiceProvider extends ModuleServiceProvider
$manager->registerFormWidget('Backend\FormWidgets\TagList', 'taglist');
$manager->registerFormWidget('Backend\FormWidgets\MediaFinder', 'mediafinder');
$manager->registerFormWidget('Backend\FormWidgets\NestedForm', 'nestedform');
$manager->registerFormWidget('Backend\FormWidgets\Sensitive', 'sensitive');
});
}

View File

@ -679,9 +679,10 @@ nav#layout-mainmenu .toolbar-item:before {left:-12px}
nav#layout-mainmenu .toolbar-item:after {right:-12px}
nav#layout-mainmenu .toolbar-item.scroll-active-before:before {color:#fff}
nav#layout-mainmenu .toolbar-item.scroll-active-after:after {color:#fff}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-preview {margin:0 0 0 21px}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-preview i {font-size:20px}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-preview a {position:relative;padding:0 10px;top:-1px}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action {margin:0}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action:first-child {margin-left:21px}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action i {font-size:20px}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action a {position:relative;padding:0 10px;top:-1px}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account {margin-right:0}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account >a {padding:0 15px 0 10px;font-size:13px;position:relative}
nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account.highlight >a {z-index:600}
@ -706,8 +707,8 @@ nav#layout-mainmenu ul li .mainmenu-accountmenu li:first-child a:active:after {c
nav#layout-mainmenu ul li .mainmenu-accountmenu li.divider {height:1px;width:100%;background-color:#e0e0e0}
nav#layout-mainmenu.navbar-mode-inline,
nav#layout-mainmenu.navbar-mode-inline_no_icons {height:60px}
nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-toolbar li.mainmenu-preview a,
nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-toolbar li.mainmenu-preview a {height:60px;line-height:60px}
nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-toolbar li.mainmenu-quick-action a,
nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-toolbar li.mainmenu-quick-action a {height:60px;line-height:60px}
nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-toolbar li.mainmenu-account >a,
nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-toolbar li.mainmenu-account >a {height:60px;line-height:60px}
nav#layout-mainmenu.navbar-mode-inline ul li .mainmenu-accountmenu,
@ -730,7 +731,7 @@ nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li:last-child,
nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li:last-child {margin-right:0}
nav#layout-mainmenu.navbar-mode-inline_no_icons .nav-icon {display:none !important}
nav#layout-mainmenu.navbar-mode-tile {height:78px}
nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-toolbar li.mainmenu-preview a {height:78px;line-height:78px}
nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-toolbar li.mainmenu-quick-action a {height:78px;line-height:78px}
nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-toolbar li.mainmenu-account >a {height:78px;line-height:78px}
nav#layout-mainmenu.navbar-mode-tile ul li .mainmenu-accountmenu {top:88px}
nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li a {position:relative;width:65px;height:65px}
@ -749,14 +750,14 @@ nav#layout-mainmenu .menu-toggle .menu-toggle-title {margin-left:10px}
nav#layout-mainmenu .menu-toggle:hover .menu-toggle-icon {opacity:1}
body.mainmenu-open nav#layout-mainmenu .menu-toggle-icon {opacity:1}
nav#layout-mainmenu.navbar-mode-collapse {padding-left:0;height:45px}
nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-preview a {height:45px;line-height:45px}
nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-quick-action a {height:45px;line-height:45px}
nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-account >a {height:45px;line-height:45px}
nav#layout-mainmenu.navbar-mode-collapse ul li .mainmenu-accountmenu {top:55px}
nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-account >a {padding-right:0}
nav#layout-mainmenu.navbar-mode-collapse ul li .mainmenu-accountmenu:after {right:13px}
nav#layout-mainmenu.navbar-mode-collapse ul.nav {display:none}
nav#layout-mainmenu.navbar-mode-collapse .menu-toggle {display:inline-block;color:#fff !important}
@media (max-width:769px) {nav#layout-mainmenu.navbar {padding-left:0;height:45px }nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-preview a {height:45px;line-height:45px }nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-account >a {height:45px;line-height:45px }nav#layout-mainmenu.navbar ul li .mainmenu-accountmenu {top:55px }nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-account >a {padding-right:0 }nav#layout-mainmenu.navbar ul li .mainmenu-accountmenu:after {right:13px }nav#layout-mainmenu.navbar ul.nav {display:none }nav#layout-mainmenu.navbar .menu-toggle {display:inline-block;color:#fff !important }}
@media (max-width:769px) {nav#layout-mainmenu.navbar {padding-left:0;height:45px }nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-quick-action a {height:45px;line-height:45px }nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-account >a {height:45px;line-height:45px }nav#layout-mainmenu.navbar ul li .mainmenu-accountmenu {top:55px }nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-account >a {padding-right:0 }nav#layout-mainmenu.navbar ul li .mainmenu-accountmenu:after {right:13px }nav#layout-mainmenu.navbar ul.nav {display:none }nav#layout-mainmenu.navbar .menu-toggle {display:inline-block;color:#fff !important }}
.mainmenu-collapsed {position:absolute;height:100%;top:0;left:0;margin:0;background:#000}
.mainmenu-collapsed >div {display:block;height:100%}
.mainmenu-collapsed >div ul.mainmenu-nav li a {position:relative;width:65px;height:65px}

View File

@ -47,7 +47,7 @@ body.mainmenu-open {
height: @height;
ul.mainmenu-toolbar {
li.mainmenu-preview {
li.mainmenu-quick-action {
a {
height: @height;
line-height: @height;
@ -191,8 +191,12 @@ nav#layout-mainmenu {
//
ul.mainmenu-toolbar {
li.mainmenu-preview {
margin: 0 0 0 21px;
li.mainmenu-quick-action {
margin: 0;
&:first-child {
margin-left: 21px;
}
i {
font-size: 20px;

0
modules/backend/assets/vendor/jcrop/MIT-LICENSE.txt vendored Normal file → Executable file
View File

0
modules/backend/assets/vendor/jcrop/README.md vendored Normal file → Executable file
View File

0
modules/backend/assets/vendor/jcrop/css/Jcrop.gif vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 329 B

0
modules/backend/assets/vendor/jcrop/css/jquery.Jcrop.min.css vendored Normal file → Executable file
View File

0
modules/backend/assets/vendor/jcrop/js/jquery.Jcrop.js vendored Normal file → Executable file
View File

View File

@ -646,7 +646,7 @@ class FormController extends ControllerBehavior
* View helper to render the form fields belonging to the
* secondary tabs section.
*
* <?= $this->formRenderPrimaryTabs() ?>
* <?= $this->formRenderSecondaryTabs() ?>
*
* @return string HTML markup
* @throws \October\Rain\Exception\ApplicationException if the Form Widget isn't set

View File

@ -11,10 +11,11 @@ use Backend\Behaviors\ImportExportController\TranscodeFilter;
use Illuminate\Database\Eloquent\MassAssignmentException;
use League\Csv\Reader as CsvReader;
use League\Csv\Writer as CsvWriter;
use October\Rain\Parse\League\EscapeFormula as CsvEscapeFormula;
use League\Csv\EscapeFormula as CsvEscapeFormula;
use ApplicationException;
use SplTempFileObject;
use Exception;
use League\Csv\Statement;
/**
* Adds features for importing and exporting data.
@ -250,10 +251,13 @@ class ImportExportController extends ControllerBehavior
$reader = $this->createCsvReader($path);
if (post('first_row_titles')) {
$reader->setOffset(1);
$reader->setHeaderOffset(1);
}
$result = $reader->setLimit(50)->fetchColumn((int) $columnId);
$result = (new Statement())
->limit(50)
->process($reader)
->fetchColumn((int) $columnId);
$data = iterator_to_array($result, false);
/*
@ -624,9 +628,7 @@ class ImportExportController extends ControllerBehavior
$csv->setDelimiter($options['delimiter']);
$csv->setEnclosure($options['enclosure']);
$csv->setEscape($options['escape']);
// Temporary until upgrading to league/csv >= 9.1.0 (will be $csv->addFormatter($formatter))
$formatter = new CsvEscapeFormula();
$csv->addFormatter(new CsvEscapeFormula());
/*
* Add headers
@ -662,9 +664,6 @@ class ImportExportController extends ControllerBehavior
$record[] = $value;
}
// Temporary until upgrading to league/csv >= 9.1.0
$record = $formatter($record);
$csv->insertOne($record);
}
@ -808,9 +807,9 @@ class ImportExportController extends ControllerBehavior
if (
$options['encoding'] !== null &&
$reader->isActiveStreamFilter()
$reader->supportsStreamFilter()
) {
$reader->appendStreamFilter(sprintf(
$reader->addStreamFilter(sprintf(
'%s%s:%s',
TranscodeFilter::FILTER_NAME,
strtolower($options['encoding']),

View File

@ -145,6 +145,7 @@ class ListController extends ControllerBehavior
'recordUrl',
'recordOnClick',
'recordsPerPage',
'perPageOptions',
'showPageNumbers',
'noRecordsMessage',
'defaultSort',
@ -297,16 +298,6 @@ class ListController extends ControllerBehavior
return call_user_func_array([$this->controller, 'onDelete'], func_get_args());
}
/*
* Validate checked identifiers
*/
$checkedIds = post('checked');
if (!$checkedIds || !is_array($checkedIds) || !count($checkedIds)) {
Flash::error(Lang::get('backend::lang.list.delete_selected_empty'));
return $this->controller->listRefresh();
}
/*
* Establish the list definition
*/
@ -318,6 +309,20 @@ class ListController extends ControllerBehavior
$listConfig = $this->controller->listGetConfig($definition);
/*
* Validate checked identifiers
*/
$checkedIds = post('checked');
if (!$checkedIds || !is_array($checkedIds) || !count($checkedIds)) {
Flash::error(Lang::get(
(!empty($listConfig->noRecordsDeletedMessage))
? $listConfig->noRecordsDeletedMessage
: 'backend::lang.list.delete_selected_empty'
));
return $this->controller->listRefresh();
}
/*
* Create the model
*/
@ -344,10 +349,18 @@ class ListController extends ControllerBehavior
$record->delete();
}
Flash::success(Lang::get('backend::lang.list.delete_selected_success'));
Flash::success(Lang::get(
(!empty($listConfig->deleteMessage))
? $listConfig->deleteMessage
: 'backend::lang.list.delete_selected_success'
));
}
else {
Flash::error(Lang::get('backend::lang.list.delete_selected_empty'));
Flash::error(Lang::get(
(!empty($listConfig->noRecordsDeletedMessage))
? $listConfig->noRecordsDeletedMessage
: 'backend::lang.list.delete_selected_empty'
));
}
return $this->controller->listRefresh($definition);

View File

@ -669,8 +669,9 @@ class RelationController extends ControllerBehavior
$config->defaultSort = $this->getConfig('view[defaultSort]');
$config->recordsPerPage = $this->getConfig('view[recordsPerPage]');
$config->showCheckboxes = $this->getConfig('view[showCheckboxes]', !$this->readOnly);
$config->recordUrl = $this->getConfig('view[recordUrl]', null);
$config->customViewPath = $this->getConfig('view[customViewPath]', null);
$config->recordUrl = $this->getConfig('view[recordUrl]');
$config->customViewPath = $this->getConfig('view[customViewPath]');
$config->noRecordsMessage = $this->getConfig('view[noRecordsMessage]');
$defaultOnClick = sprintf(
"$.oc.relationBehavior.clickViewListRecord(':%s', '%s', '%s')",
@ -818,6 +819,7 @@ class RelationController extends ControllerBehavior
$config->showSorting = $this->getConfig('manage[showSorting]', !$isPivot);
$config->defaultSort = $this->getConfig('manage[defaultSort]');
$config->recordsPerPage = $this->getConfig('manage[recordsPerPage]');
$config->noRecordsMessage = $this->getConfig('manage[noRecordsMessage]');
if ($this->viewMode == 'single') {
$config->showCheckboxes = false;
@ -1113,7 +1115,7 @@ class RelationController extends ControllerBehavior
$this->relationObject->add($newModel, $sessionKey);
}
elseif ($this->viewMode == 'single') {
$newModel = $this->manageWidget->model;
$newModel = $this->viewModel = $this->viewWidget->model = $this->manageWidget->model;
$this->viewWidget->setFormValues($saveData);
/*
@ -1123,6 +1125,15 @@ class RelationController extends ControllerBehavior
$newModel->save(null, $this->manageWidget->getSessionKey());
}
if ($this->relationType === 'hasOne') {
// Unassign previous relation if one is already assigned
$relation = $this->relationObject->getParent()->{$this->relationName} ?? null;
if ($relation) {
$this->relationObject->remove($relation, $sessionKey);
}
}
$this->relationObject->add($newModel, $sessionKey);
/*
@ -1157,10 +1168,9 @@ class RelationController extends ControllerBehavior
}
}
elseif ($this->viewMode == 'single') {
$this->viewModel = $this->manageWidget->model;
$this->manageWidget->setFormValues($saveData);
$this->manageWidget->model->save(null, $this->manageWidget->getSessionKey());
$this->viewWidget->setFormValues($saveData);
$this->viewModel->save(null, $this->manageWidget->getSessionKey());
}
return $this->relationRefresh();
@ -1241,6 +1251,15 @@ class RelationController extends ControllerBehavior
*/
elseif ($this->viewMode == 'single') {
if ($recordId && ($model = $this->relationModel->find($recordId))) {
if ($this->relationType === 'hasOne') {
// Unassign previous relation if one is already assigned
$relation = $this->relationObject->getParent()->{$this->relationName} ?? null;
if ($relation) {
$this->relationObject->remove($relation, $sessionKey);
}
}
$this->relationObject->add($model, $sessionKey);
$this->viewWidget->setFormValues($model->attributes);
@ -1309,7 +1328,11 @@ class RelationController extends ControllerBehavior
}
}
// Reinitialise the form with a blank model
$this->initRelation($this->model);
$this->viewWidget->setFormValues([]);
$this->viewModel = $this->relationModel;
}
return $this->relationRefresh();

View File

@ -214,7 +214,10 @@ class ReorderController extends ControllerBehavior
$model = $this->controller->reorderGetModel();
$modelTraits = class_uses($model);
if (isset($modelTraits[\October\Rain\Database\Traits\Sortable::class])) {
if (
isset($modelTraits[\October\Rain\Database\Traits\Sortable::class]) ||
$model->isClassExtendedWith(\October\Rain\Database\Behaviors\Sortable::class)
) {
$this->sortMode = 'simple';
}
elseif (isset($modelTraits[\October\Rain\Database\Traits\NestedTree::class])) {
@ -222,7 +225,7 @@ class ReorderController extends ControllerBehavior
$this->showTree = true;
}
else {
throw new ApplicationException('The model must implement the NestedTree or Sortable traits.');
throw new ApplicationException('The model must implement the Sortable trait/behavior or the NestedTree trait.');
}
return $model;

View File

@ -111,6 +111,14 @@ class BackendController extends ControllerBase
self::extendableExtendCallback($callback);
}
/**
* @inheritDoc
*/
public function callAction($method, $parameters)
{
return parent::callAction($method, array_values($parameters));
}
/**
* Pass unhandled URLs to the CMS Controller, if it exists
*
@ -210,7 +218,7 @@ class BackendController extends ControllerBase
* Look for a Plugin controller
*/
if (count($params) >= 2) {
list($author, $plugin) = $params;
[$author, $plugin] = $params;
$pluginCode = ucfirst($author) . '.' . ucfirst($plugin);
if (PluginManager::instance()->isDisabled($pluginCode)) {

View File

@ -617,7 +617,7 @@ class Controller extends ControllerBase
$pageHandler = $this->action . '_' . $handler;
if ($this->methodExists($pageHandler)) {
$result = call_user_func_array([$this, $pageHandler], $this->params);
$result = call_user_func_array([$this, $pageHandler], array_values($this->params));
return $result ?: true;
}
@ -625,7 +625,7 @@ class Controller extends ControllerBase
* Process page global handler (onSomething)
*/
if ($this->methodExists($handler)) {
$result = call_user_func_array([$this, $handler], $this->params);
$result = call_user_func_array([$this, $handler], array_values($this->params));
return $result ?: true;
}
@ -662,7 +662,7 @@ class Controller extends ControllerBase
{
$this->addViewPath($widget->getViewPaths());
$result = call_user_func_array([$widget, $handler], $this->params);
$result = call_user_func_array([$widget, $handler], array_values($this->params));
$this->vars = $widget->vars + $this->vars;

View File

@ -124,7 +124,7 @@ class FormField
/**
* @var string Specifies a comment to accompany the field
*/
public $comment;
public $comment = '';
/**
* @var string Specifies the comment position.
@ -139,7 +139,7 @@ class FormField
/**
* @var string Specifies a message to display when there is no value supplied (placeholder).
*/
public $placeholder;
public $placeholder = '';
/**
* @var array Contains a list of attributes specified in the field configuration.

View File

@ -28,6 +28,11 @@ class NavigationManager
*/
protected $items;
/**
* @var QuickActionItem[] List of registered quick actions.
*/
protected $quickActions;
protected $contextSidenavPartials = [];
protected $contextOwner;
@ -54,6 +59,9 @@ class NavigationManager
*/
protected function loadItems()
{
$this->items = [];
$this->quickActions = [];
/*
* Load module items
*/
@ -68,12 +76,19 @@ class NavigationManager
foreach ($plugins as $id => $plugin) {
$items = $plugin->registerNavigation();
if (!is_array($items)) {
$quickActions = $plugin->registerQuickActions();
if (!is_array($items) && !is_array($quickActions)) {
continue;
}
if (is_array($items)) {
$this->registerMenuItems($id, $items);
}
if (is_array($quickActions)) {
$this->registerQuickActions($id, $quickActions);
}
}
/**
* @event backend.menu.extendItems
@ -91,17 +106,21 @@ class NavigationManager
Event::fire('backend.menu.extendItems', [$this]);
/*
* Sort menu items
* Sort menu items and quick actions
*/
uasort($this->items, static function ($a, $b) {
return $a->order - $b->order;
});
uasort($this->quickActions, static function ($a, $b) {
return $a->order - $b->order;
});
/*
* Filter items user lacks permission for
* Filter items and quick actions that the user lacks permission for
*/
$user = BackendAuth::getUser();
$this->items = $this->filterItemPermissions($user, $this->items);
$this->quickActions = $this->filterItemPermissions($user, $this->quickActions);
foreach ($this->items as $item) {
if (!$item->sideMenu || !count($item->sideMenu)) {
@ -183,10 +202,6 @@ class NavigationManager
*/
public function registerMenuItems($owner, array $definitions)
{
if (!$this->items) {
$this->items = [];
}
$validator = Validator::make($definitions, [
'*.label' => 'required',
'*.icon' => 'required_without:*.iconSvg',
@ -320,6 +335,21 @@ class NavigationManager
return true;
}
/**
* Remove multiple side menu items
*
* @param string $owner
* @param string $code
* @param array $sideCodes
* @return void
*/
public function removeSideMenuItems($owner, $code, $sideCodes)
{
foreach ($sideCodes as $sideCode) {
$this->removeSideMenuItem($owner, $code, $sideCode);
}
}
/**
* Removes a single main menu item
* @param string $owner
@ -346,10 +376,14 @@ class NavigationManager
*/
public function listMainMenuItems()
{
if ($this->items === null) {
if ($this->items === null && $this->quickActions === null) {
$this->loadItems();
}
if ($this->items === null) {
return [];
}
foreach ($this->items as $item) {
if ($item->badge) {
$item->counter = (string) $item->badge;
@ -429,6 +463,137 @@ class NavigationManager
return $items;
}
/**
* Registers quick actions in the main navigation.
*
* Quick actions are single purpose links displayed to the left of the user menu in the
* backend main navigation.
*
* The argument is an array of the quick action items. The array keys represent the
* quick action item codes, specific for the plugin/module. Each element in the
* array should be an associative array with the following keys:
* - label - specifies the action label localization string key, used as a tooltip, required.
* - icon - an icon name from the Font Awesome icon collection, required if iconSvg is unspecified.
* - iconSvg - a custom SVG icon to use for the icon, required if icon is unspecified.
* - url - the back-end relative URL the quick action item should point to, required.
* - permissions - an array of permissions the back-end user should have, optional.
* The item will be displayed if the user has any of the specified permissions.
* - order - a position of the item in the menu, optional.
*
* @param string $owner Specifies the quick action items owner plugin or module in the format Author.Plugin.
* @param array $definitions An array of the quick action item definitions.
* @return void
* @throws SystemException If the validation of the quick action configuration fails
*/
public function registerQuickActions($owner, array $definitions)
{
$validator = Validator::make($definitions, [
'*.label' => 'required',
'*.icon' => 'required_without:*.iconSvg',
'*.url' => 'required'
]);
if ($validator->fails()) {
$errorMessage = 'Invalid quick action item detected in ' . $owner . '. Contact the plugin author to fix (' . $validator->errors()->first() . ')';
if (Config::get('app.debug', false)) {
throw new SystemException($errorMessage);
}
Log::error($errorMessage);
}
$this->addQuickActionItems($owner, $definitions);
}
/**
* Dynamically add an array of quick action items
*
* @param string $owner
* @param array $definitions
* @return void
*/
public function addQuickActionItems($owner, array $definitions)
{
foreach ($definitions as $code => $definition) {
$this->addQuickActionItem($owner, $code, $definition);
}
}
/**
* Dynamically add a single quick action item
*
* @param string $owner
* @param string $code
* @param array $definition
* @return void
*/
public function addQuickActionItem($owner, $code, array $definition)
{
$itemKey = $this->makeItemKey($owner, $code);
if (isset($this->quickActions[$itemKey])) {
$definition = array_merge((array) $this->quickActions[$itemKey], $definition);
}
$item = array_merge($definition, [
'code' => $code,
'owner' => $owner
]);
$this->quickActions[$itemKey] = QuickActionItem::createFromArray($item);
}
/**
* Gets the instance of a specified quick action item.
*
* @param string $owner
* @param string $code
* @return QuickActionItem
* @throws SystemException
*/
public function getQuickActionItem(string $owner, string $code)
{
$itemKey = $this->makeItemKey($owner, $code);
if (!array_key_exists($itemKey, $this->quickActions)) {
throw new SystemException('No quick action item found with key ' . $itemKey);
}
return $this->quickActions[$itemKey];
}
/**
* Removes a single quick action item
*
* @param $owner
* @param $code
* @return void
*/
public function removeQuickActionItem($owner, $code)
{
$itemKey = $this->makeItemKey($owner, $code);
unset($this->quickActions[$itemKey]);
}
/**
* Returns a list of quick action items.
*
* @return array
* @throws SystemException
*/
public function listQuickActionItems()
{
if ($this->items === null && $this->quickActions === null) {
$this->loadItems();
}
if ($this->quickActions === null) {
return [];
}
return $this->quickActions;
}
/**
* Sets the navigation context.
* The function sets the navigation owner, main menu item code and the side menu item code.

View File

@ -8,23 +8,18 @@
"authors": [
{
"name": "Alexey Bobkov",
"email": "aleksey.bobkov@gmail.com"
"email": "aleksey.bobkov@gmail.com",
"role": "Co-founder"
},
{
"name": "Samuel Georges",
"email": "daftspunky@gmail.com"
},
{
"name": "Luke Towers",
"email": "octobercms@luketowers.ca",
"homepage": "https://luketowers.ca",
"role": "Maintainer"
"email": "daftspunky@gmail.com",
"role": "Co-founder"
}
],
"require": {
"php": ">=7.0",
"composer/installers": "~1.0",
"october/rain": "~1.0.469"
"php": ">=7.2",
"composer/installers": "~1.0"
},
"autoload": {
"psr-4": {

View File

@ -13,6 +13,7 @@ use ApplicationException;
use ValidationException;
use Exception;
use Config;
use October\Rain\Foundation\Http\Middleware\CheckForTrustedHost;
/**
* Authentication controller
@ -147,6 +148,20 @@ class Auth extends Controller
*/
public function restore_onSubmit()
{
// Force Trusted Host verification on password reset link generation
// regardless of config to protect against host header poisoning
$trustedHosts = Config::get('app.trustedHosts', false);
if ($trustedHosts === false) {
$hosts = CheckForTrustedHost::processTrustedHosts(true);
if (count($hosts)) {
Request::setTrustedHosts($hosts);
// Trigger the host validation logic
Request::getHost();
}
}
$rules = [
'login' => 'required|between:2,255'
];
@ -158,10 +173,16 @@ class Auth extends Controller
$user = BackendAuth::findUserByLogin(post('login'));
if (!$user) {
if (Config::get('app.debug', false)) {
throw new ValidationException([
'login' => trans('backend::lang.account.restore_error', ['login' => post('login')])
]);
}
else {
Flash::success(trans('backend::lang.account.restore_success'));
return Backend::redirect('backend/auth/signin');
}
}
Flash::success(trans('backend::lang.account.restore_success'));

View File

@ -57,7 +57,7 @@ class Preferences extends Controller
*/
public function formExtendFields($form)
{
if (!$this->user->hasAccess('backend.manage_editor')) {
if (!$this->user->hasAccess('backend.manage_own_editor')) {
$form->removeTab('backend::lang.backend_preferences.code_editor');
}
}

View File

@ -1,19 +1,32 @@
<?php namespace Backend\Database\Seeds;
use Str;
use Seeder;
use Eloquent;
use Backend\Database\Seeds\SeedSetupAdmin;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
* @return string
*/
public function run()
{
Eloquent::unguard();
$shouldRandomizePassword = SeedSetupAdmin::$password === 'admin';
$adminPassword = $shouldRandomizePassword ? Str::random(22) : SeedSetupAdmin::$password;
$this->call('Backend\Database\Seeds\SeedSetupAdmin');
Eloquent::unguarded(function () use ($adminPassword) {
// Generate a random password for the seeded admin account
$adminSeeder = new \Backend\Database\Seeds\SeedSetupAdmin;
$adminSeeder->setDefaults([
'password' => $adminPassword
]);
$this->call($adminSeeder);
});
return $shouldRandomizePassword ? 'The following password has been automatically generated for the "admin" account: '
. "<fg=yellow;options=bold>${adminPassword}</>" : '';
}
}

View File

@ -2,12 +2,24 @@
use October\Rain\Support\Facade;
/**
* @method static string uri()
* @method static string url(string $path = null, array $parameters = [], bool $secure = null)
* @method static string baseUrl(string $path = null)
* @method static string skinAsset(string $path = null)
* @method static \Illuminate\Http\RedirectResponse redirect(string $path, int $status = 302, array $headers = [], bool $secure = null)
* @method static \Illuminate\Http\RedirectResponse redirectGuest(string $path, int $status = 302, array $headers = [], bool $secure = null)
* @method static \Illuminate\Http\RedirectResponse redirectIntended(string $path, int $status = 302, array $headers = [], bool $secure = null)
* @method static string date($dateTime, array $options = [])
* @method static string dateTime($dateTime, array $options = [])
*
* @see \Backend\Helpers\Backend
*/
class Backend extends Facade
{
/**
* Get the registered name of the component.
*
* @see \Backend\Helpers\Backend
* @return string
*/
protected static function getFacadeAccessor()

View File

@ -2,14 +2,22 @@
use October\Rain\Support\Facade;
/**
* @method static void registerCallback(callable $callback)
* @method static void registerPermissions(string $owner, array $definitions)
* @method static void removePermission(string $owner, string $code)
* @method static array listPermissions()
* @method static array listTabbedPermissions()
* @method static array listPermissionsForRole(string $role, bool $includeOrphans = true)
* @method static boolean hasPermissionsForRole(string $role)
*
* @see \Backend\Classes\AuthManager
*/
class BackendAuth extends Facade
{
/**
* Get the registered name of the component.
*
* Resolves to:
* - Backend\Classes\AuthManager
*
* @return string
*/
protected static function getFacadeAccessor()

View File

@ -2,14 +2,36 @@
use October\Rain\Support\Facade;
/**
* @method static void registerCallback(callable $callback)
* @method static void registerMenuItems(string $owner, array $definitions)
* @method static void addMainMenuItems(string $owner, array $definitions)
* @method static void addMainMenuItem(string $owner, $code, array $definition)
* @method static \Backend\Classes\MainMenuItem getMainMenuItem(string $owner, string $code)
* @method static void removeMainMenuItem(string $owner, string $code)
* @method static void addSideMenuItems(string $owner, string $code, array $definitions)
* @method static bool addSideMenuItem(string $owner, string $code, string $sideCode, array $definition)
* @method static bool removeSideMenuItem(string $owner, string $code, string $sideCode)
* @method static \Backend\Classes\MainMenuItem[] listMainMenuItems()
* @method static \Backend\Classes\SideMenuItem[] listSideMenuItems(string|null $owner = null, string|null $code = null)
* @method static void setContext(string $owner, string $mainMenuItemCode, string|null $sideMenuItemCode = null)
* @method static void setContextOwner(string $owner)
* @method static void setContextMainMenu(string $mainMenuItemCode)
* @method static object getContext()
* @method static void setContextSideMenu(string $sideMenuItemCode)
* @method static bool isMainMenuItemActive(\Backend\Classes\MainMenuItem $item)
* @method static \Backend\Classes\MainMenuItem|null getActiveMainMenuItem()
* @method static bool isSideMenuItemActive(\Backend\Classes\SideMenuItem $item)
* @method static void registerContextSidenavPartial(string $owner, string $mainMenuItemCode, string $partial)
* @method static mixed getContextSidenavPartial(string $owner, string $mainMenuItemCode)
*
* @see \Backend\Classes\NavigationManager
*/
class BackendMenu extends Facade
{
/**
* Get the registered name of the component.
*
* Resolves to:
* - Backend\Classes\NavigationManager
*
* @return string
*/
protected static function getFacadeAccessor()

View File

@ -64,6 +64,11 @@ class FileUpload extends FormWidgetBase
*/
public $maxFilesize;
/**
* @var integer|null Max files number.
*/
public $maxFiles;
/**
* @var array Options used for generating thumbnails.
*/
@ -109,6 +114,7 @@ class FileUpload extends FormWidgetBase
'imageHeight',
'fileTypes',
'maxFilesize',
'maxFiles',
'mimeTypes',
'thumbOptions',
'useCaption',
@ -152,13 +158,14 @@ class FileUpload extends FormWidgetBase
$this->vars['singleFile'] = $fileList->first();
$this->vars['displayMode'] = $this->getDisplayMode();
$this->vars['emptyIcon'] = $this->getConfig('emptyIcon', 'icon-upload');
$this->vars['imageHeight'] = $this->imageHeight;
$this->vars['imageWidth'] = $this->imageWidth;
$this->vars['imageHeight'] = (is_int($this->imageHeight)) ? $this->imageHeight : null;
$this->vars['imageWidth'] = (is_int($this->imageWidth)) ? $this->imageWidth : null;
$this->vars['acceptedFileTypes'] = $this->getAcceptedFileTypes(true);
$this->vars['maxFilesize'] = $this->maxFilesize;
$this->vars['maxFilesize'] = (is_int($this->maxFilesize)) ? $this->maxFilesize : null;
$this->vars['cssDimensions'] = $this->getCssDimensions();
$this->vars['cssBlockDimensions'] = $this->getCssDimensions('block');
$this->vars['useCaption'] = $this->useCaption;
$this->vars['maxFiles'] = (is_int($this->maxFiles)) ? $this->maxFiles : null;
$this->vars['prompt'] = $this->getPromptText();
}

View File

@ -248,16 +248,6 @@ class Repeater extends FormWidgetBase
}
}
if (!$this->childAddItemCalled && $currentValue === null) {
$this->formWidgets = [];
return;
}
if ($this->childAddItemCalled && !isset($currentValue[$this->childIndexCalled])) {
// If no value is available but a child repeater has added an item, add a "stub" repeater item
$this->makeItemFormWidget($this->childIndexCalled);
}
// Ensure that the minimum number of items are preinitialized
// ONLY DONE WHEN NOT IN GROUP MODE
if (!$this->useGroups && $this->minItems > 0) {
@ -273,6 +263,16 @@ class Repeater extends FormWidgetBase
}
}
if (!$this->childAddItemCalled && $currentValue === null) {
$this->formWidgets = [];
return;
}
if ($this->childAddItemCalled && !isset($currentValue[$this->childIndexCalled])) {
// If no value is available but a child repeater has added an item, add a "stub" repeater item
$this->makeItemFormWidget($this->childIndexCalled);
}
if (!is_array($currentValue)) {
return;
}

View File

@ -186,6 +186,19 @@ class RichEditor extends FormWidgetBase
{
$result = [];
/**
* @event backend.richeditor.listTypes
* Register additional "page link types" to the RichEditor FormWidget
*
* Example usage:
*
* Event::listen('backend.richeditor.listTypes', function () {
* return [
* 'my-identifier' => 'author.plugin::lang.richeditor.link_types.my_identifier',
* ];
* });
*
*/
$apiResult = Event::fire('backend.richeditor.listTypes');
if (is_array($apiResult)) {
foreach ($apiResult as $typeList) {
@ -205,6 +218,28 @@ class RichEditor extends FormWidgetBase
protected function getPageLinks($type)
{
$result = [];
/**
* @event backend.richeditor.getTypeInfo
* Register additional "page link types" to the RichEditor FormWidget
*
* Example usage:
*
* Event::listen('backend.richeditor.getTypeInfo', function ($type) {
* if ($type === 'my-identifier') {
* return [
* 'https://example.com/page1' => 'Page 1',
* 'https://example.com/parent-page' => [
* 'title' => 'Parent Page',
* 'links' => [
* 'https://example.com/child-page' => 'Child Page',
* ],
* ],
* ];
* }
* });
*
*/
$apiResult = Event::fire('backend.richeditor.getTypeInfo', [$type]);
if (is_array($apiResult)) {
foreach ($apiResult as $typeInfo) {

0
modules/backend/formwidgets/codeeditor/assets/vendor/ace/ace.js vendored Normal file → Executable file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

@ -100,12 +100,19 @@
paramName: this.options.paramName,
clickable: this.$uploadButton.get(0),
previewsContainer: this.$filesContainer.get(0),
maxFiles: !this.options.isMulti ? 1 : null,
maxFilesize: this.options.maxFilesize,
timeout: 0,
headers: {}
}
if (!this.options.isMulti) {
this.uploaderOptions.maxFiles = 1
} else if (this.options.maxFiles) {
this.uploaderOptions.maxFiles = this.options.maxFiles
} else {
this.uploaderOptions.maxFiles = null
}
if (this.options.fileTypes) {
this.uploaderOptions.acceptedFiles = this.options.fileTypes
}
@ -131,10 +138,40 @@
}
this.dropzone = new Dropzone(this.$el.get(0), this.uploaderOptions)
this.dropzone.on('addedfile', this.proxy(this.onUploadAddedFile))
this.dropzone.on('sending', this.proxy(this.onUploadSending))
this.dropzone.on('success', this.proxy(this.onUploadSuccess))
this.dropzone.on('error', this.proxy(this.onUploadError))
this.dropzone.on('maxfilesreached', this.proxy(this.removeEventListeners))
this.dropzone.on('removedfile', this.proxy(this.setupEventListeners))
this.loadAlreadyUploadedFiles()
}
FileUpload.prototype.removeEventListeners = function () {
this.dropzone.removeEventListeners()
}
FileUpload.prototype.setupEventListeners = function () {
if (this.dropzone.files.length < this.dropzone.options.maxFiles) {
this.dropzone.setupEventListeners()
}
}
FileUpload.prototype.loadAlreadyUploadedFiles = function () {
var self = this
this.$el.find('.server-file').each(function () {
var file = $(this).data()
self.dropzone.files.push(file)
self.dropzone.emit('addedfile', file)
self.dropzone.emit('success', file, file)
$(this).remove()
})
self.dropzone._updateMaxFilesReachedClass()
}
FileUpload.prototype.onResizeFileInfo = function (file) {
@ -142,7 +179,7 @@
targetWidth,
targetHeight
if (!this.options.thumbnailWidth && !this.options.thumbnailWidth) {
if (!this.options.thumbnailWidth && !this.options.thumbnailHeight) {
targetWidth = targetHeight = 100
}
else if (this.options.thumbnailWidth) {
@ -278,7 +315,6 @@
FileUpload.prototype.onSortAttachments = function () {
if (this.options.sortHandler) {
/*
* Build an object of ID:ORDER
*/

View File

@ -9,6 +9,7 @@
data-max-filesize="<?= $maxFilesize ?>"
<?php if ($useCaption): ?>data-config-handler="<?= $this->getEventHandler('onLoadAttachmentConfig') ?>"<?php endif ?>
<?php if ($acceptedFileTypes): ?>data-file-types="<?= $acceptedFileTypes ?>"<?php endif ?>
<?php if ($maxFiles): ?>data-max-files="<?= $maxFiles ?>"<?php endif ?>
<?= $this->formField->getAttributes() ?>
>
@ -20,27 +21,14 @@
<!-- Existing files -->
<div class="upload-files-container">
<?php foreach ($fileList as $file): ?>
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->pathUrl ?>">
<div class="icon-container">
<i class="icon-file"></i>
</div>
<div class="info">
<h4 class="filename">
<span data-dz-name><?= e($file->title ?: $file->file_name) ?></span>
<a
href="javascript:;"
class="upload-remove-button"
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
data-request-data="file_id: <?= $file->id ?>"
><i class="icon-times"></i></a>
</h4>
<p class="size"><?= e($file->sizeToString()) ?></p>
</div>
<div class="meta">
<a href="javascript:;" class="drag-handle"><i class="icon-bars"></i></a>
</div>
</div>
<div class="server-file"
data-id="<?= $file->id ?>"
data-path="<?= $file->pathUrl ?>"
data-thumb="<?= $file->thumbUrl ?>"
data-name="<?= e($file->title ?: $file->file_name) ?>"
data-size="<?= e($file->file_size) ?>"
data-accepted="true"
></div>
<?php endforeach ?>
</div>
</div>

View File

@ -9,6 +9,7 @@
data-max-filesize="<?= $maxFilesize ?>"
<?php if ($useCaption): ?>data-config-handler="<?= $this->getEventHandler('onLoadAttachmentConfig') ?>"<?php endif ?>
<?php if ($acceptedFileTypes): ?>data-file-types="<?= $acceptedFileTypes ?>"<?php endif ?>
<?php if ($maxFiles): ?>data-max-files="<?= $maxFiles ?>"<?php endif ?>
<?= $this->formField->getAttributes() ?>
>
@ -20,27 +21,14 @@
<!-- Existing files -->
<div class="upload-files-container">
<?php foreach ($fileList as $file): ?>
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->pathUrl ?>">
<div class="icon-container image">
<img src="<?= $file->thumbUrl ?>" alt="" />
</div>
<div class="info">
<h4 class="filename">
<span data-dz-name><?= e($file->title ?: $file->file_name) ?></span>
<a
href="javascript:;"
class="upload-remove-button"
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
data-request-data="file_id: <?= $file->id ?>"
><i class="icon-times"></i></a>
</h4>
<p class="size"><?= e($file->sizeToString()) ?></p>
</div>
<div class="meta">
<a href="javascript:;" class="drag-handle"><i class="icon-bars"></i></a>
</div>
</div>
<div class="server-file"
data-id="<?= $file->id ?>"
data-path="<?= $file->pathUrl ?>"
data-thumb="<?= $file->thumbUrl ?>"
data-name="<?= e($file->title ?: $file->file_name) ?>"
data-size="<?= e($file->file_size) ?>"
data-accepted="true"
></div>
<?php endforeach ?>
</div>
</div>

View File

0
modules/backend/formwidgets/richeditor/assets/js/build-min.js vendored Normal file → Executable file
View File

View File

@ -64,9 +64,10 @@ setTimeout(function(){editor.popups.show('link.insert')
setLinkValue(link)},300)}
function setLinkValue(link){var $popup=editor.popups.get('link.insert');var text_inputs=$popup.find('input.fr-link-attr[type="text"]');var check_inputs=$popup.find('input.fr-link-attr[type="checkbox"]');var $input;var i;for(i=0;i<text_inputs.length;i++){$input=$(text_inputs[i]);if(link[$input.attr('name')]){$input.val(link[$input.attr('name')]);}
else if($input.attr('name')!='text'){$input.val('');}}
for(i=0;i<check_inputs.length;i++){$input=$(check_inputs[i]);$input.prop('checked',$input.data('checked')==link[$input.attr('name')]);}}
for(i=0;i<check_inputs.length;i++){$input=$(check_inputs[i]);$input.prop('checked',$input.data('checked')==link[$input.attr('name')]);}
editor.selection.restore();}
function insertLink(){richeditorPageLinksPlugin=this
editor.$el.popup({handler:editor.opts.pageLinksHandler})}
editor.$el.popup({handler:editor.opts.pageLinksHandler}).one('shown.oc.popup.pageLinks',function(){editor.selection.save()})}
function _init(){}
return{_init:_init,setLinkValueFromPopup:setLinkValueFromPopup,setLinkValue:setLinkValue,insertLink:insertLink}}
$.FE.DEFAULTS.linkInsertButtons=['linkBack','|','linkPageLinks']

View File

@ -54,6 +54,9 @@ $.FroalaEditor.DEFAULTS.key = 'JA6B2B5A1qB1F1F4D3I1A15A11D3E6B5dVh1VCQWa1EOQFe1N
$input = $(check_inputs[i]);
$input.prop('checked', $input.data('checked') == link[$input.attr('name')]);
}
// Restore selection, so that the link gets inserted properly.
editor.selection.restore();
}
function insertLink() {
@ -61,6 +64,9 @@ $.FroalaEditor.DEFAULTS.key = 'JA6B2B5A1qB1F1F4D3I1A15A11D3E6B5dVh1VCQWa1EOQFe1N
editor.$el.popup({
handler: editor.opts.pageLinksHandler
}).one('shown.oc.popup.pageLinks', function () {
// Save the current selection so it can be restored after popup is closed.
editor.selection.save()
})
}

View File

View File

View File

@ -55,7 +55,7 @@ $.FE.LANGUAGE['sk'] = {
"Remove": "Odstr\u00e1ni\u0165",
"More": "Viac",
"Update": "Aktualizova\u0165",
"Style": "\u0165t\u00fdl",
"Style": "\u0160t\u00fdl",
// Font
"Font Family": "Typ p\u00edsma",
@ -77,7 +77,7 @@ $.FE.LANGUAGE['sk'] = {
"Heading 4": "Nadpis 4",
// Style
"Paragraph Style": "\u0165t\u00fdl odstavca",
"Paragraph Style": "\u0160t\u00fdl odstavca",
"Inline Style": "Inline \u0161t\u00fdl",
// Alignment
@ -157,7 +157,7 @@ $.FE.LANGUAGE['sk'] = {
"Insert Table": "Vlo\u017ei\u0165 tabu\u013eku",
"Table Header": "Hlavi\u010dka tabu\u013eky",
"Remove Table": "Odstrani\u0165 tabu\u013eku",
"Table Style": "\u0165t\u00fdl tabu\u013eky",
"Table Style": "\u0160t\u00fdl tabu\u013eky",
"Horizontal Align": "Horizont\u00e1lne zarovnanie",
"Row": "Riadok",
"Insert row above": "Vlo\u017ei\u0165 riadok nad",
@ -179,9 +179,11 @@ $.FE.LANGUAGE['sk'] = {
"Align Top": "Zarovnat na vrch",
"Align Middle": "Zarovnat na stred",
"Align Bottom": "Zarovnat na spodok",
"Cell Style": "\u0165t\u00fdl bunky",
"Cell Style": "\u0160t\u00fdl bunky",
// Files
"Insert Audio": "Vlo\u017Ei\u0165 zvuk",
"Insert File": "Vlo\u017Ei\u0165 s\u00FAbor",
"Upload File": "Nahra\u0165 s\u00fabor",
"Drop file": "Vlo\u017ete s\u00fabor sem",

View File

View File

@ -1,18 +1,32 @@
<?php
$selectedValues = is_array($selectedValues) ? $selectedValues : [];
$availableOptions = $useKey ? $fieldOptions : array_unique(array_merge($selectedValues, $fieldOptions));
$displayOnlyOptions = [];
foreach ($availableOptions as $key => $option) {
if (!strlen($option)) {
continue;
}
if (($useKey && in_array($key, $selectedValues)) || (!$useKey && in_array($option, $selectedValues))) {
$displayOnlyOptions[] = $option;
}
}
?>
<!-- Tag List -->
<?php if ($this->previewMode || $field->readOnly || $field->disabled): ?>
<ul class="form-control taglist--preview" <?= $field->readOnly || $field->disabled ? 'disabled="disabled"' : ''; ?>>
<?php foreach ($availableOptions as $key => $option): ?>
<?php if (!strlen($option)) continue ?>
<?php if (($useKey && in_array($key, $selectedValues)) || (!$useKey && in_array($option, $selectedValues))): ?>
<?php foreach ($displayOnlyOptions as $option): ?>
<li class="taglist__item"><?= e(trans($option)) ?></li>
<?php endif ?>
<?php endforeach ?>
</ul>
<?php if ($field->readOnly): ?>
<?php if (is_array($field->value)): ?>
<?php foreach ($displayOnlyOptions as $option): ?>
<input
type="hidden"
name="<?= $field->getName() ?>[]"
value="<?= $option ?>">
<?php endforeach ?>
<?php else: ?>
<input
type="hidden"
name="<?= $field->getName() ?>"

View File

@ -10,6 +10,7 @@ use October\Rain\Router\Helper as RouterHelper;
use System\Helpers\DateTime as DateTimeHelper;
use Backend\Classes\Skin;
use Backend\Helpers\Exception\DecompileException;
use Exception;
/**
* Backend Helper
@ -85,6 +86,26 @@ class Backend
return Redirect::intended($this->uri() . '/' . $path, $status, $headers, $secure);
}
/**
* makeCarbon converts mixed inputs to a Carbon object and sets the backend timezone
* @return \Carbon\Carbon
*/
public static function makeCarbon($value, $throwException = true)
{
$carbon = DateTimeHelper::makeCarbon($value, $throwException);
try {
// Find user preference
$carbon->setTimezone(\Backend\Models\Preference::get('timezone'));
}
catch (Exception $ex) {
// Use system default
$carbon->setTimezone(Config::get('backend.timezone', Config::get('app.timezone')));
}
return $carbon;
}
/**
* Proxy method for dateTime() using "date" format alias.
* @return string
@ -214,14 +235,14 @@ class Backend
$contents = file_get_contents($assetFile);
// Find all assets that are compiled in this file
preg_match_all('/^=require\s+([A-z0-9-_+\.\/]+)$/m', $contents, $matches, PREG_SET_ORDER);
preg_match_all('/^=require\s+([A-z0-9-_+\.\/]+)[\n|\r\n|$]/m', $contents, $matches, PREG_SET_ORDER);
// Determine correct asset path
$directory = str_replace(basename($file), '', $file);
if (count($matches)) {
$results = array_map(function ($match) use ($directory) {
return $directory . $match[1];
return str_replace('/', DIRECTORY_SEPARATOR, $directory . $match[1]);
}, $matches);
foreach ($results as $i => $result) {

View File

@ -2,12 +2,15 @@
return [
'auth' => [
'title' => 'Admin-Bereich'
'title' => 'Admin-Bereich',
'invalid_login' => 'Die Angaben stimmen nicht mit unseren Aufzeichnungen überein. Überprüfen Sie diese und versuchen Sie es noch einmal.',
],
'field' => [
'invalid_type' => 'Ungültiger Feldtyp :type.',
'options_method_invalid_model' => 'Das Attribut ":field" löst sich nicht zu einen gültigen Model auf. Probiere die options Methode der Model-Klasse :model explicit zu definieren.',
'options_method_not_exists' => 'Die Model-Klasse :model muss eine Methode :method() mit Rückgabe der Werte von ":field" besitzen.',
'options_method_not_exists' => 'Die Modell-Klasse :model muss eine Methode :method() mit Rückgabe der Werte von ":field" besitzen.',
'options_static_method_invalid_value' => "Die statische Methode ':method()' in der Klasse :class hat kein valides Optionsarray zurückgegeben.",
'colors_method_not_exists' => "Die Modellklasse :model muss eine Methode :method() definieren, welche html color (HEX) codes für das ':field' Formularfeld zurückgibt.",
],
'widget' => [
'not_registered' => "Ein Widget namens ':name' wurde nicht registriert",
@ -15,6 +18,11 @@ return [
],
'page' => [
'untitled' => "Unbenannt",
'404' => [
'label' => 'Seite nicht gefunden',
'help' => "Die von Ihnen angeforderte Seite konnte nicht gefunden werden.",
'back_link' => 'Zurück zur vorigen Seite',
],
'access_denied' => [
'label' => "Zugriff verweigert",
'help' => "Sie haben nicht die erforderlichen Berechtigungen, um diese Seite zu sehen.",
@ -28,14 +36,23 @@ return [
],
'partial' => [
'not_found_name' => "Das Partial ':name' wurde nicht gefunden.",
'invalid_name' => 'Ungültiger Partial: :name.',
],
'ajax_handler' => [
'invalid_name' => 'Ungültiger AJAX handler: :name.',
'not_found' => "AJAX handler ':name' wurde nicht gefunden.",
],
'account' => [
'impersonate_confirm' => 'Sind Sie sicher, dass Sie sich als dieser Benutzer anmelden wollen? Sie können zu Ihrem ursprünglichen Zustand zurückkehren, indem Sie sich abmelden.',
'impersonate_success' => 'Sie sind jetzt als dieser Benutzer angemeldet',
'signed_in_as' => 'Angemeldet als :full_name',
'sign_out' => 'Abmelden',
'login' => 'Anmelden',
'reset' => 'Zurücksetzen',
'restore' => 'Wiederherstellen',
'login_placeholder' => 'Benutzername',
'password_placeholder' => 'Passwort',
'remember_me' => 'Angemeldet bleiben',
'forgot_password' => "Passwort vergessen?",
'enter_email' => "Bitte E-Mail-Adresse eingeben",
'enter_login' => "Bitte Benutzernamen eingeben",
@ -112,6 +129,8 @@ return [
'last_name' => 'Nachname',
'full_name' => 'Kompletter Name',
'email' => 'E-Mail',
'role_field' => 'Rolle',
'role_comment' => 'Rollen definieren Benutzerberechtigungen, die auf Benutzerebene auf der Registerkarte Berechtigungen überschrieben werden können.',
'groups' => 'Gruppen',
'groups_comment' => 'Geben Sie hier die Gruppenzugehörigkeit an',
'avatar' => 'Avatar',
@ -148,9 +167,25 @@ return [
'return' => 'Zurück zur Gruppen-Übersicht',
'users_count' => 'Benutzer',
],
'role' => [
'name' => 'Rolle',
'name_field' => 'Name',
'name_comment' => 'Der Name wird in der Rollenliste auf dem Administratorformular angezeigt.',
'description_field' => 'Beschreibung',
'code_field' => 'Code',
'code_comment' => 'Geben Sie einen eindeutigen Code an, wenn Sie mit der API auf das Rollenobjekt zugreifen möchten.',
'menu_label' => 'Rollen verwalten',
'list_title' => 'Rollen verwalten',
'new' => 'Neue Rolle',
'delete_confirm' => 'Diese Administratorrolle löschen?',
'return' => 'Zurück zur Rollenliste',
'users_count' => 'Benutzer',
],
'preferences' => [
'not_authenticated' => 'Zum Speichern oder Anzeigen dieser Einstellungen liegt kein Nutzerkonto vor'
]
],
'trashed_hint_title' => 'Dieses Konto wurde gelöscht.',
'trashed_hint_desc' => 'Dieses Konto wurde gelöscht und kann nicht mehr angemeldet werden. Um es wiederherzustellen, klicken Sie auf das Symbol "Benutzer wiederherstellen" unten rechts',
],
'list' => [
'default_title' => 'Auflisten',
@ -195,6 +230,11 @@ return [
'remove_confirm' => 'Sind Sie sicher?',
'remove_file' => 'Datei entfernen',
],
'repeater' => [
'add_new_item' => 'Neues Element hinzufügen',
'min_items_failed' => ':name erfordert ein Minimum an :min Elementen, aber es wurden nur :items bereitgestellt',
'max_items_failed' => ':name lässt nur bis zu :max Elemente zu, :items wurden bereitgestellt',
],
'form' => [
'create_title' => "Neuer :name",
'update_title' => "Bearbeite :name",
@ -312,6 +352,8 @@ return [
'permissions' => 'Verzeichnis :name oder ein Unterverzeichnis kann nicht von PHP beschrieben werden. Bitte setzen Sie die korrekten Rechte für den Webserver in diesem Verzeichnis.',
'extension' => 'Die PHP Erweiterung :name ist nicht installiert. Bitte installieren Sie diese Library und aktivieren Sie die Erweiterung.',
'plugin_missing' => 'Das Plugin :name hat eine Abhängigkeit die nicht installiert ist. Bitte installieren Sie alle benötigten Plugins.',
'debug' => 'Der Debug-Modus ist aktiviert. Dies wird für Produktionsinstallationen nicht empfohlen.',
'decompileBackendAssets' => 'Assets im Backend sind derzeit dekompiliert. Dies wird für Produktionsinstallationen nicht empfohlen.',
],
'editor' => [
'menu_label' => 'Editor Einstellungen',
@ -367,6 +409,8 @@ return [
'minimal' => 'Minimal',
'full' => 'Vollständig',
],
'paragraph_formats' => 'Absatzformatierungen',
'paragraph_formats_comment' => 'Die Optionen, welche in der Dropdown-Liste für Absatzformatierungen angezeigt werden.',
],
'tooltips' => [
'preview_website' => 'Vorschau der Webseite'
@ -386,6 +430,8 @@ return [
'brand' => 'Brand',
'logo' => 'Logo',
'logo_description' => 'Lade ein eigenes Logo hoch, das im Backend verwendet werden soll.',
'favicon' => 'Favicon',
'favicon_description' => 'Laden Sie ein benutzerdefiniertes Favicon zur Verwendung im Back-End hoch',
'app_name' => 'App-Name',
'app_name_description' => 'Dieser Name wird als Titel des Backends angezeigt.',
'app_tagline' => 'App-Tagline',
@ -399,6 +445,7 @@ return [
'navigation' => 'Navigation',
'menu_mode' => 'Menustyles',
'menu_mode_inline' => 'Inline',
'menu_mode_inline_no_icons' => 'Inline (ohne Icons)',
'menu_mode_tile' => 'Tiles',
'menu_mode_collapsed' => 'Collapsed'
],
@ -503,6 +550,7 @@ return [
],
'permissions' => [
'manage_media' => 'Medien verwalten',
'allow_unsafe_markdown' => 'Unsicheres Markdown verwenden (kann Javascript enthalten)',
],
'mediafinder' => [
'label' => 'Media Finder',
@ -534,7 +582,12 @@ return [
'multiple_selected' => 'Mehrere Dateien ausgewählt.',
'uploading_file_num' => 'Lade :number Datei(en)...',
'uploading_complete' => 'Upload vollständig',
'uploading_error' => 'Upload fehlgeschlagen',
'type_blocked' => 'Der verwendete Dateityp ist aus Sicherheitsgründen gesperrt.',
'order_by' => 'Sortieren nach',
'direction' => 'Direction',
'direction_asc' => 'Aufsteigend',
'direction_desc' => 'Absteigend',
'folder' => 'Ordner',
'no_files_found' => 'Keine entsprechenden Dateien gefunden.',
'delete_empty' => 'Bitte Wählen Sie Dateien zum Löschen aus.',
@ -557,11 +610,11 @@ return [
'restore' => 'Alle Änderungen rückgängig machen',
'resize' => 'Größe anpassen...',
'selection_mode_normal' => 'Normal',
'selection_mode_fixed_ratio' => 'Fixes Verhältnis',
'selection_mode_fixed_size' => 'Fixe Größe',
'selection_mode_fixed_ratio' => 'Festes Verhältnis',
'selection_mode_fixed_size' => 'Feste Größe',
'height' => 'Höhe',
'width' => 'Breite',
'selection_mode' => 'Selection mode',
'selection_mode' => 'Auswahlmodus',
'resize_image' => 'Bildgröße anpassen',
'image_size' => 'Dimensionen:',
'selected_size' => 'Ausgewählt:'

View File

@ -9,6 +9,7 @@ return [
'invalid_type' => 'Invalid field type used :type.',
'options_method_invalid_model' => "The attribute ':field' does not resolve to a valid model. Try specifying the options method for model class :model explicitly.",
'options_method_not_exists' => "The model class :model must define a method :method() returning options for the ':field' form field.",
'options_static_method_invalid_value' => "The static method ':method()' on :class did not return a valid options array.",
'colors_method_not_exists' => "The model class :model must define a method :method() returning html color HEX codes for the ':field' form field.",
],
'widget' => [
@ -372,6 +373,7 @@ return [
'editor' => [
'menu_label' => 'Editor settings',
'menu_description' => 'Customize the global editor preferences, such as font size and color scheme.',
'preview' => 'Preview',
'font_size' => 'Font size',
'tab_size' => 'Tab size',
'use_hard_tabs' => 'Indent using tabs',

View File

@ -396,7 +396,8 @@ return [
'filter' => [
'all' => 'todo',
'options_method_not_exists' => "La clase de modelo :model debe definir un método :method() para regresar opciones para el filtro ':filter'.",
'date_all' => 'todo el período'
'date_all' => 'todo el período',
'number_all' => 'todos los números'
],
'import_export' => [
'upload_csv_file' => '1. Subir un archivo CSV',

View File

@ -119,7 +119,7 @@ return [
'role_field' => 'Rôle',
'role_comment' => 'Les rôles définissent les permissions de l\'utilisateur, elles peuvent être écrasés au niveau de l\'utilisateur dans l\'onglet "Permissions".',
'groups' => 'Groupes',
'groups_comment' => 'Préciser les groupes auxquels ce compte doit appartenir. Les groupes définissent les permissions des utilisateurs, qui peuvent être surchargées au niveau de lutilisateur, dans longlet Permissions.',
'groups_comment' => 'Préciser les groupes auxquels ce compte doit appartenir.',
'avatar' => 'Avatar',
'password' => 'Mot de passe',
'password_confirmation' => 'Confirmer le mot de passe',

View File

@ -8,7 +8,8 @@ return [
'field' => [
'invalid_type' => 'A(z) :type mezőtípus érvénytelen.',
'options_method_invalid_model' => "A(z) ':field' tulajdonság nem passzol a modellhez. Próbálja meghatározni a beállítást, ami megfelelő a(z) :model osztály számára.",
'options_method_not_exists' => "A(z) :model modell osztálynak egy :method() nevű metódust kell definiálnia a(z) ':field' űrlapmező számára, ami visszaadja a beállításokat.",
'options_method_not_exists' => "A(z) :model osztálynak egy :method() nevű metódust kell definiálnia a(z) ':field' űrlapmező számára, ami visszaadja a beállításokat.",
'options_static_method_invalid_value' => "A(z) :class osztályban lévő ':method()' nevű metódus nem ad vissza érvényes tömböt.",
'colors_method_not_exists' => "A(z) :model modell osztálynak egy :method() nevű metódust kell definiálnia a(z) ':field' űrlapmező számára, ami visszaadja a html HEX kódot."
],
'widget' => [
@ -43,11 +44,15 @@ return [
],
'account' => [
'impersonate' => 'Átjelentkezés a fiókba',
'impersonate_confirm' => 'Biztos benne, hogy átjelentkezik a felhasználó saját fiókjába? Ezáltal a jelenlegi munkamenetből ki lesz jelentkeztetve.',
'impersonate_confirm' => 'Biztos, hogy átjelentkezik a felhasználó saját fiókjába? Ezáltal a jelenlegi munkamenetből ki lesz jelentkeztetve.',
'impersonate_success' => 'Sikeresen átjelentkezett a másik fiókba',
'impersonate_working' => 'Átjelentkezés...',
'impersonating' => 'Átjelentkezve mint :full_name',
'stop_impersonating' => 'Visszajelentkezés',
'unsuspend' => 'Felfüggesztés',
'unsuspend_confirm' => 'Biztos, hogy felfüggeszti a felhasználót?',
'unsuspend_success' => 'A felfüggesztés sikeresen megtörtént.',
'unsuspend_working' => 'Felfüggesztés folyamatban...',
'signed_in_as' => 'Belépve mint :full_name',
'sign_out' => 'Kijelentkezés',
'login' => 'Belépés',
@ -368,6 +373,7 @@ return [
'editor' => [
'menu_label' => 'Szövegszerkesztő',
'menu_description' => 'A megjelenésének és működésének testreszabása.',
'preview' => 'Előnézet',
'font_size' => 'Betűméret',
'tab_size' => 'Tabulátor mérete',
'use_hard_tabs' => 'Behúzás tabulátorokkal',
@ -402,6 +408,7 @@ return [
'label' => 'Megnevezés',
'class_name' => 'CSS osztály',
'markup_tags' => 'Szabályok',
'markup_tag' => 'Szabály',
'allowed_empty_tags' => 'Engedélyezett üres elemek',
'allowed_empty_tags_comment' => 'Azon HTML elemek, amik üres érték esetén sem lesznek eltávolítva.',
'allowed_tags' => 'Engedélyezett elemek',
@ -412,14 +419,17 @@ return [
'remove_tags_comment' => 'Azon HTML elemek, amik a tartalmukkal együtt törölhetőek.',
'line_breaker_tags' => 'Sortörő elemek',
'line_breaker_tags_comment' => 'Azon HTML elemek, amik végén kötelezően egy új sor jelenik meg.',
'toolbar_buttons' => 'Eszköztár',
'toolbar_options' => 'Eszköztár',
'toolbar_buttons' => 'Saját konfiguráció',
'toolbar_buttons_comment' => 'Az alapértelmezetten megjelenő eszközök listája.',
'toolbar_buttons_preset' => 'Előre beállított eszköztár konfigurációk:',
'toolbar_buttons_preset' => 'Előre beállított konfigurációk:',
'toolbar_buttons_presets' => [
'default' => 'Alapértelmezett',
'minimal' => 'Minimális',
'full' => 'Teljes',
],
'paragraph_formats' => 'Bekezdés formátumok',
'paragraph_formats_comment' => 'Az ehhez tartozó lenyíló listában fognak megjelenni.',
],
'tooltips' => [
'preview_website' => 'Weboldal megtekintése'
@ -562,7 +572,8 @@ return [
]
],
'permissions' => [
'manage_media' => 'Média kezelése'
'manage_media' => 'Média kezelése',
'allow_unsafe_markdown' => 'Nem biztonságos szerkesztő használata',
],
'mediafinder' => [
'label' => 'Média',

View File

@ -228,7 +228,7 @@ return [
'preview_no_record_message' => 'Nessun record selezionato.',
'select' => 'Seleziona',
'select_all' => 'seleziona tutto',
'select_none' => 'non selezionare niente',
'select_none' => 'deseleziona tutto',
'select_placeholder' => 'seleziona',
'insert_row' => 'Inserisci riga',
'insert_row_below' => 'Inserisci riga sotto',

View File

@ -9,6 +9,7 @@ return [
'invalid_type' => 'Ongeldig type veld: :type.',
'options_method_invalid_model' => "Het attribuut ':field' levert geen geldig model op. Probeer de opties methode expliciet te specifieren voor modelklasse :model.",
'options_method_not_exists' => 'De modelklasse :model moet de methode :method() definiëren met daarin opties voor het veld ":field".',
'options_static_method_invalid_value' => "De statische methode ':method()' in :class leverde geen geldige array met opties op.",
'colors_method_not_exists' => 'De modelklasse :model moet de methode :method() definiëren met daarin html HEX kleurcodes voor het veld ":field".',
],
'widget' => [
@ -372,6 +373,7 @@ return [
'editor' => [
'menu_label' => 'Editor instellingen',
'menu_description' => 'Beheer editor instellingen, zoals lettergrootte en kleurschema.',
'preview' => 'Voorbeeldweergave',
'font_size' => 'Lettergrootte',
'tab_size' => 'Tab grootte',
'use_hard_tabs' => 'Inspringen met tabs',
@ -406,6 +408,7 @@ return [
'label' => 'Label',
'class_name' => 'Class naam',
'markup_tags' => 'Opmaak HTML-tags',
'markup_tag' => 'Opmaak HTML-tag',
'allowed_empty_tags' => 'Toegestane lege HTML-tags',
'allowed_empty_tags_comment' => 'Een lijst van HTML-tags die niet worden verwijderd als ze leeg zijn.',
'allowed_tags' => 'Toegestane HTML-tags',
@ -416,6 +419,7 @@ return [
'remove_tags_comment' => 'Een lijst van HTML-tags die samen met hun inhoud worden verwijderd.',
'line_breaker_tags' => 'Line breaker tags',
'line_breaker_tags_comment' => 'Een lijst van HTML-tags waartussen een line breaker element wordt geplaatst.',
'toolbar_options' => 'Toolbar opties',
'toolbar_buttons' => 'Toolbar knoppen',
'toolbar_buttons_comment' => 'De toolbar knoppen die standaard getoond worden door de Rich Editor.',
'toolbar_buttons_preset' => 'Voeg preset toe voor toolbar knoppen:',
@ -424,9 +428,11 @@ return [
'minimal' => 'Minimaal',
'full' => 'Volledig',
],
'paragraph_formats' => 'Paragraaf formaten',
'paragraph_formats_comment' => 'De opties die in de "Paragraaf formaat" lijst zullen verschijnen.',
],
'tooltips' => [
'preview_website' => 'Voorvertoning website',
'preview_website' => 'Voorbeeldweergave website',
],
'mysettings' => [
'menu_label' => 'Mijn instellingen',

View File

@ -9,6 +9,7 @@ return [
'invalid_type' => 'Tipo de campo inválido :type.',
'options_method_invalid_model' => 'O atributo ":field" não resolve a classe. Tente especificar as opções do método para o modelo :model.',
'options_method_not_exists' => 'A classe :model deve definir um método :method() retornando opções para o campo ":field".',
'options_static_method_invalid_value' => "O método estático ':method()' na :class não retornou um array de opções válidas.",
'colors_method_not_exists' => 'A classe de modelo :model deve definir um método :method() retornando códigos HEX de cor html para o campo de formulário ":field".'
],
'widget' => [
@ -48,14 +49,18 @@ return [
'impersonate_working' => 'Representando...',
'impersonating' => 'Representando :full_name',
'stop_impersonating' => 'Pare de representar',
'unsuspend' => 'Reativar',
'unsuspend_confirm' => 'Tem certeza de que deseja reativar este usuário?',
'unsuspend_success' => 'O usuário foi reativado.',
'unsuspend_working' => 'Reativando...',
'signed_in_as' => 'Assinado como :full_name',
'remember_me' => 'Permaneça logado',
'sign_out' => 'Sair',
'login' => 'Entrar',
'reset' => 'Redefinir',
'restore' => 'Restaurar',
'login_placeholder' => 'Usuário',
'password_placeholder' => 'Senha',
'remember_me' => 'Permaneça logado',
'forgot_password' => 'Esqueceu sua senha?',
'enter_email' => 'Entre com seu email',
'enter_login' => 'Entre com seu nome de usuário',
@ -214,8 +219,8 @@ return [
'setup_title' => 'Configuração da Lista',
'setup_help' => 'Selecione as colunas que deseja ver na lista. Você pode alterar as posições das colunas arrastando-as para cima ou para baixo.',
'records_per_page' => 'Registros por página',
'check' => 'Marcar',
'records_per_page_help' => 'Selecione o número de registros a serem exibidos por página. Note que um número grande pode prejudicar a performance.',
'check' => 'Marcar',
'delete_selected' => 'Excluir selecionado',
'delete_selected_empty' => 'Não há registros selecionados para excluir.',
'delete_selected_confirm' => 'Excluir os registros selecionados?',
@ -236,6 +241,7 @@ return [
'remove_file' => 'Remover arquivo'
],
'repeater' => [
'add_new_item' => 'Adicionar novo item',
'min_items_failed' => ':name requer um mínimo de :min itens, apenas :items foram fornecidos',
'max_items_failed' => ':name requer um máximo de :max itens, apenas :items foram fornecidos',
],
@ -246,6 +252,7 @@ return [
'create_success' => ':name foi criado com sucesso',
'update_success' => ':name foi atualizado com sucesso',
'delete_success' => ':name foi apagado com sucesso',
'restore_success' => ':name restaurado',
'reset_success' => 'Reinicialização completada',
'missing_id' => 'O ID do registro não foi fornecido',
'missing_model' => 'Formulário utilizado na classe :class não tem um model definido.',
@ -304,6 +311,10 @@ return [
'invalid_model_class' => 'A classe de modelo fornecida ":modelClass" para o recordfinder é inválida',
'cancel' => 'Cancelar',
],
'pagelist' => [
'page_link' => 'Link da página',
'select_page' => 'Selecione uma página ...',
],
'relation' => [
'missing_config' => 'Comportamento relation não tem uma configuração para ":config".',
'missing_definition' => 'Comportamento relation não contém uma definição para ":field".',
@ -356,21 +367,25 @@ return [
'permissions' => 'Diretório :name ou seus subdiretórios não são graváveis pelo PHP. Por favor, defina permissões de escrita para o servidor neste diretório.',
'extension' => 'A extensão PHP :name não está instalada. Por favor, instale esta biblioteca para ativar a extensão.',
'plugin_missing' => 'O plugin :name é uma dependência, mas não está instalado. Por favor, instale este plugin.',
'debug' => 'O modo de depuração está ativado. Isso não é recomendado para instalações de produção.',
'decompileBackendAssets' => 'Os assets no Backend estão atualmente descompilados. Isso não é recomendado para instalações de produção.',
],
'editor' => [
'menu_label' => 'Definições do Editor',
'menu_description' => 'Gerenciar configurações do editor.',
'preview' => 'Prévia',
'font_size' => 'Tamanho da fonte',
'tab_size' => 'Tamanho do espaçamento',
'use_hard_tabs' => 'Recuo usando guias',
'code_folding' => 'Código flexível',
'code_folding_begin' => 'Marca de início',
'code_folding_begin_end' => 'Marca de início e fim',
'autocompletion' => 'Autocompletar',
'code_folding' => 'Código flexível',
'word_wrap' => 'Quebra de linha',
'highlight_active_line' => 'Destaque na linha ativa',
'auto_closing' => 'Auto completar tags e caracteres especiais',
'show_invisibles' => 'Mostrar caracteres invisíveis',
'show_gutter' => 'Mostrar numeração de linhas',
'basic_autocompletion'=> 'Autocompletar básico (Ctrl + Espaço)',
'live_autocompletion'=> 'Autocompletar em tempo real',
'enable_snippets'=> 'Habilitar trechos de códigos (Tab)',
@ -380,7 +395,7 @@ return [
'mode_fluid' => 'Fluido',
'40_characters' => '40 caracteres',
'80_characters' => '80 caracteres',
'show_gutter' => 'Mostrar numeração de linhas',
'theme' => 'Esquema de cores',
'markup_styles' => 'Estilos de marcação',
'custom_styles' => 'Folha de estilo personalizada',
'custom styles_comment' => 'Estilos personalizados para incluir no editor HTML.',
@ -393,6 +408,7 @@ return [
'label' => 'Rótulo',
'class_name' => 'Nome da classe',
'markup_tags' => 'Etiquetas de marcação',
'markup_tag' => 'Tag de marcação',
'allowed_empty_tags' => 'Permitir etiquetas vazias',
'allowed_empty_tags_comment' => 'A lista de etiquetas não é removida quando não há conteúdo.',
'allowed_tags' => 'Etiquetas permitidas',
@ -401,11 +417,19 @@ return [
'no_wrap_comment' => 'Lista de etiquetas que não devem ser agrupadas.',
'remove_tags' => 'Excluir etiqueta',
'remove_tags_comment' => 'Lista de etiquetas que serão exclídas juntas com seu conteúdo.',
'theme' => 'Esquema de cores',
'line_breaker_tags' => 'Tags de quebra de linha',
'line_breaker_tags_comment' => 'A lista de tags usadas para colocar um elemento em quebra de linha.',
'toolbar_options' => 'Opções da barra de ferramentas',
'toolbar_buttons' => 'Botões da barra de ferramentas',
'toolbar_buttons_comment' => 'Os botões da barra de ferramentas a serem exibidos no Rich Editor por padrão.',
'toolbar_buttons_preset' => 'Insira uma configuração predefinida de botãos na barra de ferramentas:',
'toolbar_buttons_presets' => [
'default' => 'Padrão',
'minimal' => 'Mínimo',
'full' => 'Completo',
],
'paragraph_formats' => 'Formatos de parágrafo',
'paragraph_formats_comment' => 'As opções que aparecerão na lista de Formatos do parágrafo.',
],
'tooltips' => [
'preview_website' => 'Visualizar a página'
@ -542,12 +566,14 @@ return [
'iso_8859_13' => 'ISO-8859-13 (Latin-7, Baltic Rim)',
'iso_8859_14' => 'ISO-8859-14 (Latin-8, Celtic)',
'iso_8859_15' => 'ISO-8859-15 (Latin-9, Western European revision with euro sign)',
'windows_1250' => 'Windows-1250 (CP1250, Central and Eastern European)',
'windows_1251' => 'Windows-1251 (CP1251)',
'windows_1252' => 'Windows-1252 (CP1252)'
]
],
'permissions' => [
'manage_media' => 'Gerenciar mídias'
'manage_media' => 'Gerenciar mídias',
'allow_unsafe_markdown' => 'Usar Markdown inseguro (pode incluir Javascript)',
],
'mediafinder' => [
'label' => 'Localizador de Mídia',

Some files were not shown because too many files have changed in this diff Show More