Generator.php
[Pman.Core] / 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_Core_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($options['mods'] );
228         foreach($this->modsql as $m => $fl)
229         {
230             if ($cli && isset($options['database_'. $m])) {
231                 $url =parse_url($options['database_'.$m]);
232             }
233             
234             $mysql_cmd = $mysql .
235                 ' -h ' . $url['host'] .
236                 ' -u' . escapeshellarg($url['user']) .
237                 (!empty($url['pass']) ? ' -p' . escapeshellarg($url['pass'])  :  '') .
238                 ' ' . basename($url['path']);
239            
240             echo $mysql_cmd . "\n" ;
241             
242             if (!empty($options['mods'] ) && !in_array($m,  $options['mods'] )) {
243                 continue;
244             }
245             
246             foreach($fl as $f) {
247                 $fn = $ff->page->rootDir. "/Pman/$m/DataObjects/$f";
248                 $cmd = $cat . ' ' . escapeshellarg($fn) . " | $mysql_cmd -f ";
249                 echo $cmd. ($cli ? "\n" : "<BR>\n");
250                 if ($cli) {
251                     passthru($cmd);
252                 }
253                 
254             }
255         }
256         
257         
258         
259     }
260     /**
261      * Scan the folders for DataObjects
262      * - Use the list of php files in DataObjects folders 
263      *   to determine which module owns which database table.
264      * 
265      */
266     
267     
268     function scanModules()
269     {
270         
271         $options = &PEAR::getStaticProperty('DB_DataObject','options');
272         if (isset($options['modtables'])) {
273             $this->modtables = $options['modtables'];
274             $this->modmap = $options['modmap'];
275             $this->modsql = $options['modsql'];
276             return;
277         }
278         
279         $ff = HTML_Flexyframework::get();
280         
281         $top = $ff->page->rootDir .'/Pman';
282         $this->modtables = array();
283         $this->modmap = array();
284         $this->modmapsql = array();
285         
286         foreach(scandir($top) as $m) {
287             
288             if (!strlen($m) || 
289                     $m[0] == '.' || 
290                     !is_dir($top .'/'.$m) || 
291                     !file_exists($top .'/'.$m.'/DataObjects')
292                 ) {
293                 continue;
294             }
295             $this->modtables[$m] = array();
296             $this->modsql[$m] = array();
297             foreach(scandir($top .'/'.$m.'/DataObjects') as $f) {
298                 if (!strlen($f) ||   $m[0] == '.') {
299                     continue;
300                 }
301                 if (preg_match('/\.sql$/', $f))  {
302                     $this->modsql[$m][] = $f;
303                 }
304                                 
305                 if (preg_match('/\.php$/', $f))  {
306                     $tn = strtolower(preg_replace('/\.php$/', '', $f));
307                     $this->modtables[$m][] = $tn;
308                     $this->modmap[$tn] = $m;
309                     continue;
310                 }
311             }
312         }
313         $options['modtables'] = $this->modtables;
314         $options['modmap'] = $this->modmap;
315         $options['modsql'] = $this->modsql;
316        // print_r($options);
317         
318     }
319     /**
320      * 
321      * this is run first, so picks up any missing dataobject files..
322      */
323     
324     function generateDefinitions()
325     {
326         if (!$this->tables) {
327             $this->debug("-- NO TABLES -- \n");
328             return;
329         }
330         if (!isset($this->modmap)) {
331             $this->scanModules();
332         }
333          $options = &PEAR::getStaticProperty('DB_DataObject','options');
334         $builder_options = PEAR::getStaticProperty('Pman_Builder','options');
335         $ignore = empty($builder_options['skip_tables']) ? array() : $builder_options['skip_tables'];
336         
337          $mods = $options['mods'];
338         $inis = array();
339         $this->_newConfig = '';
340         foreach($this->tables as $this->table) {
341             
342             $tn  = strtolower($this->table);
343             //print_r($this->modmap);//[$tn]);//
344             
345             
346             
347             if (!isset($this->modmap[$tn])) {
348                 
349                 if (in_array($this->table, $ignore)) {
350                     continue;
351                 }
352              
353              
354                 die("No existing DataObject file found for table {$this->table} 
355                 
356 - either add it to Pman_Builder[skip_tables] or\n
357 - create an empty file in the related Module/DataObjects directory
358 eg. 
359 touch Pman/????/DataObjects/".ucfirst($this->table).".php
360
361 ");
362                     
363             }
364             $mod = $this->modmap[$tn];
365             $inis[$mod] = isset($inis[$mod]) ? $inis[$mod] : '';
366             
367             
368             $this->_newConfig = '';
369             $this->_generateDefinitionsTable();
370             
371             
372             $inis[$mod] .= $this->_newConfig;
373         }
374         
375         //echo '<PRE>';print_r($this->_inis); exit;
376         $options = PEAR::getStaticProperty('DB_DataObject','options');
377         
378         $rd = $options['rootDir'];
379         foreach($inis as $m=>$ini) {
380             if (!empty($mods) && !in_array($m, $mods)) {
381                 continue;
382             }
383             
384             if (!file_exists($rd.'/'.$m)) {
385                 mkdir($rd.'/'.$m, 0775, true);
386             }
387             $fname = '/pman.ini';
388             if (isset($options['database_'. $m])) {
389                 $url = parse_url($options['database_'.$m]);
390                 $fname = '/'. basename($url['path']).'.ini';
391             }
392
393             
394             file_put_contents($rd.'/'.$m.$fname, $ini);
395         }
396          
397          
398     }
399     
400     function generateClasses() 
401     {
402       // print_R($this->modmap);
403        // die("generateClasses");
404         $options = &PEAR::getStaticProperty('DB_DataObject','options');
405         
406         $ff = HTML_Flexyframework::get();
407         
408         $rd = $options['rootDir'];
409         $mods = $options['mods'];
410         $this->_extends = 'DB_DataObject';
411         $this->_extendsFile = 'DB/DataObject.php';
412         $cli = $options['cli'];
413
414         foreach($this->tables as $this->table) {
415             $this->table        = trim($this->table);
416             $tn  = strtolower($this->table);
417             $mod = $this->modmap[$tn];
418             
419              if (!empty($mods) && !in_array($mod, $mods)) {
420                 continue;
421             }
422             
423             
424             $this->classname    = 'Pman_'.$mod . '_DataObjects_'. ucfirst($this->table); // replace odd chars?
425            
426            
427             $outfilename    = $rd.'/'.$mod.'/'. ucfirst($this->table).'.php';
428             $orig           = $ff->page->rootDir .'/Pman/'.$mod.'/DataObjects/'. ucfirst($this->table).'.php';
429             
430            
431                 // file_get_contents???
432             $oldcontents = file_get_contents($orig);
433             
434              
435             echo "GENERATE: " .   $this->classname  . ($cli ? "\n" : "<BR>");
436             
437             $out = $this->_generateClassTable($oldcontents);
438             
439             // get rid of static GET!!!
440             $out = preg_replace('/(\n|\r\n)\s*function staticGet[^\n]+(\n|\r\n)/s', '', $out);
441             $out = preg_replace('#/\* Static get \*/#s', '', $out);
442               
443
444            // $this->debug( "writing $this->classname\n");
445             //$tmpname = tempnam(session_save_path(),'DataObject_');
446             file_put_contents($outfilename, $out);
447             
448         }
449     }
450     
451     
452         
453    // function generateDefinitions() { }
454     ////function generateForeignKeys() { }
455    // function generateClasses() { }
456    
457       
458      
459      
460    
461     function parseConfig()
462     {
463          $options = &PEAR::getStaticProperty('DB_DataObject','options');
464         
465         if (isset($options['modtables'])) {
466             $this->modtables = $options['modtables'];
467             $this->modmap = $options['modmap'];
468             $this->modsql = $options['modsql'];
469         }
470         
471         $ff = HTML_Flexyframework::get();
472         $dirs = array($ff->page->rootDir.'/Pman/DataObjects'); // not used anymore!
473         foreach($this->modtables as $m=>$ts) {
474             $dirs[] = $ff->page->rootDir.'/Pman/'.$m.'/DataObjects';
475         }
476         
477          //echo '<PRE>';print_R($ini);//exit;
478         
479         
480          
481     }
482      
483         //var_dump($table);
484         //print_r( $this->def['readers'][$table]);
485        // print_r( $this->def['colmodels'][$table]);
486         //print_r($this->def['readers'][$table]); exit;
487         
488       
489        
490     function writeFileEx($n, $f, $str) 
491     {
492         if (file_exists($f)) {
493             // all - will not overwrite stuff.. (only being specific willl)
494             if (!in_array($n, $this->overwrite)) {
495                 $this->writeFile($f.'.generated',$str);
496                 return;
497             }
498         }
499         $this->writeFile($f,$str);
500         
501         
502     }
503     function writeFile($f, $str)
504     {
505         require_once 'System.php';
506         System::mkdir(array('-p', dirname($f)));
507         // overwrite???
508         echo "write: $f\n";
509         file_put_contents($f, $str);
510     } 
511    
512 }
513