Generator.php
[Pman.Core] / Generator.php
1 <?php
2  
3  
4 /**
5  * 
6  * Generate DataObjects...
7  * 
8  * This does not generate ini files any more - as that is done on the fly by the framework.
9  * 
10  * note - we write to a temporary directory first...
11  * 
12  * 
13  */
14  
15 require_once 'DB/DataObject/Generator.php';
16
17
18 /** basic thing now works... 
19
20 * it needs a bit more intelligence to work out what to do...
21
22
23 * Basically we need to build up all the formats for each db column
24 * then 
25 *   - overlay any mapping stuff.
26 *   
27 *   - overlay user defined settings
28 *   = write it out to file..
29 *   
30 *  Strucutres:
31 $this->def['order'][$table][] = $t->name;
32 $this->def['readers'][$table][$t->name] = $reader;
33 $this->def['colmodels'][$table][$t->name] = $colmodel;
34 $this->def['forms'][$table][$t->name] = $form;
35
36 *   Readers
37 *       readersDef[table.col]
38
39
40
41 * **/
42
43
44
45 class Pman_Core_Generator extends DB_DataObject_Generator
46 {
47     
48
49    
50     // inherrited..
51     // $tablekeys
52     // $tables
53     // $_definitions
54     /**
55      * def[order]  
56      *      [tablename] => array( list of columns ones with '-' indicate lookup
57      *    [readers]
58      *       [tablename][colname] -> reader foramt
59      *    [forms]
60      *        [tablename][colname] => xtype / name etc...
61      *    [readerArgs]
62      *        [tablename] => data for reader args (eg. id / total prop etc.)
63      *  readers =>
64      *         [tablename] => array of cols with types
65      *  forms =>
66      *        [tablename] -> array of cols
67      * 
68      */ 
69     var $def;
70     
71       
72     var $page = false; // page container when run from cli.
73     
74     // dont do usual stuff!!!
75     var $rootDir = '';
76     var $tablekeys = array();
77     
78     var $overwrite = array(); // default dont overwrite any of the files..
79     //  array('master', 'corejs', 'corephp', 'index', 'Roo')
80     // and ('js-?????' where ??? is the table name) <- for all the generated js classes.
81     // we always overwrite the definition!!!
82     // set to array('all') to overwrite everything!!!
83     
84     function start($cli=false, $mods='', $overwrite='')
85     {
86         
87         $ff = HTML_Flexyframework::get();
88         $this->scanModules();
89         //echo '<PRE>'; print_r($this->modtables); exit;
90         
91         $options = &PEAR::getStaticProperty('DB_DataObject','options');
92         
93         
94         $proj = 'pman'; //ucfirst(basename($options['database']));
95         // we are going to generate all of the code into a temporay foldler..
96         $user = posix_getpwuid(posix_getuid());
97         
98         $options['rootDir'] = ini_get('session.save_path').'/temp_'. $proj.'_'. $user['name'];
99         $options['cli'] = $cli;
100         $options['mods'] = empty($mods) ? array() : explode('/',$mods);
101        
102         if (!file_exists($options['rootDir'])) {
103             mkdir($options['rootDir'], 0775, true);
104         }
105         
106         $this->rootDir = $options['rootDir'];
107         $options['schema_location'] =  $this->rootDir .'/'.$proj.'/DataObjects';
108         $options['class_location'] = $this->rootDir .'/'.$proj.'/DataObjects';
109         $options['require_prefix'] =    $proj . '/DataObjects/';
110         $options['class_prefix'] =    $proj . '_DataObjects_';
111        //  print_r($this);exit;
112        
113        
114         $this->importSQL();
115        
116         $standard_database = $options['database'];
117        
118        
119        
120        
121        
122        
123        
124        
125        
126         parent::start();
127         
128         $this->scanModules();
129         require_once 'System.php';
130         $diff = System::which('diff');
131         // now for each of the directories copy/show diffs..
132         echo $cli ? '' : '<PRE>';
133         $flist = explode(',', $overwrite);
134         foreach($this->modtables as $m=>$ar) {
135             if ($options['database'] !=  $standard_database) {
136                 $options['database'] =  $standard_database ;
137                 
138                 parent::start();
139             }
140             
141             $options['database'] =  $standard_database ;
142             if (isset($options['database_'. $m])) {
143                 $options['database'] =  $options['database_'. $m];
144                 //var_dump($url);exit;
145                 
146                 // start again?
147                 parent::start();
148             }
149             
150             
151             if (!empty($options['mods'] ) && !in_array($m,  $options['mods'] )) {
152                 continue;
153             }
154             
155             
156             foreach(scandir($options['rootDir'].'/'.$m) as $f) {
157                 if (!strlen($f) || $f[0] == '.') {
158                     continue;
159                 }
160                 // does it exist!!!
161                 $src = $options['rootDir']."/$m/$f";
162                 $tg = $ff->page->rootDir."/Pman/$m/DataObjects/$f";
163                 if (preg_match('/\.js$/', $f)) {
164                     $tg = $ff->page->rootDir."/Pman/$m/$f";
165                 }
166                 
167                 if (!file_exists($tg) || !filesize($tg) ) {
168                   
169                     if ($cli && !filesize($tg) || in_array($f, $flist)) {
170                         echo "COPY $src $tg" . ($cli ? "\n" : "<BR>");
171                         copy($src, $tg);
172                         continue;
173                     }
174                     echo "!!!!MISSING!!! $tg" . ($cli ? "\n" : "<BR>");
175                     
176                     continue;
177                 }
178                 // always copy readers and ini file.=  nope - not on live..
179                 if ($cli && in_array($f, $flist)) {
180                     
181                    //|| $f=='pman.ini' || preg_match('/\.js$/', $f))) {
182                     echo "COPY $src $tg". ($cli ? "\n" : "<BR>");
183                     copy($src, $tg);
184                     continue;
185                 }
186                 
187                 // diff the two..
188                 $cmd = "$diff -u -w ". escapeshellarg($tg) . ' ' . escapeshellarg($src);
189                  
190                 $out = array(); $ret = 0;
191                 exec($cmd, $out, $ret);
192                 if ($ret ==0) { // files match..
193                     continue;
194                 }
195                 // var_dump($ret);
196                 echo "\n" .implode( "\n" , $out) . "\n";
197                
198                 
199             }
200             
201             
202         }
203         
204         
205         
206         
207     }
208     /**
209      * imports SQL files from all DataObjects directories....
210      * 
211      * except any matching /migrate/
212      */
213     function importSQL()
214     {
215         $options = &PEAR::getStaticProperty('DB_DataObject','options');
216         
217         $ff = HTML_Flexyframework::get();
218         
219         $url = parse_url($options['database']);
220         // hide stuff for web..
221         $cli = $options['cli'];
222         if (!$cli) {
223             $url['pass'] = '*****';
224             $url['user'] = '*****';
225             $url['host'] = '*****';
226         }
227         
228         require_once 'System.php';
229         $cat = System::which('cat');
230         $mysql = System::which('mysql');
231         print_r($options['mods'] );
232         foreach($this->modsql as $m => $fl)
233         {
234             if ($cli && isset($options['database_'. $m])) {
235                 $url = parse_url($options['database_'.$m]);
236             }
237             
238             $mysql_cmd = $mysql .
239                 ' -h ' . $url['host'] .
240                 ' -u' . escapeshellarg($url['user']) .
241                 (!empty($url['pass']) ? ' -p' . escapeshellarg($url['pass'])  :  '') .
242                 ' ' . basename($url['path']);
243            
244             echo $mysql_cmd . "\n" ;
245             
246             if (!empty($options['mods'] ) && !in_array($m,  $options['mods'] )) {
247                 continue;
248             }
249             
250             foreach($fl as $f) {
251                 $fn = $ff->page->rootDir. "/Pman/$m/DataObjects/$f";
252                 if (preg_match('/migrate/i', $f)) { // skip migration scripts at present..
253                     continue;
254                 }
255                 
256                 $cmd = $cat . ' ' . escapeshellarg($fn) . " | $mysql_cmd -f ";
257                 echo $cmd. ($cli ? "\n" : "<BR>\n");
258                 if ($cli) {
259                     passthru($cmd);
260                 }
261                 
262             }
263         }
264         
265         
266         
267     }
268     /**
269      * Scan the folders for DataObjects
270      * - Use the list of php files in DataObjects folders 
271      *   to determine which module owns which database table.
272      * 
273      */
274     
275     
276     function scanModules()
277     {
278         
279         $options = &PEAR::getStaticProperty('DB_DataObject','options');
280         if (isset($options['modtables'])) {
281             $this->modtables = $options['modtables'];
282             $this->modmap = $options['modmap'];
283             $this->modsql = $options['modsql'];
284             return;
285         }
286         
287         $ff = HTML_Flexyframework::get();
288         
289         $top = $ff->page->rootDir .'/Pman';
290         $this->modtables = array();
291         $this->modmap = array();
292         $this->modmapsql = array();
293         
294         foreach(scandir($top) as $m) {
295             
296             if (!strlen($m) || 
297                     $m[0] == '.' || 
298                     !is_dir($top .'/'.$m) || 
299                     !file_exists($top .'/'.$m.'/DataObjects')
300                 ) {
301                 continue;
302             }
303             $this->modtables[$m] = array();
304             $this->modsql[$m] = array();
305             foreach(scandir($top .'/'.$m.'/DataObjects') as $f) {
306                 if (!strlen($f) ||   $m[0] == '.') {
307                     continue;
308                 }
309                 if (preg_match('/\.sql$/', $f))  {
310                     $this->modsql[$m][] = $f;
311                 }
312                                 
313                 if (preg_match('/\.php$/', $f))  {
314                     $tn = strtolower(preg_replace('/\.php$/', '', $f));
315                     $this->modtables[$m][] = $tn;
316                     $this->modmap[$tn] = $m;
317                     continue;
318                 }
319             }
320         }
321         $options['modtables'] = $this->modtables;
322         $options['modmap'] = $this->modmap;
323         $options['modsql'] = $this->modsql;
324        // print_r($options);
325         
326     }
327     /**
328      * 
329      * this is run first, so picks up any missing dataobject files..
330      */
331     
332     function generateDefinitions()
333     {
334         if (!$this->tables) {
335             $this->debug("-- NO TABLES -- \n");
336             return;
337         }
338         if (!isset($this->modmap)) {
339             $this->scanModules();
340         }
341          $options = &PEAR::getStaticProperty('DB_DataObject','options');
342         $builder_options = PEAR::getStaticProperty('Pman_Builder','options');
343         $ignore = empty($builder_options['skip_tables']) ? array() : $builder_options['skip_tables'];
344         
345          $mods = $options['mods'];
346         $inis = array();
347         $this->_newConfig = '';
348         foreach($this->tables as $this->table) {
349             
350             $tn  = strtolower($this->table);
351             //print_r($this->modmap);//[$tn]);//
352             
353             
354             
355             if (!isset($this->modmap[$tn])) {
356                 
357                 if (in_array($this->table, $ignore)) {
358                     continue;
359                 }
360                 if (empty($mods)) {
361                 
362                 
363                    die("No existing DataObject file found for table {$this->table} 
364             
365 - either add it to Pman_Builder[skip_tables] or\n
366 - run generator and specify that module..
367 - create an empty file in the related Module/DataObjects directory
368 eg. 
369 touch Pman/????/DataObjects/".ucfirst($this->table).".php
370    
371    ");
372                 }
373                 // use mods to determine where it should output to..
374                 //var_dump($mods);exit;
375                 $this->modmap[$tn] = $mods[0];
376                 
377                 
378             }
379             $mod = $this->modmap[$tn];
380             $inis[$mod] = isset($inis[$mod]) ? $inis[$mod] : '';
381             
382             
383             $this->_newConfig = '';
384             $this->_generateDefinitionsTable();
385             
386             
387             $inis[$mod] .= $this->_newConfig;
388         }
389         return; // we do not generate in ifiles any more..
390          
391     }
392     
393     function generateClasses() 
394     {
395       // print_R($this->modmap);
396        // die("generateClasses");
397         $options = &PEAR::getStaticProperty('DB_DataObject','options');
398         
399         $ff = HTML_Flexyframework::get();
400         
401         $rd = $options['rootDir'];
402         $mods = $options['mods'];
403         $this->_extends = 'DB_DataObject';
404         $this->_extendsFile = 'DB/DataObject.php';
405         $cli = $options['cli'];
406
407         foreach($this->tables as $this->table) {
408             $this->table        = trim($this->table);
409             $tn  = strtolower($this->table);
410             $mod = $this->modmap[$tn];
411             
412              if (!empty($mods) && !in_array($mod, $mods)) {
413                 continue;
414             }
415             
416             
417             $this->classname    = 'Pman_'.$mod . '_DataObjects_'. ucfirst($this->table); // replace odd chars?
418            
419            
420             $outfilename    = $rd.'/'.$mod.'/'. ucfirst($this->table).'.php';
421             $orig           = $ff->page->rootDir .'/Pman/'.$mod.'/DataObjects/'. ucfirst($this->table).'.php';
422             
423            
424                 // file_get_contents???
425             
426             $oldcontents = file_exists($orig) ? file_get_contents($orig) : '';
427             
428              
429             echo "GENERATE: " .   $this->classname  . ($cli ? "\n" : "<BR>");
430             
431             $out = $this->_generateClassTable($oldcontents);
432             
433             // get rid of static GET!!!
434             $out = preg_replace('/(\n|\r\n)\s*function staticGet[^\n]+(\n|\r\n)/s', '', $out);
435             $out = preg_replace('#/\* Static get \*/#s', '', $out);
436               
437             if (!file_exists(dirname($outfilename))) {
438                 mkdir(dirname($outfilename), 0755, true);
439             }
440            // $this->debug( "writing $this->classname\n");
441             //$tmpname = tempnam(session_save_path(),'DataObject_');
442             file_put_contents($outfilename, $out);
443             
444         }
445     }
446     
447     
448         
449    // function generateDefinitions() { }
450     ////function generateForeignKeys() { }
451    // function generateClasses() { }
452    
453       
454      
455      
456    
457     function parseConfig()
458     {
459          $options = &PEAR::getStaticProperty('DB_DataObject','options');
460         
461         if (isset($options['modtables'])) {
462             $this->modtables = $options['modtables'];
463             $this->modmap = $options['modmap'];
464             $this->modsql = $options['modsql'];
465         }
466         
467         $ff = HTML_Flexyframework::get();
468         $dirs = array($ff->page->rootDir.'/Pman/DataObjects'); // not used anymore!
469         foreach($this->modtables as $m=>$ts) {
470             $dirs[] = $ff->page->rootDir.'/Pman/'.$m.'/DataObjects';
471         }
472         
473          //echo '<PRE>';print_R($ini);//exit;
474         
475         
476          
477     }
478      
479         //var_dump($table);
480         //print_r( $this->def['readers'][$table]);
481        // print_r( $this->def['colmodels'][$table]);
482         //print_r($this->def['readers'][$table]); exit;
483         
484       
485        
486     function writeFileEx($n, $f, $str) 
487     {
488         if (file_exists($f)) {
489             // all - will not overwrite stuff.. (only being specific willl)
490             if (!in_array($n, $this->overwrite)) {
491                 $this->writeFile($f.'.generated',$str);
492                 return;
493             }
494         }
495         $this->writeFile($f,$str);
496         
497         
498     }
499     function writeFile($f, $str)
500     {
501         require_once 'System.php';
502         System::mkdir(array('-p', dirname($f)));
503         // overwrite???
504         echo "write: $f\n";
505         file_put_contents($f, $str);
506     } 
507    
508 }
509