* @license PHP License * @package WB * @subpackage base */ WBClass::load('WBHtml'); /** * Insert HTML * * Basic interface to insert some HTML * * @version 0.3.0 * @package WB * @subpackage html */ class WBHtml_JS extends WBHtml { /** * file type: any */ const TYPE_ANY = 0; /** * file type: js */ const TYPE_JS = 1; /** * file type: css */ const TYPE_CSS = 2; /** * JavaScript Area: include a file */ const AREA_INCLUDE = 1; /** * JavaScript Area: things to do on load */ const AREA_ONLOAD = 2; /** * JavaScript Area: include some lines of code */ const AREA_CODE = 4; /** * JavaScript Area: some code below content */ const AREA_FOOT = 8; /** * template to include files */ const FMT_INCLUDE = ''; /** * template to include code snippets */ const FMT_CODE = ''; /** * list of included files * @var array */ private static $included = array(); /** * complet javascript buffer * @see finalize() * @var array */ private static $bufferCode = array(); /** * complet javascript buffer * @see finalize() * @var array */ private static $bufferFoot = array(); /** * static constructor * * make sure that basic WB class is always loaded */ public static function staticConstruct() { $file = WBClass::create('WBFile'); $file->mkdir('var/cache/javascript'); WBHtml::addFinalizer(array(__CLASS__, 'finalize')); } public static function getIncluded($flush = false) { $inc = self::$included; if ($flush) { self::$included = array(); } return $inc; } /** * add Javascript * * add string that will be included in HTML at the end * * @param string $html * @param in $area */ public static function add($js, $area = self::AREA_INCLUDE) { switch ($area) { case self::AREA_INCLUDE: $js = ltrim($js, '/'); // include only once if (isset(self::$included[$js])) { ++self::$included[$js]; return; } self::$included[$js] = 1; return; break; case self::AREA_CODE: if (WBParam::get('wb/html/js/include', 'bulk')) { self::$bufferCode[] = array( 'type' => 'code', 'load' => $js ); return; } $html = sprintf(self::FMT_CODE, $js); $des = parent::AREA_HEAD; break; case self::AREA_ONLOAD: $html = $js; $des = parent::AREA_JS_ONLOAD; break; case self::AREA_FOOT: self::$bufferFoot[] = $js; return; break; default: parent::checkArea(null); return; break; } parent::add($html, $des); } /** * finalize * * Build bulk file if requzired. Append all included JavaScript files * and code snippets to a single bulk. */ public static function finalize() { foreach (self::$included as $js => $count) { if (WBParam::get('wb/html/js/include', 'bulk') == 'bulk') { self::$bufferCode[] = array( 'type' => 'file', 'load' => $js ); continue; } // actually load class parent::add(sprintf(self::FMT_INCLUDE, $js), parent::AREA_HEAD); // tell class loader that file was loaded $js = str_replace('/', '.', $js); array_unshift(self::$bufferFoot, sprintf('WB.Class.loaded["%s"] = 1;', $js)); } // add foot if (!empty(self::$bufferFoot)) { $html = sprintf(self::FMT_CODE, implode("\n", self::$bufferFoot)); parent::add($html, parent::AREA_FOOT); } self::$bufferFoot = array(); // normal include if (WBParam::get('wb/html/js/include', 'bulk') != 'bulk') { return; } // shortcut for empty buffer if (empty(self::$bufferCode)) { return; } $md5 = md5(serialize(self::$bufferCode)); $dir = WBParam::get('wb/dir/base') . '/var/cache/javascript/bulk'; $file = $dir . '/' . $md5; $html = sprintf(self::FMT_INCLUDE, '?cs=' . $md5); parent::add($html, parent::AREA_HEAD); // in case file exists, cache file must be younger than youngest file if (file_exists($file)) { $maxMTime = 0; foreach (self::$bufferCode as $b) { if ($b['type'] != 'file') { continue; } $maxMTime = max($maxMTime, filemtime(self::realpath($b['load']))); } if (filemtime($file) > $maxMTime) { return; } // remove cache file unlink($file); // in case file does not exists, make sure folder exists } else if (!is_dir($dir)) { mkdir($dir, 0777, true); chmod($dir, 0777); } // create bulk JavaScript file touch($file); // first run: create actual bulk file foreach (self::$bufferCode as $b) { switch ($b['type']) { case 'file': $real = self::realpath($b['load']); if (empty($real)) { // echo 'leer
' . var_export($b, true) . "\n"; } file_put_contents($file, '// file: ' . $b['load'] . "\n", FILE_APPEND); $js = file_get_contents(self::realpath($b['load'])); break; case 'code': file_put_contents($file, '// code: ' . strlen($b['load']) . "\n", FILE_APPEND); $js = $b['load']; break; } file_put_contents($file, $js . "\n", FILE_APPEND); } // second run: tell loaded that files where included foreach (self::$bufferCode as $b) { switch ($b['type']) { case 'file': $js = str_replace('/', '.', $b['load']); file_put_contents($file, sprintf('WB.Class.loaded["%s"] = 1;' . "\n", $js), FILE_APPEND); break; case 'code': break; } } chmod($file, 0666); self::$bufferCode = array(); } /** * resolve path of JavaScript file * * Like the PHP funktion realpath(), it resolves the actual path * of a JavaScript file. In case the requested file is neither in SYSTEMDIR * nor in BASEDIR, the result will be empty. * * @see realpath() * @param $js * @param $type * @return string */ public static function realpath($js, &$type = null) { // remove optional ".js" $ext = 'js'; $type = self::TYPE_JS; if (strpos($js, '.')) { $tmp = explode('.', $js); if (end($tmp) == 'js') { array_pop($tmp); } else if (end($tmp) == 'css') { $ext = array_pop($tmp); $type = self::TYPE_CSS; } else { $ext = array_pop($tmp); $type = self::TYPE_ANY; } $js = implode('.', $tmp); } if ($js[0] != '/') { $js = '/' . $js; } // try to locate file in base dir and in system dir $dir = realpath(WBParam::get('wb/dir/base') . '/resource/js'); $file = realpath($dir . $js . '.' . $ext); if (!file_exists($file)) { $dir = realpath(WBParam::get('wb/dir/system') . '/resource/js'); $file = realpath($dir . $js . '.' . $ext); } if(empty($file)) { // tweek for Xinha because it sometimes uses wrong cases if (strncmp($js, '/WB/XinhaCore/', 14) == 0) { $js = explode('/', $js); $last = array_pop($js); $last = ucfirst(strtolower($last)); $js[] = $last; $js = implode('/', $js); // try to locate file in base dir and in system dir $dir = realpath(WBParam::get('wb/dir/base') . '/resource/js'); $file = realpath($dir . $js . '.' . $ext); if (!file_exists($file)) { $dir = realpath(WBParam::get('wb/dir/system') . '/resource/js'); $file = realpath($dir . $js . '.' . $ext); } return $file; } return ''; } // avoid to break out of sysem/base dir if (strncmp($dir, $file, strlen($dir)) != 0) { WBClass::load('WBException_Argument'); throw new WBException_Argument('".." are not allowed in JavaScript path', 2, __CLASS__); } return $file; } /** * receive path of buld file * * @param String $md5 * @return string */ public static function getBulkPath($md5) { $dir = WBParam::get('wb/dir/base') . '/var/cache/javascript/bulk'; $file = $dir . '/' . $md5; if (file_exists($file)) { return $file; } return ''; } } ?>