re-enable readers - used by meta somewhere I think
[pear] / HTML / FlexyFramework2 / Generator.php
1 <?php
2
3
4 /**
5  * This works by creating '_generate** methods, which are called by start()
6  * 
7  */
8
9 require_once 'PDO/DataObject/Generator.php';
10
11
12 class HTML_FlexyFramework2_Generator extends PDO_DataObject_Generator 
13 {
14     // block class generation.
15     static $generateClasses = false;
16     
17     function generateClasses()
18     {
19 //        echo "GENERATE CLASSES?";
20         if (!HTML_FlexyFramework2_Generator::$generateClasses ) {
21             return;
22         }
23        
24         //echo "GENERATE CLASSES?";
25         parent::generateClasses();
26     }
27     
28     
29     function generateReaders()
30     {
31         $options = PDO_DataObject::config();
32         
33         $out = array();
34         foreach($this->tables as $table) {
35               
36             $out = array_merge($out, $this->_generateReader($table));
37             
38             
39         }
40            
41         file_put_contents($options["schema_location"] . '.reader', serialize($out));
42          
43     }
44     
45     function generatePhp ()
46     {
47         // NOOP 
48     }
49     
50     /**
51      * Generate the cached readers used for meta data in the queries.
52      * 
53      */
54     function _generateReader($table)
55     {
56         $DB = $this->PDO();
57         $dbtype = $DB->getAttribute(PDO::ATTR_DRIVER_NAME);;
58          
59         $ret = array();
60         foreach($table->columns as $t) {
61              switch (strtoupper($t->type)) {
62
63                 case 'INT':
64                 case 'INT2':    // postgres
65                 case 'INT4':    // postgres
66                 case 'INT8':    // postgres
67                 case 'SERIAL4': // postgres
68                 case 'SERIAL8': // postgres
69                 case 'INTEGER':
70                 case 'TINYINT':
71                 case 'SMALLINT':
72                 case 'MEDIUMINT':
73                 case 'BIGINT':
74                 // wierd ones..
75                 case 'YEAR':
76                 
77                     $ret[$table->table.'.'.$t->name] = array('type' => 'int');
78                     continue 2;
79                
80                 case 'REAL':
81                 case 'DOUBLE':
82                 case 'DOUBLE PRECISION': // double precision (firebird)
83                 case 'FLOAT':
84                 case 'FLOAT4': // real (postgres)
85                 case 'FLOAT8': // double precision (postgres)
86                 case 'DECIMAL':
87                 case 'MONEY':  // mssql and maybe others
88                 case 'NUMERIC':
89                 case 'NUMBER': // oci8 
90                     $ret[$table->table.'.'.$t->name] = array('type' => 'float'); //???
91                     break;
92                     
93                 case 'BIT':
94                 case 'BOOL':   
95                 case 'BOOLEAN':   
96                     $ret[$table->table.'.'.$t->name] = array('type' => 'boolean'); //???
97                     // postgres needs to quote '0'
98                     if ($dbtype == 'pgsql') {
99                         ///$type +=  DB_DATAOBJECT_STR;
100                     }
101                     break;
102                     
103                 case 'STRING':
104                 case 'CHAR':
105                 case 'VARCHAR':
106                 case 'VARCHAR2':
107                 case 'TINYTEXT':
108                 
109                 case 'ENUM':
110                 case 'SET':         // not really but oh well
111                 
112                 case 'POINT':       // mysql geometry stuff - not really string - but will do..
113                 
114                 case 'TIMESTAMPTZ': // postgres
115                 case 'BPCHAR':      // postgres
116                 case 'INTERVAL':    // postgres (eg. '12 days')
117                 
118                 case 'CIDR':        // postgres IP net spec
119                 case 'INET':        // postgres IP
120                 case 'MACADDR':     // postgress network Mac address.
121                 
122                 case 'INTEGER[]':   // postgres type
123                 case 'BOOLEAN[]':   // postgres type
124                 
125                 
126                 case 'TEXT':
127                 case 'MEDIUMTEXT':
128                 case 'LONGTEXT':
129                 case 'BLOB':       /// these should really be ignored!!!???
130                 case 'TINYBLOB':
131                 case 'MEDIUMBLOB':
132                 case 'LONGBLOB':
133                 
134                 case 'CLOB': // oracle character lob support
135                 
136                 case 'BYTEA':   // postgres blob support..
137                     $ret[$table->table.'.'.$t->name] =  $t->name; // strings are not sent as arrays..
138                    // $type = DB_DATAOBJECT_STR;
139                     break;
140                 
141                 
142                 
143                 
144                 case 'DATE':    
145                     $ret[$table->table.'.'.$t->name] = array('type' => 'date', 'dateFormat' => 'Y-m-d'); //???
146                     break;
147                     
148                 case 'TIME':    
149                     $ret[$table->table.'.'.$t->name] = $t->name; // technically not...
150                     break;    
151                     
152                 
153                 case 'DATETIME': 
154                     $ret[$table->table.'.'.$t->name] = array('type' => 'date', 'dateFormat' => 'Y-m-d H:i:s'); //???
155                     break;    
156                     
157                 case 'TIMESTAMP': // do other databases use this???
158                     
159                     $ret[$table->table.'.'.$t->name] =   ($dbtype == 'mysql') ?
160                          array('type' => 'float') : 
161                         array('type' => 'date', 'dateFormat' => 'Y-m-d H:i:s');
162                     break;    
163                     
164                 
165                 
166                     
167                     
168                 default:     
169                     $ret[$table->table.'.'.$t->name] = $t->name;
170                     break;
171             }
172         }
173         
174         return $ret;
175         
176         
177     }
178     /**
179      * Generate the cached *.ini and links.ini files (merged for all components)
180      * 
181      */
182     static function writeCache($iniCacheTmp, $iniCache, $replace = array())
183     {
184         
185         $fp = fopen($iniCache.".lock", "a+");
186         flock($fp,LOCK_EX);
187
188         $ff = HTML_FlexyFramework2::get();
189         $ff->debug('Framework Generator:writeCache ' . $iniCacheTmp .  ' ' . $iniCache);
190           
191         //var_dump($iniCacheTmp);
192        // echo '<PRE>';echo file_get_contents($iniCacheTmp);exit;
193         // only unpdate if nothing went wrong.
194         if (file_exists($iniCacheTmp) && filesize($iniCacheTmp)) {
195             // is the replace file exist?
196             if (!isset($replace[$iniCache]) || $replace[$iniCache] != md5_file($iniCacheTmp)) {
197             
198             
199                 if (file_exists($iniCache)) {
200                     unlink($iniCache);
201                 }
202                 $ff->debug("Writing merged ini file : $iniCache\n");
203                 rename($iniCacheTmp, $iniCache);
204             } else {
205                 touch($iniCache);
206             }
207         }
208          // readers..??? not needed??? (historical)
209         if (file_exists($iniCacheTmp.'.reader') &&  filesize($iniCacheTmp.'.reader')) {
210             
211             
212             if (file_exists($iniCache.'.reader') ) {
213                 if ($replace[$iniCache] != md5_file($iniCacheTmp.'.reader')) {
214                     unlink($iniCache.'.reader');
215                     rename($iniCacheTmp.'.reader', $iniCache.'.reader');
216                 } else {
217                     // do not need to touch..
218                     unlink($iniCacheTmp.'.reader');
219                 }
220             } else {
221                 rename($iniCacheTmp.'.reader', $iniCache.'.reader');
222             }
223         
224              
225         }
226         
227         // merge and set links.. test for generated links file..
228         
229         $linksCacheTmp = preg_replace('/\.ini/', '.links.ini', $iniCacheTmp );
230         $links = array();
231         if (file_exists($linksCacheTmp )) {
232             $links = self::mergeIni( parse_ini_file($linksCacheTmp, true), $links);
233             unlink($linksCacheTmp);
234         }
235         // we are going to use the DataObject directories..
236         
237         $inis = explode(PATH_SEPARATOR,$ff->PDO_DataObject['class_location']);
238         //print_r($inis);exit;
239         $ff->debug("class_location = ". $ff->PDO_DataObject['class_location']);
240         
241         
242         $lproject = strtolower(explode('/', $ff->project)[0]);
243         
244         foreach($inis as $path) {
245             $ini = $path . '/'. strtolower( $lproject ) . '.links.ini';
246              //var_dump($ini);
247             if (!file_exists($ini)) {
248                 $ff->debug("Framework Generator:writeCache PROJECT.links.ini does not exist in $path - trying glob");
249        
250                 // try scanning the directory for another ini file..
251                 $ar = glob(dirname($ini).'/*.links.ini');
252                 
253                 
254                 if (empty($ar)) {
255                     continue;
256                 }
257                 
258                 
259                 sort($ar);
260                 $ff->debug("Framework Generator:writeCache using {$ar[0]}");
261                 
262                 // first file.. = with links removed..
263                 $ini = preg_replace('/\.links\./' , '.', $ar[0]);
264                 $ini = preg_replace('/\.ini$/', '.links.ini', $ini);
265             }
266             
267             // why do this twice???
268             if (!file_exists($ini)) {
269                 continue;
270             }
271             $ff->debug("Adding in $ini");
272             // prefer first ?
273             $links = self::mergeIni( parse_ini_file($ini, true), $links);   
274         }
275         $iniLinksCache = preg_replace('/\.ini$/', '.links.ini', $iniCache);
276         $out = array();
277         foreach($links as $tbl=>$ar) {
278             $out[] = '['. $tbl  .']';
279             foreach ($ar as $k=>$v) {
280                 $out[] = $k . '=' .$v;
281             }
282             $out[] = '';
283         }
284         if (count($out)) {
285             $ff->debug("Writing merged Links file : $iniLinksCache \n");
286             $out_str = implode("\n", $out);
287             // is target file different?
288             if (!isset($replace[$iniLinksCache]) || $replace[$iniLinksCache] != md5($out)) {
289           
290                  file_put_contents($iniCacheTmp. '.links.ini', $out_str);
291                  if (file_exists($iniLinksCache)) {                
292                      unlink($iniLinksCache);
293                  }
294                  rename($iniCacheTmp. '.links.ini', $iniLinksCache);
295             } else {
296                 touch($iniLinksCache);
297                 
298             }
299         } // we ignore that we might need to delete old links.ini
300         
301         flock($fp, LOCK_UN);
302         fclose($fp);
303         
304         clearstatcache();
305         
306         if(file_exists($iniCache.".lock")){
307             unlink($iniCache.".lock");
308         }
309         
310     }
311     /* bit like merge recursive, but it avoids doing stuff with arrays.. */
312     static function mergeIni($new, $old) 
313     {
314         foreach($new as $g => $ar) {
315             if (!isset($old[$g])) {
316                 $old[$g] = $ar;
317                 continue;
318             }
319             foreach($ar as $k=>$v) {
320                 if (isset($old[$g][$k])) {
321                     continue;
322                 }
323                 $old[$g][$k] = $v;
324             }
325         }
326         return $old;
327         
328         
329     }
330     
331 }