Location: PHPKode > projects > MicroMVC PHP Framework > required/classes.php
<?php defined('SYSTEM_PATH') or die('No direct access');
/**
 * Load, Config, Lang, & Hook Classes
 *
 * These are the basic system classes need on every page. Do not change.
 *
 * @package		MicroMVC
 * @author		David Pennington
 * @copyright	(c) 2010 MicroMVC Framework
 * @license		http://micromvc.com/license
 ********************************** 80 Columns *********************************
 */

/**
 * Load Class
 *
 * Loads classes and keeps track of object instances to achieve singleton design
 */
class load {

	// Array of files and their locations
	public static $files = array();

	// Have any new files been loaded this request?
	public static $changed = FALSE;

	// Array of object instances
	public static $objects = array();

	// The locations to look for files
	public static $paths = array(SITE_PATH);

	/**
	 * On startup, set the modules loaded and load the files cache if enabled.
	 * 
	 * @param $modules the array of modules
	 */
	public static function init(array $modules)
	{
		// If we are also loading files from modules
		if($modules)
		{
			foreach($modules as $module)
			{
				self::$paths[] = MODULE_PATH. $module. DS;
			}
		}

		if($data = cache::get('load::init'))
		{
			// If the paths have NOT changed since last load
			if($data[1] == self::$paths)
			{
				self::$files = $data[0];
			}
		}
	}


	/**
	 * Auto-called when a class needs to be loaded
	 * 
	 * @param string $class the name of the class to load
	 * @return boolean
	 */
	public static function autoload($class)
	{
		$file = strtolower(str_replace('_', DS, $class));

		// If this class is found
		if($path = self::find_file($file))
		{
			return require_once($path);
		}
	}


	/**
	 * Returns the full system path of the file requested
	 *
	 * @param $file
	 * @param $dir
	 * @param $ext
	 * @return	string
	 */
	public static function find_file($file, $dir = 'classes', $ext = 'php')
	{

		$file .= '.'.$ext;

		// If we already know where this file is
		if(isset(self::$files[$dir.$file]))
		{
			return self::$files[$dir.$file];
		}

		// Look under each path
		foreach(self::$paths as $path)
		{
			// Build the path
			$path .= $dir. DS;

			// Look for this file
			if(is_file($path. $file))
			{
				self::$changed = TRUE;
				return self::$files[$dir.$file] = $path. $file;
			}
		}

		return FALSE;
	}


	/**
	 * Load a class, create and store an instance of the object, and return the object.
	 *
	 * @param $class the name of the class to load (may also contain paths)
	 * @param $path the absolute path to load the class from
	 * @param $params the arguments to give to the object constructor
	 * @param $instantiate if false then only load file and don't create object
	 * @return object
	 */
	public static function singleton($class = NULL, $params = NULL, $instantiate = TRUE)
	{
		// Class case doesn't matter
		$class = strtolower($class);

		// If this class is already loaded
		if( ! empty(self::$objects[$class]))
		{
			return self::$objects[$class];
		}

		// If we just want to load the file - nothing more
		if ($instantiate === FALSE)
		{
			self::autoload($class);
			return TRUE;
		}

		return self::$objects[$class] = new $class($params);
	}


	/**
	 * Remove a loaded object by class name
	 * 
	 * @param string $class the name of the class
	 */
	public static function remove($class = NULL)
	{
		// Remove object (case doesn't matter)
		unset(self::$objects[strtolower($class)]);
	}
	
	
	/**
	 * Load a helper function file
	 *
	 * @param $name the name of the function file to load
	 * @return boolean
	 */
	public static function helper($name = NULL)
	{
		// Look for the helper file
		$path = self::find_file($name, 'helpers');

		// Try to load the file
		return require_once($path);
	}


	/**
	 * Load an error page
	 *
	 * @param string|array $message error message OR array of view data
	 * @param string $title the optional title
	 * @param int $header the HTTP status code to send
	 * @return string
	 */
	public static function error($message = NULL, $title = NULL, $header = 500)
	{
		// Get HTTP status
		if( ! $status = http_response_status( (int) $header))
		{
			// If failure - default to "Internal Server Error"
			$status = http_response_status($header = 500);
		}

		// Try to send an error header
		if( ! headers_sent())
		{
			// Send the header
			header('HTTP/1.0 '. $header. ' '. $status);
		}

		if( ! is_array($message))
		{
			// If a message is not given - try to find a matching HTTP status message
			$message = ($message ? $message : lang($header));
			
			// If a title is not given - use the HTTP status message
			$title = ($title ? $title : $status);
	
			// Build view data
			$message = array('message' => $message, 'title' => $title);
		}
		
		// Load error page
		return self::view('errors/error', $message);
	}


