First commit. Genres and categories partially fleshed out

This commit is contained in:
Timothy Warren 2012-06-13 13:49:10 -04:00
parent 4bf8891444
commit 13b63edc5f
45 changed files with 4015 additions and 17 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
sys/*.sqlite

115
README.md
View File

@ -1,22 +1,103 @@
#meta
# miniMVC
miniMVC is a minimalistic Modular MVC framework, with built-in minifier, and pure-PHP templating system.
### Requirements
* PHP 5.4+
* PDO extensions for databases you wish to use
* Webserver that correctly handles REQUEST_URI, such as:
* Apache
* IIS
* Lighttpd
* SimpleTest library for running unit tests
### Unique features
#### Extensive use of PHP's magic methods on the base class
* `__toString()` method allows a view of the current class object when the current class object is used as a string. If you prefer `var_dump()` or `var_export()`, you can pass the name of that function if you call the `__toString` method directly.
Eg. `$this . "string"`, `$this->__toString()`, `echo $this`;
* `__call()` method allows the dynamic addition of callable closure objects
Eg. `$this->foo = function($baz){}` is callable as `$this->foo()`, with the current object as the last argument
* `MM` class extends ArrayObject, and all the main classes extend this class. Functions begining with `array_` are callable on object from this class. E.g. `$this->array_keys()` will return a list of the class properties.
#### Database class is an extension of PHP's PDO class.
Database class uses [Query](https://github.com/aviat4ion/Query) as a database abstraction layer and query builder.
Database connections are set in /app/config/db.php
### File Structure
* index.php - framework bootstrap
* app - configuration and app-wide files
* classes - helper classes
* config - configuration files
* modules - MVC triads
* controllers - controller classes
* models - model classes
* views - module-specific views
* views - global page templates
* errors - error page templates
* assets - frontend files
* js - javascript files
* css - css files
* config - minifier configuration files
* sys - core framework classes
### Common Tasks
* Creating a controller
<?php
class Foo extends miniMVC\Controller {
function __construct()
{
parent::__construct();
}
}
* Creating a model
<?php
class Bar extends miniMVC\Model {
function __construct()
{
parent::__construct();
}
}
* Loading a database
`$this->db = miniMVC\db::get_instance($db_name);`
Note that multiple databases can be used in the same class
by specifying a different database name.
* Loading a model (From a controller)
`$this->load_model($model)` - creates an instance of that model as a member of the current class. After loading the model, you can call its methods like so
`$this->[model name]->method()`
* Loading a class
Librarys / classes found in `app/classes` or `sys/libraries` are autoloaded.
To call a library, simply instantiate that class.
Classes with a `get_instance` static methods should be called like so:
`$obj =& miniMVC\class::get_instance()`
So, you know all that client information you need to keep track of, like passwords and servers? Or how about all those serial keys for the software you have? meta is a webapp to organize these kinds of data for easier reference.
Other classes should be called using the new operator
##Organizing Data
Meta has a four-level hierarchy
1. Genre
* The broadest category. An example could be titled 'Client Data'
2. Category
* A general item in the genre. For example, an individual client.
3. Section
* A grouping of label-data pairs. Something like 'CMS Access'
4. Data
* Pairs of labels and values.
Eg. Username : admin
`$obj = new miniMVC\class()`
This basic hierarchy enables keeping track of simple data in a neat fashion.

0
app/classes/index.html Normal file
View File

135
app/config/config.php Normal file
View File

@ -0,0 +1,135 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* Main config file
*
* @package miniMVC
* @subpackage App
*/
// --------------------------------------------------------------------------
/*
|--------------------------------------------------------------------------
| Display Debug backtrace
|--------------------------------------------------------------------------
|
| If set to TRUE, a backtrace will be displayed along with php errors.
|
*/
define('SHOW_DEBUG_BACKTRACE', TRUE);
/*
|--------------------------------------------------------------------------
| Base Url
|--------------------------------------------------------------------------
|
| This is the url path where the framework is located. Requires trailing
| slash.
|
*/
// Determine the default site url
$ri = $_SERVER['REQUEST_URI'];
$ind_pos = stripos($ri, "index.php");
$default_path = ($ind_pos !== FALSE) ? substr($ri, 0, $ind_pos) : $ri;
$default_baseurl = "//" . str_replace("//", "/", $_SERVER['HTTP_HOST']. $default_path);
define('BASE_URL', $default_baseurl);
/*
|--------------------------------------------------------------------------
| Url index file
|--------------------------------------------------------------------------
|
| This determines whether "index.php" is in generated urls
|
*/
define('URL_INDEX_FILE', 'index.php/');
/*
|--------------------------------------------------------------------------
| Content Domain
|--------------------------------------------------------------------------
|
| This is the domain used for serving content, such as css, javascript.
|
*/
define('CONTENT_DOMAIN', BASE_URL);
/*
|--------------------------------------------------------------------------
| Static Lib Path
|--------------------------------------------------------------------------
|
| This is the path where the 'assets' directory is on the static domain.
|
*/
define('STATIC_LIB_PATH', CONTENT_DOMAIN.'assets/');
/*
|--------------------------------------------------------------------------
| Group Style Path
|--------------------------------------------------------------------------
|
| This is the path that is used to determine the relative path to the
| stylesheet minifier. This should not need to be changed.
|
*/
define('STYLE_PATH', STATIC_LIB_PATH . 'css.php/g/');
/*
|--------------------------------------------------------------------------
| Group Javascript Path
|--------------------------------------------------------------------------
|
| This is the path that is used to determine the relative path to the
| javascript minifier. This should not need to be changed.
|
*/
define('SCRIPT_PATH', STATIC_LIB_PATH . 'js.php/g/');
/*
|--------------------------------------------------------------------------
| Default title
|--------------------------------------------------------------------------
|
| Default title for webpages
|
*/
define('DEFAULT_TITLE', "meta");
/*
|--------------------------------------------------------------------------
| Default css group
|--------------------------------------------------------------------------
|
| Default css group
|
*/
define('DEFAULT_CSS_GROUP', "css");
/*
|--------------------------------------------------------------------------
| Default js group
|--------------------------------------------------------------------------
|
| Default js group
|
*/
define('DEFAULT_JS_GROUP', "js");
// End of config.php

37
app/config/db.php Normal file
View File

@ -0,0 +1,37 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* Database config file
*
* @package miniMVC
* @subpackage App
*/
// --------------------------------------------------------------------------
$db_conf = array(
'default' => array(
'type' => 'sqlite',
'host' => '',
'user' => '',
'pass' => '',
'port' => '',
'database' => '',
'file' => MM_SYS_PATH . 'meta.sqlite',
)
);
// End of db.php

41
app/config/routes.php Normal file
View File

@ -0,0 +1,41 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* File to configure routes
*
* Routes work on simple/regex matching.
*
* For a route mapping http://example.com/blog to the blog controller in the blog module:
* 'blog' => 'blog/blog/index'
*
* To route a special 404 page, set '404_route' to the "module/controller/method" you wish to use
*
* @package miniMVC
* @subpackage App
*/
// --------------------------------------------------------------------------
return array(
// Default Paths
'default_controller' => 'welcome',
'default_module' => 'meta',
'genre' => 'meta/genre/index',
'genre/add' => 'meta/genre/add',
'404_route' => '',
);
// End of routes.php

View File

@ -0,0 +1,102 @@
<?php
/**
* meta
*
* Hierarchial data tool
*
* @package meta
* @author Timothy J. Warren
* @copyright Copyright (c) 2012
* @link https://github.com/aviat4ion/meta
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* Genre controller
*
* @package meta
*/
class Genre extends miniMVC\Controller {
/**
* Initialize the Controller
*/
public function __construct()
{
parent::__construct();
$this->load_model('meta\model');
$this->page->build_header();
}
/**
* Default controller method
*/
public function index()
{
// Re-route to detail page if the last segment
// is a valid integer
$id = (int) miniMVC\get_last_segment();
if ($id !== 0)
{
return $this->detail($id);
}
// Otherwise, display list of genres
$data = array();
$data['genres'] = $this->model->get_genres();
$this->load_view('genres', $data);
$this->page->build_footer();
}
/**
* Adds a new genre
*/
public function add()
{
// Strip away tags for the sake of security
$name = strip_tags($_POST['genre']);
// Make sure the name doesn't already exist. If it does, show an error.
$res = $this->model->add_genre($name);
if ($res === TRUE)
{
$this->page->set_message('success', 'Added new genre');
}
else
{
$this->page->set_message('error', 'Genre already exists');
}
// Render the basic page
$this->index();
}
/**
* Returns the categories / editing options for a genre
*
* @param int
*/
public function detail($id)
{
$genre = $this->model->get_genre_by_id($id);
$categories = $this->model->get_categories($id);
$data = array(
'genre' => $genre,
'categories' => $categories,
'genre_id' => $id
);
$this->load_view('genre_detail', $data);
$this->page->build_footer();
}
}
// End of genre.php

