Pman.php
[Pman.Base] / Pman.php
1 <?php 
2 /**
3  * Pman Base class
4  * 
5  * Provides:
6  *  - base application setup (variables etc to javascript)
7  * 
8  *  - authentication and permission info about user / application
9  *  - json output methods.
10  *  - file upload error checking - checkFileUploadError
11  *  - logging to event table
12  *  - sendTemplate code (normally use the Person version for sending to specific people..)
13  * 
14  *  - doc managment code?? - remarks and tracking??? - MOVEME
15  *  - authentication link checking?? MOVEME?
16  *  - authentication reset password ?? MOVEME?
17  *  ?? arrayClean.. what's it doing here?!? ;)
18  * 
19  * Usefull implemetors
20  * DB_DataObject*:*toEventString (for logging - this is generically prefixed to all database operations.)
21  *   - any data object where this method exists, the result will get prefixed to the log remarks
22  */
23
24 class Pman extends HTML_FlexyFramework_Page 
25 {
26     var $appName= "";
27     var $appLogo= "";
28     var $appShortName= "";
29     var $appVersion = "1.8";
30     var $version = 'dev';
31     var $onloadTrack = 0;
32     var $linkFail = "";
33     var $showNewPass = 0;
34     var $logoPrefix = '';
35     var $appModules = '';
36     var $appDisabled = array(); // array of disabled modules..
37                     // (based on config option disable)
38     
39     var $authUser; // always contains the authenticated user..
40     
41    
42     
43     /**
44      * ------------- Standard getAuth/get/post methods of framework.
45      * 
46      * 
47      */
48     
49     function getAuth() // everyone allowed in!!!!!
50     {
51         $this->loadOwnerCompany();
52         
53         return true;
54         
55     }
56     
57     function init() 
58     {
59         if (isset($this->_hasInit)) {
60             return;
61         }
62         $this->_hasInit = true;
63           
64         $boot = HTML_FlexyFramework::get();
65         // echo'<PRE>';print_R($boot);exit;
66         $this->appName= $boot->appName;
67         $this->appNameShort= $boot->appNameShort;
68         
69         
70         $this->appModules= $boot->enable;
71         $this->isDev = empty($boot->Pman['isDev']) ? false : $boot->Pman['isDev'];
72         $this->appDisable = $boot->disable;
73         $this->appDisabled = explode(',', $boot->disable);
74         $this->version = $boot->version;
75         
76         if (!empty($ff->Pman['local_autoauth']) && 
77             ($_SERVER['SERVER_ADDR'] == '127.0.0.1') &&
78             ($_SERVER['REMOTE_ADDR'] == '127.0.0.1') 
79         ) {
80             $this->isDev = true;
81         }
82         if ($this->company->logo_id) {
83             $im = DB_DataObject::Factory('Image');
84             $im->get($this->company->logo_id);
85             $this->appLogo = $this->baseURL . '/Images/'. $this->company->logo_id .'/' . $im->filename;
86         }
87         
88         
89         
90     }
91     
92     function get($base) 
93     {
94         $this->init();
95             //$this->allowSignup= empty($opts['allowSignup']) ? 0 : 1;
96         $bits = explode('/', $base);
97         //print_R($bits);
98         if ($bits[0] == 'Link') {
99             $this->linkFail = $this->linkAuth(@$bits[1],@$bits[2]);
100             header('Content-type: text/html; charset=utf-8');
101             return;
102         } 
103         if ($bits[0] == 'PasswordReset') {
104             $this->linkFail = $this->resetPassword(@$bits[1],@$bits[2],@$bits[3]);
105             header('Content-type: text/html; charset=utf-8');
106             return;
107         } 
108         
109         
110         if ($this->getAuthUser()) {
111             $this->addEvent("RELOAD");
112         }
113         
114         
115         if (strlen($base)) {
116             $this->addEvent("BADURL", false, $base);
117             $this->jerr("invalid url");
118         }
119         // deliver template
120         if (isset($_GET['onloadTrack'])) {
121             $this->onloadTrack = (int)$_GET['onloadTrack'];
122         }
123         // getting this to work with xhtml is a nightmare
124         // = nbsp / <img> issues screw everyting up.
125          //var_dump($this->isDev);
126         // force regeneration on load for development enviroments..
127         
128         HTML_FlexyFramework::get()->generateDataobjectsCache($this->isDev);
129         
130         //header('Content-type: application/xhtml+xml; charset=utf-8');
131         header('Content-type: text/html; charset=utf-8');
132          
133     }
134     function post($base) {
135         return $this->get($base);
136     }
137     
138     
139     // --------------- AUTHENTICATION or  system information
140     /**
141      * loadOwnerCompany:
142      * finds the compay with comptype=='OWNER'
143      *
144      * @return {Pman_Core_DataObjects_Companies} the owner company
145      */
146     function loadOwnerCompany()
147     {
148          
149         $this->company = DB_DataObject::Factory('Companies');
150         if (!is_a($this->company, 'DB_DataObject')) { // non-core pman projects
151             return false; 
152         }
153         $this->company->get('comptype', 'OWNER');
154         return $this->company;
155     }
156     
157     
158     
159     /**
160      * getAuthUser: - get the authenticated user..
161      *
162      * @return {DB_DataObject} of type Pman[authTable] if authenticated.
163      */
164     
165     function getAuthUser()
166     {
167         if (!empty($this->authUser)) {
168             return $this->authUser;
169         }
170         $ff = HTML_FlexyFramework::get();
171         $tbl = empty($ff->Pman['authTable']) ? 'Person' : $ff->Pman['authTable'];
172         
173         $u = DB_DataObject::factory( $tbl );
174         if (!$u->isAuth()) {
175             return false;
176         }
177         $this->authUser =$u->getAuthUser();
178         return $this->authUser ;
179     }
180     /**
181      * hasPerm:
182      * wrapper arround authuser->hasPerm
183      * @see Pman_Core_DataObjects_User::hasPerm
184      *
185      * @param {String} $name  The permission name (eg. Projects.List)
186      * @param {String} $lvl   eg. (C)reate (E)dit (D)elete ... etc.
187      * 
188      */
189     function hasPerm($name, $lvl)  // do we have a permission
190     {
191         static $pcache = array();
192         $au = $this->getAuthUser();
193         return $au && $au->hasPerm($name,$lvl);
194         
195     }
196    
197     /**
198      * modulesList:  List the modules in the application
199      *
200      * @return {Array} list of modules
201      */
202     function modulesList()
203     {
204         $this->init();
205         
206         $mods = explode(',', $this->appModules);
207         if (in_array('Core',$mods)) { // core has to be the first  modules loaded as it contains Pman.js
208             array_unshift($mods,   'Core');
209         }
210         
211         $mods = array_unique($mods);
212          
213         $disabled =  explode(',', $this->appDisable ? $this->appDisable: '');
214         $ret = array();
215         foreach($mods as $mod) {
216             // add the css file..
217             if (in_array($mod, $disabled)) {
218                 continue;
219             }
220             $ret[] = $mod;
221         }
222         return $ret;
223     }
224     
225      
226     
227     
228     function hasModule($name) 
229     {
230         $this->init();
231         if (!strpos( $name,'.') ) {
232             // use enable / disable..
233             return in_array($name, $this->modules()); 
234         }
235         
236         $x = DB_DataObject::factory('Group_Rights');
237         $ar = $x->defaultPermData();
238         if (empty($ar[$name]) || empty($ar[$name][0])) {
239             return false;
240         }
241         return true;
242     }
243     
244      
245     
246     
247     
248     /**
249      * ---------------- Global Tools ---------------   
250      */
251     
252     
253     
254     /**
255      * send a template to the user
256      * rcpts are read from the resulting template.
257      * 
258      * @arg $templateFile  - the file in mail/XXXXXX.txt
259      * @arg $args  - variables available to the form as {t.*} over and above 'this'
260      * 
261      * 
262      */
263     
264     function sendTemplate($templateFile, $args)
265     {
266         
267         
268         
269         $content  = clone($this);
270         
271         foreach((array)$args as $k=>$v) {
272             $content->$k = $v;
273         }
274         $content->msgid = md5(time() . rand());
275         
276         $content->HTTP_HOST = $_SERVER["HTTP_HOST"];
277         /* use the regex compiler, as it doesnt parse <tags */
278         require_once 'HTML/Template/Flexy.php';
279         $template = new HTML_Template_Flexy( array(
280                  'compiler'    => 'Regex',
281                  'filters' => array('SimpleTags','Mail'),
282             //     'debug'=>1,
283             ));
284         
285         // this should be done by having multiple template sources...!!!
286          
287         $template->compile('mail/'. $templateFile.'.txt');
288         
289         /* use variables from this object to ouput data. */
290         $mailtext = $template->bufferedOutputObject($content);
291         //echo "<PRE>";print_R($mailtext);
292         
293         /* With the output try and send an email, using a few tricks in Mail_MimeDecode. */
294         require_once 'Mail/mimeDecode.php';
295         require_once 'Mail.php';
296         
297         $decoder = new Mail_mimeDecode($mailtext);
298         $parts = $decoder->getSendArray();
299         if (PEAR::isError($parts)) {
300             return $parts;
301             //echo "PROBLEM: {$parts->message}";
302             //exit;
303         } 
304         list($recipents,$headers,$body) = $parts;
305         ///$recipents = array($this->email);
306         $mailOptions = PEAR::getStaticProperty('Mail','options');
307         $mail = Mail::factory("SMTP",$mailOptions);
308         $headers['Date'] = date('r');
309         if (PEAR::isError($mail)) {
310             return $mail;
311         } 
312         $oe = error_reporting(E_ALL ^ E_NOTICE);
313         $ret = $mail->send($recipents,$headers,$body);
314         error_reporting($oe);
315        
316         return $ret;
317     
318     }
319     
320     function checkFileUploadError()  // check for file upload errors.
321     {    
322         if (
323             empty($_FILES['File']) 
324             || empty($_FILES['File']['name']) 
325             || empty($_FILES['File']['tmp_name']) 
326             || empty($_FILES['File']['type']) 
327             || !empty($_FILES['File']['error']) 
328             || empty($_FILES['File']['size']) 
329         ) {
330             $this->jerr("File upload error: <PRE>" . print_r($_FILES,true) . print_r($_POST,true) . "</PRE>");
331         }
332     }
333     
334     
335     /**
336      * generate a tempory file with an extension (dont forget to delete it)
337      */
338     
339     function tempName($ext)
340     {
341         $x = tempnam(ini_get('session.save_path'), HTML_FlexyFramework::get()->appNameShort.'TMP');
342         unlink($x);
343         return $x .'.'. $ext;
344     }
345     /**
346      * ------------- Authentication testing ------ ??? MOVEME?
347      * 
348      * 
349      */
350     function linkAuth($trid, $trkey) 
351     {
352         $tr = DB_DataObject::factory('Documents_Tracking');
353         if (!$tr->get($trid)) {
354             return "Invalid URL";
355         }
356         if (strtolower($tr->authkey) != strtolower($trkey)) {
357             $this->AddEvent("ERROR-L", false, "Invalid Key");
358             return "Invalid KEY";
359         }
360         // check date..
361         $this->onloadTrack = (int) $tr->doc_id;
362         if (strtotime($tr->date_sent) < strtotime("NOW - 14 DAYS")) {
363             $this->AddEvent("ERROR-L", false, "Key Expired");
364             return "Key Expired";
365         }
366         // user logged in and not
367         $au = $this->getAuthUser();
368         if ($au && $au->id && $au->id != $tr->person_id) {
369             $au->logout();
370             
371             return "Logged Out existing Session\n - reload to log in with correct key";
372         }
373         if ($au) { // logged in anyway..
374             $this->AddEvent("LOGIN", false, "With Key (ALREADY)");
375             header('Location: ' . $this->baseURL.'?onloadTrack='.$this->onloadTrack);
376             exit;
377             return false;
378         }
379         
380         // authenticate the user...
381         // slightly risky...
382         $u = DB_DataObject::factory('Person');
383          
384         $u->get($tr->person_id);
385         $u->login();
386         $this->AddEvent("LOGIN", false, "With Key");
387         
388         // we need to redirect out - otherwise refererer url will include key!
389         header('Location: ' . $this->baseURL.'?onloadTrack='.$this->onloadTrack);
390         exit;
391         
392         return false;
393         
394         
395         
396         
397     }
398     
399     
400     /**
401      * ------------- Authentication password reset ------ ??? MOVEME?
402      * 
403      * 
404      */
405     
406     
407     function resetPassword($id,$t, $key)
408     {
409         
410         $au = $this->getAuthUser();
411         if ($au) {
412             return "Already Logged in - no need to use Password Reset";
413         }
414         
415         $u = DB_DataObject::factory('Person');
416         //$u->company_id = $this->company->id;
417         $u->active = 1;
418         if (!$u->get($id) || !strlen($u->passwd)) {
419             return "invalid id";
420         }
421         
422         // validate key.. 
423         if ($key != $u->genPassKey($t)) {
424             return "invalid key";
425         }
426         $uu = clone($u);
427         $u->no_reset_sent = 0;
428         $u->update($uu);
429         
430         if ($t < strtotime("NOW - 1 DAY")) {
431             return "expired";
432         }
433         $this->showNewPass = implode("/", array($id,$t,$key));
434         return false;
435     }
436     
437     /**
438      * jerrAuth: standard auth failure - with data that let's the UI know..
439      */
440     function jerrAuth()
441     {
442         $au = $this->authUser();
443         if ($au) {
444             // is it an authfailure?
445             $this->jerr("Permission denied to view this resource", array('authFailure' => true));
446         }
447         $this->jerr("Not authenticated", array('authFailure' => true));
448     }
449      
450      
451      
452     /**
453      * ---------------- Standard JSON outputers. - used everywhere
454      */
455     
456     function jerr($str, $errors=array()) // standard error reporting..
457     {
458         
459         $cli = HTML_FlexyFramework::get()->cli;
460         if ($cli) {
461             echo "ERROR:\n" .$str . "\n";
462             exit;
463         }
464         
465         require_once 'Services/JSON.php';
466         $json = new Services_JSON();
467         
468         // log all errors!!!
469         $this->addEvent("ERROR", false, $str);
470         
471         if (!empty($_REQUEST['returnHTML']) || 
472             (isset($_SERVER['CONTENT_TYPE']) && preg_match('#multipart/form-data#i', $_SERVER['CONTENT_TYPE']))
473         ) {
474             header('Content-type: text/html');
475             echo "<HTML><HEAD></HEAD><BODY>";
476             echo  $json->encodeUnsafe(array(
477                     'success'=> false, 
478                     'errorMsg' => $str,
479                     'message' => $str, // compate with exeption / loadexception.
480
481                     'errors' => $errors ? $errors : true, // used by forms to flag errors.
482                     'authFailure' => !empty($errors['authFailure']),
483                 ));
484             echo "</BODY></HTML>";
485             exit;
486         }
487         
488         echo $json->encode(array(
489             'success'=> false, 
490             'data'=> array(), 
491             'errorMsg' => $str,
492             'message' => $str, // compate with exeption / loadexception.
493             'errors' => $errors ? $errors : true, // used by forms to flag errors.
494             'authFailure' => !empty($errors['authFailure']),
495         ));
496         exit;
497         
498     }
499     function jok($str)
500     {
501         
502         require_once 'Services/JSON.php';
503         $json = new Services_JSON();
504         
505         if (!empty($_REQUEST['returnHTML']) || 
506             (isset($_SERVER['CONTENT_TYPE']) && preg_match('#multipart/form-data#i', $_SERVER['CONTENT_TYPE']))
507         
508         ) {
509             header('Content-type: text/html');
510             echo "<HTML><HEAD></HEAD><BODY>";
511             // encode html characters so they can be read..
512             echo  str_replace(array('<','>'), array('\u003c','\u003e'),
513                         $json->encodeUnsafe(array('success'=> true, 'data' => $str)));
514             echo "</BODY></HTML>";
515             exit;
516         }
517          
518         
519         echo  $json->encode(array('success'=> true, 'data' => $str));
520         exit;
521         
522     }
523     /**
524      * output data for grids or tree
525      * @ar {Array} ar Array of data
526      * @total {Number|false} total number of records (or false to return count(ar)
527      * @extra {Array} extra key value list of data to pass as extra data.
528      * 
529      */
530     function jdata($ar,$total=false, $extra=array())
531     {
532         // should do mobile checking???
533         if ($total == false) {
534             $total = count($ar);
535         }
536         $extra=  $extra ? $extra : array();
537         require_once 'Services/JSON.php';
538         $json = new Services_JSON();
539         if (isset($_SERVER['CONTENT_TYPE']) && preg_match('#multipart/form-data#i', $_SERVER['CONTENT_TYPE'])) {
540             
541             header('Content-type: text/html');
542             echo "<HTML><HEAD></HEAD><BODY>";
543             // encode html characters so they can be read..
544             echo  str_replace(array('<','>'), array('\u003c','\u003e'),
545                         $json->encodeUnsafe(array('success' =>  true, 'total'=> $total, 'data' => $ar) + $extra));
546             echo "</BODY></HTML>";
547             exit;
548         }
549         
550       
551         
552         
553         
554         
555        
556         echo $json->encode(array('success' =>  true, 'total'=> $total, 'data' => $ar) + $extra);    
557         exit;
558         
559         
560     }
561     
562     
563    
564     
565     /**
566      * ---------------- OUTPUT
567      */
568     function hasBg($fn) // used on front page to check if logos exist..
569     {
570         return file_exists($this->rootDir.'/Pman/'.$this->appNameShort.'/templates/images/'.  $fn);
571     }
572      /**
573      * outputJavascriptIncludes:
574      *
575      * output <script....> for all the modules in the applcaiton
576      *
577      */
578     function outputJavascriptIncludes() // includes on devel version..
579     {
580         
581         $mods = $this->modulesList();
582         
583         foreach($mods as $mod) {
584             // add the css file..
585         
586             
587             $files = $this->moduleJavascriptList($mod.'/widgets');
588              foreach($files as $f) {
589                 echo '<script type="text/javascript" src="'. $f. '"></script>'."\n";
590             }
591             
592             $files = $this->moduleJavascriptList($mod);
593             foreach($files as $f) {
594                 echo '<script type="text/javascript" src="'. $f. '"></script>'."\n";
595             }
596             
597         }
598          
599     }
600      /**
601      * outputCSSIncludes:
602      *
603      * output <link rel=stylesheet......> for all the modules in the applcaiton
604      *
605      */
606     function outputCSSIncludes() // includes on CSS links.
607     {
608         
609         $mods = $this->modulesList();
610         
611         
612         foreach($mods as $mod) {
613             // add the css file..
614             $css = $this->rootDir.'/Pman/'.$mod.'/'.strtolower($mod).'.css';
615             if (file_exists( $css)){
616                 $css = $this->rootURL .'/Pman/'.$mod.'/'.strtolower($mod).'.css';
617                 echo '<link rel="stylesheet" type="text/css" href="'.$css.'" />'."\n";
618             }
619              
620             
621         }
622          
623     }
624       
625     /**
626      * Gather infor for javascript files..
627      *
628      * @param {String} $mod the module to get info about.
629      * @return {StdClass}  details about module.
630      */
631     function moduleJavascriptFilesInfo($mod)
632     {
633         
634         static $cache = array();
635         
636         if (isset($cache[$mod])) {
637             return $cache[$mod];
638         }
639         
640         
641         $ff = HTML_FlexyFramework::get();
642         
643         $base = dirname($_SERVER['SCRIPT_FILENAME']);
644         $dir =   $this->rootDir.'/Pman/'. $mod;
645         $path = $this->rootURL ."/Pman/$mod/";
646         
647         $ar = glob($dir . '/*.js');
648         
649         $files = array();
650         $arfiles = array();
651         $maxtime = 0;
652         $mtime = 0;
653         foreach($ar as $fn) {
654             $f = basename($fn);
655             // got the 'module file..'
656             $mtime = filemtime($dir . '/'. $f);
657             $maxtime = max($mtime, $maxtime);
658             $arfiles[$fn] = $mtime;
659             $files[] = $path . $f . '?ts='.$mtime;
660         }
661         
662         ksort($arfiles); // just sort by name so it's consistant for serialize..
663         
664         $compile  = empty($ff->Pman['public_cache_dir']) ? 0 : 1;
665         $basedir = $ff->Pman['public_cache_dir'];
666         $baseurl = $ff->Pman['public_cache_url'];
667         
668         $lsort = create_function('$a,$b','return strlen($a) > strlen($b) ? 1 : -1;');
669         usort($files, $lsort);
670         
671         $smod = str_replace('/','.',$mod);
672         
673         $output = date('Y-m-d-H-i-s-', $maxtime). $smod .'-'.md5(serialize($arfiles)) .'.js';
674         
675         $tmtime = file_exists($this->rootDir.'/_translations_/'. $smod.'.js')
676             ? filemtime($this->rootDir.'/_translations_/'. $smod.'.js') : 0;
677         
678         $cache[$mod]  = (object) array(
679             'smod' =>               $smod, // module name without '/'
680             'files' =>              $files, // list of all files.
681             'filesmtime' =>         $arfiles,  // map of mtime=>file
682             'maxtime' =>            $maxtime, // max mtime
683             'compile' =>            $this->isDev ? false : $compile,
684             'translation_file' =>   $base .'/_translations_/' . $smod .  '.js',
685             'translation_mtime' =>  $tmtime,
686             'output' =>             $output,
687             'translation_data' =>   preg_replace('/\.js$/', '.__translation__.js', $output),
688             'translation_base' =>   $dir .'/', //prefix of filename (without moudle name))
689             'basedir' =>            $basedir,   
690             'baseurl' =>            $baseurl,
691             'module_dir' =>         $dir,  
692         );
693         return $cache[$mod];
694     }
695      
696     
697     /**
698      *  moduleJavascriptList: list the javascript files in a module
699      *
700      *  The original version of this.. still needs more thought...
701      *
702      *  Compiled is in Pman/_compiled_/{$mod}/{LATEST...}.js
703      *  Translations are in Pman/_translations_/{$mod}.js
704      *  
705      *  if that stuff does not exist just list files in  Pman/{$mod}/*.js
706      *
707      *  Compiled could be done on the fly..
708      * 
709      *
710      *
711      *  @param {String} $mod  the module to look at - eg. Pman/{$mod}/*.js
712      *  @return {Array} list of include paths (either compiled or raw)
713      *
714      */
715
716     
717     
718     function moduleJavascriptList($mod)
719     {
720         
721         
722         $dir =   $this->rootDir.'/Pman/'. $mod;
723         
724         
725         if (!file_exists($dir)) {
726             echo '<!-- missing directory '. htmlspecialchars($dir) .' -->';
727             return array();
728         }
729         
730         $info = $this->moduleJavascriptFilesInfo($mod);
731        
732         
733           
734         if (empty($info->files)) {
735             return array();
736         }
737         // finally sort the files, so they are in the right order..
738         
739         // only compile this stuff if public_cache is set..
740         
741          
742         // suggestions...
743         //  public_cache_dir =   /var/www/myproject_cache
744         //  public_cache_url =   /myproject_cache    (with Alias apache /myproject_cache/ /var/www/myproject_cache/)
745         
746         // bit of debugging
747         if (!$info->compile) {
748             echo "<!-- Javascript compile turned off (isDev on, or public_cache_dir not set) -->\n";
749             return $info->files;
750         }
751         // where are we going to write all of this..
752         // This has to be done via a 
753         if (!file_exists($info->basedir.'/'.$info->output)) {
754             require_once 'Pman/Core/JsCompile.php';
755             $x = new Pman_Core_JsCompile();
756             
757             $x->pack($info->filesmtime,$info->basedir.'/'.$info->output, $info->translation_base);
758         }
759         
760         if (file_exists($info->basedir.'/'.$info->output) &&
761                 filesize($info->basedir.'/'.$info->output)) {
762             
763             $ret =array(
764                 $info->baseurl.'/'. $info->output,
765               
766             );
767             if ($info->translation_mtime) {
768                 $ret[] = $this->rootURL."/_translations_/". $info->smod.".js?ts=".$info->translation_mtime;
769             }
770             return $ret;
771         }
772         
773         
774         
775         // give up and output original files...
776         
777          
778         return $info->files;
779
780         
781     }
782     
783     
784     
785     /**
786      * ---------------- Logging ---------------   
787      */
788     
789     /**
790      * addEventOnce:
791      * Log an action (only if it has not been logged already.
792      * 
793      * @param {String} action  - group/name of event
794      * @param {DataObject|false} obj - dataobject action occured on.
795      * @param {String} any remarks
796      * @return {false|DB_DataObject} Event object.,
797      */
798     
799     function addEventOnce($act, $obj = false, $remarks = '') 
800     {
801         
802         $e = DB_DataObject::factory('Events');
803         $e->init($act,$obj,$remarks); 
804         if ($e->find(true)) {
805             return false;
806         }
807         return $this->addEvent($act, $obj, $remarks);
808     }
809     /**
810      * addEvent:
811      * Log an action.
812      * 
813      * @param {String} action  - group/name of event
814      * @param {DataObject|false} obj - dataobject action occured on.
815      * @param {String} any remarks
816      * @return {DB_DataObject} Event object.,
817      */
818     
819     function addEvent($act, $obj = false, $remarks = '') 
820     {
821         $au = $this->getAuthUser();
822        
823         $e = DB_DataObject::factory('Events');
824         $e->init($act,$obj,$remarks); 
825          
826         $e->event_when = date('Y-m-d H:i:s');
827         
828         $eid = $e->insert();
829         
830         $wa = DB_DataObject::factory('core_watch');
831         $wa->notifyEvent($e); // trigger any actions..
832         
833         
834         $ff  = HTML_FlexyFramework::get();
835         if (empty($ff->Pman['event_log_dir'])) {
836             return $e;
837         }
838         $file = $ff->Pman['event_log_dir']. date('/Y/m/d/'). $eid . ".php";
839         if (!file_exists(dirname($file))) {
840             mkdir(dirname($file),0700,true);
841         }
842         file_put_contents($file, var_export(array(
843             'REQUEST_URI' => empty($_SERVER['REQUEST_URI']) ? 'cli' : $_SERVER['REQUEST_URI'],
844             'GET' => empty($_GET) ? array() : $_GET,
845             'POST' => empty($_POST) ? array() : $_POST,
846         ), true));
847          
848         return $e;
849         
850     }
851     // ------------------ DEPERCIATED ---
852      
853     function modules() // DEPRECITAED
854     {
855         return $this->modulesList(); 
856     }
857     function staticGetAuthUser() // DEPRECIATED..
858     {
859         
860         $x = new Pman();
861         return $x->getAuthUser();
862         
863     }
864      
865     
866 }