feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
- Base: wintercms/winter branch 1.2 (full framework) - Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS - Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication - Partials: hero (offline-first), features, modes (offline/nube toggle), screenshots, pricing (3 planes), comparison, FAQ, CTA - Plugin VivesPOS.Site with ContactForm - Dockerfile: PHP 8.2 Apache, port 80, healthcheck - Added winter/wn-pages, blog, sitemap, seo plugins - Active theme set to vivespos
This commit is contained in:
417
modules/system/classes/SettingsManager.php
Normal file
417
modules/system/classes/SettingsManager.php
Normal file
@@ -0,0 +1,417 @@
|
||||
<?php namespace System\Classes;
|
||||
|
||||
use Event;
|
||||
use Backend;
|
||||
use BackendAuth;
|
||||
use SystemException;
|
||||
|
||||
/**
|
||||
* Manages the system settings.
|
||||
*
|
||||
* @package winter\wn-system-module
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*/
|
||||
class SettingsManager
|
||||
{
|
||||
use \Winter\Storm\Support\Traits\Singleton;
|
||||
use \System\Traits\LazyOwnerAlias;
|
||||
|
||||
/**
|
||||
* Allocated category types
|
||||
*/
|
||||
const CATEGORY_CMS = 'system::lang.system.categories.cms';
|
||||
const CATEGORY_MISC = 'system::lang.system.categories.misc';
|
||||
const CATEGORY_MAIL = 'system::lang.system.categories.mail';
|
||||
const CATEGORY_LOGS = 'system::lang.system.categories.logs';
|
||||
const CATEGORY_SHOP = 'system::lang.system.categories.shop';
|
||||
const CATEGORY_TEAM = 'system::lang.system.categories.team';
|
||||
const CATEGORY_USERS = 'system::lang.system.categories.users';
|
||||
const CATEGORY_SOCIAL = 'system::lang.system.categories.social';
|
||||
const CATEGORY_SYSTEM = 'system::lang.system.categories.system';
|
||||
const CATEGORY_EVENTS = 'system::lang.system.categories.events';
|
||||
const CATEGORY_BACKEND = 'system::lang.system.categories.backend';
|
||||
const CATEGORY_CUSTOMERS = 'system::lang.system.categories.customers';
|
||||
const CATEGORY_MYSETTINGS = 'system::lang.system.categories.my_settings';
|
||||
const CATEGORY_NOTIFICATIONS = 'system::lang.system.categories.notifications';
|
||||
|
||||
/**
|
||||
* @var array Cache of registration callbacks.
|
||||
*/
|
||||
protected $callbacks = [];
|
||||
|
||||
/**
|
||||
* @var array List of registered items.
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* @var array List of owner aliases. ['Aliased.Owner' => 'Real.Owner']
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* @var array Grouped collection of all items, by category.
|
||||
*/
|
||||
protected $groupedItems;
|
||||
|
||||
/**
|
||||
* @var string Active plugin or module owner.
|
||||
*/
|
||||
protected $contextOwner;
|
||||
|
||||
/**
|
||||
* @var string Active item code.
|
||||
*/
|
||||
protected $contextItemCode;
|
||||
|
||||
/**
|
||||
* @var array Settings item defaults.
|
||||
*/
|
||||
protected static $itemDefaults = [
|
||||
'code' => null,
|
||||
'label' => null,
|
||||
'category' => null,
|
||||
'icon' => null,
|
||||
'url' => null,
|
||||
'permissions' => [],
|
||||
'order' => 500,
|
||||
'context' => 'system',
|
||||
'keywords' => null
|
||||
];
|
||||
|
||||
/**
|
||||
* @var System\Classes\PluginManager
|
||||
*/
|
||||
protected $pluginManager;
|
||||
|
||||
/**
|
||||
* Initialize this singleton.
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
foreach (static::$lazyAliases as $alias => $owner) {
|
||||
$this->registerOwnerAlias($owner, $alias);
|
||||
}
|
||||
$this->pluginManager = PluginManager::instance();
|
||||
}
|
||||
|
||||
protected function loadItems()
|
||||
{
|
||||
/*
|
||||
* Load module items
|
||||
*/
|
||||
foreach ($this->callbacks as $callback) {
|
||||
$callback($this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load plugin items
|
||||
*/
|
||||
$plugins = $this->pluginManager->getPlugins();
|
||||
|
||||
foreach ($plugins as $id => $plugin) {
|
||||
$items = $plugin->registerSettings();
|
||||
if (!is_array($items)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->registerSettingItems($id, $items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @event system.settings.extendItems
|
||||
* Provides an opportunity to manipulate the system settings manager
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* Event::listen('system.settings.extendItems', function ((\System\Classes\SettingsManager) $settingsManager) {
|
||||
* $settingsManager->addSettingItem(...)
|
||||
* $settingsManager->removeSettingItem(...)
|
||||
* });
|
||||
*
|
||||
*/
|
||||
Event::fire('system.settings.extendItems', [$this]);
|
||||
|
||||
/*
|
||||
* Sort settings items
|
||||
*/
|
||||
uasort($this->items, function ($a, $b) {
|
||||
return $a->order - $b->order;
|
||||
});
|
||||
|
||||
/*
|
||||
* Filter items user lacks permission for
|
||||
*/
|
||||
$user = BackendAuth::getUser();
|
||||
$this->items = $this->filterItemPermissions($user, $this->items);
|
||||
|
||||
/*
|
||||
* Process each item in to a category array
|
||||
*/
|
||||
$catItems = [];
|
||||
foreach ($this->items as $code => $item) {
|
||||
$category = $item->category ?: self::CATEGORY_MISC;
|
||||
if (!isset($catItems[$category])) {
|
||||
$catItems[$category] = [];
|
||||
}
|
||||
|
||||
$catItems[$category][$code] = $item;
|
||||
}
|
||||
|
||||
$this->groupedItems = $catItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of all settings by group, filtered by context
|
||||
* @param string $context
|
||||
* @return array
|
||||
*/
|
||||
public function listItems($context = null)
|
||||
{
|
||||
if ($this->items === null) {
|
||||
$this->loadItems();
|
||||
}
|
||||
|
||||
if ($context !== null) {
|
||||
return $this->filterByContext($this->groupedItems, $context);
|
||||
}
|
||||
|
||||
return $this->groupedItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a set of items by a given context.
|
||||
* @param array $items
|
||||
* @param string $context
|
||||
* @return array
|
||||
*/
|
||||
protected function filterByContext($items, $context)
|
||||
{
|
||||
$filteredItems = [];
|
||||
foreach ($items as $categoryName => $category) {
|
||||
$filteredCategory = [];
|
||||
foreach ($category as $item) {
|
||||
$itemContext = is_array($item->context) ? $item->context : [$item->context];
|
||||
if (in_array($context, $itemContext)) {
|
||||
$filteredCategory[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($filteredCategory)) {
|
||||
$filteredItems[$categoryName] = $filteredCategory;
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback function that defines setting items.
|
||||
* The callback function should register setting items by calling the manager's
|
||||
* registerSettingItems() function. The manager instance is passed to the
|
||||
* callback function as an argument. Usage:
|
||||
*
|
||||
* SettingsManager::registerCallback(function ($manager) {
|
||||
* $manager->registerSettingItems([...]);
|
||||
* });
|
||||
*
|
||||
* @param callable $callback A callable function.
|
||||
*/
|
||||
public function registerCallback(callable $callback)
|
||||
{
|
||||
$this->callbacks[] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the back-end setting items.
|
||||
* The argument is an array of the settings items. The array keys represent the
|
||||
* setting item codes, specific for the plugin/module. Each element in the
|
||||
* array should be an associative array with the following keys:
|
||||
* - label - specifies the settings label localization string key, required.
|
||||
* - icon - an icon name from the Font Awesome icon collection, required.
|
||||
* - url - the back-end relative URL the setting item should point to.
|
||||
* - class - the back-end relative URL the setting item should point to.
|
||||
* - 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 setting, optional.
|
||||
* - category - a string to assign this item to a category, optional.
|
||||
* @param string $owner Specifies the setting items owner plugin or module in the format Vendor.Module.
|
||||
* @param array $definitions An array of the setting item definitions.
|
||||
*/
|
||||
public function registerSettingItems($owner, array $definitions)
|
||||
{
|
||||
if (!$this->items) {
|
||||
$this->items = [];
|
||||
}
|
||||
|
||||
$this->addSettingItems($owner, $definitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an owner alias
|
||||
*
|
||||
* @param string $owner The owner to register an alias for. Example: Real.Owner
|
||||
* @param string $alias The alias to register. Example: Aliased.Owner
|
||||
* @return void
|
||||
*/
|
||||
public function registerOwnerAlias(string $owner, string $alias)
|
||||
{
|
||||
$this->aliases[strtolower($alias)] = $owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically add an array of setting items
|
||||
* @param string $owner
|
||||
* @param array $definitions
|
||||
*/
|
||||
public function addSettingItems($owner, array $definitions)
|
||||
{
|
||||
foreach ($definitions as $code => $definition) {
|
||||
$this->addSettingItem($owner, $code, $definition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically add a single setting item
|
||||
* @param string $owner
|
||||
* @param string $code
|
||||
* @param array $definitions
|
||||
*/
|
||||
public function addSettingItem($owner, $code, array $definition)
|
||||
{
|
||||
$itemKey = $this->makeItemKey($owner, $code);
|
||||
|
||||
if (isset($this->items[$itemKey])) {
|
||||
$definition = array_merge((array) $this->items[$itemKey], $definition);
|
||||
}
|
||||
|
||||
$item = array_merge(self::$itemDefaults, array_merge($definition, [
|
||||
'code' => $code,
|
||||
'owner' => $owner
|
||||
]));
|
||||
|
||||
/*
|
||||
* Link to the generic settings page if a URL is not provided
|
||||
*/
|
||||
if (isset($item['class']) && !isset($item['url'])) {
|
||||
$uri = [];
|
||||
|
||||
if (strpos($owner, '.') !== null) {
|
||||
list($author, $plugin) = explode('.', $owner);
|
||||
$uri[] = strtolower($author);
|
||||
$uri[] = strtolower($plugin);
|
||||
}
|
||||
else {
|
||||
$uri[] = strtolower($owner);
|
||||
}
|
||||
|
||||
$uri[] = strtolower($code);
|
||||
$uri = implode('/', $uri);
|
||||
$item['url'] = Backend::url('system/settings/update/' . $uri);
|
||||
}
|
||||
|
||||
$this->items[$itemKey] = (object) $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single setting item
|
||||
*/
|
||||
public function removeSettingItem($owner, $code)
|
||||
{
|
||||
if (!$this->items) {
|
||||
throw new SystemException('Unable to remove settings item before items are loaded.');
|
||||
}
|
||||
|
||||
$itemKey = $this->makeItemKey($owner, $code);
|
||||
unset($this->items[$itemKey]);
|
||||
|
||||
if ($this->groupedItems) {
|
||||
foreach ($this->groupedItems as $category => $items) {
|
||||
if (isset($items[$itemKey])) {
|
||||
unset($this->groupedItems[$category][$itemKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the navigation context.
|
||||
* @param string $owner Specifies the setting items owner plugin or module in the format Vendor.Module.
|
||||
* @param string $code Specifies the settings item code.
|
||||
*/
|
||||
public static function setContext($owner, $code)
|
||||
{
|
||||
$instance = self::instance();
|
||||
|
||||
$instance->contextOwner = strtolower($owner);
|
||||
$instance->contextItemCode = strtolower($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the current settings context.
|
||||
* @return mixed Returns an object with the following fields:
|
||||
* - itemCode
|
||||
* - owner
|
||||
*/
|
||||
public function getContext()
|
||||
{
|
||||
return (object) [
|
||||
'itemCode' => $this->contextItemCode,
|
||||
'owner' => strtolower($this->aliases[$this->contextOwner] ?? $this->contextOwner),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates a setting item object by it's owner and code
|
||||
* @param string $owner
|
||||
* @param string $code
|
||||
* @return mixed The item object or FALSE if nothing is found
|
||||
*/
|
||||
public function findSettingItem($owner, $code)
|
||||
{
|
||||
if ($this->items === null) {
|
||||
$this->loadItems();
|
||||
}
|
||||
|
||||
$itemKey = $this->makeItemKey($owner, $code);
|
||||
|
||||
if (isset($this->items[$itemKey])) {
|
||||
return $this->items[$itemKey];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes settings items from an array if the supplied user lacks permission.
|
||||
* @param User $user A user object
|
||||
* @param array $items A collection of setting items
|
||||
* @return array The filtered settings items
|
||||
*/
|
||||
protected function filterItemPermissions($user, array $items)
|
||||
{
|
||||
if (!$user) {
|
||||
return $items;
|
||||
}
|
||||
|
||||
$items = array_filter($items, function ($item) use ($user) {
|
||||
if (!$item->permissions || !count($item->permissions)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->hasAnyAccess($item->permissions);
|
||||
});
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to make a unique key for an item.
|
||||
* @param object $item
|
||||
* @return string
|
||||
*/
|
||||
protected function makeItemKey($owner, $code)
|
||||
{
|
||||
return strtoupper($this->aliases[strtolower($owner)] ?? $owner).'.'.strtoupper($code);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user