View File

@ -0,0 +1,59 @@
<?php
/**
* meta
*
* Hierarchial data tool
*
* @package meta
* @author Timothy J. Warren
* @copyright Copyright (c) 2012
* @link https://github.com/aviat4ion/meta
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* Default Controller class
*
* @package meta
*/
class Welcome extends miniMVC\Controller {
/**
* Initialize the constructor
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->load_model('meta\model');
}
// --------------------------------------------------------------------------
/**
* Default route for the controller
*
* @return void
*/
public function index()
{
$data = array();
$data['genres'] = $this->model->get_genres();
$this->page->render('genres', $data);
}
// --------------------------------------------------------------------------
public function login()
{
}
}
// End of welcome.php

View File

@ -0,0 +1,351 @@
<?php
/**
* meta
*
* Simple hierarchial data management
*
* @package meta
* @author Timothy J. Warren
* @copyright Copyright (c) 2012
* @link https://github.com/aviat4ion/meta
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace meta;
/**
* Main Model for database interaction
*
* @package meta
*/
class Model extends \miniMVC\Model {
/**
* Reference to database connection
*
* @var Query_Builder
*/
protected $db;
/**
* Reference to session
*
* @var Session
*/
protected $session;
/**
* Initialize the model
*/
public function __construct()
{
parent::__construct();
$this->session =& \miniMVC\Session::get_instance();
$this->db =& \miniMVC\db::get_instance();
}
// --------------------------------------------------------------------------
/**
* Delete a genre/category/section or data item
*
* @param string $type
* @param int $id
*/
public function delete($type, $id)
{
$this->db->where('id', (int) $id)
->delete($type);
}
// --------------------------------------------------------------------------
/**
* Move a category/section/data item to another parent
*
* @param string
* @param int
* @param int
*/
public function move($type, $type_id, $parent_id)
{
$parent_type = array(
'data' => 'section',
'section' => 'category',
'category' => 'genre'
);
$parent_field = "{$parent_type[$type]}_id";
$this->db->set($parent_field, $parent_id)
->where('id', (int) $type_id)
->update($type);
}
// --------------------------------------------------------------------------
/**
* Add genre
*
* @param string
* @return bool
*/
public function add_genre($genre)
{
// Check for duplicates
$query = $this->db->from('genre')
->where('genre', $genre)
->get();
// Fetch the data as a workaround
// for databases that do not support
// grabbing result counts (SQLite / Firebird)
$array = $query->fetchAll();
if (count($array) === 0)
{
$this->db->set('genre', $genre)
->insert('genre');
return TRUE;
}
return FALSE;
}
// --------------------------------------------------------------------------
/**
* Rename a genre
*
* @param int
* @param string
*/
public function update_genre($genre_id, $genre)
{
$this->db->set('genre', $genre)
->where('id', $genre_id)
->update('genre');
}
// --------------------------------------------------------------------------
/**
* Add category to genre
*
* @param string
* @param int
*/
public function add_category($cat, $genre_id)
{
$this->db->set('category', $cat)
->set('genre_id', $genre_id)
->insert('category');
}
// --------------------------------------------------------------------------
/**
* Rename a category
*
* @param int
* @param string
*/
public function update_category($cat_id, $category)
{
$this->db->set('category', $category)
->where('id', (int) $cat_id)
->update('category');
}
// --------------------------------------------------------------------------
/**
* Add a section to a category
*
* @param string
* @param int
*/
public function add_section($section, $category_id)
{
$this->db->set('section', $section)
->set('category_id', (int) $category_id)
->insert('section');
}
// --------------------------------------------------------------------------
/**
* Rename a section
*
* @param int
* @param string
*/
public function update_section($section_id, $section)
{
$this->db->set('section', $section)
->where('id', (int) $section_id)
->update('section');
}
// --------------------------------------------------------------------------
/**
* Add key/value data to a section
*
* @param int
* @param mixed object/array
*/
public function add_data($section_id, $data)
{
// Convert the data to json for storage
$data_str = json_encode($data);
// Save the data
$this->db->set('data', $data_str)
->set('section_id', (int) $section_id)
->insert('data');
}
// --------------------------------------------------------------------------
/**
* Update the data
*
* @param int
* @param mixed
*/
public function update_data($data_id, $data)
{
// Convert the data to json for storage
$data_str = json_encode('data', $data_str);
// Save the data
$this->db->set('data', $data_str)
->where('id', (int) $data_id)
->update('data');
}
// --------------------------------------------------------------------------
/**
* Gets the list of genres
*
* @return array
*/
public function get_genres()
{
$genres = array();
$query = $this->db->select('id, genre')
->from('genre')
->order_by('genre', 'asc')
->get();
while($row = $query->fetch(\PDO::FETCH_ASSOC))
{
$genres[$row['id']] = $row['genre'];
}
return $genres;
}
/**
* Gets the name of the genre from its id
*
* @param int
* @return string
*/
public function get_genre_by_id($id)
{
$query = $this->db->select('genre')
->from('genre')
->where('id', (int) $id)
->get();
$row = $query->fetch(\PDO::FETCH_ASSOC);
return $row['genre'];
}
// --------------------------------------------------------------------------
/**
* Get the categories for the specified genre
*
* @param int
* @return array
*/
public function get_categories($genre_id)
{
$cats = array();
$query = $this->db->select('id, category')
->from('category')
->where('genre_id', (int) $genre_id)
->get();
while($row = $query->fetch(\PDO::FETCH_ASSOC))
{
$cats[$row['id']] = $row['category'];
}
return $cats;
}
// --------------------------------------------------------------------------
/**
* Get the sections for the specified category id
*
* @param int
* @return array
*/
public function get_sections($category_id)
{
$sections = array();
$query = $this->db->select('id, section')
->from('section')
->where('category_id', (int) $category_id)
->get();
while($row = $query->fetch(\PDO::FETCH_ASSOC))
{
$sections[$row['id']] = $row['section'];
}
return $sections;
}
// --------------------------------------------------------------------------
/**
* Get the data fro the section
*
* @param int
* @return array
*/
public function get_data($section_id)
{
$data = array();
$query = $this->db->select('id, data')
->from('data')
->where('section_id', (int) $section_id)
->get();
while($row = $query->fetch(\PDO::FETCH_ASSOC))
{
$data[$row['id']] = json_decode($row['data'], TRUE);
}
return $data;
}
}
// End of model.php

View File

@ -0,0 +1,32 @@
<?php
/**
* meta
*
* Simple hierarchial data management
*
* @package meta
* @author Timothy J. Warren
* @copyright Copyright (c) 2012
* @link https://github.com/aviat4ion/meta
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace meta;
/**
* Model for dealing with user logins / permissions
*
* @package meta
*/
class User_model extends \miniMVC\Model {
public function __construct()
{
parent::__construct();
}
}
// End of user_model.php

View File

@ -0,0 +1,23 @@
<h1>meta</h1>
<h3><?= $genre ?></h3>
<h4>Genre Categories</h4>
<ul class="list">
<?php foreach($categories as $id => $cat): ?>
<li><a href="<?= miniMVC\site_url("category/{$id}") ?>"><?= $cat ?></a></li>
<?php endforeach ?>
</ul>
<form action="<?= miniMVC\site_url("category/add") ?>" method="post">
<fieldset>
<lengend>Add Category</lengend>
<dl>
<!-- Weird tag wrapping is intentional for display: inline-block -->
<dt><label for="category">Category name:</label></dt><dd>
<input type="text" name="category" id="category" /></dd>
<dt><input type="hidden" name="genre_id" value="<?= $genre_id ?>" /></dt><dd>
<button type="submit">Add Category</button></dd>
</dl>
</fieldset>
</form>

