<?php
/**
* dbscript for PHP 4 & 5 - restful crud framework
* @version 0.3.0 -- 10-Jun-2007
* @author Brian Hendrickson <hide@address.com>
* @link http://dbscript.net/
* @copyright Copyright 2007 Brian Hendrickson
* @package dbscript
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* classify
*
* takes a table/resource name ('entries')
* makes it singular & capitalized ('Entry')
*
* @access public
* @param string $resource
* @return string
*/
function classify( $resource ) {
$n = strtolower(str_replace( '_', ' ', $resource ));
switch( $n ) {
// renaming handlers
case ( 'people' ) :
$n = 'Person';
break;
case ( substr( $n, -3 ) == 'ies' ) :
$n = substr( $n, 0, -3 ) . "y";
break;
case ( substr( $n, -1 ) == 's' ) :
$n = substr( $n, 0, -1 );
break;
}
$n = ucwords($n);
$n = str_replace( ' ', '', $n );
return $n;
}
/**
* tableize
*
* takes a (CamelCase or not) name ('DbSession')
* makes it lower_case and plural ('db_sessions')
*
* @access public
* @param string $table
* @return string
*/
function tableize( $object ) {
$n = preg_split( '//', $object );
// replace uppercase Chars with _ and lowercase char
foreach ( $n as $idx=>$char ) {
if ( ctype_upper( $char ) && ( $idx > 1 ) && $char )
$n[$idx] = "_" . strtolower($char);
elseif ( ctype_upper( $char ) )
$n[$idx] = strtolower($char);
}
$n = implode($n);
switch( strtolower($n) ) {
// renaming handlers
case ( $n == 'person' ) :
$n = 'people';
break;
case ( substr( $n, -1 ) == 'y' ) :
$n = substr( $n, 0, -1 ) . "ies";
break;
case ( substr( $n, -1 ) != 's' ) :
$n = $n . "s";
break;
}
return $n;
}
/**
* Error
*
* custom Error handling per-client-type
*
* @author Brian Hendrickson <hide@address.com>
* @access public
* @param integer $errno
* @param string $errstr
* @param string $errfile
* @param integer $errline
* @todo return based on content-negotiation status
*/
function dbscript_error( $errno, $errstr, $errfile, $errline ) {
if ( !error_reporting() || $errno == 2048 )
return;
switch ($errno) {
case E_USER_ERROR:
$req = request_object();
if (isset($_GET['dbscript_xml_error_continue'])) {
$xml = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
$xml .= "<root>\n";
$xml .= " <dbscript_error>Fatal error in line $errline of file $errfile<br>: $errstr</dbscript_error>\n";
$xml .= "</root>\n";
print $xml;
} elseif (isset($req->error)) {
$req->handle_error( $errstr );
print "<b>ERROR</b> [$errno] $errstr<br />\n";
print " Fatal error in line $errline of file $errfile<br />\n";
print "Aborting...<br />\n";
exit(1);
} else {
print "<b>ERROR</b> [$errno] $errstr<br />\n";
print " Fatal error in line $errline of file $errfile<br />\n";
print "Aborting...<br />\n";
exit(1);
}
break;
case E_USER_WARNING:
print "<b>WARNING</b> [$errno] $errstr<br />\n";
break;
case E_USER_NOTICE:
print "<b>NOTICE</b> [$errno] $errstr<br />\n";
break;
default:
print "<b>ERROR</b> [$errno] $errstr<br />\n";
print " Error in line $errline of file $errfile<br />\n";
break;
}
}
/**
* Trigger Before
*
* trip before filters for a function
*
* @access public
* @param string $func
* @param object $obj_a
* @param object $obj_b
*/
function trigger_before( $func, &$obj_a, &$obj_b ) {
if ( isset( $GLOBALS['ASPECTS']['before'][$func] ) ) {
foreach( $GLOBALS['ASPECTS']['before'][$func] as $callback ) {
call_user_func_array( $callback, array( $obj_a, $obj_b ) );
}
}
}
/**
* Trigger After
*
* trip after filters for a function
*
* @access public
* @param string $func
* @param object $obj_a
* @param object $obj_b
*/
function trigger_after( $func, &$obj_a, &$obj_b ) {
if ( isset( $GLOBALS['ASPECTS']['after'][$func] ) ) {
foreach( $GLOBALS['ASPECTS']['after'][$func] as $callback ) {
call_user_func_array( $callback, array( $obj_a, $obj_b ) );
}
}
}
/**
* aspect_join_functions
*
* add trigger function name pairs to GLOBALS
*
* @access public
* @param string $func
* @param string $callback
* @param string $type
*/
function aspect_join_functions( $func, $callback, $type = 'after' ) {
$GLOBALS['ASPECTS'][$type][$func][] = $callback;
}
/**
* Before Filter
*
* set an aspect function to trigger before another function
*
* @access public
* @param string $name
* @param string $func
* @param string $when
*/
function before_filter( $name, $func, $when = 'before' ) {
aspect_join_functions( $func, $name, $when );
}
/**
* After Filter
*
* set an aspect function to trigger after another function
*
* @access public
* @param string $name
* @param string $func
* @param string $when
*/
function after_filter( $name, $func, $when = 'after' ) {
aspect_join_functions( $func, $name, $when );
}
/**
* Never
*
* returns false
*
* @access public
* @return boolean false
*/
function never() {
return false;
}
/**
* Always
*
* returns true
*
* @access public
* @return boolean true
*/
function always() {
return true;
}
/**
* model_path
*
* path to data models
*
* @access public
* @return string
*/
function model_path() {
return $GLOBALS['PATH']['models'];
}
/**
* library_path
*
* path to libraries
*
* @access public
* @return string
*/
function library_path() {
return $GLOBALS['PATH']['library'];
}
/**
* dbscript_path
*
* path to library/dbscript
*
* @access public
* @return string
*/
function dbscript_path() {
return $GLOBALS['PATH']['dbscript'];
}
/**
* ignore_errors
*
* returns value of environment variable, if set
*
* @access public
* @return boolean
*/
function ignore_errors() {
global $env;
if ( isset( $env['ignore_errors'] ) && $env['ignore_errors'] )
return true;
return false;
}
/**
* plugin_path
*
* path to data models
*
* @access public
* @return string
*/
function plugin_path() {
return $GLOBALS['PATH']['plugins'];
}
/**
* controller_path
*
* path to controllers
*
* @access public
* @return string
*/
function controller_path() {
return $GLOBALS['PATH']['controllers'];
}
/**
* db_object
*
* get global Database object
*
* @access public
* @return string
*/
function &db_object() {
global $db;
return $db;
}
function &environment() {
global $env;
return $env;
}
function render_blob( $value ) {
$db =& db_object();
if (is_array( $value )) {
$db->large_object_fetch(
$value['t'],
$value['f'],
$value['k'],
$value['i']
);
} else {
$db->large_object_fetch( $value );
}
}
function fetch_blob( $value ) {
$db =& db_object();
if (is_array( $value )) {
$db->large_object_fetch(
$value['t'],
$value['f'],
$value['k'],
$value['i'],
true
);
} else {
$db->large_object_fetch( $value, true );
}
}
/**
* template_exists
*
* find a template during content-negotiation
*
* @access public
* @param Mapper $request
* @param string $extension
* @return boolean
*/
function template_exists( &$request, $extension, $template ) {
#if ($template == 'introspection') print 'ye';
#print "template_exists $template ".$extension."<br>";
$view = $request->get_template_path( $extension, $template );
if ( file_exists( $view ) )
return true;
return false;
}
/**
* Form For
*
* generate a form action string
*
* @access public
* @param string $template
* @todo implement
*/
function form_for( &$resource, &$member, $url ) {
$request =& request_object();
if (is_object($resource)) {
if ( isset( $resource->table )) {
// remote_form_for :entry, @new_entry, :url => entries_url(:project_id => @project.id )
return "<form method=\"post\" >";
}
}
}
/**
* URL For
*
* generate a url from a Route
*
* @access public
* @param array $params
* @param array $altparams
*/
function url_for( $params, $altparams = NULL ) {
$request =& request_object();
print $request->url_for( $params, $altparams );
}
function base_url() {
$request =& request_object();
print $request->base;
}
/**
* Redirect To
*
* redirect the browser via Routes
*
* @access public
* @param string $template
*/
function redirect_to( $param, $altparam = NULL ) {
$request =& request_object();
// check for qooxdoo "POST" and bail before redirect
if (strstr($request->uri,"&method="))
echo "OK";
$request->redirect_to( $param, $altparam );
}
/**
* Render
*
* render template or blob using content-negotiation
*
* @access public
* @param string $template
*/
function render( $param, $value ) {
$db =& db_object();
$response =& response_object();
$request =& request_object();
if ( $param == 'action' && !(strpos($value,".") === false ) ) {
$spleet = split( "\.", $value );
$value = $spleet[0];
$request->set_param( 'client_wants', $spleet[1] );
}
$request->set_param( $param, $value );
$response->render( $request );
exit;
}
/**
* Member Of
*
* check group membership for a Person
*
* @access public
* @param string $template
*/
function member_of( $group ) {
$request =& request_object();
if ( $group == 'everyone' )
return true;
if (!(check_cookie()))
return false;
$db =& db_object();
$Person =& $db->model('Person');
$Group =& $db->model('Group');
$p = $Person->find( get_cookie_user() );
while ( $m = $p->NextChild( 'memberships' )) {
$g = $Group->find( $m->group_id );
if (!$g)
trigger_error( "the Group with id ".$m->group_id." does not exist", E_USER_ERROR );
if ( $g->name == $group )
return true;
}
return false;
}
/**
* Render Partial
*
* render a _template using content-negotiation
*
* @access public
* @param string $template
*/
function render_partial( $template ) {
$request =& request_object();
$response =& response_object();
if (!(strpos($template,".") === false)) {
$spleet = split("\.",$template);
$template = $spleet[0];
$request->set_param( 'client_wants', $spleet[1] );
}
$response->render_partial( $request, $template );
}
/**
* content_for_layout
*
* render a _template using content-negotiation
*
* @access public
* @param string $template
*/
function content_for_layout() {
$request =& request_object();
render_partial( $request->action );
}
function breadcrumbs() {
$request =& request_object();
echo $request->breadcrumbs();
}
/**
* request_object
*
* get global Mapper object
*
* @access public
* @return Mapper
*/
function &request_object() {
global $request;
return $request;
}
function content_types() {
global $env;
$variants = array(
array(
'id' => 'html',
'qs' => 1.000,
'type' => 'text/html',
'encoding' => null,
'charset' => 'iso-8859-1',
'language' => 'en',
'size' => 3000
)
);
if (isset($env['content_types']))
return $env['content_types'];
else
return $variants;
}
/**
* response_object
*
* get global View object
*
* @access public
* @return View
*/
function &response_object() {
global $response;
return $response;
}
/**
* db_include
*
* include a dbscript file
*
* @access public
*/
function db_include( $file ) {
if (is_array($file)) {
foreach($file as $f)
require_once dbscript_path() . $f . ".php";
} else {
require_once dbscript_path() . $file . ".php";
}
}
/**
* lib_include
*
* include a library file
*
* @access public
*/
function lib_include( $file ) {
if (is_array($file)) {
foreach($file as $f)
require_once library_path() . $f . ".php";
} else {
require_once library_path() . $file . ".php";
}
}
function load_plugin( $plugin ) {
if ( file_exists( $GLOBALS['PATH']['plugins'] . $plugin . '.php' ) )
include $GLOBALS['PATH']['plugins'] . $plugin . '.php';
$init = $plugin . "_init";
if ( function_exists( $init ) )
$init();
}
/**
* version
*
* get dbscript version
*
* @access public
* @return string
*/
function version() {
global $version;
return $version;
}
function timestamp() {
return date( "Y-m-d H:i:s", strtotime( "now" ));
}
/**
* magic_quotes_stripslashes_b
*
* @access public
* @param array $a
* @return array $r
*/
function magic_quotes_stripslashes_b($a) { // Back
$r=array();
foreach ($a as $k=>$v) {
if (!is_array($v)) $r[stripslashes($k)] = stripslashes($v);
else $r[stripslashes($k)] = magic_quotes_stripslashes_b($v);
}
return $r;
}
/**
* magic_quotes_stripslashes
*
* @access public
* @param array $a
* @return array $r
*/
function magic_quotes_stripslashes($a) { // Top
$r=array();
foreach ($a as $k=>$v) {
if (!is_array($v)) $r[$k] = stripslashes($v);
else $r[$k] = magic_quotes_stripslashes_b($v);
}
return $r;
}
/**
* magic_quotes_stripquotes_b
*
* @access public
* @param array $a
* @return array $r
*/
function magic_quotes_stripquotes_b($a) { // Back
$r=array();
foreach ($a as $k=>$v) {
if (!is_array($v)) $r[str_replace('\'\'','\'',$k)] = str_replace('\'\'','\'',$v);
else $r[str_replace('\'\'','\'',$k)] = magic_quotes_stripquotes_b($v);
}
return $r;
}
/**
* magic_quotes_stripquotes
*
* @access public
* @param array $a
* @return array $r
*/
function magic_quotes_stripquotes($a) { // Top
$r=array();
foreach ($a as $k=>$v) {
if (!is_array($v)) $r[$k] = str_replace('\'\'','\'',$v);
else $r[$k] = magic_quotes_stripquotes_b($v);
}
return $r;
}
/**
* header_status
*
* @access public
* @param string $status
*/
function header_status( $status, $http = false ) {
if ( !$http || substr( php_sapi_name(), 0, 3 ) == 'cgi' )
header( 'Status: ' . $status, TRUE );
else
header( $_SERVER['SERVER_PROTOCOL'] .' '. $status );
}
/**
* set_cookie
*
* bake a fresh Cookie
*
* @access public
* @param integer $userid
*/
function set_cookie($userid) {
$cookie = new Cookie();
$cookie->userid = $userid;
$cookie->set();
}
/**
* unset_cookie
*
* throw the Cookie away? noo..
*
* @access public
*/
function unset_cookie() {
$cookie = new Cookie();
$cookie->logout();
}
/**
* check_cookie
*
* is the Cookie fit for consumption?
*
* @access public
* @return boolean
*/
function check_cookie() {
$cookie = new Cookie();
if ($cookie->validate()) {
return true;
} else {
return false;
}
}
/**
* get_cookie_user
*
* get the person_id of the cookie owner
*
* @access public
* @return integer
*/
function get_cookie_user() {
$cookie = new Cookie();
if ($cookie->userid)
return $cookie->userid;
return 0;
}
/**
* Vars
*
* mutator function makes an array of local variables extractable
*
* @access public
* @param string $var
* @return string
*/
function vars($varios, $scope=false, $prefix='unique', $suffix='value') {
if ( $scope )
$vals = $scope;
else
$vals = $GLOBALS;
$i = 0;
foreach ($varios as $orig) {
$var =& $varios[$i];
$old = $var;
$var = $new = $prefix . rand() . $suffix;
$vname = FALSE;
foreach( $vals as $key => $val ) {
if ( $val === $new ) $vname = $key;
}
$var = $old;
if ($vname) {
$varios[$vname] = $var;
}
$i++;
}
return $varios;
}
/**
* Randomstring
*
* give it a string length and you will receive a random string!
*
* @access public
* @param integer $len
* @return string
*/
function randomstring($len) {
srand(date("s"));
$i = 0;
$str = "";
while($i<$len)
{
$str.=chr((rand()%26)+97);
$i++;
}
return $str;
}
function getEtag($id) {
return "ci-".dechex(crc32($id.microtime()));
}
/**
* drop_array_element
*
* returns the array minus the named element
*
* @access public
* @param string $str
*/
function drop_array_element($array_with_elements, $key_name) {
$key_index = array_keys(array_keys($array_with_elements), $key_name);
if (count($key_index) != '') {
array_splice($array_with_elements, $key_index[0], 1);
}
return $array_with_elements;
}
/**
* dictionary_parse
*
* Parses an xml dictionary.
* First argument is file name OR xml data.
* Second argument must be 'true' if the first arg is file name.
*
* <code>
* $array = dictionary_parse( $file_name, true );
* </code>
*
* @author Brian Hendrickson <hide@address.com>
* @access public
* @param string $data
* @return array
*/
function dictionary_parse( $data ) { /* parse XML dictionaries (lookup tables) */
$dict = array();
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1);
xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 0);
if (!$xml_parser) {
trigger_error("error creating xml parser (xml_parser_create) in dictionary_parse", E_USER_ERROR );
}
$func_args = func_get_args();
if (count($func_args) > 1) {
if ($func_args[1] == true) {
$data = file_get_contents($data);
if (!$data) {
trigger_error("error reading file contents in dictionary_parse, file name was: ".$func_args[0], E_USER_ERROR );
}
}
}
$int = xml_parse_into_struct($xml_parser, $data, $values, $tags);
if (!($int > 0)) {
trigger_error("error parsing XML in dictionary_parse: ".xml_error_string(xml_get_error_code($xml_parser)), E_USER_ERROR )." ". $data;
}
foreach ($tags as $tagname=>$valuelocations) {
if ($tagname == "KEY") {
$i = 0;
foreach ($valuelocations as $valkey=>$valloc) {
$map[$i] = $values[$valloc]['value'];
$dict[$values[$valloc]['value']] = "";
$i++;
}
}
if ($tagname == "STRING") {
$i = 0;
foreach ($valuelocations as $valkey=>$valloc) {
if (isset($values[$valloc]['value'])) {
$dict[$map[$i]] = $values[$valloc]['value'];
} else {
$dict[$map[$i]] = "";
}
$i++;
}
}
}
xml_parser_free($xml_parser);
return $dict;
}
/**
* in_string
*
* search for a substring
*
* @access public
* @param string $needle
* @param array $haystack
* @param integer $insensitive
* @return boolean
*/
function in_string($needle, $haystack, $insensitive = 0) {
if ($insensitive) {
return (false !== stristr($haystack, $needle)) ? true : false;
} else {
return (false !== strpos($haystack, $needle)) ? true : false;
}
}
/**
* get_script_name
*
* the name of the current script
*
* @access public
* @return string
*/
function get_script_name() {
if (!empty($_SERVER['PHP_SELF'])) {
$strScript = $_SERVER['PHP_SELF'];
} else if (!empty($_SERVER['SCRIPT_NAME'])) {
$strScript = @$_SERVER['SCRIPT_NAME'];
} else {
trigger_error("error reading script name in get_script_name", E_USER_ERROR );
}
$intLastSlash = strrpos($strScript, "/");
if (strrpos($strScript, "\\")>$intLastSlash) {
$intLastSlash = strrpos($strScript, "\\");
}
return substr($strScript, $intLastSlash+1, strlen($strScript));
}
function dircopy($srcdir, $dstdir, $verbose = false) {
$num = 0;
if(!is_dir($dstdir)) mkdir($dstdir);
if($curdir = opendir($srcdir)) {
while($file = readdir($curdir)) {
if($file != '.' && $file != '..') {
$srcfile = $srcdir . DIRECTORY_SEPARATOR . $file;
$dstfile = $dstdir . DIRECTORY_SEPARATOR . $file;
if(is_file($srcfile)) {
if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1;
if($ow > 0) {
if($verbose) echo "Copying '$srcfile' to '$dstfile'...";
if(copy($srcfile, $dstfile)) {
touch($dstfile, filemtime($srcfile)); $num++;
if($verbose) echo "OK\n";
}
else echo "Error: File '$srcfile' could not be copied!\n";
}
}
else if(is_dir($srcfile)) {
$num += dircopy($srcfile, $dstfile, $verbose);
}
}
}
closedir($curdir);
}
return $num;
}
/**
* is_obj
*
* more flexible is_object
*
* @access public
* @param object $object
* @param boolean $check
* @param boolean $strict
* @return boolean
*/
function is_obj( &$object, $check=null, $strict=true ) {
if (is_object($object)) {
if ($check == null) {
return true;
} else {
$object_name = get_class($object);
return ($strict === true)?
( $object_name == $check ):
( strtolower($object_name) == strtolower($check) );
}
} else {
return false;
}
}
?>