UpdateDatabase.php
[Pman.Core] / UpdateDatabase.php
1 <?php
2
3 /**
4  *
5  * This applies database files from
6  * a) OLD - {MODULE}/DataObjects/XXXX.{dbtype}.sql
7  *
8  * b) NEW - {MODULE}/sql/XXX.sql (SHARED or translable)
9  *  and {MODULE}/{dbtype}/XXX.sql (SHARED or translable)
10  *
11  *
12  */
13
14 require_once 'Pman.php';
15 class Pman_Core_UpdateDatabase extends Pman
16 {
17     
18     static $cli_desc = "Update SQL - Beta (it will run updateData of all modules)";
19  
20     static $cli_opts = array(
21         'source' => array(
22             'desc' => 'Source directory for json files.',
23             'short' => 'f',
24             'default' => '',
25             'min' => 1,
26             'max' => 1,
27         ),
28         'prefix' => array(
29             'desc' => 'prefix for the passwrod',
30             'short' => 'p',
31             'default' => '',
32             'min' => 1,
33             'max' => 1,
34         ),
35         'name' => array(
36             'desc' => 'name of the company',
37             'short' => 'n',
38             'default' => '',
39             'min' => 1,
40             'max' => 1,
41         ),
42         'comptype' => array(
43             'desc' => 'the type of company',
44             'short' => 't',
45             'default' => '',
46             'min' => 1,
47             'max' => 1,
48         )
49         
50     );
51     
52     var $cli = false;
53     function getAuth() {
54         
55         
56         $ff = HTML_FlexyFramework::get();
57         if (!empty($ff->cli)) {
58             $this->cli = true;
59             return true;
60         }
61         
62         parent::getAuth(); // load company!
63         $au = $this->getAuthUser();
64         if (!$au || $au->company()->comptype != 'OWNER') {
65             $this->jerr("Not authenticated", array('authFailure' => true));
66         }
67         $this->authUser = $au;
68         return true;
69     }
70      
71     function get($args, $opt)
72     {
73         if($args == 'Person'){
74             if(empty($opt['source']) || empty($opt['prefix'])){
75                 die("Missing Source directory for person json files or prefix for the passwrod! Try -f [JSON file path] -p [prefix] \n");
76             }
77             if (!file_exists($opt['source'])) {
78                 die("can not found person json file : {$opt['source']} \n");
79             }
80             
81             $persons = json_decode(file_get_contents($opt['source']),true);
82             
83             DB_DataObject::factory('person')->importFromArray($this, $persons, $opt['prefix']);
84             die("DONE! \n");
85         }
86         
87         if($args == 'Company'){
88             if(empty($opt['name']) || empty($opt['comptype'])){
89                 die("Missing company name or type! Try --name=[the name of company] -- comptype=[the type of company] \n");
90             }
91             
92             DB_DataObject::factory('companies')->initCompanies($this, $opt['name'], $opt['comptype']);
93             
94             die("DONE! \n");
95         }
96         
97         $this->importSQL();
98         $this->runUpdateModulesData();
99          
100     }
101     function output() {
102         return '';
103     }
104      /**
105      * imports SQL files from all DataObjects directories....
106      * 
107      * except any matching /migrate/
108      */
109     function importSQL()
110     {
111         
112         $ff = HTML_Flexyframework::get();
113         
114         $url = parse_url($ff->DB_DataObject['database']);
115         
116         $this->{'import' . $url['scheme']}($url);
117         
118     }
119     
120     /**
121      * mysql - does not support conversions.
122      * 
123      *
124      */
125     
126     
127     function importmysqldir($dburl, $dir)
128     {
129         
130         require_once 'System.php';
131         $cat = System::which('cat');
132         $mysql = System::which('mysql');
133         
134        
135            
136         $mysql_cmd = $mysql .
137             ' -h ' . $dburl['host'] .
138             ' -u' . escapeshellarg($dburl['user']) .
139             (!empty($dburl['pass']) ? ' -p' . escapeshellarg($dburl['pass'])  :  '') .
140             ' ' . basename($dburl['path']);
141         echo $mysql_cmd . "\n" ;
142        
143        
144         foreach(glob($dir.'/*.sql') as $fn) {
145                 
146                  
147                 if (preg_match('/migrate/i', basename($fn))) { // skip migration scripts at present..
148                     continue;
149                 }
150                 // .my.sql but not .pg.sql
151                 if (preg_match('#\.[a-z]{2}\.sql#i', basename($fn))
152                     && !preg_match('#\.my\.sql#i', basename($fn))
153                 ) { // skip migration scripts at present..
154                     continue;
155                 }
156                 $cmd = basename($dir).'/'. basename($fn) .    " :: $mysql_cmd -f < " . escapeshellarg($fn) ;
157                 
158                 echo $cmd. ($this->cli ? "\n" : "<BR>\n");
159                 
160                 passthru($cmd);
161             
162                 
163         }
164        
165         
166         
167     }
168     
169     
170     
171     function importmysql($dburl)
172     {
173         
174         // hide stuff for web..
175         $ar = $this->modulesList();
176         
177          
178         
179         // old -- DAtaObjects/*.sql
180         
181         foreach($ar as $m) {
182             
183             $fd = $this->rootDir. "/Pman/$m/DataObjects";
184             
185             $this->importmysqldir($dburl, $fd);
186             
187             // new -- sql directory..
188             // new style will not support migrate ... they have to go into mysql-migrate.... directories..
189             // new style will not support pg.sql etc.. naming - that's what the direcotries are for..
190             
191             $this->importmysqldir($dburl, $this->rootDir. "/Pman/$m/sql");
192             $this->importmysqldir($dburl, $this->rootDir. "/Pman/$m/mysql");
193               
194             
195         }
196         
197         
198         
199     }
200     /**
201      * postgresql import..
202      */
203     function importpgsql($url)
204     {
205         
206         // hide stuff for web..
207         
208         require_once 'System.php';
209         $cat = System::which('cat');
210         $psql = System::which('psql');
211         
212         $ar = $this->modulesList();
213         
214         if (!empty($url['pass'])) { 
215             putenv("PGPASSWORD=". $url['pass']);
216         }
217            
218         $psql_cmd = $psql .
219             ' -h ' . $url['host'] .
220             ' -U' . escapeshellarg($url['user']) .
221              ' ' . basename($url['path']);
222         echo $psql_cmd . "\n" ;
223         
224         
225         
226         
227         foreach($ar as $m) {
228             
229             $fd = $this->rootDir. "/Pman/$m/DataObjects";
230             
231             foreach(glob($fd.'/*.sql') as $bfn) {
232                 
233                  
234                 if (preg_match('/migrate/i', basename($bfn))) { // skip migration scripts at present..
235                     continue;
236                 }
237                 if (preg_match('#\.[a-z]{2}\.sql#i', basename($bfn))
238                     && !preg_match('#\.pg\.sql#i', basename($bfn))
239                 ) { // skip migration scripts at present..
240                     continue;
241                 }
242                 // files ending in .pg.sql are native postgres files..
243                 $fn = preg_match('#\.pg\.sql$#', basename($bfn)) ? false : $this->convertToPG($bfn);
244                 
245                 $cmd = "$psql_cmd  < " . escapeshellarg($fn ? $fn : $bfn) . ' 2>&1' ;
246                 
247                 echo "$bfn:   $cmd ". ($this->cli ? "\n" : "<BR>\n");
248                 
249                 
250                 passthru($cmd);
251                 
252                 if ($fn) {
253                     unlink($fn);
254                 }
255             }
256             
257             
258             
259             $fd = $this->rootDir. "/Pman/$m/sql";
260             // sql directory  - we try to convert..
261             foreach(glob($fd.'/*.sql') as $bfn) {
262                 $fn =  $this->convertToPG($bfn);
263                 $cmd = "$psql_cmd  < " . escapeshellarg($fn) ;
264                 echo $cmd. ($this->cli ? "\n" : "<BR>\n");
265                 passthru($cmd);
266             }
267             
268             // postgres specific directory..
269             
270             $fd = $this->rootDir. "/Pman/$m/pgsql";
271             
272             foreach(glob($fd.'/*.sql') as $fn) {
273                 $cmd = "$psql_cmd   < " . escapeshellarg($fn) ;
274                 echo $cmd. ($this->cli ? "\n" : "<BR>\n");
275                 passthru($cmd);
276             }
277             
278             
279             
280         }
281         
282     }
283     /**
284      * simple regex based convert mysql to pgsql...
285      */
286     function convertToPG($src)
287     {
288         $fn = $this->tempName('sql');
289         
290         $ret = array( ); // pad it a bit.
291         $extra = array("", "" );
292         
293         $tbl = false;
294         foreach(file($src) as $l) {
295             $l = trim($l);
296             
297             if (!strlen($l) || $l[0] == '#') {
298                 continue;
299             }
300             $m = array();
301             if (preg_match('#create\s+table\s+([a-z0-9_]+)#i',  $l, $m)) {
302                 $tbl = $m[1];
303                // $extra[]  =   "drop table {$tbl};";
304              }
305             // autoinc
306             if ($tbl && preg_match('#auto_increment#i',  $l, $m)) {
307                 $l = preg_replace('#auto_increment#i', "default nextval('{$tbl}_seq')", $l);
308                 $extra[]  =   "create sequence {$tbl}_seq;";
309               
310             }
311             $m = array();
312             if (preg_match('#alter\s+table\s+([a-z0-9_]+)\s+add\s+index\s+([^(]+)(.*)$#i',  $l, $m)) {
313                $l = "CREATE INDEX  {$m[1]}_{$m[2]} ON {$m[1]} {$m[3]}";
314              }
315             // ALTER TABLE core_event_audit ADD     INDEX looku
316             // CREATE INDEX 
317             
318             // basic types..
319             $l = preg_replace('#int\([0-9]+\)#i', 'INT', $l);
320             
321             $l = preg_replace('# datetime #i', ' TIMESTAMP WITHOUT TIME ZONE ', $l);
322             $l = preg_replace('# blob #i', ' TEXT ', $l);
323              $l = preg_replace('# longtext #i', ' TEXT ', $l);
324             //$l = preg_match('#int\([0-9]+\)#i', 'INT', $l);
325                             
326             $ret[] = $l;
327             
328             
329             
330             
331             
332             
333             
334         }
335         $ret = array_merge($extra,$ret);
336         
337         //echo implode("\n", $ret); //exit;
338         file_put_contents($fn, implode("\n", $ret));
339         
340         return $fn;
341     }
342     
343     function runUpdateModulesData()
344     {
345         // runs core...
346         $this->updateData(); 
347         $modules = array_reverse($this->modulesList());
348         
349         // move 'project' one to the end...
350         
351         foreach ($modules as $module){
352             $file = $this->rootDir. "/Pman/$module/UpdateDatabase.php";
353             if($module == 'Core' || !file_exists($file)){
354                 continue;
355             }
356             require_once $file;
357             $class = "Pman_{$module}_UpdateDatabase";
358             $x = new $class;
359             if(!method_exists($x, 'updateData')){
360                 continue;
361             };
362             $x->updateData();
363         }
364                 
365     }
366     
367     
368     function updateDataEnums()
369     {
370         $enum = DB_DataObject::Factory('core_enum');
371         $enum->initEnums(
372             array(
373                 array(
374                     'etype' => '',
375                     'name' => 'COMPTYPE',
376                     'display_name' =>  'Company Types',
377                     'is_system_enum' => 1,
378                     'cn' => array(
379                         array(
380                             'name' => 'OWNER',
381                             'display_name' => 'Owner',
382                             'seqid' => 999, // last...
383                             'is_system_enum' => 1,
384                         )
385                         
386                     )
387                 ),
388                 array(
389                     'etype' => '',
390                     'name' => 'HtmlEditor.font-family',
391                     'display_name' =>  'HTML Editor font families',
392                     'is_system_enum' => 1,
393                     'cn' => array(
394                         array(
395                             'name' => 'Helvetica,Arial,sans-serif',
396                             'display_name' => 'Helvetica',
397                             
398                         ),
399                         
400                         array(
401                             'name' => 'Courier New',
402                             'display_name' => 'Courier',
403                              
404                         ),
405                         array(
406                             'name' => 'Tahoma',
407                             'display_name' => 'Tahoma',
408                             
409                         ),
410                         array(
411                             'name' => 'Times New Roman,serif',
412                             'display_name' => 'Times',
413                            
414                         ),
415                         array(
416                             'name' => 'Verdana',
417                             'display_name' => 'Verdana',
418                             
419                         ),
420                         
421                             
422                         
423                     )
424                 ),
425             )
426         ); 
427         
428     }
429     function updateDataGroups()
430     {
431          
432         $groups = DB_DataObject::factory('groups');
433         $groups->initGroups();
434         
435         $groups->initDatabase($this,array(
436             array(
437                 'name' => 'bcc-email', // group who are bcc'ed on all requests.
438                 'type' => 0, // system
439             ),
440             
441         ));
442         
443     }
444     
445     function updateDataCompanies()
446     {
447          
448         // fix comptypes enums..
449         $c = DB_DataObject::Factory('Companies');
450         $c->selectAdd();
451         $c->selectAdd('distinct(comptype) as comptype');
452         $c->whereAdd("comptype != ''");
453         
454         $ctb = array();
455         foreach($c->fetchAll('comptype') as $cts) {
456             
457             
458             
459            $ctb[]= array( 'etype'=>'COMPTYPE', 'name' => $cts, 'display_name' => ucfirst(strtolower($cts)));
460         
461         }
462          $c = DB_DataObject::Factory('core_enum');
463          
464         $c->initEnums($ctb);
465         //DB_DataObject::debugLevel(1);
466         // fix comptypeid
467         $c = DB_DataObject::Factory('Companies');
468         $c->query("
469             UPDATE Companies 
470                 SET
471                     comptype_id = (SELECT id FROM core_enum where etype='comptype' and name=Companies.comptype)
472                 WHERE
473                     comptype_id = 0
474                     AND
475                     LENGTH(comptype) > 0
476                   
477                   
478                   ");
479          
480         
481         
482     }
483     
484     function updateData()
485     {
486         // fill i18n data..
487         
488         $this->updateDataEnums();
489         $this->updateDataGroups();
490         $this->updateDataCompanies();
491         
492        
493          
494        
495         
496         
497     }
498     
499     
500 }