View File

@ -0,0 +1,22 @@
<h1>Meta</h1>
<h3>Genres</h3>
<ul class="list">
<?php foreach($genres as $id => $name): ?>
<li><a href="<?= miniMVC\site_url("genre/{$id}") ?>"><?= $name ?></a></li>
<?php endforeach ?>
</ul>
<form action="<?= miniMVC\site_url("genre/add") ?>" method="post">
<fieldset>
<lengend>Add Genre</lengend>
<dl>
<!-- Weird tag wrapping is intentional for display: inline-block -->
<dt><label for="genre">Genre name:</label></dt><dd>
<input type="text" name="genre" id="genre" /></dd>
<dt>&nbsp;</dt><dd>
<button type="submit">Add Genre</button></dd>
</dl>
</fieldset>
</form>

View File

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<title>404 Not Found</title>
<style type="text/css">
div{position:relative; margin:0.5em auto; padding:0.5em; width:95%; border:1px solid #924949; background: #f3e6e6;}
</style>
</head>
<body>
<div class="message error">
<?php if (isset($title)) : ?>
<h1><?= $title ?></h1>
<?php endif ?>
<?= $message; ?>
</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<div style="position:relative; margin:0.5em auto; padding:0.5em; width:95%; border:1px solid #924949; background: #f3e6e6;">
<h4>A Database Error was encountered</h4>
<p>Code: <?= $code ?></p>
<p>Driver Code: <?= $driver_code ?></p>
<p>Message: <?= $message ?></p>
</div>

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<title>404 Not Found</title>
<style type="text/css">
div{position:relative; margin:0.5em auto; padding:0.5em; width:95%; border:1px solid #924949; background: #f3e6e6;}
</style>
</head>
<body>
<div class="message error">
<?php if (isset($title)) : ?>
<h1><?= $title ?></h1>
<?php endif ?>
<?= $message; ?>
</div>
</body>
</html>

View File

@ -0,0 +1,22 @@
<div style="position:relative; margin:0.5em auto; padding:0.5em; width:95%; border:1px solid #924949; background: #f3e6e6;">
<h4>An uncaught exception was thrown.</h4>
<p>Message: <?= $message; ?></p>
<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>
<p>Backtrace: </p>
<?php foreach($exception->getTrace() as $error): ?>
<?php if (isset($error['file']) && ! stristr($error['file'], MM_SYS_PATH)): ?>
<p style="margin-left:10px">
File: <?= str_replace(MM_BASE_PATH, "", $error['file']) ?><br />
Line: <?= $error['line'] ?><br />
Function: <?= $error['function'] ?>
</p>
<?php endif ?>
<?php endforeach ?></p>
<?php endif ?>
</div>

6
app/views/footer.php Normal file
View File

@ -0,0 +1,6 @@
<?php if ($foot_js != ""): ?>
<?= $foot_js ?>
<?php endif ?>
</body>
</html>

11
app/views/header.php Normal file
View File

@ -0,0 +1,11 @@
<head>
<?= $meta ?>
<?= $css ?>
<?= $head_tags ?>
<title><?= $title ?></title>
<?php if (!empty($base)) { ?><base href="<?=$base ?>" /><?php } ?>
<?= $head_tags ?>
<?= $head_js ?>
</head>
<body<?= (!empty($body_class)) ? "class=\"" . $body_class . "\"" : ""; ?><?= (!empty($body_id)) ? " id=\"" . $body_id . "\"" : ""; ?>>

5
app/views/message.php Normal file
View File

@ -0,0 +1,5 @@
<div class="message <?= $stat_class ?>">
<span class="icon"></span>
<?= $message ?>
<span class="close" onclick="this.parentElement.style.display='none'"></span>
</div>

76
assets/config/config.php Executable file
View File

@ -0,0 +1,76 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* Asset management configuration file
*
* @package miniMVC
* @subpackage Assets
*/
/*
|--------------------------------------------------------------------------
| Document Root
|--------------------------------------------------------------------------
|
| The folder where the index of the website exists. In most situations,
| this will not need to be changed.
|
| If the website is in a folder off of the domain name, like:
| http://example.com/website/
| you will need to add that folder to the document root.
|
*/
$document_root = './';
/*
|--------------------------------------------------------------------------
| CSS Folder
|--------------------------------------------------------------------------
|
| The folder where css files exist, in relation to the document root
|
*/
$css_root = $document_root. 'css/';
/*
|--------------------------------------------------------------------------
| Path from
|--------------------------------------------------------------------------
|
| Path fragment to rewrite in css files
|
*/
$path_from = '';
/*
|--------------------------------------------------------------------------
| Path to
|--------------------------------------------------------------------------
|
| The path fragment replacement for the css files
|
*/
$path_to = '';
/*
|--------------------------------------------------------------------------
| JS Folder
|--------------------------------------------------------------------------
|
| The folder where javascript files exist, in relation to the document root
|
*/
$js_root = $document_root. '/js/';

View File

@ -0,0 +1,29 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* This is the config array for css files to concatenate and minify
*/
return array(
/*-----
Css
-----*/
'css' => array(
'normalize.css',
'message.css',
'theme.css'
)
);
// End of css_groups.php

28
assets/config/js_groups.php Executable file
View File

@ -0,0 +1,28 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* This is the config array for javascript files to concatenate and minify
*/
return [
/*
For each group create an array like so
'my_group' => array(
'path/to/css/file1.css',
'path/to/css/file2.css'
),
*/
];

135
assets/css.php Executable file
View File

@ -0,0 +1,135 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* CSS Minifier and Cacher
*
* @package miniMVC
* @subpackage Assets
*/
//Get config files
require('./config/config.php');
//Include the css groups
$groups = require("./config/css_groups.php");
//The name of this file
$this_file = __FILE__;
// --------------------------------------------------------------------------
/**
* CSS Minifier
*
* @param string $buffer
* @return string
*/
function compress($buffer) {
//Remove CSS comments
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
//Remove tabs, spaces, newlines, etc.
$buffer = preg_replace('`\s+`', ' ', $buffer);
$replace = [
' )' => ')',
') ' => ')',
' }' => '}',
'} ' => '}',
' {' => '{',
'{ ' => '{',
', ' => ',',
': ' => ':',
'; ' => ';',
];
//Eradicate every last space!
$buffer = trim(strtr($buffer, $replace));
$buffer = str_replace('{ ', '{', $buffer);
$buffer = str_replace('} ', '}', $buffer);
return $buffer;
}
// --------------------------------------------------------------------------
//Creative rewriting
$pi = $_SERVER['PATH_INFO'];
$pia = explode('/', $pi);
$pia_len = count($pia);
$i = 1;
while($i < $pia_len)
{
$j = $i+1;
$j = (isset($pia[$j])) ? $j : $i;
$_GET[$pia[$i]] = $pia[$j];
$i = $j + 1;
};
$css = '';
$modified = [];
if (isset($groups[$_GET['g']]))
{
foreach ($groups[$_GET['g']] as &$file)
{
$new_file = $css_root.$file;
$css .= file_get_contents($new_file);
$modified[] = filemtime($new_file);
}
}
//Add this page too
$modified[] = filemtime($this_file);
//Get the latest modified date
rsort($modified);
$last_modified = $modified[0];
$requested_time= (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
: time();
if ($last_modified === $requested_time)
{
header("HTTP/1.1 304 Not Modified");
exit();
}
if (!isset($_GET['debug']))
{
$css = compress($css);
}
$size = strlen($css) * 8;
//This GZIPs the CSS for transmission to the user
//making file size smaller and transfer rate quicker
ob_start("ob_gzhandler");
header("Content-Type: text/css; charset=utf8");
header("Cache-control: public, max-age=691200, must-revalidate");
header("Last-Modified: ".gmdate('D, d M Y H:i:s', $last_modified)." GMT");
header("Expires: ".gmdate('D, d M Y H:i:s', (filemtime($this_file) + 691200))." GMT");
echo $css;
ob_end_flush();
//End of css.php

36
assets/css/message.css Normal file
View File

@ -0,0 +1,36 @@
.message{
position:relative;
margin:0.5em auto;
padding:0.5em;
width:95%;
}
.message .close{
width:1em;
height:1em;
border:1px solid #000;
position:absolute;
right:0.5em;
top:0.5em;
}
.message .icon{
left:0.5em;
top:0.5em;
margin-right:1em;
}
.error{
border:1px solid #924949;
background: #f3e6e6;
}
.success{
border:1px solid #1f8454;
background: #70dda9;
}
.info{
border:1px solid #bfbe3a;
background: #FFFFCC;
}

504
assets/css/normalize.css vendored Normal file
View File

@ -0,0 +1,504 @@
/*! normalize.css 2012-03-11T12:53 UTC - http://github.com/necolas/normalize.css */
/* =============================================================================
HTML5 display definitions
========================================================================== */
/*
* Corrects block display not defined in IE6/7/8/9 & FF3
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
/*
* Corrects inline-block display not defined in IE6/7/8/9 & FF3
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
/*
* Prevents modern browsers from displaying 'audio' without controls
* Remove excess height in iOS5 devices
*/
audio:not([controls]) {
display: none;
height: 0;
}
/*
* Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
* Known issue: no IE6 support
*/
[hidden] {
display: none;
}
/* =============================================================================
Base
========================================================================== */
/*
* 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
* http://clagnut.com/blog/348/#c790
* 2. Prevents iOS text size adjust after orientation change, without disabling user zoom
* www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/*
* Addresses font-family inconsistency between 'textarea' and other form elements.
*/
html,
button,
input,
select,
textarea {
font-family: sans-serif;
}
/*
* Addresses margins handled incorrectly in IE6/7
*/
body {
margin: 0;
}
/* =============================================================================
Links
========================================================================== */
/*
* Addresses outline displayed oddly in Chrome
*/
a:focus {
outline: thin dotted;
}
/*
* Improves readability when focused and also mouse hovered in all browsers
* people.opera.com/patrickl/experiments/keyboard/test
*/
a:hover,
a:active {
outline: 0;
}
/* =============================================================================
Typography
========================================================================== */
/*
* Addresses font sizes and margins set differently in IE6/7
* Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
h3 {
font-size: 1.17em;
margin: 1em 0;
}
h4 {
font-size: 1em;
margin: 1.33em 0;
}
h5 {
font-size: 0.83em;
margin: 1.67em 0;
}
h6 {
font-size: 0.75em;
margin: 2.33em 0;
}
/*
* Addresses styling not present in IE7/8/9, S5, Chrome
*/
abbr[title] {
border-bottom: 1px dotted;
}
/*
* Addresses style set to 'bolder' in FF3+, S4/5, Chrome
*/
b,
strong {
font-weight: bold;
}
blockquote {
margin: 1em 40px;
}
/*
* Addresses styling not present in S5, Chrome
*/
dfn {
font-style: italic;
}
/*
* Addresses styling not present in IE6/7/8/9
*/
mark {
background: #ff0;
color: #000;
}
/*
* Addresses margins set differently in IE6/7
*/
p,
pre {
margin: 1em 0;
}
/*
* Corrects font family set oddly in IE6, S4/5, Chrome
* en.wikipedia.org/wiki/User:Davidgothberg/Test59
*/
pre,
code,
kbd,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em;
}
/*
* Improves readability of pre-formatted text in all browsers
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* 1. Addresses CSS quotes not supported in IE6/7
* 2. Addresses quote property not supported in S4
*/
/* 1 */
q {
quotes: none;
}
/* 2 */
q:before,
q:after {
content: '';
content: none;
}
small {
font-size: 75%;
}
/*
* Prevents sub and sup affecting line-height in all browsers
* gist.github.com/413930
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* =============================================================================
Lists
========================================================================== */
/*
* Addresses margins set differently in IE6/7
*/
dl,
menu,
ol,
ul {
margin: 1em 0;
}
dd {
margin: 0 0 0 40px;
}
/*
* Addresses paddings set differently in IE6/7
*/
menu,
ol,
ul {
padding: 0 0 0 40px;
}
/*
* Corrects list images handled incorrectly in IE7
*/
nav ul,
nav ol {
list-style: none;
list-style-image: none;
}
/* =============================================================================
Embedded content
========================================================================== */
/*
* 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
* 2. Improves image quality when scaled in IE7
* code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/*
* Corrects overflow displayed oddly in IE9
*/
svg:not(:root) {
overflow: hidden;
}
/* =============================================================================
Figures
========================================================================== */
/*
* Addresses margin not present in IE6/7/8/9, S5, O11
*/
figure {
margin: 0;
}
/* =============================================================================
Forms
========================================================================== */
/*
* Corrects margin displayed oddly in IE6/7
*/
form {
margin: 0;
}
/*
* Define consistent border, margin, and padding
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/*
* 1. Corrects color not being inherited in IE6/7/8/9
* 2. Corrects text not wrapping in FF3
* 3. Corrects alignment displayed oddly in IE6/7
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/*
* 1. Corrects font size not being inherited in all browsers
* 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
* 3. Improves appearance and consistency in all browsers
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/*
* Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
*/
button,
input {
line-height: normal; /* 1 */
}
/*
* 1. Improves usability and consistency of cursor style between image-type 'input' and others
* 2. Corrects inability to style clickable 'input' types in iOS
* 3. Removes inner spacing in IE7 without affecting normal text inputs
* Known issue: inner spacing remains in IE6
*/
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
cursor: pointer; /* 1 */
-webkit-appearance: button; /* 2 */
*overflow: visible; /* 3 */
}
/*
* Re-set default cursor for disabled elements
*/
button[disabled],
input[disabled] {
cursor: default;
}
/*
* 1. Addresses box sizing set to content-box in IE8/9
* 2. Removes excess padding in IE8/9
* 3. Removes excess padding in IE7
Known issue: excess padding remains in IE6
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/*
* 1. Addresses appearance set to searchfield in S5, Chrome
* 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/*
* Removes inner padding and search cancel button in S5, Chrome on OS X
*/
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none;
}
/*
* Removes inner padding and border in FF3+
* www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/*
* 1. Removes default vertical scrollbar in IE6/7/8/9
* 2. Improves readability and alignment in all browsers
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* =============================================================================
Tables
========================================================================== */
/*
* Remove most spacing between table cells
*/
table {
border-collapse: collapse;
border-spacing: 0;
}

