JsCompile.php
[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         $arfiles = array();
90         $ofiles = array();
91         foreach($files as $f) {
92              if (!file_exists($basedir .'/' .$f)) {
93                 continue;
94             }
95             if (!is_dir($basedir .'/' .$f)) {
96                 
97                 $arfiles[$basedir .'/' .$f] = filemtime($basedir .'/' .$f);
98                  $ofiles[] = $f;
99                 continue;
100             }
101             foreach(glob($basedir .'/' .$f.'/*.js') as $fx) {
102                 $arfiles[$fx] = filemtime($fx);
103                 $ofiles [] = $f . '/'. basename($fx);
104             }
105         }
106         
107         $output = md5(serialize($arfiles)) .'.js';
108         
109         if ( $compile && !file_exists($basedir.'/_cache_/'.$output)) {
110             $this->pack($arfiles,$basedir.'/_cache_/'.$output);
111         }
112         
113         if ($compile && file_exists($basedir.'/_cache_/'.$output)) {
114             
115             echo '<script type="text/javascript" src="'.$output_url.'/_cache_/'. $output.'"></script>';
116             return;
117         }
118         foreach($ofiles as $f) {
119             echo '<script type="text/javascript" src="'.$output_url.'/'.$f.'"></script>'."\n";
120             
121         }
122          
123         
124     }
125     function packCss($basedir, $files,   $output_url)
126     {
127         // this outputs <script tags..>
128         // either for just the original files,
129         // or the compressed version.
130         // first expand files..
131         
132         $arfiles = array();
133         $ofiles = array();
134         //print_R($files);
135         foreach($files as $f) {
136             if (!file_exists($basedir .'/' .$f)) {
137                 continue;
138             }
139             if (!is_dir($basedir .'/' .$f)) {
140                 $arfiles[$basedir .'/' .$f] = filemtime($basedir .'/' .$f);
141                 $ofiles[] = $f;
142                 continue;
143             }
144             foreach(glob($basedir .'/' .$f.'/*.css') as $fx) {
145                 $arfiles[$fx] = filemtime($fx);
146                 $ofiles [] = $f . '/'. basename($fx);
147             }
148         }
149         
150         $output = md5(serialize($arfiles)) .'.css';
151         
152         if (!file_exists($basedir.'/_cache_/'.$output)) {
153             $this->packCssCore($arfiles,$basedir.'/_cache_/'.$output);
154         }
155         //var_dump()$basedir. '/_cache_/'.$output);
156         if (file_exists($basedir. '/_cache_/'.$output)) {
157             echo '<link type="text/css" rel="stylesheet" media="screen" href="'.$output_url. '/_cache_/'. $output.'" />';
158             return;
159         }
160         foreach($ofiles as $f ) {
161             echo '<link type="text/css" rel="stylesheet" media="screen" href="'.$output_url.'/'.$f.'" />'."\n";
162              
163         }
164          
165         
166     }
167      /**
168      * wrapper arroudn packer...
169      * @param {Array} map of $files => filemtime the files to pack
170      * @param {String} $output name fo file to output
171      *
172      */
173     function packCssCore($files, $output)
174     {
175         
176          
177         $o = HTML_FlexyFramework::get()->Pman_Core;
178         
179         if (empty($o['cssminify']) || !file_exists($o['cssminify'])) {
180             echo '<!-- cssminify not set -->';
181             return false;
182         }
183         require_once 'System.php';
184         $seed= System::which('seed');
185         if (!$seed) {
186             echo '<!-- seed not installed -->';
187             return false;
188             
189         }
190         $targetm = file_exists($output) ? filemtime($output) : 0;
191         $max = 0;
192         $ofiles = array();
193         foreach($files as $f => $mt) {
194             $max = max($max,$mt);
195             $ofiles[] = escapeshellarg($f);
196         }
197         if ($max < $targetm)  {
198             return true;
199         }
200         if (!file_exists(dirname($output))) {
201             mkdir(dirname($output), 0755, true);
202         }
203         $eoutput = escapeshellarg($output);
204         $cmd = "$seed {$o['cssminify']}  $eoutput " . implode($ofiles, ' ');
205         //echo "<PRE>$cmd\n"; echo `$cmd`; exit;
206         `$cmd`;
207         
208         
209         // we should do more checking.. return val etc..
210         if (file_exists($output) && ($max < filemtime($output) ) ) {
211             return true;
212         }
213         return false;
214         
215     }
216     /**
217      * wrapper arround packer...
218      * uses the translation module & puts index in __tra
219      * 
220      * @param {Array} map of $files => filemtime the files to pack
221      * @param {String} $output name fo file to output
222      *
223      */
224     function pack($files, $output, $translation_base=false)
225     {
226         
227          
228         $o = HTML_FlexyFramework::get()->Pman_Core;
229         
230         if (empty($o['jspacker']) || !file_exists($o['jspacker'].'/pack.js')) {
231             echo '<!-- JS COMPILE ERROR: option: Pman_Core[jspacker] not set to directory -->';
232             return false;
233             
234         }
235         require_once 'System.php';
236         $seed= System::which('seed');
237         if (!$seed) {
238             echo '<!-- JS COMPILE ERROR: seed not installed -->';
239             return false;
240             
241         }
242         $targetm = file_exists($output) ? filemtime($output) : 0;
243         $max = 0;
244         $ofiles = array();
245         foreach($files as $f => $mt) {
246             $max = max($max,$mt);
247             $ofiles[] = escapeshellarg($f);
248         }
249         if ($max < $targetm)  {
250             return true;
251         }
252         //var_dump($output);
253         if (!file_exists(dirname($output))) {
254             mkdir(dirname($output), 0755, true);
255         }
256         $lsort = create_function('$a,$b','return strlen($a) > strlen($b) ? 1 : -1;');
257         usort($ofiles, $lsort);
258         
259         $eoutput = " -o " . escapeshellarg($output) .
260                    " -O ". escapeshellarg(preg_replace('/\.js$/', '.__debug__.js', $output));
261                    
262         if ( $translation_base) {
263             $toutput = "-t ". escapeshellarg(preg_replace('/\.js$/', '.__translation__.js', $output)) .
264                     " -p " . escapeshellarg($translation_base);
265         }
266         
267         
268         
269         $cmd = "$seed {$o['jspacker']}/pack.js  $eoutput  $toutput " . implode($ofiles, ' ') . ' 2>&1';
270         //echo "<PRE>$cmd\n";
271         //echo `$cmd`;
272         
273          echo "<!-- Compile javascript
274           
275             " . htmlspecialchars($cmd) . "
276             
277             -->";
278             
279        // return false;
280         
281         $res = `$cmd`;
282         //exit;
283         file_put_contents($output.'.log', $cmd."\n\n". $res);
284         // since this only appears when we change.. it's ok to dump it out..
285           echo "<!-- Compiled javascript
286             " . htmlspecialchars($res) . "
287             -->";
288             
289         // we should do more checking.. return val etc..
290         if (file_exists($output) && ($max < filemtime($output) ) ) {
291             
292             return true;
293         }
294         echo "<!-- JS COMPILE ERROR: packed file did not exist  -->";
295         return false;
296         
297     }
298     
299     
300     /***
301      * build:
302      *
303      * @param {String} $proj name of Pman component to build
304      * runs pack.js -m {proj} -a $src/*.js
305      * 
306      *
307      */
308       
309     function build($proj) 
310     {
311         echo "Building $proj\n";
312        // var_dump($proj);
313         if (empty($proj)) {
314             $this->err = "no project";
315             if ($this->cli) echo $this->err;
316             return;
317         }
318         // first item in path is always the app start directory..
319         $src= array_shift(explode(PATH_SEPARATOR, ini_get('include_path'))) .'/Pman/'. $proj;
320         
321         
322         
323        //$tmp = ini_get('session.save_path')."/{$proj}_". posix_getuid(). '_'.md5($src);
324         
325         
326         require_once 'System.php';
327         $seed= System::which('seed');
328         if (!$seed) {
329             $this->err ="no seed installed";
330             if ($this->cli) echo $this->err;
331             return false;
332         }
333         
334         $o = HTML_FlexyFramework::get()->Pman_Core;
335         
336         if (empty($o['jspacker']) || !file_exists($o['jspacker'].'/pack.js')) {
337             $this->err ="no jstoolkit path set [Pman_Core][jspacker] to the
338                     introspection documentation directory where pack.js is located.";
339             if ($this->cli) echo $this->err;
340             return false;
341         }  
342         
343         // should we be more specirfic!??!?!?
344          
345         $cmd = "$seed {$o['jspacker']}/pack.js -m $proj  -a  $src/*.js";
346         echo "$cmd\n";
347         passthru($cmd);
348         // technically we should trash old compiled files.. 
349         // or we move towards a 'cache in session directory model..'
350         
351         
352         /*
353         
354         $ret = $tmp . '/'. $proj . '.js';
355         if ($this->cli) {
356             echo "BUILT:  $ret \n";
357             exit;
358         }
359         return $ret;
360         */
361         
362     }
363     // link {PROJECT}/compiled/{PROJECT}.js to _compiled_ folder to make it live.
364         
365     function install($proj) 
366     {
367        
368         $base = dirname(realpath($_SERVER["SCRIPT_FILENAME"]));
369         if (empty($base )) {
370             $base = getcwd();
371         }
372         var_dump($base .'/Pman/'. $proj.'/compiled/'.$proj .'.js');
373         $src =  realpath($base .'/Pman/'. $proj.'/compiled/'.$proj .'.js');
374         if (!$src) {
375             echo "SKIP : no js file $proj\n";
376             return;
377         }
378         if (!file_exists("$base/_compiled_")) {
379             mkdir ("$base/_compiled_", 0755, true);
380         }
381         $target = "$base/_compiled_/".$proj .'.js';
382         print_R(array($src,$target));
383         if (file_exists($target)) {
384             return; // already installed.
385         }
386         
387         symlink($src, $target);
388         
389         
390     }
391     
392     function gatherProjects() {
393         $src= array_shift(explode(PATH_SEPARATOR, ini_get('include_path'))) .'/Pman';
394         
395         $ret = array();
396         foreach(scandir($src) as $f) {
397             if (!strlen($f) || $f[0] == '.') {
398                 continue;
399             }
400             
401             $fp = "$src/$f";
402             if (!is_dir($fp)) {
403                 continue;
404             }
405             if ($f == 'templates') {
406                 continue;
407             }
408             $ret[] = $f;
409             
410             
411         }
412         return $ret;
413     }
414 }
415