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=array())
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         $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 =   $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             // this happens when we have no database tables from a module,
153             // but module code has been defined.
154             if (!file_exists($options['rootDir'].'/'.$m)) {
155                 continue;
156             }
157             foreach(scandir($options['rootDir'].'/'.$m) as $f) {
158                 
159                 echo "SCAN {$options['rootDir']} $f\n";
160                 
161                 if (!strlen($f) || $f[0] == '.') {
162                     continue;
163                 }
164                 // does it exist!!!
165                 $src = $options['rootDir']."/$m/$f";
166                 $tg = $ff->page->rootDir."/Pman/$m/DataObjects/$f";
167                 if (preg_match('/\.js$/', $f)) {
168                     $tg = $ff->page->rootDir."/Pman/$m/$f";
169                 }
170                 
171                 if (!file_exists($tg) || !filesize($tg) ) {
172                   
173                     if ($cli && file_exists($tg) || in_array($f, $flist) || in_array('_all_', $flist )) {
174                         echo "COPY $src $tg" . ($cli ? "\n" : "<BR>");
175                         copy($src, $tg);
176                         continue;
177                     }
178                     echo "!!!!MISSING!!! $tg" . ($cli ? "\n" : "<BR>");
179                     
180                     continue;
181                 }
182                 // always copy readers and ini file.=  nope - not on live..
183                 if ($cli && in_array($f, $flist) || in_array('_all_', $flist )) {
184                     
185                    //|| $f=='pman.ini' || preg_match('/\.js$/', $f))) {
186                     echo "COPY $src $tg". ($cli ? "\n" : "<BR>");
187                     copy($src, $tg);
188                     continue;
189                 }
190                 
191                 // diff the two..
192                 $cmd = "$diff -u -w ". escapeshellarg($tg) . ' ' . escapeshellarg($src);
193                  
194                 $out = array(); $ret = 0;
195                 exec($cmd, $out, $ret);
196                 if ($ret ==0) { // files match..
197                     continue;
198                 }
199                 // var_dump($ret);
200                 echo "\n" .implode( "\n" , $out) . "\n";
201                
202                 
203             }
204             
205             
206         }
207         
208         
209         
210         
211     }
212      
213     /**
214      * Scan the folders for DataObjects
215      * - Use the list of php files in DataObjects folders 
216      *   to determine which module owns which database table.
217      * 
218      */
219     
220     
221     function scanModules()
222     {
223         
224         $options = &PEAR::getStaticProperty('DB_DataObject','options');
225         if (isset($options['modtables'])) {
226             $this->modtables = $options['modtables'];
227             $this->modmap = $options['modmap'];
228             $this->modsql = $options['modsql'];
229             return;
230         }
231         
232         $ff = HTML_Flexyframework::get();
233         
234         $top = $ff->page->rootDir .'/Pman';
235         $this->modtables = array();
236         $this->modmap = array();
237         $this->modmapsql = array();
238         
239         foreach(scandir($top) as $m) {
240             
241             if (!strlen($m) || 
242                     $m[0] == '.' || 
243                     !is_dir($top .'/'.$m) || 
244                     !file_exists($top .'/'.$m.'/DataObjects')
245                 ) {
246                 continue;
247             }
248             $this->modtables[$m] = array();
249             $this->modsql[$m] = array();
250             foreach(scandir($top .'/'.$m.'/DataObjects') as $f) {
251                 if (!strlen($f) ||   $m[0] == '.') {
252                     continue;
253                 }
254                 if (preg_match('/\.sql$/', $f))  {
255                     $this->modsql[$m][] = $f;
256                 }
257                                 
258                 if (preg_match('/\.php$/', $f))  {
259                     $tn = strtolower(preg_replace('/\.php$/', '', $f));
260                     $this->modtables[$m][] = $tn;
261                     $this->modmap[$tn] = $m;
262                     continue;
263                 }
264             }
265         }
266         $options['modtables'] = $this->modtables;
267         $options['modmap'] = $this->modmap;
268         $options['modsql'] = $this->modsql;
269        // print_r($options);
270         
271     }
272     /**
273      * 
274      * this is run first, so picks up any missing dataobject files..
275      */
276     
277     function generateDefinitions()
278     {
279         if (!$this->tables) {
280             $this->debug("-- NO TABLES -- \n");
281             return;
282         }
283         if (!isset($this->modmap)) {
284             $this->scanModules();
285         }
286          $options = &PEAR::getStaticProperty('DB_DataObject','options');
287         $builder_options = PEAR::getStaticProperty('Pman_Builder','options');
288         $ignore = empty($builder_options['skip_tables']) ? array() : $builder_options['skip_tables'];
289         
290          $mods = $options['mods'];
291         $inis = array();
292         $this->_newConfig = '';
293         foreach($this->tables as $this->table) {
294             
295             $tn  = strtolower($this->table);
296             //print_r($this->modmap);//[$tn]);//
297             
298             
299             
300             if (!isset($this->modmap[$tn])) {
301                 
302                 if (in_array($this->table, $ignore)) {
303                     continue;
304                 }
305                 if (empty($mods)) {
306                 
307                 
308                    die("No existing DataObject file found for table {$this->table} 
309             
310 - either add it to Pman_Builder[skip_tables] or\n
311 - run generator and specify that module..
312 - create an empty file in the related Module/DataObjects directory
313 eg. 
314 touch Pman/????/DataObjects/".ucfirst($this->table).".php
315    
316    ");
317                 }
318                 // use mods to determine where it should output to..
319                 //var_dump($mods);exit;
320                 $this->modmap[$tn] = $mods[0];
321                 
322                 
323             }
324             $mod = $this->modmap[$tn];
325             $inis[$mod] = isset($inis[$mod]) ? $inis[$mod] : '';
326             
327             
328             $this->_newConfig = '';
329             $this->_generateDefinitionsTable();
330             
331             
332             $inis[$mod] .= $this->_newConfig;
333         }
334         return; // we do not generate in ifiles any more..
335          
336     }
337     
338     function generateClasses() 
339     {
340       // print_R($this->modmap);
341        // die("generateClasses");
342         $options = &PEAR::getStaticProperty('DB_DataObject','options');
343         
344         $ff = HTML_Flexyframework::get();
345         
346         $rd = $options['rootDir'];
347         $mods = $options['mods'];
348         $this->_extends = 'DB_DataObject';
349         $this->_extendsFile = 'DB/DataObject.php';
350         $cli = $options['cli'];
351
352         foreach($this->tables as $this->table) {
353             
354             $this->table        = trim($this->table);
355             $tn  = strtolower($this->table);
356             $mod = $this->modmap[$tn];
357             
358              if (!empty($mods) && !in_array($mod, $mods)) {
359                 continue;
360             }
361             
362             $clean_table = preg_replace('/[^A-Z0-9]+/i','_',ucfirst(trim($this->table)));
363             
364             $this->classname    = 'Pman_'.$mod . '_DataObjects_'. $clean_table; // replace odd chars?
365            
366            
367             $outfilename    = $rd.'/'.$mod.'/'. $clean_table .'.php';
368             $orig           = $ff->page->rootDir .'/Pman/'.$mod.'/DataObjects/'.  $clean_table.'.php';
369             
370            
371                 // file_get_contents???
372             
373             $oldcontents = file_exists($orig) ? file_get_contents($orig) : '';
374             
375              
376             echo "GENERATE: " .   $this->classname  . ($cli ? "\n" : "<BR>");
377             
378             $out = $this->_generateClassTable($oldcontents);
379             
380             // get rid of static GET!!!
381             $out = preg_replace('/(\n|\r\n)\s*function staticGet[^\n]+(\n|\r\n)/s', '', $out);
382             $out = preg_replace('#/\* Static get \*/#s', '', $out);
383               
384             if (!file_exists(dirname($outfilename))) {
385                 mkdir(dirname($outfilename), 0755, true);
386             }
387            // $this->debug( "writing $this->classname\n");
388             //$tmpname = tempnam(session_save_path(),'DataObject_');
389             file_put_contents($outfilename, $out);
390             
391         }
392     }
393     
394     
395         
396    // function generateDefinitions() { }
397     ////function generateForeignKeys() { }
398    // function generateClasses() { }
399    
400       
401      
402      
403    
404     function parseConfig()
405     {
406          $options = &PEAR::getStaticProperty('DB_DataObject','options');
407         
408         if (isset($options['modtables'])) {
409             $this->modtables = $options['modtables'];
410             $this->modmap = $options['modmap'];
411             $this->modsql = $options['modsql'];
412         }
413         
414         $ff = HTML_Flexyframework::get();
415         $dirs = array($ff->page->rootDir.'/Pman/DataObjects'); // not used anymore!
416         foreach($this->modtables as $m=>$ts) {
417             $dirs[] = $ff->page->rootDir.'/Pman/'.$m.'/DataObjects';
418         }
419         
420          //echo '<PRE>';print_R($ini);//exit;
421         
422         
423          
424     }
425      
426         //var_dump($table);
427         //print_r( $this->def['readers'][$table]);
428        // print_r( $this->def['colmodels'][$table]);
429         //print_r($this->def['readers'][$table]); exit;
430         
431       
432        
433     function writeFileEx($n, $f, $str) 
434     {
435         if (file_exists($f)) {
436             // all - will not overwrite stuff.. (only being specific willl)
437             if (!in_array($n, $this->overwrite)) {
438                 $this->writeFile($f.'.generated',$str);
439                 return;
440             }
441         }
442         $this->writeFile($f,$str);
443         
444         
445     }
446     function writeFile($f, $str)
447     {
448         require_once 'System.php';
449         System::mkdir(array('-p', dirname($f)));
450         // overwrite???
451         echo "write: $f\n";
452         file_put_contents($f, $str);
453     } 
454    
455 }
456