Root/
<?php /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* # ***** BEGIN LICENSE BLOCK ***** # This file is part of Plume Framework, a simple PHP Application Framework. # Copyright (C) 2001-2007 Loic d'Anterroches and contributors. # # Plume Framework is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Plume Framework is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # ***** END LICENSE BLOCK ***** */ /** * The main class of the framework. From where all start. * * The __autoload function is automatically set. */ class Pluf { /** * Start the Plume Framework. * * Load the configuration files. * * @param string Configuration file to use */ static function start( $config ) { $GLOBALS [ '_PX_starttime' ] = microtime(true); $GLOBALS [ '_PX_uniqid' ] = uniqid( $GLOBALS [ '_PX_starttime' ], true); $GLOBALS [ '_PX_signal' ] = array (); $GLOBALS [ '_PX_locale' ] = array (); Pluf::loadConfig( $config ); date_default_timezone_set(Pluf::f( 'time_zone' , 'Europe/Berlin' )); mb_internal_encoding(Pluf::f( 'encoding' , 'UTF-8' )); mb_regex_encoding(Pluf::f( 'encoding' , 'UTF-8' )); } /** * Load the given configuration file. * * The configuration is saved in the $GLOBALS['_PX_config'] array. * The relations between the models are loaded in $GLOBALS['_PX_models']. * * @param string Configuration file to load. */ static function loadConfig( $config_file ) { if (false !== ( $file =Pluf::fileExists( $config_file ))) { $GLOBALS [ '_PX_config' ] = require $file ; } else { throw new Exception( 'Configuration file does not exist: ' . $config_file ); } // Load the relations for each installed application. Each // application folder must be in the include path. self::loadRelations(!Pluf::f( 'debug' , false)); } /** * Get the model relations and signals. * * If not in debug mode, it will automatically cache the * information. This allows one include file when many * applications and thus many includes are needed. * * Signals and relations are cached in the same file as the way to * go for signals is to put them in the relations.php file. * * @param bool Use the cache (true) */ static function loadRelations( $usecache =true) { $GLOBALS [ '_PX_models' ] = array (); $GLOBALS [ '_PX_models_init_cache' ] = array (); $apps = Pluf::f( 'installed_apps' , array ()); $cache = Pluf::f( 'tmp_folder' ). '/Pluf_relations_cache_' .md5(serialize( $apps )). '.phps' ; if ( $usecache and file_exists ( $cache )) { list( $GLOBALS [ '_PX_models' ], $GLOBALS [ '_PX_models_related' ], $GLOBALS [ '_PX_signal' ]) = include $cache ; return ; } $m = $GLOBALS [ '_PX_models' ]; foreach ( $apps as $app ) { $m = array_merge_recursive ( $m , require $app . '/relations.php' ); } $GLOBALS [ '_PX_models' ] = $m ; $_r = array ( 'relate_to' => array (), 'relate_to_many' => array (), ); foreach ( $GLOBALS [ '_PX_models' ] as $model => $relations ) { foreach ( $relations as $type => $related ) { foreach ( $related as $related_model ) { if (!isset( $_r [ $type ][ $related_model ])) { $_r [ $type ][ $related_model ] = array (); } $_r [ $type ][ $related_model ][] = $model ; } } } $_r [ 'foreignkey' ] = $_r [ 'relate_to' ]; $_r [ 'manytomany' ] = $_r [ 'relate_to_many' ]; $GLOBALS [ '_PX_models_related' ] = $_r ; // $GLOBALS['_PX_signal'] is automatically set by the require // statement and possibly in the configuration file. if ( $usecache ) { $s = var_export( array ( $GLOBALS [ '_PX_models' ], $GLOBALS [ '_PX_models_related' ], $GLOBALS [ '_PX_signal' ]), true); if (@ file_put_contents ( $cache , '<?php return ' . $s . ';' . "\n" , LOCK_EX)) { chmod ( $cache , 0755); } } } /** * Access a configuration variable. * * @param string Configuration variable * @param mixed Possible default value if value is not set ('') * @return mixed Configuration variable or default value if not defined. */ static function f( $cfg , $default = '' ) { if (isset( $GLOBALS [ '_PX_config' ][ $cfg ])) { return $GLOBALS [ '_PX_config' ][ $cfg ]; } return $default ; } /** * Access an array of configuration variables having a given * prefix. * * @param string Prefix. * @param bool Strip the prefix from the keys (false). * @return array Configuration variables. */ static function pf( $pfx , $strip =false) { $ret = array (); $pfx_len = strlen ( $pfx ); foreach ( $GLOBALS [ '_PX_config' ] as $key => $val ) { if (0 === strpos ( $key , $pfx )) { if (! $strip ) { $ret [ $key ] = $val ; } else { $ret [ substr ( $key , $pfx_len )] = $val ; } } } return $ret ; } /** * Returns a given object. * * Loads automatically the corresponding class file if needed. * If impossible to get the class $model, exception is thrown. * * @param string Model to load. * @param mixed Extra parameters for the constructor of the model. */ public static function factory( $model , $params =null) { if ( $params !== null) { return new $model ( $params ); } return new $model (); } /** * Load a class depending on its name. * * Throw an exception if not possible to load the class. * * @param string Class to load. */ public static function loadClass( $class ) { if ( class_exists ( $class , false)) { return ; } $file = str_replace ( '_' , DIRECTORY_SEPARATOR, $class ) . '.php' ; include $file ; if (! class_exists ( $class , false)) { $error = 'Impossible to load the class: ' . $class . "\n" . 'Tried to include: ' . $file . "\n" . 'Include path: ' .get_include_path(); throw new Exception( $error ); } } /** * Load a function depending on its name. * * The implementation file of the function * MyApp_Youpla_Boum_Stuff() is MyApp/Youpla/Boum.php That way it * is possible to group all the related function in one file. * * Throw an exception if not possible to load the function. * * @param string Function to load. */ public static function loadFunction( $function ) { if (function_exists( $function )) { return ; } $elts = explode ( '_' , $function ); array_pop ( $elts ); $file = implode(DIRECTORY_SEPARATOR, $elts ) . '.php' ; if (false !== ( $file =Pluf::fileExists( $file ))) { include $file ; } if (!function_exists( $function )) { throw new Exception( 'Impossible to load the function: ' . $function ); } } /** * Hack for [[php file_exists()]] that checks the include_path. * * Use this to see if a file exists anywhere in the include_path. * * <code type="php"> * $file = 'path/to/file.php'; * if (Pluf::fileExists('path/to/file.php')) { * include $file; * } * </code> * * @credits Paul M. Jones <pmjones@solarphp.net> * * @param string $file Check for this file in the include_path. * @return mixed Full path to the file if the file exists and * is readable in the include_path, false if not. */ public static function fileExists( $file ) { $file = trim( $file ); if (! $file ) { return false; } // using an absolute path for the file? // dual check for Unix '/' and Windows '\', // or Windows drive letter and a ':'. $abs = ( $file [0] == '/' || $file [0] == '\\' || $file [1] == ':' ); if ( $abs && file_exists ( $file )) { return $file ; } // using a relative path on the file $path = explode (PATH_SEPARATOR, ini_get ( 'include_path' )); foreach ( $path as $dir ) { // strip Unix '/' and Windows '\' $target = rtrim( $dir , '\\/' ).DIRECTORY_SEPARATOR. $file ; if ( file_exists ( $target )) { return $target ; } } // never found it return false; } /** * Helper to load the default database connection. * * This method is just dispatching to the function define in the * configuration by the 'db_get_connection' key or use the default * 'Pluf_DB_getConnection'. If you want to use your own function, * take a look at the Pluf_DB_getConnection function to use the * same approach for your method. * * The extra parameters can be used to selectively connect to a * given database. When the ORM is getting a connection, it is * passing the current model as parameter. That way you could get * different databases for different models. * * @param mixed Extra parameters. * @return resource DB connection. */ public static function &db( $extra =null) { $func = Pluf::f( 'db_get_connection' , 'Pluf_DB_getConnection' ); Pluf::loadFunction( $func ); $a = $func ( $extra ); return $a ; } } /** * Translate a string. * * @param string String to be translated. * @return string Translated string. */ function __( $str ) { $locale = (isset( $GLOBALS [ '_PX_current_locale' ])) ? $GLOBALS [ '_PX_current_locale' ] : 'en' ; if (! empty ( $GLOBALS [ '_PX_locale' ][ $locale ][ $str ][0])) { return $GLOBALS [ '_PX_locale' ][ $locale ][ $str ][0]; } return $str ; } /** * Translate the plural form of a string. * * @param string Singular form of the string. * @param string Plural form of the string. * @param int Number of elements. * @return string Translated string. */ function _n( $sing , $plur , $n ) { $locale = (isset( $GLOBALS [ '_PX_current_locale' ])) ? $GLOBALS [ '_PX_current_locale' ] : 'en' ; if (isset( $GLOBALS [ '_PX_current_locale_plural_form' ])) { $pform = $GLOBALS [ '_PX_current_locale_plural_form' ]; } else { $pform = Pluf_Translation::getPluralForm( $locale ); } $index = Pluf_Translation:: $pform ( $n ); if (! empty ( $GLOBALS [ '_PX_locale' ][ $locale ][ $sing . '#' . $plur ][ $index ])) { return $GLOBALS [ '_PX_locale' ][ $locale ][ $sing . '#' . $plur ][ $index ]; } // We have no translations or default English if ( $n == 1) { return $sing ; } return $plur ; } /** * Autoload function. * * @param string Class name. */ function __autoload( $class_name ) { try { Pluf::loadClass( $class_name ); } catch (Exception $e ) { if (Pluf::f( 'debug' )) { print $e ->getMessage(); die (); } eval (" class $class_name { function __construct() { throw new Exception( 'Class $class_name not found' ); } static function __callstatic(\ $m , \ $args ) { throw new Exception( 'Class $class_name not found' ); } }"); } } /** * Exception to catch the PHP errors. * * @credits errd */ class PlufErrorHandlerException extends Exception { public function setLine( $line ) { $this ->line = $line ; } public function setFile( $file ) { $this ->file = $file ; } } /** * The function that is the real error handler. */ function PlufErrorHandler( $code , $string , $file , $line ) { if (0 == error_reporting ()) return ; if (E_STRICT == $code && ( 0 === strpos ( $file , Pluf::f( 'pear_path' , '/usr/share/php/' )) or false !== strripos ( $file , 'pear' ) // if pear in the path, ignore ) ) { return ; } $exception = new PlufErrorHandlerException( $string , $code ); $exception ->setLine( $line ); $exception ->setFile( $file ); throw $exception ; } // Set the error handler only if not performing the unittests. if (!defined( 'IN_UNIT_TESTS' )) { set_error_handler( 'PlufErrorHandler' , error_reporting ()); } /** * Shortcut needed all over the place. * * Note that in some cases, we need to escape strings not in UTF-8, so * this is not possible to safely use a call to htmlspecialchars. This * is why str_replace is used. * * @param string Raw string * @return string HTML escaped string */ function Pluf_esc( $string ) { return str_replace ( array ( '&' , '"' , '<' , '>' ), array ( '&' , '"' , '<' , '>' ), (string) $string ); } |