Generator.php
[Pman.Builder] / Generator.php
1 <?php
2  
3  
4 /**
5  * 
6  * Generate DataObjects... and readers in the right places..
7  * 
8  * note - we write to a temporary directory first...
9  * 
10  * 
11  */
12  
13 require_once 'DB/DataObject/Generator.php';
14
15
16 /** basic thing now works... 
17
18 * it needs a bit more intelligence to work out what to do...
19
20
21 * Basically we need to build up all the formats for each db column
22 * then 
23 *   - overlay any mapping stuff.
24 *   
25 *   - overlay user defined settings
26 *   = write it out to file..
27 *   
28 *  Strucutres:
29 $this->def['order'][$table][] = $t->name;
30 $this->def['readers'][$table][$t->name] = $reader;
31 $this->def['colmodels'][$table][$t->name] = $colmodel;
32 $this->def['forms'][$table][$t->name] = $form;
33
34 *   Readers
35 *       readersDef[table.col]
36
37
38
39 * **/
40
41
42
43 class Pman_Builder_Generator extends DB_DataObject_Generator
44 {
45     
46
47    
48     // inherrited..
49     // $tablekeys
50     // $tables
51     // $_definitions
52     /**
53      * def[order]  
54      *      [tablename] => array( list of columns ones with '-' indicate lookup
55      *    [readers]
56      *       [tablename][colname] -> reader foramt
57      *    [forms]
58      *        [tablename][colname] => xtype / name etc...
59      *    [readerArgs]
60      *        [tablename] => data for reader args (eg. id / total prop etc.)
61      *  readers =>
62      *         [tablename] => array of cols with types
63      *  forms =>
64      *        [tablename] -> array of cols
65      * 
66      */ 
67     var $def;
68     
69       
70     var $page = false; // page container when run from cli.
71     
72     // dont do usual stuff!!!
73     var $rootDir = '';
74     var $tablekeys = array();
75     
76     var $overwrite = array(); // default dont overwrite any of the files..
77     //  array('master', 'corejs', 'corephp', 'index', 'Roo')
78     // and ('js-?????' where ??? is the table name) <- for all the generated js classes.
79     // we always overwrite the definition!!!
80     // set to array('all') to overwrite everything!!!
81     
82     function start($cli=false, $mods='', $overwrite='')
83     {
84         
85         $ff = HTML_Flexyframework::get();
86         $this->scanModules();
87         //echo '<PRE>'; print_r($this->modtables); exit;
88         
89         $options = &PEAR::getStaticProperty('DB_DataObject','options');
90         
91         
92         $proj = 'pman'; //ucfirst(basename($options['database']));
93         // we are going to generate all of the code into a temporay foldler..
94         $options['rootDir'] = ini_get('session.save_path').'/temp_'. $proj;
95         $options['cli'] = $cli;
96         $options['mods'] = empty($mods) ? array() : explode('/',$mods);
97        
98         if (!file_exists($options['rootDir'])) {
99             mkdir($options['rootDir'], 0775, true);
100         }
101         
102         $this->rootDir = $options['rootDir'];
103         $options['schema_location'] =  $this->rootDir .'/'.$proj.'/DataObjects';
104         $options['class_location'] = $this->rootDir .'/'.$proj.'/DataObjects';
105         $options['require_prefix'] =    $proj . '/DataObjects/';
106         $options['class_prefix'] =    $proj . '_DataObjects_';
107        //  print_r($this);exit;
108        
109        
110         $this->importSQL();
111        
112         $standard_database = $options['database'];
113        
114        
115        
116        
117        
118        
119        print_r($ff);exit;
120        
121        
122        
123         parent::start();
124         
125         $this->scanModules();
126         require_once 'System.php';
127         $diff = System::which('diff');
128         // now for each of the directories copy/show diffs..
129         echo $cli ? '' : '<PRE>';
130         $flist = explode(',', $overwrite);
131         foreach($this->modtables as $m=>$ar) {
132             if ($options['database'] !=  $standard_database) {
133                 $options['database'] =  $standard_database ;
134                 
135                 parent::start();
136             }
137             
138             $options['database'] =  $standard_database ;
139             if (isset($options['database_'. $m])) {
140                 $options['database'] =  $options['database_'. $m];
141                 //var_dump($url);exit;
142                 
143                 // start again?
144                 parent::start();
145             }
146             
147             
148             if (!empty($options['mods'] ) && !in_array($m,  $options['mods'] )) {
149                 continue;
150             }
151             foreach(scandir($options['rootDir'].'/'.$m) as $f) {
152                 if (!strlen($f) || $f[0] == '.') {
153                     continue;
154                 }
155                 // does it exist!!!
156                 $src = $options['rootDir']."/$m/$f";
157                 $tg = $ff->page->rootDir."/Pman/$m/DataObjects/$f";
158                 if (preg_match('/\.js$/', $f)) {
159                     $tg = $ff->page->rootDir."/Pman/$m/$f";
160                 }
161                 
162                 if (!file_exists($tg) || !filesize($tg) ) {
163                   
164                     if ($cli && in_array($f, $flist)) {
165                        echo "COPY $src $tg" . ($cli ? "\n" : "<BR>");
166                         copy($src, $tg);
167                         continue;
168                     }
169                     echo "!!!!MISSING!!! $tg" . ($cli ? "\n" : "<BR>");
170                     
171                     continue;
172                 }
173                 // always copy readers and ini file.=  nope - not on live..
174                 if ($cli && in_array($f, $flist)) {
175                     
176                    //|| $f=='pman.ini' || preg_match('/\.js$/', $f))) {
177                     echo "COPY $src $tg". ($cli ? "\n" : "<BR>");
178                     copy($src, $tg);
179                     continue;
180                 }
181                 
182                 // diff the two..
183                 $cmd = "$diff -u -w ". escapeshellarg($tg) . ' ' . escapeshellarg($src);
184                  
185                 $out = array(); $ret = 0;
186                 exec($cmd, $out, $ret);
187                 if ($ret ==0) { // files match..
188                     continue;
189                 }
190                 // var_dump($ret);
191                 echo "\n" .implode( "\n" , $out) . "\n";
192                
193                 
194             }
195             
196             
197         }
198         
199         
200         
201         
202     }
203     
204     
205     
206     function importSQL()
207     {
208         $options = &PEAR::getStaticProperty('DB_DataObject','options');
209         
210         $ff = HTML_Flexyframework::get();
211         
212         $url = parse_url($options['database']);
213         // hide stuff for web..
214         $cli = $options['cli'];
215         if (!$cli) {
216             $url['pass'] = '*****';
217             $url['user'] = '*****';
218             $url['host'] = '*****';
219         }
220          
221         
222         
223         require_once 'System.php';
224         $cat = System::which('cat');
225         $mysql = System::which('mysql');
226         print_r($options['mods'] );
227         foreach($this->modsql as $m => $fl)
228         {
229             if ($cli && isset($options['database_'. $m])) {
230                 $url =parse_url($options['database_'.$m]);
231             }
232             
233             $mysql_cmd = $mysql .
234                 ' -h ' . $url['host'] .
235                 ' -u' . escapeshellarg($url['user']) .
236                 (!empty($url['pass']) ? ' -p' . escapeshellarg($url['pass'])  :  '') .
237                 ' ' . basename($url['path']);
238            
239             echo $mysql_cmd . "\n" ;
240             
241             if (!empty($options['mods'] ) && !in_array($m,  $options['mods'] )) {
242                 continue;
243             }
244             
245             foreach($fl as $f) {
246                 $fn = $ff->page->rootDir. "/Pman/$m/DataObjects/$f";
247                 $cmd = $cat . ' ' . escapeshellarg($fn) . " | $mysql_cmd -f ";
248                 echo $cmd. ($cli ? "\n" : "<BR>\n");
249                 if ($cli) {
250                     passthru($cmd);
251                 }
252                 
253             }
254         }
255         
256         
257         
258     }
259     /**
260      * Scan the folders for DataObjects
261      * - Use the list of php files in DataObjects folders 
262      *   to determine which module owns which database table.
263      * 
264      */
265     
266     
267     function scanModules()
268     {
269         
270         $options = &PEAR::getStaticProperty('DB_DataObject','options');
271         if (isset($options['modtables'])) {
272             $this->modtables = $options['modtables'];
273             $this->modmap = $options['modmap'];
274             $this->modsql = $options['modsql'];
275             return;
276         }
277         
278         $ff = HTML_Flexyframework::get();
279         
280         $top = $ff->page->rootDir .'/Pman';
281         $this->modtables = array();
282         $this->modmap = array();
283         $this->modmapsql = array();
284         
285         foreach(scandir($top) as $m) {
286             
287             if (!strlen($m) || 
288                     $m[0] == '.' || 
289                     !is_dir($top .'/'.$m) || 
290                     !file_exists($top .'/'.$m.'/DataObjects')
291                 ) {
292                 continue;
293             }
294             $this->modtables[$m] = array();
295             $this->modsql[$m] = array();
296             foreach(scandir($top .'/'.$m.'/DataObjects') as $f) {
297                 if (!strlen($f) ||   $m[0] == '.') {
298                     continue;
299                 }
300                 if (preg_match('/\.sql$/', $f))  {
301                     $this->modsql[$m][] = $f;
302                 }
303                                 
304                 if (preg_match('/\.php$/', $f))  {
305                     $tn = strtolower(preg_replace('/\.php$/', '', $f));
306                     $this->modtables[$m][] = $tn;
307                     $this->modmap[$tn] = $m;
308                     continue;
309                 }
310             }
311         }
312         $options['modtables'] = $this->modtables;
313         $options['modmap'] = $this->modmap;
314         $options['modsql'] = $this->modsql;
315        // print_r($options);
316         
317     }
318     /**
319      * 
320      * this is run first, so picks up any missing dataobject files..
321      */
322     
323     function generateDefinitions()
324     {
325         if (!$this->tables) {
326             $this->debug("-- NO TABLES -- \n");
327             return;
328         }
329         if (!isset($this->modmap)) {
330             $this->scanModules();
331         }
332          $options = &PEAR::getStaticProperty('DB_DataObject','options');
333          $mods = $options['mods'];
334         $inis = array();
335         $this->_newConfig = '';
336         foreach($this->tables as $this->table) {
337             
338             $tn  = strtolower($this->table);
339             //print_r($this->modmap);//[$tn]);//
340             if (!isset($this->modmap[$tn])) {
341                 die("No existing DataObject file found for table {$this->table} \n".
342                     "- create an empty file in the related Module/DataObjects directory
343                     eg. 
344                     touch Pman/????/DataObjects/".ucfirst($this->table).".php
345                    \n");
346                     
347             }
348             $mod = $this->modmap[$tn];
349             $inis[$mod] = isset($inis[$mod]) ? $inis[$mod] : '';
350             
351             
352             $this->_newConfig = '';
353             $this->_generateDefinitionsTable();
354             
355             
356             $inis[$mod] .= $this->_newConfig;
357         }
358         
359         //echo '<PRE>';print_r($this->_inis); exit;
360         $options = PEAR::getStaticProperty('DB_DataObject','options');
361         
362         $rd = $options['rootDir'];
363         foreach($inis as $m=>$ini) {
364             if (!empty($mods) && !in_array($m, $mods)) {
365                 continue;
366             }
367             
368             if (!file_exists($rd.'/'.$m)) {
369                 mkdir($rd.'/'.$m, 0775, true);
370             }
371             $fname = '/pman.ini';
372             if (isset($options['database_'. $m])) {
373                 $url = parse_url($options['database_'.$m]);
374                 $fname = '/'. basename($url['path']).'.ini';
375             }
376
377             
378             file_put_contents($rd.'/'.$m.$fname, $ini);
379         }
380          
381          
382     }
383     
384     function generateClasses() 
385     {
386       // print_R($this->modmap);
387        // die("generateClasses");
388         $options = &PEAR::getStaticProperty('DB_DataObject','options');
389         
390         $ff = HTML_Flexyframework::get();
391         
392         $rd = $options['rootDir'];
393         $mods = $options['mods'];
394         $this->_extends = 'DB_DataObject';
395         $this->_extendsFile = 'DB/DataObject.php';
396         $cli = $options['cli'];
397
398         foreach($this->tables as $this->table) {
399             $this->table        = trim($this->table);
400             $tn  = strtolower($this->table);
401             $mod = $this->modmap[$tn];
402             
403              if (!empty($mods) && !in_array($mod, $mods)) {
404                 continue;
405             }
406             
407             
408             $this->classname    = 'Pman_'.$mod . '_DataObjects_'. ucfirst($this->table); // replace odd chars?
409            
410            
411             $outfilename    = $rd.'/'.$mod.'/'. ucfirst($this->table).'.php';
412             $orig           = $ff->page->rootDir .'/Pman/'.$mod.'/DataObjects/'. ucfirst($this->table).'.php';
413             
414            
415                 // file_get_contents???
416             $oldcontents = file_get_contents($orig);
417             
418              
419             echo "GENERATE: " .   $this->classname  . ($cli ? "\n" : "<BR>");
420             
421             $out = $this->_generateClassTable($oldcontents);
422             
423             // get rid of static GET!!!
424             $out = preg_replace('/(\n|\r\n)\s*function staticGet[^\n]+(\n|\r\n)/s', '', $out);
425             $out = preg_replace('#/\* Static get \*/#s', '', $out);
426               
427
428            // $this->debug( "writing $this->classname\n");
429             //$tmpname = tempnam(session_save_path(),'DataObject_');
430             file_put_contents($outfilename, $out);
431             
432         }
433     }
434     
435     
436         
437    // function generateDefinitions() { }
438     ////function generateForeignKeys() { }
439    // function generateClasses() { }
440    
441     var $jsHeader = "//<script type=\"text/javascript\">\n";
442         
443     function generateRoo()
444     {
445          
446         $options = &PEAR::getStaticProperty('DB_DataObject','options');
447          $mods = $options['mods'];
448         $this->rootDir = $options['rootDir'];
449         $this->overwrite = true;
450         //$this->parseOld();
451         
452         require_once 'Pman/Builder/Generator/JSON.php';
453         
454         $ret = '//<script type="text/javascript">'."\n";
455         
456       
457         foreach($this->tables as $this->table) {
458             $this->_generateData($this->table);
459         }
460         
461         
462        //echo '<PRE>';print_R($this->def);
463         $this->parseConfig();
464          
465         
466         
467          
468         $ds = $this->_database;
469         $ds = ucfirst($this->_database);
470        
471         // we always write these files....
472         foreach($this->modtables as $m=>$ts) {
473              if (!empty($mods) && !in_array($m, $mods)) {
474                 continue;
475             }
476              
477             file_put_contents($this->rootDir."/$m/$m.readers.js", $this->_generateReaders($m));
478            
479         }
480       
481     }
482     
483     
484     
485     
486      
487     
488     function _generateReaders($m)
489     {
490          
491         $udb = ucfirst($this->_database);
492         $ret = $this->jsHeader;
493         $j = new Pman_Builder_Generator_JSON();
494         $j->indent = 0;
495         
496         $j2 = new Pman_Builder_Generator_JSON(array('crlf' => '', 'tab' => ''));
497         
498         
499         foreach($this->tables as $this->table) {
500             
501             
502             if ($this->modmap[strtolower($this->table)] != $m) {
503                 continue;
504             }
505             
506             $utable = ucfirst($this->table);
507             
508             $r =  $this->def['readers'][$this->table];
509             foreach($r as $k=>$tab) {
510                 if ($tab['type'] == 'string') {
511                     $r[$k] = $tab['name'];
512                 }
513             }
514             $this->readersArgs[$this->table]['xtype'] = 'JsonReader';
515             $ret.="\n$udb.Readers.$utable = ";
516             $x = $j->encodeUnsafe($this->readersArgs[$this->table]);
517             $ret .=  trim(substr($x, 0, -1)) . ",\n"; // strip of trailing ;};
518             $ret .=  $j->tab . "fields : [\n". $j->tab.$j->tab;
519             $ar = array();
520             foreach($r as $xr) {
521                 $ar[] = $j2->encodeUnsafe($xr);
522             }
523             $ret .= implode(",\n". $j->tab.$j->tab, $ar);
524             $ret .= "\n".  $j->tab . "]\n};\n";
525             
526         }
527         return $ret;
528    
529     }
530     /**
531      * tableToData:
532      * Generic covert databse data to readers etc..
533      * usage:
534      * $x = DB_DataObject::factory('anytable');
535      * $def = $x->getDatabaseConnection()->tableInfo($table);
536      * $mydata = Generator::tableToData($table, $def);
537      * 
538      * returns tablekey, args(for reader header), order, readers, colmodels, forms.
539      * 
540      * 
541      * 
542      */
543      
544     function tableToData($table, $def)
545     {
546         
547       
548         
549         $ret= array(
550             'tablekey' => '',   //$this->tablekeys[$this->table] 
551             'args' => array(    // was retiun..
552                 'root' => 'data',
553                 'totalProperty' => 'total',
554                 'id' => 'id', // primary key!!?
555             ),
556             'order' => array(),
557             'readers' => array(),
558             'colmodels' => array(),
559             'forms' => array()
560             
561         );
562          
563         $readers = array( );
564         $colmodels = array();
565         $form  = array();
566         $utable = ucfirst($table);
567         //$this->tablekeys[$this->table] = '';
568         
569         foreach($def as $t) {
570             if (is_array($t)) {
571                 $t = (object)$t;
572             }
573             $reader = array(
574                 'name' => $t->name,
575             );
576             
577             $colmodel = array(
578                 'id' => str_replace('_', '-', strtolower($utable.'-'.$t->name)),
579                 'header' => ucfirst($t->name), // get from somewhere?!!?!?
580                 'dataIndex' => $t->name,
581                 'sortable' => true,
582                 'width' => 150,
583                 //'editor' => 
584             );
585             $felement = array(
586                 'name' => $t->name,
587                 'fieldLabel' => str_replace(array('_id', '_'), array('', ' '), ucfirst($t->name)),
588                 'value' => '',
589                 'allowBlank' =>  preg_match('/not_null/i', $t->flags) ? false : true,
590                 'qtip' => 'Enter '. $t->name ,
591             );
592
593                 
594             switch (strtoupper($t->type)) {
595
596                 case 'INT':
597                 case 'INT2':    // postgres
598                 case 'INT4':    // postgres
599                 case 'INT8':    // postgres
600                 case 'SERIAL4': // postgres
601                 case 'SERIAL8': // postgres
602                 case 'INTEGER':
603                 case 'TINYINT':
604                 case 'SMALLINT':
605                 case 'MEDIUMINT':
606                 case 'BIGINT':
607                     $colmodel['width'] = 100;
608                     $reader['type'] = 'int';
609                     $felement['xtype'] = 'NumberField';
610                      $felement['allowDecimals'] = false;
611                     if ($t->len == 1) {
612                         $reader['type'] = 'boolean';
613                     }
614                     break;
615                
616                 case 'REAL':
617                 case 'DOUBLE':
618                 case 'DOUBLE PRECISION': // double precision (firebird)
619                 case 'FLOAT':
620                 case 'FLOAT4': // real (postgres)
621                 case 'FLOAT8': // double precision (postgres)
622                 case 'DECIMAL':
623                 case 'MONEY':  // mssql and maybe others
624                 case 'NUMERIC':
625                 case 'NUMBER': // oci8 
626                     $reader['type']  = 'float'; // should really by FLOAT!!! / MONEY...
627                     
628                     $colmodel['width'] = 100;
629                     $felement['xtype'] = 'NumberField';
630                     break;
631                     
632                 case 'YEAR':
633                     $reader['type']  = 'int'; 
634                     $felement['allowDecimals'] = false;
635                     $felement['xtype'] = 'NumberField';
636                     break;
637                     
638                 case 'BIT':
639                 case 'BOOL':   
640                 case 'BOOLEAN':   
641                     $colmodel['width'] = 50;
642                     $reader['type']  =  'boolean';
643                     $felement['xtype'] = 'CheckBox';
644                     // postgres needs to quote '0'
645                    
646                     break;
647                     
648                 case 'STRING':
649                 case 'CHAR':
650                 case 'VARCHAR':
651                 case 'VARCHAR2':
652                 case 'TINYTEXT':
653                 
654                 case 'ENUM':
655                 case 'SET':         // not really but oh well
656                 
657                 case 'POINT':       // mysql geometry stuff - not really string - but will do..
658                 
659                 case 'TIMESTAMPTZ': // postgres
660                 case 'BPCHAR':      // postgres
661                 case 'INTERVAL':    // postgres (eg. '12 days')
662                 
663                 case 'CIDR':        // postgres IP net spec
664                 case 'INET':        // postgres IP
665                 case 'MACADDR':     // postgress network Mac address.
666                 
667                 case 'INTEGER[]':   // postgres type
668                 case 'BOOLEAN[]':   // postgres type
669                   
670                     $colmodel['width'] = isset($t->len) ? max(50, min(floor($t->len * 10), 300)) : 10;
671                     // editor - $colmodel['allowBlank'] = preg_match('/not_null/i', $t->flags) ? false, true;
672                     $reader['type']  = 'string';
673                     $felement['xtype'] = 'TextField';
674                     break;
675                 
676                 case 'TEXT':
677                 case 'MEDIUMTEXT':
678                 case 'LONGTEXT':
679                     $colmodel['width'] =  300;
680                     $reader['type']  = 'string';
681                     $felement['xtype'] = 'TextArea'; // or HtmlEditor
682                     $felement['height'] = 100;
683                     break;
684                 
685                 
686                 case 'DATE':    
687                     $colmodel['width'] =  100;
688                     ///$colmodel['renderer'] =  
689                     
690                     $reader['type']  = 'date';
691                     $reader['dateFormat']   = 'Y-m-d';
692                     $felement['xtype'] = 'DateField'; 
693                     
694                     $felement['altFormats'] = 'Y-m-d|d/m/Y';
695                     $felement['format'] = 'd/m/Y';
696                     $felement['hiddenFormat'] = 'Y-m-d'; // not supported ATM
697         
698                     break;
699                     
700                 case 'TIME':    
701                     $colmodel['width'] = 100;
702                     ///$colmodel['renderer'] =  
703                     $reader['type']  = 'string';
704                     $felement['xtype'] = 'TextField';
705                     break;    
706                     
707                 
708                 case 'DATETIME': 
709                      $colmodel['width'] =  100;
710                     ///$colmodel['renderer'] =  
711                     $reader['type']  = 'date';
712                     $reader['dateFormat']   = 'Y-m-d H:i:s';
713                     $felement['xtype'] = 'TextField';
714                     $felement['readOnly'] = 'true';
715                      
716         
717                     
718                     break;    
719                     
720                 case 'TIMESTAMP': // do other databases use this???
721                      $colmodel['width'] =  100;
722                     ///$colmodel['renderer'] =  
723                     $reader['type']  = 'date';
724                     $reader['dateFormat']   = 'YmdHis';
725                     $felement['xtype'] = 'TextField';
726                     $felement['readOnly'] = 'true'; 
727                     break;    
728                     
729                 
730                 case 'BLOB':       /// these should really be ignored!!!???
731                 case 'TINYBLOB':
732                 case 'MEDIUMBLOB':
733                 case 'LONGBLOB':
734                 
735                 case 'CLOB': // oracle character lob support
736                 
737                 case 'BYTEA':   // postgres blob support..
738                     $colmodel['width'] =  300;
739                     $reader['type']  = 'string';
740                     $felement['xtype'] = 'TextArea'; // or HtmlEditor
741                     $felement['height'] = 100;
742                     break;
743                     
744                 default:     
745                     echo "*****************************************************************\n".
746                          "**               WARNING UNKNOWN TYPE                          **\n".
747                          "** Found column '{$t->name}', of type  '{$t->type}'            **\n".
748                          "** Please submit a bug, describe what type you expect this     **\n".
749                          "** column  to be                                               **\n".
750                          "** ---------POSSIBLE FIX / WORKAROUND -------------------------**\n".
751                          "** Try using MDB2 as the backend - eg set the config option    **\n".
752                          "** db_driver = MDB2                                            **\n".
753                          "*****************************************************************\n";
754                     $write_ini = false;
755                     break;
756             }
757             
758             if (preg_match('/(auto_increment|nextval\()/i',rawurldecode($t->flags)) 
759                 || (isset($t->autoincrement) && ($t->autoincrement === true))) {
760                     
761                 if (empty($ret['tablekeys'])) {
762                     $ret['tablekeys'] = $t->name;
763                 }
764                  
765             
766             }
767             
768             
769             
770              
771             // form inherits from users' colmodel width..
772             $felement['width'] = $colmodel['width'];
773             
774             //$readers[] = $reader;
775             //$colmodels[] = $colmodel;
776             if ($ret['tablekey'] == $t->name) {
777                 // do allow id to be 
778                 $felement['xtype'] = 'Hidden';
779                 unset($felement['allowBlank']);
780                 unset($felement['fieldLabel']);
781                 
782                 
783                 
784                 
785             } else {
786                 // only put id in the key col.
787                 unset($colmodel['id']);
788             }
789             // hidden elemetns do not need any display components..
790             if ($felement['xtype'] == 'Hidden') {
791                 foreach($felement as $k=>$v) {
792                     if (!in_array($k , array('name', 'xtype'))) {
793                         unset($felement[$k]);
794                     }
795                 }
796                  
797             }
798             
799            // $form[] = $felement;
800            
801             // store the globals
802             $ret['order'][] = $t->name;
803             $ret['readers'][$t->name] = $reader;
804             $ret['colmodels'][$t->name] = $colmodel;
805             $ret['forms'][$t->name] = $felement;
806             
807              
808         }
809         //$ret['args'] = $args;
810         
811         return $ret;
812         
813     }
814      
815     function _generateData($table)
816     {
817          
818         $args = array(
819             'root' => 'data',
820             'totalProperty' => 'total',
821             'id' => 'id', // primary key!!?
822         );
823          
824         $d = $this->tableToData($this->_definitions[$table]);
825         
826         $this->tablekeys[$this->table]  = $d['tablekey'];
827         
828             // $form[] = $felement;
829            
830             // store the globals
831         $this->def['order'][$table] = $d['order'];
832         $this->def['readers'][$table]= $d['readers'];
833         $this->def['colmodels'][$table] = $d['colmodes'];
834         $this->def['forms'][$table] = $d['forms'];
835         
836         $this->readersArgs[$table]   = $d['args'];
837         
838         
839         
840     }
841     
842      
843      
844    
845     function parseConfig()
846     {
847          $options = &PEAR::getStaticProperty('DB_DataObject','options');
848         
849         if (isset($options['modtables'])) {
850             $this->modtables = $options['modtables'];
851             $this->modmap = $options['modmap'];
852             $this->modsql = $options['modsql'];
853         }
854         
855         $ff = HTML_Flexyframework::get();
856         $dirs = array($ff->page->rootDir.'/Pman/DataObjects'); // not used anymore!
857         foreach($this->modtables as $m=>$ts) {
858             $dirs[] = $ff->page->rootDir.'/Pman/'.$m.'/DataObjects';
859         }
860         $ini = array('database__render' => array());
861         foreach($dirs as $d) {
862             if (!file_exists($d.'/pman.links.ini')) {
863                 continue;
864             }
865             $in = parse_ini_file($d.'/pman.links.ini',true);
866             $r = array();
867             if (isset($in['database__render'])) {
868                 $r = $in['database__render'];
869                 unset($in['database__render']);
870             }
871             $ini = array_merge($ini, $in);
872             $ini['database__render'] = array_merge($ini['database__render'] , $r);
873         }
874          //echo '<PRE>';print_R($ini);//exit;
875         
876         
877         if (!isset($ini['database__render'])) {
878             die("database__render not available in links files.");
879             return;
880         }
881         $this->mapcols = array();
882         foreach($ini as $tab=>$conf) {
883             if ($tab == 'database__render') {
884                 continue;
885             }
886             $this->mergeConfig($tab,$conf,$ini['database__render']);
887              
888         }
889         $this->renderMap = $ini['database__render'];
890     }
891     function mergeConfig($table, $conf, $render)
892     {
893         $this->mapcols[$table] = array();
894         $options = &PEAR::getStaticProperty('DB_DataObject','options');
895         if (isset($options['modtables'])) {
896             $this->modtables = $options['modtables'];
897             $this->modmap = $options['modmap'];
898             $this->modsql = $options['modsql'];
899         }
900         
901         
902         foreach($conf as $ocol=>$info) {
903             // format col => showval..
904             //list($rtc, $rshow) = explode(':', $info);
905             list($tab,$col) = explode(':', $info);
906             //print_r($render);
907             $rshow = $render[$tab];
908             
909             $this->mapcols[$table][$ocol] = array('table'=>$tab, 'col' => $col);
910             
911             // for the grid...
912             
913             // reader:
914             //- just add an extra line..
915             if (!isset($this->def['readers'][$tab][$rshow])){
916                 echo "WARNING in links.ini TABLE $tab does not have renderer $rshow <BR>\n";
917                 continue;
918             }
919             
920             // for the readers.. we need to merge all the columns in the left to the right...
921             
922             // table => original
923             // ocol => column in table
924             // tab => remote table
925             // col => right col linked to...
926             
927             $rdef = $this->_definitions[$tab];
928             
929             
930             foreach($rdef as $t) {
931                 //copy typedata from old coll
932                 $this->def['readers'][$table][$ocol.'-'. $t->name] = $this->def['readers'][$tab][$t->name];
933                 $this->def['readers'][$table][$ocol.'-'. $t->name]['name'] = $ocol.'_'. $t->name;
934             }
935             
936             
937             
938             
939             
940             // remove the def column from the id one..
941             if (isset($this->def['colmodels'][$table][$ocol])) {
942                 unset($this->def['colmodels'][$table][$ocol]);
943             }
944             $this->def['colmodels'][$table][$ocol.'-'. $rshow] = 
945                     $this->def['colmodels'][$tab][$rshow];
946             
947             // change the header name (merge of two..)
948             list($colname,) = explode('_',$ocol,2);
949             
950             $this->def['colmodels'][$table][$ocol.'-'. $rshow]['dataIndex'] = $ocol.'_'. $rshow;
951             $this->def['colmodels'][$table][$ocol.'-'. $rshow]['id'] = $ocol.'-'. $rshow;
952             
953             $this->def['colmodels'][$table][$ocol.'-'. $rshow]['header'] = ucwords($colname . ' ' . 
954                 $this->def['colmodels'][$tab][$rshow]['header']);
955             
956             // last of all add replace the old $col, with 
957             $p = array_search($ocol, empty($this->def['order'][$table]) ? array() : $this->def['order'][$table]);
958             $this->def['order'][$table][$p] = $ocol.'-'. $rshow;
959             $this->def['order'][$table][] = $ocol;
960              
961             // --- now for forms!!!!
962             
963              
964         }
965         //var_dump($table);
966         //print_r( $this->def['readers'][$table]);
967        // print_r( $this->def['colmodels'][$table]);
968         //print_r($this->def['readers'][$table]); exit;
969         
970     }
971         
972        
973     function writeFileEx($n, $f, $str) 
974     {
975         if (file_exists($f)) {
976             // all - will not overwrite stuff.. (only being specific willl)
977             if (!in_array($n, $this->overwrite)) {
978                 $this->writeFile($f.'.generated',$str);
979                 return;
980             }
981         }
982         $this->writeFile($f,$str);
983         
984         
985     }
986     function writeFile($f, $str)
987     {
988         require_once 'System.php';
989         System::mkdir(array('-p', dirname($f)));
990         // overwrite???
991         echo "write: $f\n";
992         file_put_contents($f, $str);
993     } 
994    
995 }
996