1
0
mirror of https://github.com/monstra-cms/monstra.git synced 2025-07-31 18:30:20 +02:00

Core Improvements: Next Round #79 #80

This commit is contained in:
Awilum
2013-01-08 21:07:01 +02:00
parent b7dcc5be49
commit 0c984788c0
23 changed files with 1534 additions and 1521 deletions

View File

@@ -23,7 +23,7 @@ define('BACKEND', true);
define('MONSTRA_ACCESS', true);
// Load bootstrap file
require_once(ROOT.'/engine/_init.php');
require_once ROOT. DS .'engine'. DS .'_init.php';
// Errors var when users login failed
$login_error = '';

View File

@@ -49,6 +49,18 @@ class Core
*/
public static $environment = Core::PRODUCTION;
/**
* Monstra environment names
*
* @var array
*/
public static $environment_names = array(
Core::PRODUCTION => 'production',
Core::STAGING => 'staging',
Core::TESTING => 'testing',
Core::DEVELOPMENT => 'development',
);
/**
* Protected clone method to enforce singleton behavior.
*
@@ -60,11 +72,13 @@ class Core
}
/**
* Construct
* Protected Construct
*/
protected function __construct()
{
// Load core defines
/**
* Load core defines
*/
Core::loadDefines();
/**
@@ -106,20 +120,61 @@ class Core
/**
* Include Gelato Library
*/
include ROOT . '/libraries/Gelato/Gelato.php';
include ROOT . DS . 'libraries'. DS .'Gelato'. DS .'Gelato.php';
// Start session
/**
* Map all Monstra Classes
*/
ClassLoader::mapClasses(array(
// Site Modules
'Security' => ROOT . DS .'engine'. DS .'Security.php',
'Uri' => ROOT . DS .'engine'. DS .'Uri.php',
'Site' => ROOT . DS .'engine'. DS .'Site.php',
'Alert' => ROOT . DS .'engine'. DS .'Alert.php',
// XMLDB API
'XML' => ROOT . DS .'engine'. DS .'Xmldb'. DS .'XML.php',
'DB' => ROOT . DS .'engine'. DS .'Xmldb'. DS .'DB.php',
'Table' => ROOT . DS .'engine'. DS .'Xmldb'. DS .'Table.php',
// Plugin API
'Plugin' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Plugin.php',
'Frontend' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Frontend.php',
'Backend' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Backend.php',
'Action' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Action.php',
'Filter' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Filter.php',
'View' => ROOT . DS .'engine'. DS .'Plugin'. DS .'View.php',
'I18n' => ROOT . DS .'engine'. DS .'Plugin'. DS .'I18n.php',
'Stylesheet' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Stylesheet.php',
'Javascript' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Javascript.php',
'Navigation' => ROOT . DS .'engine'. DS .'Plugin'. DS .'Navigation.php',
// Option API
'Option' => ROOT . DS .'engine'. DS .'Option.php',
// Shortcode API
'Shortcode' => ROOT . DS .'engine'. DS .'Shortcode.php',
));
/**
* Start session
*/
Session::start();
// Init ORM
/**
* Init Idiorm
*/
if (defined('MONSTRA_DB_DSN')) {
require_once(ROOT . '/libraries/Idiorm/Idiorm.php');
require_once ROOT . DS . 'libraries'. DS .'Idiorm'. DS .'Idiorm.php';
Orm::configure(MONSTRA_DB_DSN);
Orm::configure('username', MONSTRA_DB_USER);
Orm::configure('password', MONSTRA_DB_PASSWORD);
}
// Auto cleanup if MONSTRA_DEBUG is true
/**
* Auto cleanup if MONSTRA_DEBUG is TRUE
*/
if (Core::$environment == Core::DEVELOPMENT) {
// Cleanup minify
@@ -129,55 +184,51 @@ class Core
if (count($namespaces = Dir::scan(CACHE)) > 0) foreach ($namespaces as $namespace) Dir::delete(CACHE . DS . $namespace);
}
// Set cache dir
/**
* Set Cache dir
*/
Cache::configure('cache_dir', CACHE);
// Load Securitu module
require_once(ROOT . '/engine/Security.php');
// Load URI module
require_once(ROOT . '/engine/Uri.php');
// Load XMLDB API module
require_once(ROOT . '/engine/Xmldb.php');
// Load Options API module
require_once(ROOT . '/engine/Options.php');
// Init Options API module
/**
* Init Options API module
*/
Option::init();
// Set default timezone
/**
* Set default timezone
*/
@ini_set('date.timezone', Option::get('timezone'));
if (function_exists('date_default_timezone_set')) date_default_timezone_set(Option::get('timezone')); else putenv('TZ='.Option::get('timezone'));
// Sanitize URL to prevent XSS - Cross-site scripting
/**
* Sanitize URL to prevent XSS - Cross-site scripting
*/
Security::runSanitizeURL();
// Load Plugins API module
require_once(ROOT . '/engine/Plugins.php');
// Load Shortcodes API module
require_once(ROOT . '/engine/Shortcodes.php');
// Load default
/**
* Load default
*/
Core::loadPluggable();
// Init I18n
/**
* Init I18n
*/
I18n::init(Option::get('language'));
// Init Plugins API
/**
* Init Plugins API
*/
Plugin::init();
// Init Notification service
/**
* Init Notification service
*/
Notification::init();
// Load Site module
require_once(ROOT . '/engine/Site.php');
// Init site module
/**
* Init site module
*/
if( ! BACKEND) Site::init();
}
/**
@@ -185,13 +236,8 @@ class Core
*/
protected static function loadDefines()
{
$environments = array(1 => 'production',
2 => 'staging',
3 => 'testing',
4 => 'development');
$root_defines = ROOT . DS . 'boot' . DS . 'defines.php';
$environment_defines = ROOT . DS . 'boot' . DS . $environments[Core::$environment] . DS . 'defines.php';
$environment_defines = ROOT . DS . 'boot' . DS . Core::$environment_names[Core::$environment] . DS . 'defines.php';
$monstra_defines = ROOT . DS . 'engine' . DS . 'boot' . DS . 'defines.php';
if (file_exists($root_defines)) {
@@ -210,13 +256,8 @@ class Core
*/
protected static function loadPluggable()
{
$environments = array(1 => 'production',
2 => 'staging',
3 => 'testing',
4 => 'development');
$root_pluggable = ROOT . DS . 'boot';
$environment_pluggable = ROOT . DS . 'boot' . DS . $environments[Core::$environment];
$environment_pluggable = ROOT . DS . 'boot' . DS . Core::$environment_names[Core::$environment];
$monstra_pluggable = ROOT . DS . 'engine' . DS . 'boot';
if (file_exists($root_pluggable . DS . 'filters.php')) {
@@ -226,7 +267,7 @@ class Core
} elseif (file_exists($monstra_pluggable . DS . 'filters.php')) {
include $monstra_pluggable . DS . 'filters.php';
} else {
throw new RuntimeException("The pluggable file does not exist.");
throw new RuntimeException("The pluggable filters.php file does not exist.");
}
if (file_exists($root_pluggable . DS . 'actions.php')) {
@@ -236,7 +277,7 @@ class Core
} elseif (file_exists($monstra_pluggable . DS . 'actions.php')) {
include $monstra_pluggable . DS . 'actions.php';
} else {
throw new RuntimeException("The pluggable file does not exist.");
throw new RuntimeException("The pluggable actions.php file does not exist.");
}
if (file_exists($root_pluggable . DS . 'shortcodes.php')) {
@@ -246,7 +287,7 @@ class Core
} elseif (file_exists($monstra_pluggable . DS . 'shortcodes.php')) {
include $monstra_pluggable . DS . 'shortcodes.php';
} else {
throw new RuntimeException("The pluggable file does not exist.");
throw new RuntimeException("The pluggable shortcodes.php file does not exist.");
}
}

113
engine/Plugin/Action.php Normal file
View File

@@ -0,0 +1,113 @@
<?php
/**
* Action class
*/
class Action
{
/**
* Actions
*
* @var array
*/
public static $actions = array();
/**
* 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>
*
* @param string $action_name Action name
* @param string $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.
Action::$actions[] = array(
'action_name' => (string) $action_name,
'function' => (string) $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>
*
* @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 = array(), $return = false)
{
// Redefine arguments
$action_name = (string) $action_name;
$return = (bool) $return;
// Run action
if (count(Action::$actions) > 0) {
// Sort actions by priority
$actions = Arr::subvalSort(Action::$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']);
}
}
}
}
}
}
}

10
engine/Plugin/Backend.php Normal file
View File

@@ -0,0 +1,10 @@
<?php
/**
* Backend class
*/
class Backend
{
public static function main() { }
}

113
engine/Plugin/Filter.php Normal file
View File

@@ -0,0 +1,113 @@
<?php
/**
* Filter class
*/
class Filter
{
/**
* Filters
*
* @var array
*/
public static $filters = array();
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
// Nothing here
}
/**
* Apply filters
*
* <code>
* Filter::apply('content', $content);
* </code>
*
* @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(Filter::$filters[$filter_name])) {
return $value;
}
foreach (Filter::$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>
*
* @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 = (string) $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(Filter::$filters[$filter_name]["$priority"])) {
foreach (Filter::$filters[$filter_name]["$priority"] as $filter) {
if ($filter['function'] == $function_to_add) {
return true;
}
}
}
Filter::$filters[$filter_name]["$priority"][] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
// Sort
ksort(Filter::$filters[$filter_name]["$priority"]);
return true;
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* Frontend class
*/
class Frontend
{
public static function main() { }
public static function title() { return ''; }
public static function description() { return ''; }
public static function keywords() { return ''; }
public static function template() { return 'index'; }
public static function content() { return ''; }
}

188
engine/Plugin/I18n.php Normal file
View File

@@ -0,0 +1,188 @@
<?php
/**
* I18n class
*/
class I18n
{
/**
* Locales array
*
* @var array
*/
public static $locales = array(
'ar' => 'العربية',
'bg' => 'Български',
'ca' => 'Català',
'cs' => 'Česky',
'da' => 'Dansk',
'de' => 'Deutsch',
'el' => 'Ελληνικά',
'en' => 'English',
'es' => 'Español',
'fi' => 'Suomi',
'fr' => 'Français',
'gl' => 'Galego',
'hu' => 'Magyar',
'it' => 'Italiano',
'ja' => '日本語',
'lt' => 'Lietuvių',
'nl' => 'Nederlands',
'no' => 'Norsk',
'pl' => 'Polski',
'pt' => 'Português',
'pt-br' => 'Português do Brasil',
'ru' => 'Русский',
'sk' => 'Slovenčina',
'sl' => 'Slovenščina',
'sv' => 'Svenska',
'tr' => 'Türkçe',
'uk' => 'Українська',
'zh' => '中文',
);
/**
* Dictionary
*
* @var array
*/
public static $dictionary = array();
/**
* An instance of the I18n class
*
* @var I18n
*/
protected static $instance = null;
/**
* Initializing I18n
*
* @param string $dir Plugins directory
*/
public static function init($locale)
{
if ( ! isset(self::$instance)) self::$instance = new I18n($locale);
return self::$instance;
}
/**
* Protected clone method to enforce singleton behavior.
*
* @access protected
*/
protected function __clone()
{
// Nothing here.
}
/**
* Construct
*/
protected function __construct($locale)
{
// Redefine arguments
$locale = (string) $locale;
// Get lang table for current locale
$lang_table = Cache::get('i18n', $locale);
// If lang_table is empty then create new
if (! $lang_table) {
// Get plugins Table
$plugins = new Table('plugins');
// Get all plugins
$records = $plugins->select(null, 'all', null, array('location', 'priority'), 'priority', 'ASC');
// Init var
$lang_table = array();
// Loop through each installed plugin
foreach ($records as $record) {
if (is_dir(ROOT . DS . dirname($record['location']) . DS . 'languages')) {
// Init var
$t = array();
// Check lang file
if (file_exists(ROOT . DS . dirname($record['location']) . DS . 'languages' . DS . $locale . '.lang.php')) {
// Merge the language strings into the sub table
$t = array_merge($t, include ROOT . DS . dirname($record['location']) . DS . 'languages' . DS . $locale . '.lang.php');
}
// Append the sub table, preventing less specific language files from overloading more specific files
$lang_table += $t;
}
}
// Save lang table for current locale
Cache::put('i18n', $locale, $lang_table);
// Update dictionary
I18n::$dictionary = $lang_table;
}
// Update dictionary
I18n::$dictionary = $lang_table;
}
/**
* Returns translation of a string. If no translation exists, the original
* string will be returned. No parameters are replaced.
*
* <code>
* $hello = I18n::find('Hello friends, my name is :name', 'namespace');
* <code>
*
* @param string $string Text to translate
* @param string $namespace Namespace
* @return string
*/
public static function find($string, $namespace = null)
{
// Redefine arguments
$string = (string) $string;
// Return string
if (isset(I18n::$dictionary[$namespace][$string])) return I18n::$dictionary[$namespace][$string]; else return $string;
}
}
/**
* Global Translation/internationalization function.
* Accepts an English string and returns its translation
* to the active system language. If the given string is not available in the
* current dictionary the original English string will be returned.
*
* <code>
* // Display a translated message
* echo __('Hello, world', 'namespace');
*
* // With parameter replacement
* echo __('Hello, :user', 'namespace', array(':user' => $username));
* </code>
*
* @global array $dictionary Dictionary
* @param string $string String to translate
* @param array $values Values to replace in the translated text
* @param string $namespace Namespace
* @return string
*/
function __($string, $namespace = null, array $values = null)
{
// Redefine arguments
$string = (string) $string;
// Find string in dictionary
$string = I18n::find($string, $namespace);
// Return string
return empty($values) ? $string : strtr($string, $values);
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* Javascript class
*/
class Javascript
{
/**
* Javascripts
*
* @var array
*/
public static $javascripts = array();
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
// Nothing here
}
/**
* Add javascript
*
* <code>
* Javascript::add('path/to/my/script1.js');
* Javascript::add('path/to/my/script2.js', 'frontend', 11);
* Javascript::add('path/to/my/script3.js', 'backend', 12);
* <code>
*
* @param string $file File path
* @param string $load Load script on frontend, backend or both
* @param inteeer $priority Priority default is 10
*/
public static function add($file, $load = 'frontend', $priority = 10)
{
Javascript::$javascripts[] = array(
'file' => (string) $file,
'load' => (string) $load,
'priority' => (int) $priority,
);
}
/**
* Combine and load site javascript
*/
public static function load()
{
$backend_site_js_path = MINIFY . DS . 'backend_site.minify.js';
$frontend_site_js_path = MINIFY . DS . 'frontend_site.minify.js';
// Load javascripts
if (count(Javascript::$javascripts) > 0) {
$backend_buffer = '';
$backend_regenerate = false;
$frontend_buffer = '';
$frontend_regenerate = false;
// Sort javascripts by priority
$javascripts = Arr::subvalSort(Javascript::$javascripts, 'priority');
if (BACKEND) {
// Build backend site javascript
foreach ($javascripts as $javascript) {
if ((file_exists(ROOT . DS . $javascript['file'])) and (($javascript['load'] == 'backend') or ($javascript['load'] == 'both')) ) {
if ( ! file_exists($backend_site_js_path) or filemtime(ROOT . DS . $javascript['file']) > filemtime($backend_site_js_path)) {
$backend_regenerate = true;
break;
}
}
}
// Regenerate site javascript
if ($backend_regenerate) {
foreach ($javascripts as $javascript) {
if ((file_exists(ROOT . DS . $javascript['file'])) and (($javascript['load'] == 'backend') or ($javascript['load'] == 'both')) ) {
$backend_buffer .= file_get_contents(ROOT . DS . $javascript['file']);
}
}
file_put_contents($backend_site_js_path, $backend_buffer);
$backend_regenerate = false;
}
} else {
// Build frontend site javascript
foreach ($javascripts as $javascript) {
if ((file_exists(ROOT . DS . $javascript['file'])) and (($javascript['load'] == 'frontend') or ($javascript['load'] == 'both')) ) {
if ( ! file_exists($frontend_site_js_path) or filemtime(ROOT . DS . $javascript['file']) > filemtime($frontend_site_js_path)) {
$frontend_regenerate = true;
break;
}
}
}
// Regenerate site javascript
if ($frontend_regenerate) {
foreach ($javascripts as $javascript) {
if ((file_exists(ROOT . DS . $javascript['file'])) and (($javascript['load'] == 'frontend') or ($javascript['load'] == 'both')) ) {
$frontend_buffer .= file_get_contents(ROOT . DS . $javascript['file']);
}
}
file_put_contents($frontend_site_js_path, $frontend_buffer);
$frontend_regenerate = false;
}
}
// Render
if (BACKEND) {
echo '<script type="text/javascript" src="'.Option::get('siteurl').'tmp/minify/backend_site.minify.js"></script>';
} else {
echo '<script type="text/javascript" src="'.Option::get('siteurl').'tmp/minify/frontend_site.minify.js"></script>';
}
}
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* Navigation class
*/
class Navigation
{
/**
* Items
*
* @var array
*/
public static $items = array();
/**
* Navigation types
*/
const LEFT = 1;
const TOP = 2;
/**
* Add new item
*
* <code>
* // Add link for left navigation
* Navigation::add(__('Blog'), 'content', 'blog', 11);
*
* // Add link for top navigation
* Navigation::add(__('View site'), 'top', 'http://site.com/', 11, Navigation::TOP, true);
* <code>
*
* @param string $name Name
* @param string $category Category
* @param stirng $link Link
* @param integer $priority Priority. Default is 10
* @param integer $type Type. Default is LEFT
* @param bool $external External or not. Default is false
*/
public static function add($name, $category, $id, $priority = 10, $type = Navigation::LEFT, $external = false)
{
Navigation::$items[] = array(
'name' => (string) $name,
'category' => (string) $category,
'id' => (string) $id,
'priority' => (int) $priority,
'type' => (int) $type,
'external' => (bool) $external,
);
}
/**
* Draw items
*
* <code>
* Navigation::draw('content');
* Navigation::draw('top', Navigation::TOP);
* <code>
*
* @param string $category Category
* @param integer $type Type. Default is LEFT
*/
public static function draw($category, $type = Navigation::LEFT)
{
// Sort items by priority
$items = Arr::subvalSort(Navigation::$items, 'priority');
// Draw left navigation
if ($type == Navigation::LEFT) {
// Loop trough the items
foreach ($items as $item) {
// If current plugin id == selected item id then set class to current
if (Request::get('id') == $item['id'] && $item['external'] == false) $class = 'class = "current" '; else $class = '';
// If current category == item category and navigation type is left them draw this item
if ($item['category'] == $category && $item['type'] == Navigation::LEFT) {
// Is external item id or not ?
if ($item['external'] == false) {
echo '<li><a '.$class.'href="index.php?id='.$item['id'].'">'.$item['name'].'</a></li>';
} else {
echo '<li><a target="_blank" href="'.$item['id'].'">'.$item['name'].'</a></li>';
}
}
}
} elseif ($type == Navigation::TOP) {
// Draw top navigation
foreach ($items as $item) {
if ($item['category'] == $category && $item['type'] == Navigation::TOP) {
if ($item['external'] == false) {
echo '<a class="btn btn-small btn-inverse" href="index.php?id='.$item['id'].'">'.$item['name'].'</a>'.Html::nbsp(2);
} else {
echo '<a target="_blank" class="btn btn-small btn-inverse" href="'.$item['id'].'">'.$item['name'].'</a>'.Html::nbsp(2);
}
}
}
}
}
}

172
engine/Plugin/Plugin.php Normal file
View File

@@ -0,0 +1,172 @@
<?php
/**
* Plugin class
*/
class Plugin
{
/**
* Plugins
*
* @var array
*/
public static $plugins = array();
/**
* Components
*
* @var array
*/
public static $components = array();
/**
* An instance of the Plugin class
*
* @var plugin
*/
protected static $instance = null;
/**
* Initializing plugins
*
* @return Plugin
*/
public static function init()
{
if ( ! isset(self::$instance)) self::$instance = new Plugin();
return self::$instance;
}
/**
* Protected clone method to enforce singleton behavior.
*
* @access protected
*/
protected function __clone()
{
// Nothing here.
}
/**
* Construct
*/
protected function __construct()
{
// Get plugins Table
$plugins = new Table('plugins');
// Select all plugins
$records = $plugins->select(null, 'all', null, array('location', 'frontend', 'backend', 'status', 'priority'), 'priority', 'ASC');
// Now include plugins from $records plugins array
// If plugin is active then load it to the system.
foreach ($records as $record) {
if ($record['status'] == 'active') {
include_once ROOT . DS . $record['location'];
}
}
}
/**
* Get plugin admin
*
* <code>
* // Get admin for Blog plugin
* Plugin::admin('blog');
* </code>
*
* @param string $plug Plugin Name
* @param string $alt_folder Alternative plugin folder
*/
public static function admin($plug, $alt_folder = null)
{
// Redefine arguments
$plug = (string) $plug;
// Plugin admin extension
$ext = '.admin.php';
// Plugin admin can be loaded only in backend
if (BACKEND) {
// Plugin admin folder
if ( ! empty($alt_folder)) {
$folder = $alt_folder . DS . strtolower($plug);
} else {
$folder = strtolower($plug);
}
// Path to plugin admin file
$path = PLUGINS . DS . $folder . DS . $plug . $ext;
// Load plugin admin
if (File::exists($path)) {
include $path;
}
}
}
/**
* Register new plugin in system
*
* <code>
* // Register plugin
* Plugin::register( __FILE__,
* __('Blog'),
* __('Blog plugin'),
* '1.0.0',
* 'Awilum',
* 'http://example.org/',
* 'blog');
* </code>
*
* @param string $file Plugin file
* @param string $title Plugin title
* @param string $description Plugin description
* @param string $version Plugin version
* @param string $author Plugin author
* @param string $author_uri Plugin author uri
* @param string $component Plugin as component
* @param boolean $box Plugin as box
*/
public static function register($file, $title, $description = null, $version = null, $author = null, $author_uri = null, $component = null, $box = false)
{
// Redefine arguments
$file = (string) $file;
$title = (string) $title;
$description = ($description === null) ? null : (string) $description;
$version = ($version === null) ? null : (string) $version;
$author = ($author === null) ? null : (string) $author;
$author_uri = ($author_uri === null) ? null : (string) $author_uri;
$component = ($component === null) ? null : (string) $component;
$box = (bool) $box;
// Get plugin id from name.plugin.php
$id = strtolower(basename($file, '.plugin.php'));
// Set plugin privilege 'box' if $box is true
if ($box) $privilege = 'box'; else $privilege = '';
// Register plugin in global plugins array.
Plugin::$plugins[$id] = array(
'id' => $id,
'title' => $title,
'privilege' => $privilege,
'version' => $version,
'description' => $description,
'author' => $author,
'author_uri' => $author_uri,
);
// Add plugin as a component
// Plugin - component will be available at the link sitename/component_name
// Example:
// www.example.org/guestbook
// www.example.org/news
if ( ! empty($component)) {
Plugin::$components[] = $component;
}
}
}

View File

@@ -0,0 +1,148 @@
<?php
/**
* Stylesheet class
*/
class Stylesheet
{
/**
* Stylesheets
*
* @var array
*/
public static $stylesheets = array();
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
// Nothing here
}
/**
* Add stylesheet
*
* <code>
* Stylesheet::add('path/to/my/stylesheet1.css');
* Stylesheet::add('path/to/my/stylesheet2.css', 'frontend', 11);
* Stylesheet::add('path/to/my/stylesheet3.css', 'backend',12);
* <code>
*
* @param string $file File path
* @param string $load Load stylesheet on frontend, backend or both
* @param integer $priority Priority. Default is 10
*/
public static function add($file, $load = 'frontend', $priority = 10)
{
Stylesheet::$stylesheets[] = array(
'file' => (string) $file,
'load' => (string) $load,
'priority' => (int) $priority,
);
}
/**
* Minify, combine and load site stylesheet
*/
public static function load()
{
$backend_site_css_path = MINIFY . DS . 'backend_site.minify.css';
$frontend_site_css_path = MINIFY . DS . 'frontend_site.minify.css';
// Load stylesheets
if (count(Stylesheet::$stylesheets) > 0) {
$backend_buffer = '';
$backend_regenerate = false;
$frontend_buffer = '';
$frontend_regenerate = false;
// Sort stylesheets by priority
$stylesheets = Arr::subvalSort(Stylesheet::$stylesheets, 'priority');
if (BACKEND) {
// Build backend site stylesheets
foreach ($stylesheets as $stylesheet) {
if ((file_exists(ROOT . DS . $stylesheet['file'])) and (($stylesheet['load'] == 'backend') or ($stylesheet['load'] == 'both')) ) {
if ( ! file_exists($backend_site_css_path) or filemtime(ROOT . DS . $stylesheet['file']) > filemtime($backend_site_css_path)) {
$backend_regenerate = true;
break;
}
}
}
// Regenerate site stylesheet
if ($backend_regenerate) {
foreach ($stylesheets as $stylesheet) {
if ((file_exists(ROOT . DS . $stylesheet['file'])) and (($stylesheet['load'] == 'backend') or ($stylesheet['load'] == 'both')) ) {
$backend_buffer .= file_get_contents(ROOT . DS . $stylesheet['file']);
}
}
$backend_buffer = Stylesheet::parseVariables($backend_buffer);
file_put_contents($backend_site_css_path, Minify::css($backend_buffer));
$backend_regenerate = false;
}
} else {
// Build frontend site stylesheets
foreach ($stylesheets as $stylesheet) {
if ((file_exists(ROOT . DS . $stylesheet['file'])) and (($stylesheet['load'] == 'frontend') or ($stylesheet['load'] == 'both')) ) {
if ( ! file_exists($frontend_site_css_path) or filemtime(ROOT . DS . $stylesheet['file']) > filemtime($frontend_site_css_path)) {
$frontend_regenerate = true;
break;
}
}
}
// Regenerate site stylesheet
if ($frontend_regenerate) {
foreach ($stylesheets as $stylesheet) {
if ((file_exists(ROOT . DS . $stylesheet['file'])) and (($stylesheet['load'] == 'frontend') or ($stylesheet['load'] == 'both')) ) {
$frontend_buffer .= file_get_contents(ROOT . DS . $stylesheet['file']);
}
}
$frontend_buffer = Stylesheet::parseVariables($frontend_buffer);
file_put_contents($frontend_site_css_path, Minify::css($frontend_buffer));
$frontend_regenerate = false;
}
}
// Render
if (BACKEND) {
echo '<link rel="stylesheet" href="'.Option::get('siteurl').'tmp/minify/backend_site.minify.css'.'" type="text/css" />';
} else {
echo '<link rel="stylesheet" href="'.Option::get('siteurl').'tmp/minify/frontend_site.minify.css'.'" type="text/css" />';
}
}
}
/**
* CSS Parser
*/
public static function parseVariables($frontend_buffer)
{
return str_replace(array('@site_url',
'@theme_site_url',
'@theme_admin_url'),
array(Option::get('siteurl'),
Option::get('siteurl').'public/themes/'.Option::get('theme_site_name'),
Option::get('siteurl').'admin/themes/'.Option::get('theme_admin_name')),
$frontend_buffer);
}
}

227
engine/Plugin/View.php Normal file
View File

@@ -0,0 +1,227 @@
<?php
/**
* View class
*/
class View
{
/**
* Path to view file.
*
* @var string
*/
protected $view_file;
/**
* View variables.
*
* @var array
*/
protected $vars = array();
/**
* Global view variables.
*
* @var array
*/
protected static $global_vars = array();
/**
* The output.
*
* @var string
*/
protected $output;
/**
* Create a new view object.
*
* <code>
* // Create new view object
* $view = new View('blog/views/backend/index');
*
* // Assign some new variables
* $view->assign('msg', 'Some message...');
*
* // Get view
* $output = $view->render();
*
* // Display view
* echo $output;
* </code>
*
* @param string $view Name of the view file
* @param array $variables Array of view variables
*/
public function __construct($view, array $variables = array())
{
// Set view file
// From current theme folder or from plugin folder
if (File::exists($theme_view_file = THEMES_SITE . DS . Site::theme() . DS . $view . '.view.php') && BACKEND == false) {
$this->view_file = $theme_view_file;
} else {
$this->view_file = PLUGINS . DS . $view . '.view.php';
}
// Is view file exists ?
if (file_exists($this->view_file) === false) {
throw new RuntimeException(vsprintf("%s(): The '%s' view does not exist.", array(__METHOD__, $view)));
}
// Set view variables
$this->vars = $variables;
}
/**
* View factory
*
* <code>
* // Create new view object, assign some variables
* // and displays the rendered view in the browser.
* View::factory('blog/views/backend/index')
* ->assign('msg', 'Some message...')
* ->display();
* </code>
*
* @param string $view Name of the view file
* @param array $variables Array of view variables
* @return View
*/
public static function factory($view, array $variables = array())
{
return new View($view, $variables);
}
/**
* Assign a view variable.
*
* <code>
* $view->assign('msg', 'Some message...');
* </code>
*
* @param string $key Variable name
* @param mixed $value Variable value
* @param boolean $global Set variable available in all views
* @return View
*/
public function assign($key, $value, $global = false)
{
// Assign a new view variable (global or locale)
if ($global === false) {
$this->vars[$key] = $value;
} else {
View::$global_vars[$key] = $value;
}
return $this;
}
/**
* Include the view file and extracts the view variables before returning the generated output.
*
* <code>
* // Get view
* $output = $view->render();
*
* // Display output
* echo $output;
* </code>
*
* @param string $filter Callback function used to filter output
* @return string
*/
public function render($filter = null)
{
// Is output empty ?
if (empty($this->output)) {
// Extract variables as references
extract(array_merge($this->vars, View::$global_vars), EXTR_REFS);
// Turn on output buffering
ob_start();
// Include view file
include($this->view_file);
// Output...
$this->output = ob_get_clean();
}
// Filter output ?
if ($filter !== null) {
$this->output = call_user_func($filter, $this->output);
}
// Return output
return $this->output;
}
/**
* Displays the rendered view in the browser.
*
* <code>
* $view->display();
* </code>
*
*/
public function display()
{
echo $this->render();
}
/**
* Magic setter method that assigns a view variable.
*
* @param string $key Variable name
* @param mixed $value Variable value
*/
public function __set($key, $value)
{
$this->vars[$key] = $value;
}
/**
* Magic getter method that returns a view variable.
*
* @param string $key Variable name
* @return mixed
*/
public function __get($key)
{
if (isset($this->vars[$key])) {
return $this->vars[$key];
}
}
/**
* Magic isset method that checks if a view variable is set.
*
* @param string $key Variable name
* @return boolean
*/
public function __isset($key)
{
return isset($this->vars[$key]);
}
/**
* Magic unset method that unsets a view variable.
*
* @param string $key Variable name
*/
public function __unset($key)
{
unset($this->vars[$key]);
}
/**
* Method that magically converts the view object into a string.
*
* @return string
*/
public function __toString()
{
return $this->render();
}
}

File diff suppressed because it is too large Load Diff

71
engine/Xmldb/DB.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
/**
* DB Class
*/
class DB
{
/**
* XMLDB directory
*
* @var string
*/
public static $db_dir = STORAGE;
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
// Nothing here
}
/**
* Configure the settings of XMLDB
*
* @param mixed $setting Setting name
* @param mixed $value Setting value
*/
public static function configure($setting, $value)
{
if (property_exists("db", $setting)) DB::$$setting = $value;
}
/**
* Create new database
*
* @param string $db_name Database name
* @param integer $mode Mode
* @return boolean
*/
public static function create($db_name, $chmod = 0775)
{
// Redefine vars
$db_name = (string) $db_name;
// Create
if (is_dir(DB::$db_dir . '/' . $db_name)) return false;
return mkdir(DB::$db_dir . '/' . $db_name, $chmod);
}
/**
* Drop database
*
* @param string $db_name Database name
* @return boolean
*/
public static function drop($db_name)
{
// Redefine vars
$db_name = (string) $db_name;
// Drop
if (is_dir(DB::$db_dir . '/' . $db_name)){$ob=scandir(DB::$db_dir . '/' . $db_name); foreach ($ob as $o) {if ($o!='.'&&$o!='..') {if(filetype(DB::$db_dir . '/' . $db_name.'/'.$o)=='dir')DB::drop(DB::$db_dir . '/' . $db_name.'/'.$o); else unlink(DB::$db_dir . '/' . $db_name.'/'.$o);}}}
reset($ob); rmdir(DB::$db_dir . '/' . $db_name);
}
}

View File

@@ -1,177 +1,5 @@
<?php defined('MONSTRA_ACCESS') or die('No direct script access.');
<?php
/**
* Monstra XMLDB API module.
*
* Use SimpleXML and xPath to navigate through elements and attributes in an XML document.
* @link http://www.w3schools.com/xml/
* @link http://www.w3schools.com/xpath/
*
* @package Monstra
* @subpackage Engine
* @author Romanenko Sergey / Awilum
* @copyright 2012 Romanenko Sergey / Awilum
* @version $Id$
* @since 1.0.0
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* Monstra is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYING.txt for copyright notices and details.
* @filesource
*/
/**
* XML class
*/
class XML
{
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
// Nothing here
}
/**
* Create safe xml data. Removes dangerous characters for string.
*
* <code>
* $xml_safe = XML::safe($xml_unsafe);
* </code>
*
* @param string $str String
* @param boolean $flag Flag
* @return string
*/
public static function safe($str, $flag = true)
{
// Redefine vars
$str = (string) $str;
$flag = (bool) $flag;
// Remove invisible chars
$non_displayables = array('/%0[0-8bcef]/', '/%1[0-9a-f]/', '/[\x00-\x08]/', '/\x0b/', '/\x0c/', '/[\x0e-\x1f]/');
do {
$cleaned = $str;
$str = preg_replace($non_displayables, '', $str);
} while ($cleaned != $str);
// htmlspecialchars
if ($flag) $str = htmlspecialchars($str, ENT_QUOTES, 'utf-8');
// Return safe string
return $str;
}
/**
* Get XML file
*
* <code>
* $xml_file = XML::loadFile('path/to/file.xml');
* </code>
*
* @param string $file File name
* @param boolean $force Method
* @return array
*/
public static function loadFile($file, $force = false)
{
// Redefine vars
$file = (string) $file;
$force = (bool) $force;
// For CMS API XML file force method
if ($force) {
$xml = file_get_contents($file);
$data = simplexml_load_string($xml);
return $data;
} else {
if (file_exists($file) && is_file($file)) {
$xml = file_get_contents($file);
$data = simplexml_load_string($xml);
return $data;
} else {
return false;
}
}
}
}
/**
* DB Class
*/
class DB
{
/**
* XMLDB directory
*
* @var string
*/
public static $db_dir = STORAGE;
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
// Nothing here
}
/**
* Configure the settings of XMLDB
*
* @param mixed $setting Setting name
* @param mixed $value Setting value
*/
public static function configure($setting, $value)
{
if (property_exists("db", $setting)) DB::$$setting = $value;
}
/**
* Create new database
*
* @param string $db_name Database name
* @param integer $mode Mode
* @return boolean
*/
public static function create($db_name, $chmod = 0775)
{
// Redefine vars
$db_name = (string) $db_name;
// Create
if (is_dir(DB::$db_dir . '/' . $db_name)) return false;
return mkdir(DB::$db_dir . '/' . $db_name, $chmod);
}
/**
* Drop database
*
* @param string $db_name Database name
* @return boolean
*/
public static function drop($db_name)
{
// Redefine vars
$db_name = (string) $db_name;
// Drop
if (is_dir(DB::$db_dir . '/' . $db_name)){$ob=scandir(DB::$db_dir . '/' . $db_name); foreach ($ob as $o) {if ($o!='.'&&$o!='..') {if(filetype(DB::$db_dir . '/' . $db_name.'/'.$o)=='dir')DB::drop(DB::$db_dir . '/' . $db_name.'/'.$o); else unlink(DB::$db_dir . '/' . $db_name.'/'.$o);}}}
reset($ob); rmdir(DB::$db_dir . '/' . $db_name);
}
}
/**
* Table class

84
engine/Xmldb/XML.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
/**
* XML class
*/
class XML
{
/**
* Protected constructor since this is a static class.
*
* @access protected
*/
protected function __construct()
{
// Nothing here
}
/**
* Create safe xml data. Removes dangerous characters for string.
*
* <code>
* $xml_safe = XML::safe($xml_unsafe);
* </code>
*
* @param string $str String
* @param boolean $flag Flag
* @return string
*/
public static function safe($str, $flag = true)
{
// Redefine vars
$str = (string) $str;
$flag = (bool) $flag;
// Remove invisible chars
$non_displayables = array('/%0[0-8bcef]/', '/%1[0-9a-f]/', '/[\x00-\x08]/', '/\x0b/', '/\x0c/', '/[\x0e-\x1f]/');
do {
$cleaned = $str;
$str = preg_replace($non_displayables, '', $str);
} while ($cleaned != $str);
// htmlspecialchars
if ($flag) $str = htmlspecialchars($str, ENT_QUOTES, 'utf-8');
// Return safe string
return $str;
}
/**
* Get XML file
*
* <code>
* $xml_file = XML::loadFile('path/to/file.xml');
* </code>
*
* @param string $file File name
* @param boolean $force Method
* @return array
*/
public static function loadFile($file, $force = false)
{
// Redefine vars
$file = (string) $file;
$force = (bool) $force;
// For CMS API XML file force method
if ($force) {
$xml = file_get_contents($file);
$data = simplexml_load_string($xml);
return $data;
} else {
if (file_exists($file) && is_file($file)) {
$xml = file_get_contents($file);
$data = simplexml_load_string($xml);
return $data;
} else {
return false;
}
}
}
}

View File

@@ -16,12 +16,23 @@
* See COPYING.txt for copyright notices and details.
*/
// Main engine defines
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', rtrim(dirname(__FILE__), '\\/'));
define('BACKEND', false);
define('MONSTRA_ACCESS', true);
/* TEMP CODE BEGIN */
function byteFormat($size)
{
$unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
return @round($size/pow(1024, ($i=floor(log($size, 1024)))), 2).' '.$unit[$i];
}
$_start = memory_get_usage();
/* TEMP CODE END */
// First check for installer then go
if (file_exists('install.php')) {
if (isset($_GET['install'])) {
@@ -37,7 +48,7 @@ if (file_exists('install.php')) {
} else {
// Load Engine init file
require_once(ROOT. DS . 'engine'. DS . '_init.php');
require_once ROOT. DS . 'engine'. DS . '_init.php';
// Check for maintenance mod
if ('on' == Option::get('maintenance_status')) {
@@ -54,7 +65,7 @@ if (file_exists('install.php')) {
Action::run('frontend_pre_render');
// Load site template
require(MINIFY . DS . 'theme.' . Site::theme() . '.' . Site::template() . '.template.php');
require MINIFY . DS . 'theme.' . Site::theme() . '.' . Site::template() . '.template.php';
// Frontend pre render
Action::run('frontend_post_render');
@@ -62,3 +73,7 @@ if (file_exists('install.php')) {
// Flush (send) the output buffer and turn off output buffering
ob_end_flush();
}
/* TEMP CODE BEGIN */
echo byteFormat(memory_get_usage() - $_start);
/* TEMP CODE END */

View File

@@ -74,8 +74,7 @@ class ClassLoader
*/
public static function mapClasses(array $classes)
{
foreach($classes as $name => $path)
{
foreach ($classes as $name => $path) {
static::$classes[$name] = $path;
}
}
@@ -128,8 +127,7 @@ class ClassLoader
{
$classPath = '';
if(($pos = strripos($className, '\\')) !== false)
{
if (($pos = strripos($className, '\\')) !== false) {
$namespace = substr($className, 0, $pos);
$className = substr($className, $pos + 1);
$classPath = str_replace('\\', '/', $namespace) . '/';
@@ -139,10 +137,8 @@ class ClassLoader
$directories = ($directory === null) ? static::$directories : array($directory);
foreach($directories as $directory)
{
if(file_exists($directory . '/' . $classPath))
{
foreach ($directories as $directory) {
if (file_exists($directory . '/' . $classPath)) {
include($directory . '/' . $classPath);
return true;
@@ -152,7 +148,6 @@ class ClassLoader
return false;
}
/**
* Autoloader.
*
@@ -162,19 +157,22 @@ class ClassLoader
*/
public static function load($className)
{
/*
var_dump(static::$classes);
die();
*/
$className = ltrim($className, '\\');
// Try to autoload an aliased class
if(isset(static::$aliases[$className]))
{
if (isset(static::$aliases[$className])) {
return class_alias(static::$aliases[$className], $className);
}
// Try to load a mapped class
if(isset(static::$classes[$className]) && file_exists(static::$classes[$className]))
{
if (isset(static::$classes[$className]) && file_exists(static::$classes[$className])) {
include static::$classes[$className];
return true;
@@ -182,12 +180,9 @@ class ClassLoader
// Try to load class from a registered namespace
foreach(static::$namespaces as $namespace => $path)
{
if(strpos($className, $namespace) === 0)
{
if(static::loadPSR0(substr($className, strlen($namespace)), $path))
{
foreach (static::$namespaces as $namespace => $path) {
if (strpos($className, $namespace) === 0) {
if (static::loadPSR0(substr($className, strlen($namespace)), $path)) {
return true;
}
}
@@ -195,8 +190,7 @@ class ClassLoader
// Try to load a PSR-0 compatible class
// The second call to the loadPSR0 method is used to autoload legacy code
if (static::loadPSR0($className) || static::loadPSR0(strtolower($className)))
{
if (static::loadPSR0($className) || static::loadPSR0(strtolower($className))) {
return true;
}

View File

@@ -13,7 +13,6 @@
* @since 1.0.0
*/
class Registry
{
@@ -24,7 +23,6 @@ class Registry
*/
private static $registry = array();
/**
* Checks if an object with this name is in the registry.
*

View File

@@ -1,5 +1,5 @@
<h2><?php echo __('Information', 'information'); ?></h2>
<br />
<br>
<div class="tabbable">
<ul class="nav nav-tabs">
@@ -116,10 +116,6 @@
<td><?php echo ROOT . DS . 'public' ?></td>
<td><?php if (Dir::writable(ROOT . DS . 'public')) { ?><span class="badge badge-success"><?php echo __('Writable', 'information'); ?></span><?php } else { ?><span class="badge badge-error"><?php echo __('Unwritable', 'information'); ?></span><?php } ?></td>
</tr>
<tr>
<td><?php echo MONSTRA ?></td>
<td><?php if (Dir::writable(MONSTRA)) { ?><span class="badge badge-success"><?php echo __('Writable', 'information'); ?></span><?php } else { ?><span class="badge badge-error"><?php echo __('Unwritable', 'information'); ?></span><?php } ?></td>
</tr>
<tr>
<td><?php echo PLUGINS ?></td>
<td><?php if (Dir::writable(PLUGINS)) { ?><span class="badge badge-success"><?php echo __('Writable', 'information'); ?></span><?php } else { ?><span class="badge badge-error"><?php echo __('Unwritable', 'information'); ?></span><?php } ?></td>
@@ -143,12 +139,6 @@
</tr>
</thead>
<tbody>
<?php if (File::writable(MONSTRA . DS)) { ?>
<tr>
<td><span class="badge badge-error" style="padding-left:5px; padding-right:5px;"><b>!</b></span> </td>
<td><?php echo __('The Monstra core directory (":path") and/or files underneath it has been found to be writable. We would advise you to remove all write permissions. <br/>You can do this on unix systems with: <code>chmod -R a-w :path</code>', 'information', array(':path' => MONSTRA . DS)); ?></td>
</tr>
<?php } ?>
<?php if (File::writable(ROOT . DS . '.htaccess')) { ?>
<tr>
<td><span class="badge badge-error" style="padding-left:5px; padding-right:5px;"><b>!</b></span> </td>