PHP Classes
Icontem

File: QVizualisationGoogleGraph.class.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Tom Schaefer  >  QGoogleVisualizationAPI  >  QVizualisationGoogleGraph.class.php  
File: QVizualisationGoogleGraph.class.php
Role: Class source
Content type: text/plain
Description: Visualization Class
Class: QGoogleVisualizationAPI
Google Visualization API (deprecated)
 

Contents

Class file image Download
<?php

/**
 * Wrapper for Google Visualisation API
 * Visualisation Class
 * 
 * wraps all Google Visualisation Types dynamically and 
 * in a generic way
 * 
 * holds common functions for API to generate Javascript source code
 *
 * @author Thomas Sch&#65533;fer
 * @since 2008-06-29
 * 
 */
class QVizualisationGoogleGraph extends QGoogleGraph {
	
	/**
	 * version
	 *
	 * @var integer
	 */
	private $vizApi = 1;
	
	protected $vizualisationScope = "google.visualization";
	
	/**
	 * basic reference link
	 *
	 * @var string
	 */
	private $vizReference = "http://code.google.com/apis/visualization/documentation/gallery/";
	
	/**
	 * holder of context node => name of visualisation type
	 *
	 * @var string
	 */
	protected $context;
	
	
	/**
	 * holder of xml root element
	 *
	 * @var string
	 */
	protected $rootNode = 'root';
	
	/**
	 * holder of visualisation package name
	 *
	 * @var unknown_type
	 */
	private $package = "";
	
	/**
	 * holder of data columns
	 *
	 * @var array
	 */
	protected $columns;
	
	/**
	 * offset of context name in context array
	 *
	 * @var integer
	 */
	protected $contextNode = 1;
	
	/**
	 * flag for prevent output of div container
	 *
	 * @var unknown_type
	 */
	
	protected $ignoreContainer = false;
	
	/**
	 * package usage 
	 *
	 * @var bool
	 */
	private $usePackage = true;
	
	/**
	 * Holder for additional scripts and css
	 * while render process the add. elements
	 * will be transfered from a classes package
	 * property to the register of packages
	 *
	 * @var array
	 */
	protected $registerPackage = array();

	protected $methodName;
	
	/**
	 * constructor:
	 * - initializes xml objects
	 * - adds package info
	 * - binds methods to visualisation type
	 * - sets default property values
	 * @return void
	 */
	public function __construct(){
		
		
		
		// identifies context part of class name
		$this->context = QTool::make()
			->toUnderscore(get_class($this))
			->toArray()
			->get();
			
		// package = context
		$this->package = $this->getContext();
		
		// xml root node
		$xml = '<?xml version="1.0" encoding="UTF-8"?><'.$this->rootNode.'></'.$this->rootNode.'>';
				
		// set api section
		$this->object["api"] = new SimpleXMLElement($xml);
		$api = $this->object["api"];
		$apiscript = $api->addChild('script');
		$apiscript->addAttribute("type", "text/javascript");
		$apiscript->addAttribute("src", "http://www.google.com/jsapi");
		
		// set base section 
		$this->object["base"] = new SimpleXMLElement($xml);
		$object = $this->object["base"];
		$script = $object->addChild("script");
		$script->addAttribute("type", "text/javascript");
		
		// do ignore if container must not be rendered
		if(empty($this->ignoreContainer)){
			$this->object["div"] = new SimpleXMLElement($xml);
			$object = $this->object["div"];
			$object->addChild("div");
			
			// add attributes for local requirements
			switch($this->getContext()){
				case "map":
				case "annotatedtimeline":
					$object->div->addAttribute("style", 'width:'.$this->drawProperties["width"].";height:".$this->drawProperties["height"].";");
					break;
			}
		}
		$this->initDrawProperties();
		
	}
	
	public function setMethod($name){
		$this->methodName = $name;
		return $this;
	}

	/**
	 * if set then the div container will not be renderer
	 *
	 * @return self
	 */
	public function ignoreContainer(){
		
		$this->ignoreContainer = true;
		return $this;
	}

	/**
	 * no package usage 
	 *
	 * @return self
	 */
	public function noPackage(){
		
		$this->usePackage = false;
		return $this;
	}
	
