PHP7 fix
[Pman.Core] / JsCompile.php
index 98c12b0..a5b9159 100644 (file)
@@ -4,12 +4,26 @@
 * wrapper code around js builder...
 * 
 *  -- we will use this later to compile on the fly...
+*
+*  -- updated to use roojspacker https://github.com/roojs/roojspacker
+*
+*
+* For general usage:
+*  $x = new Pman_Core_JsCompile();
+*  $x->pack('/path/to/files/', 'destination')
+*  
 */
 require_once 'Pman.php';
 
 
 class Pman_Core_JsCompile  extends Pman
 {
+    
+    static $cli_desc = "Wrapper around Javascript compression tools
+                        Runs the javascript compiler - merging all the JS files so the load faster.
+                        Note: cfg option Pman_Builder['jspacker'] must be set to location of jstoolkit code 
+";
+    
     var $cli = false;
     function getAuth()
     {
@@ -23,7 +37,7 @@ class Pman_Core_JsCompile  extends Pman
     }
     
     
-    function get($proj, $args)
+    function get($proj, $args=array())
     {
         if (empty($args)) {
             die("missing action : eg. build or install");
@@ -58,88 +72,413 @@ class Pman_Core_JsCompile  extends Pman
         }
         exit;
     }
-    function build($proj) 
+    /**
+     * packScript:
+     *
+     * @param {String} basedir absolute path to files
+     * @param {Array}  list of files (ontop of basedir) 
+     * @param {String} output url (path to basedir basically), or false
+     *                  to not compile
+     * 
+     *
+     */
+    
+    static function jsSort($a,$b)
     {
-        echo "Building $proj\n";
-       // var_dump($proj);
-        if (empty($proj)) {
-            $this->err = "no project";
-            if ($this->cli) echo $this->err;
+        $a = substr($a, 0, -3);
+        $b=  substr($b, 0, -3);
+        if ($a == $b) {
+            return 0;
+        }
+        return ($a > $b) ? +1 : -1;
+    }
+    
+    
+    function packScript($basedir, $files,  $output_url, $compile=true)
+    {
+        // this outputs <script tags..>
+        // either for just the original files,
+        // or the compressed version.
+        // first expand files..
+        
+        echo "<!-- compiling   $basedir  -->\n";
+        
+        $arfiles = array();
+        $ofiles = array();
+        foreach($files as $f) {
+             if (!file_exists($basedir .'/' .$f)) {
+                continue;
+            }
+            if (!is_dir($basedir .'/' .$f)) {
+                
+                $arfiles[$basedir .'/' .$f] = filemtime($basedir .'/' .$f);
+                $ofiles[] = $f;
+                continue;
+            }
+            
+            foreach(glob($basedir .'/' .$f.'/*.js') as $fx) {
+                
+                $arfiles[$fx] = filemtime($fx);
+                $ofiles [] = $f . '/'. basename($fx);
+            }
+        }
+        $tf = 
+        // sort exc. the .js
+        usort($ofiles,function($a,$b) { return Pman_Core_JsCompile::jsSort($a,$b); });
+        
+        //print_R($ofiles);
+        
+        $output = md5(serialize($arfiles)) .'.js';
+        
+        if ( $compile && !file_exists($basedir.'/_cache_/'.$output)) {
+            $this->pack($arfiles,$basedir.'/_cache_/'.$output);
+        }
+        
+        if ($compile && file_exists($basedir.'/_cache_/'.$output)) {
+            
+            echo '<script type="text/javascript" src="'.$output_url.'/_cache_/'. $output.'"></script>';
             return;
         }
-        // first item in path is always the app start directory..
-        $src= array_shift(explode(PATH_SEPARATOR, ini_get('include_path'))) .'/Pman/'. $proj;
+        foreach($ofiles as $f) {
+            echo '<script type="text/javascript" src="'.$output_url.'/'.$f.'"></script>'."\n";
+            
+        }
+          
+    }
+    
+    // this is depricated... - we can use the pear CSS library for this..
+    
+    function packCss($basedir, $files,   $output_url)
+    {
+        // this outputs <script tags..>
+        // either for just the original files,
+        // or the compressed version.
+        // first expand files..
         
+        $arfiles = array();
+        $ofiles = array();
+        //print_R($files);
+        foreach($files as $f) {
+            if (!file_exists($basedir .'/' .$f)) {
+                continue;
+            }
+            if (!is_dir($basedir .'/' .$f)) {
+                $arfiles[$basedir .'/' .$f] = filemtime($basedir .'/' .$f);
+                $ofiles[] = $f;
+                continue;
+            }
+            foreach(glob($basedir .'/' .$f.'/*.css') as $fx) {
+                $arfiles[$fx] = filemtime($fx);
+                $ofiles [] = $f . '/'. basename($fx);
+            }
+        }
         
+        $output = md5(serialize($arfiles)) .'.css';
+        
+        if (!file_exists($basedir.'/_cache_/'.$output)) {
+            $this->packCssCore($arfiles,$basedir.'/_cache_/'.$output);
+        }
+        //var_dump()$basedir. '/_cache_/'.$output);
+        if (file_exists($basedir. '/_cache_/'.$output)) {
+            echo '<link type="text/css" rel="stylesheet" media="screen" href="'.$output_url. '/_cache_/'. $output.'" />';
+            return;
+        }
+        foreach($ofiles as $f ) {
+            echo '<link type="text/css" rel="stylesheet" media="screen" href="'.$output_url.'/'.$f.'" />'."\n";
+             
+        }
+         
         
-        $tmp = ini_get('session.save_path')."/{$proj}_". posix_getuid(). '_'.md5($src);
+    }
+     /**
+     * wrapper arroudn packer...
+     * @param {Array} map of $files => filemtime the files to pack
+     * @param {String} $output name fo file to output
+     *
+     */
+    function packCssCore($files, $output)
+    {
         
+         
+        $o = HTML_FlexyFramework::get()->Pman_Core;
         
+        if (empty($o['cssminify']) || !file_exists($o['cssminify'])) {
+            echo '<!-- cssminify not set -->';
+            return false;
+        }
         require_once 'System.php';
+        
         $seed= System::which('seed');
-        if (!$seed) {
-            $this->err ="no seed installed";
-            if ($this->cli) echo $this->err;
+        $gjs = System::which('gjs');
+        
+        if (!$seed && !$gjs) {
+            echo '<!-- seed or gjs are  not installed -->';
             return false;
+            
+        }
+        $targetm = file_exists($output) ? filemtime($output) : 0;
+        $max = 0;
+        $ofiles = array();
+        foreach($files as $f => $mt) {
+            $max = max($max,$mt);
+            $ofiles[] = escapeshellarg($f);
         }
+        if ($max < $targetm)  {
+            return true;
+        }
+        if (!file_exists(dirname($output))) {
+            mkdir(dirname($output), 0755, true);
+        }
+        $eoutput = escapeshellarg($output);
+        $cmd = $seed ?
+            ("$seed {$o['cssminify']}  $eoutput " . implode($ofiles, ' ')) :
+            ("$gjs {$o['cssminify']} -- -- $eoutput " . implode($ofiles, ' ')); 
+        //echo "<PRE>$cmd\n"; echo `$cmd`; exit;
+        `$cmd`;
         
-        $o = PEAR::getStaticProperty('Pman_Core','options');
-        if (empty($o['jspacker']) || !file_exists($o['jspacker'].'/pack.js')) {
-            $this->err ="no jstoolkit path set [Pman_Core][jspacker] to the introspection documentation directory where pack.js is located.";
-            if ($this->cli) echo $this->err;
+        
+        // we should do more checking.. return val etc..
+        if (file_exists($output) && ($max < filemtime($output) ) ) {
+            return true;
+        }
+        return false;
+        
+    }
+    /**
+     * wrapper arround packer...
+     * uses the translation module & puts index in __tra
+     * 
+     * @param {Array} map of $files => filemtime the files to pack
+     * @param {String} $output name fo file to output
+     *
+     */
+    
+    function pack($files, $output, $translation_base=false)
+    {
+        
+        if (empty($files)) {
             return false;
-        }  
+        }
         
-        // should we be more specirfic!??!?!?
+        $o = HTML_FlexyFramework::get()->Pman_Core;
+        if (isset($o['packseed'])) {
+            return $this->packSeed($files,$output,$translation_base);
+        }
         
-        $buildjs = 
-        $cmd = "$seed {$o['jspacker']}/pack.js -m$proj  -a  $src/*.js -o $tmp";
-        echo $cmd;
-        passthru($cmd);
         
+        require_once 'System.php';
+        $packer = System::which('roojspacker');
         
-        exit;
-        // copy into the revision controlled area.
         
+        if (!$packer) {
+            echo '<!-- roojspacker is not installed -->';
+            return false;
+            
+        }
+        $targetm = file_exists($output) && filesize($output) ? filemtime($output) : 0;
+        $max = 0;
+        $ofiles = array();
+        foreach($files as $f => $mt) {
+            $max = max($max,$mt);
+            $ofiles[] = escapeshellarg($f);
+        }
+        if ($max < $targetm) {
+            echo '<!--  use cached compile. -->';
+            return true;
+        }
         
+        if (file_exists($output)) {
+            unlink($output);
+        }
         
+         
+        if (!file_exists(dirname($output))) {
+            mkdir(dirname($output), 0755, true);
+        }
         
+        usort($ofiles, function($a,$b)  { return strlen($a) > strlen($b) ? 1 : -1; });
         
+        //$eoutput = " -k  -o " . escapeshellarg($output) ; // with whitespace..
+        $eoutput = "  -t " . escapeshellarg($output) ;
+          
+        // no support for translation any more?         
+        //if (  $translation_base) {
+        //    $toutput = " -t ". escapeshellarg(preg_replace('/\.js$/', '.__translation__.js', $output)) .
+        //            " -p " . escapeshellarg($translation_base) ;//." -k "; // this kills the compression.
+        //            
+        //}
         
+    
+        $cmd = "$packer  $eoutput  -f " . implode(' -f ', $ofiles) . ' 2>&1';
+        //echo "<PRE>$cmd\n";
+        //echo `$cmd`;
         
-        $src = realpath(dirname(__FILE__).'/../../_compiled_tmp_/'.$proj .'.js');
-        if (!$src) {
-            return;
+         echo "<!-- Compile javascript
+          
+            " . htmlspecialchars($cmd) . "
+            
+            -->";
+            
+       // return false;
+        
+        $res = `$cmd`;
+        //exit;
+        file_put_contents($output.'.log', $cmd."\n\n". $res);
+        // since this only appears when we change.. it's ok to dump it out..
+        echo "<!-- Compiled javascript
+            " . htmlspecialchars($res) . "
+            -->";
+        clearstatcache();
+        // we should do more checking.. return val etc..
+        if (file_exists($output) && filesize($output) && ($max < filemtime($output) ) ) {
+            echo "<!-- file looks like its been generated -->\n";
+            return true;
         }
-        $pdir = realpath(dirname(__FILE__).'/../'. $proj);
-        if (!file_exists($pdir.'/compiled')) {
-            mkdir($pdir.'/compiled', 0755, true);
+        echo '<script type="text/javascript"> alert('. json_encode("Error: Javascript Compile failed\n" . $res) .');</script>';
+     
+        
+        echo "<!-- JS COMPILE ERROR: packed file did not exist  -->";
+        return false;
+        
+    }
+    
+    // depricated verison using seed.
+    function packSeed($files, $output, $translation_base=false)
+    {
+        
+         
+        $o = HTML_FlexyFramework::get()->Pman_Core;
+        
+        if (empty($o['packseed']) || !file_exists($o['jspacker'].'/pack.js')) {
+            echo '<!-- JS COMPILE ERROR: option: Pman_Core[jspacker] not set to directory -->';
+            return false;
             
         }
-        copy($src , $pdir.'/compiled/'. $proj .'.js');
+        require_once 'System.php';
+        $seed= System::which('seed');
+        $gjs = System::which('gjs');
         
-        // copy the translation strings.
-        $src = realpath(dirname(__FILE__).'/../../_compiled_tmp_/'.$proj .'/build/_translation_.js');
-       // var_dump($src);
+        if (!$seed && !$gjs) {
+            echo '<!-- seed or gjs are  not installed -->';
+            return false;
+            
+        }
+        $targetm = file_exists($output) && filesize($output) ? filemtime($output) : 0;
+        $max = 0;
+        $ofiles = array();
+        foreach($files as $f => $mt) {
+            $max = max($max,$mt);
+            $ofiles[] = escapeshellarg($f);
+        }
+        if ($max < $targetm) {
+            echo '<!--  use cached compile. -->';
+            return true;
+        }
+        //var_dump($output);
+        if (!file_exists(dirname($output))) {
+            mkdir(dirname($output), 0755, true);
+        }
+        $lsort = create_function('$a,$b','return strlen($a) > strlen($b) ? 1 : -1;');
+        usort($ofiles, $lsort);
         
-        $pdir = realpath(dirname(__FILE__).'/../'. $proj);
-       
-        copy($src , $pdir.'/compiled/_translation_.js');
+        //$eoutput = " -k  -o " . escapeshellarg($output) ; // with whitespace..
+        $eoutput = "  -o " . escapeshellarg($output) ;
+                   
+        if (  $translation_base) {
+            $toutput = " -t ". escapeshellarg(preg_replace('/\.js$/', '.__translation__.js', $output)) .
+                    " -p " . escapeshellarg($translation_base) ;//." -k "; // this kills the compression.
+                    
+        }
         
-        if ($svn) {
-            $base = getcwd();
-            chdir($pdir);
-            $cmd = "$svn add compiled";
-            `$cmd`;
-            $cmd = "$svn add ". escapeshellarg('compiled/'.$proj .'.js'); 
-            $cmd = "$svn add ". escapeshellarg('compiled/_translation_.js'); 
+        
+        $cmd = ($seed ?
+             "$seed {$o['packseed']}/pack.js " :
+             "$gjs -I {$o['packseed']} -I {$o['packseed']}/JSDOC  {$o['packseed']}/pack.js -- -- " 
+              
+             ) . " $eoutput  $toutput " . implode($ofiles, ' ') . ' 2>&1';
+        //echo "<PRE>$cmd\n";
+        //echo `$cmd`;
+        
+         echo "<!-- Compile javascript
+          
+            " . htmlspecialchars($cmd) . "
+            
+            -->";
+            
+       // return false;
+        
+        $res = `$cmd`;
+        //exit;
+        file_put_contents($output.'.log', $cmd."\n\n". $res);
+        // since this only appears when we change.. it's ok to dump it out..
+        echo "<!-- Compiled javascript
+            " . htmlspecialchars($res) . "
+            -->";
+            
+        // we should do more checking.. return val etc..
+        if (file_exists($output) && ($max < filemtime($output) ) ) {
             
-            `$cmd`;
-            `$svn commit -m 'update compiled version'`;
-            chdir($base);
+            return true;
+        }
+        
+         
+        echo "\n<!-- JS COMPILE ERROR: packed file did not exist  -->\n";
+        return false;
+        
+    }
+    
+    
+    /***
+     * build:
+     *
+     * @param {String} $proj name of Pman component to build
+     * runs pack.js -m {proj} -a $src/*.js
+     * 
+     *
+     */
+      
+    function build($proj) 
+    {
+        echo "Building $proj\n";
+       // var_dump($proj);
+        if (empty($proj)) {
+            $this->err = "no project";
+            if ($this->cli) echo $this->err;
+            return;
         }
+        // first item in path is always the app start directory..
+        $src= array_shift(explode(PATH_SEPARATOR, ini_get('include_path'))) .'/Pman/'. $proj;
+        
         
         
+       //$tmp = ini_get('session.save_path')."/{$proj}_". posix_getuid(). '_'.md5($src);
+        
+        
+        require_once 'System.php';
+        $seed= System::which('seed');
+        if (!$seed) {
+            $this->err ="no seed installed";
+            if ($this->cli) echo $this->err;
+            return false;
+        }
+        
+        $o = HTML_FlexyFramework::get()->Pman_Core;
+        
+        if (empty($o['packseed']) || !file_exists($o['packseed'].'/pack.js')) {
+            $this->err ="no jstoolkit path set [Pman_Core][packseed] to the
+                    introspection documentation directory where pack.js is located.";
+            if ($this->cli) echo $this->err;
+            return false;
+        }  
+        
+        // should we be more specirfic!??!?!?
+         
+        $cmd = "$seed {$o['packseed']}/pack.js -m $proj  -a  $src/*.js";
+        echo "$cmd\n";
+        passthru($cmd);
+        // technically we should trash old compiled files.. 
+        // or we move towards a 'cache in session directory model..'
+        
         
         /*
         
@@ -182,7 +521,8 @@ class Pman_Core_JsCompile  extends Pman
     }
     
     function gatherProjects() {
-        $src =  realpath(dirname(__FILE__).'/../');
+        $src= array_shift(explode(PATH_SEPARATOR, ini_get('include_path'))) .'/Pman';
+        
         $ret = array();
         foreach(scandir($src) as $f) {
             if (!strlen($f) || $f[0] == '.') {