1
0
mirror of https://github.com/flextype/flextype.git synced 2025-08-08 14:16:46 +02:00

Merge pull request #17 from flextype/dev

Dev
This commit is contained in:
Sergey Romanenko
2018-05-17 13:41:36 +03:00
committed by GitHub
29 changed files with 765 additions and 548 deletions

View File

@@ -1,3 +1,16 @@
# Flextype 0.4.0, 2018-05-16
* Using SCSS for Simple theme
* Using Flextype Form Component
* Themes: class bug fixes
* Plugins: access for $locales changed to private
* Plugins: cache bug fixes
* New powerful Content class added for working with content instead of Pages, Shortcode, Markdown
* Content: new page field: `published` added
* Content: method for page blocks added
* Content: cache added for pages and blocks
* define CONSTANTS in PHP7 style
* Themes: changing from template() to view()
# 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.

View File

@@ -1,5 +1,5 @@
# Flextype
![version](https://img.shields.io/badge/version-0.3.0-brightgreen.svg?style=flat-square "Version")
![version](https://img.shields.io/badge/version-0.4.0-brightgreen.svg?style=flat-square "Version")
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](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.
@@ -25,6 +25,13 @@ You can easily install Flextype with Composer.
composer create-project flextype/flextype
```
Also you may need to install node_modules libs for default Simple Theme
```
cd /flextype/site/themes/simple
npm install
```
## Contributing
1. Help on the [Forum.](http://forum.flextype.org)
2. Develop a new plugin.

View File

@@ -30,6 +30,7 @@
"flextype-components/event" : "1.*",
"flextype-components/errorhandler" : "1.*",
"flextype-components/filesystem" : "1.*",
"flextype-components/form" : "1.*",
"flextype-components/i18n" : "1.*",
"flextype-components/http" : "1.*",
"flextype-components/html" : "1.*",
@@ -43,9 +44,6 @@
"autoload": {
"classmap": [
"flextype"
],
"files": [
"flextype/boot/defines.php"
]
}
}

View File

@@ -84,7 +84,7 @@ class Cache
static::$now = time();
// Create cache key to allow invalidate all cache on configuration changes.
static::$key = (Registry::get('site.cache.prefix') ?? 'flextype') . '-' . md5(ROOT_DIR . Flextype::VERSION);
static::$key = (Registry::get('site.cache.prefix') ?? 'flextype') . '-' . md5(PATH['site'] . Flextype::VERSION);
// Get Cache Driver
static::$driver = static::getCacheDriver();
@@ -166,7 +166,7 @@ class Cache
break;
default:
// Create doctrine cache directory if its not exists
!Filesystem::fileExists($cache_directory = CACHE_PATH . '/doctrine/') and Filesystem::createDir($cache_directory);
!Filesystem::fileExists($cache_directory = PATH['cache'] . '/doctrine/') and Filesystem::createDir($cache_directory);
$driver = new DoctrineCache\FilesystemCache($cache_directory);
break;
}
@@ -243,7 +243,7 @@ class Cache
function_exists('opcache_reset') and @opcache_reset();
// Remove cache dir
Filesystem::deleteDir(CACHE_PATH . '/doctrine/');
Filesystem::deleteDir(PATH['cache'] . '/doctrine/');
}
/**

470
flextype/Content.php Executable file
View File

@@ -0,0 +1,470 @@
<?php
/**
* @package Flextype
*
* @author Sergey Romanenko <awilum@yandex.ru>
* @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 Flextype\Component\{Arr\Arr, Http\Http, Filesystem\Filesystem, Event\Event, Registry\Registry};
use Symfony\Component\Yaml\Yaml;
use Thunder\Shortcode\ShortcodeFacade;
use Thunder\Shortcode\Shortcode\ShortcodeInterface;
use ParsedownExtra as Markdown;
class Content
{
/**
* An instance of the Cache class
*
* @var object
* @access protected
*/
protected static $instance = null;
/**
* Markdown Object
*
* @var object
* @access private
*/
private static $markdown = null;
/**
* Shortcode object
*
* @var object
* @access private
*/
private static $shortcode = null;
/**
* Current page data array
*
* @var array
* @access protected
*/
private static $page = [];
/**
* 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
{
// Event: The page is not processed and not sent to the display.
Event::dispatch('onPageBeforeRender');
// Create Markdown Parser object
Content::$markdown = new Markdown();
// Create Shortcode Parser object
Content::$shortcode = new ShortcodeFacade();
// Register default shortcodes
Content::registerDefaultShortcodes();
// Set current requested page data to $page array
Content::$page = Content::getPage(Http::getUriString());
// Display page for current requested url
Content::displayCurrentPage();
// Event: The page has been fully processed and sent to the display.
Event::dispatch('onPageAfterRender');
}
/**
* Get current page
*
* $page = Content::getCurrentPage();
*
* @access public
* @return array
*/
public static function getCurrentPage() : array
{
return Content::$page;
}
/**
* Update current page
*
* Content::updateCurrentPage('title', 'New page title');
*
* @access public
* @param string $path Array path
* @param mixed $value Value to set
* @return void
*/
public static function updateCurrentPage(string $path, $value) : void
{
Arr::set(Content::$page, $path, $value);
}
/**
* Get page
*
* $page = Content::getPage('projects');
*
* @access public
* @param string $url Page url
* @param bool $raw Raw or not raw content
* @return array|string
*/
public static function getPage(string $url = '', bool $raw = false)
{
// if $url is empty then set path for defined main page
if ($url === '') {
$file_path = PATH['pages'] . '/' . Registry::get('site.pages.main') . '/page.md';
} else {
$file_path = PATH['pages'] . '/' . $url . '/page.md';
}
$page_cache_id = '';
// Page cache id
if (Filesystem::fileExists($file_path)) {
$page_cache_id = md5('page' . filemtime($file_path) . (($raw === true) ? 'true' : 'false'));
}
// Try to get page from cache
if (Cache::driver()->contains($page_cache_id)) {
return Cache::driver()->fetch($page_cache_id);
} else {
// Get 404 page if page file is not exists
if (Filesystem::fileExists($file_path)) {
$file_path = $file_path;
} else {
if (Filesystem::fileExists($file_path = PATH['pages'] . '/404/page.md')) {
$file_path = $file_path;
Http::setResponseStatus(404);
} else {
throw new \RuntimeException("404 page file does not exist.");
}
}
// Get raw page if $raw is true
if ($raw) {
Content::$page = Content::processPage($file_path, true);
Event::dispatch('onPageContentRawAfter');
} else {
Content::$page = Content::processPage($file_path);
Event::dispatch('onPageContentAfter');
// Get 404 page if page is not published
if (isset(Content::$page['published']) && Content::$page['published'] === false) {
if (Filesystem::fileExists($file_path = PATH['pages'] . '/404/page.md')) {
Content::$page = Content::processPage($file_path);
Http::setResponseStatus(404);
} else {
throw new \RuntimeException("404 page file does not exist.");
}
}
}
Cache::driver()->save($page_cache_id, Content::$page);
return Content::$page;
}
}
/**
* Get pages
*
* $pages = Content::getPages('projects');
*
* @access public
* @param string $url Page url
* @param bool $raw Raw or not raw content
* @param string $order_by Order type
* @param int $offset Offset
* @param int $length Length
* @return array
*/
public static function getPages(string $url = '', bool $raw = false, string $order_by = 'date', string $order_type = 'DESC', int $offset = null, int $length = null) : array
{
// if $url is empty then set path for defined main page
if ($url === '') {
$file_path = PATH['pages'] . '/';
} else {
$file_path = PATH['pages'] . '/' . $url;
}
// Page cache id
$pages_cache_id = md5('pages' . $file_path . (($raw === true) ? 'true' : 'false') . $order_by . $order_type . $offset . $length);
// Try to get pages from cache
if (Cache::driver()->contains($pages_cache_id)) {
return Cache::driver()->fetch($pages_cache_id);
} else {
// Pages array where founded pages will stored
$pages = [];
// Get pages for $url
// If $url is empty then we want to have a list of pages for /pages dir.
if ($url === '') {
// Get pages list
$pages_list = Filesystem::getFilesList($file_path , 'md');
// Create pages array from pages list
foreach ($pages_list as $key => $page) {
$pages[$key] = Content::processPage($page, $raw);
}
} else {
// Get pages list
$pages_list = Filesystem::getFilesList($file_path, 'md');
// Create pages array from pages list and ignore current requested page
foreach ($pages_list as $key => $page) {
if (strpos($page, $url . '/page.md') !== false) {
// ignore ...
} else {
$pages[$key] = Content::processPage($page, $raw);
}
}
}
// Sort and Slice pages if $raw === false
if (!$raw) {
$pages = Arr::sort($pages, $order_by, $order_type);
if ($offset !== null && $length !== null) {
$pages = array_slice($pages, $offset, $length);
}
}
Cache::driver()->save($pages_cache_id, $pages);
// Return pages array
return $pages;
}
}
/**
* Get block
*
* $block = Content::getBlock('block-name');
*
* @access public
* @param string $block_name Block name
* @param bool $raw Raw or not raw content
* @return string
*/
public static function getBlock($block_name, $raw = false) : string
{
$block_path = PATH['blocks'] . '/' . $block_name . '.md';
// Block cache id
$block_cache_id = '';
if (Filesystem::fileExists($block_path)) {
$block_cache_id = md5('block' . filemtime($block_path) . (($raw === true) ? 'true' : 'false'));
}
// Try to get block from cache
if (Cache::driver()->contains($block_cache_id)) {
return Cache::driver()->fetch($block_cache_id);
} else {
if (Filesystem::fileExists($block_path)) {
$content = Filesystem::getFileContent($block_path);
if ($raw === false) {
$content = Content::processContent($content);
}
Cache::driver()->save($block_cache_id, $content);
return $content;
} else {
throw new \RuntimeException("Block does not exist.");
}
}
}
/**
* Returns $shortcode object
*
* @access public
* @return object
*/
public static function shortcode() : ShortcodeFacade
{
return Content::$shortcode;
}
/**
* Process page
*
* $page = Content::processPage(PATH['pages'] . '/home/page.md');
*
* @access public
* @param string $file_path File path
* @param string $raw Raw or not raw content
* @return array|string
*/
public static function processPage(string $file_path, bool $raw = false)
{
// Get page from file
$page = trim(Filesystem::getFileContent($file_path));
// Return raw page if $raw is true
if ($raw) {
return $page;
} else {
// Create $page_frontmatter and $page_content
$page = explode('---', $page, 3);
$page_frontmatter = $page[1];
$page_content = $page[2];
// Create empty $_page
$_page = [];
// Process $page_frontmatter with YAML and Shortcodes parsers
$_page = Yaml::parse(Content::processShortcodes($page_frontmatter));
// Create page url item
$url = str_replace(PATH['pages'] , Http::getBaseUrl(), $file_path);
$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('/'.Registry::get('site.pages.main'), '', $url);
$url = rtrim($url, '/');
$_page['url'] = $url;
// Create page slug item
$url = str_replace(Http::getBaseUrl(), '', $url);
$url = ltrim($url, '/');
$url = rtrim($url, '/');
$_page['slug'] = str_replace(Http::getBaseUrl(), '', $url);
// Create page date item
$_page['date'] = $result_page['date'] ?? date(Registry::get('site.date_format'), filemtime($file_path));
// Create page content item with $page_content
$_page['content'] = Content::processContent($page_content);
// Return page
return $_page;
}
}
/**
* Process shortcodes
*
* $content = Content::processShortcodes($content);
*
* @access public
* @param string $content Content to parse
* @return string
*/
public static function processShortcodes(string $content) : string
{
return Content::shortcode()->process($content);
}
/**
* Process markdown
*
* $content = Content::processMarkdown($content);
*
* @access public
* @param string $content Content to parse
* @return string
*/
public static function processMarkdown(string $content) : string
{
return Content::$markdown->text($content);
}
/**
* Process content with markdown and shortcodes processors
*
* $content = Content::processContent($content);
*
* @access public
* @param string $content Content to parse
* @return string
*/
public static function processContent(string $content) : string
{
$content = Content::processShortcodes($content);
$content = Content::processMarkdown($content);
return $content;
}
/**
* Register default shortcodes
*
* @access protected
* @return void
*/
protected static function registerDefaultShortcodes() : void
{
Content::shortcode()->addHandler('site_url', function() {
return Http::getBaseUrl();
});
Content::shortcode()->addHandler('block', function(ShortcodeInterface $s) {
return Content::getBlock($s->getParameter('name'), (($s->getParameter('raw') === 'true') ? true : false));
});
Content::shortcode()->addHandler('registry', function(ShortcodeInterface $s) {
return Registry::get($s->getParameter('item'));
});
}
/**
* Display current page
*
* @access protected
* @return void
*/
protected static function displayCurrentPage() : void
{
Themes::view(empty(Content::$page['template']) ? 'templates/default' : 'templates/' . Content::$page['template'])
->assign('page', Content::$page, true)
->display();
}
/**
* Return the Content instance.
* Create it if it's not already created.
*
* @access public
* @return object
*/
public static function instance()
{
return !isset(self::$instance) and self::$instance = new Content();
}
}

View File

@@ -40,7 +40,7 @@ class Flextype
*
* @var string
*/
const VERSION = '0.3.0';
const VERSION = '0.4.0';
/**
* Constructor.
@@ -66,7 +66,7 @@ class Flextype
Registry::set('site', []);
// Set site items if site config exists
if (Filesystem::fileExists($site_config = CONFIG_PATH . '/' . 'site.yaml')) {
if (Filesystem::fileExists($site_config = PATH['config'] . '/' . 'site.yaml')) {
Registry::set('site', Yaml::parseFile($site_config));
} else {
throw new \RuntimeException("Flextype site config file does not exist.");
@@ -100,17 +100,14 @@ class Flextype
// Create Cache Instance
Cache::instance();
// Create Shortcodes Instance
Shortcodes::instance();
// Create Themes Instance
Themes::instance();
// Create Plugins Instance
Plugins::instance();
// Create Pages Instance
Pages::instance();
// Create Content Instance
Content::instance();
// Flush (send) the output buffer and turn off output buffering
ob_end_flush();

View File

@@ -1,40 +0,0 @@
<?php
/**
* @package Flextype
*
* @author Sergey Romanenko <awilum@yandex.ru>
* @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 ParsedownExtra;
class Markdown
{
/**
* Parsedown Extra Object
*
* @var object
* @access protected
*/
protected static $markdown;
/**
* Markdown parser
*
* @access public
* @param string $content Content to parse
* @return string Formatted content
*/
public static function parse(string $content) : string
{
!static::$markdown and static::$markdown = new ParsedownExtra();
return static::$markdown->text($content);
}
}

View File

@@ -1,248 +0,0 @@
<?php
/**
* @package Flextype
*
* @author Sergey Romanenko <awilum@yandex.ru>
* @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 Flextype\Component\{Arr\Arr, Http\Http, Filesystem\Filesystem, Event\Event, Registry\Registry};
use Symfony\Component\Yaml\Yaml;
class Pages
{
/**
* An instance of the Cache class
*
* @var object
*/
protected static $instance = null;
/**
* Page
*
* @var Page
*/
public static $page;
/**
* 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.
Event::dispatch('onPageBeforeRender');
// Add parseContent on content event
Event::addListener('content', 'Flextype\Pages::parseContent');
// Get current page
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.
Event::dispatch('onPageAfterRender');
}
/**
* Page finder
*
* @param string $url
* @param bool $url_abs
*/
public static function finder(string $url = '', bool $url_abs = false) : string
{
// If url is empty that its a homepage
if ($url_abs) {
if ($url) {
$file = $url;
} else {
$file = PAGES_PATH . '/' . Registry::get('site.pages.main') . '/' . 'page.md';
}
} else {
if ($url) {
$file = PAGES_PATH . '/' . $url . '/page.md';
} else {
$file = PAGES_PATH . '/' . Registry::get('site.pages.main') . '/' . 'page.md';
}
}
// Get 404 page if file not exists
if (Filesystem::fileExists($file)) {
$file = $file;
} else {
$file = PAGES_PATH . '/404/page.md';
Http::setResponseStatus(404);
}
return $file;
}
/**
* Render page
*/
public static function renderPage(array $page)
{
Themes::template(empty($page['template']) ? 'templates/default' : 'templates/' . $page['template'])
->assign('page', $page, true)
->display();
}
/**
* Page page file
*/
public static function parseFile(string $file) : array
{
$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, 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('/'.Registry::get('site.pages.main'), '', $url);
$url = rtrim($url, '/');
$result_page['url'] = $url;
// Get page slug
$url = str_replace(Http::getBaseUrl(), '', $url);
$url = ltrim($url, '/');
$url = rtrim($url, '/');
$result_page['slug'] = str_replace(Http::getBaseUrl(), '', $url);
// Set page date
$result_page['date'] = $result_page['date'] ?? date(Registry::get('site.date_format'), filemtime($file));
// Set page content
$result_page['content'] = $page[2];
// Return page
return $result_page;
}
/**
* Get page
*/
public static function getPage(string $url = '', bool $raw = false, bool $url_abs = false)
{
$file = static::finder($url, $url_abs);
if ($raw) {
$page = trim(Filesystem::getFileContent($file));
static::$page = $page;
Event::dispatch('onPageContentRawAfter');
} else {
$page = static::parseFile($file);
static::$page = $page;
static::$page['content'] = Event::dispatch('content', ['content' => static::$page['content']], true);
Event::dispatch('onPageContentAfter');
}
return static::$page;
}
/**
* Parse Content
*
* @param $content Сontent to parse
* @return string
*/
public static function parseContent(string $content) : string
{
$content = Shortcodes::driver()->process($content);
$content = Markdown::parse($content);
return $content;
}
/**
* Get Pages
*/
public static function getPages(string $url = '', bool $raw = false, string $order_by = 'date', string $order_type = 'DESC', int $offset = null, int $length = null)
{
// Pages array where founded pages will stored
$pages = [];
// Get pages for $url
// If $url is empty then we want to have a list of pages for /pages dir.
if ($url == '') {
// Get pages list
$pages_list = Filesystem::getFilesList(PAGES_PATH, 'md');
// Create pages array from pages list
foreach ($pages_list as $key => $page) {
$pages[$key] = static::getPage($page, $raw, true);
}
} else {
// Get pages list
$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, $url.'/page.md') !== false) {
// ignore ...
} else {
$pages[$key] = static::getPage($page, $raw, true);
}
}
}
// Sort and Slice pages if $raw === false
if (!$raw) {
$pages = Arr::sort($pages, $order_by, $order_type);
if ($offset !== null && $length !== null) {
$pages = array_slice($pages, $offset, $length);
}
}
// Return pages array
return $pages;
}
/**
* Return the Pages instance.
* Create it if it's not already created.
*
* @access public
* @return object
*/
public static function instance()
{
return !isset(self::$instance) and self::$instance = new Pages();
}
}

View File

@@ -29,7 +29,7 @@ class Plugins
*
* @var array
*/
public static $locales = [
private static $locales = [
'ar' => 'العربية',
'bg' => 'Български',
'ca' => 'Català',
@@ -87,6 +87,7 @@ class Plugins
// Plugin cache id
$plugins_cache_id = '';
$_plugins_cache_id = '';
// Get Plugins List
$plugins_list = Registry::get('site.plugins');
@@ -99,60 +100,60 @@ class Plugins
// Go through...
foreach ($plugins_list as $plugin) {
if (Filesystem::fileExists($_plugin = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yaml')) {
$plugins_cache_id .= filemtime($_plugin);
if (Filesystem::fileExists($_plugin = PATH['plugins'] . '/' . $plugin . '/' . $plugin . '.yaml')) {
$_plugins_cache_id .= filemtime($_plugin);
}
}
// Create Unique Cache ID for Plugins
$plugins_cache_id = md5('plugins' . PLUGINS_PATH . $plugins_cache_id);
}
$plugins_cache_id = md5('plugins' . PATH['plugins'] . '/' . $_plugins_cache_id);
// Get plugins list from cache or scan plugins folder and create new plugins cache item
if (Cache::driver()->contains($plugins_cache_id)) {
Registry::set('plugins', Cache::driver()->fetch($plugins_cache_id));
} else {
// Get plugins list from cache or scan plugins folder and create new plugins cache item
if (Cache::driver()->contains($plugins_cache_id)) {
Registry::set('plugins', Cache::driver()->fetch($plugins_cache_id));
} else {
// If Plugins List isnt empty
// If Plugins List isnt empty
if (is_array($plugins_list) && count($plugins_list) > 0) {
// Go through...
foreach ($plugins_list as $plugin) {
if (Filesystem::fileExists($_plugin_manifest = PATH['plugins'] . '/' . $plugin . '/' . $plugin . '.yaml')) {
$plugin_manifest = Yaml::parseFile($_plugin_manifest);
}
$_plugins_config[basename($_plugin_manifest, '.yaml')] = $plugin_manifest;
}
Registry::set('plugins', $_plugins_config);
Cache::driver()->save($plugins_cache_id, $_plugins_config);
}
}
// Create Dictionary
if (is_array($plugins_list) && count($plugins_list) > 0) {
// Go through...
foreach ($plugins_list as $plugin) {
if (Filesystem::fileExists($_plugin_manifest = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yaml')) {
$plugin_manifest = Yaml::parseFile($_plugin_manifest);
}
$_plugins_config[basename($_plugin_manifest, '.yaml')] = $plugin_manifest;
}
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));
foreach (static::$locales as $locale => $locale_title) {
foreach ($plugins_list as $plugin) {
$language_file = PATH['plugins'] . '/' . $plugin . '/languages/' . $locale . '.yaml';
if (Filesystem::fileExists($language_file)) {
I18n::add($plugin, $locale, Yaml::parseFile($language_file));
}
}
}
}
}
// Include enabled plugins
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';
// Include enabled plugins
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 PATH['plugins'] . '/' . $plugin_name .'/'. $plugin_name . '.php';
}
}
}
}
Event::dispatch('onPluginsInitialized');
Event::dispatch('onPluginsInitialized');
}
}
/**

View File

@@ -1,94 +0,0 @@
<?php
/**
* @package Flextype
*
* @author Sergey Romanenko <awilum@yandex.ru>
* @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 Thunder\Shortcode\ShortcodeFacade;
use Flextype\Component\Http\Http;
class Shortcodes
{
/**
* An instance of the Shortcodes class
*
* @var object
*/
protected static $instance = null;
/**
* ShortcodeFacade Driver
*
* @var ShortcodeFacade
*/
protected static $driver;
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
static::init();
}
/**
* Init Shortcodes
*
* @access protected
* @return void
*/
protected static function init() : void
{
// Set driver
static::$driver = new ShortcodeFacade();
// Register Default Shortcodes
static::registerDefaultShortcodes();
}
/**
* Returns driver variable
*
* @access public
* @return object
*/
public static function driver() : ShortcodeFacade
{
return static::$driver;
}
/**
* Register default shortcodes
*
* @access protected
*/
protected static function registerDefaultShortcodes() : void
{
static::driver()->addHandler('site_url', function() {
return Http::getBaseUrl();
});
}
/**
* Return the Shortcodes instance.
* Create it if it's not already created.
*
* @access public
* @return object
*/
public static function instance()
{
return !isset(self::$instance) and self::$instance = new Shortcodes();
}
}

View File

@@ -51,16 +51,17 @@ class Themes
// Get current theme
$theme = Registry::get('site.theme');
// Set empty theme item
Registry::set('theme', []);
// Set empty themes items
Registry::set('themes', []);
// Create Unique Cache ID for Theme
$theme_cache_id = md5('theme' . THEMES_PATH . $theme);
$theme_cache_id = md5('theme' . PATH['themes'] . $theme);
// Get Theme mafifest file and write to site.themes array
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')) {
if (Filesystem::fileExists($theme_manifest_file = PATH['themes'] . '/' . $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);
@@ -69,22 +70,21 @@ class Themes
}
/**
* Return the Themes instance.
* Create it if it's not already created.
* Get themes view
*
* @param string $template Template file
* @param string $variables Variables
* @access public
* @return object
*/
public static function template(string $template, array $variables = [])
public static function view(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;
if (Filesystem::fileExists(PATH['themes'] . '/' . Registry::get('site.theme') . '/views/' . $template . View::$view_ext)) {
$template = PATH['themes'] . '/' . Registry::get('site.theme') . '/views/' . $template;
} else {
$template = PLUGINS_PATH . '/views/' . $template;
$template = PATH['plugins'] . '/' . $template;
}
// Return template

View File

@@ -1,40 +0,0 @@
<?php
/**
* @package Flextype
*
* @author Sergey Romanenko <awilum@yandex.ru>
* @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;
// Define the path to the root directory (without trailing slash).
define('ROOT_DIR', str_replace(DIRECTORY_SEPARATOR, '/', getcwd()));
// Define the path to the site directory (without trailing slash).
define('SITE_PATH', ROOT_DIR . '/site');
// Define the path to the pages directory (without trailing slash).
define('PAGES_PATH', SITE_PATH . '/pages');
// Define the path to the themes directory (without trailing slash).
define('THEMES_PATH', SITE_PATH . '/themes');
// Define the path to the plugins directory (without trailing slash).
define('PLUGINS_PATH', SITE_PATH . '/plugins');
// Define the path to the config directory (without trailing slash).
define('CONFIG_PATH', SITE_PATH . '/config');
// Define the path to the cache directory (without trailing slash).
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');

View File

@@ -15,6 +15,23 @@ namespace Flextype;
// Define the application minimum supported PHP version.
define('FLEXTYPE_MINIMUM_PHP', '7.1.3');
// Define the path to the root directory (without trailing slash).
define('ROOT_DIR', str_replace(DIRECTORY_SEPARATOR, '/', getcwd()));
// Define the PATH (without trailing slash).
define('PATH', ['site' => ROOT_DIR . '/site',
'plugins' => ROOT_DIR . '/site/plugins',
'themes' => ROOT_DIR . '/site/themes',
'pages' => ROOT_DIR . '/site/pages',
'blocks' => ROOT_DIR . '/site/blocks',
'data' => ROOT_DIR . '/site/data',
'config' => ROOT_DIR . '/site/config',
'cache' => ROOT_DIR . '/site/cache',
'accounts' => ROOT_DIR . '/site/accounts']);
// Define the path to the logs directory (without trailing slash).
define('LOGS_PATH', PATH['site'] . '/logs');
// Check PHP Version
version_compare($ver = PHP_VERSION, $req = FLEXTYPE_MINIMUM_PHP, '<') and exit(sprintf('You are running PHP %s, but Flextype needs at least <strong>PHP %s</strong> to run.', $ver, $req));
@@ -24,5 +41,5 @@ version_compare($ver = PHP_VERSION, $req = FLEXTYPE_MINIMUM_PHP, '<') and exit(s
// Register The Auto Loader
$loader = require_once $autoload;
// Init Flextype
// Init Flextype Application
Flextype::instance();

View File

@@ -1,4 +0,0 @@
username: admin
password: admin
role: admin
state: enabled

0
site/blocks/.gitkeep Executable file
View File

View File

@@ -1,46 +0,0 @@
html,
body {
font-family: 'Source Sans Pro', sans-serif;
font-size: 16px;
height: 100%;
color: black;
background: white;
}
body,
button,
input,
select,
textarea,
p {
font-family: 'Source Sans Pro', sans-serif;
font-weight: 400;
color: black;
}
body,
p {
line-height: 26px;
}
pre {
background: #f0f0f0;
padding-left: 10px;
}
.content {
padding-top: 40px;
}
.navbar-brand {
letter-spacing: 3px;
text-transform: uppercase;
}
.powered {
padding-top: 30px;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
//
// Main
//
html,
body {
font-family: $base-font-family;
font-size: $base-font-size;
height: 100%;
color: black;
background: white;
}
body,
button,
input,
select,
textarea,
p {
font-family: $base-font-family;
font-weight: 400;
color: black;
}
body,
p {
line-height: $base-line-height;
}
pre {
background: #f0f0f0;
padding-left: 10px;
}

View File

@@ -0,0 +1,39 @@
//
// Twitter Bootsrap
//
@import "node_modules/bootstrap/scss/functions";
@import "node_modules/bootstrap/scss/variables";
@import "node_modules/bootstrap/scss/mixins";
@import "node_modules/bootstrap/scss/root";
@import "node_modules/bootstrap/scss/reboot";
@import "node_modules/bootstrap/scss/type";
@import "node_modules/bootstrap/scss/images";
@import "node_modules/bootstrap/scss/code";
@import "node_modules/bootstrap/scss/grid";
@import "node_modules/bootstrap/scss/tables";
@import "node_modules/bootstrap/scss/forms";
@import "node_modules/bootstrap/scss/buttons";
@import "node_modules/bootstrap/scss/transitions";
@import "node_modules/bootstrap/scss/dropdown";
@import "node_modules/bootstrap/scss/button-group";
@import "node_modules/bootstrap/scss/input-group";
@import "node_modules/bootstrap/scss/custom-forms";
@import "node_modules/bootstrap/scss/nav";
@import "node_modules/bootstrap/scss/navbar";
@import "node_modules/bootstrap/scss/card";
@import "node_modules/bootstrap/scss/breadcrumb";
@import "node_modules/bootstrap/scss/pagination";
@import "node_modules/bootstrap/scss/badge";
@import "node_modules/bootstrap/scss/jumbotron";
@import "node_modules/bootstrap/scss/alert";
@import "node_modules/bootstrap/scss/progress";
@import "node_modules/bootstrap/scss/media";
@import "node_modules/bootstrap/scss/list-group";
@import "node_modules/bootstrap/scss/close";
@import "node_modules/bootstrap/scss/modal";
@import "node_modules/bootstrap/scss/tooltip";
@import "node_modules/bootstrap/scss/popover";
@import "node_modules/bootstrap/scss/carousel";
@import "node_modules/bootstrap/scss/utilities";
@import "node_modules/bootstrap/scss/print";

View File

@@ -0,0 +1,7 @@
//
// Footer
//
.powered {
padding-top: 30px;
}

View File

@@ -0,0 +1,8 @@
//
// Nav
//
.navbar-brand {
letter-spacing: 3px;
text-transform: uppercase;
}

View File

@@ -0,0 +1,35 @@
//
// Variables
//
//
// Base
//
$base-font-family: Helvetica, arial, sans-serif;
$base-font-color: #606060;
$base-font-size: 16px;
$base-line-height: 24px;
//
// Colors Grayscale
//
$black: #000000;
$gray-darkest: lighten($black, 13.5%); // #222222
$gray-darker: lighten($black, 26.5%); // #444444
$gray-dark: lighten($black, 46.7%); // #777777
$gray: lighten($black, 66.5%); // #aaaaaa
$gray-light: lighten($black, 87%); // #dedede
$gray-lighter: lighten($black, 93.75%); // #efefef
$gray-lightest: lighten($black, 97.25%); // #f8f8f8
$white: #ffffff;
//
// Scaffolding
//
$body-bg: #f2f4f5;
//
// Spacing
//
$base-spacing-unit: $base-font-size;
$half-spacing-unit: $base-spacing-unit / 2;

View File

@@ -0,0 +1,7 @@
//
// Container
//
.content {
padding-top: 40px;
}

View File

@@ -0,0 +1,27 @@
//
// Simple Theme main SCSS
// (c) Sergey Romanenko <https://github.com/Awilum>
//
// Import Twitter Bootstrap
@import "bootstrap";
// Generic
// Low-specificity, far-reaching rulesets
@import "generic/variables";
// Base
// Unclassed HTML elements
@import "base/main";
// Objects
// Abstractions, Objects and design patterns
@import "objects/container";
// Components
// Discrete, complete chunks of UI
@import "components/nav";
@import "components/footer";
// Thumps
// High-specificity, very explicit selectors. Overrides and helper classes

23
site/themes/simple/gulpfile.js Executable file
View File

@@ -0,0 +1,23 @@
//
// Flextype Gulp.js
// (c) Sergey Romanenko <https://github.com/Awilum>
//
var Promise = require("es6-promise").Promise,
gulp = require('gulp'),
csso = require('gulp-csso'),
autoprefixer = require('gulp-autoprefixer'),
sass = require('gulp-sass');
gulp.task('process-css', function() {
return gulp.src('assets/scss/simple.scss')
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer({
browsers: ['last 2 versions'],
cascade: false
}))
.pipe(csso())
.pipe(gulp.dest('assets/dist/css/'));
});
gulp.task('default', ['process-css'], function() { });

7
site/themes/simple/package.json Normal file → Executable file
View File

@@ -2,7 +2,12 @@
"name": "flextype",
"version": "1.0.0",
"devDependencies": {
"bootstrap": "^4.1.0",
"es6-promise": "^4.2.4",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^5.0.0",
"gulp-csso": "^3.0.1",
"gulp-sass": "^4.0.1",
"bootstrap": "^4.1.1",
"jquery": "^3.3.1"
}
}

View File

@@ -1,6 +1,6 @@
<?php namespace Flextype; ?>
<?php Themes::template('partials/tail')->display(); ?>
<?php Themes::view('partials/tail')->display(); ?>
<div class="powered">
Powered by <a href="http://flextype.org">Flextype</a>

View File

@@ -16,13 +16,10 @@
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,700' rel='stylesheet' type='text/css'>
<!-- Bootstrap core CSS -->
<link href="<?php echo Http::getBaseUrl(); ?>/site/themes/<?php echo Registry::get('site.theme'); ?>/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="<?php echo Http::getBaseUrl(); ?>/site/themes/<?php echo Registry::get('site.theme'); ?>/assets/dist/css/simple.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="<?php echo Http::getBaseUrl(); ?>/site/themes/<?php echo Registry::get('site.theme'); ?>/assets/css/theme.css" rel="stylesheet">
<?php Event::dispatch('onThemeHeader'); ?>
<?php Event::dispatch('onThemeHeader'); ?>
</head>
<body>
<?php Themes::template('partials/navigation')->display(); ?>
<?php Themes::view('partials/navigation')->display(); ?>
<main role="main" class="container content">

View File

@@ -1,4 +1,4 @@
<?php namespace Flextype; ?>
<?php Themes::template('partials/head')->display(); ?>
<?php Themes::view('partials/head')->display(); ?>
<?php echo $page['content']; ?>
<?php Themes::template('partials/footer')->display(); ?>
<?php Themes::view('partials/footer')->display(); ?>