	/**
	 * use package
	 *
	 * @return self
	 */
	public function usePackage(){
		
		$this->usePackage = true;
		return $this;
	}

	/**
	 * get package name
	 *
	 * @return string
	 */
	public function getPackage(){
		
		return $this->package;	
	}
	/**
	 * get state of package usage
	 *
	 * @return boolean
	 */
	public function getUsePackage(){
		
		return $this->usePackage;
	}
	
	public function getScope() {
		return $this->vizualisationScope;
	}
	
	/**
	 * return visualization api version
	 *
	 * @return integer
	 */
	public function getVizApi(){
		
		return $this->vizApi; 
	}
	
	public function getVisualizationType(){
		
		return $this->vizualisationType; 
	}
	
	/**
	 * sets default properties into working array
	 *
	 * @return void
	 */
	public function initDrawProperties(){
		
		foreach($this->drawProperties as $key => $value){
			$this->putProperty("drawproperties", array(	$key => $value));
		}
		
	}
		
	/**
	 * context/package getter
	 *
	 * @return array
	 */
	public function getContexts(){
		
		return $this->context;
	}

	/**
	 * returns the class context name (2nd part of splitted class name) 
	 *
	 * @return string
	 */
	public function getContext(){
		
		return $this->context[$this->contextNode];	
	}
	
	
	/**
	 * adds package lines to working array
	 * 
	 * @return void
	 */
	public function addPackage($localPackage=true){
		
		
		
		$this->putProperty("package","");
		
		if($localPackage) { // usually used by mash ups
			if($this->getUsePackage()==true && !isset($this->members)) {
				$this->putProperty("package", 'google.load("visualization", "'.$this->getVizApi().'", {packages:["'.$this->package.'"]});');
			} elseif($this->getUsePackage()==true && isset($this->members)) {
				$packages = array();
				foreach($this->members as $member) {
					$packages[] = $member->getPackage();
				}
				$packages = implode('","', $packages);
				$this->putProperty("package", 'google.load("visualization", "'.$this->getVizApi().'", {packages:["'.$packages.'"]});');
			} else {
				$this->putProperty("package", 'google.load("visualization", "'.$this->getVizApi().'");');
			}
		}
		if(isset($this->methodName)) {
			$this->putProperty("package", 'google.setOnLoadCallback(draw'.ucfirst($this->methodName).');');
		} else {
			$this->putProperty("package", 'google.setOnLoadCallback(draw'.ucfirst($this->getPackage()).');');
		}
	}
	
	/**
	 * puts and names function outlines for working array
	 *
	 * @return void
	 */
	public function addFunction(){
		
		$this->putProperty("openfunction","");
		if(isset($this->methodName)) {
			$this->putProperty("openfunction", 'function draw'.ucfirst($this->methodName).'() {');
		} else {
			$this->putProperty("openfunction", 'function draw'.ucfirst($this->getPackage()).'() {');
		}
		$this->putProperty("closefunction", '}');
		$this->putProperty("closefunction", "\n");
	}
	
	/**
	 * adds columns source to working array
	 * counts columns
	 *
	 * @param array $columns
	 * @return self
	 */
	public function addColumns($columns=array()){
		
		$this->columns = count($columns);
		$this->putProperty("function", "var data = new google.visualization.DataTable();");
		foreach($columns as $column){
			switch($this->getContext()){
				case "intensitymap":
					$this->putProperty("function", "data.addColumn('".$column[0]."','".$column[1]."','".$column[2]."');");					
					break;
				default:
					$this->putProperty("function", "data.addColumn('".$column[0]."','".$column[1]."');");
					break;
			}
		}
		return $this;
	}

