FW_HTML_Controller: eine Erweiterung des Standart-Controllers um Tools für die HTML-Generierung zur Verfügung zu stellen.
/** (c) 2010 Arne "w13531" Wenzel [ mailto: w13531 (at) terrorhippiecrew (dot) net ] **/
abstract class FW_HTML_Controller extends FW_Controller {
protected $view_html = null; //HTML Template
protected $view_outer = null; //Business Template
protected $view_inner = null; //Content Template
private $use_cache = false; //enable caching
/**
* constructor
**/
public function __construct(array $params = null) {
parent::__construct($params);
//HTML Template(cached, optionally)
$this->view_html = FW_Workbench::ClassLoader('FW_HTML_Cached_View', array('file' => DR . 'resources' . DS . 'tpl' . DS . 'html.tpl', 'cache_id' => strtolower($this->request->getServer('request_uri')), 'expire' => 900));
//Business Template(non-cached, included in view_html)
$this->view_outer = FW_Workbench::ClassLoader('FW_HTML_View', DR . 'resources' . DS . 'tpl' . DS . 'outer.tpl');
//headers
$this->response->addHeader('Last-Modified', gmdate("D, d M Y H:i:s", time()) . ' GMT');
$this->response->addHeader('Expires', gmdate ('D, d M Y H:i:s', time() + 2592000) . ' GMT');
$this->response->addHeader('Content-type', 'text/html');
}
/**
* enables caching
**/
protected function enableCaching() {
$this->use_cache = true;
}
/**
* disables caching
**/
protected function disableCaching() {
$this->use_cache = false;
}
/**
* shows data from xml in a tpl file
* HTML Cache support
**/
protected function view_xml_action(array $params = null) {
$tpl_file = DR . 'resources' . DS . 'tpl' . DS . strtolower($params[0]) . '.tpl';
$xml_file = DR . 'resources' . DS . 'xml' . DS . strtolower($params[0]) . '.xml';
//Content Template and XML File exists???
if(file_exists($tpl_file) && file_exists($xml_file) && filesize($xml_file) > 0) {
if(!$this->use_cache || !$this->view_html->is_cached()) { //wenn nicht gecached
//get XML as array
$xml = FW_Workbench::ClassLoader('FW_XML_File_Model', DR . 'resources' . DS . 'xml' . DS . strtolower($params[0]) . '.xml')->XMLFile2array();
//get content template
$this->view_inner = FW_Workbench::ClassLoader('FW_HTML_View', DR . 'resources' . DS . 'tpl' . DS . strtolower($params[0]) . '.tpl');
//get global meta
$global_meta = FW_Config::getInstance()->get('meta');
//get local meta
if(!empty($xml['meta'])) {
$local_meta = array_filter($xml['meta']);
} else {
$local_meta = array();
}
//set meta in HTML Template
$this->view_html->set('meta', array_merge($global_meta, $local_meta));
//set Content in Content Template
$this->view_inner->set('data', $xml['data']);
}
} else {
$this->response->redirect($this->request, $this->response, 'Error', 'error_400');
}
}
/**
* renders a page and outputs it in browser
* HTML Cache support
**/
protected function render() {
if($this->use_cache && $this->view_html->is_cached()) {
$this->response->addContent($this->minify($this->view_html->fetch_cache()));
} else {
if(!function_exists('flashtool')) {
function flashtool($var1,$var2,$var3,$var4) {
return FW_HTML_Controller::flashtool($var1,$var2,$var3,$var4);
}
}
$flashtool = "flashtool";
if($this->view_inner != null) {
$this->view_inner->set('flashtool', $flashtool);
$this->view_outer->set('content', $this->view_inner);
}
$this->view_outer->set("flashtool", $flashtool);
$this->view_html->set('content', $this->view_outer);
if($this->use_cache) {
$this->response->addContent($this->minify($this->view_html->fetch_cache()));
} else {
$this->response->addContent($this->minify($this->view_html->fetch()));
}
}
}
/**
* TODO: shows data from a db in the templates
**/
/*protected function view_db_action(array $params = null) {
if(!empty($params)) {
$db = FW_DB_Model::getInstance(FW_Config::getInstance()->get('DB'));
$result = $db->read('sites', '*', "name LIKE " . $db->quote($params[0]) . ";");
if(!empty($result)) {
$global_meta = FW_Config::get_instance()->get('meta');
$local_meta = array_filter(array('title' => $result[0]['meta_title'], 'creator' => $result[0]['meta_creator'],
'description' => $result[0]['meta_description'], 'keywords' => $result[0]['meta_keywords'],
'publisher' => $result[0]['meta_publisher'], 'identifier' => $result[0]['meta_identifier'],
'language' => $result[0]['meta_language'], 'rights' => $result[0]['meta_rights'],
'robots' => $result[0]['meta_robots'], 'region' => $result[0]['meta_region'],
'placename' => $result[0]['meta_placename'], 'position' => $result[0]['meta_position'],
'ICBM' => $result[0]['meta_ICBM'], 'favicon_path' => $result[0]['meta_favicon_path'],
'css_path' => $result[0]['meta_css_path'], 'js_path' => $result[0]['meta_js_path']));
$meta = array_merge($global_meta, $local_meta);
$this->view_outer->set('content', $result[0]['content']);
$this->view_html->set('meta', $meta);
$this->view_html->set('content', $this->view_outer);
if($this->request->getHeader('accept_encoding') && strpos($this->request->getHeader('accept_encoding'), 'gzip') !== false) {
$this->response->addContent(gzencode($this->view_html->fetch(), 9));
} else {
$this->response->addContent($this->view_html->fetch());
}
} else {
$this->response->redirect($this->request, $this->response, 'Error', 'error_404');
}
} else {
$this->response->redirect($this->request, $this->response, 'Error', 'error_400');
}
}*/
/**
* Minifies HTML Code
**/
protected function minify($str_output) {
if(DEVELOPMENT_ENVIRONMENT == false) {
//Remove HTML Commentary
$str_output = preg_replace('/<!--.+?-->/s', '', $str_output);
//Remove newlines and blanks between tags
$str_output = preg_replace(array('/>\s+/', '/\s+</', '/[\r\n]+/'), array('>', '<', ' '), $str_output);
//Remove tabs
$str_output = str_replace("\t", ' ', $str_output);
//Remove +1 blanks
$str_output = preg_replace('/ +/', ' ', $str_output);
}
return $str_output;
}
/**
* provides flash include
**/
public static function flashtool($width, $height, $file, $name="Flash Movie") {
$string = "<script type=\"text/javascript\">
if (AC_FL_RunContent == 0) {
alert(\"Diese Seite erfordert die Datei AC_RunActiveContent.js\");
} else {
AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0',
'width', '".$width."',
'height', '".$height."',
'src', '".$file."',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'transparent',
'devicefont', 'false',
'id', 'image_view',
'bgcolor', '#ffffff',
'name', '".$name."',
'menu', 'true',
'allowScriptAccess','sameDomain','movie', '".$file."','salign', ''
);
}
</script>
<noscript><div>
<object type=\"application/x-shockwave-flash\" data=\"".$file."\" width=\"".$width."\" height=\"".$height."\">
<param name=\"movie\" value=\"".$file."\" />
<param name=\"wmode\" value=\"transparent\" />
</object>
</div></noscript>";
return $string;
}
}
FW_Resources_Controller: eine Erweiterung des FW_Controllers, sie ist der Resource-Mapper, d.h. ich bekomme über Ihn Zugang zum Resources-Verzeichnis, spezielle Operationen die mit Dateitypen ausgeführt werden(hier CSS/JS) können auch definiert werden. Also wenn z.B. eine spezielle XML-Aktion ausgeführt werden soll muss hier eine xml_action existieren, sonst wird die Standart-Funktion inkl. Parameter aufgerufen. von Aussen sieht es aus wie eine Normale URL, trozdem läuft Sie über den definierten Entry Point, so kann man genau definieren, wer zu was Zugang haben darf und zu was nicht. Die css_action minimiert Stylesheets und bindet Bilder via DATA-URI ein, die js_action minimiert Javascripts. Bei Abhänigkeiten von Javascripten müssen die Dateien so benannt werden, das diese Aufgelöst werden können. Beide Actions legen, wenn gewünscht Cache-Files an, Sie minimieren alle Dateien die im CSS/JS Verzeichnis mit der jeweiligen Dateiendung liegen.
/** (c) 2010 Arne "w13531" Wenzel [ mailto: w13531 (at) terrorhippiecrew (dot) net ] **/
abstract class FW_Resources_Controller extends FW_Controller {
/**
* default action
**/
function index_action(array $params = null) {
if(!empty($params)) {
foreach($params as $value) {
$path .= DS . $value;
}
$data_path = DR . 'resources' . $path;
$this->log(date('H:i:s', time()) . "\t" . __CLASS__ . ':' . __FUNCTION__ . '() serves file: ' . $data_path);
if(file_exists($data_path)) {
//set headers
$this->response->addHeader('Content-type', $this->detect_mime(basename($data_path)));
$this->response->addHeader('Last-Modified', gmdate("D, d M Y H:i:s", filemtime($data_path)) . ' GMT');
$this->response->addHeader('Expires', gmdate ('D, d M Y H:i:s', time() + 2592000) . ' GMT');
$this->response->addContent(@file_get_contents($data_path));
} else {
$this->response->redirect($this->request, $this->response, 'error', 'error_404', $params);
}
}
}
/**
* JavaScript Compressor
* Removes useless Characters
* Caches
**/
public function js_action(array $params = null) {
//configuration
$config = FW_Config::getInstance()->get('js_caching');
$std_conf = array('js_cache' => DR . 'tmp' . DS . 'cache' . DS . 'vscript.cache', 'refresh_time' => 60 * 60 * 24, 'js_caching' => false);
$js_files = glob(DR . 'resources' . DS . 'js' . DS . '*.js');
if(!empty($config)) {
$config = array_merge($std_conf, $config);
} else{
$config = $std_conf;
}
//set headers
$this->response->addHeader('Content-type', 'text/javascript');
$this->response->addHeader('Last-Modified', gmdate("D, d M Y H:i:s", filemtime($config['js_cache'])) . ' GMT');
$this->response->addHeader('Expires', gmdate ('D, d M Y H:i:s', time() + 2592000) . ' GMT');
//caching
if($config['js_caching'] && file_exists($config['js_cache']) && (time() - filemtime($config['js_cache'])) < $config['refresh_time'] && filesize($config['js_cache']) > 10) {
$str_output = file_get_contents($config['js_cache']);
$this->log(date('H:i:s', time()) . "\t" . __CLASS__ . ':' . __FUNCTION__ . '() serves cache file: ' . $config['js_cache']);
} else {
$this->log(date('H:i:s', time()) . "\t" . __CLASS__ . ':' . __FUNCTION__ . '() creates cache file: ' . $config['js_cache']);
$str_output = '';
if(!empty($js_files)) {
foreach($js_files as $value) {
if(file_exists($value)) {
$str_output .= file_get_contents($value);
}
}
}
// Remove comments
$str_output = preg_replace('#((?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:\/\/.*))#', '', $str_output);
// Remove tabs
$str_output = str_replace("\t", ' ', $str_output);
//Convert \r\n to \n
$str_output = str_replace("\r\n", "\n", $str_output);
//Remove +1 blanks
$str_output = preg_replace("/ +/", ' ', $str_output);
//Remove +1 blank newlines
$str_output = preg_replace("/ +\n/", "\n", $str_output);
//Remove +1 newlines
$str_output = trim(preg_replace("/\n+/", "\n", $str_output));
//refresh cache
if($config['js_caching']) {
file_put_contents($config['js_cache'], $str_output);
}
}
//send to browser
$this->response->addContent($str_output);
}
/**
* CSS Compressor
* Removes useless characters
* Inludes Pictures via DataURI
* Caches
**/
public function css_action(array $params = null) {
//configuration
$config = FW_Config::getInstance()->get('css_caching');
$std_conf = array('css_cache' => DR . 'tmp' . DS . 'cache' . DS . 'vstyle.cache', 'refresh_time' => 60 * 60 * 24, 'css_caching' => false);
$css_files = glob(DR . 'resources' . DS . 'css' . DS . '*.css');
if(!empty($config)) {
$config = array_merge($std_conf, $config);
} else{
$config = $std_conf;
}
//set headers
$this->response->addHeader('Content-type', 'text/css');
$this->response->addHeader('Last-Modified', gmdate("D, d M Y H:i:s", filemtime($config['css_cache'])) . ' GMT');
$this->response->addHeader('Expires', gmdate ('D, d M Y H:i:s', time() + 2592000) . ' GMT');
//caching
if($config['css_caching'] && file_exists($config['css_cache']) && (time() - filemtime($config['css_cache'])) < $config['refresh_time'] && filesize($config['css_cache']) > 10) {
$str_output = file_get_contents($config['css_cache']);
$this->log(date('H:i:s', time()) . "\t" . __CLASS__ . ':' . __FUNCTION__ . '() serves cache file: ' . $config['css_cache']);
} else {
$this->log(date('H:i:s', time()) . "\t" . __CLASS__ . ':' . __FUNCTION__ . '() creates cache file: ' . $config['css_cache']);
$str_output = '';
if(!empty($css_files)) {
foreach($css_files as $value) {
if(file_exists($value)) {
$str_output .= file_get_contents($value);
}
}
}
//compress
$str_output = preg_replace_callback("#url\((.*)\)#", array($this, 'data_url'), $str_output);
$str_output = str_replace(array("\n","\r","\t"), array("","",""), $str_output);
$str_output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $str_output);
$str_output = preg_replace("/;( *)}( *)/i", "}", $str_output);
$str_output = preg_replace("/( *){( *)/i", "{", $str_output);
$str_output = preg_replace("/;( *)/i", ";", $str_output);
$str_output = str_replace(": ", ":", $str_output);
$str_output = str_replace("'", "", $str_output);
//refresh cache
if($config['css_caching']) {
file_put_contents($config['css_cache'], $str_output);
}
}
//send to browser
$this->response->addContent($str_output);
}
/**
* Creates the DataURIs used by CSS Compressor
**/
private function data_url($matches) {
$base64 = base64_encode(@file_get_contents(DR . 'resources' . DS . 'img' . DS . $matches[1]));
$mime = $this->detect_mime(basename($matches[1]));
return 'url(data:' . $mime . ';base64,' . $base64 . ')';
}
/**
* Detects the mime of the submitted files
**/
private function detect_mime($filename) {
$filetype=strrchr($filename, '.');
switch ($filetype) {
case '.zip': $mime = 'application/zip'; break;
case '.ez': $mime = 'application/andrew-inset'; break;
case '.hqx': $mime = 'application/mac-binhex40'; break;
case '.cpt': $mime = 'application/mac-compactpro'; break;
case '.doc': $mime = 'application/msword'; break;
case '.bin': $mime = 'application/octet-stream'; break;
case '.dms': $mime = 'application/octet-stream'; break;
case '.lha': $mime = 'application/octet-stream'; break;
case '.lzh': $mime = 'application/octet-stream'; break;
case '.exe': $mime = 'application/octet-stream'; break;
case '.class': $mime = 'application/octet-stream'; break;
case '.so': $mime = 'application/octet-stream'; break;
case '.dll': $mime = 'application/octet-stream'; break;
case '.oda': $mime = 'application/oda'; break;
case '.pdf': $mime = 'application/pdf'; break;
case '.ai': $mime = 'application/postscript'; break;
case '.eps': $mime = 'application/postscript'; break;
case '.ps': $mime = 'application/postscript'; break;
case '.smi': $mime = 'application/smil'; break;
case '.smil': $mime = 'application/smil'; break;
case '.xls': $mime = 'application/vnd.ms-excel'; break;
case '.ppt': $mime = 'application/vnd.ms-powerpoint'; break;
case '.wbxml': $mime = 'application/vnd.wap.wbxml'; break;
case '.wmlc': $mime = 'application/vnd.wap.wmlc'; break;
case '.wmlsc': $mime = 'application/vnd.wap.wmlscriptc'; break;
case '.bcpio': $mime = 'application/x-bcpio'; break;
case '.vcd': $mime = 'application/x-cdlink'; break;
case '.pgn': $mime = 'application/x-chess-pgn'; break;
case '.cpio': $mime = 'application/x-cpio'; break;
case '.csh': $mime = 'application/x-csh'; break;
case '.dcr': $mime = 'application/x-director'; break;
case '.dir': $mime = 'application/x-director'; break;
case '.dxr': $mime = 'application/x-director'; break;
case '.dvi': $mime = 'application/x-dvi'; break;
case '.spl': $mime = 'application/x-futuresplash'; break;
case '.gtar': $mime = 'application/x-gtar'; break;
case '.hdf': $mime = 'application/x-hdf'; break;
case '.js': $mime = 'application/x-javascript'; break;
case '.skp': $mime = 'application/x-koan'; break;
case '.skd': $mime = 'application/x-koan'; break;
case '.skt': $mime = 'application/x-koan'; break;
case '.skm': $mime = 'application/x-koan'; break;
case '.latex': $mime = 'application/x-latex'; break;
case '.nc': $mime = 'application/x-netcdf'; break;
case '.cdf': $mime = 'application/x-netcdf'; break;
case '.sh': $mime = 'application/x-sh'; break;
case '.shar': $mime = 'application/x-shar'; break;
case '.swf': $mime = 'application/x-shockwave-flash'; break;
case '.sit': $mime = 'application/x-stuffit'; break;
case '.sv4cpio': $mime = 'application/x-sv4cpio'; break;
case '.sv4crc': $mime = 'application/x-sv4crc'; break;
case '.tar': $mime = 'application/x-tar'; break;
case '.tcl': $mime = 'application/x-tcl'; break;
case '.tex': $mime = 'application/x-tex'; break;
case '.texinfo': $mime = 'application/x-texinfo'; break;
case '.texi': $mime = 'application/x-texinfo'; break;
case '.t': $mime = 'application/x-troff'; break;
case '.tr': $mime = 'application/x-troff'; break;
case '.roff': $mime = 'application/x-troff'; break;
case '.man': $mime = 'application/x-troff-man'; break;
case '.me': $mime = 'application/x-troff-me'; break;
case '.ms': $mime = 'application/x-troff-ms'; break;
case '.ustar': $mime = 'application/x-ustar'; break;
case '.src': $mime = 'application/x-wais-source'; break;
case '.xhtml': $mime = 'application/xhtml+xml'; break;
case '.xht': $mime = 'application/xhtml+xml'; break;
case '.zip': $mime = 'application/zip'; break;
case '.au': $mime = 'audio/basic'; break;
case '.snd': $mime = 'audio/basic'; break;
case '.mid': $mime = 'audio/midi'; break;
case '.midi': $mime = 'audio/midi'; break;
case '.kar': $mime = 'audio/midi'; break;
case '.mpga': $mime = 'audio/mpeg'; break;
case '.mp2': $mime = 'audio/mpeg'; break;
case '.mp3': $mime = 'audio/mpeg'; break;
case '.aif': $mime = 'audio/x-aiff'; break;
case '.aiff': $mime = 'audio/x-aiff'; break;
case '.aifc': $mime = 'audio/x-aiff'; break;
case '.m3u': $mime = 'audio/x-mpegurl'; break;
case '.ram': $mime = 'audio/x-pn-realaudio'; break;
case '.rm': $mime = 'audio/x-pn-realaudio'; break;
case '.rpm': $mime = 'audio/x-pn-realaudio-plugin'; break;
case '.ra': $mime = 'audio/x-realaudio'; break;
case '.wav': $mime = 'audio/x-wav'; break;
case '.pdb': $mime = 'chemical/x-pdb'; break;
case '.xyz': $mime = 'chemical/x-xyz'; break;
case '.bmp': $mime = 'image/bmp'; break;
case '.gif': $mime = 'image/gif'; break;
case '.ief': $mime = 'image/ief'; break;
case '.jpeg': $mime = 'image/jpeg'; break;
case '.jpg': $mime = 'image/jpeg'; break;
case '.jpe': $mime = 'image/jpeg'; break;
case '.png': $mime = 'image/png'; break;
case '.tiff': $mime = 'image/tiff'; break;
case '.tif': $mime = 'image/tiff'; break;
case '.djvu': $mime = 'image/vnd.djvu'; break;
case '.djv': $mime = 'image/vnd.djvu'; break;
case '.wbmp': $mime = 'image/vnd.wap.wbmp'; break;
case '.ras': $mime = 'image/x-cmu-raster'; break;
case '.pnm': $mime = 'image/x-portable-anymap'; break;
case '.pbm': $mime = 'image/x-portable-bitmap'; break;
case '.pgm': $mime = 'image/x-portable-graymap'; break;
case '.ppm': $mime = 'image/x-portable-pixmap'; break;
case '.rgb': $mime = 'image/x-rgb'; break;
case '.xbm': $mime = 'image/x-xbitmap'; break;
case '.xpm': $mime = 'image/x-xpixmap'; break;
case '.xwd': $mime = 'image/x-xwindowdump'; break;
case '.igs': $mime = 'model/iges'; break;
case '.iges': $mime = 'model/iges'; break;
case '.msh': $mime = 'model/mesh'; break;
case '.mesh': $mime = 'model/mesh'; break;
case '.silo': $mime = 'model/mesh'; break;
case '.wrl': $mime = 'model/vrml'; break;
case '.vrml': $mime = 'model/vrml'; break;
case '.css': $mime = 'text/css'; break;
case '.html': $mime = 'text/html'; break;
case '.htm': $mime = 'text/html'; break;
case '.asc': $mime = 'text/plain'; break;
case '.txt': $mime = 'text/plain'; break;
case '.rtx': $mime = 'text/richtext'; break;
case '.rtf': $mime = 'text/rtf'; break;
case '.sgml': $mime = 'text/sgml'; break;
case '.sgm': $mime = 'text/sgml'; break;
case '.tsv': $mime = 'text/tab-separated-values'; break;
case '.wml': $mime = 'text/vnd.wap.wml'; break;
case '.wmls': $mime = 'text/vnd.wap.wmlscript'; break;
case '.etx': $mime = 'text/x-setext'; break;
case '.xml': $mime = 'text/xml'; break;
case '.xsl': $mime = 'text/xml'; break;
case '.mpeg': $mime = 'video/mpeg'; break;
case '.mpg': $mime = 'video/mpeg'; break;
case '.mpe': $mime = 'video/mpeg'; break;
case '.qt': $mime = 'video/quicktime'; break;
case '.mov': $mime = 'video/quicktime'; break;
case '.mxu': $mime = 'video/vnd.mpegurl'; break;
case '.avi': $mime = 'video/x-msvideo'; break;
case '.movie': $mime = 'video/x-sgi-movie'; break;
case '.asf': $mime = 'video/x-ms-asf'; break;
case '.asx': $mime = 'video/x-ms-asf'; break;
case '.wm': $mime = 'video/x-ms-wm'; break;
case '.wmv': $mime = 'video/x-ms-wmv'; break;
case '.wvx': $mime = 'video/x-ms-wvx'; break;
case '.ice': $mime = 'x-conference/x-cooltalk'; break;
}
return $mime;
}
}