Merge branch 'develop' into main
commit
f24e7bc4c2
|
@ -3,6 +3,7 @@ namespace App\Model\Table;
|
||||||
|
|
||||||
use App\Model\Table\AppTable;
|
use App\Model\Table\AppTable;
|
||||||
use Cake\ORM\Table;
|
use Cake\ORM\Table;
|
||||||
|
use Cake\Filesystem\File;
|
||||||
use Cake\Core\Configure;
|
use Cake\Core\Configure;
|
||||||
use Cake\Error\Debugger;
|
use Cake\Error\Debugger;
|
||||||
|
|
||||||
|
@ -73,10 +74,18 @@ class SettingsTable extends AppTable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$setting['value'] = $value ?? '';
|
$setting['value'] = $value ?? '';
|
||||||
|
if (isset($setting['test'])) {
|
||||||
|
$validationResult = $this->SettingsProvider->evaluateFunctionForSetting($setting['test'], $setting);
|
||||||
|
if ($validationResult !== true) {
|
||||||
|
$errors[] = $validationResult;
|
||||||
|
$setting['errorMessage'] = $validationResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (empty($errors) && !empty($setting['beforeSave'])) {
|
if (empty($errors) && !empty($setting['beforeSave'])) {
|
||||||
$beforeSaveResult = $this->SettingsProvider->evaluateFunctionForSetting($setting['beforeSave'], $setting);
|
$beforeSaveResult = $this->SettingsProvider->evaluateFunctionForSetting($setting['beforeSave'], $setting);
|
||||||
if ($beforeSaveResult !== true) {
|
if ($beforeSaveResult !== true) {
|
||||||
$errors[] = $beforeSaveResult;
|
$errors[] = $beforeSaveResult;
|
||||||
|
$setting['errorMessage'] = $validationResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (empty($errors)) {
|
if (empty($errors)) {
|
||||||
|
@ -85,6 +94,8 @@ class SettingsTable extends AppTable
|
||||||
if (!empty($setting['afterSave'])) {
|
if (!empty($setting['afterSave'])) {
|
||||||
$this->SettingsProvider->evaluateFunctionForSetting($setting['afterSave'], $setting);
|
$this->SettingsProvider->evaluateFunctionForSetting($setting['afterSave'], $setting);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$errors[] = __('Could not save settings on disk');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $errors;
|
return $errors;
|
||||||
|
@ -129,8 +140,16 @@ class SettingsTable extends AppTable
|
||||||
$settings = $this->readSettings();
|
$settings = $this->readSettings();
|
||||||
$settings[$name] = $value;
|
$settings[$name] = $value;
|
||||||
$settings = json_encode($settings, JSON_PRETTY_PRINT);
|
$settings = json_encode($settings, JSON_PRETTY_PRINT);
|
||||||
file_put_contents(CONFIG . 'config.json', $settings);
|
$path = CONFIG . 'config.json';
|
||||||
$this->loadSettings();
|
$file = new File($path);
|
||||||
return true;
|
if ($file->writable()) {
|
||||||
|
$success = file_put_contents($path, $settings);
|
||||||
|
if ($success) {
|
||||||
|
$this->loadSettings();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
return $success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,4 +135,18 @@ class UserSettingsTable extends AppTable
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validURI - Ensure the provided URI can be safely put as a link
|
||||||
|
*
|
||||||
|
* @param String $uri
|
||||||
|
* @return bool if the URI is safe to be put as a link
|
||||||
|
*/
|
||||||
|
public function validURI(String $uri): bool
|
||||||
|
{
|
||||||
|
$parsed = parse_url($uri);
|
||||||
|
$isLocalPath = empty($parsed['scheme']) && empty($parsed['domain']) && !empty($parsed['path']);
|
||||||
|
$isValidURL = !empty($parsed['scheme']) && in_array($parsed['scheme'], ['http', 'https']) && filter_var($uri, FILTER_SANITIZE_URL);
|
||||||
|
return $isLocalPath || $isValidURL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Cake\ORM\TableRegistry;
|
||||||
|
|
||||||
$bookmarks = !empty($loggedUser->user_settings_by_name['ui.bookmarks']['value']) ? json_decode($loggedUser->user_settings_by_name['ui.bookmarks']['value'], true) : [];
|
$bookmarks = !empty($loggedUser->user_settings_by_name['ui.bookmarks']['value']) ? json_decode($loggedUser->user_settings_by_name['ui.bookmarks']['value'], true) : [];
|
||||||
|
$this->userSettingsTable = TableRegistry::getTableLocator()->get('UserSettings');
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -9,18 +13,24 @@ $bookmarks = !empty($loggedUser->user_settings_by_name['ui.bookmarks']['value'])
|
||||||
<?= __('Bookmarks') ?>
|
<?= __('Bookmarks') ?>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<?php if (!empty($bookmarks)): ?>
|
<?php if (!empty($bookmarks)) : ?>
|
||||||
<ul class="col-sm-12 col-md-10 col-l-8 col-xl-8 mb-3">
|
<ul class="col-sm-12 col-md-10 col-l-8 col-xl-8 mb-3">
|
||||||
<?php foreach ($bookmarks as $bookmark) : ?>
|
<?php foreach ($bookmarks as $bookmark) : ?>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a href="<?= h($bookmark['url']) ?>" class="w-bold">
|
<?php if ($this->userSettingsTable->validURI($bookmark['url'])): ?>
|
||||||
<?= h($bookmark['label']) ?>
|
<a href="<?= h($bookmark['url']) ?>" class="w-bold">
|
||||||
</a>
|
<?= h($bookmark['label']) ?>
|
||||||
|
</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="w-bold">
|
||||||
|
<?= h($bookmark['url']) ?>
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
<span class="ms-3 fw-light"><?= h($bookmark['name']) ?></span>
|
<span class="ms-3 fw-light"><?= h($bookmark['name']) ?></span>
|
||||||
</li>
|
</li>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
<?php else: ?>
|
<?php else : ?>
|
||||||
<p class="fw-light"><?= __('No bookmarks') ?></p>
|
<p class="fw-light"><?= __('No bookmarks') ?></p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
(!empty($setting['error']) ? $appView->get('variantFromSeverity')[$setting['severity']] : ''),
|
(!empty($setting['error']) ? $appView->get('variantFromSeverity')[$setting['severity']] : ''),
|
||||||
],
|
],
|
||||||
($setting['type'] == 'textarea' ? '' : 'type') => ($setting['type'] == 'textarea' ? '' : 'text'),
|
($setting['type'] == 'textarea' ? '' : 'type') => ($setting['type'] == 'textarea' ? '' : 'text'),
|
||||||
'id' => $settingId,
|
'id' => h($settingId),
|
||||||
'data-setting-name' => $settingName,
|
'data-setting-name' => h($settingName),
|
||||||
'value' => isset($setting['value']) ? $setting['value'] : "",
|
'value' => isset($setting['value']) ? h($setting['value']) : "",
|
||||||
'placeholder' => $setting['default'] ?? '',
|
'placeholder' => empty($setting['default']) ? '' : h($setting['default']),
|
||||||
'aria-describedby' => "{$settingId}Help"
|
'aria-describedby' => h("{$settingId}Help")
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
})($settingName, $setting, $this);
|
})($settingName, $setting, $this);
|
||||||
|
@ -28,13 +28,13 @@
|
||||||
return $this->Bootstrap->switch([
|
return $this->Bootstrap->switch([
|
||||||
'label' => h($setting['description']),
|
'label' => h($setting['description']),
|
||||||
'checked' => !empty($setting['value']),
|
'checked' => !empty($setting['value']),
|
||||||
'id' => $settingId,
|
'id' => h($settingId),
|
||||||
'class' => [
|
'class' => [
|
||||||
(!empty($setting['error']) ? 'is-invalid' : ''),
|
(!empty($setting['error']) ? 'is-invalid' : ''),
|
||||||
(!empty($setting['error']) ? $appView->get('variantFromSeverity')[$setting['severity']] : ''),
|
(!empty($setting['error']) ? $appView->get('variantFromSeverity')[$setting['severity']] : ''),
|
||||||
],
|
],
|
||||||
'attrs' => [
|
'attrs' => [
|
||||||
'data-setting-name' => $settingName
|
'data-setting-name' => h($settingName)
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
})($settingName, $setting, $this);
|
})($settingName, $setting, $this);
|
||||||
|
@ -53,16 +53,16 @@
|
||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'min' => '0',
|
'min' => '0',
|
||||||
'step' => 1,
|
'step' => 1,
|
||||||
'id' => $settingId,
|
'id' => h($settingId),
|
||||||
'data-setting-name' => $settingName,
|
'data-setting-name' => h($settingName),
|
||||||
'aria-describedby' => "{$settingId}Help"
|
'aria-describedby' => h("{$settingId}Help")
|
||||||
]);
|
]);
|
||||||
})($settingName, $setting, $this);
|
})($settingName, $setting, $this);
|
||||||
|
|
||||||
} elseif ($setting['type'] == 'select' || $setting['type'] == 'multi-select') {
|
} elseif ($setting['type'] == 'select' || $setting['type'] == 'multi-select') {
|
||||||
$input = (function ($settingName, $setting, $appView) {
|
$input = (function ($settingName, $setting, $appView) {
|
||||||
$settingId = str_replace('.', '_', $settingName);
|
$settingId = str_replace('.', '_', $settingName);
|
||||||
$setting['value'] = $setting['value'] ?? '';
|
$setting['value'] = empty($setting['value']) ? '' : h($setting['value']);
|
||||||
if ($setting['type'] == 'multi-select') {
|
if ($setting['type'] == 'multi-select') {
|
||||||
if (!is_array($setting['value'])) {
|
if (!is_array($setting['value'])) {
|
||||||
$firstChar = substr($setting['value'], 0, 1);
|
$firstChar = substr($setting['value'], 0, 1);
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
foreach ($setting['options'] as $key => $value) {
|
foreach ($setting['options'] as $key => $value) {
|
||||||
$optionParam = [
|
$optionParam = [
|
||||||
'class' => [],
|
'class' => [],
|
||||||
'value' => $key,
|
'value' => h($key),
|
||||||
];
|
];
|
||||||
if ($setting['type'] == 'multi-select') {
|
if ($setting['type'] == 'multi-select') {
|
||||||
if (in_array($key, $setting['value'])) {
|
if (in_array($key, $setting['value'])) {
|
||||||
|
@ -100,10 +100,10 @@
|
||||||
(!empty($setting['error']) ? $appView->get('variantFromSeverity')[$setting['severity']] : ''),
|
(!empty($setting['error']) ? $appView->get('variantFromSeverity')[$setting['severity']] : ''),
|
||||||
],
|
],
|
||||||
($setting['type'] == 'multi-select' ? 'multiple' : '') => ($setting['type'] == 'multi-select' ? 'multiple' : ''),
|
($setting['type'] == 'multi-select' ? 'multiple' : '') => ($setting['type'] == 'multi-select' ? 'multiple' : ''),
|
||||||
'id' => $settingId,
|
'id' => h($settingId),
|
||||||
'data-setting-name' => $settingName,
|
'data-setting-name' => h($settingName),
|
||||||
'placeholder' => $setting['default'] ?? '',
|
'placeholder' => empty($setting['default']) ? '' : h($setting['default']),
|
||||||
'aria-describedby' => "{$settingId}Help"
|
'aria-describedby' => h("{$settingId}Help")
|
||||||
], $options);
|
], $options);
|
||||||
})($settingName, $setting, $this);
|
})($settingName, $setting, $this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
use Cake\Routing\Router;
|
use Cake\Routing\Router;
|
||||||
|
use Cake\ORM\TableRegistry;
|
||||||
|
|
||||||
|
$this->userSettingsTable = TableRegistry::getTableLocator()->get('UserSettings');
|
||||||
|
|
||||||
$seed = 'sb-' . mt_rand();
|
$seed = 'sb-' . mt_rand();
|
||||||
$icon = $entry['icon'] ?? '';
|
$icon = $entry['icon'] ?? '';
|
||||||
|
@ -14,6 +17,8 @@
|
||||||
$active = true;
|
$active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$validURI = $this->userSettingsTable->validURI($url);
|
||||||
|
|
||||||
echo $this->Bootstrap->button([
|
echo $this->Bootstrap->button([
|
||||||
'nodeType' => 'a',
|
'nodeType' => 'a',
|
||||||
'text' => h($label),
|
'text' => h($label),
|
||||||
|
@ -22,9 +27,9 @@
|
||||||
'outline' => !$active,
|
'outline' => !$active,
|
||||||
'size' => 'sm',
|
'size' => 'sm',
|
||||||
'icon' => h($icon),
|
'icon' => h($icon),
|
||||||
'class' => ['mb-1'],
|
'class' => ['mb-1', !$validURI ? 'disabled' : ''],
|
||||||
'params' => [
|
'params' => [
|
||||||
'href' => h($url),
|
'href' => $validURI ? h($url) : '#',
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
?>
|
?>
|
||||||
|
|
Loading…
Reference in New Issue