470 lines
9.8 KiB
PHP
470 lines
9.8 KiB
PHP
<?php
|
|
/**
|
|
* MiniMVC
|
|
*
|
|
* Convention-based micro-framework for PHP
|
|
*
|
|
* @package miniMVC
|
|
* @author Timothy J. Warren
|
|
* @copyright Copyright (c) 2011 - 2012
|
|
* @link https://github.com/timw4mail/miniMVC
|
|
* @license http://philsturgeon.co.uk/code/dbad-license
|
|
*/
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
/**
|
|
* File including common framework-wide functions
|
|
*
|
|
* @package miniMVC
|
|
* @subpackage System
|
|
*/
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ! Autoloading
|
|
// --------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Function to autoload system libraries
|
|
*
|
|
* @param string
|
|
*/
|
|
function sys_autoload($name)
|
|
{
|
|
$path = MM_SYS_PATH . "/core/{$name}.php";
|
|
$trait_path = MM_SYS_PATH . "/core/traits/{$name}.php";
|
|
|
|
if (is_file($path))
|
|
{
|
|
require_once($path);
|
|
}
|
|
elseif (is_file($trait_path))
|
|
{
|
|
require_once($trait_path);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Function to autoload libraries/classes
|
|
*
|
|
* @param string
|
|
*/
|
|
function autoload($name)
|
|
{
|
|
// In a subdirectory? No problem
|
|
if (strpos("/", $name) !== FALSE)
|
|
{
|
|
$n = explode("/", $name);
|
|
$name = $n[count($n) -1];
|
|
}
|
|
|
|
// Try system library first, then app library
|
|
$name = strtolower($name);
|
|
$path = MM_SYS_PATH . "libraries/{$name}.php";
|
|
|
|
if ( ! is_file($path))
|
|
{
|
|
$path = MM_APP_PATH . "classes/{$name}.php";
|
|
}
|
|
|
|
// Load the class file if need be
|
|
if ( ! class_exists($name))
|
|
{
|
|
if (is_file($path))
|
|
{
|
|
require_once($path);
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ! 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 = array(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('MM_Controller'), get_class_methods('MM_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 = BASEURL . 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('shutdown');
|
|
|
|
//Set error handlers
|
|
set_error_handler('on_error');
|
|
set_exception_handler('on_exception');
|
|
|
|
// Load Database classes
|
|
require_once(MM_SYS_PATH . 'db/autoload.php');
|
|
|
|
// Map to the appropriate module/controller/function
|
|
route();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
/**
|
|
* 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, '/');
|
|
|
|
// URL matches the route exactly? Cool, that was easy
|
|
if (isset($routes[$pi]))
|
|
{
|
|
list($module, $controller, $func) = explode("/", $routes[$pi]);
|
|
$route_set = TRUE;
|
|
}
|
|
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);
|
|
$route_set = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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';
|
|
}
|
|
|
|
}
|
|
elseif ($num_segments >= 3)
|
|
{
|
|
list($module, $controller, $func) = $segments;
|
|
}
|
|
}
|
|
}
|
|
|
|
$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_array([&$class, $func], []);
|
|
}
|
|
|
|
// Function doesn't exist...404
|
|
show_404();
|
|
die();
|
|
}
|
|
|
|
// If it gets here, it's still a 404
|
|
show_404();
|
|
}
|
|
|
|
// Load system libraries/traits
|
|
spl_autoload_register('sys_autoload');
|
|
|
|
// Start the library autoloader
|
|
spl_autoload_register('autoload');
|
|
|
|
// End of common.php
|