mirror of
https://github.com/monstra-cms/monstra.git
synced 2025-07-31 18:30:20 +02:00
#431 initial commit for MONSTRA 4
This commit is contained in:
6
.gitignore
vendored
Executable file
6
.gitignore
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
.idea
|
||||
.DS_Store
|
||||
composer.phar
|
||||
composer.lock
|
||||
vendor
|
||||
site-katerinasitnikova
|
63
.htaccess
Executable file
63
.htaccess
Executable file
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# This file is part of the Monstra.
|
||||
#
|
||||
# (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
#
|
||||
# For the full copyright and license information, please view the LICENSE
|
||||
# file that was distributed with this source code.
|
||||
#
|
||||
|
||||
# Set default charset utf-8
|
||||
AddDefaultCharset UTF-8
|
||||
|
||||
# PHP 5, Apache 1 and 2.
|
||||
<IfModule mod_php5.c>
|
||||
php_flag magic_quotes_gpc off
|
||||
php_flag magic_quotes_sybase off
|
||||
php_flag register_globals off
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
|
||||
## Begin - Rewrite rules to block out some common exploits.
|
||||
# If you experience problems on your site block out the operations listed below
|
||||
# This attempts to block the most common type of exploit `attempts` to Monstra
|
||||
#
|
||||
# Block out any script trying to base64_encode data within the URL.
|
||||
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
|
||||
# Block out any script that includes a <script> tag in URL.
|
||||
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
|
||||
# Block out any script trying to set a PHP GLOBALS variable via URL.
|
||||
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
|
||||
# Block out any script trying to modify a _REQUEST variable via URL.
|
||||
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
|
||||
# Return 403 Forbidden header and show the content of the root homepage
|
||||
RewriteRule .* index.php [F]
|
||||
#
|
||||
## End - Rewrite rules to block out some common exploits.
|
||||
|
||||
## Begin - Rewrite rules for Monstra
|
||||
RewriteBase /monstra/
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ index.php [QSA,L]
|
||||
## End - Rewrite rules for Monstra
|
||||
|
||||
## Begin - Rewrite rules for SEO improvements.
|
||||
# RewriteCond %{HTTP_HOST} ^www.example.org [NC]
|
||||
# RewriteRule ^(.*)$ http://example.org/$1 [R=301,L]
|
||||
# Redirect 301 /index http://example.org/
|
||||
## End - Rewrite rules for SEO improvements.
|
||||
|
||||
</IfModule>
|
||||
|
||||
# Prevent visitors from viewing files directly.
|
||||
<FilesMatch "(^#.*#|\.(md|txt|html|tpl|yml|yaml)|~)$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</FilesMatch>
|
||||
|
||||
# Don't show directory listings for URLs which map to a directory.
|
||||
Options -Indexes
|
2
CHANGELOG.md
Executable file
2
CHANGELOG.md
Executable file
@@ -0,0 +1,2 @@
|
||||
# Monstra 4.0.0, 2018-03-30
|
||||
*
|
21
LICENSE.md
Executable file
21
LICENSE.md
Executable file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Monstra Content Management
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
47
README.md
Executable file
47
README.md
Executable file
@@ -0,0 +1,47 @@
|
||||
# Monstra
|
||||
[](https://gitter.im/Monstra/Monstra?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Monstra is Modern Open Source Flat-File Content Management site.
|
||||
Content in Monstra 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.
|
||||
|
||||
## Requirements
|
||||
PHP 5.5.9 or higher with PHP's [Multibyte String module](http://php.net/mbstring)
|
||||
Apache with [Mod Rewrite](http://httpd.apache.org/docs/current/mod/mod_rewrite.html)
|
||||
|
||||
## Installation
|
||||
|
||||
#### Using (S)FTP
|
||||
|
||||
[Download the latest version.](http://monstra.org/download)
|
||||
|
||||
Unzip the contents to a new folder on your local computer, and upload to your webhost using the (S)FTP client of your choice. After you’ve done this, be sure to chmod the following directories (with containing files) to 777, so they are readable and writable by Monstra:
|
||||
* `cache/`
|
||||
* `config/`
|
||||
* `storage/`
|
||||
* `themes/`
|
||||
* `plugins/`
|
||||
|
||||
#### Using Composer
|
||||
|
||||
You can easily install Monstra with Composer.
|
||||
|
||||
```
|
||||
composer create-project monstra-cms/monstra
|
||||
```
|
||||
|
||||
## Contributing
|
||||
1. Help on the [Forum.](http://forum.Monstra.org)
|
||||
2. Develop a new plugin.
|
||||
3. Create a new theme.
|
||||
4. Find and [report issues.](https://github.com/Monstra/Monstra/issues)
|
||||
5. Link back to [Monstra](http://monstra.org).
|
||||
|
||||
## Links
|
||||
- [Site](http://monstra.org)
|
||||
- [Forum](http://forum.Monstra.org)
|
||||
- [Documentation](http://monstra.org/documentation)
|
||||
- [Github Repository](https://github.com/Monstra/Monstra)
|
||||
|
||||
## License
|
||||
See [LICENSE](https://github.com/Monstra/Monstra/blob/master/LICENSE.md)
|
43
composer.json
Executable file
43
composer.json
Executable file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "monstra-cms/monstra",
|
||||
"type": "library",
|
||||
"description": "Monstra is Modern Open Source Flat-File Content Management System",
|
||||
"keywords": ["Monstra", "php", "cms", "flat-file", "markdown"],
|
||||
"homepage": "http://monstra.org",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sergey Romanenko",
|
||||
"email": "awilum@msn.com",
|
||||
"homepage": "https://github.com/Awilum"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/monstra-cms/monstra/issues"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"erusev/parsedown-extra": "0.7.*",
|
||||
"mustangostang/spyc" : "0.5.*",
|
||||
"doctrine/cache": "1.6.*",
|
||||
"doctrine/collections": "1.3",
|
||||
"force/session" : "*",
|
||||
"force/filesystem" : "*",
|
||||
"force/arr" : "*",
|
||||
"force/http" : "*",
|
||||
"force/shortcode" : "*",
|
||||
"force/token" : "*",
|
||||
"force/url" : "*"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"Monstra"
|
||||
],
|
||||
"files": [
|
||||
"Monstra/boot/defines.php",
|
||||
"Monstra/boot/shortcodes.php",
|
||||
"Monstra/boot/filters.php",
|
||||
"Monstra/boot/actions.php"
|
||||
]
|
||||
}
|
||||
}
|
BIN
favicon.ico
Executable file
BIN
favicon.ico
Executable file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
10
index.php
Executable file
10
index.php
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Monstra requires PHP 5.5.9 or greater
|
||||
version_compare(PHP_VERSION, "5.5.9", "<") and exit("Monstra requires PHP 5.5.9 or greater.");
|
||||
|
||||
// Register the auto-loader.
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// Initialize Monstra Application
|
||||
Monstra::init();
|
113
monstra/Action.php
Executable file
113
monstra/Action.php
Executable file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Action
|
||||
{
|
||||
/**
|
||||
* Actions
|
||||
*
|
||||
* @var array
|
||||
* @access protected
|
||||
*/
|
||||
protected static $actions = [];
|
||||
|
||||
/**
|
||||
* Protected constructor since this is a static class.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
// Nothing here
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks a function on to a specific action.
|
||||
*
|
||||
* <code>
|
||||
* // Hooks a function "newLink" on to a "footer" action.
|
||||
* Action::add('footer', 'newLink', 10);
|
||||
*
|
||||
* function newLink() {
|
||||
* echo '<a href="#">My link</a>';
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $action_name Action name
|
||||
* @param mixed $added_function Added function
|
||||
* @param integer $priority Priority. Default is 10
|
||||
* @param array $args Arguments
|
||||
*/
|
||||
public static function add($action_name, $added_function, $priority = 10, array $args = null)
|
||||
{
|
||||
// Hooks a function on to a specific action.
|
||||
static::$actions[] = array(
|
||||
'action_name' => (string) $action_name,
|
||||
'function' => $added_function,
|
||||
'priority' => (int) $priority,
|
||||
'args' => $args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run functions hooked on a specific action hook.
|
||||
*
|
||||
* <code>
|
||||
* // Run functions hooked on a "footer" action hook.
|
||||
* Action::run('footer');
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $action_name Action name
|
||||
* @param array $args Arguments
|
||||
* @param boolean $return Return data or not. Default is false
|
||||
* @return mixed
|
||||
*/
|
||||
public static function run($action_name, $args = [], $return = false)
|
||||
{
|
||||
// Redefine arguments
|
||||
$action_name = (string) $action_name;
|
||||
$return = (bool) $return;
|
||||
|
||||
// Run action
|
||||
if (count(static::$actions) > 0) {
|
||||
|
||||
// Sort actions by priority
|
||||
$actions = Arr::subvalSort(static::$actions, 'priority');
|
||||
|
||||
// Loop through $actions array
|
||||
foreach ($actions as $action) {
|
||||
|
||||
// Execute specific action
|
||||
if ($action['action_name'] == $action_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']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
102
monstra/Blocks.php
Executable file
102
monstra/Blocks.php
Executable file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Blocks
|
||||
{
|
||||
/**
|
||||
* An instance of the Blocks class
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Protected clone method to enforce singleton behavior.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __clone()
|
||||
{
|
||||
// Nothing here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
$blocks_cache_id = '';
|
||||
|
||||
$blocks = File::scan(STORAGE_PATH . '/blocks', 'md');
|
||||
|
||||
if ($blocks) {
|
||||
foreach ($blocks as $block) {
|
||||
$blocks_cache_id .= filemtime($block);
|
||||
}
|
||||
|
||||
// Create Unique Cache ID for Block
|
||||
$blocks_cache_id = md5('blocks' . ROOT_DIR . $blocks_cache_id);
|
||||
}
|
||||
|
||||
if (Cache::driver()->contains($blocks_cache_id)) {
|
||||
Cache::driver()->fetch($blocks_cache_id);
|
||||
} else {
|
||||
Config::set('site.pages.flush_cache', true);
|
||||
Cache::driver()->save($blocks_cache_id, $blocks_cache_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Page Block
|
||||
*
|
||||
* <code>
|
||||
* $block = Blocks::get('my-block');
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $name Block name
|
||||
* @return string Formatted Block content
|
||||
*/
|
||||
public static function get($name)
|
||||
{
|
||||
if (File::exists($block_path = STORAGE_PATH .'/blocks/' . $name . '.md')) {
|
||||
|
||||
// Create Unique Cache ID for Block
|
||||
$block_cache_id = md5('block' . ROOT_DIR . $block_path . filemtime($block_path));
|
||||
|
||||
if (Cache::driver()->contains($block_cache_id)) {
|
||||
return Cache::driver()->fetch($block_cache_id);
|
||||
} else {
|
||||
Cache::driver()->save($block_cache_id, $block = Filter::apply('content', file_get_contents($block_path)));
|
||||
return $block;
|
||||
}
|
||||
} else {
|
||||
return 'Block '.$name.' is not found!';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Monstra Blocks
|
||||
*
|
||||
* <code>
|
||||
* Blocks::init();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public static function init()
|
||||
{
|
||||
return !isset(self::$instance) and self::$instance = new Blocks();
|
||||
}
|
||||
}
|
248
monstra/Cache.php
Executable file
248
monstra/Cache.php
Executable file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Cache
|
||||
{
|
||||
/**
|
||||
* An instance of the Cache class
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Unique cache key
|
||||
*
|
||||
* @var string Cache key.
|
||||
*/
|
||||
protected static $key;
|
||||
|
||||
/**
|
||||
* Lifetime
|
||||
*
|
||||
* @var int Lifetime.
|
||||
*/
|
||||
protected static $lifetime;
|
||||
|
||||
/**
|
||||
* Current time
|
||||
*
|
||||
* @var int Current time.
|
||||
*/
|
||||
protected static $now;
|
||||
|
||||
/**
|
||||
* Cache Driver
|
||||
*
|
||||
* @var DoctrineCache
|
||||
*/
|
||||
protected static $driver;
|
||||
|
||||
/**
|
||||
* Protected clone method to enforce singleton behavior.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __clone()
|
||||
{
|
||||
// Nothing here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
// Set current time
|
||||
static::$now = time();
|
||||
|
||||
// Cache key allows us to invalidate all cache on configuration changes.
|
||||
static::$key = (Config::get('site.cache.prefix') ? Config::get('site.cache.prefix') : 'Monstra') . '-' . md5(ROOT_DIR . Monstra::VERSION);
|
||||
|
||||
// Get Cache Driver
|
||||
static::$driver = static::getCacheDriver();
|
||||
|
||||
// Set the cache namespace to our unique key
|
||||
static::$driver->setNamespace(static::$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Cache Driver
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public static function getCacheDriver()
|
||||
{
|
||||
$driver_name = Config::get('site.cache.driver');
|
||||
|
||||
if (!$driver_name || $driver_name == 'auto') {
|
||||
if (extension_loaded('apc')) {
|
||||
$driver_name = 'apc';
|
||||
} elseif (extension_loaded('wincache')) {
|
||||
$driver_name = 'wincache';
|
||||
} elseif (extension_loaded('xcache')) {
|
||||
$driver_name = 'xcache';
|
||||
}
|
||||
} else {
|
||||
$driver_name = 'file';
|
||||
}
|
||||
|
||||
switch ($driver_name) {
|
||||
case 'apc':
|
||||
$driver = new \Doctrine\Common\Cache\ApcCache();
|
||||
break;
|
||||
case 'wincache':
|
||||
$driver = new \Doctrine\Common\Cache\WinCacheCache();
|
||||
break;
|
||||
case 'xcache':
|
||||
$driver = new \Doctrine\Common\Cache\XcacheCache();
|
||||
break;
|
||||
case 'memcache':
|
||||
$memcache = new \Memcache();
|
||||
$memcache->connect(Config::get('site.cache.memcache.server', 'localhost'),
|
||||
Config::get('site.cache.memcache.port', 11211));
|
||||
$driver = new \Doctrine\Common\Cache\MemcacheCache();
|
||||
$driver->setMemcache($memcache);
|
||||
break;
|
||||
case 'redis':
|
||||
$redis = new \Redis();
|
||||
$redis->connect(Config::get('site.cache.redis.server', 'localhost'),
|
||||
Config::get('site.cache.redis.port', 6379));
|
||||
$driver = new \Doctrine\Common\Cache\RedisCache();
|
||||
$driver->setRedis($redis);
|
||||
break;
|
||||
default:
|
||||
// Create doctrine cache directory if its not exists
|
||||
!Dir::exists($cache_directory = CACHE_PATH . '/doctrine/') and Dir::create($cache_directory);
|
||||
$driver = new \Doctrine\Common\Cache\FilesystemCache($cache_directory);
|
||||
break;
|
||||
}
|
||||
|
||||
return $driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns driver variable
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public static function driver()
|
||||
{
|
||||
return static::$driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function getKey()
|
||||
{
|
||||
return static::$key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an entry from the cache.
|
||||
*
|
||||
* @access public
|
||||
* @param string $id The id of the cache entry to fetch.
|
||||
* @return mixed The cached data or FALSE, if no cache entry exists for the given id.
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
if (Config::get('site.cache.enabled')) {
|
||||
return static::$driver->fetch($id);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts data into the cache.
|
||||
*
|
||||
* @access public
|
||||
* @param string $id The cache id.
|
||||
* @param mixed $data The cache entry/data.
|
||||
* @param int $lifeTime The lifetime in number of seconds for this cache entry.
|
||||
* If zero (the default), the entry never expires (although it may be deleted from the cache
|
||||
* to make place for other entries).
|
||||
*/
|
||||
public function save($id, $data, $lifetime = null)
|
||||
{
|
||||
if (Config::get('site.cache.enabled')) {
|
||||
if ($lifetime === null) {
|
||||
$lifetime = static::getLifetime();
|
||||
}
|
||||
static::$driver->save($id, $data, $lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Cache
|
||||
*/
|
||||
public static function clear()
|
||||
{
|
||||
Dir::delete(CACHE_PATH . '/doctrine/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache lifetime.
|
||||
*
|
||||
* @access public
|
||||
* @param int $future timestamp
|
||||
*/
|
||||
public static function setLifetime($future)
|
||||
{
|
||||
if (!$future) {
|
||||
return;
|
||||
}
|
||||
|
||||
$interval = $future - $this->now;
|
||||
|
||||
if ($interval > 0 && $interval < static::getLifetime()) {
|
||||
static::$lifetime = $interval;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cache lifetime (in seconds)
|
||||
*
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getLifetime()
|
||||
{
|
||||
if (static::$lifetime === null) {
|
||||
static::$lifetime = Config::get('site.cache.lifetime') ?: 604800;
|
||||
}
|
||||
return static::$lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Monstra Cache
|
||||
*
|
||||
* <code>
|
||||
* Cache::init();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public static function init()
|
||||
{
|
||||
return !isset(self::$instance) and self::$instance = new Cache();
|
||||
}
|
||||
}
|
113
monstra/Config.php
Executable file
113
monstra/Config.php
Executable file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
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()
|
||||
{
|
||||
static::$config['site'] = Yaml::parseFile(CONFIG_PATH . '/' . 'site.yml');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new or update existing config variable
|
||||
*
|
||||
* <code>
|
||||
* Config::set('site.title', 'value');
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $key Key
|
||||
* @param mixed $value Value
|
||||
*/
|
||||
public static function set($key, $value)
|
||||
{
|
||||
Arr::set(static::$config, $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config variable
|
||||
*
|
||||
* <code>
|
||||
* Config::get('site');
|
||||
* Config::get('site.title');
|
||||
* Config::get('site.title', 'Default title');
|
||||
* </code>
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* <code>
|
||||
* $config = Config::getConfig();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public static function getConfig()
|
||||
{
|
||||
return static::$config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Monstra Config
|
||||
*
|
||||
* <code>
|
||||
* Config::init();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public static function init()
|
||||
{
|
||||
return !isset(self::$instance) and self::$instance = new Config();
|
||||
}
|
||||
}
|
120
monstra/Filter.php
Executable file
120
monstra/Filter.php
Executable file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Filter
|
||||
{
|
||||
/**
|
||||
* Filters
|
||||
*
|
||||
* @var array
|
||||
* @access protected
|
||||
*/
|
||||
protected static $filters = [];
|
||||
|
||||
/**
|
||||
* Protected constructor since this is a static class.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
// Nothing here
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters
|
||||
*
|
||||
* <code>
|
||||
* Filter::apply('content', $content);
|
||||
* </code>
|
||||
*
|
||||
* @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 apply($filter_name, $value)
|
||||
{
|
||||
// Redefine arguments
|
||||
$filter_name = (string) $filter_name;
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filter
|
||||
*
|
||||
* <code>
|
||||
* Filter::add('content', 'replacer');
|
||||
*
|
||||
* function replacer($content) {
|
||||
* return preg_replace(array('/\[b\](.*?)\[\/b\]/ms'), array('<strong>\1</strong>'), $content);
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @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 boolean
|
||||
*/
|
||||
public static function add($filter_name, $function_to_add, $priority = 10, $accepted_args = 1)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
39
monstra/Markdown.php
Executable file
39
monstra/Markdown.php
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Markdown
|
||||
{
|
||||
/**
|
||||
* Parsedown Extra Object
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected static $markdown;
|
||||
|
||||
/**
|
||||
* Markdown parser
|
||||
*
|
||||
* <code>
|
||||
* $content = Markdown::parse($content);
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $content Content to parse
|
||||
* @return string Formatted content
|
||||
*/
|
||||
public static function parse($content)
|
||||
{
|
||||
!static::$markdown and static::$markdown = new ParsedownExtra();
|
||||
|
||||
return static::$markdown->text($content);
|
||||
}
|
||||
}
|
98
monstra/Monstra.php
Executable file
98
monstra/Monstra.php
Executable file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Monstra
|
||||
*
|
||||
* @package Monstra
|
||||
* @author Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
* @link http://monstra.org
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Monstra
|
||||
{
|
||||
/**
|
||||
* An instance of the Monstra class
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* The version of Monstra
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '4.0.0 alpha';
|
||||
|
||||
/**
|
||||
* Protected clone method to enforce singleton behavior.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __clone()
|
||||
{
|
||||
// Nothing here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
// Init Config
|
||||
Config::init();
|
||||
|
||||
// Turn on output buffering
|
||||
ob_start();
|
||||
|
||||
// Display Errors
|
||||
Config::get('site.errors.display') and error_reporting(-1);
|
||||
|
||||
// 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'));
|
||||
|
||||
// Set default timezone
|
||||
date_default_timezone_set(Config::get('site.timezone'));
|
||||
|
||||
// Start the session
|
||||
Session::start();
|
||||
|
||||
// Init Cache
|
||||
Cache::init();
|
||||
|
||||
// Init Plugins
|
||||
Plugins::init();
|
||||
|
||||
// Init Blocks
|
||||
Blocks::init();
|
||||
|
||||
// Init Pages
|
||||
Pages::init();
|
||||
|
||||
// Flush (send) the output buffer and turn off output buffering
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Monstra Application
|
||||
*
|
||||
* <code>
|
||||
* Monstra::init();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public static function init()
|
||||
{
|
||||
return !isset(self::$instance) and self::$instance = new Monstra();
|
||||
}
|
||||
}
|
309
monstra/Pages.php
Executable file
309
monstra/Pages.php
Executable file
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Pages
|
||||
{
|
||||
/**
|
||||
* An instance of the Pages class
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Current page.
|
||||
*
|
||||
* @var array
|
||||
* @access protected
|
||||
*/
|
||||
protected static $current_page;
|
||||
|
||||
/**
|
||||
* Current page template.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected static $current_template;
|
||||
|
||||
/**
|
||||
* Protected clone method to enforce singleton behavior.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __clone()
|
||||
{
|
||||
// Nothing here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
// Get Current Page
|
||||
static::$current_page = static::getPage(Url::getUriString());
|
||||
|
||||
// Get Theme Templates
|
||||
static::$current_template = ((!empty(static::$current_page['template'])) ? static::$current_page['template'] : 'index');
|
||||
|
||||
// Send default header
|
||||
header('Content-Type: text/html; charset='.Config::get('site.charset'));
|
||||
|
||||
// Run actions before page rendered
|
||||
Action::run('before_page_rendered');
|
||||
|
||||
// Display page for current requested url
|
||||
static::display(static::$current_page);
|
||||
|
||||
// Run actions after page rendered
|
||||
Action::run('after_page_rendered');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pages
|
||||
*
|
||||
* <code>
|
||||
* $pages = Pages::getPages('blog');
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $url Url
|
||||
* @param string $order_by Order by
|
||||
* @param string $order_type Order type
|
||||
* @param array $ignore Pages to ignore
|
||||
* @param int $limit Limit of pages
|
||||
* @return array
|
||||
*/
|
||||
public static function getPages($url = '', $order_by = 'date', $order_type = 'DESC', $ignore = array('404'), $limit = null)
|
||||
{
|
||||
$pages = File::scan(STORAGE_PATH . '/pages/' . $url, 'md');
|
||||
|
||||
if ($pages) {
|
||||
foreach ($pages as $page) {
|
||||
$pages_cache_id .= filemtime($page);
|
||||
}
|
||||
|
||||
// Create Unique Cache ID for Pages
|
||||
$pages_cache_id = md5('pages' . ROOT_DIR . $url . $order_by . $order_type . implode(",", $ignore) . (($limit === null) ? 'null' : $limit) . $pages_cache_id);
|
||||
}
|
||||
|
||||
if (Cache::driver()->contains($pages_cache_id)) {
|
||||
return Cache::driver()->fetch($pages_cache_id);
|
||||
} else {
|
||||
foreach ($pages as $key => $page) {
|
||||
if (!in_array(basename($page, '.md'), $ignore)) {
|
||||
$content = file_get_contents($page);
|
||||
|
||||
$_page = explode('---', $content, 3);
|
||||
|
||||
$_pages[$key] = Yaml::parse($_page[1]);
|
||||
|
||||
$url = str_replace(STORAGE_PATH . '/pages', Url::getBase(), $page);
|
||||
$url = str_replace('index.md', '', $url);
|
||||
$url = str_replace('.md', '', $url);
|
||||
$url = str_replace('\\', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
$_pages[$key]['url'] = $url;
|
||||
|
||||
$_content = $_page[2];
|
||||
|
||||
// Parse page for summary <!--more-->
|
||||
if (($pos = strpos($_content, "<!--more-->")) === false) {
|
||||
$_content = Filter::apply('content', $_content);
|
||||
} else {
|
||||
$_content = explode("<!--more-->", $_content);
|
||||
$_content['summary'] = Filter::apply('content', $_content[0]);
|
||||
$_content['content'] = Filter::apply('content', $_content[0].$_content[1]);
|
||||
}
|
||||
|
||||
if (is_array($_content)) {
|
||||
$_pages[$key]['summary'] = $_content['summary'];
|
||||
$_pages[$key]['content'] = $_content['content'];
|
||||
} else {
|
||||
$_pages[$key]['summary'] = $_content;
|
||||
$_pages[$key]['content'] = $_content;
|
||||
}
|
||||
|
||||
$_pages[$key]['slug'] = basename($page, '.md');
|
||||
}
|
||||
}
|
||||
|
||||
$_pages = Arr::subvalSort($_pages, $order_by, $order_type);
|
||||
|
||||
if ($limit != null) {
|
||||
$_pages = array_slice($_pages, null, $limit);
|
||||
}
|
||||
|
||||
Cache::driver()->save($pages_cache_id, $_pages);
|
||||
return $_pages;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page
|
||||
*
|
||||
* <code>
|
||||
* $page = Pages::getPage('downloads');
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $url Url
|
||||
* @return array
|
||||
*/
|
||||
public static function getPage($url)
|
||||
{
|
||||
|
||||
// If url is empty that its a homepage
|
||||
if ($url) {
|
||||
$file = STORAGE_PATH . '/pages/' . $url;
|
||||
} else {
|
||||
$file = STORAGE_PATH . '/pages/' . 'index';
|
||||
}
|
||||
|
||||
// Select the file
|
||||
if (is_dir($file)) {
|
||||
$file = STORAGE_PATH . '/pages/' . $url .'/index.md';
|
||||
} else {
|
||||
$file .= '.md';
|
||||
}
|
||||
|
||||
// Get 404 page if file not exists
|
||||
if (!file_exists($file)) {
|
||||
$file = STORAGE_PATH . '/pages/' . '404.md';
|
||||
Response::status(404);
|
||||
}
|
||||
|
||||
// Create Unique Cache ID for requested page
|
||||
$page_cache_id = md5('page' . ROOT_DIR . $file . filemtime($file));
|
||||
|
||||
if (Cache::driver()->contains($page_cache_id) && Config::get('site.pages.flush_cache') == false) {
|
||||
return Cache::driver()->fetch($page_cache_id);
|
||||
} else {
|
||||
$content = file_get_contents($file);
|
||||
|
||||
$_page = explode('---', $content, 3);
|
||||
|
||||
$page = Yaml::parse($_page[1]);
|
||||
|
||||
$url = str_replace(STORAGE_PATH . '/pages', Url::getBase(), $file);
|
||||
$url = str_replace('index.md', '', $url);
|
||||
$url = str_replace('.md', '', $url);
|
||||
$url = str_replace('\\', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
$page['url'] = $url;
|
||||
|
||||
$_content = $_page[2];
|
||||
|
||||
// Parse page for summary <!--more-->
|
||||
if (($pos = strpos($_content, "<!--more-->")) === false) {
|
||||
$_content = Filter::apply('content', $_content);
|
||||
} else {
|
||||
$_content = explode("<!--more-->", $_content);
|
||||
$_content['summary'] = Filter::apply('content', $_content[0]);
|
||||
$_content['content'] = Filter::apply('content', $_content[0].$_content[1]);
|
||||
}
|
||||
|
||||
if (is_array($_content)) {
|
||||
$page['summary'] = $_content['summary'];
|
||||
$page['content'] = $_content['content'];
|
||||
} else {
|
||||
$page['content'] = $_content;
|
||||
}
|
||||
|
||||
$page['slug'] = basename($file, '.md');
|
||||
|
||||
// Overload page title, keywords and description if needed
|
||||
empty($page['title']) and $page['title'] = Config::get('site.title');
|
||||
empty($page['keywords']) and $page['keywords'] = Config::get('site.keywords');
|
||||
empty($page['description']) and $page['description'] = Config::get('site.description');
|
||||
|
||||
Cache::driver()->save($page_cache_id, $page);
|
||||
return $page;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Current Page
|
||||
*
|
||||
* <code>
|
||||
* $page = Pages::getCurrentPage();
|
||||
* </code>
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCurrentPage()
|
||||
{
|
||||
return static::$current_page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Current Page
|
||||
*
|
||||
* <code>
|
||||
* Pages::updateCurrentPage('title', 'My new Page Title');
|
||||
* </code>
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function updateCurrentPage($path, $value)
|
||||
{
|
||||
Arr::set(static::$current_page, $path, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display Page
|
||||
*
|
||||
* <code>
|
||||
* Pages::display($page);
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param array $page Page array
|
||||
* @return string
|
||||
*/
|
||||
public static function display($page)
|
||||
{
|
||||
Theme::getTemplate(((!empty($page['template'])) ? $page['template'] : 'index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Current Template
|
||||
*
|
||||
* <code>
|
||||
* $template = Pages::getCurrentTemplate();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public static function getCurrentTemplate()
|
||||
{
|
||||
return static::$current_template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Monstra Pages
|
||||
*
|
||||
* <code>
|
||||
* Pages::init();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public static function init()
|
||||
{
|
||||
return !isset(self::$instance) and self::$instance = new Pages();
|
||||
}
|
||||
}
|
116
monstra/Plugins.php
Executable file
116
monstra/Plugins.php
Executable file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Plugins
|
||||
{
|
||||
/**
|
||||
* An instance of the Plugins class
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Protected clone method to enforce singleton behavior.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __clone()
|
||||
{
|
||||
// Nothing here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
$plugins_cache_id = '';
|
||||
|
||||
$plugin_manifest = [];
|
||||
$plugin_settings = [];
|
||||
|
||||
// Get Plugins List
|
||||
$plugins_list = Config::get('site.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 (File::exists($_plugin = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yml')) {
|
||||
$plugins_cache_id .= filemtime($_plugin);
|
||||
}
|
||||
}
|
||||
|
||||
// Create Unique Cache ID for Plugins
|
||||
$plugins_cache_id = md5('plugins' . ROOT_DIR . PLUGINS_PATH . $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)) {
|
||||
Config::set('plugins', Cache::driver()->fetch($plugins_cache_id));
|
||||
} else {
|
||||
|
||||
// If Plugins List isnt empty
|
||||
if (is_array($plugins_list) && count($plugins_list) > 0) {
|
||||
|
||||
// Go through...
|
||||
foreach ($plugins_list as $plugin) {
|
||||
if (File::exists($_plugin_manifest = PLUGINS_PATH . '/' . $plugin . '/' . $plugin . '.yml')) {
|
||||
$plugin_manifest = Yaml::parseFile($_plugin_manifest);
|
||||
}
|
||||
|
||||
if (File::exists($_plugin_settings = PLUGINS_PATH . '/' . $plugin . '/settings.yml')) {
|
||||
$plugin_settings = Yaml::parseFile($_plugin_settings);
|
||||
}
|
||||
|
||||
$_plugins_config[File::name($_plugin_manifest)] = array_merge($plugin_manifest, $plugin_settings);
|
||||
}
|
||||
|
||||
Config::set('plugins', $_plugins_config);
|
||||
Cache::driver()->save($plugins_cache_id, $_plugins_config);
|
||||
}
|
||||
}
|
||||
|
||||
// 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')) {
|
||||
include_once PLUGINS_PATH .'/'. $plugin_name .'/'. $plugin_name . '.php';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run Actions on plugins_loaded
|
||||
Action::run('plugins_loaded');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Monstra Plugins
|
||||
*
|
||||
* <code>
|
||||
* Plugins::init();
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public static function init()
|
||||
{
|
||||
if (! isset(self::$instance)) {
|
||||
self::$instance = new Plugins();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
9
monstra/Theme.php
Executable file
9
monstra/Theme.php
Executable file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
class Theme
|
||||
{
|
||||
public static function getTemplate($template = null)
|
||||
{
|
||||
include THEMES_PATH . '/' . Config::get('site.theme') . '/' . $template . '.php';
|
||||
}
|
||||
}
|
59
monstra/Yaml.php
Executable file
59
monstra/Yaml.php
Executable file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Yaml
|
||||
{
|
||||
/**
|
||||
* Parses YAML to array.
|
||||
*
|
||||
* <code>
|
||||
* $array = Yaml::parseFile('file.yml');
|
||||
* </code>
|
||||
*
|
||||
* @access public
|
||||
* @param string $file Path to YAML file.
|
||||
* @return array
|
||||
*/
|
||||
public static function parseFile($file)
|
||||
{
|
||||
return Spyc::YAMLLoad($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses YAML to array.
|
||||
*
|
||||
* <code>
|
||||
* $array = Yaml::parse('title: My title');
|
||||
* </code>
|
||||
*
|
||||
* @param string $string YAML string.
|
||||
* @return array
|
||||
*/
|
||||
public static function parse($string)
|
||||
{
|
||||
return Spyc::YAMLLoadString($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps array to YAML.
|
||||
*
|
||||
* <code>
|
||||
* $yaml = Yaml::dump($data);
|
||||
* </code>
|
||||
*
|
||||
* @param array $data Array.
|
||||
* @return string
|
||||
*/
|
||||
public static function dump($data)
|
||||
{
|
||||
return Spyc::YAMLDump($data, false, false, true);
|
||||
}
|
||||
}
|
15
monstra/boot/actions.php
Executable file
15
monstra/boot/actions.php
Executable file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// Set Monstra Meta Generator
|
||||
Action::add('theme_meta', function () {
|
||||
echo('<meta name="generator" content="Powered by Monstra" />');
|
||||
});
|
34
monstra/boot/defines.php
Executable file
34
monstra/boot/defines.php
Executable file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// Define the path to the root directory (without trailing slash).
|
||||
define('ROOT_DIR', str_replace(DIRECTORY_SEPARATOR, '/', getcwd()));
|
||||
|
||||
// Define the path to the storage directory (without trailing slash).
|
||||
define('SITE_PATH', ROOT_DIR . '/site');
|
||||
|
||||
// Define the path to the storage directory (without trailing slash).
|
||||
define('STORAGE_PATH', SITE_PATH . '/storage');
|
||||
|
||||
// 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 cache directory (without trailing slash).
|
||||
define('ACCOUNTS_PATH', SITE_PATH . '/cache');
|
16
monstra/boot/filters.php
Executable file
16
monstra/boot/filters.php
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// Add Shortcode parser filter
|
||||
Filter::add('content', 'Shortcode::parse', 1);
|
||||
|
||||
// Add Parsedown parser filter
|
||||
Filter::add('content', 'Markdown::parse', 2);
|
22
monstra/boot/shortcodes.php
Executable file
22
monstra/boot/shortcodes.php
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Monstra.
|
||||
*
|
||||
* (c) Romanenko Sergey / Awilum <awilum@msn.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// Add {block name=block-name} shortcode
|
||||
Shortcode::add('block', function ($attributes) {
|
||||
if (isset($attributes['name'])) {
|
||||
return Blocks::get($attributes['name']);
|
||||
}
|
||||
});
|
||||
|
||||
// Add {site_url} shortcode
|
||||
Shortcode::add('site_url', function () {
|
||||
return Url::getBase();
|
||||
});
|
5
robots.txt
Executable file
5
robots.txt
Executable file
@@ -0,0 +1,5 @@
|
||||
User-agent: *
|
||||
Disallow: /monstra/
|
||||
Disallow: /site/plugins/
|
||||
Disallow: /site/config/
|
||||
Disallow: /vendor/
|
0
site/accounts/.gitkeep
Executable file
0
site/accounts/.gitkeep
Executable file
0
site/cache/.gitkeep
vendored
Executable file
0
site/cache/.gitkeep
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
0
|
||||
a:7:{s:5:"title";s:9:"Error 404";s:6:"robots";s:16:"noindex,nofollow";s:3:"url";s:33:"http://localhost:8888/monstra/404";s:7:"content";s:95:"<h2>Error 404</h2>
|
||||
<p>We're sorry but the page you are looking for doesn't appear to exist!</p>";s:4:"slug";s:3:"404";s:8:"keywords";N;s:11:"description";s:54:"Modern Open Source Flat-File Content Management System";}
|
@@ -0,0 +1,2 @@
|
||||
0
|
||||
a:6:{s:3:"url";s:33:"http://localhost:8888/monstra/404";s:7:"content";s:0:"";s:4:"slug";s:3:"404";s:5:"title";N;s:8:"keywords";N;s:11:"description";N;}
|
@@ -0,0 +1,2 @@
|
||||
0
|
||||
s:32:"abfbf2473a6b4c7a46df458d9c10a7f6";
|
@@ -0,0 +1,19 @@
|
||||
0
|
||||
a:7:{s:5:"title";s:7:"Welcome";s:11:"description";s:64:"Monstra is a simple and light-weighted Content Management System";s:8:"template";s:5:"index";s:3:"url";s:29:"http://localhost:8888/monstra";s:7:"content";s:823:"<h2>Monstra is succesfully installed!</h2>
|
||||
<p>You can start editing the content and customising your site.</p>
|
||||
<h3>Edit this Page</h3>
|
||||
<p>To edit this page, simply go to the folder you installed Monstra, and then browse to the <code>/storage/pages/</code> folder and open the <code>index.md</code> file in your editor.</p>
|
||||
<h3>Create a New page</h3>
|
||||
<p>Creating a new page is very simple in Monstra. </p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Launch your text editor and paste this sample text:</p>
|
||||
<pre><code>---
|
||||
title: My New Page
|
||||
---
|
||||
My new page body.</code></pre>
|
||||
</li>
|
||||
<li>Save this file in the <code>/storage/pages/</code> folder as <code>my-new-page.md</code> and its will be available by this url: <a href="http://yoursite/my-new-page">http://yoursite/my-new-page</a></li>
|
||||
</ol>
|
||||
<p>That is it! </p>
|
||||
<p>Block Monstra-docs is not found!</p>";s:4:"slug";s:5:"index";s:8:"keywords";N;}
|
@@ -0,0 +1,2 @@
|
||||
0
|
||||
s:0:"";
|
28
site/config/site.yml
Executable file
28
site/config/site.yml
Executable file
@@ -0,0 +1,28 @@
|
||||
# Site configuration
|
||||
|
||||
title: 'Monstra'
|
||||
description: 'Modern Open Source Flat-File Content Management System'
|
||||
author:
|
||||
email: ''
|
||||
|
||||
|
||||
# System Configuration
|
||||
|
||||
timezone: UTC
|
||||
charset: UTF-8
|
||||
|
||||
theme: default
|
||||
|
||||
plugins:
|
||||
|
||||
pages:
|
||||
flush_cache: false
|
||||
|
||||
errors:
|
||||
display: false
|
||||
|
||||
cache:
|
||||
enabled: false
|
||||
prefix: Monstra
|
||||
driver: auto
|
||||
lifetime: 604800
|
0
site/plugins/.gitkeep
Executable file
0
site/plugins/.gitkeep
Executable file
1
site/storage/blocks/fansoro-docs.md
Executable file
1
site/storage/blocks/fansoro-docs.md
Executable file
@@ -0,0 +1 @@
|
||||
Check **Monstra** documentation for more details: http://monstra.org/documentation
|
7
site/storage/pages/404.md
Executable file
7
site/storage/pages/404.md
Executable file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Error 404
|
||||
robots: noindex,nofollow
|
||||
---
|
||||
|
||||
## Error 404
|
||||
We're sorry but the page you are looking for doesn't appear to exist!
|
15
site/storage/pages/contact.md
Executable file
15
site/storage/pages/contact.md
Executable file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Contact
|
||||
description: Monstra is a simple and light-weighted Content Management System
|
||||
---
|
||||
|
||||
## Stay in touch
|
||||
|
||||
[Monstra official site](http://monstra.org/)
|
||||
[Monstra forum](http://forum.Monstra.org/)
|
||||
[Monstra on Github](https://github.com/Monstra/Monstra)
|
||||
[Monstra Gitter chat room](https://gitter.im/Monstra/Monstra)
|
||||
|
||||
## Follow us on Twitter
|
||||
|
||||
Follow Monstra on Twitter [@Monstra_cms](https://twitter.com/Monstra_cms)
|
28
site/storage/pages/index.md
Executable file
28
site/storage/pages/index.md
Executable file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Welcome
|
||||
description: Monstra is a simple and light-weighted Content Management System
|
||||
template: index
|
||||
---
|
||||
## Monstra 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 Monstra, and then browse to the `/storage/pages/` folder and open the `index.md` file in your editor.
|
||||
|
||||
### Create a New page
|
||||
Creating a new page is very simple in Monstra.
|
||||
|
||||
1. Launch your text editor and paste this sample text:
|
||||
|
||||
```
|
||||
---
|
||||
title: My New Page
|
||||
---
|
||||
My new page body.
|
||||
```
|
||||
|
||||
2. Save this file in the `/storage/pages/` folder as `my-new-page.md` and its will be available by this url: http://yoursite/my-new-page
|
||||
|
||||
That is it!
|
||||
|
||||
{block name=Monstra-docs}
|
0
site/themes/default/assets/css/theme.css
Executable file
0
site/themes/default/assets/css/theme.css
Executable file
BIN
site/themes/default/assets/img/morfy-logo.png
Executable file
BIN
site/themes/default/assets/img/morfy-logo.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
13
site/themes/default/default.yml
Executable file
13
site/themes/default/default.yml
Executable file
@@ -0,0 +1,13 @@
|
||||
name: Default
|
||||
version: 1.0.0
|
||||
description: Default Monstra theme
|
||||
author:
|
||||
name: Sergey Romanenko
|
||||
email: awilum@msn.com
|
||||
url: https://github.com/Awilum
|
||||
homepage: https://github.com/Monstra/Monstra
|
||||
bugs: https://github.com/Monstra/Monstra/issues
|
||||
license: MIT
|
||||
|
||||
# Theme settings
|
||||
enabled: true
|
3
site/themes/default/index.php
Executable file
3
site/themes/default/index.php
Executable file
@@ -0,0 +1,3 @@
|
||||
<?php Theme::getTemplate('partials/head'); ?>
|
||||
index
|
||||
<?php Theme::getTemplate('partials/footer'); ?>
|
3
site/themes/default/partials/footer.php
Executable file
3
site/themes/default/partials/footer.php
Executable file
@@ -0,0 +1,3 @@
|
||||
<?php Theme::getTemplate('tail'); ?>
|
||||
</body>
|
||||
</html>
|
18
site/themes/default/partials/head.php
Executable file
18
site/themes/default/partials/head.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="icon" href="../../../../favicon.ico">
|
||||
|
||||
<title>Cover Template for Bootstrap</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="../../../../dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="cover.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
1
site/themes/default/partials/navigation.php
Executable file
1
site/themes/default/partials/navigation.php
Executable file
@@ -0,0 +1 @@
|
||||
navigation here
|
5
site/themes/default/partials/tail.php
Executable file
5
site/themes/default/partials/tail.php
Executable file
@@ -0,0 +1,5 @@
|
||||
{* Bootstrap core JavaScript *}
|
||||
{* Placed at the end of the document so the pages load faster *}
|
||||
<script src="<?php echo Url::getBase(); ?>/themes/<?php echo Config::get('site.theme'); ?>/bower_components/jquery/dist/jquery.min.js"></script>
|
||||
<script src="<?php echo Url::getBase(); ?>}/themes/<?php echo Config::get('site.theme'); ?>/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<?php Action::run('theme_footer'); ?>
|
Reference in New Issue
Block a user