Merge branch 'master' of http://git.roojs.com:8081/Pman.Core
[Pman.Core] / JsCompile.php
1 <?php
2
3 /**
4 * wrapper code around js builder...
5
6 *  -- we will use this later to compile on the fly...
7 *
8 *
9 * For general usage:
10 *  $x = new Pman_Core_JsCompile();
11 *  $x->pack('/path/to/files/', 'destination')
12 *  
13 */
14 require_once 'Pman.php';
15
16
17 class Pman_Core_JsCompile  extends Pman
18 {
19     
20     static $cli_desc = "Wrapper around Javascript compression tools";
21     
22     var $cli = false;
23     function getAuth()
24     {
25         // command line only ATM
26         $this->cli = HTML_FlexyFramework::get()->cli;
27       //  var_dump($this->cli);
28         if ($this->cli) {
29             return true;
30         }
31         return  false;
32     }
33     
34     
35     function get($proj, $args)
36     {
37         if (empty($args)) {
38             die("missing action : eg. build or install");
39         }
40         // list of projects.
41         if (empty($args[1])) {
42             
43             $ar = $this->gatherProjects();
44              echo "SELECT Component to build\n";
45             print_r($ar);
46             exit;
47         } else {
48             $ar = array($args[1]); 
49             //$ar = $args;
50             //array_shift($ar);
51         }
52         
53         switch ($args[0]) {
54             case 'build':
55              
56                 foreach($ar as $p) {
57                     $this->build($p);
58                     //$this->install($p);
59                 }
60                 break;
61             case 'install' :     // needed for install on remote sites..
62                 die('not yet..');
63                 foreach($ar as $p) {
64                     $this->install($p);
65                 }
66                 break;
67         }
68         exit;
69     }
70     /**
71      * packScript:
72      *
73      * @param {String} basedir absolute path to files
74      * @param {Array}  list of files (ontop of basedir) 
75      * @param {String} output url (path to basedir basically), or false
76      *                  to not compile
77      * 
78      *
79      */
80     
81     
82     function packScript($basedir, $files,  $output_url, $compile=true)
83     {
84         // this outputs <script tags..>
85         // either for just the original files,
86         // or the compressed version.
87         // first expand files..
88         
89         echo "<!-- compiling   $basedir  -->\n";
90         
91         $arfiles = array();
92         $ofiles = array();
93         foreach($files as $f) {
94              if (!file_exists($basedir .'/' .$f)) {
95                 continue;
96             }
97             if (!is_dir($basedir .'/' .$f)) {
98                 
99                 $arfiles[$basedir .'/' .$f] = filemtime($basedir .'/' .$f);
100                  $ofiles[] = $f;
101                 continue;
102             }
103             foreach(glob($basedir .'/' .$f.'/*.js') as $fx) {
104                 $arfiles[$fx] = filemtime($fx);
105                 $ofiles [] = $f . '/'. basename($fx);
106             }
107         }
108         
109         $output = md5(serialize($arfiles)) .'.js';
110         
111         if ( $compile && !file_exists($basedir.'/_cache_/'.$output)) {
112             $this->pack($arfiles,$basedir.'/_cache_/'.$output);
113         }
114         
115         if ($compile && file_exists($basedir.'/_cache_/'.$output)) {
116             
117             echo '<script type="text/javascript" src="'.$output_url.'/_cache_/'. $output.'"></script>';
118             return;
119         }
120         foreach($ofiles as $f) {
121             echo '<script type="text/javascript" src="'.$output_url.'/'.$f.'"></script>'."\n";
122             
123         }
124           
125     }
126     
127     function packCss($basedir, $files,   $output_url)
128     {
129         // this outputs <script tags..>
130         // either for just the original files,
131         // or the compressed version.
132         // first expand files..
133         
134         $arfiles = array();
135         $ofiles = array();
136         //print_R($files);
137         foreach($files as $f) {
138             if (!file_exists($basedir .'/' .$f)) {
139                 continue;
140             }
141             if (!is_dir($basedir .'/' .$f)) {
142                 $arfiles[$basedir .'/' .$f] = filemtime($basedir .'/' .$f);
143                 $ofiles[] = $f;
144                 continue;
145             }
146             foreach(glob($basedir .'/' .$f.'/*.css') as $fx) {
147                 $arfiles[$fx] = filemtime($fx);
148                 $ofiles [] = $f . '/'. basename($fx);
149             }
150         }
151         
152         $output = md5(serialize($arfiles)) .'.css';
153         
154         if (!file_exists($basedir.'/_cache_/'.$output)) {
155             $this->packCssCore($arfiles,$basedir.'/_cache_/'.$output);
156         }
157         //var_dump()$basedir. '/_cache_/'.$output);
158         if (file_exists($basedir. '/_cache_/'.$output)) {
159             echo '<link type="text/css" rel="stylesheet" media="screen" href="'.$output_url. '/_cache_/'. $output.'" />';
160             return;
161         }
162         foreach($ofiles as $f ) {
163             echo '<link type="text/css" rel="stylesheet" media="screen" href="'.$output_url.'/'.$f.'" />'."\n";
164              
165         }
166          
167         
168     }
169      /**
170      * wrapper arroudn packer...
171      * @param {Array} map of $files => filemtime the files to pack
172      * @param {String} $output name fo file to output
173      *
174      */
175     function packCssCore($files, $output)
176     {
177         
178          
179         $o = HTML_FlexyFramework::get()->Pman_Core;
180         
181         if (empty($o['cssminify']) || !file_exists($o['cssminify'])) {
182             echo '<!-- cssminify not set -->';
183             return false;
184         }
185         require_once 'System.php';
186         $seed= System::which('seed');
187         if (!$seed) {
188             echo '<!-- seed not installed -->';
189             return false;
190             
191         }
192         $targetm = file_exists($output) ? filemtime($output) : 0;
193         $max = 0;
194         $ofiles = array();
195         foreach($files as $f => $mt) {
196             $max = max($max,$mt);
197             $ofiles[] = escapeshellarg($f);
198         }
199         if ($max < $targetm)  {
200             return true;
201         }
202         if (!file_exists(dirname($output))) {
203             mkdir(dirname($output), 0755, true);
204         }
205         $eoutput = escapeshellarg($output);
206         $cmd = "$seed {$o['cssminify']}  $eoutput " . implode($ofiles, ' ');
207         //echo "<PRE>$cmd\n"; echo `$cmd`; exit;
208         `$cmd`;
209         
210         
211         // we should do more checking.. return val etc..
212         if (file_exists($output) && ($max < filemtime($output) ) ) {
213             return true;
214         }
215         return false;
216         
217     }
218     /**
219      * wrapper arround packer...
220      * uses the translation module & puts index in __tra
221      * 
222      * @param {Array} map of $files => filemtime the files to pack
223      * @param {String} $output name fo file to output
224      *
225      */
226     function pack($files, $output, $translation_base=false)
227     {
228         
229          
230         $o = HTML_FlexyFramework::get()->Pman_Core;
231         
232         if (empty($o['jspacker']) || !file_exists($o['jspacker'].'/pack.js')) {
233             echo '<!-- JS COMPILE ERROR: option: Pman_Core[jspacker] not set to directory -->';
234             return false;
235             
236         }
237         require_once 'System.php';
238         $seed= System::which('seed');
239         if (!$seed) {
240             echo '<!-- JS COMPILE ERROR: seed not installed -->';
241             return false;
242             
243         }
244         $targetm = file_exists($output) && filesize($output) ? filemtime($output) : 0;
245         $max = 0;
246         $ofiles = array();
247         foreach($files as $f => $mt) {
248             $max = max($max,$mt);
249             $ofiles[] = escapeshellarg($f);
250         }
251         if ($max < $targetm) {
252             echo '<!--  use cached compile. -->';
253             return true;
254         }
255         //var_dump($output);
256         if (!file_exists(dirname($output))) {
257             mkdir(dirname($output), 0755, true);
258         }
259         $lsort = create_function('$a,$b','return strlen($a) > strlen($b) ? 1 : -1;');
260         usort($ofiles, $lsort);
261         
262         $eoutput = " -o " . escapeshellarg($output) ;
263             
264                    
265         if (  $translation_base) {
266             $toutput = "-t ". escapeshellarg(preg_replace('/\.js$/', '.__translation__.js', $output)) .
267                     " -p " . escapeshellarg($translation_base) ;//." -k "; // this kills the compression.
268                     
269         }
270         
271         
272         $cmd = "$seed {$o['jspacker']}/pack.js   $eoutput  $toutput " . implode($ofiles, ' ') . ' 2>&1';
273         //echo "<PRE>$cmd\n";
274         //echo `$cmd`;
275         
276          echo "<!-- Compile javascript
277           
278             " . htmlspecialchars($cmd) . "
279             
280             -->";
281             
282        // return false;
283         
284         $res = `$cmd`;
285         //exit;
286         file_put_contents($output.'.log', $cmd."\n\n". $res);
287         // since this only appears when we change.. it's ok to dump it out..
288         echo "<!-- Compiled javascript
289             " . htmlspecialchars($res) . "
290             -->";
291             
292         // we should do more checking.. return val etc..
293         if (file_exists($output) && ($max < filemtime($output) ) ) {
294             
295             return true;
296         }
297         echo "<!-- JS COMPILE ERROR: packed file did not exist  -->";
298         return false;
299         
300     }
301     
302     
303     /***
304      * build:
305      *
306      * @param {String} $proj name of Pman component to build
307      * runs pack.js -m {proj} -a $src/*.js
308      * 
309      *
310      */
311       
312     function build($proj) 
313     {
314         echo "Building $proj\n";
315        // var_dump($proj);
316         if (empty($proj)) {
317             $this->err = "no project";
318             if ($this->cli) echo $this->err;
319             return;
320         }
321         // first item in path is always the app start directory..
322         $src= array_shift(explode(PATH_SEPARATOR, ini_get('include_path'))) .'/Pman/'. $proj;
323         
324         
325         
326        //$tmp = ini_get('session.save_path')."/{$proj}_". posix_getuid(). '_'.md5($src);
327         
328         
329         require_once 'System.php';
330         $seed= System::which('seed');
331         if (!$seed) {
332             $this->err ="no seed installed";
333             if ($this->cli) echo $this->err;
334             return false;
335         }
336         
337         $o = HTML_FlexyFramework::get()->Pman_Core;
338         
339         if (empty($o['jspacker']) || !file_exists($o['jspacker'].'/pack.js')) {
340             $this->err ="no jstoolkit path set [Pman_Core][jspacker] to the
341                     introspection documentation directory where pack.js is located.";
342             if ($this->cli) echo $this->err;
343             return false;
344         }  
345         
346         // should we be more specirfic!??!?!?
347          
348         $cmd = "$seed {$o['jspacker']}/pack.js -m $proj  -a  $src/*.js";
349         echo "$cmd\n";
350         passthru($cmd);
351         // technically we should trash old compiled files.. 
352         // or we move towards a 'cache in session directory model..'
353         
354         
355         /*
356         
357         $ret = $tmp . '/'. $proj . '.js';
358         if ($this->cli) {
359             echo "BUILT:  $ret \n";
360             exit;
361         }
362         return $ret;
363         */
364         
365     }
366     // link {PROJECT}/compiled/{PROJECT}.js to _compiled_ folder to make it live.
367         
368     function install($proj) 
369     {
370        
371         $base = dirname(realpath($_SERVER["SCRIPT_FILENAME"]));
372         if (empty($base )) {
373             $base = getcwd();
374         }
375         var_dump($base .'/Pman/'. $proj.'/compiled/'.$proj .'.js');
376         $src =  realpath($base .'/Pman/'. $proj.'/compiled/'.$proj .'.js');
377         if (!$src) {
378             echo "SKIP : no js file $proj\n";
379             return;
380         }
381         if (!file_exists("$base/_compiled_")) {
382             mkdir ("$base/_compiled_", 0755, true);
383         }
384         $target = "$base/_compiled_/".$proj .'.js';
385         print_R(array($src,$target));
386         if (file_exists($target)) {
387             return; // already installed.
388         }
389         
390         symlink($src, $target);
391         
392         
393     }
394     
395     function gatherProjects() {
396         $src= array_shift(explode(PATH_SEPARATOR, ini_get('include_path'))) .'/Pman';
397         
398         $ret = array();
399         foreach(scandir($src) as $f) {
400             if (!strlen($f) || $f[0] == '.') {
401                 continue;
402             }
403             
404             $fp = "$src/$f";
405             if (!is_dir($fp)) {
406                 continue;
407             }
408             if ($f == 'templates') {
409                 continue;
410             }
411             $ret[] = $f;
412             
413             
414         }
415         return $ret;
416     }
417 }
418