/** * Constructor. * * @param \Cake\Network\Request $request Request object for this controller. * Can be null for testing, but expect that features that use the request * parameters will not work. * @param \Cake\Network\Response $response Response object for this controller. */ public function __construct($request = null, $response = null) { parent::__construct($request, $response); $location = $this->response->location(); $this->viewBuilder()->className('CMS\\View\\View'); if (empty($location)) { $this->viewMode('default'); $this->prepareTheme(); $this->checkMaintenanceMode(); } $this->response->header('Content-Language', language('code')); $this->response->header('X-Generator', sprintf('QuickAppsCMS %s (http://quickappscms.org)', quickapps('version'))); }
/** * Prepares the default language to use by the script. * * ### Detection Methods * * This method applies the following detection methods when looking for * language to use: * * - GET parameter: If `locale` GET parameter is present in current request, and * if it's a valid language code, then will be used as current language and * also will be persisted on `locale` session for further use. * * - URL: If current URL is prefixed with a valid language code and * `url_locale_prefix` option is enabled, URL's language code will be used. * * - Locale session: If `locale` session exists it will be used. * * - User session: If user is logged in and has selected a valid preferred * language it will be used. * * - Default: Site's language will be used otherwise. * * ### Locale Prefix * * If `url_locale_prefix` option is enabled, and current request's URL is not * language prefixed, user will be redirected to a locale-prefixed version of * the requested URL (using the language code selected as explained above). * * For example: * * /article/demo-article.html * * Might redirects to: * * /en_US/article/demo-article.html * * @param \Cake\Event\Event $event containing the request, response and * additional parameters * @return void * @throws \Cake\Network\Exception\InternalErrorException When no valid request * object could be found */ public function beforeDispatch(Event $event) { parent::beforeDispatch($event); $request = Router::getRequest(); if (empty($request)) { throw new InternalErrorException(__d('cms', 'No request object could be found.')); } $locales = array_keys(quickapps('languages')); $localesPattern = '(' . implode('|', array_map('preg_quote', $locales)) . ')'; $rawUrl = str_replace_once($request->base, '', env('REQUEST_URI')); $normalizedURL = str_replace('//', '/', "/{$rawUrl}"); if (!empty($request->query['locale']) && in_array($request->query['locale'], $locales)) { $request->session()->write('locale', $request->query['locale']); I18n::locale($request->session()->read('locale')); } elseif (option('url_locale_prefix') && preg_match("/\\/{$localesPattern}\\//", $normalizedURL, $matches)) { I18n::locale($matches[1]); } elseif ($request->session()->check('locale') && in_array($request->session()->read('locale'), $locales)) { I18n::locale($request->session()->read('locale')); } elseif ($request->is('userLoggedIn') && in_array(user()->locale, $locales)) { I18n::locale(user()->locale); } elseif (in_array(option('default_language'), $locales)) { I18n::locale(option('default_language')); } else { I18n::locale(CORE_LOCALE); } if (option('url_locale_prefix') && !$request->is('home') && !preg_match("/\\/{$localesPattern}\\//", $normalizedURL)) { $url = Router::url('/' . I18n::locale() . $normalizedURL, true); http_response_code(303); header("Location: {$url}"); die; } }
/** * Constructor. * * @param string $package Package name as string. e.g. `vendor-name/package-name` * @param string $path Full path to package's root directory * @param string $version Package version number */ public function __construct($package, $path, $version = null) { $this->_packageName = $package; list($this->_vendor, $this->_name) = packageSplit($this->_packageName); $this->_version = $version; $this->_path = $path; if (strtolower($this->_packageName) === 'cakephp/cakephp') { $this->_version = Configure::version(); } elseif (strtolower($this->_packageName) === 'quickapps/cms') { $this->_version = quickapps('version'); } }
/** * Gets a list of languages suitable for select boxes. * * @param bool $full Set to true to return the entire list of languages * (from catalog). Set to false (by default) to get a list of installed languages * @param bool $sort Sort languages alphabetically if set to true (by default). * @return void */ public static function languagesList($full = false, $sort = true) { $languages = []; if ($full) { foreach (static::$_catalog as $code => $info) { $languages[$code] = $info['language']; } } else { foreach (quickapps('languages') as $code => $data) { $languages[$code] = $data['name']; } } if ($sort) { asort($languages); } return $languages; }
/** * Constructor. * * We tweak Field UI here, as contents are polymorphic we need to dynamically * change `$_manageTable` property according to `content_type`. * * @param \Cake\Network\Request $request Request object for this controller. Can * be null for testing, but expect that features that use the request * parameters will not work. * @param \Cake\Network\Response $response Response object for this controller. */ public function __construct($request = null, $response = null) { parent::__construct($request, $response); $validTypes = quickapps('content_types'); if (!isset($request->query['type']) || !in_array($request->query['type'], $validTypes)) { $this->redirect(['plugin' => 'System', 'controller' => 'dashboard', 'prefix' => 'admin']); } else { // allows to manage polymorphic entities $this->_bundle = $request->query['type']; // Make $_GET['type'] persistent Router::addUrlFilter(function ($params, $request) { if (isset($request->query['type'])) { $params['type'] = $request->query['type']; } return $params; }); } }
/** * Checks whether a plugins is installed on the system regardless of its status. * * @param string $plugin Plugin to check * @return bool True if exists, false otherwise */ public static function exists($plugin) { $check = quickapps("plugins.{$plugin}"); return !empty($check); }
/** * Displays a header for the shell * * @return void */ protected function _welcome() { if (!defined('QUICKAPPS_CORE')) { return parent::_welcome(); } $this->out(); $this->out(__d('cms', '<info>Welcome to QuickApps CMS v{0} Console</info>', quickapps('version'))); $this->hr(); $this->out(__d('cms', 'Site Title: {0}', option('site_title'))); $this->hr(); $this->out(); }
/** * Tries to get a QuickAppsCMS plugin. * * @param string $package Full package name * @return bool|\CMS\Core\Package\PluginPackage */ protected static function _getPlugin($package) { list(, $plugin) = packageSplit($package, true); if (Plugin::exists($plugin)) { return new PluginPackage(quickapps("plugins.{$plugin}.name"), quickapps("plugins.{$plugin}.path")); } return false; }
/** * Strips language prefix from the given URL. * * For instance, `/en_US/article/my-first-article.html` becomes * `/article/my-first-article.html`. * * @param string $url The URL * @return string New URL */ function stripLanguagePrefix($url) { static $localesPattern = null; if (!$localesPattern) { $locales = array_keys(quickapps('languages')); $localesPattern = '(' . implode('|', array_map('preg_quote', $locales)) . ')'; } $url = preg_replace('/(^|\\/)' . $localesPattern . '\\//', '/', $url); return $url; }
/** * Returns a regular expression that is used to verify if an URL starts * or not with a language prefix. * * ## Example: * * ``` * (en\-us|fr|es|it) * ``` * * @return string */ protected function _localesPattern() { $cacheKey = '_localesPattern'; $cache = static::cache($cacheKey); if ($cache) { return $cache; } $pattern = '(' . implode('|', array_map('preg_quote', array_keys(quickapps('languages')))) . ')'; return static::cache($cacheKey, $pattern); }
/** * Implements the "locale" shortcode. * * {locale code /} * {locale name /} * {locale direction /} * * @param \Cake\Event\Event $event The event that was fired * @param array $atts An associative array of attributes, or an empty string if * no attributes are given * @param string $content The enclosed content (if the shortcode is used in its * enclosing form) * @param string $tag The shortcode tag * @return string */ public function shortcodeLocale(Event $event, array $atts, $content, $tag) { $option = array_keys((array) $atts); $locale = I18n::locale(); $languages = quickapps('languages'); $out = ''; if (!isset($languages[$locale])) { return $out; } if (empty($option)) { $option = 'code'; } else { $option = $option[0]; } if ($info = $languages[$locale]) { switch ($option) { case 'code': $out = $info['code']; break; case 'name': $out = $info['name']; break; case 'direction': $out = $info['direction']; break; } } return $out; }
}); /** * Checks if page being rendered is the dashboard. * * $request->isDashboard(); */ Request::addDetector('dashboard', function ($request) { return !empty($request->params['plugin']) && strtolower($request->params['plugin']) === 'system' && !empty($request->params['controller']) && strtolower($request->params['controller']) === 'dashboard' && !empty($request->params['action']) && strtolower($request->params['action']) === 'index'; }); /** * Checks if current URL is language prefixed. * * $request->isLocalized(); */ Request::addDetector('localized', function ($request) { $locales = array_keys(quickapps('languages')); $localesPattern = '(' . implode('|', array_map('preg_quote', $locales)) . ')'; $url = str_starts_with($request->url, '/') ? str_replace_once('/', '', $request->url) : $request->url; return preg_match("/^{$localesPattern}\\//", $url); }); /** * Checks if visitor user is logged in. * * $request->isUserLoggedIn(); */ Request::addDetector('userLoggedIn', function ($request) { $sessionExists = $request->session()->check('Auth.User.id'); $sessionContent = $request->session()->read('Auth.User.id'); return $sessionExists && !empty($sessionContent); }); /**
<?php /** * Licensed under The GPL-3.0 License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @since 2.0.0 * @author Christopher Castro <*****@*****.**> * @link http://www.quickappscms.org * @license http://opensource.org/licenses/gpl-3.0.html GPL-3.0 License */ use Cake\Routing\Router; use CMS\View\ViewModeRegistry; /** * Register default view-modes */ ViewModeRegistry::add(['default' => ['name' => __d('content', 'Default'), 'description' => __d('content', 'Default is used as a generic view mode if no other view mode has been defined for your content.')], 'teaser' => ['name' => __d('content', 'Teaser'), 'description' => __d('content', 'Teaser is a really short format that is typically used in main the main page, such as "last news", etc.')], 'search-result' => ['name' => __d('content', 'Search Result'), 'description' => __d('content', 'Search Result is a short format that is typically used in lists of multiple content items such as search results.')], 'rss' => ['name' => __d('content', 'RSS'), 'description' => __d('content', 'RSS is similar to "Search Result" but intended to be used when rendering content as part of a RSS feed list.')], 'full' => ['name' => __d('content', 'Full'), 'description' => __d('content', 'Full content is typically used when the content is displayed on its own page.')]]); if (is_array(quickapps('content_types'))) { Router::connect('/:content_type_slug/:content_slug:extension', ['plugin' => 'Content', 'controller' => 'Serve', 'action' => 'details'], ['content_type_slug' => implode('|', array_map('preg_quote', quickapps('content_types'))), 'content_slug' => '.+', 'extension' => preg_quote(CONTENT_EXTENSION), 'pass' => ['content_type_slug', 'content_slug'], '_name' => 'content_details', 'routeClass' => 'Cake\\Routing\\Route\\InflectedRoute']); } Router::connect('/find/:criteria', ['plugin' => 'Content', 'controller' => 'Serve', 'action' => 'search'], ['pass' => ['criteria'], '_name' => 'content_search', 'routeClass' => 'Cake\\Routing\\Route\\InflectedRoute']); Router::connect('/rss/:criteria', ['plugin' => 'Content', 'controller' => 'Serve', 'action' => 'rss'], ['pass' => ['criteria'], '_name' => 'content_search_rss', 'routeClass' => 'Cake\\Routing\\Route\\InflectedRoute']); Router::connect('/', ['plugin' => 'Content', 'controller' => 'Serve', 'action' => 'home'], ['_name' => 'home', 'routeClass' => 'Cake\\Routing\\Route\\InflectedRoute']);
/** * Gets information for this plugin. * * When `$full` is set to true some additional keys will be repent in the * resulting array: * * - `settings`: Plugin's settings info fetched from DB. * - `composer`: Composer JSON information, converted to an array. * - `permissions`: Permissions tree for this plugin, see `PluginPackage::permissions()` * * ### Example: * * Reading full information: * * ```php * $plugin->info(); * * // returns an array as follow: * [ * 'name' => 'User, * 'isTheme' => false, * 'hasHelp' => true, * 'hasSettings' => false, * 'eventListeners' => [ ... ], * 'status' => 1, * 'path' => '/path/to/plugin', * 'settings' => [ ... ], // only when $full = true * 'composer' => [ ... ], // only when $full = true * 'permissions' => [ ... ], // only when $full = true * ] * ``` * * Additionally the first argument, $key, can be used to get an specific value * using a dot syntax path: * * ```php * $plugin->info('isTheme'); * $plugin->info('settings.some_key'); * ``` * * If the given path is not found NULL will be returned * * @param string $key Optional path to read from the resulting array * @return mixed Plugin information as an array if no key is given, or the * requested value if a valid $key was provided, or NULL if $key path is not * found */ public function &info($key = null) { $plugin = $this->name(); if (empty($this->_info)) { $this->_info = (array) quickapps("plugins.{$plugin}"); } $parts = explode('.', $key); $getComposer = in_array('composer', $parts) || $key === null; $getSettings = in_array('settings', $parts) || $key === null; $getPermissions = in_array('permissions', $parts) || $key === null; if ($getComposer && !isset($this->_info['composer'])) { $this->_info['composer'] = $this->composer(); } if ($getSettings && !isset($this->_info['settings'])) { $this->_info['settings'] = (array) $this->settings(); } if ($getPermissions && !isset($this->_info['permissions'])) { $this->_info['permissions'] = (array) $this->permissions(); } if ($key === null) { return $this->_info; } return $this->_getKey($parts); }
/** * Check if a current URL matches any pattern in a set of patterns. * * @param string $patterns String containing a set of patterns separated by * \n, \r or \r\n * @return bool TRUE if the path matches a pattern, FALSE otherwise */ protected function _urlMatch($patterns) { if (empty($patterns)) { return false; } $url = urldecode($this->_View->request->url); $path = str_starts_with($url, '/') ? str_replace_once('/', '', $url) : $url; if (option('url_locale_prefix')) { $patterns = explode("\n", $patterns); $locales = array_keys(quickapps('languages')); $localesPattern = '(' . implode('|', array_map('preg_quote', $locales)) . ')'; foreach ($patterns as &$p) { if (!preg_match("/^{$localesPattern}\\//", $p)) { $p = I18n::locale() . '/' . $p; $p = str_replace('//', '/', $p); } } $patterns = implode("\n", $patterns); } // Convert path settings to a regular expression. // Therefore replace newlines with a logical or, /* with asterisks and "/" with the front page. $toReplace = ['/(\\r\\n?|\\n)/', '/\\\\\\*/', '/(^|\\|)\\/($|\\|)/']; $replacements = ['|', '.*', '\\1' . preg_quote($this->_View->Url->build('/'), '/') . '\\2']; $patternsQuoted = preg_quote($patterns, '/'); $patterns = '/^(' . preg_replace($toReplace, $replacements, $patternsQuoted) . ')$/'; return (bool) preg_match($patterns, $path); }
/** * Gets a list of all active aspect classes. * * @return array */ function aspects() { return quickapps('aspects'); }