2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 // +----------------------------------------------------------------------+
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license, |
9 // | that is bundled with this package in the file LICENSE, and is |
10 // | available at through the world-wide-web at |
11 // | http://www.php.net/license/2_02.txt. |
12 // | If you did not receive a copy of the PHP license and are unable to |
13 // | obtain it through the world-wide-web, please send a note to |
14 // | license@php.net so we can mail you a copy immediately. |
15 // +----------------------------------------------------------------------+
16 // | Authors: Alan Knowles <alan@akbkhome.com> |
17 // +----------------------------------------------------------------------+
19 // $Id: FlexyFramework.php,v 1.8 2003/02/22 01:52:50 alan Exp $
22 // A Page (URL) to Object Mapper
23 // Cleaned up version.. - for use on new projects -- not BC!! beware!!!
27 // Initialize Static Options
28 require_once 'PEAR.php';
29 require_once 'HTML/FlexyFramework/Page.php';
30 require_once 'HTML/FlexyFramework/Error.php';
32 require_once 'DB/DataObject.php';
34 // To be removed ?? or made optional or something..
39 error_reporting(E_ALL & ~E_STRICT);
40 //ini_set('display_errors','off');
41 //ini_set('log_errors','off');
43 //PEAR::setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_ERROR);
49 * The URL to Object Mapper
52 * Create a index.php and add these lines.
54 * ini_set("include_path", "/path/to/application");
55 * require_once 'HTML/FlexyFramework.php';
56 * HTML_FlexyFramework::factory(array("dir"=>"/where/my/config/dir/is");
59 * the path could include pear's path, if you dont install all the pear
60 * packages into the development directory.
62 * It attempts to load a the config file from the includepath,
63 * looks for ConfigData/default.ini
64 * or ConfigData/{hostname}.ini
65 * if your file is called staging.php rather than index.php
66 * it will try staging.ini
70 class HTML_FlexyFramework {
73 * Confirgurable items..
74 * If we set them to 'true', they must be set, otherwise they are optional.
76 var $project; // base class name
77 var $database; // set to true even if nodatabase=true
81 var $enable = false; // modules
82 var $disable = false; // modules or permissions
84 var $appNameShort = false; // appname (which has templates)
85 var $version = false; // give it a version name. (appended to compile dir)
86 var $nodatabase = false; // set to true to block db config and testing.
87 var $fatalAction = false; // page to redirct to on failure. (eg. databse down etc.)
88 var $charset = false; // default UTF8
89 var $dataObjectsCache = true; // use dataobjects ini cache.. - let's try this as the default behaviour...
90 var $dataObjectsCacheExpires = 72000; // 20 hours..
95 var $cli = false; // from cli
96 var $run = false; // from cli
97 var $enableArray = false; // from enable.
98 var $classPrefix = false; // from prject.
99 var $baseDir = false ; // (directory+project)
100 var $rootDir = false ; // (directory that index.php is in!)
102 var $baseURL = false;
103 var $rootURL = false ; // basename($baseURL)
105 var $page = false; // active page..
106 var $timer = false; // the debug timer
107 var $calls = false; // the number of calls made to run!
108 var $start = false; // the start tiem.
110 var $baseRequest = '';
111 var $ext; // the striped extention.
113 var $dataObjectsOriginalIni = ''; // 1 houre..
116 * Constructor - with assoc. array of props as option
121 // function HTML_FlexyFramework($config) {
122 // return $this->__construct($config);
125 function __construct($config)
127 if (isset($GLOBALS[__CLASS__])) {
128 trigger_error("FlexyFramework Construct called twice!", E_ERROR);
130 $GLOBALS[__CLASS__] = &$this;
134 $m = explode(' ',microtime());
135 $this->start = $m[0] + $m[1];
137 foreach($config as $k=>$v) {
140 $this->_parseConfig();
142 // echo '<PRE>'; print_r($this);exit;
144 $args = $_SERVER['argv'];
147 $this->_run($this->run,false,$args);
149 // handle apache mod_rewrite..
150 if (!empty($_SERVER['REDIRECT_URL'])) {
152 $this->_run($_SERVER['SCRIPT_NAME'] . $_SERVER['REQUEST_URI'],false);
156 $this->_run($_SERVER['REQUEST_URI'],false);
160 static function get()
162 return $GLOBALS[__CLASS__];
166 function _parseConfig()
168 foreach(get_class_vars(__CLASS__) as $k =>$v) {
169 if ($v === false && !isset($this->$k)) {
170 die("$k is not set");
174 if (!empty($this->enable)) {
175 $this->enableArray = explode(',', $this->enable);
176 if (!in_array('Core',$this->enableArray )) {
177 $this->enable = 'Core,'. $this->enable ;
178 $this->enableArray = explode(',', $this->enable);
181 // are we running cli?
182 $this->cli = php_sapi_name() == 'cli';
184 // will these work ok with cli?
186 $bits = explode(basename($_SERVER["SCRIPT_FILENAME"]), $_SERVER["SCRIPT_NAME"]);
188 $bits[0] = str_replace('%2F','/',urlencode($bits[0]));
189 $this->baseURL = $bits[0] . basename($_SERVER["SCRIPT_FILENAME"]);
191 // if cli - you have to have set baseURL...
194 $this->rootDir = realpath(dirname($_SERVER["SCRIPT_FILENAME"]));
195 $this->baseDir = $this->rootDir .'/'. $this->project;
196 $this->rootURL = dirname($this->baseURL);
197 $this->rootURL = ($this->rootURL == '/') ? '' : $this->rootURL;
201 //var_dump($this->baseURL);
203 if (!isset($this->database) && isset($this->DB_DataObject['database'])) {
204 $this->database = $this->DB_DataObject['database'];
206 $this->classPrefix = $this->project . '_';
208 // list the available options..
209 if ($this->cli && empty($_SERVER['argv'][1])) {
210 require_once 'HTML/FlexyFramework/Cli.php';
211 $fcli = new HTML_FlexyFramework_Cli($this);
217 // see if it's a framework assignment.
220 require_once 'HTML/FlexyFramework/Cli.php';
221 $fcli = new HTML_FlexyFramework_Cli($this);
222 $res = $fcli->parseDefaultOpts();
230 $this->run = $this->cli ? $_SERVER['argv'][1] : false;
233 $this->_parseConfigDataObjects();
234 if ($this->dataObjectsCache && !$this->nodatabase) {
235 $this->_configDataObjectsCache();
239 $this->_parseConfigTemplate();
240 $this->_parseConfigMail();
242 // echo '<PRE>';print_r($this);exit;
244 $this->_exposeToPear();
245 $this->_validateEnv();
250 $this->_validateDatabase();
251 $this->_validateTemplate();
257 * overlay array properties..
260 function applyIf($prop, $ar) {
261 if (!isset($this->$prop)) {
265 // add only things that where not set!!!.
266 $this->$prop = array_merge($ar,$this->$prop);
269 //foreach($ar as $k=>$v) {
270 // if (!isset($this->$prop->$k)) {
271 // $this->$prop->$k = $v;
278 * - if turned on (dataObjectsCache = true) then
279 * a) ini file points to a parsed version of the structure.
280 * b) links.ini is a merged version of the configured link files.
282 * This only will force a generation if no file exists at all.. - after that it has to be called manually
283 * from the core page.. - which uses the Expires time to determine if regeneration is needed..
288 function _configDataObjectsCache()
290 // cli works under different users... it may cause problems..
291 $this->debug(__METHOD__);
292 if (function_exists('posix_getpwuid')) {
293 $uinfo = posix_getpwuid( posix_getuid () );
294 $user = $uinfo['name'];
296 $user = getenv('USERNAME'); // windows.
301 $iniCache = ini_get('session.save_path') .'/' .
302 'dbcfg-' . $user . '/'. $this->project ;
305 if ($this->appNameShort) {
306 $iniCache .= '_' . $this->appNameShort;
308 if ($this->version) {
309 $iniCache .= '.' . $this->version;
311 $dburl = parse_url($this->database);
312 if (!empty($dburl['path'])) {
313 $iniCache .= '-'.ltrim($dburl['path'],'/');
317 $this->debug(__METHOD__ . " : ini cache : $iniCache");
319 $dburl = parse_url($this->database);
320 $dbini = 'ini_'. basename($dburl['path']);
321 $this->debug(__METHOD__ . " : ini file : $dbini");
322 //override ini setting... - store original..
323 if (isset($this->DB_DataObject[$dbini])) {
324 $this->dataObjectsOriginalIni = $this->DB_DataObject[$dbini];
325 ///print_r($this->DB_DataObject);exit;
331 $this->DB_DataObject[$dbini] = $iniCache;
332 // we now have the configuration file name..
335 if (!file_exists($iniCache) || empty( $this->dataObjectsCacheExpires)) {
336 $this->generateDataobjectsCache(true);
344 * _generateDataobjectsCache:
346 * create xxx.ini and xxx.links.ini
348 * @arg force (boolean) force generation - default false;
352 function generateDataobjectsCache($force = false)
354 //$this->debug('generateDataobjectsCache: force=' . ($force ? 'yes' : 'no'));
355 if (!$this->dataObjectsCache) { // does not use dataObjects Caching..
356 $this->debug('generateDataobjectsCache', 'dataObjectsCache - empty');
360 $dburl = parse_url($this->database);
361 $dbini = 'ini_'. basename($dburl['path']);
364 $iniCache = $this->DB_DataObject[$dbini];
365 $iniCacheTmp = $iniCache . '.tmp' .md5(rand()); // random to stop two processes using the same file.
367 $force = ($force ? $force : !file_exists($iniCache)) || !$this->dataObjectsCacheExpires;
368 // $this->debug('generateDataobjectsCache: after check : force=' . ($force ? 'yes' : 'no'));
369 // not force or not expired, do not bother..
371 if ((filemtime($iniCache) + $this->dataObjectsCacheExpires) >time()) {
378 // force quoting of column names..
379 // unless it forced off..
380 if (!isset($this->DB_DataObject['quote_identifiers_tableinfo'] )) {
381 $this->DB_DataObject['quote_identifiers_tableinfo'] = true;
383 if (!file_exists(dirname($iniCache))) {
384 mkdir(dirname($iniCache),0700, true);
387 $this->DB_DataObject[$dbini] = $iniCacheTmp;
388 $this->_exposeToPear();
391 // DB_DataObject::debugLevel(1);
392 require_once 'HTML/FlexyFramework/Generator.php';
393 $generator = new HTML_FlexyFramework_Generator();
396 HTML_FlexyFramework_Generator::writeCache($iniCacheTmp, $iniCache);
397 // reset the cache to the correct lcoation.
398 $this->DB_DataObject[$dbini] = $iniCache;
399 $this->_exposeToPear();
401 //$GLOBALS['_DB_DATAOBJECT']['INI'][$this->database] = parse_ini_file($iniCache, true);
402 //$GLOBALS['_DB_DATAOBJECT']['SEQUENCE']
403 // clear any dataobject cache..
410 * DataObject Configuration:
411 * Always in Project/DataObjects
412 * unless enableArray is available...
417 function _parseConfigDataObjects()
419 if ($this->nodatabase && !$this->database) {
422 $dburl = parse_url($this->database);
423 $dbini = 'ini_'. basename($dburl['path']);
425 $dbinis = array(); //array(dirname(__FILE__) . '/Pman/DataObjects/pman.ini');
426 $dbreq = array(); //array( dirname(__FILE__) . '/Pman/DataObjects/');
427 $dbcls = array(); //array('Pman_DataObjects_');
429 if (!empty($this->enableArray)) {
431 foreach($this->enableArray as $m) {
432 // look in Pman/MODULE/DataObjects/*
433 if (file_exists($this->baseDir.'/'.$m.'/DataObjects')) {
434 $dbinis[] = $this->baseDir.'/'.$m.'/DataObjects/'. strtolower($this->project).'.ini';
435 $dbcls[] = $this->project .'_'. $m . '_DataObjects_';
436 $dbreq[] = $this->baseDir.'/'.$m.'/DataObjects';
439 // look in MODULE/DataObjects
440 if (file_exists($this->baseDir.'/../'.$m.'/DataObjects')) {
441 $dbinis[] = $this->baseDir.'/../'.$m.'/DataObjects/'. strtolower($this->project).'.ini';
442 $dbcls[] = $m . '_DataObjects_';
443 $dbreq[] = $this->baseDir.'/../'.$m.'/DataObjects';
452 if (isset($this->DB_DataObject['schema_location'])) {
453 $dbinis[] = $this->DB_DataObject['schema_location'] .'/'.basename($dburl['path']).'.ini';
455 $dbinis[] = $this->baseDir.'/DataObjects/'.basename($dburl['path']).'.ini';
459 $dbcls[] = $this->project .'_DataObjects_';
460 $dbreq[] = $this->baseDir.'/DataObjects';
464 $this->applyIf('DB_DataObject', array(
466 'class_location' => implode(PATH_SEPARATOR,$dbreq),
467 'class_prefix' => implode(PATH_SEPARATOR,$dbcls),
468 'database' => $this->database,
469 ///'require_prefix' =>
470 // 'schema_location' => dirname(__FILE__) . '/Pman/DataObjects/',
471 $dbini=> implode(PATH_SEPARATOR,$dbinis),
475 // print_r($this->DB_DataObject);exit;
481 function _parseConfigTemplate()
485 if (function_exists('posix_getpwuid')) {
486 $uinfo = posix_getpwuid( posix_getuid () );
488 $user = $uinfo['name'];
490 $user = getenv('USERNAME'); // windows.
493 $compileDir = ini_get('session.save_path') .'/' .
494 $user . '_compiled_templates_' . $this->project;
496 if ($this->appNameShort) {
497 $compileDir .= '_' . $this->appNameShort;
499 if ($this->version) {
500 $compileDir .= '.' . $this->version;
503 // templates. -- all this should be cached!!!
505 $src[] = $this->baseDir . '/templates';
506 if ($this->appNameShort) {
507 // in app based version, template directory is in Core
512 $this->baseDir . '/Core/templates',
513 $this->baseDir . '/'. $this->appNameShort. '/templates'
517 if (!empty($this->enableArray)) {
518 foreach($this->enableArray as $m) {
519 $add = $this->baseDir . '/' . $m .'/templates';
520 if (!in_array($add,$src) && file_exists($add)) {
528 // images may come from multiple places: - if we have multiple template directories.?
529 // how do we deal with this..?
530 // images/ << should always be mapped to master!
531 // for overridden appdir ones we will have to se rootURL etc.
533 $url_rewrite = 'images/:'. $this->rootURL . '/'. $this->project. '/templates/images/';
535 $this->applyIf('HTML_Template_Flexy', array(
536 'templateDir' => implode(PATH_SEPARATOR, $src),
537 'compileDir' => $compileDir,
538 'multiSource' => true,
540 'url_rewrite' => $url_rewrite,
541 'filters' => 'Php,SimpleTags', /// for non-tokenizer version?
542 'debug' => $this->debug ? 1 : 0,
550 function _parseConfigMail()
552 $this->applyIf('HTML_Template_Flexy', array(
555 'host' => 'localhost',
559 function _exposeToPear()
561 $cls = array_keys(get_class_vars(__CLASS__));
564 // anything that get's set, that's not in our default properties
565 // is assumed to be an option set .
566 foreach(get_object_vars($this) as $k=>$v) {
567 if (in_array($k,$cls)) {
571 $options = &PEAR::getStaticProperty($k,'options');
574 $options = &PEAR::getStaticProperty('HTML_FlexyFramework','options');
580 function _validateEnv()
582 /* have I been initialized */
585 if (get_magic_quotes_gpc() && !$this->cli) {
587 "magic quotes is enabled add the line<BR>
588 php_value magic_quotes_gpc 0<BR>
589 to your .htaccess file <BR>
590 (Apache has to be configured to "AllowOverride Options AuthConfig" for the directory)
594 // set up error handling -
595 $this->error = new HTML_FlexyFramework_Error();
597 /// fudge work around bugs in PEAR::setErrorHandling(,)
598 $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_CALLBACK;
599 $GLOBALS['_PEAR_default_error_options'] = array($this->error,'raiseError');
604 require_once 'Benchmark/Timer.php';
605 $this->timer = new BenchMark_Timer(true);
610 function _validateDatabase()
612 if ($this->nodatabase == true) {
615 //echo "<PRE>"; print_R($config);
616 $options = &PEAR::getStaticProperty('DB_DataObject','options');
617 $dd = empty($options['dont_die']) ? false : true;
618 $options['dont_die'] = true;
620 // database is the only setting - we dont support mult databses?
622 $x = new DB_Dataobject;
623 $x->_database = $this->database;
625 if (PEAR::isError($err = $x->getDatabaseConnection())) {
627 $this->fatalError("Configuration or Database Error: could not connect to Database, <BR>
628 Please check the value given to HTML_FlexyFramework, or run with debug on!<BR>
629 <BR> ".$err->toString());
632 $options['dont_die'] = $dd ;
634 function _validateTemplate()
636 // check that we have a writeable directory for flexy's compiled templates.
638 if (empty($this->HTML_Template_Flexy['compileDir'])) {
642 if ( !file_exists($this->HTML_Template_Flexy['compileDir'])) {
643 mkdir($this->HTML_Template_Flexy['compileDir'], 0700);
644 @mkdir($this->HTML_Template_Flexy['compileDir'], 0700, true);
647 if ( !file_exists($this->HTML_Template_Flexy['compileDir'])) {
649 $this->fatalError("Configuration Error: you specified a directory that does not exist for<BR>
650 HTML_Template_Flexy => compileDir {$this->HTML_Template_Flexy['compileDir']}<BR>\n"
655 if (!is_writeable($this->HTML_Template_Flexy['compileDir'])) {
656 $this->fatalError("Configuration Error: Please make sure the template cache directory is writeable<BR>
658 chmod 700 {$this->HTML_Template_Flexy['compileDir']}<BR>
659 chgrp apache_user {$this->HTML_Template_Flexy['compileDir']}<BR>\n"
662 //echo "<PRE>";print_R($config);
680 * HTML_FlexyFramework::run('someurl/someother',array('somearg'=>'xxx'));
682 * exit; <- dont cary on!!!!
686 * @param string redirect to url
687 * @param array Args Optional any data you want to send to the next page..
696 function run($request,$args=array())
698 $GLOBALS[__CLASS__]->_run($request,true,$args);
704 * The main execution loop
706 * recursivly self called if redirects (eg. return values from page start methods)
708 * @param string from $_REQUEST or redirect from it'self.
709 * @param boolean isRedirect = is the request a redirect
712 * @return false || other false indicates no page was served!
713 * @access public|private
714 * @see see also methods.....
717 function _run($request,$isRedirect = false,$args = array())
720 // clean the request up.
723 if ($this->calls > 5) {
724 // to many redirections...
725 trigger_error("FlexyFramework:: too many redirects - backtrace me!",E_USER_ERROR);
729 $newRequest = $this->_getRequest($request,$isRedirect);
731 // find the class/file to load
732 list($classname,$subRequest) = $this->requestToClassName($newRequest,FALSE);
735 $this->debug("requestToClassName return = CLASSNAME: $classname SUB REQUEST: $subRequest");
737 // assume that this was handled by getclassname ?????
742 // make page data/object accessable at anypoint in time using this
743 $classobj = &PEAR::getStaticProperty('HTML_FlexyFramework', 'page');
745 $classobj = new $classname(); // normally do not have constructors.
748 $classobj->baseURL = $this->baseURL;
749 $classobj->rootURL = $this->rootURL;
750 $classobj->rootDir = $this->rootDir;
751 $classobj->bootLoader = $this;
752 $classobj->request = $newRequest;
753 $classobj->timer = &$this->timer;
755 $this->page = $classobj;
756 if ($this->cli && !$isRedirect ) { // redirect always just takes redirect args..
757 require_once 'HTML/FlexyFramework/Cli.php';
758 $fcli = new HTML_FlexyFramework_Cli($this);
759 $nargs = $fcli->cliParse($classname);
760 $args = $nargs === false ? $args : $nargs; /// replace if found.
761 $classobj->cli_args = $nargs;
764 // echo '<PRE>'; print_r($this);exit;
765 // echo "CHECK GET AUTH?";
766 if (!method_exists($classobj, 'getAuth')) {
767 // echo "NO GET AUTH?";
768 $this->fatalError("class $classname does not have a getAuth Method");
772 /* check auth on the page */
773 if (is_string($redirect = $classobj->getAuth())) {
774 $this->debug("GOT AUTH REDIRECT".$redirect);
775 return $this->_run($redirect,TRUE);
777 // used HTML_FlexyFramework::run();
780 if ($redirect === false) {
781 $this->debug("GOT AUTH FALSE");
782 return false; /// Access deined!!! -
785 // allow the page to implement caching (for the full page..)
786 // although normally it should implement caching on the outputBody() method.
788 if (method_exists($classobj,"getCache")) {
789 if ($result = $classobj->getCache()) {
793 /* allow redirect from start */
794 if (method_exists($classobj,"start")) {
795 if (is_string($redirect = $classobj->start($subRequest,$isRedirect,$args))) {
796 $this->debug("REDIRECT $redirect <BR>");
797 return $this->_run($redirect,TRUE);
799 if ($redirect === false) {
805 // used HTML_FlexyFramework::run();
808 * Modules are common page components like navigation headers etc.
809 * that can have dynamic code.
810 * Code has been removed now..
815 $this->timer->setMarker("After $request loadModules Modules");
818 /* output it - (our base page does not implement output for cli. */
820 if ( method_exists($classobj,'output')) {
826 $this->timer->setMarker("After $request output");
827 $this->timer->stop(); //?? really - yes...
835 exit; /// die here...
840 * map the request into an object and run the page.
842 * The core of the work is done here.
845 * @param request the request string
846 * @param boolean isRedirect - indicates that it should not attempt to strip the .../index.php from the request.
851 function _getRequest($request, $isRedirect)
860 $startRequest = $request;
861 $request =@ array_shift(explode('?', $request));
862 $this->debug("INPUT REQUEST $request<BR>");
864 // check that request forms contains baseurl????
866 $subreq = substr($request,0,strlen($this->baseURL));
867 if ($subreq != substr($this->baseURL,0,strlen($subreq))) {
869 "Configuration error: Got base of $subreq which does not
870 match configuration of: $this->baseURL} ");
872 $request = substr($request,strlen($this->baseURL));
876 // echo "REQUEST WAS: $request<BR>";
877 // $request = preg_replace('/^'.preg_quote($base_url,'/').'/','',trim($request));
878 // echo "IS NOW: $request<BR>";
880 // strip valid html stuff
881 //$request = preg_replace('/\/[.]+/','',$request);
884 $request = preg_replace('/^[\/]*/','',$request);
885 $request = preg_replace('/\?.*$/','',$request);
886 $request = preg_replace('/[\/]*$/','',$request);
887 $this->baseRequest = $request;
888 $request = str_replace('&','',$request); // any other invalid characters???
889 $request = preg_replace('/\.([a-z]+)$/','',$request);
890 $this->ext = substr($this->baseRequest , strlen($request));
892 // REDIRECT ROO to index.php! for example..
894 if (!$request && !$isRedirect) {
895 if ($this->baseURL && (strlen($startRequest) < strlen($this->baseURL))) {
896 // needs to handle https + port
897 $http = ((!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on')) ? 'https' : 'http';
899 if (!empty($_SERVER['SERVER_PORT'])) {
900 if ((($http == 'http') && ($_SERVER['SERVER_PORT'] == 80)) || (($http == 'https') && ($_SERVER['SERVER_PORT'] == 443))) {
903 $sp .= ':'.((int) $_SERVER['SERVER_PORT']);
906 $host = !empty($_SERVER["HTTP_X_FORWARDED_HOST"]) ? $_SERVER["HTTP_X_FORWARDED_HOST"] : $_SERVER["HTTP_HOST"];
907 header('Location: '.$http.'://'.$host .$sp . $this->baseURL);
913 $this->debug("OUTPUT REQUEST $request<BR>");
921 * get the Class name and filename to load
923 * Parses the request and converts that into a File + Classname
924 * if the class doesnt exist it will attempt to find a file below it, and
925 * call that one with the data.
926 * Used by the module loader to determine the location of the modules
928 * @param request the request string
929 * @param boolean showError - if false, allows you to continue if the class doesnt exist.
932 * @return array classname, filepath
937 function requestToClassName($request,$showError=TRUE)
939 // if ($request == "error") {
940 // return array("HTML_FlexyFramework_Error","");
943 // special classes ::
944 if ($this->cli && in_array($request, array('DataObjects'))) {
945 require_once 'HTML/FlexyFramework/'. $request . '.php';
946 return array('HTML_FlexyFramework_'. $request,'');
950 $request_array=explode("/",$request);
951 $original_request_array = $request_array;
952 $sub_request_array = array();
953 $l = count($request_array)-1;
954 if ($l > 10) { // ?? configurable?
955 //PEAR::raiseError("Request To Long");
956 $this->fatalError("Request To Long");
961 // tidy up request array
963 if ($request_array) {
964 foreach(array_keys($request_array) as $i) {
965 $request_array[$i] = preg_replace('/[^a-z0-9]/i','_',urldecode($request_array[$i]));
968 //echo "<PRE>"; print_r($request_array);
969 // technically each module should do a check here... similar to this..
973 for ($i=$l;$i >-1;$i--) {
974 $location = implode('/',$request_array) . ".php";
975 $this->debug("baseDIR = {$this->baseDir}");
976 $floc = "{$this->baseDir}/$location";
977 //$this->debug("CHECK LOCATION $floc");
978 if (!empty($location) && @file_exists($floc )) { // hide? error???
980 $classname = $this->classPrefix . implode('_',$request_array);
981 $this->debug("FOUND FILE - SET CLASS = $classname <BR>");
984 $this->debug("$floc - !!FOUND NOT FILE!!");
986 $sub_request_array[] = $original_request_array[$i];
987 unset($request_array[$i]);
988 unset($original_request_array[$i]);
991 // is this really needed here!
993 $classname = preg_replace('/[^a-z0-9]/i','_',$classname);
994 $this->debug("CLASSNAME is '$classname'");
996 if ($classname && class_exists($classname)) {
997 $this->debug("using $classname");
998 //print_r($sub_request_array);
999 return array($classname,implode('/',array_reverse($sub_request_array)));
1003 $this->fatalError("INVALID REQUEST: \n $request FILE:".$this->baseDir. "/{$location} CLASS:{$classname}");
1008 $this->debug("Try base {$this->baseDir}.php");
1009 // try {project name}.php
1010 // this used to be silenced @ - if this fails we are usually pretty fried..
1012 if (file_exists($this->baseDir.'.php')) {
1015 $classname = basename($this->baseDir);
1017 $this->debug("FOUND {$this->baseDir} requring and checking class $classname");
1018 require_once $this->baseDir.'.php';
1019 $this->debug("require success");
1021 if (!class_exists($classname)) {
1022 $this->fatalError( "{$this->baseDir}.php did not contain class $classname");
1025 // got projectname.php
1026 if ($classname && class_exists($classname)) {
1027 $this->debug("using $classname");
1028 //print_r($sub_request_array);
1030 return array($classname,implode('/',array_reverse($sub_request_array)));
1034 $this->fatalError( "can not find {$this->baseDir}.php"); // dies..
1040 * ensure Single CLi process
1042 * HTML_FlexyFramework::ensureSingle(__FILE__, $this);
1043 * @param string filename of running class
1044 * @param object class
1047 static function ensureSingle($sig, $class)
1049 $ff = HTML_FlexyFramework::get();
1050 if (function_exists('posix_getpwuid')) {
1051 $uinfo = posix_getpwuid( posix_getuid () );
1052 $user = $uinfo['name'];
1054 $user = getenv('USERNAME'); // windows.
1056 $fdir = ini_get('session.save_path') .'/' .
1057 $user . '_cli_' . $ff->project ;
1060 if (!file_exists($fdir)) {
1063 $lock = $fdir.'/'. md5($sig);
1064 if (!file_exists($lock)) {
1065 file_put_contents($lock, getmypid());
1068 $oldpid = file_get_contents($lock);
1069 if (!file_exists('/proc/' . $oldpid)) {
1070 file_put_contents($lock, getmypid());
1073 // file exists, but process might not be the same..
1074 $name = array_pop(explode('_', get_class($class)));
1075 $cmd = file_get_contents('/proc/' . $oldpid.'/cmdline');
1076 if (!preg_match('/php/i',$cmd) || !preg_match('/'.$name.'/i',$cmd)) {
1077 file_put_contents($lock, getmypid());
1080 die("process " . $sig . " already running\n");
1084 * removes the lock for the applicaiton - use with care...
1088 static function ensureSingleClear($sig, $class)
1090 $ff = HTML_FlexyFramework::get();
1091 if (function_exists('posix_getpwuid')) {
1092 $uinfo = posix_getpwuid( posix_getuid () );
1093 $user = $uinfo['name'];
1095 $user = getenv('USERNAME'); // windows.
1097 $fdir = ini_get('session.save_path') .'/' .
1098 $user . '_cli_' . $ff->project ;
1101 if (!file_exists($fdir)) {
1104 $lock = $fdir.'/'. md5($sig);
1105 if (!file_exists($lock)) {
1116 * @param string text to output.
1120 function debug($output) {
1122 if (empty($this->debug)) {
1126 "HTML_FlexyFramework::debug - ".$output."\n"
1127 : "<B>HTML_FlexyFramework::debug</B> - ".$output."<BR>\n";
1131 * Raises a fatal error. - normally only used when setting up to help get the config right.
1133 * can redirect to fatal Action page.. - hoepfully not issued before basic vars are set up..
1135 * @param string text to output.
1139 function fatalError($msg,$showConfig = 0)
1144 if ($this->fatalAction) {
1145 HTML_FlexyFramework::run($this->fatalAction,$msg);
1149 echo $this->cli ? $msg ."\n" : "<H1>$msg</H1>configuration information<PRE>";
1154 $ff = HTML_FlexyFramework::get();