<?php
/**
 * swfObject Plugin
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     i-net software <tools@inetsoftware.de>
 * @author     Gerry Weissbach <gweissbach@inetsoftware.de>
 */

 
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
 
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_swfobject extends DokuWiki_Syntax_Plugin {

	var $saveData = array();
	var $swfID = array();

	function getInfo(){
        return array(
            'author' => 'i-net software',
            'email'  => 'tools@inetsoftware.de',
            'date'   => '2010-03-18',
            'name'   => 'swfObject',
            'desc'   => 'The Plugin wraps the SWFObject which can display an alternative if Flash is not present.',
        );
    }
 
    function getType(){ return 'protected';}
    function getAllowedTypes() { return array('container','substition','protected','disabled','formatting','paragraphs'); }
    function getPType(){ return 'block';}

	function getSort(){ return 194; }
	function connectTo($mode) {       
		$this->Lexer->addEntryPattern('<swfobject\s[^\r\n\|]*?>(?=.*?</swfobject.*?>)',$mode,'plugin_swfobject');
	}

	function postConnect() {
		$this->Lexer->addExitPattern('</swfobject.*?>', 'plugin_swfobject');
	}

	/**
	 * Handle the match
	 */
	function handle($match, $state, $pos, &$handler){

		switch ($state) {
			case DOKU_LEXER_ENTER:
				if( preg_match('%<swfobject\s([^\r\n\|]*?)>%', $match, $matches) ) {

					$conf = split('\?', $matches[1], 2);

					$return = array(	'swffile' => $conf[0],
										'width' => $this->getConf('width'),
										'height' => $this->getConf('height'),
										'minfla' => $this->getConf('minfla'), 
										'skiplinux' => $this->getConf('skiplinux'),
										'autowidth' => $this->getConf('autowidth'),
										'param' => array(
															'play' => 'true',
															'loop' => 'false',
															'menu' => 'false',
															'quality' => 'autohigh',
															'scale' => 'default',
															'salign' => '',
															'wmode' => 'transparent',
															'bgcolor' => '',
															'base' => '',
															'swliveconnect' => 'false',
															'flashvars' => '',
															'devicefont' => 'true',
															'allowscriptaccess' => 'false',
															'seamlesstabbing' => 'false',
															'allowfullscreen' => 'false',
															'allownetworking' => 'true'
										)
									);

					$conf = explode('&', $conf[1]);
					foreach ( $conf AS $keyValue ) {
						list ($key, $value) = explode('=', $keyValue);
						if (empty($key)) { continue; }

						if ( substr($value, 0, 1) == ':' )
							$value = ml(cleanID($value));

						if ( in_array(strtolower($key), array_keys($return['param'])) ) {
							$return['param'][strtolower($key)] = strtolower($value);
						} else if ( in_array(strtolower($key), array_keys($return)) ) {
								$return[strtolower($key)] = $value;
						} else {
								if ( !empty($return['param']['flashvars']) )
									$return['param']['flashvars'] .= '&';
								$return['param']['flashvars'] .= "$key=$value";
						}
					}

					return array('SWFOBJECT__ENTER', $return);
			}

			break;

			case DOKU_LEXER_UNMATCHED:
					return array('SWFOBJECT__UNMATCHED', $match);
			break;

			case DOKU_LEXER_EXIT:
					return array('SWFOBJECT__EXIT', $match);
			break;
        }
        return false;
    }
 
	/**
	 * Create output
	 */
	function render($mode, &$renderer, $inputData) {
		global $conf;
		
		if($mode == 'xhtml'){

			list( $state, $data) = $inputData;
			switch ( $state ) {
				case 'SWFOBJECT__ENTER' : 
					$this->saveData[] = $data;
					//Alternative Content
					$swfID = "SWFObject__Alternative" . rand(0, 1000000);
					$this->swfID[] = $swfID;

					$renderer->doc .= <<<OUTPUT
				<div id="$swfID" class="swfobject alternate show">
				<!-- DEFAULT CONTENT -->
OUTPUT;
					return true;
					break;

				case 'SWFOBJECT__UNMATCHED' : 
					$renderer->doc .= $renderer->_xmlEntities($data);

					return true;
					break;

				case 'SWFOBJECT__EXIT' : 
				
					$data = array_pop($this->saveData);
					$swfID = array_pop($this->swfID);

					$skipLinux = $data['skiplinux'] ? " && clientPC.indexOf('linux') == -1 ": '';

					$file = ml($data['swffile'], null, true, '&');

					$flashvars = "";
					$params = "";
					if ( is_array($data['param']) ) {
						foreach( array_keys($data['param']) AS $paramKeys ) {
							if ( empty( $paramKeys ) || empty($data['param'][$paramKeys]) ) { continue; }
							if ( !empty($params) ) { $params.= ','; }
							$params .= $paramKeys .':\''. $data['param'][$paramKeys] . '\'';
						}
					}

					$attributes = "styleclass: 'swfobject'";
					$autoWidth = '';
					if ( $data['autowidth'] ) {
						$autoWidth = "$('$swfID').style.width = \"100%\";";
					}

					$DOKU_BASE = DOKU_BASE;
					$XI = ( $this->getConf("useExpressInstall") ) ? "\"{$DOKU_BASE}lib/plugins/swfobject/expressinstall.swf\"" : "null";
					$JS = <<<JSOUTPUT
					
					var counter$swfID = 10;
					var addSWF$swfID = function () {
					
						if ( counter$swfID <= 0 ) { if ( $('$swfID') ) $('$swfID').className += ' show'; return; }
						if ( typeof addInitEvent == "undefined" ) { counter$swfID--; window.setTimeout("addSWF$swfID", 100); return; }
					
						addInitEvent( function() {
							if ( typeof swfobject != "undefined" $skipLinux) {
								swfobject.embedSWF("$file", "$swfID", "{$data['width']}", "{$data['height']}", "{$data['minfla']}", $XI, { $flashvars }, { $params }, { $attributes }, null );
								$autoWidth
							} else {
								if ( $('$swfID') ) $('$swfID').className += ' show';
							}
						});
					};
					
					if ( document.getElementById('$swfID') ) document.getElementById('$swfID').className = document.getElementById('$swfID').className.substr( 0, document.getElementById('$swfID').className.lastIndexOf("show")-1 );
					addSWF$swfID();
					
JSOUTPUT;
					if ( $conf['compress'] ) $JS = $this->js_compress($JS);
					$renderer->doc .= <<<OUTPUT

				</div>

				<script type="text/javascript">{$JS}</script>
OUTPUT;
				break;
				return true;
			}
		}
		return false;
	}

	/**
	 * Strip comments and whitespaces from given JavaScript Code
	 *
	 * This is a port of Nick Galbreath's python tool jsstrip.py which is
	 * released under BSD license. See link for original code.
	 * 
	 * This was taken from the Core.
	 *
	 * @author Nick Galbreath <nickg@modp.com>
	 * @author Andreas Gohr <andi@splitbrain.org>
	 * @link   http://code.google.com/p/jsstrip/
	 */
	function js_compress($s){
		
	    $s = ltrim($s);     // strip all initial whitespace
	    $s .= "\n";
	    $i = 0;             // char index for input string
	    $j = 0;             // char forward index for input string
	    $line = 0;          // line number of file (close to it anyways)
	    $slen = strlen($s); // size of input string
	    $lch  = '';         // last char added
	    $result = '';       // we store the final result here
	
	    // items that don't need spaces next to them
	    $chars = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r'\"[]";
	
	    while($i < $slen){
	        // skip all "boring" characters.  This is either
	        // reserved word (e.g. "for", "else", "if") or a
	        // variable/object/method (e.g. "foo.color")
	        while ($i < $slen && (strpos($chars,$s[$i]) === false) ){
	            $result .= $s{$i};
	            $i = $i + 1;
	        }
	
	        $ch = $s{$i};
	        // multiline comments (keeping IE conditionals)
	        if($ch == '/' && $s{$i+1} == '*' && $s{$i+2} != '@'){
	            $endC = strpos($s,'*/',$i+2);
	            if($endC === false) trigger_error('Found invalid /*..*/ comment', E_USER_ERROR);
	            $i = $endC + 2;
	            continue;
	        }
	
	        // singleline
	        if($ch == '/' && $s{$i+1} == '/'){
	            $endC = strpos($s,"\n",$i+2);
	            if($endC === false) trigger_error('Invalid comment', E_USER_ERROR);
	            $i = $endC;
	            continue;
	        }
	
	        // tricky.  might be an RE
	        if($ch == '/'){
	            // rewind, skip white space
	            $j = 1;
	            while($s{$i-$j} == ' '){
	                $j = $j + 1;
	            }
	            if( ($s{$i-$j} == '=') || ($s{$i-$j} == '(') ){
	                // yes, this is an re
	                // now move forward and find the end of it
	                $j = 1;
	                while($s{$i+$j} != '/'){
	                    while( ($s{$i+$j} != '\\') && ($s{$i+$j} != '/')){
	                        $j = $j + 1;
	                    }
	                    if($s{$i+$j} == '\\') $j = $j + 2;
	                }
	                $result .= substr($s,$i,$j+1);
	                $i = $i + $j + 1;
	                continue;
	            }
	        }
	
	        // double quote strings
	        if($ch == '"'){
	            $j = 1;
	            while( $s{$i+$j} != '"' && ($i+$j < $slen)){
	                if( $s{$i+$j} == '\\' && ($s{$i+$j+1} == '"' || $s{$i+$j+1} == '\\') ){
	                    $j += 2;
	                }else{
	                    $j += 1;
	                }
	            }
	            $result .= substr($s,$i,$j+1);
	            $i = $i + $j + 1;
	            continue;
	        }
	
	        // single quote strings
	        if($ch == "'"){
	            $j = 1;
	            while( $s{$i+$j} != "'" && ($i+$j < $slen)){
	                if( $s{$i+$j} == '\\' && ($s{$i+$j+1} == "'" || $s{$i+$j+1} == '\\') ){
	                    $j += 2;
	                }else{
	                    $j += 1;
	                }
	            }
	            $result .= substr($s,$i,$j+1);
	            $i = $i + $j + 1;
	            continue;
	        }
	
	        // whitespaces
	        if( $ch == ' ' || $ch == "\r" || $ch == "\n" || $ch == "\t" ){
	            // leading spaces
	            if($i+1 < $slen && (strpos($chars,$s[$i+1]) !== false)){
	                $i = $i + 1;
	                continue;
	            }
	            // trailing spaces
	            //  if this ch is space AND the last char processed
	            //  is special, then skip the space
	            $lch = substr($result,-1);
	            if($lch && (strpos($chars,$lch) !== false)){
	                $i = $i + 1;
	                continue;
	            }
	            // else after all of this convert the "whitespace" to
	            // a single space.  It will get appended below
	            $ch = ' ';
	        }
	
	        // other chars
	        $result .= $ch;
	        $i = $i + 1;
	    }
	
	    return trim($result);
	}
}
  
//Setup VIM: ex: et ts=4 enc=utf-8 :