	/**
	 * internal: count rows on different contexts
	 * @param array $values
	 * 
	 * @return void
	 */
	private function setAddRows($values){
		switch($this->getContext()) {
			case "annotatedtimeline":
				$i=0;
				foreach($values as $value){
					if(substr($value[2],0,3)=='new'){
						$i++;
					}
				}
				$this->putProperty("function", "data.addRows(".$i.");");
			break;
		}

		switch($this->getContext()){
			case "orgchart":
			case "piechart":
				$this->putProperty("function", "data.addRows(".count($values).");");
				break;
			case "linechart":
			case "barchart":
			case "columnchart":
			case "areachart":
			case "table":
			case "scatterchart":
			case "gauge":
			case "map":
				$this->putProperty("function", "data.addRows(".(count($values)/$this->columns).");");
				break;
			case "intensitymap":
			case "motionchart":
				$this->putProperty("function", "data.addRows(".ceil(count($values)/$this->columns).");");
				break;
		}	
	}
	
	/**
	 * set values into working array
	 *
	 * @param array $values
	 * @return self
	 */
	public function setValues($values=array()){
		
		
		$this->putProperty("function","");
		
		$this->setAddRows($values); // add the row counter
		
		foreach($values as $value){
			
			if(is_string($value[2])) {
				$value3 = "'".$value[2]."'" ;
			} elseif(is_bool($value[2])) {
				$value3 = $value[2]?"true":"false"; 
			} else {
				$value3 = (is_null($value[2])?'null':$value[2]);
			}
			
			switch($this->getContext()){
				case "annotatedtimeline":
				case "motionchart":
					if(substr($value[0],0,3)=='new'){
						$value0 = $value[0];	
					} elseif(is_string($value[0])||is_bool($value[0])){
						$value0 = "'".$value[0]."'";
					} else {
						$value0 = $value[0];
					}
					if(substr($value[1],0,3)=='new'){
						$value1 = $value[1];	
					} elseif(is_string($value[1])||is_bool($value[1])){
						$value1 = "'".$value[1]."'";
					} else {
						$value1 = $value[1];
					}
					if(substr($value[2],0,3)=='new'){
						$value2 = $value[2];	
						$i++;
					} elseif(is_string($value[2])||is_bool($value[2])){
						$value2 = "'".$value[2]."'";
					} else {
						$value2 = (is_null($value[2])?'null':$value[2]);
					}
								
					$this->putProperty("function", "data.setValue(".$value0.",".$value1.",".$value2.");");
					break;
				case "map":
				case "table":
				case "orgchart":
					$this->putProperty("function", "data.setCell(".$value[0].",".$value[1].",".$value3.");");
					break;
				default:
					$this->putProperty("function", "data.setValue(".$value[0].",".$value[1].",".$value3.");");
					break;
			}
		}
		return $this;
	}


	/**
	 * set selection script function
	 *
	 * @param string $type
	 * @param string $option
	 * @param string $startObject
	 * @param string $endObject
	 * @return string
	 */
	public function getSelection($type, $option, $startObject, $endObject) {
		$so = (strpos($startObject,'Control')?$startObject:strtolower($type).$startObject);
		$eo = (strpos($endObject,'Control')?$endObject:strtolower($type).$endObject);
		return $so.',"'.$option.'",function(){'.$eo.'.setSelection('.$so.'.getSelection());}';
	}
	
	/**
	 * add listener script line
	 *
	 * @param string $object
	 * @param string $listener
	 * @return self
	 */
	public function addListener($object, $listener="filterControls") {
		$string = array();
		$string[] = 'google.visualization.events.addListener(';
		$string[] = $object;
		$string[] = ');';		
		$this->putProperty($listener,implode($string),"listen");
		return $this;
	}
	
