User:Woozle/libmgr.php

About
There's probably a better way of doing this -- perhaps even just a systematic way of using the existing PHP code-loading functions. I have to rethink it at some point.

The basic idea is that an included file (X) which needs to include other files (Y) might have an idea of where those files are, but the callers might want to override the locations of Y before X tries to load them.

Code
<?php /* FILE: libmgr.php PURPOSE: class for managing library loading HISTORY: 2009-07-05 Trying to make this usable: shortened method names, added Path, AddLog 2009-10-06 IsLoaded 2010-10-06 Log shows if update is not a change 2011-09-15 Add now has a "force" parameter to override an existing entry. By default, it does not replace existing entries. 2012-04-18 class autoload registration 2013-01-02 substantially rewritten - new clsModule class interface; clsLibMgr deprecated

define('LIBMGR',1); define('LIBMGR_VER','2013-01-02');

spl_autoload_register(__NAMESPACE__ .'\clsLibMgr::LoadClass');	// is this working?

class clsModule { private static $arMods;

private $strName;	// name by which to refer to module private $fsModule;	// filespec to loadable module private $fsCaller;	// filespec of caller private $intCaller;	// line number where called (in caller) private $isLoaded;	// TRUE = this module has already been loaded (included)

/*     USAGE: new clsLibModule(__FILE__, __LINE__,, ); */   public function __construct($iCallerSpec, $iLine, $iName, $iModuleSpec=NULL) { if (self::Exists($iName)) { // return existing module if it already exists return self::ByName($iName); } else { $this->strName = $iName; $this->fsModule = $iModuleSpec; $this->fsCaller = $iCallerSpec; $this->intCaller = $iLine; $this->isLoaded = FALSE;

self::Register($this); }   }    public function Key { return $this->strName; }   public function Path { return $this->fsModule; }   /*      NOTES: * We want to prevent modules from being loaded more than once, but this is not an error if it happens. Multiple plugins or independent libraries may be dependent on the same module. */   protected function Load { $fsMod = $this->Path; //		$fsModule = self::$vList[$iName]; //		self::AddLog('Loading '.$iName.' as ['.$fsModule.']'); $ok = FALSE; try { if (file_exists($fsMod)) { if (!$this->isLoaded) { require_once $fsMod; }		$ok = TRUE; } else { $strName = $this->Key; $fsCaller = $this->fsCaller; $intCaller = $this->intCaller; echo "Module $strName could not be loaded because source file $fsMod, set in $fsCaller line $intCaller, is not found."; }	} catch(Exception $e) { echo "LibMgr could not load module [$iName] from [$fsModule]; error: ".$e->getMessage.'';

throw new exception('Module file could not be loaded.'); }	return $ok; }   /*      USAGE: Should only be called internally to register new classes */   protected static function Register(clsModule $iModule) { if (!isset(self::$arMods)) { // static stuff has not been initialized yet, so do it now. self::$arMods = array; }	self::$arMods[$iModule->Key] = $iModule; }   /*      ASSUMES: static stuff has been initialized, i.e. Register has been called at least once */   protected static function Exists($iName) { if (isset(self::$arMods)) { return array_key_exists($iName,self::$arMods); } else { return FALSE; }   }    /*      ASSUMES: static stuff has been initialized, i.e. Register has been called at least once USED BY: clsLibMgr::Path */   public static function ByName($iName) { if (self::Exists($iName)) { return self::$arMods[$iName]; } else { return NULL; }   }    public static function Load_byName($iName,$iFile,$iLine) { $ok = FALSE; if (self::Exists($iName)) { $objMod = self::ByName($iName); $ok = $objMod->Load; } else { echo "Attempting to load undefined module $iName from $iFile line $iLine."; }	return $ok; } }

class clsLibMgr { //   private static $vList; private static $vLoaded; private static $arClasses; //   public static $Log;

/*   public static function Init { self::AddLog(__FILE__); }   // This is the OLD method of adding modules public static function Add($iName,$iSpec,$iFile,$iLine,$iForce=FALSE) { $objMod = new clsModule($iFile,$iLine,$iName,$iSpec);

/*	$doChg = TRUE; if (isset(self::$vList[$iName])) { $fsCur = self::$vList[$iName]; if ($fsCur == $iSpec) { self::AddLog('Updating '.$iName.' from ['.$fsCur.']: no change'); } else { if ($iForce) { self::AddLog('Changing '.$iName.' from ['.$fsCur.'] to ['.$iSpec.']'); } else { $doChg = FALSE; self::AddLog('Not changing '.$iName.', currently ['.$fsCur.']; discarding ['.$iSpec.']'); }	   }	} else { self::AddLog('Adding '.$iName.' as ['.$iSpec.']'); }	self::AddLog(' -- from '.$iFile); if ($doChg) { self::$vList[$iName] = $iSpec; }   }    public static function AddClass($iClass, $iModule) { self::$arClasses[$iClass] = $iModule; }   public static function LoadClass($iClass) { if (ArrayHas(self::$arClasses,$iClass)) { $strMod = self::$arClasses[$iClass]; self::Load($strMod,__FILE__,__LINE__); } else { //	   echo ' CLASS ['.$iClass.'] has not been registered. '; //	   throw new exception('Unregistered class requested.'); }   }    /*      NOTES: Duplicate loads are inevitable across different plug-ins, so don't bother showing an error when this happens. */   public static function Load($iName,$iFile,$iLine) { $ok = clsModule::Load_byName($iName,$iFile,$iLine); if ($ok) { self::$vLoaded[$iName] = TRUE; }	return $ok; /* //	if (ArrayHas(self::$vList,$iName)) { if (clsModule::Exists($iName)) { if (self::IsLoaded($iName)) { echo "Duplicate load of $iName in $iFile line $iLine. " //		self::AddLog('Duplicate load of '.$iName.''); } else { $objMod = clsModule::byName($iName); $fsModule = $objMod->Path; //		$fsModule = self::$vList[$iName]; //		self::AddLog('Loading '.$iName.' as ['.$fsModule.']'); try { if (file_exists($fsModule)) { require_once $fsModule; } else { echo "File $fsModule not found for module $iName."; }		} catch(Exception $e) { echo "LibMgr could not load module [$iName] from [$fsModule]; error: ".$e->getMessage.'';

throw new exception('Module file could not be loaded.'); }		self::$vLoaded[$iName] = TRUE; }	} else { echo 'UNKNOWN LIBRARY '.$iName.' REQUESTED by '.$iFile.' line '.$iLine; }   }

protected static function IsLoaded($iName) { if (ArrayHas(self::$vLoaded,$iName)) { return self::$vLoaded[$iName]; } else { return FALSE; }   }    public static function Path($iName) { $objMod = clsModule::ByName($iName); if (is_object($objMod)) { return $objMod->Path; } else { return NULL; } /*	if (isset(self::$vList[$iName])) { return self::$vList[$iName]; } else { return NULL; }   }    private static function AddLog($iText) { self::$Log .= "\n$iText "; } } //clsLibMgr::Init;

/* PURPOSE: like array_key_exists, but parameters are in a sensible order, and doesn't choke if array is NULL or not set. if (!function_exists('ArrayHas')) { function ArrayHas(array $iArr=NULL,$iKey) { if (is_null($iArr)) { return FALSE; } else { return array_key_exists($iKey,$iArr); }   } }