diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d45e84..f51a43b7 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +# Flextype 0.3.0, 2018-05-05 +* Using Flextype Components instead of Symphony Components +* Available Flextype Components for developers: Arr, Assets, Cookie, Date, Debug, ErrorHandler, Event, Filesystem, Html, Http, I18n, Notification, Number, Registry, Session, Text, Token, View. +* Using `.yaml` files instead of `.yml` +* Default theme from now is `simple` +* Themes structure is changed. From now main folder for all theme templates and partials is `views` inside theme folder. +* Templates moved to `/simple/views/templates/` and partials moved to `/simple/views/partials/` +* Default template changes from `index.php` to `default.php` +* Plugins templates can be overridden by templates in themes folder. +* For pages we will not use `index.md` anymore. From now page file will have a name `page.md` +* Config class was removed, from now we will use simple powerful Registry Component to access configurations. +* Event, Filter, View class was removed. From now we are using more powerful Flextype Components! +* Fixed issue with getPages() method. +* Twitter Bootstrap updated to 4.1.0 for default theme. +* ErrorHandler added with errors logs. +* Code cleanup and refactoring #5 + # Flextype 0.2.1, 2018-03-26 * date_format setting added to /site/config.site.yml * Pages: Fixed bug with pages sort and slice in getPages() method diff --git a/README.md b/README.md index 34488c50..a624e7dc 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Flextype - + [](https://github.com/flextype/flextype/blob/master/LICENSE.txt) Flextype is next generation of Legendary Monstra Engine it is also Open Source, fast and flexible file-based Content Management System. That's Easy to install, upgrade and use. Flextype provides amazing API's for plugins, themes and core developers! Content in Flextype is just a simple files written with markdown syntax in pages folder. You simply create markdown files in the pages folder and that becomes a page. diff --git a/composer.json b/composer.json index 3171b847..55ce0116 100755 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { "name": "flextype/flextype", "type": "project", - "description": "Flextype is Modern Open Source Flat-File Content Management System", - "keywords": ["Flextype", "php", "cms", "flat-file cms", "flat cms", "flatfile cms", "markdown"], + "description": "Flextype is The Best Open Source Flat-File Content Management System", + "keywords": ["flextype", "php", "cms", "flat-file cms", "flat cms", "flatfile cms", "markdown"], "homepage": "http://flextype.org", "license": "MIT", "authors": [ @@ -19,17 +19,26 @@ "php": ">=7.1.3", "erusev/parsedown": "1.7.0", "erusev/parsedown-extra": "0.7.1", - "doctrine/cache": "1.7.1", - "symfony/yaml": "4.0.4", - "symfony/filesystem": "4.0.4", - "symfony/finder": "4.0.4", - "thunderer/shortcode": "0.6.5", - "force/session" : "*", - "force/arr" : "*", - "force/http" : "*", - "force/token" : "*", - "force/errorhandler" : "*", - "force/url" : "*" + "doctrine/cache": "1.*", + "symfony/yaml": "4.*", + "thunderer/shortcode": "0.*", + "flextype-components/arr" : "1.*", + "flextype-components/assets" : "1.*", + "flextype-components/cookie" : "1.*", + "flextype-components/date" : "1.*", + "flextype-components/debug" : "1.*", + "flextype-components/event" : "1.*", + "flextype-components/errorhandler" : "1.*", + "flextype-components/filesystem" : "1.*", + "flextype-components/i18n" : "1.*", + "flextype-components/http" : "1.*", + "flextype-components/html" : "1.*", + "flextype-components/number" : "1.*", + "flextype-components/notification" : "1.*", + "flextype-components/registry" : "1.*", + "flextype-components/token" : "1.*", + "flextype-components/view" : "1.*", + "flextype-components/text" : "1.*" }, "autoload": { "classmap": [ diff --git a/flextype/Config.php b/flextype/Config.php deleted file mode 100755 index c1cbdef4..00000000 --- a/flextype/Config.php +++ /dev/null @@ -1,106 +0,0 @@ - - * @link http://flextype.org - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flextype; - -use Arr; -use Symfony\Component\Yaml\Yaml; - -class Config -{ - - /** - * An instance of the Config class - * - * @var object - * @access protected - */ - protected static $instance = null; - - /** - * Config - * - * @var array - * @access protected - */ - protected static $config = []; - - /** - * Protected clone method to enforce singleton behavior. - * - * @access protected - */ - protected function __clone() - { - // Nothing here. - } - - /** - * Constructor. - * - * @access protected - */ - protected function __construct() - { - if (Flextype::filesystem()->exists($site_config = CONFIG_PATH . '/' . 'site.yml')) { - static::$config['site'] = Yaml::parse(file_get_contents($site_config)); - } else { - throw new RuntimeException("Flextype site config file does not exist."); - } - } - - /** - * Set new or update existing config variable - * - * @access public - * @param string $key Key - * @param mixed $value Value - */ - public static function set($key, $value) : void - { - Arr::set(static::$config, $key, $value); - } - - /** - * Get config variable - * - * @access public - * @param string $key Key - * @param mixed $default Default value - * @return mixed - */ - public static function get($key, $default = null) - { - return Arr::get(static::$config, $key, $default); - } - - /** - * Get config array - * - * @access public - * @return array - */ - public static function getConfig() : array - { - return static::$config; - } - - /** - * Initialize Flextype Config - * - * @access public - */ - public static function init() - { - return !isset(self::$instance) and self::$instance = new Config(); - } -} diff --git a/flextype/Events.php b/flextype/Events.php deleted file mode 100644 index a4d0ffa4..00000000 --- a/flextype/Events.php +++ /dev/null @@ -1,104 +0,0 @@ - - * @link http://flextype.org - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flextype; - -use Arr; - -class Events -{ - - /** - * Events - * - * @var array - * @access protected - */ - protected static $events = []; - - /** - * Protected constructor since this is a static class. - * - * @access protected - */ - protected function __construct() - { - // Nothing here - } - - /** - * Hooks a function on to a specific event. - * - * @access public - * @param string $event_name Event name - * @param mixed $added_function Added function - * @param integer $priority Priority. Default is 10 - * @param array $args Arguments - * @return void - */ - public static function addListener(string $event_name, $added_function, int $priority = 10, array $args = null) : void - { - // Hooks a function on to a specific event. - static::$events[] = array( - 'event_name' => $event_name, - 'function' => $added_function, - 'priority' => $priority, - 'args' => $args - ); - } - - /** - * Run functions hooked on a specific event. - * - * @access public - * @param string $event_name Event name - * @param array $args Arguments - * @param boolean $return Return data or not. Default is false - * @return mixed - */ - public static function dispatch(string $event_name, array $args = [], bool $return = false) - { - // Redefine arguments - $event_name = $event_name; - $return = $return; - - // Run event - if (count(static::$events) > 0) { - - // Sort actions by priority - $events = Arr::subvalSort(static::$events, 'priority'); - - // Loop through $events array - foreach ($events as $action) { - - // Execute specific action - if ($action['event_name'] == $event_name) { - // isset arguments ? - if (isset($args)) { - // Return or Render specific action results ? - if ($return) { - return call_user_func_array($action['function'], $args); - } else { - call_user_func_array($action['function'], $args); - } - } else { - if ($return) { - return call_user_func_array($action['function'], $action['args']); - } else { - call_user_func_array($action['function'], $action['args']); - } - } - } - } - } - } -} diff --git a/flextype/Filters.php b/flextype/Filters.php deleted file mode 100755 index 6a80a2e8..00000000 --- a/flextype/Filters.php +++ /dev/null @@ -1,114 +0,0 @@ - - * @link http://flextype.org - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flextype; - -class Filters -{ - - /** - * @var Flextype - */ - protected $flextype; - - /** - * Filters - * - * @var array - * @access protected - */ - protected static $filters = []; - - /** - * Protected constructor since this is a static class. - * - * @access protected - */ - protected function __construct() - { - // Nothing here - } - - /** - * Add filter - * - * @access public - * @param string $filter_name The name of the filter to hook the $function_to_add to. - * @param string $function_to_add The name of the function to be called when the filter is applied. - * @param integer $priority Function to add priority - default is 10. - * @param integer $accepted_args The number of arguments the function accept default is 1. - * @return bool - */ - public static function addListener($filter_name, $function_to_add, $priority = 10, $accepted_args = 1) : bool - { - // Redefine arguments - $filter_name = (string) $filter_name; - $function_to_add = $function_to_add; - $priority = (int) $priority; - $accepted_args = (int) $accepted_args; - - // Check that we don't already have the same filter at the same priority. Thanks to WP :) - if (isset(static::$filters[$filter_name]["$priority"])) { - foreach (static::$filters[$filter_name]["$priority"] as $filter) { - if ($filter['function'] == $function_to_add) { - return true; - } - } - } - - static::$filters[$filter_name]["$priority"][] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); - - // Sort - ksort(static::$filters[$filter_name]["$priority"]); - - return true; - } - - /** - * Dispatch filters - * - * @access public - * @param string $filter_name The name of the filter hook. - * @param mixed $value The value on which the filters hooked. - * @return mixed - */ - public static function dispatch(string $filter_name, $value) - { - $args = array_slice(func_get_args(), 2); - - if (! isset(static::$filters[$filter_name])) { - return $value; - } - - foreach (static::$filters[$filter_name] as $priority => $functions) { - if (! is_null($functions)) { - foreach ($functions as $function) { - $all_args = array_merge(array($value), $args); - $function_name = $function['function']; - $accepted_args = $function['accepted_args']; - if ($accepted_args == 1) { - $the_args = array($value); - } elseif ($accepted_args > 1) { - $the_args = array_slice($all_args, 0, $accepted_args); - } elseif ($accepted_args == 0) { - $the_args = null; - } else { - $the_args = $all_args; - } - $value = call_user_func_array($function_name, $the_args); - } - } - } - - return $value; - } -} diff --git a/flextype/Flextype.php b/flextype/Flextype.php index 761709a7..f64fb5a6 100755 --- a/flextype/Flextype.php +++ b/flextype/Flextype.php @@ -12,9 +12,8 @@ namespace Flextype; -use Symfony\Component\{Filesystem\Filesystem, Finder\Finder}; -use Url; -use Session; +use Flextype\Component\{Http\Http, Session\Session, ErrorHandler\ErrorHandler, Registry\Registry, Filesystem\Filesystem}; +use Symfony\Component\Yaml\Yaml; class Flextype { @@ -26,22 +25,6 @@ class Flextype */ protected static $instance = null; - /** - * Filesystem object - * - * @var Filesystem - * @access public - */ - public static $filesystem = null; - - /** - * Finder object - * - * @var Finder - * @access public - */ - public static $finder = null; - /** * Protected clone method to enforce singleton behavior. * @@ -66,30 +49,31 @@ class Flextype */ protected function __construct() { - static::app(); + static::init(); } /** - * Application. + * Init Application * * @access protected */ - protected static function app() : void + protected static function init() : void { - // Init Finder - static::$finder = new Finder(); - - // Init Filesystem - static::$filesystem = new Filesystem(); - - // Init Config - Config::init(); - // Turn on output buffering ob_start(); + // Set empty site item + Registry::set('site', []); + + // Set site items if site config exists + if (Filesystem::fileExists($site_config = CONFIG_PATH . '/' . 'site.yaml')) { + Registry::set('site', Yaml::parseFile($site_config)); + } else { + throw new \RuntimeException("Flextype site config file does not exist."); + } + // Display Errors - if (Config::get('site.errors.display')) { + if (Registry::get('site.errors.display')) { define('DEVELOPMENT', true); error_reporting(-1); } else { @@ -99,71 +83,47 @@ class Flextype // Set internal encoding function_exists('mb_language') and mb_language('uni'); - function_exists('mb_regex_encoding') and mb_regex_encoding(Config::get('site.charset')); - function_exists('mb_internal_encoding') and mb_internal_encoding(Config::get('site.charset')); + function_exists('mb_regex_encoding') and mb_regex_encoding(Registry::get('site.charset')); + function_exists('mb_internal_encoding') and mb_internal_encoding(Registry::get('site.charset')); // Set Error handler - set_error_handler('ErrorHandler::error'); - register_shutdown_function('ErrorHandler::fatal'); - set_exception_handler('ErrorHandler::exception'); + set_error_handler('Flextype\Component\ErrorHandler\ErrorHandler::error'); + register_shutdown_function('Flextype\Component\ErrorHandler\ErrorHandler::fatal'); + set_exception_handler('Flextype\Component\ErrorHandler\ErrorHandler::exception'); // Set default timezone - date_default_timezone_set(Config::get('site.timezone')); + date_default_timezone_set(Registry::get('site.timezone')); // Start the session Session::start(); - // Init Cache - Cache::init(); + // Create Cache Instance + Cache::instance(); - // Init I18n - I18n::init(); + // Create Shortcodes Instance + Shortcodes::instance(); - // Init Shortcodes - Shortcodes::init(); + // Create Themes Instance + Themes::instance(); - // Init Themes - Themes::init(); + // Create Plugins Instance + Plugins::instance(); - // Init Plugins - Plugins::init(); - - // Init Pages - Pages::init(); + // Create Pages Instance + Pages::instance(); // Flush (send) the output buffer and turn off output buffering ob_end_flush(); } /** - * Returns filesystem object + * Return the Flextype instance. + * Create it if it's not already created. * * @access public - * @return Filesystem + * @return object */ - public static function filesystem() : Filesystem - { - return static::$filesystem; - } - - /** - * Returns finder object - * - * @access public - * @return Finder - */ - public static function finder() : Finder - { - return static::$finder; - } - - /** - * Initialize Flextype Application - * - * @access public - * @return object - */ - public static function init() + public static function instance() { return !isset(self::$instance) and self::$instance = new Flextype(); } diff --git a/flextype/I18n.php b/flextype/I18n.php deleted file mode 100644 index 9f73cfc0..00000000 --- a/flextype/I18n.php +++ /dev/null @@ -1,143 +0,0 @@ - - * @link http://flextype.org - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flextype; - -use Symfony\Component\Yaml\Yaml; - -class I18n -{ - /** - * An instance of the I18n class - * - * @var object - */ - protected static $instance = null; - - /** - * Locales array - * - * @var array - */ - public static $locales = [ - 'ar' => 'العربية', - 'bg' => 'Български', - 'ca' => 'Català', - 'cs' => 'Česky', - 'da' => 'Dansk', - 'de' => 'Deutsch', - 'el' => 'Ελληνικά', - 'en' => 'English', - 'es' => 'Español', - 'fa' => 'Farsi', - 'fi' => 'Suomi', - 'fr' => 'Français', - 'gl' => 'Galego', - 'ka-ge' => 'Georgian', - 'hu' => 'Magyar', - 'it' => 'Italiano', - 'id' => 'Bahasa Indonesia', - 'ja' => '日本語', - 'lt' => 'Lietuvių', - 'nl' => 'Nederlands', - 'no' => 'Norsk', - 'pl' => 'Polski', - 'pt' => 'Português', - 'pt-br' => 'Português do Brasil', - 'ru' => 'Русский', - 'sk' => 'Slovenčina', - 'sl' => 'Slovenščina', - 'sv' => 'Svenska', - 'sr' => 'Srpski', - 'tr' => 'Türkçe', - 'uk' => 'Українська', - 'zh-cn' => '简体中文', - ]; - - /** - * Dictionary - * - * @var array - */ - public static $dictionary = []; - - /** - * Protected clone method to enforce singleton behavior. - * - * @access protected - */ - protected function __clone() - { - // Nothing here. - } - - /** - * Construct - */ - protected function __construct() - { - - // Get Plugins and Site Locales list - (array) $plugins_list = Config::get('site.plugins'); - (array) $locales = Config::get('site.locales'); - (array) $dictionary = []; - - // Create dictionary - if (is_array($plugins_list) && count($plugins_list) > 0) { - foreach ($locales as $locale) { - foreach ($plugins_list as $plugin) { - $language_file = PLUGINS_PATH . '/' . $plugin . '/languages/' . $locale . '.yml'; - if (file_exists($language_file)) { - $dictionary[$plugin][$locale] = Yaml::parse(file_get_contents($language_file)); - } - } - } - } - - // Save dictionary - static::$dictionary = $dictionary; - } - - /** - * Returns translation of a string. If no translation exists, the original - * string will be returned. No parameters are replaced. - * - * @param string $string Text to translate - * @param string $namespace Namespace - * @param string $locale Locale - * @return string - */ - public static function find(string $string, string $namespace, string $locale, array $values = []) : string - { - // Search current string to translate in the Dictionary - if (isset(static::$dictionary[$namespace][$locale][$string])) { - $string = static::$dictionary[$namespace][$locale][$string]; - $string = empty($values) ? $string : strtr($string, $values); - } else { - $string = $string; - } - - // Return translation of a string - return $string; - } - - /** - * Initialize Flextype I18n - * - * @access public - * @return object - */ - public static function init() - { - return !isset(self::$instance) and self::$instance = new I18n(); - } -} diff --git a/flextype/Pages.php b/flextype/Pages.php index 942a4468..fe521619 100755 --- a/flextype/Pages.php +++ b/flextype/Pages.php @@ -12,9 +12,7 @@ namespace Flextype; -use Arr; -use Url; -use Response; +use Flextype\Component\{Arr\Arr, Http\Http, Filesystem\Filesystem, Event\Event, Registry\Registry}; use Symfony\Component\Yaml\Yaml; class Pages @@ -34,23 +32,37 @@ class Pages public static $page; /** - * Constructor + * Protected constructor since this is a static class. * * @access protected */ protected function __construct() + { + static::init(); + } + + /** + * Init Pages + * + * @access protected + * @return void + */ + protected static function init() : void { // The page is not processed and not sent to the display. - Events::dispatch('onPageBeforeRender'); + Event::dispatch('onPageBeforeRender'); + + // Add parseContent on content event + Event::addListener('content', 'Flextype\Pages::parseContent'); // Get current page - static::$page = static::getPage(Url::getUriString()); + static::$page = static::getPage(Http::getUriString()); // Display page for current requested url static::renderPage(static::$page); // The page has been fully processed and sent to the display. - Events::dispatch('onPageAfterRender'); + Event::dispatch('onPageAfterRender'); } /** @@ -66,22 +78,22 @@ class Pages if ($url) { $file = $url; } else { - $file = PAGES_PATH . '/' . Config::get('site.pages.main') . '/' . 'index.md'; + $file = PAGES_PATH . '/' . Registry::get('site.pages.main') . '/' . 'page.md'; } } else { if ($url) { - $file = PAGES_PATH . '/' . $url . '/index.md'; + $file = PAGES_PATH . '/' . $url . '/page.md'; } else { - $file = PAGES_PATH . '/' . Config::get('site.pages.main') . '/' . 'index.md'; + $file = PAGES_PATH . '/' . Registry::get('site.pages.main') . '/' . 'page.md'; } } // Get 404 page if file not exists - if (Flextype::filesystem()->exists($file)) { + if (Filesystem::fileExists($file)) { $file = $file; } else { - $file = PAGES_PATH . '/404/index.md'; - Response::status(404); + $file = PAGES_PATH . '/404/page.md'; + Http::setResponseStatus(404); } return $file; @@ -92,16 +104,9 @@ class Pages */ public static function renderPage(array $page) { - $template_ext = '.php'; - $template_name = empty($page['template']) ? 'index' : $page['template']; - $site_theme = Config::get('site.theme'); - $template_path = THEMES_PATH . '/' . $site_theme . '/' . $template_name . $template_ext; - - if (Flextype::filesystem()->exists($template_path)) { - include $template_path; - } else { - throw new RuntimeException("Template {$template_name} does not exist."); - } + Themes::template(empty($page['template']) ? 'templates/default' : 'templates/' . $page['template']) + ->assign('page', $page, true) + ->display(); } /** @@ -109,33 +114,33 @@ class Pages */ public static function parseFile(string $file) : array { - $page = trim(file_get_contents($file)); + $page = trim(Filesystem::getFileContent($file)); $page = explode('---', $page, 3); $frontmatter = Shortcodes::driver()->process($page[1]); $result_page = Yaml::parse($frontmatter); // Get page url - $url = str_replace(PAGES_PATH, Url::getBase(), $file); - $url = str_replace('index.md', '', $url); + $url = str_replace(PAGES_PATH, Http::getBaseUrl(), $file); + $url = str_replace('page.md', '', $url); $url = str_replace('.md', '', $url); $url = str_replace('\\', '/', $url); $url = str_replace('///', '/', $url); $url = str_replace('//', '/', $url); $url = str_replace('http:/', 'http://', $url); $url = str_replace('https:/', 'https://', $url); - $url = str_replace('/'.Config::get('site.pages.main'), '', $url); + $url = str_replace('/'.Registry::get('site.pages.main'), '', $url); $url = rtrim($url, '/'); $result_page['url'] = $url; // Get page slug - $url = str_replace(Url::getBase(), '', $url); + $url = str_replace(Http::getBaseUrl(), '', $url); $url = ltrim($url, '/'); $url = rtrim($url, '/'); - $result_page['slug'] = str_replace(Url::getBase(), '', $url); + $result_page['slug'] = str_replace(Http::getBaseUrl(), '', $url); // Set page date - $result_page['date'] = $result_page['date'] ?? date(Config::get('site.date_format'), filemtime($file)); + $result_page['date'] = $result_page['date'] ?? date(Registry::get('site.date_format'), filemtime($file)); // Set page content $result_page['content'] = $page[2]; @@ -153,14 +158,14 @@ class Pages $file = static::finder($url, $url_abs); if ($raw) { - $page = trim(file_get_contents($file)); + $page = trim(Filesystem::getFileContent($file)); static::$page = $page; - Events::dispatch('onPageContentRawAfter'); + Event::dispatch('onPageContentRawAfter'); } else { $page = static::parseFile($file); static::$page = $page; - static::$page['content'] = Filters::dispatch('content', static::parseContent(static::$page['content'])); - Events::dispatch('onPageContentAfter'); + static::$page['content'] = Event::dispatch('content', ['content' => static::$page['content']], true); + Event::dispatch('onPageContentAfter'); } return static::$page; @@ -193,24 +198,24 @@ class Pages if ($url == '') { // Get pages list - $pages_list = Flextype::finder()->files()->name('*.md')->in(PAGES_PATH); + $pages_list = Filesystem::getFilesList(PAGES_PATH, 'md'); // Create pages array from pages list foreach ($pages_list as $key => $page) { - $pages[$key] = static::getPage($page->getPathname(), $raw, true); + $pages[$key] = static::getPage($page, $raw, true); } } else { // Get pages list - $pages_list = Flextype::finder()->files()->name('*.md')->in(PAGES_PATH . '/' . $url); + $pages_list = Filesystem::getFilesList(PAGES_PATH . '/' . $url, 'md'); // Create pages array from pages list and ignore current requested page foreach ($pages_list as $key => $page) { - if (strpos($page->getPathname(), $url.'/index.md') !== false) { + if (strpos($page, $url.'/page.md') !== false) { // ignore ... } else { - $pages[$key] = static::getPage($page->getPathname(), $raw, true); + $pages[$key] = static::getPage($page, $raw, true); } } @@ -218,7 +223,7 @@ class Pages // Sort and Slice pages if $raw === false if (!$raw) { - $pages = Arr::subvalSort($pages, $order_by, $order_type); + $pages = Arr::sort($pages, $order_by, $order_type); if ($offset !== null && $length !== null) { $pages = array_slice($pages, $offset, $length); @@ -230,12 +235,13 @@ class Pages } /** - * Initialize Flextype Pages + * Return the Pages instance. + * Create it if it's not already created. * * @access public * @return object */ - public static function init() + public static function instance() { return !isset(self::$instance) and self::$instance = new Pages(); } diff --git a/flextype/Plugins.php b/flextype/Plugins.php index 66e74c9f..70fec038 100755 --- a/flextype/Plugins.php +++ b/flextype/Plugins.php @@ -12,6 +12,7 @@ namespace Flextype; +use Flextype\Component\{Filesystem\Filesystem, Event\Event, I18n\I18n, Registry\Registry}; use Symfony\Component\Yaml\Yaml; class Plugins @@ -24,11 +25,62 @@ class Plugins protected static $instance = null; /** - * Init Plugins + * Locales array * - * @access public + * @var array + */ + public static $locales = [ + 'ar' => 'العربية', + 'bg' => 'Български', + 'ca' => 'Català', + 'cs' => 'Česky', + 'da' => 'Dansk', + 'de' => 'Deutsch', + 'el' => 'Ελληνικά', + 'en' => 'English', + 'es' => 'Español', + 'fa' => 'Farsi', + 'fi' => 'Suomi', + 'fr' => 'Français', + 'gl' => 'Galego', + 'ka-ge' => 'Georgian', + 'hu' => 'Magyar', + 'it' => 'Italiano', + 'id' => 'Bahasa Indonesia', + 'ja' => '日本語', + 'lt' => 'Lietuvių', + 'nl' => 'Nederlands', + 'no' => 'Norsk', + 'pl' => 'Polski', + 'pt' => 'Português', + 'pt-br' => 'Português do Brasil', + 'ru' => 'Русский', + 'sk' => 'Slovenčina', + 'sl' => 'Slovenščina', + 'sv' => 'Svenska', + 'sr' => 'Srpski', + 'tr' => 'Türkçe', + 'uk' => 'Українська', + 'zh-cn' => '简体中文', + ]; + + /** + * Protected constructor since this is a static class. + * + * @access protected */ protected function __construct() + { + static::init(); + } + + /** + * Init Plugins + * + * @access protected + * @return void + */ + protected static function init() : void { // Plugin manifest $plugin_manifest = []; @@ -37,14 +89,17 @@ class Plugins $plugins_cache_id = ''; // Get Plugins List - $plugins_list = Config::get('site.plugins'); + $plugins_list = Registry::get('site.plugins'); + + // Set empty plugins item + Registry::set('plugins', []); // If Plugins List isnt empty then create plugin cache ID if (is_array($plugins_list) && count($plugins_list) > 0) { // Go through... foreach ($plugins_list as $plugin) { - if (Flextype::filesystem()->exists($_plugin = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yml')) { + if (Filesystem::fileExists($_plugin = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yaml')) { $plugins_cache_id .= filemtime($_plugin); } } @@ -55,7 +110,7 @@ class Plugins // Get plugins list from cache or scan plugins folder and create new plugins cache item if (Cache::driver()->contains($plugins_cache_id)) { - Config::set('plugins', Cache::driver()->fetch($plugins_cache_id)); + Registry::set('plugins', Cache::driver()->fetch($plugins_cache_id)); } else { // If Plugins List isnt empty @@ -64,37 +119,50 @@ class Plugins // Go through... foreach ($plugins_list as $plugin) { - if (Flextype::filesystem()->exists($_plugin_manifest = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yml')) { + if (Filesystem::fileExists($_plugin_manifest = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yaml')) { $plugin_manifest = Yaml::parseFile($_plugin_manifest); } - $_plugins_config[basename($_plugin_manifest, '.yml')] = $plugin_manifest; + $_plugins_config[basename($_plugin_manifest, '.yaml')] = $plugin_manifest; } - Config::set('plugins', $_plugins_config); + Registry::set('plugins', $_plugins_config); Cache::driver()->save($plugins_cache_id, $_plugins_config); } } + // Create dictionary + if (is_array($plugins_list) && count($plugins_list) > 0) { + foreach (static::$locales as $locale => $locale_title) { + foreach ($plugins_list as $plugin) { + $language_file = PLUGINS_PATH . '/' . $plugin . '/languages/' . $locale . '.yaml'; + if (Filesystem::fileExists($language_file)) { + I18n::add($plugin, $locale, Yaml::parseFile($language_file)); + } + } + } + } + // Include enabled plugins - if (is_array(Config::get('plugins')) && count(Config::get('plugins')) > 0) { - foreach (Config::get('plugins') as $plugin_name => $plugin) { - if (Config::get('plugins.'.$plugin_name.'.enabled')) { + if (is_array(Registry::get('plugins')) && count(Registry::get('plugins')) > 0) { + foreach (Registry::get('plugins') as $plugin_name => $plugin) { + if (Registry::get('plugins.'.$plugin_name.'.enabled')) { include_once PLUGINS_PATH .'/'. $plugin_name .'/'. $plugin_name . '.php'; } } } - Events::dispatch('onPluginsInitialized'); + Event::dispatch('onPluginsInitialized'); } /** - * Initialize Flextype Plugins + * Return the Plugins instance. + * Create it if it's not already created. * * @access public * @return object */ - public static function init() + public static function instance() { return !isset(self::$instance) and self::$instance = new Plugins(); } diff --git a/flextype/Shortcodes.php b/flextype/Shortcodes.php index 089b70a6..7b8036d4 100644 --- a/flextype/Shortcodes.php +++ b/flextype/Shortcodes.php @@ -13,7 +13,7 @@ namespace Flextype; use Thunder\Shortcode\ShortcodeFacade; -use Url; +use Flextype\Component\Http\Http; class Shortcodes { @@ -38,6 +38,17 @@ class Shortcodes * @access protected */ protected function __construct() + { + static::init(); + } + + /** + * Init Shortcodes + * + * @access protected + * @return void + */ + protected static function init() : void { // Set driver static::$driver = new ShortcodeFacade(); @@ -65,17 +76,18 @@ class Shortcodes protected static function registerDefaultShortcodes() : void { static::driver()->addHandler('site_url', function() { - return Url::getBase(); + return Http::getBaseUrl(); }); } /** - * Initialize Flextype Shortcodes + * Return the Shortcodes instance. + * Create it if it's not already created. * * @access public * @return object */ - public static function init() + public static function instance() { return !isset(self::$instance) and self::$instance = new Shortcodes(); } diff --git a/flextype/Templates.php b/flextype/Templates.php deleted file mode 100644 index 35a154ca..00000000 --- a/flextype/Templates.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @link http://flextype.org - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flextype; - -class Templates -{ - - /** - * Protected constructor since this is a static class. - * - * @access protected - */ - protected function __construct() - { - // Nothing here - } - - /** - * Get Themes template - * - * @access public - * @param string $template_name Template name - * @return mixed - */ - public static function display(string $template_name) - { - $template_ext = '.php'; - - $page = Pages::$page; - - $template_path = THEMES_PATH . '/' . Config::get('site.theme') . '/' . $template_name . $template_ext; - - if (Flextype::filesystem()->exists($template_path)) { - include $template_path; - } else { - throw new RuntimeException("Template {$template_name} does not exist."); - } - } -} diff --git a/flextype/Themes.php b/flextype/Themes.php index 5478ab8e..457cc320 100644 --- a/flextype/Themes.php +++ b/flextype/Themes.php @@ -12,6 +12,7 @@ namespace Flextype; +use Flextype\Component\{Filesystem\Filesystem, View\View, Registry\Registry}; use Symfony\Component\Yaml\Yaml; class Themes @@ -24,32 +25,80 @@ class Themes protected static $instance = null; /** - * Init Themes + * Protected constructor since this is a static class. * - * @access public - * @return mixed + * @access protected */ protected function __construct() + { + static::init(); + } + + /** + * Init Themes + * + * @access protected + * @return void + */ + protected static function init() : void { // Theme Manifest $theme_manifest = []; - // Get current theme - $theme = Config::get('site.theme'); + // Theme cache id + $theme_cache_id = ''; - if (Flextype::filesystem()->exists($theme_manifest_file = THEMES_PATH . '/' . $theme . '/' . $theme . '.yml')) { - $theme_manifest = Yaml::parseFile($theme_manifest_file); - Config::set('themes.'.Config::get('site.theme'), $theme_manifest); + // Get current theme + $theme = Registry::get('site.theme'); + + // Set empty theme item + Registry::set('theme', []); + + // Create Unique Cache ID for Theme + $theme_cache_id = md5('theme' . THEMES_PATH . $theme); + + if (Cache::driver()->contains($theme_cache_id)) { + Registry::set('themes.'.Registry::get('site.theme'), Cache::driver()->fetch($theme_cache_id)); + } else { + if (Filesystem::fileExists($theme_manifest_file = THEMES_PATH . '/' . $theme . '/' . $theme . '.yaml')) { + $theme_manifest = Yaml::parseFile($theme_manifest_file); + Registry::set('themes.'.Registry::get('site.theme'), $theme_manifest); + Cache::driver()->save($theme_cache_id, $theme_manifest); + } } } /** - * Initialize Flextype Themes + * Return the Themes instance. + * Create it if it's not already created. + * + * @param string $template Template file + * @param string $variables Variables + * @access public + * @return object + */ + public static function template(string $template, array $variables = []) + { + // Set view file + // From current theme folder or from plugin folder + if (Filesystem::fileExists(THEMES_PATH . '/' . Registry::get('site.theme') . '/views/' . $template . View::$view_ext)) { + $template = THEMES_PATH . '/' . Registry::get('site.theme') . '/views/' . $template; + } else { + $template = PLUGINS_PATH . '/views/' . $template; + } + + // Return template + return new View($template, $variables); + } + + /** + * Return the Themes instance. + * Create it if it's not already created. * * @access public * @return object */ - public static function init() + public static function instance() { return !isset(self::$instance) and self::$instance = new Themes(); } diff --git a/flextype/boot/defines.php b/flextype/boot/defines.php index b76a107c..3c8a1bec 100755 --- a/flextype/boot/defines.php +++ b/flextype/boot/defines.php @@ -35,3 +35,6 @@ define('CACHE_PATH', SITE_PATH . '/cache'); // Define the path to the logs directory (without trailing slash). define('LOGS_PATH', SITE_PATH . '/logs'); + +// Define the path to the logs directory (without trailing slash). +define('ACCOUNTS_PATH', SITE_PATH . '/accounts'); diff --git a/index.php b/index.php index 4ab0274a..39414efe 100755 --- a/index.php +++ b/index.php @@ -25,4 +25,4 @@ version_compare($ver = PHP_VERSION, $req = FLEXTYPE_MINIMUM_PHP, '<') and exit(s $loader = require_once $autoload; // Init Flextype -Flextype::init(); +Flextype::instance(); diff --git a/site/config/site.yml b/site/config/site.yaml similarity index 92% rename from site/config/site.yml rename to site/config/site.yaml index 7d83a7cd..977c7f17 100755 --- a/site/config/site.yml +++ b/site/config/site.yaml @@ -11,12 +11,11 @@ timezone: UTC date_format: "F d Y H:i:s." charset: UTF-8 -theme: default +theme: simple plugins: locale: "en" -locales: [en] pages: flush_cache: false diff --git a/site/pages/404/index.md b/site/pages/404/page.md similarity index 100% rename from site/pages/404/index.md rename to site/pages/404/page.md diff --git a/site/pages/home/index.md b/site/pages/home/page.md similarity index 76% rename from site/pages/home/index.md rename to site/pages/home/page.md index f06c5911..2a772ce1 100755 --- a/site/pages/home/index.md +++ b/site/pages/home/page.md @@ -1,14 +1,14 @@ --- title: Welcome description: Flextype is a simple and light-weighted Content Management System -template: index +template: default --- ## Flextype is succesfully installed! You can start editing the content and customising your site. ### Edit this Page -To edit this page, simply go to the folder you installed Flextype, and then browse to the `/site/pages/home/` folder and open the `index.md` file in your editor. +To edit this page, simply go to the folder you installed Flextype, and then browse to the `/site/pages/home/` folder and open the `page.md` file in your editor. ### Create a New page Creating a new page is very simple in Flextype. @@ -24,6 +24,7 @@ Creating a new page is very simple in Flextype. This is the body of **My New Page** ``` -2. Save this file in the `/site/pages/my-new-page/` folder as `index.md` and its will be available by this url: [site_url]/my-new-page +2. Save this file in the `/site/pages/my-new-page/` folder as `page.md` and its will be available by this url: [site_url]/my-new-page + That is it! diff --git a/site/themes/default/index.php b/site/themes/default/index.php deleted file mode 100755 index f368db90..00000000 --- a/site/themes/default/index.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/site/themes/default/partials/head.php b/site/themes/default/partials/head.php deleted file mode 100755 index c0ca14e2..00000000 --- a/site/themes/default/partials/head.php +++ /dev/null @@ -1,24 +0,0 @@ - - -
- - - - - - - -