	/**
	 * build javascript data property object 
	 * @return void
	 */
	private function buildPropertyObject() {
	
		$array = array();
	
		$string = "chart.draw(data, {";
		switch($this->getContext()){
			case "annotatedtimeline":
				$drawproperties = array_reverse($this->getProperty("drawproperties"));
				$checkArray = array();
				foreach($drawproperties as $row){
					foreach($row as $attribute => $value){
						$keys = array_keys($this->configuration);
						
						if(in_array($attribute, $keys) && !in_array($attribute, $checkArray)){
							$check = $this->checkProperties($attribute, $value);
							switch($check){
								case "array":
								case "literal":
									$array[] = $attribute .':'. trim($value);
									break;
								case "bool":
								case "integer":
								case "float":
									$array[] = $attribute . ":".$value;
									break;
								default:
									switch($attribute) {
										// not checked for the moment for correctness
										case "zoomEndTime":
										case "zoomStartTime":
											$array[] = $attribute . ":".$value;
											break;
										default:
											$array[] = $attribute . ":'".$value."'";
											break;
									}
									break;
							}
							$checkArray[] = $attribute;
						}
					}
				}
				$string .= implode(", ", $array);
				$string .= "});";
				$this->putProperty("function", $string);
				break;
			default:
				$drawproperties = array_reverse($this->getProperty("drawproperties"));
				$checkArray = array();
				foreach($drawproperties as $row){
					foreach($row as $attribute => $value){
						$keys = array_keys($this->configuration);
						if(in_array($attribute, $keys) && !in_array($attribute, $checkArray)){
							$check = $this->checkProperties($attribute, $value);
							switch($check){
								case "literal":
									$array[] =$attribute .':'. trim($value);;
									break;
								case "bool":
								case "integer":
								case "float":
									$array[] = $attribute . ":".$value;
									break;
								default:
									switch($attribute) {
										// not checked for the moment for correctness
										case "zoomEndTime":
										case "zoomStartTime":
											$array[] = $attribute . ":".$value;
											break;
										default:
											$array[] = $attribute . ":'".$value."'";
											break;
									}
									break;
							}
						}
						$checkArray[] = $attribute;
					}
				}
				$string .= implode(", ", $array);
				$string .= "});";
				$this->putProperty("function", $string);
				break;
		}
	}		

	public function setDrawProperties($array=array()) {
		$this->drawProperties = $array;
		return $this;	
	}
	
	public function buildProperties() {
		$string = "{";
		$drawproperties = array_reverse($this->getProperty("drawproperties"));
		$checkArray = array();
		foreach($drawproperties as $row){
			foreach($row as $attribute => $value){
				$keys = array_keys($this->configuration);
				if(in_array($attribute, $keys) && !in_array($attribute, $checkArray)){
					$check = $this->checkProperties($attribute, $value);
					switch($check){
						case "literal":
							$array[] =$attribute .':'. trim($value);;
							break;
						case "bool":
						case "integer":
						case "float":
							$array[] = $attribute . ":".$value;
							break;
						default:
							switch($attribute) {
								// not checked for the moment for correctness
								case "zoomEndTime":
								case "zoomStartTime":
									$array[] = $attribute . ":".$value;
									break;
								default:
									$array[] = $attribute . ":'".$value."'";
									break;
							}
							break;
					}
				}
				$checkArray[] = $attribute;
			}
		}
		$string .= implode(", ", $array);
		$string .= "}";
		return $string;
	}
	
	/**
	 * prepares source to be rendered
	 * @return void
	 */
	public function prepare($usePackage=true){
		
		
		$this->addPackage($usePackage);
		$this->addFunction();
		
		if(isset($this->packageSetup)){
			$xml = '<?xml version="1.0" encoding="UTF-8"?><'.$this->rootNode.'></'.$this->rootNode.'>';
			
			foreach($this->packageSetup as $element => $attributes){
				if(is_array($attributes) and isset($attributes[0])) {
					$this->object["addon"][$element] = new SimpleXMLElement($xml);
					$this->registerPackage = $element; // register package by name
					foreach($attributes as $elm => $attr) {
						// new addon 
						$usePack = $this->object["addon"][$element];
						if(isset($attr["text"])) {
							$usePackChild = $usePack->addChild($element, $attr["text"]); 
						} else {
							$usePackChild = $usePack->addChild($element); 
						}
						foreach($attr as $attrName => $attrValue){
							if($attrName!="text") {
								$usePackChild->addAttribute($attrName, $attrValue);
							}
						}
							
					}
					if(!empty($customPackage)) {
						$this->object["api"]["script"] = null;
					}
				} else {
					$this->registerPackage = $element; // register package by name
					// new addon 
					$this->object["addon"][$element] = new SimpleXMLElement($xml);
					$usePack = $this->object["addon"][$element];
					$usePackChild = $usePack->addChild($element); // attributes to the element
					foreach($attributes as $attrName => $attrValue){
						$usePackChild->addAttribute($attrName, $attrValue);
					}
				}
			}		
			
			if(method_exists($this,"loadCustomPackage")) {
				$this->object["customPackage"] = new SimpleXMLElement($xml);
				$customPackage = $this->object["customPackage"];
				$customScript = $customPackage->addChild("script", $this->loadCustomPackage());				
				$customScript->addAttribute("type", "text/javascript");
			}
		}
		
		// build container id
		if(!$this->hasProperty("id") and empty($this->ignoreContainer)){
			$this->setId();
		} else {
			$this->setId($this->getContext());
		}
		
		if($this->getUsePackage()){
			$this->putProperty("function", "");
			$this->putProperty("function", "var chart = new google.visualization.".$this->vizualisationType."(document.getElementById('".$this->getProperty("id")."'));");
			$this->buildPropertyObject();	
		}
		
		$output = implode("\n", $this->getProperty("package"));
		$output .= "\n";
		$output .= implode("\n", $this->getProperty("openfunction"));
		$output .= "\n";
		
		// append custom javascript code
		if(in_array("customAppend", get_class_methods($this))){
			$this->customAppend();
		}		
		$output .= implode("\n", $this->getProperty("function"));
		
		$output .= "\n";
		$output .= implode("\n", $this->getProperty("closefunction"));
		
		unset($this->properties);
		
		$object = $this->object["base"];
		$object->script = $output;

		return $this;
	}
	
