DataObjects/Core_template.php
[Pman.Core] / DataObjects / Core_template.php
1 <?php
2 /**
3  * Table Definition for core_template 
4  *
5  *
6  * The idea here is that it contains all the strings in the templates with a language '' (empty)
7  * , it then generates a matching set of strings
8  * 
9  */
10 class_exists('DB_DataObject') ? '' : require_once 'DB/DataObject.php';
11
12 class Pman_Core_DataObjects_Core_template  extends DB_DataObject 
13 {
14     ###START_AUTOCODE
15     /* the code below is auto generated do not remove the above tag */
16
17     public $__table = 'core_template';         // table name
18     public $id;                              // int(11)  not_null primary_key auto_increment
19     public $template;                           // string(64)  not_null
20
21     public $updated;                        // blob(65535)  blob
22     public $lang;    // text  NOT NULL;
23     public $view_name; // eg mobile or desktop
24     /* the code above is auto generated do not remove the tag below */
25     ###END_AUTOCODE
26     
27     
28     function applyFilters($q, $au, $roo)
29     {
30         //DB_DataObject::debugLEvel(1);
31 //        $x = DB_Dataobject::Factory($this->tableName());
32         
33         
34         // template scanning and syncing should be done by the UpdateDatabase Code.
35         //if (!$x->count() || !empty($q['_rescan'])) {
36             //DB_DataObject::debugLEvel(1);
37             //$tp = DB_DataObject::factory('core_template');
38             //$opts = HTML_FlexyFramework::get()->Pman_Core;
39             //$tp->syncTemplateDir(false, '', !empty($q['_rescan']));
40             //if (isset($q['lang'])) {
41             //    $this->syncLang($q['lang']);
42             //}
43         //} 
44 //        $this->whereAdd("
45 //                join_
46 //            ");
47         
48     }
49         
50     function toRooArray($req)
51     {
52         $ret = $this->toArray();
53         if (!empty($req['_clean_name']) ) {
54             $ret['template_clean'] = preg_replace('#\.html$#i', '', $this->template);
55             
56         }
57         return $ret;
58         
59     }
60     
61     function beforeUpdate($old, $q, $roo)
62     {
63         if (!empty($q['_rescan'])){
64             if ($this->filetype != 'html') {
65                 $roo->jerr("can not update a php source file currently - TDOD");
66             }
67             $pg = HTML_FlexyFramework::get()->page;
68             
69             $this->syncTemplatePage(array(
70                 'template_dir' => $pg->rootDir . '/'. str_replace('.', '/', $this->view_name). '/templates',
71                 'template' => $this->template,
72                 'base' => $this->view_name,
73                 'force' => true
74             ));
75             // update the different langage versions of this page.
76             $x = DB_Dataobject::Factory('core_templatestr');
77             $x->selectAdd();
78             $x->selectAdd('distinct(lang) as lang');
79             $x->whereAdd("lang != ''");
80             $langs  = $x->fetchAll('lang');
81             foreach($langs as $l) {
82                 $x = DB_Dataobject::Factory('core_templatestr');
83                 $x->syncLang($l, $this->id);
84             }
85            
86             
87             $roo->jok("updated -" .  $this->template);
88         }
89     }
90    
91     
92     
93     
94     /*
95      * USED? - this is in updateBJSTemplate ?
96      * @param base (should be full path to template directory)
97      * @param subdir = empty for top or subpath.
98      */
99     /*
100     function syncTemplateDir($base = false,  $subdir = '', $force = false)
101     {
102         echo "syncTemplateDir: $base , $subdir, $force \n";
103         //print_r(func_get_args());
104         if (!$base) {
105             $ff = HTML_FlexyFramework::get();
106             if (!isset($ff->Pman_Core)) {
107                 echo "[ERROR] Not scanning template directory - no set in Pman_Core[templateDir]\n";
108                 return;
109             }
110             $opts = $ff->Pman_Core;
111             if (is_array($opts['templateDir'])) {
112                 foreach($opts['templateDir'] as $type=>$dir) {
113                     $this->syncTemplateDir($dir, '', $force);
114                 }
115                 return;
116             }
117             
118             $base = $opts['templateDir'];
119             
120             
121         }
122         if($force){
123             $tmpls = DB_DataObject::factory('core_template');
124             $this->tmpls = $tmpls->fetchAll('template','id'); // dupes??
125         }
126         
127         $tmp_dir = $base . (empty($subdir) ? '' : '/') . $subdir;
128         
129         if(!is_dir($tmp_dir)){
130             return;
131         }
132         
133         $dh = opendir($tmp_dir);
134         if(!$dh){
135             return; // something went wrong!?
136         }
137         
138         while (($fn = readdir($dh)) !== false) {
139             // do we care that it will try and parse the template directory??? - not really..
140             // as we are only looking for php files..
141             if(empty($fn) || $fn[0] == '.'){
142                 continue;
143             }
144
145             $fullpath = $tmp_dir."/".$fn;
146 //            echo "filename: ".$fullpath." \n";    
147              
148             $relpath = $subdir . (empty($subdir) ? '' : '/') . $fn;
149             
150             if(is_dir($fullpath)){
151                 // then recursively call self...
152 //                var_Dump($base);
153 //                var_Dump($subdir . (empty($subdir) ? '' : '/') . $fn);
154                 $this->syncTemplateDir($base, $subdir . (empty($subdir) ? '' : '/') . $fn );
155                 
156                 continue;
157             }
158             if (!preg_match('/(\.html|\.txt|\.abw)$/', $fn)) {
159                 continue;
160             }
161             
162              
163 //            var_dump($tmp);
164 //            var_dump($tmp_path);
165 //            $fn = basename($fn);
166             if (isset($this->tmpls[$relpath])) {
167                 unset($this->tmpls[$relpath]);
168             }
169             
170             
171             
172                
173             $template = $this->syncTemplate($relpath, true, false);
174 //            var_dump($template);
175             if (is_a($template, 'PEAR_Error')) {
176                 continue;
177             }
178         }
179         closedir($dh);
180 //        
181  
182         if($force){
183             foreach($this->tmpls as $id) {
184                 $x = DB_DataObject::factory($this->tableName());
185                 if ($x->get($id)) {
186                     $x->delete();
187                 }
188             }
189         }
190     }
191     */
192     /* compile a html template  - called by UpdateBjsTemplates - scan Pman Templates
193      *  
194      *  @param template_dir  << the path to the template dir ... Pman/XXX/template ...
195      *  @param template   << name of template used by name field)
196      *  @param base  << view name (module ? + templates?)
197      *  @param force << optional - forces even if database is newer.
198      *  
199      *  
200      */
201     
202     function syncTemplatePage($pgdata)
203     {
204         //print_r($pgdata);
205         
206         $force = true;
207          //echo "compiling:"; print_r($pgdata);
208         // read the template and extract the translatable strings.
209         ini_set('memory_limit', '512M');
210         
211         //var_dump($n);
212         $n = $pgdata['template'];  // remove trailing slash..
213         
214         $fopts = HTML_FlexyFramework::get()->HTML_Template_Flexy;
215         $opts = HTML_FlexyFramework::get()->Pman_Core;
216         //print_R($opts);
217         //$dir = $opts['templateDir'] . '/' . $node;
218         $oo = array(
219             'fatalError'    => PEAR_ERROR_EXCEPTION,  
220             'disableTranslate' => false,
221             'templateDir' => $pgdata['template_dir'],
222             'compileDir' => $fopts['compileDir'] . '_translation_files',
223             'forceCompile' => true, //?? only for force above???
224         );
225          
226         // non-html templates - treat as such..
227         // abiword - treat as html?
228         if (!preg_match('/\.(html|abw)$/i', $pgdata['template'])) {
229             $oo['nonHTML'] = true;
230         }
231         
232         //print_r(array($oo, $n));
233         
234         
235         $flexy = new HTML_Template_Flexy( $oo );
236           
237         if (!$flexy->resolvePath ($pgdata['template'])) {
238             //echo "SKIP - could not resolve path?\n"; print_r($oo);
239             return false;
240         }
241         
242         // attempt to find the template... record.
243         $tmpl = DB_DataObject::Factory($this->tableName());
244        
245         $tmpl->view_name = $pgdata['base'];
246         if ($tmpl->get('template',  $pgdata['template'])) {
247             clearstatcache();
248             if (strtotime($tmpl->updated) >= filemtime($flexy->resolvePath ($pgdata['template']) . '/'. $pgdata['template'])) {
249                 if ($tmpl->is_deleted != 0 ||  $tmpl->filetype != 'html') {
250                     $oo = clone($tmpl);
251                     $tmpl->is_deleted = 0;
252                     $tmpl->filetype = 'html';
253                     $tmpl->update($oo);
254                 }
255                 if (empty($pgdata['force'])) {
256                   //  echo "SKIP NO UPDATE: " . $pgdata['template'] ."\n";
257                    // echo $flexy->resolvePath ($pgdata['template']).  ':'. $tmpl->updated  . ">=" .  date('Y-m-d H:i:s',filemtime($flexy->resolvePath ($pgdata['template']))) . "\n";
258                     return $tmpl;
259                 }
260             }
261         }
262         
263         //die("got here");
264         
265         try {
266             $r = $flexy->compile($pgdata['template']);
267            
268             
269         } catch(Exception $e) {
270             $old = clone($tmpl);
271             $tmpl->updated   = date('Y-m-d H:i:s',filemtime($flexy->resolvePath ($pgdata['template']) . '/'. $pgdata['template']));
272             if ($tmpl->id) {
273                 $tmpl->is_deleted = 0;
274                 $tmpl->filetype = 'html';
275                 $tmpl->update($tmpl);
276             } else {
277                 $tmpl->is_deleted = 0;
278                 $tmpl->filetype = 'html';
279                 $tmpl->lang = 'en';
280                 $tmpl->insert();
281             }
282             //echo "SKIP: " . $pgdata['template'] ."\n";
283            //   echo "SKIP - exception\n"; print_r($e);
284             return false;
285         }
286        
287       
288         if (is_a($r,'PEAR_Error')) {
289             //echo "SKIP: " . $pgdata['template'] ."\n";
290             //echo $r->toString(). "\n";
291             return $r;
292         }
293           
294         $tmpl = DB_DataObject::Factory($this->tableName());
295         $tmpl->words = file_exists($flexy->getTextStringsFile) ?
296                 unserialize(file_get_contents($flexy->getTextStringsFile)) :
297                 array();
298         
299         $tmpl->contentStrings   = $flexy->compiler->contentStrings;
300         //var_dump(file_exists($flexy->getTextStringsFile));
301         //print_r($tmpl->words);
302         $tmpl->currentTemplate  = $flexy->currentTemplate;
303         
304         $tmpl->view_name = $pgdata['base'];
305         
306         //echo $pgdata['template'] ."\n";
307         if (!$tmpl->get('template',  $pgdata['template'])) {
308             $tmpl->is_deleted = 0;
309             $tmpl->filetype = 'html';
310             $tmpl->template = $pgdata['template'];
311             $tmpl->lang = 'en'; /// ??? hard coded??
312             $tmpl->updated = date('Y-m-d H:i:s', filemtime($flexy->currentTemplate));
313             $tmpl->insert();
314         } else {
315             $xx =clone($tmpl);
316             // has it been cahnged...
317             //if (!$force && filemtime($flexy->currentTemplate) == strtotime($tmpl->updated)) {
318                 // nothing changed..
319             //    return $tmpl;
320             //}
321             if (empty($tmpl->lang))  {
322                 //echo "FIX LANG?";exit;
323                 $tmpl->lang = 'en'; /// ??? hard coded??
324             }
325             $tmpl->filetype = 'html';
326             $tmpl->is_deleted = 0;
327             $tmpl->updated = date('Y-m-d H:i:s', filemtime($flexy->currentTemplate));
328             $tmpl->update($xx);
329         }
330       
331         
332         $x = DB_DataObject::Factory('core_templatestr');
333         $x->syncTemplateWords($tmpl);
334         
335         // if file_exists ( template/path/name.php << eg. a matching view..)
336         // then create a system page for this. 
337         
338         
339         
340         $x = DB_DataObject::Factory('core_template_element');
341         $tmpl->elements = $x->syncTemplateElement($tmpl,
342                 file_get_contents($flexy->currentTemplate),
343                 $flexy->compiler->contentStrings,
344                 false);
345         
346         
347         
348         return clone($tmpl);
349     
350     }
351     
352     // allow reuse in cms templatstr
353     function factoryStr()
354     {
355         return DB_DataObject::factory('core_templatestr');
356     }
357
358     function syncFileWord($pgdata, $filetype)
359     {
360         $tmpl = DB_DataObject::Factory($this->tableName());
361         $tmpl->view_name = $pgdata['base'];
362         $tmpl->currentTemplate = $pgdata['template_dir'] . '/'. $pgdata['template'];
363         
364         if ($tmpl->get('template',  $pgdata['template'])) {
365             if (strtotime($tmpl->updated) >= filemtime( $tmpl->currentTemplate )) {
366                 if ($tmpl->is_deleted != 0 ||  $tmpl->filetype != $filetype) {
367                     $oo = clone($tmpl);
368                     $tmpl->is_deleted = 0;
369                     $tmpl->filetype = $filetype;
370                     $tmpl->update($oo);
371                 }
372                 return $tmpl;
373             }
374         }
375
376         $words = array();
377
378         switch($filetype) {
379             case "php":
380                 $ar = token_get_all(file_get_contents( $tmpl->currentTemplate  ));
381                 foreach( $ar as $i=> $tok) {
382                     if (!is_array($tok) || $tok[0] != T_CONSTANT_ENCAPSED_STRING) {
383                         continue;
384                     }
385                     if ($i < 2) {
386                         continue;
387                     }
388                     if (is_array($ar[$i-1]) || $ar[$i-1] != '(') {
389                         continue;
390                     }
391                     if (!is_array($ar[$i-2]) || $ar[$i-2][1] != '_') {
392                         continue;
393                     }
394                     $ct = $tok[1][0];
395                     $words[] =  str_replace('\\'. $ct, $ct, trim($tok[1] , $ct));
396                     
397                 }
398                 break;
399             case "js":
400                 $fc = file_get_contents( $tmpl->currentTemplate );
401         
402                 preg_match_all('/\._\("([^"]+)"\)/', $fc, $outd);
403                 $words = $outd[1];
404                  
405                 preg_match_all('/\._\(\'([^\']+)\'\)/', $fc, $outs);
406                 
407                 // ?? seriously adding two arrays?
408                 $words =  array_diff(array_merge($words, $outs[1]), array_intersect($words, $outs[1]));
409                 break;
410             case "xml":
411                 $words = $pgdata['words'];
412                 break;
413         }
414
415         $words = array_unique($words);
416
417         var_dump($words);
418         die('c');
419
420         if(empty($words)) {
421             return;
422         }
423
424         if ($tmpl->id) {
425             $tmpl->is_deleted = 0;
426             $tmpl->filetype = $filetype;
427             $tmpl->updated = date('Y-m-d H:i:s', filemtime($tmpl->currentTemplate));
428             $tmpl->update($tmpl);
429         } else {
430             $tmpl->is_deleted = 0;
431             $tmpl->filetype = $filetype;
432             $tmpl->lang = 'en';
433             $tmpl->updated = date('Y-m-d H:i:s', filemtime($tmpl->currentTemplate));
434             $tmpl->insert();
435         }
436
437         $tmpl->words = $words;
438
439         $this->factoryStr()->syncTemplateWords($tmpl);
440
441         return $tmpl;
442     }
443
444     function syncPhpGetText($pgdata)
445     {
446         return $this->syncFileWord($pgdata, 'php'); 
447     }
448
449     /**
450      * plain JS files use ._(....) to flag 
451      * it does not support quoted strings or anything really
452      * very simple strings only
453      */ 
454     
455     function syncJsWords($pgdata)
456     {
457         return $this->syncFileWord($pgdata, 'js');   
458     }
459
460     function syncPowerpointXMLText($pgdata) 
461     {
462         return $this->syncFileWord($pgdata, 'xml');
463     }
464     
465     /*
466     SELECT LOWER(
467 CONCAT(
468 REPLACE(view_name, '.','_'),
469 '_',
470 REPLACE(template,'/','_')
471 )
472 )
473 FROM core_template
474
475 WHERE (
476  = 'release_pressrelease_distributionreportnew_journalistdistribution.php'
477 )
478 */
479
480     
481     function genGetText($clsname, $lang=false)
482     {
483         static $done = array();
484         $clsname = strtolower($clsname);
485
486         textdomain($clsname);
487      
488
489         $ff = HTML_FlexyFramework::get();
490         $lang = $lang ? $lang : (isset($ff->locale) ? $ff->locale : 'en');
491         
492
493         if (!empty($done[$clsname.':'.$lang])) {
494             return true; // already sent headers and everything.
495         }
496         
497         putenv("LANGUAGE=$lang");
498         if ($lang != 'en') {
499             if (!setlocale(LC_ALL, $lang.'.UTF-8')) {
500                 $ff->page->jerr("Language is not available {$lang}");
501             }
502         }
503         
504         
505         $d = DB_DataObject::factory($this->tableName());
506         $d->whereAdd("
507             LOWER(
508                 CONCAT(
509                       REPLACE(view_name, '.','_'),
510                     '_',
511                     REPLACE(template,'/','_')
512                 )
513             ) = '{$clsname}.php'
514        ");
515         $d->filetype = 'php';
516         if (! $d->find(true) ){
517             $done[$clsname.':'.$lang] = true;
518             return false;
519         }
520         $user = 'www-data'; // ?? do we need other ones
521         $compileDir = ini_get('session.save_path') .'/' . 
522             $user . '_gettext_' . $ff->project;
523         
524         if ($ff->appNameShort) {
525             $compileDir .= '_' . $ff->appNameShort;
526         }
527         if ($ff->version) {
528             $compileDir .= '.' . $ff->version;
529         }
530         $lang = $lang ? $lang : $ff->locale;
531         $fdir = "{$compileDir}/{$lang}/LC_MESSAGES";
532         $fname = "{$fdir}/{$clsname}.mo";
533         
534          
535         //exit;
536         bindtextdomain($clsname, $compileDir) ;
537         bind_textdomain_codeset($clsname, 'UTF-8');
538
539         textdomain($clsname);
540
541         
542         //textdomain($clsname);
543         
544         $done[$clsname.':'.$lang] = 1;
545         
546         // do we need to compile the file..
547         $ts = $this->factoryStr();
548         $ts->selectAdd('COALESCE(MAX(updated), "1000-01-01") as updated');
549         $ts->lang = $lang;
550         $ts->template_id = $d->id;
551         if (!$ts->find(true)) {
552             // then in theory there are no translations
553             return false;
554         }
555         if (file_exists($fname) && strtotime($ts->updated) < filemtime($fname)) {
556             return $fname; // file exists and is newer than our updated line.
557         }
558         //DB_DataObject::debugLevel(1);
559
560         $ts = $this->factoryStr();
561         $ts->autoJoin();
562         $ts->selectAdd("join_src_id_id.txt as src_id_txt, {$ts->tableName()}.txt as txt");
563         $ts->lang = $lang;
564         $ts->template_id = $d->id;
565         $ts->whereAdd("LENGTH(join_src_id_id.txt) > 0 AND LENGTH({$ts->tableName()}.txt) > 0");
566         $words = $ts->fetchAll('src_id_txt', 'txt' );
567                
568         if (!file_exists($fdir)) {
569             //var_dump($fdir);
570             mkdir($fdir, 0700, true);
571         }
572         
573         require_once 'File/Gettext.php';
574         $gt = File_Gettext::factory('PO', preg_replace('/\.mo$/', '.po', $fname));
575         $gt->fromArray(
576             
577             array(
578                 'meta' => array(
579                     "Language" =>  $lang,
580                     'Content-Type'      => 'text/plain; charset=UTF-8',
581                     'Content-Transfer-Encoding'      => ' 8bit',
582                      'PO-Revision-Date'  => date('Y-m-d H:iO'),
583                  ),
584                 'strings' => $words
585             )
586             
587         );
588         $gt->save();
589         
590         // mo DOESNT WORK!!
591         require_once 'System.php';
592         $poname = preg_replace('/\.mo$/', '.po', $fname);
593         $msgfmt = System::which('msgfmt');
594         $cmd = "{$msgfmt} {$poname}  -o {$fname}";
595         //echo $cmd;
596         
597         `$cmd`;
598         
599         
600          
601         
602         return $fname;
603         
604         require_once 'File/Gettext.php';
605         $gt = File_Gettext::factory('MO', $fname);
606         $gt->fromArray(
607             
608             array(
609                 'meta' => array(
610                      "Language" =>  $lang,
611                     'Content-Type'      => 'text/plain; charset=UTF-8',
612                     'Content-Transfer-Encoding'      => ' 8bit',
613                      'PO-Revision-Date'  => date('Y-m-d H:iO'),
614                 ),
615                 'strings' => $words
616             )
617             
618         );
619         $gt->save(); 
620         
621     }
622 }