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