	/**
	 * rendering
	 * - prepares js source
	 * - builds xml
	 * - converts xml to xhtml
	 * 
	 * @param string $name
	 * @param boolean $return
	 * @return mixed
	 */
	public function render($name = false, $return = false){
		
		$this->prepare();
		
		$dom_api_node = dom_import_simplexml($this->object["api"]);
		
		if(empty($this->ignoreContainer)){
			// build chart type browser container
			$dom_div_node = dom_import_simplexml($this->object["div"]);
		}

		// use base or alt. container as root
		$dom_node 	= !empty($name)
					? dom_import_simplexml($this->object[$name])
					: dom_import_simplexml($this->object["base"]);
		
		$dom = new DomDocument();
		
		// append add-ons
		if(empty($this->usePackage) and isset($this->packageSetup)){
			$addons = $this->object["addon"];
			if(is_array($addons)) {
				foreach($addons as $addon){
					$dom_addon = $dom->importNode(dom_import_simplexml($addon), true);
					$dom->appendChild($dom_addon);
				}
			}
			if(method_exists($this,"loadCustomPackage") and isset($this->object["customPackage"])) {
				$dom_addon = $dom->importNode(dom_import_simplexml($this->object["customPackage"]), true);
				$dom->appendChild($dom_addon);
			}
		} elseif(isset($this->packageSetup)){
			$addons = $this->object["addon"];
			if(is_array($addons)) {
				foreach($addons as $addon){
					$dom_addon = $dom->importNode(dom_import_simplexml($addon), true);
					$dom->appendChild($dom_addon);
				}
			}
			if(method_exists($this,"loadCustomPackage") and isset($this->object["customPackage"])) {
				$dom_addon = $dom->importNode(dom_import_simplexml($this->object["customPackage"]), true);
				$dom->appendChild($dom_addon);
			}
		}

		// append presentation container
		if(empty($this->ignoreContainer)){
			$dom_div_node = $dom->importNode($dom_div_node, true);
			$dom->appendChild($dom_div_node);
		}
		
		// append api source
		$dom_api_node = $dom->importNode($dom_api_node, true);
		$dom->appendChild($dom_api_node);
		
		// append defaults
		$dom_node = $dom->importNode($dom_node, true);
		$dom->appendChild($dom_node);
		
		
		// strip root node tags for they are not used
		$output = str_replace("<".$this->rootNode.">","", $dom->saveHTML());
		$output = str_replace("</".$this->rootNode.">","", $output);
		
		if($return) {
			return $output;
		} else {
			echo $output;
		}
		return false;
	}
				
		
	public function getReferenceLink() {
		$link = '<a href="'.$this->vizReference;
		$link .= strtolower($this->getContext());
		$link .= '.html" target="_blank">Goto Google Visualization Web API Gallery</a>';
		return $link;
	}
	
}


 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products