	/**
	 * This function is used to load views files.
	 *
	 * @access	private
	 * @param	String	file path/name
	 * @param	array	values to pass to the view
	 * @param	boolean	return the output or print it?
	 * @return	void
	 */
	public static function view($__file = NULL, $__variables = NULL, $__return = TRUE)
	{
		// Fetch the path to the view file
		if( ! $__path = self::find_file($__file, 'views'))
		{
			throw new Exception($__file. ' view not found');
		}

		if(is_array($__variables))
		{
			// Make each value passed to this view available for use
			foreach($__variables as $__key => $__variable)
			{
				$$__key = $__variable;
			}
		}

		// Delete them now
		$__variables = null;

		// We just want to print to the screen
		if( ! $__return)
		{
			return include($__path);
		}

		// Buffer the output so we can save it to a string
		ob_start();

		// include() vs include_once() allows for multiple views with the same name
		include($__path);

		// Get the output
		$__buffer = ob_get_contents();
		ob_end_clean();
		
		return $__buffer;
	}


	/**
	 * Assigns a copy of all the objects loaded into the object given
	 *
	 * @param $object the object to load a copy of the objects into
	 */
	public static function objects_into($object = NULL)
	{
		foreach(self::$objects as $class => $obj)
		{
			if(isset($object->$class)) { continue; }
			$object->$class = $obj;
		}
	}

	
	/**
	 * Record the updated files array if caching is enabled.
	 */
	public static function shutdown()
	{
		if(self::$changed)
		{
			cache::set('load::init', array(self::$files, self::$paths));
		}
	}

}



/**
 * Config Class
 *
 * Loads and manages config settings for the current page request.
 */
class config {

	public static $config = array();

	/**
	 * Get the value of a config group key, loading it if needed.
	 *
	 * @param string $key the name of the config value to fetch
	 * @param string $group the name of the group to find the $key in
	 * @return mixed
	 */
	public static function get($key = NULL, $group = 'config')
	{
		// Load the config if needed
		if( empty(self::$config[$group]))
		{
			self::load($group);
		}

		// Return the key or the whole group config
		return ( $key === NULL ? self::$config[$group] : self::$config[$group][$key] );
	}


	/**
	 * Set the value of a config group key, loading it if needed
	 *
	 * @param string $key the name of the config value to fetch
	 * @param string $group the name of the group to find the $key in
	 * @param mixed $value the new value to set the $key to
	 */
	public static function set($key = NULL, $group = 'config', $value = NULL)
	{

		// Load the config if needed
		if( empty(self::$config[$group]))
		{
			self::load($group);
		}

		// Set the config key to the new value
		if($key !== NULL)
		{
			self::$config[$group][$key] = $value;
		}
		else
		{
			self::$config[$group] = $value;
		}

	}


	/**
	 * Load and store a config file
	 *
	 * @param string $group the name of the config file
	 * @param bool $overwrite if true, overwrite current values if set
	 */
	public static function load($group, $overwrite = FALSE)
	{

		// If the config is already loaded
		if( ! $overwrite AND isset(self::$config[$group]))
		{
			return;
		}

		if( ! $path = load::find_file($group, 'config'))
		{
			throw new Exception($group. ' config file not found');
		}

		// Include the config
		require($path);

		// Save the config
		self::$config[$group] = $config;

	}

	
	/**
	 * Remove the loaded config for a given group.
	 * This helps to free memory.
	 * 
	 * @param string $group the config group to remove
	 */
	public static function clear($group = NULL)
	{
		unset(self::$config[$group]);
	}
}



/**
 * Lang Class
 *
 * Loads and manages language strings for the current page request.
 */
class lang {

	public static $lang = array();
	public static $language = FALSE;

	/**
	 * Get the value of a lang group key, loading it if needed.
	 *
	 * @param string $line the name of the lang value to fetch
	 * @param string $group the name of the group to find the $line in
	 * @return mixed
	 */
	public static function get($line = NULL, $group = 'system')
	{

		// Load the lang if needed
		if(empty(self::$lang[$group]))
		{
			self::load($group);
		}

		// Return the key or the whole group lang
		return ($line === NULL ? self::$lang[$group] : self::$lang[$group][$line]);
	}


	/**
	 * Set the value of a lang group key, loading it if needed
	 *
	 * @param string $line the name of the lang value to fetch
	 * @param string $group the name of the group to find the $line in
	 * @param mixed $value the new value to set the $line to
	 */
	public static function set($line = NULL, $group = 'system', $value = NULL)
	{
		// Load the lang if needed
		if( empty(self::$lang[$group]))
		{
			self::load($group);
		}

		// Set the lang key to the new value
		if( $line !== NULL )
		{
			self::$lang[$group][$line] = $value;
		}
		else
		{
			self::$lang[$group] = $value;
		}
	}


