firebox_controller_functions.php
8.6 KB, 256 lines
<?php
/* Firebox - PHP Web Application Framework
Copyright (C) 2007 Andrew J. Fabian
All rights reserved.
*/
function display($filename)
{
$args = func_get_args(); array_unshift($args, false); array_unshift($args, 'view'); array_unshift($args, 'display');
return(call_user_func_array('fbx_run_file', $args));
}
function layout($filename)
{
$args = func_get_args(); array_unshift($args, false); array_unshift($args, 'layout'); array_unshift($args, 'layout');
return(call_user_func_array('fbx_run_file', $args));
}
function action_once($filename)
{
$args = func_get_args(); array_unshift($args, true); array_unshift($args, 'model'); array_unshift($args, 'action');
return(call_user_func_array('fbx_run_file', $args));
}
function action($filename)
{
$args = func_get_args(); array_unshift($args, false); array_unshift($args, 'model'); array_unshift($args, 'action');
return(call_user_func_array('fbx_run_file', $args));
}
function query($filename)
{
$args = func_get_args(); array_unshift($args, false); array_unshift($args, 'model'); array_unshift($args, 'query');
return(call_user_func_array('fbx_run_file', $args));
}
function relocate($url)
{
fbx_execute_plugins('prerelocate', $url);
if (headers_sent()) echo "\n<script language=\"Javascript\">\ndocument.location.href='$url';\n</script>\n";
else header("Location: $url");
exit();
}
function setlink($name, $action)
{
$target = fbx_execute_plugins('setlink', $action);
if ($target == null)
{
$target = $GLOBALS['myself'] . (!strpos($action, '.') ? $GLOBALS['fbx']['call_stack'][count($GLOBALS['fbx']['call_stack'])-1]['filename'] . '.' . $action : $action);
}
fbx_debug("Storing link for $name to $target", __FILE__, __LINE__);
$GLOBALS['fbx']['links'][$name] = $target;
}
function linkto($name)
{
if (!isset($GLOBALS['fbx']['links'][$name])) return(false);
return($GLOBALS['fbx']['links'][$name]);
}
function linkaction($name)
{
if (!isset($GLOBALS['fbx']['links'][$name])) return(false);
preg_match('|go=([a-zA-Z0-9_]+\.[a-zA-Z0-9_]+)|', $GLOBALS['fbx']['links'][$name], $matches);
return($matches[1]);
}
function control($action)
{
global $fbx;
// figure out the filename and function name we're compiling
if (strpos($action, '.'))
{
list($filename, $method) = explode('.', $action, 2);
}
else
{
$filename = $fbx['call_stack'][count($fbx['call_stack'])-1]['filename'];
$method = $action;
}
$prefix = $fbx['production'] ? 'prod' : 'dev';
$is_plugin = substr($action, 0, 7) == 'plugin.';
// update our debug displays
$fbx['debug_indent']++;
$fbx['call_stack'][] = array('filename' => $filename, 'method' => $method);
// run precontrol plugins
fbx_execute_plugins('precontrol', $action);
// decide if we need to compile this function, and do so if necessary
if (!$is_plugin)
{
if (!file_exists($fbx['site_root'] . 'controller/' . $filename . '.php')) fbx_error('Controller file ' . $filename . ' doesn\'t exist.');
if (!$fbx['production'] || !file_exists($fbx['site_root'] . "parsed/$prefix/$action.php"))
{
require_once($fbx['fbx_root'] . 'firebox_compiler.php');
fbx_compile("controller/$filename.php");
}
// load our compiled file, to define our controller function and any test functions
fbx_debug("Running controller action $action from file controller/$filename.php as parsed/$prefix/controller." . $filename . '.php', __FILE__, __LINE__);
require_once($fbx['site_root'] . "parsed/$prefix/controller.$filename.php");
}
// run unit/functional tests if available and we want to
if (!$is_plugin && !$fbx['production'] && !fbx_url_option('fbx_skip_tests'))
{
if (!isset($fbx['control_tests_run']) || false === @array_search($action, $fbx['control_tests_run']))
{
$fbx['debug_indent']++;
$fbx['control_tests_run'][] = $action;
$functionname = 'test_controller_' . str_replace(array('.php','/','.'), '_', $action);
fbx_debug("Running tests for controller in function $functionname", __FILE__, __LINE__);
if (!function_exists($functionname)) fbx_debug('Warning: no tests exist.', __FILE__, __LINE__);
elseif (!$functionname()) fbx_error("Tests failed for $action", __FILE__, __LINE__);
$fbx['debug_indent']--;
}
}
// finally run the controller function
if ($is_plugin)
{
$functionname = $method;
}
else
{
$functionname = 'controller_' . str_replace(array('.php','/','.'), '_', $filename) . '_' . $method;
}
fbx_debug("Compiled controller function is $functionname", __FILE__, __LINE__);
if (!function_exists($functionname)) fbx_error('Controller function ' . $method . ', compiled as ' . $functionname . ', doesn\'t exist in file ' . $filename . '.');
$function_args = func_get_args(); array_shift($function_args);
$output = @call_user_func_array($functionname, $function_args);
// run postcontrol plugins
fbx_execute_plugins('postcontrol', $action);
// clean up and return our controller's output
$fbx['debug_indent']--;
array_pop($fbx['call_stack']);
return($output);
}
function fbx_run_file($type, $path, $only_once, $filename)
{
global $fbx;
// if only_once and it's already been run, return
if ($only_once && isset($fbx['files_run']) && (array_search($path.$filename, $fbx['files_run']) !== false))
{
fbx_debug("Skipping repeat of $path.$filename", __FILE__, __LINE__);
return;
}
else
{
$fbx['files_run'][] = $path.$filename;
}
$fbx['debug_indent']++;
// run pre[this file type] plugins
fbx_execute_plugins("pre$type", $filename);
// figure out the filename and function we're compiling
if (strpos($filename, '.'))
{
list($controller, $filename) = explode('.', $filename, 2);
}
else
{
$controller = $fbx['call_stack'][count($fbx['call_stack'])-1]['filename'];
}
$fbx['call_stack'][] = array('filename' => $controller, 'method' => $filename);
$prefix = $fbx['production'] ? 'prod' : 'dev';
fbx_debug("Running $type file $path/$controller/$filename.php", __FILE__, __LINE__);
if (!file_exists($GLOBALS['fbx']['site_root'] . $path . '/' . $controller . '/' . $filename . '.php')) fbx_error("Can't find $type file $path/$controller/$filename.php");
$outputfile = $fbx['site_root'] . "parsed/$prefix/$path.$controller." . str_replace("/", ".", $filename) . ".php";
// compile the file if we need to do so
if (!$fbx['production'] || !file_exists($outputfile))
{
require_once($fbx['fbx_root'] . 'firebox_compiler.php');
fbx_compile($path . '/' . $controller . '/' . $filename . '.php');
}
// model and view files can be run a few different ways, depending on if they define a function,
// and if that function produces output or not. here's our first try: run the file. it will
// either produce output we can use, or it'll define a function we can use.
$output = fbx_require_output($outputfile);
// if the file defined any test functions, and we're in development mode, run them now
if (!$fbx['production'] && !fbx_url_option('fbx_skip_tests'))
{
if (!isset($fbx['mv_tests_run']) || false === array_search($filename, $fbx['mv_tests_run']))
{
$fbx['mv_tests_run'][] = $filename;
$functionname = 'test_' . str_replace(array('.php','/','.'), '_', $path . '_' . $controller . '_' . $filename. '_' . $filename);
fbx_debug("Running tests for file in function $functionname", __FILE__, __LINE__);
$fbx['debug_indent']++;
if (!function_exists($functionname)) fbx_debug('Warning: no tests exist.', __FILE__, __LINE__);
elseif (!$functionname()) fbx_error("Tests failed for $functionname", __FILE__, __LINE__);
$fbx['debug_indent']--;
}
}
// if the file defined a main function, run that now and capture both it's return value and its
// direct output. Use the return value if it exists, otherwise its output
$functionname = str_replace(array('.php','/','.'), '_', $path . '_' . $controller . '_' . $filename . '_' . $filename);
if (function_exists($functionname))
{
fbx_debug("File defined a function. Running that function with provided arguements.", __FILE__, __LINE__);
$function_args = func_get_args(); array_shift($function_args); array_shift($function_args); array_shift($function_args); array_shift($function_args);
ob_start();
$output = call_user_func_array($functionname, $function_args);
if ($path != 'model' && !$output)
{
fbx_debug("View/Layout function didn't return anything. Using output buffer instead.", __FILE__, __LINE__);
$output = ob_get_contents();
if (empty($output)) fbx_debug("Warning: Output buffer is empty", __FILE__, __LINE__);
}
ob_end_clean();
}
// run post[this file type] plugins
fbx_execute_plugins("post$type", $filename);
// clean up and return our output
$fbx['debug_indent']--;
array_pop($fbx['call_stack']);
return($output);
}