miniMVC/sys/common.php

478 lines
10 KiB
PHP
Raw Normal View History

2012-01-13 11:58:06 -05:00
<?php
/**
* MiniMVC
*
* Convention-based micro-framework for PHP
*
* @package miniMVC
2012-01-13 11:58:06 -05:00
* @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
2012-01-13 11:58:06 -05:00
*/
2012-05-22 11:11:36 -04:00
namespace miniMVC;
2012-01-13 11:58:06 -05:00
// --------------------------------------------------------------------------
2012-05-21 14:49:33 -04:00
// ! Autoloading
2012-05-18 08:04:01 -04:00
// --------------------------------------------------------------------------
2012-01-13 11:58:06 -05:00
2012-05-21 14:29:36 -04:00
/**
2012-05-21 14:49:33 -04:00
* Function to autoload system libraries
*
* @param string
*/
function sys_autoload($name)
2012-05-22 11:11:36 -04:00
{
$name = str_replace('miniMVC\\', '', $name);
2012-05-21 14:49:33 -04:00
$path = MM_SYS_PATH . "/core/{$name}.php";
2012-05-21 14:58:58 -04:00
$trait_path = MM_SYS_PATH . "/core/traits/{$name}.php";
2012-05-21 14:49:33 -04:00
if (is_file($path))
{
require_once($path);
}
2012-05-21 14:58:58 -04:00
elseif (is_file($trait_path))
{
require_once($trait_path);
}
2012-05-21 14:49:33 -04:00
}
// --------------------------------------------------------------------------
/**
* Function to autoload libraries/classes
2012-05-21 14:29:36 -04:00
*
* @param string
*/
function autoload($name)
{
2012-05-22 11:11:36 -04:00
// strip off namespaces - they all go to the same folder
$names = explode('\\', $name);
$name = end($names);
2012-05-21 14:29:36 -04:00
// 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);
}
}
}
2012-05-22 11:11:36 -04:00
// Load system libraries/traits
spl_autoload_register('miniMVC\sys_autoload');
// Start the library autoloader
spl_autoload_register('miniMVC\autoload');
2012-05-21 14:49:33 -04:00
// --------------------------------------------------------------------------
// ! Error handling / messages
2012-05-21 14:29:36 -04:00
// --------------------------------------------------------------------------
2012-01-13 11:58:06 -05:00
/**
* Function to run on script shutdown
* -used to catch most fatal errors, and
* display them cleanly
2012-05-01 15:22:29 -04:00
*
* @return void
2012-01-13 11:58:06 -05:00
*/
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
2012-05-03 13:26:09 -04:00
if (in_array($error['type'], $fatal))
2012-01-13 11:58:06 -05:00
{
$file = str_replace(MM_BASE_PATH, "", $error['file']);
2012-01-13 11:58:06 -05:00
2012-05-18 08:04:01 -04:00
$err_msg = "<h2>Fatal Error: </h2>
{$error['message']}<br /><br />
<strong>File:</strong> {$file}<br /><br />
<strong>Line:</strong> {$error['line']}";
2012-01-13 11:58:06 -05:00
show_error($err_msg);
}
}
// --------------------------------------------------------------------------
/**
* Custom error handler
*
* @param int $severity
* @param string $message
* @param string $filepath
* @param int $line
2012-04-27 16:28:25 -04:00
* @return ErrorException
2012-01-13 11:58:06 -05:00
*/
2012-04-27 16:28:25 -04:00
function on_error($severity, $message, $filepath, $line)
2012-01-13 11:58:06 -05:00
{
2012-05-22 11:11:36 -04:00
throw new \ErrorException($message, 0, $severity, $filepath, $line);
2012-01-13 11:58:06 -05:00
}
// --------------------------------------------------------------------------
/**
* Custom exception handlererror_get_last
*
* @param Exception $exception
* @return void
2012-01-13 11:58:06 -05:00
*/
function on_exception($exception)
{
// This is passed to the error template
2012-01-13 11:58:06 -05:00
$message = $exception->getMessage();
// Contain the content for buffering
ob_start();
2012-05-18 08:04:01 -04:00
include(MM_APP_PATH . '/views/errors/error_php_exception.php');
2012-01-13 11:58:06 -05:00
$buffer = ob_get_contents();
ob_end_clean();
echo $buffer;
}
// --------------------------------------------------------------------------
/**
* General 404 function
2012-05-01 15:22:29 -04:00
*
* @return void
2012-01-13 11:58:06 -05:00
*/
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';
2012-05-18 08:04:01 -04:00
include(MM_APP_PATH . '/views/errors/error_404.php');
$buffer = ob_get_contents();
ob_end_clean();
die($buffer);
2012-01-13 11:58:06 -05:00
}
// --------------------------------------------------------------------------
/**
* Fatal Error page function
*
* @param string $message
* @param int $status_code
*/
function show_error($message, $status_code=null)
{
2012-05-03 13:26:09 -04:00
if ( ! is_null($status_code))
2012-01-13 11:58:06 -05:00
{
2012-05-15 16:53:10 -04:00
@header("HTTP/1.1 {$status_code}", TRUE, (int) $status_code);
2012-01-13 11:58:06 -05:00
}
// Contain the content for buffering
ob_start();
2012-05-18 08:04:01 -04:00
include(MM_APP_PATH . '/views/errors/error_general.php');
2012-01-13 11:58:06 -05:00
$buffer = ob_get_contents();
ob_end_clean();
die($buffer);
}
2012-05-18 08:04:01 -04:00
// --------------------------------------------------------------------------
// ! 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));
}
2012-01-13 11:58:06 -05:00
// --------------------------------------------------------------------------
/**
* Returns routable methods for the specified controller class
*
* @param string $controller
* @return array
*/
function controller_methods($controller)
{
2012-05-22 11:11:36 -04:00
$methods = \get_class_methods($controller);
2012-05-01 15:22:29 -04:00
// Eliminate methods from Controller and Model classes
2012-05-22 11:11:36 -04:00
$skip_methods = array_merge(\get_class_methods('miniMVC\Controller'), \get_class_methods('miniMVC\Model'));
2012-05-01 15:22:29 -04:00
$methods = array_diff($methods, $skip_methods);
2012-01-13 11:58:06 -05:00
return $methods;
}
// --------------------------------------------------------------------------
2012-05-18 08:04:01 -04:00
/**
* 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();
}
2012-05-18 13:52:12 -04:00
elseif ($method == "var_export")
2012-05-18 08:04:01 -04:00
{
ob_start();
var_export($data);
$output .= ob_get_contents();
ob_end_clean();
}
else
{
$output .= print_r($data, TRUE);
}
return $output . '</pre>';
}
// --------------------------------------------------------------------------
2012-05-18 16:20:47 -04:00
if ( ! function_exists('do_include'))
2012-05-18 08:04:01 -04:00
{
2012-05-18 16:20:47 -04:00
/**
* Array_map callback to load a folder of classes at once
*
* @param string $path
* @return void
*/
function do_include($path)
{
require_once($path);
}
2012-05-18 08:04:01 -04:00
}
// --------------------------------------------------------------------------
// ! 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));
2012-05-22 11:11:36 -04:00
register_shutdown_function('miniMVC\shutdown');
2012-05-18 08:04:01 -04:00
//Set error handlers
2012-05-22 11:11:36 -04:00
set_error_handler('miniMVC\on_error');
set_exception_handler('miniMVC\on_exception');
2012-05-18 08:04:01 -04:00
// Load Database classes
require_once(MM_SYS_PATH . 'db/autoload.php');
// Map to the appropriate module/controller/function
route();
}
// --------------------------------------------------------------------------
2012-01-13 11:58:06 -05:00
/**
* Calls the appropriate module/controller/function based on the url
2012-05-01 15:22:29 -04:00
*
* @return void
2012-01-13 11:58:06 -05:00
*/
function route()
{
2012-05-01 15:22:29 -04:00
$sn = $_SERVER['SCRIPT_NAME'];
$ru = $_SERVER['REQUEST_URI'];
// Get the equivalent to path info
2012-05-01 09:39:49 -04:00
$pi = (isset($_SERVER['PATH_INFO']))
2012-05-01 15:22:29 -04:00
? str_replace($sn, '', $ru)
2012-05-01 09:39:49 -04:00
: '/';
2012-05-01 15:22:29 -04:00
// Make sure the home page works when in a sub_directory
if (strlen($sn) > strlen($ru))
{
$pi = '/';
}
2012-01-13 11:58:06 -05:00
// Load the routes config file
2012-05-18 08:04:01 -04:00
$routes = require_once(MM_APP_PATH . 'config/routes.php');
2012-01-13 11:58:06 -05:00
// Set the default route
$module = $routes['default_module'];
$controller = $routes['default_controller'];
$func = "index";
$route_set = FALSE;
2012-05-15 16:53:10 -04:00
// If it isn't the index page
2012-05-03 13:26:09 -04:00
if ( ! empty($pi) && $pi !== "/")
2012-01-13 11:58:06 -05:00
{
//Remove trailing slash and begining slash
$pi = trim($pi, '/');
// URL matches the route exactly? Cool, that was easy
2012-05-03 13:26:09 -04:00
if (isset($routes[$pi]))
2012-01-13 11:58:06 -05:00
{
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']);
2012-05-15 11:22:16 -04:00
foreach($custom_routes as $uri => &$map)
2012-01-13 11:58:06 -05:00
{
2012-05-03 13:26:09 -04:00
if (preg_match("`{$uri}`i", $pi))
2012-01-13 11:58:06 -05:00
{
list($module, $controller, $func) = explode("/", $map);
$route_set = TRUE;
break;
}
}
}
// Doesn't match a predefined route?
2012-05-15 16:53:10 -04:00
// Match on module/controller/method, module/controller, controller/method, or method
2012-05-03 13:26:09 -04:00
if ( ! $route_set)
2012-01-13 11:58:06 -05:00
{
$num_segments = 0;
2012-05-03 13:26:09 -04:00
if (strpos($pi, '/') === FALSE && ! empty($pi))
2012-01-13 11:58:06 -05:00
{
$num_segments = 1;
}
else
{
$segments = explode('/', $pi);
$num_segments = count($segments);
}
2012-05-15 11:22:16 -04:00
// Determine route based on uri segments
2012-05-03 13:26:09 -04:00
if ($num_segments === 1)
2012-01-13 11:58:06 -05:00
{
$func = $pi;
}
2012-05-15 11:22:16 -04:00
elseif ($num_segments === 2)
2012-01-13 11:58:06 -05:00
{
2012-05-15 11:22:16 -04:00
list($module, $controller) = $segments;
// If it's just controller/function
if ($controller == 'index')
{
$controller = $module;
$module = $routes['default_module'];
$func = 'index';
}
2012-01-13 11:58:06 -05:00
}
2012-05-15 11:22:16 -04:00
elseif ($num_segments >= 3)
2012-01-13 11:58:06 -05:00
{
list($module, $controller, $func) = $segments;
}
}
}
2012-05-18 08:04:01 -04:00
$path = MM_MOD_PATH . "{$module}/controllers/{$controller}.php";
2012-01-13 11:58:06 -05:00
2012-05-03 13:26:09 -04:00
if (is_file($path))
2012-01-13 11:58:06 -05:00
{
require_once($path);
// Get the list of valid methods for that controller
$methods = controller_methods($controller);
2012-05-03 13:26:09 -04:00
if (in_array($func, $methods))
2012-01-13 11:58:06 -05:00
{
// Define the name of the current module for file loading
2012-05-01 16:39:14 -04:00
define('MM_MOD', $module);
$class = new $controller();
return call_user_func_array([&$class, $func], []);
2012-01-13 11:58:06 -05:00
}
2012-05-15 16:53:10 -04:00
// Function doesn't exist...404
2012-01-13 11:58:06 -05:00
show_404();
die();
}
// If it gets here, it's still a 404
show_404();
}
// End of common.php