28
assets/css/theme.css Normal file
View File

@ -0,0 +1,28 @@
/* ---------------- */
/* ! General Styles */
/* ---------------- */
html, body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight:200;
max-width:800px;
margin: 0 auto;
}
/* form styles */
form dt, form dd {
display:inline-block;
padding:0.25em 0;
}
form dt {
width:40%;
text-align:right;
}
form dd {
width:59%;
text-align:left;
margin-left:0;
padding-left:.25em;
}

188
assets/js.php Executable file
View File

@ -0,0 +1,188 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* JS Minifier and Cacher
*
* @package miniMVC
* @subpackage Assets
*/
//Get config files
require('./config/config.php');
//Include the js groups
$groups_file = "./config/js_groups.php";
$groups = require($groups_file);
//The name of this file
$this_file = __FILE__;
// --------------------------------------------------------------------------
/**
* Get Files
*
* Concatenates the javascript files for the current
* group as a string
* @return string
*/
function get_files()
{
global $groups, $js_root;
$js = '';
foreach ($groups[$_GET['g']] as &$file)
{
$new_file = realpath($js_root.$file);
$js .= file_get_contents($new_file);
}
return $js;
}
// --------------------------------------------------------------------------
/**
* Google Min
*
* Minifies javascript using google's closure compiler
* @param string $new_file
* @return string
*/
function google_min($new_file)
{
//Get a much-minified version from Google's closure compiler
$ch = curl_init('http://closure-compiler.appspot.com/compile');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'output_info=compiled_code&output_format=text&compilation_level=SIMPLE_OPTIMIZATIONS&js_code=' . urlencode($new_file));
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
// --------------------------------------------------------------------------
//Creative rewriting of /g/groupname to ?g=groupname
$pi = $_SERVER['PATH_INFO'];
$pia = explode('/', $pi);
$pia_len = count($pia);
$i = 1;
while ($i < $pia_len)
{
$j = $i+1;
$j = (isset($pia[$j])) ? $j : $i;
$_GET[$pia[$i]] = $pia[$j];
$i = $j + 1;
};
$js = '';
$modified = [];
// --------------------------------------------------------------------------
//Aggregate the last modified times of the files
if (isset($groups[$_GET['g']]))
{
$cache_file = $js_root.'cache/'.$_GET['g'];
foreach ($groups[$_GET['g']] as &$file)
{
$new_file = realpath($js_root.$file);
$modified[] = filemtime($new_file);
}
//Add this page too, as well as the groups file
$modified[] = filemtime($this_file);
$modified[] = filemtime($groups_file);
$cache_modified = 0;
//Add the cache file
if (is_file($cache_file))
{
$cache_modified = filemtime($cache_file);
}
}
else //Nothing to display? Just exit
{
die("You must specify a group that exists");
}
// --------------------------------------------------------------------------
//Get the latest modified date
rsort($modified);
$last_modified = $modified[0];
$requested_time=(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
: time();
// If the browser's cached version is up to date,
// don't resend the file
if ($last_modified === $requested_time)
{
header("HTTP/1.1 304 Not Modified");
exit();
}
// --------------------------------------------------------------------------
//Determine what to do: rebuild cache, send files as is, or send cache.
if ($cache_modified < $last_modified)
{
$js = google_min(get_files());
$cs = file_put_contents($cache_file, $js);
//Make sure cache file gets created/updated
if ($cs === FALSE)
{
die("Cache file was not created. Make sure you have the correct folder permissions.");
}
}
elseif (isset($_GET['debug']))
{
$js = get_files();
}
else
{
$len = filesize($cache_file);
header("Content-Length: {$len}");
$js = file_get_contents($cache_file);
}
// --------------------------------------------------------------------------
//This GZIPs the js for transmission to the user
//making file size smaller and transfer rate quicker
ob_start("ob_gzhandler");
header("Content-Type: text/javascript; charset=utf8");
header("Cache-control: public, max-age=691200, must-revalidate");
header("Last-Modified: ".gmdate('D, d M Y H:i:s', $last_modified)." GMT");
header("Expires: ".gmdate('D, d M Y H:i:s', (filemtime($this_file) + 691200))." GMT");
echo $js;
ob_end_flush();
//end of js.php

14
assets/js/meta.js Normal file
View File

@ -0,0 +1,14 @@
var meta = (function (){
"use strict";
var meta = window.meta || {};
meta.addItem = function() {
};
// Return the object to the global scope
return meta;
)());

56
index.php Normal file
View File

@ -0,0 +1,56 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* miniMVC bootstrap file
*
* @package miniMVC
* @subpackage App
*/
// --------------------------------------------------------------------------
namespace miniMVC;
// Set as either DEVELOPMENT or PRODUCTION
// DEVELOPMENT enables error reporting
// PRODUCTION disables error reporting
define('ENVIRONMENT', 'DEVELOPMENT');
if(ENVIRONMENT == 'DEVELOPMENT')
{
error_reporting(-1);
}
else if(ENVIRONMENT == 'PRODUCTION')
{
error_reporting(0);
}
// Set the default paths
define('MM_BASE_PATH', __DIR__);
define('MM_SYS_PATH', __DIR__.'/sys/');
define('MM_APP_PATH', __DIR__.'/app/');
define('MM_MOD_PATH', MM_APP_PATH.'modules/');
// Require the basic configuration file
require(MM_APP_PATH .'config/config.php');
// Require the most important files
require(MM_SYS_PATH . 'common.php');
// And away we go!
init();
// End of index.php

26
phpdoc.dist.xml Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpdoc>
<title>miniMVC</title>
<parser>
<target>docs</target>
</parser>
<transformer>
<target>docs</target>
</transformer>
<transformations>
<template name="responsive" />
</transformations>
<files>
<directory>.</directory>
<directory>tests</directory>
<directory>assets</directory>
<directory>app/config</directory>
<directory>app/views</directory>
<directory>sys/db/tests</directory>
<ignore>tests/*</ignore>
<ignore>assets/*</ignore>
<ignore>sys/db/tests/*</ignore>
<ignore>app/config/*</ignore>
<ignore>app/views/*</ignore>
</files>
</phpdoc>

499
sys/common.php Normal file
View File

@ -0,0 +1,499 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* File including common framework-wide functions
*
* @package miniMVC
* @subpackage System
*/
namespace miniMVC;
// --------------------------------------------------------------------------
// ! Autoloading
// --------------------------------------------------------------------------
/**
* Function to autoload system libraries
*
* @param string
*/
function _autoload($name)
{
if ($name == '') return;
// strip off namespaces - they all go to the same folder
$names = explode('\\', trim($name));
$name = end($names);
// Paths to load from
$sys_path = MM_SYS_PATH . "core/{$name}.php";
$lib_path = MM_SYS_PATH . "libraries/{$name}.php";
$class_path = MM_APP_PATH . "classes/{$name}.php";
if (is_file($sys_path))
{
require_once($sys_path);
}
elseif (is_file($lib_path))
{
require_once($lib_path);
}
if (is_file($class_path))
{
require_once($class_path);
}
}
// Start the autoloader
spl_autoload_register('miniMVC\_autoload');
// --------------------------------------------------------------------------
// ! Error handling / messages
// --------------------------------------------------------------------------
/**
* Function to run on script shutdown
* -used to catch most fatal errors, and
* display them cleanly
*
* @return void
*/
function shutdown()
{
// Catch the last error
$error = error_get_last();
// types of errors that are fatal
$fatal = [E_ERROR, E_PARSE, E_RECOVERABLE_ERROR];
// Display pretty error page
if (in_array($error['type'], $fatal))
{
$file = str_replace(MM_BASE_PATH, "", $error['file']);
$err_msg = "<h2>Fatal Error: </h2>
{$error['message']}<br /><br />
<strong>File:</strong> {$file}<br /><br />
<strong>Line:</strong> {$error['line']}";
show_error($err_msg);
}
}
// --------------------------------------------------------------------------
/**
* Custom error handler
*
* @param int $severity
* @param string $message
* @param string $filepath
* @param int $line
* @return ErrorException
*/
function on_error($severity, $message, $filepath, $line)
{
throw new \ErrorException($message, 0, $severity, $filepath, $line);
}
// --------------------------------------------------------------------------
/**
* Custom exception handlererror_get_last
*
* @param Exception $exception
* @return void
*/
function on_exception($exception)
{
// This is passed to the error template
$message = $exception->getMessage();
// Contain the content for buffering
ob_start();
include(MM_APP_PATH . '/views/errors/error_php_exception.php');
$buffer = ob_get_contents();
ob_end_clean();
echo $buffer;
}
// --------------------------------------------------------------------------
/**
* General 404 function
*
* @return void
*/
function show_404()
{
@header('HTTP/1.1 404 Not Found', TRUE, 404);
// Contain the content for buffering
ob_start();
// This is passed to the error template
$message = '404 Not Found';
include(MM_APP_PATH . '/views/errors/error_404.php');
$buffer = ob_get_contents();
ob_end_clean();
die($buffer);
}
// --------------------------------------------------------------------------
/**
* Fatal Error page function
*
* @param string $message
* @param int $status_code
*/
function show_error($message, $status_code=null)
{
if ( ! is_null($status_code))
{
@header("HTTP/1.1 {$status_code}", TRUE, (int) $status_code);
}
// Contain the content for buffering
ob_start();
include(MM_APP_PATH . '/views/errors/error_general.php');
$buffer = ob_get_contents();
ob_end_clean();
die($buffer);
}
// --------------------------------------------------------------------------
// ! Utility Functions
// --------------------------------------------------------------------------
/**
* Utility function to check if a variable is set, and is an array or object
*
* @param mixed $var
* @return bool
*/
function is_like_array(&$var)
{
if ( ! isset($var))
{
return FALSE;
}
return (is_array($var) OR is_object($var)) && ( ! empty($var));
}
// --------------------------------------------------------------------------
/**
* Returns routable methods for the specified controller class
*
* @param string $controller
* @return array
*/
function controller_methods($controller)
{
$methods = \get_class_methods($controller);
// Eliminate methods from Controller and Model classes
$skip_methods = array_merge(\get_class_methods('miniMVC\Controller'), \get_class_methods('miniMVC\Model'));
$methods = array_diff($methods, $skip_methods);
return $methods;
}
// --------------------------------------------------------------------------
/**
* Returns a full url from a url segment
*
* @param string $segment
* @return string
*/
function site_url($segment)
{
return $url = BASE_URL . URL_INDEX_FILE . $segment;
}
// --------------------------------------------------------------------------
/**
* Prints out the contents of the object
*
* @param object/array $data
* @param string $method
* @return string
*/
function to_string($data, $method='print_r')
{
$output = '<pre>';
if ($method == "var_dump")
{
ob_start();
var_dump($data);
$output .= ob_get_contents();
ob_end_clean();
}
elseif ($method == "var_export")
{
ob_start();
var_export($data);
$output .= ob_get_contents();
ob_end_clean();
}
else
{
$output .= print_r($data, TRUE);
}
return $output . '</pre>';
}
// --------------------------------------------------------------------------
if ( ! function_exists('do_include'))
{
/**
* Array_map callback to load a folder of classes at once
*
* @param string $path
* @return void
*/
function do_include($path)
{
require_once($path);
}
}
// --------------------------------------------------------------------------
// ! Bootstrap functions
// --------------------------------------------------------------------------
/**
* Load required classes for bootstraping
*
* @return void
*/
function init()
{
// Catch fatal errors, don't show them
error_reporting((-1) & ~(E_ERROR | E_PARSE));
register_shutdown_function('miniMVC\shutdown');
//Set error handlers
set_error_handler('miniMVC\on_error');
set_exception_handler('miniMVC\on_exception');
// Load Database classes
require_once(MM_SYS_PATH . 'db/autoload.php');
// Map to the appropriate module/controller/function
route();
}
// --------------------------------------------------------------------------
/**
* Returns the last segment of the current url
*
* @return string
*/
function get_last_segment()
{
$array = get_segments();
return end($array);
}
// --------------------------------------------------------------------------
/**
* Gets an array of the segments of the current url
*
* @return array
*/
function get_segments()
{
$sn = $_SERVER['SCRIPT_NAME'];
$ru = $_SERVER['REQUEST_URI'];
// Get the equivalent to path info
$pi = (isset($_SERVER['PATH_INFO']))
? str_replace($sn, '', $ru)
: '/';
// Correct for being in a sub-directory
if (strlen($sn) > strlen($ru))
{
$pi = '/';
}
return explode('/', $pi);
}
// --------------------------------------------------------------------------
/**
* Calls the appropriate module/controller/function based on the url
*
* @return void
*/
function route()
{
$sn = $_SERVER['SCRIPT_NAME'];
$ru = $_SERVER['REQUEST_URI'];
// Get the equivalent to path info
$pi = (isset($_SERVER['PATH_INFO']))
? str_replace($sn, '', $ru)
: '/';
// Make sure the home page works when in a sub_directory
if (strlen($sn) > strlen($ru))
{
$pi = '/';
}
// Load the routes config file
$routes = require_once(MM_APP_PATH . 'config/routes.php');
// Set the default route
$module = $routes['default_module'];
$controller = $routes['default_controller'];
$func = "index";
$route_set = FALSE;
// If it isn't the index page
if ( ! empty($pi) && $pi !== "/")
{
//Remove trailing slash and begining slash
$pi = trim($pi, '/');
$segments = explode("/", $pi);
// URL matches the route exactly? Cool, that was easy
if (isset($routes[$pi]))
{
list($module, $controller, $func) = explode("/", $routes[$pi]);
run($module, $controller, $func);
return;
}
else
{
$custom_routes = $routes;
// Skip required routes
unset($custom_routes['default_module']);
unset($custom_routes['default_controller']);
unset($custom_routes['404_handler']);
foreach($custom_routes as $uri => $map)
{
if (preg_match("`{$uri}`i", $pi))
{
list($module, $controller, $func) = explode("/", $map);
run($module, $controller, $func);
return;
}
}
}
// Doesn't match a predefined route?
// Match on module/controller/method, module/controller, controller/method, or method
if ( ! $route_set)
{
$num_segments = 0;
if (strpos($pi, '/') === FALSE && ! empty($pi))
{
$num_segments = 1;
}
else
{
$segments = explode('/', $pi);
$num_segments = count($segments);
}
// Determine route based on uri segments
if ($num_segments === 1)
{
$func = $pi;
}
elseif ($num_segments === 2)
{
list($module, $controller) = $segments;
// If it's just controller/function
if ($controller == 'index')
{
$controller = $module;
$module = $routes['default_module'];
$func = 'index';
}
}
else
{
list($module, $controller, $func) = $segments;
}
}
}
run($module, $controller, $func);
return;
}
/**
* Instantiate the appropriate controller
*
* @param string
* @param string
* @param string
*/
function run($module, $controller, $func)
{
$path = MM_MOD_PATH . "{$module}/controllers/{$controller}.php";
if (is_file($path))
{
require_once($path);
// Get the list of valid methods for that controller
$methods = controller_methods($controller);
if (in_array($func, $methods))
{
// Define the name of the current module for file loading
define('MM_MOD', $module);
$class = new $controller();
return call_user_func([&$class, $func]);
}
}
// Function doesn't exist...404
show_404();
}
// End of common.php

128
sys/core/Controller.php Normal file
View File

@ -0,0 +1,128 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Base Controller Class
*
* @package miniMVC
* @subpackage System
*/
class Controller extends miniMVC {
/**
* Instance of Page class
*
* @var Page
*/
protected $page;
/**
* Create the controller object
*
* @return void
*/
public function __construct()
{
parent::__construct();
// Create the page object
$this->page = new Page($this);
}
// --------------------------------------------------------------------------
/**
* Function for loading a model into the current class
*
* @param string $file
* @param array $args
* @return void
*/
public function load_model($file, $args=[])
{
$segments = explode('\\', $file);
$file_name = end($segments);
// The module is set via the router
$module = strtolower(MM_MOD);
$path = MM_MOD_PATH . "{$module}/models/{$file_name}.php";
if (is_file($path))
{
require_once($path);
}
if ( ! empty($args))
{
$this->$file_name = new $file($args);
}
else
{
$this->$file_name = new $file;
}
}
// --------------------------------------------------------------------------
/**
* Function for loading a view
*
* @param string $file
* @param array $data
* @param bool $return
* @return mixed
*/
public function load_view($file, array $data=[], $return=FALSE)
{
$path = "";
// The module is set via the router
$module = strtolower(MM_MOD);
$path = MM_MOD_PATH . "{$module}/views/{$file}.php";
// If it's not a module, or doesn't exist in the module view folder
// look in the app view folder
if ( ! is_file($path))
{
$path = MM_APP_PATH . "views/{$file}.php";
}
// Contain the content for buffering
ob_start();
// Extract the data array
extract($data);
// Include the file
include($path);
$buffer = ob_get_contents();
ob_end_clean();
if ($return == TRUE)
{
return $buffer;
}
else
{
$this->page->append_output($buffer);
}
}
}
// End of controller.php

70
sys/core/MM.php Normal file
View File

@ -0,0 +1,70 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Class for standalone JSObject objects
*
* @package miniMVC
* @subpackage System
*/
class MM extends \ArrayObject {
/**
* Create the ArrayObject hybrid object
*
* @param array
*/
public function __construct($members = array())
{
parent::__construct($members);
// Add the passed parameters to the object
foreach ($members as $name => &$value)
{
$this->$name = $value;
}
}
// --------------------------------------------------------------------------
/**
* Allow calling of array methods on the object and
* dynamic methods
*
* @param string $name
* @param array $params
* @return mixed
*/
public function __call($name, $params = array())
{
// Allow array operations on the object
if (substr($name, 0, 6) === 'array_' && is_callable($name))
{
$args = array_merge($this->getArrayCopy(), $args);
return call_user_func_array($name, $args);
}
// Allow dynamic method calls
if (is_callable($this->$name))
{
//Call the dynamic function
return call_user_func_array($this->$name, $params);
}
}
}
// End of MM.php

38
sys/core/Model.php Normal file
View File

@ -0,0 +1,38 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Base Model Class
*
* @package miniMVC
* @subpackage System
*/
class Model extends miniMVC {
/**
* Initialize the model class
*
* @param array $args
* @return void
*/
public function __construct(array $args = array())
{
parent::__construct($args);
}
}
// End of model.php

156
sys/core/Output.php Normal file
View File

@ -0,0 +1,156 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Class for displaying output and setting http headers
*
* @package miniMVC
* @subpackage System
*/
class Output extends MM {
/**
* Content for outputting
*
* @var string
*/
private $buffer;
/**
* HTTP headers to send
*
* @var array
*/
private $headers;
/**
* Initialize the output class
*
* @return void
*/
public function __construct()
{
$this->buffer = "";
$this->headers = array();
}
// --------------------------------------------------------------------------
/**
* PHP magic method called when ending the script
* Used for outputing HTML
*
* @return void
*/
public function __destruct()
{
if ( ! empty($this->headers))
{
// Set headers
foreach($this->headers as $key => $val)
{
if ( ! isset($val))
{
@header($key);
}
else
{
@header("$key: $val");
}
}
}
if ( ! empty($this->buffer))
{
if (is_null(error_get_last()))
{
// Compression is good!
ob_start("ob_gzhandler");
}
else
{
ob_start();
}
echo $this->buffer;
ob_end_flush();
}
}
// --------------------------------------------------------------------------
/**
* Sets a header for later output
*
* @param string $key
* @param string $val
*/
public function set_header($key, $val)
{
$this->headers[$key] = $val;
}
// --------------------------------------------------------------------------
/**
* Adds text to the output buffer
*
* @param string $string
*/
public function append_output($string)
{
$this->buffer .= $string;
}
// --------------------------------------------------------------------------
/**
* Sets the output buffer
*
* @param string $string
*/
public function set_output($string)
{
$this->buffer = $string;
}
// --------------------------------------------------------------------------
/**
* Sends headers and then removes them
*/
public function flush_headers()
{
// Set headers
foreach ($this->headers as $key => &$val)
{
if ( ! isset($val))
{
@header($key);
}
else
{
@header("{$key}: {$val}");
}
}
// Empty headers
$this->headers = array();
}
}
// End of Output.php

555
sys/core/Page.php Normal file
View File

@ -0,0 +1,555 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Class for building pages
*
* All methods are chainable, with the exception of the constructor,
* build_header(), build_footer(), and _headers() methods.
*
* @package miniMVC
* @subpackage System
*/
class Page extends Output {
/**
* Meta tags
*
* @var string
*/
private $meta;
/**
* JS tags for the header
*
* @var string
*/
private $head_js;
/**
* JS tags for the footer
*
* @var string
*/
private $foot_js;
/**
* CSS tags for the page
*
* @var string
*/
private $css;
/**
* Page title
*
* @var string
*/
private $title;
/**
* Additional header tags
*
* @var string
*/
private $head_tags;
/**
* Class(es) to apply to the main body tag
*
* @var string
*/
private $body_class;
/**
* Id to apply to the body tag
*
* @var string
*/
private $body_id;
/**
* Base tag
*
* @var string
*/
private $base;
/**
* Set up the page class
*
* @param object
* @return void
*/
public function __construct(&$controller)
{
$this->meta = "";
$this->head_js = "";
$this->foot_js = "";
$this->css = "";
$this->title = "";
$this->head_tags = "";
$this->body_class = "";
$this->body_id = "";
$this->base = "";
$this->mm = $controller;
}
// --------------------------------------------------------------------------
/**
* call the parent destructor
*/
public function __destruct()
{
parent::__destruct();
}
// --------------------------------------------------------------------------
/**
* Sets server headers and doctype
*
* Also sets page mime type, based on if sent as
* html or xhtml, and what the target browser
* supports
*
* @param bool $html5
* @return Page
*/
private function _headers($html5)
{
$this->set_header("Cache-Control", "must-revalidate, public");
$mime = "";
//Variable for accept keyword
$accept = ( ! empty($_SERVER['HTTP_ACCEPT'])) ? $_SERVER['HTTP_ACCEPT'] : "";
//Predefine doctype
$doctype_string = ($html5 == TRUE) ? '<!DOCTYPE html>' : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">';
//Predefine charset
$charset = "UTF-8";
$mime = "text/html";
if ($html5 == FALSE)
{
$doctype_string = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">';
}
$doctype_string .= "<html lang='en'>";
// finally, output the mime type and prolog type
$this->set_header("Content-Type", "{$mime};charset={$charset}");
$this->set_header("X-UA-Compatible", "chrome=1, IE=edge");
$this->set_output($doctype_string);
return $this;
}
// --------------------------------------------------------------------------
/**
* Set Meta
*
* Sets meta tags, with codeigniter native meta tag helper
*
* @param array $meta
* @return Page
*/
public function set_meta($meta)
{
$this->meta .= $this->_meta($meta);
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets minified javascript group in header
*
* @param string $group
* @param bool $debug
* @return Page
*/
public function set_head_js_group($group, $debug = FALSE)
{
if ($group === FALSE)
{
return $this;
}
$file = SCRIPT_PATH . $group;
$file .= ($debug == TRUE) ? "/debug/1" : "";
$this->head_js .= $this->script_tag($file, FALSE);
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets a minified css group
* @param string $group
* @return Page
*/
public function set_css_group($group)
{
$link = [
'href' => STYLE_PATH . $group,
'rel' => 'stylesheet',
'type' => 'text/css'
];
$this->css .= $this->_link_tag($link);
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets a minified javascript group for the page footer
*
* @param string $group
* @param bool $debug
* @return Page
*/
public function set_foot_js_group($group, $debug = FALSE)
{
$file = SCRIPT_PATH . $group;
$file .= ($debug == TRUE) ? "/debug/1" : "";
$this->foot_js .= $this->script_tag($file, FALSE);
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets html title string
*
* @param string $title
* @return Page
*/
public function set_title($title = "")
{
$title = ($title == "") ? DEFAULT_TITLE : $title;
$this->title = $title;
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets custom body class
*
* @param string $class
* @return Page
*/
public function set_body_class($class = "")
{
$this->body_class = $class;
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets custom body id
*
* @param string $id
* @return Page
*/
public function set_body_id($id = "")
{
$this->body_id = $id;
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets custom base href
*
* @param string href
* @return Page
*/
public function set_base($href)
{
$this->base = $href;
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets custom css tags
*
* @param string $name
* @param bool $domain
* @param string $media
* @return Page
*/
public function set_css_tag($name, $domain = TRUE, $media = "all")
{
$path = CONTENT_DOMAIN;
$css_file = "{$path}/css/{$name}.css";
if ($domain == FALSE)
{
$css_file = $name;
}
$this->css_tags .= $this->_link_tag([
'rel' => 'stylesheet',
'type' => 'text/css',
'media' => $media,
'href' => $css_file,
]);
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets a custom tag in the header
*
* @param string $tag
* @return Page
*/
public function set_head_tag($tag)
{
$this->head_tags .= $tag;
return $this;
}
// --------------------------------------------------------------------------
/**
* Sets custom page header
*
* @param bool $html5
* @return Page
*/
public function build_header($html5 = TRUE)
{
$data = array();
//Set Meta Tags
$this->meta = ($html5 == TRUE)
? '<meta charset="utf-8" />'. $this->meta
: $this->_meta([
'http-equiv' => 'Content-Type',
'content' => 'text/html; charset=utf-8',
]) . $this->meta;
$data['meta'] = $this->meta;
//Set CSS
if ($this->css !== "")
{
$data['css'] = $this->css;
}
else
{
//Set default CSS group
$this->set_css_group(DEFAULT_CSS_GROUP);
$data['css'] = $this->css;
}
//Set head javascript
$data['head_js'] = ( ! empty($this->head_js)) ? $this->head_js : "";
//Set Page Title
$data['title'] = ($this->title !== '') ? $this->title : DEFAULT_TITLE;
//Set Body Class
$data['body_class'] = $this->body_class;
//Set Body Id
$data['body_id'] = $this->body_id;
//Set Base HREF
$data['base'] = $this->base;
//Set individual head tags
$data['head_tags'] = $this->head_tags;
//Set Server Headers and Doctype
$this->_headers($html5);
//Output Header
$this->mm->load_view('header', $data);
return $this;
}
// --------------------------------------------------------------------------
/**
* Builds common footer with any additional js
*/
public function build_footer()
{
$data = array();
$data['foot_js'] = ($this->foot_js != "") ? $this->foot_js : '';
$this->mm->load_view('footer', $data);
}
// --------------------------------------------------------------------------
/**
* Script Tag
*
* Helper function for making script tags
*
* @param string $js
* @param bool $domain
* @return string
*/
private function script_tag($js, $domain = TRUE)
{
$path = CONTENT_DOMAIN;
$js_file = "{$path}/js/{$js}.js";
if ($domain == FALSE)
{
$js_file = $js;
}
$tag = '<script src="' . $js_file . '"></script>';
return $tag;
}
// --------------------------------------------------------------------------
/**
* Set Message
*
* Adds a message to the page
* @param string $type
* @param string $message
* @param bool $return
* @return void
*/
public function set_message($type, $message, $return=FALSE)
{
$data['stat_class'] = $type;
$data['message'] = $message;
return $this->mm->load_view('message', $data, $return);
}
// --------------------------------------------------------------------------
/**
* Redirect 303
*
* Shortcut function for 303 redirect
* @param string $url
*/
function redirect_303($url)
{
$this->set_header("HTTP/1.1 303 See Other");
$this->set_header("Location:" . $url);
}
// --------------------------------------------------------------------------
/**
* Render
*
* Shortcut function for building a page
* @param string $view
* @param array $data
*/
function render($view, $data=array())
{
$this->build_header();
$this->mm->load_view($view, $data);
$this->build_footer();
}
// --------------------------------------------------------------------------
/**
* Output String
*
* Similar to render(), this is a shortcut
* to output a string in the body of the
* page.
* @param string $string
*/
function output_string($string)
{
$this->build_header();
$this->append_output($string);
$this->build_footer();
}
// --------------------------------------------------------------------------
/**
* Private helper function to generate meta tags
*
* @param array $params
* @return string
*/
private function _meta($params)
{
$string = "<meta ";
foreach ($params as $k => &$v)
{
$string .= $k.'="'.$v.'" ';
}
$string .= " />";
return $string;
}
// --------------------------------------------------------------------------
/**
* Private helper function to generate link tags
*
* @param array $params
* @return string
*/
private function _link_tag($params)
{
$string = "<link ";
foreach ($params as $k => &$v)
{
$string .= $k . '="'.$v.'" ';
}
$string .= "/>";
return $string;
}
}
// End of page.php

100
sys/core/db.php Normal file
View File

@ -0,0 +1,100 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Extend PHP's PDO class to add some more functionality
*
* @package miniMVC
* @subpackage System
*/
class DB extends \Query_Builder {
/**
* DB connection instances
*
* @var array
*/
private static $instance = array();
// --------------------------------------------------------------------------
/**
* Indexed singleton method
*
* @param string $dbname
* @param array $options
* @return DB
*/
public static function &get_instance($dbname="default", array $options=array())
{
if ( ! isset(self::$instance[$dbname]))
{
// Include the database config file
require_once(MM_APP_PATH.'config/db.php');
// Get the correct database in the config file
if ( ! is_like_array($db_conf[$dbname]))
{
// Apparently the database doesn't exist
$this->get_last_error();
trigger_error("Database does not exist", E_USER_ERROR);
die();
}
//echo 'Creating new instance of db class.';
self::$instance[$dbname] = new DB($db_conf[$dbname]);
}
return self::$instance[$dbname];
}
// --------------------------------------------------------------------------
/**
* Returns the last error from the database
*
* @return string
*/
public function get_last_error()
{
$error = array();
if (isset($this->statement))
{
$error = $this->statement->errorInfo();
}
else
{
$error = $this->errorInfo();
}
$code = $error[0];
$driver_code = $error[1];
$message = $error[2];
// Contain the content for buffering
ob_start();
include(MM_APP_PATH.'/views/errors/error_db.php');
$buffer = ob_get_contents();
ob_end_clean();
echo $buffer;
}
}
// End of db.php

84
sys/core/miniMVC.php Normal file
View File

@ -0,0 +1,84 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Base class for the framework
*
* @package miniMVC
* @subpackage System
*/
class miniMVC extends MM {
/**
* Constructor - Any classes loaded here become subclasses of miniMVC
*
* @param array $members
*/
public function __construct($members = array())
{
// Allow the class to be used like an array
parent::__construct($members);
}
// --------------------------------------------------------------------------
/**
* Convenience function to load config files
*
* @param string $name
*/
public function load_config($name)
{
$path = MM_APP_PATH . "config/{$name}.php";
if (is_file($path))
{
require_once($path);
}
}
// --------------------------------------------------------------------------
/**
* Singleton getter function
*
* @return self
*/
public static function &get_instance()
{
if ( ! isset(self::$instance))
{
$class = __CLASS__;
self::$instance = new $class;
}
return self::$instance;
}
// --------------------------------------------------------------------------
/**
* Magic function called when cloning an object
*/
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
// End of miniMVC.php

1
sys/db Submodule

@ -0,0 +1 @@
Subproject commit 977434977e4177fe5a09fffa0f3a152faa82f606

View File

@ -0,0 +1,153 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Class for using JSON as a key->value data store
*
* @package miniMVC
* @subpackage Libraries
*/
class Data_Store {
/**
* Settings object represented by the currently loaded JSON file
*/
private $current;
/**
* Singleton instance
*/
private static $instance;
/**
* Create and/or load json file
*/
protected function __construct()
{
$path = MM_APP_PATH .'config/data_store.json';
if ( ! is_file($path))
{
touch($path);
$this->current = (object)[];
}
else
{
// Load the file
$json = file_get_contents($path);
// Load the object into the class
$this->current = json_decode($json);
}
}
// --------------------------------------------------------------------------
/**
* Output the data on destruct
*/
public function __destruct()
{
$file_string = json_encode($this->current, JSON_PRETTY_PRINT);
file_put_contents(MM_APP_PATH . 'config/data_store.json', $file_string);
}
// --------------------------------------------------------------------------
/**
* Magic function called when cloning an object
*/
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
// --------------------------------------------------------------------------
/**
* Magic method to simplify isset checking for config options
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
return (isset($this->current->{$key}))
? $this->current->{$key}
: NULL;
}
// --------------------------------------------------------------------------
/**
* Magic method to simplify setting config options
*
* @param string $key
* @param mixed
*/
public function __set($key, $val)
{
return $this->current->{$key} = $val;
}
// --------------------------------------------------------------------------
/**
* Static method to retreive current instance
* of the singleton
*
* @return self
*/
public static function &get_instance()
{
if( ! isset(self::$instance))
{
$name = __CLASS__;
self::$instance = new $name();
}
return self::$instance;
}
// --------------------------------------------------------------------------
/**
* Removes a key from the data store
*
* @param string $key
* @return void
*/
public function del($key)
{
unset($this->current->{$key});
}
// --------------------------------------------------------------------------
/**
* Return the entire data store object
*
* @return object
*/
public function get_all()
{
return $this->current;
}
}
// End of data store.php

121
sys/libraries/Session.php Normal file
View File

@ -0,0 +1,121 @@
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
* @author Timothy J. Warren
* @copyright Copyright (c) 2011 - 2012
* @link https://github.com/aviat4ion/miniMVC
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace miniMVC;
/**
* Class to improve handling of PHP sessions
*
* @package miniMVC
* @subpackage Libraries
*/
class Session {
/**
* Reference to session superglobal
*
* @var array
*/
protected $sess = array();
/**
* Reference to current instance
*
* @var Session
*/
protected static $instance;
/**
* Start a session
*/
protected function __construct()
{
session_start();
// Save a reference to the session for later access
$_SESSION['MM_SESSION'] = (isset($_SESSION['MM_SESSION'])) ?: array();
$this->sess =& $_SESSION['MM_SESSION'];
}
// --------------------------------------------------------------------------
/**
* Set a session value
*
* @param string $key
* @param mixed $val
* @return void
*/
public function __set($key, $val)
{
$this->sess[$key] = $val;
}
// --------------------------------------------------------------------------
/**
* Retreive a session value
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
return $this->sess[$key];
}
// --------------------------------------------------------------------------
/**
* Destroy a session
*
* @return void
*/
public function destroy()
{
sess_destroy();
}
// --------------------------------------------------------------------------
/**
* Singleton getter function
*
* @return self
*/
public static function &get_instance()
{
if ( ! isset(self::$instance))
{
$class = __CLASS__;
self::$instance = new $class;
}
return self::$instance;
}
// --------------------------------------------------------------------------
/**
* Magic function called when cloning an object
*/
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
// End of session.php

BIN
sys/meta.sqlite Normal file

Binary file not shown.