	/**
	 * Load and store a lang file
	 *
	 * @param string $group the name of the lang file
	 * @param bool $overwrite if true, overwrite current values if set
	 */
	public static function load($group = 'system', $overwrite = FALSE)
	{

		// If the lang is already loaded
		if( ! $overwrite AND isset(self::$lang[$group]) )
		{
			return;
		}

		if( ! $path = load::find_file(config::get('language').'/'.$group, 'lang'))
		{
			throw new Exception($group.' language file not found');
		}

		// Include the lang
		require($path);

		// Save the lang
		self::$lang[$group] = $lang;

	}
	
	
	/**
	 * Remove the loaded lang for a given group.
	 * This helps to free memory.
	 * 
	 * @param string $group the lang group to remove
	 */
	public static function clear($group = NULL)
	{
		unset(self::$lang[$group]);
	}
}



/*
 * Hook Class
 *
 * Provides plugin points for classes and functions to run and/or filter data.
 */
class hook {

	// Keeps us out of trouble with repeating hook loops
	public static $hook_in_progress = FALSE;
	// Array of hooks
	public static $hooks = array();

	/**
	 * Calls a particular hook allowing data to be
	 * filtered by the hook(s) and the result returned.
	 *
	 * @param string $name the hook name
	 * @param mixed $data the data to be parsed
	 * @return mixed
	 */
	public static function call($name = '', $data = NULL)
	{

		// If no hook is given OR found with that name
		if ( ! $name OR empty(self::$hooks[$name]))
		{
			return $data;
		}

		// Run each hook and filter the data
		foreach (self::$hooks[$name] as $val)
		{
			$data = self::run_hook($val, $data);
		}

		return $data;
	}


	/**
	 * Verify whether a hook exists - returning the array index if found
	 *
	 * @param string $name the hook name
	 * @param string $hook the function to look for
	 * @return bool
	 */
	public static function exists($name = '', $hook = NULL)
	{

		// If invaild data was given - or a hook by this name is not found
		if( ! $name OR ! is_array($hook) OR empty(self::$hooks[$name]))
		{
			return FALSE;
		}

		// Return array index or FALSE
		return array_search($hook, self::$hooks[$name]);
	}


	/**
	 * Remove the given function (or all) from the given hook trigger
	 * and return TRUE if that hook was found or FALSE if not
	 *
	 * @param string $name the hook name
	 * @param string $hook the function to remove
	 * @return boolean
	 */
	public function remove($name = '', $hook = NULL)
	{

		// If we are to remove all hooks for this trigger
		if( ! $function)
		{
			self::$hooks[$name] = array();
			return TRUE;
		}

		// Find and remove this particular hook
		if($key = self::exists($name, $hook))
		{
			unset(self::$hooks[$name][$key]);
			return TRUE;
		}

		return FALSE;
	}


	/**
	 * Add a hook to the list for the given hook trigger
	 *
	 * @param string $name the hook name
	 * @param array $hook the new hook array
	 * @return boolean
	 */
	public static function add($name = '', $hook = NULL)
	{
		// If invaild data was given
		if( ! $name OR ! is_array($hook))
			return FALSE;

		// If this hook already has been added
		if( self::exists($name, $hook))
			return TRUE;

		// Add the hook
		self::$hooks[$name][] = $hook;

		return TRUE;
	}


	/**
	 * Runs the given hook
	 *
	 * @param array $hook the hook details
	 * @param mixed $data the optional data to be filtered
	 * @return bool
	 */
	public static function run_hook($hook = NULL, $data = NULL)
	{

		// If it is NOT a hook config
		if ( ! is_array($hook) OR empty($hook))
			return $data;

		/*
		 * Safety - Prevents run-away loops
		 *
		 * If the script being called happens to have the same
		 * hook call within it a loop can happen.
		 */
		if (self::$hook_in_progress == TRUE)
			return $data;

		// Set each value to avoid php notices
		foreach(array('class', 'function', 'helper', 'static') as $type)
		{
			$$type = empty($hook[$type]) ? NULL : $hook[$type];
		}

		// If we are missing a lot of stuff...
		if ( ! $class AND ! $function)
		{
			trigger_error(lang::get('hooks_no_function'));
			return $data;
		}

		// If a function is being called we HAVE TO HAVE a file name!
		if ( ! $class AND ( ! $helper AND $function))
		{
			trigger_error(sprintf(lang::get('hooks_no_file'), $function));
			return $data;
		}

		// Set the in_progress flag
		self::$hook_in_progress = TRUE;

		// Call the class method
		if($class)
		{
				
			// If we should call the object statically
			if($static)
			{
				$data = call_user_func(array($class, $function), $data);
			}
			else
			{
				// If not already an object (i.e. not added at runtime)
				if( ! is_object($class))
				{
					$class = load::singleton($class);
				}

				// Run the function
				$data = $class->$function($data);
			}
				
		}
		else //Else just run the function
		{

			// If the function does not alreay exist
			if ( ! function_exists($function))
			{
				load::helper($helper);
			}

			$data = $function($data);
		}

		self::$hook_in_progress = FALSE;
		return $data;
	}

}

Return current item: MicroMVC PHP Framework