. */ namespace Volkszaehler\View; use Volkszaehler\Interpreter; use Volkszaehler\View\HTTP; use Volkszaehler\Util; use Volkszaehler\Model; /** * JSON view * * @package default * @author Steffen Vogel */ class JSON extends View { /** * @var array holds the JSON data in an array */ protected $json; /** * @var string padding function name or NULL if disabled */ protected $padding = FALSE; /** * Constructor * * @param HTTP\Request $request * @param HTTP\Response $response */ public function __construct(HTTP\Request $request, HTTP\Response $response) { parent::__construct($request, $response); $this->json = new Util\JSON(); $this->json['version'] = VZ_VERSION; $this->response->setHeader('Content-type', 'application/json'); $this->setPadding($request->getParameter('padding')); } /** * Add object to output * * @param mixed $data */ public function add($data) { if ($data instanceof Interpreter\Interpreter || $data instanceof Interpreter\AggregatorInterpreter) { $this->addData($data); } elseif ($data instanceof Model\Entity) { $this->addEntity($data); } elseif ($data instanceof \Exception) { $this->addException($data); } elseif ($data instanceof Util\Debug) { $this->addDebug($data); } elseif ($data instanceof Util\JSON || is_array($data)) { $this->addArray($data, $this->json); } elseif (isset($data)) { // ignores NULL data throw new \Exception('Can\'t show ' . get_class($data)); } } /** * Process, encode and print output to stdout */ protected function render() { $json = $this->json->encode((Util\Debug::isActivated()) ? JSON_PRETTY : 0); if ($this->padding) { $json = 'if (' . $this->padding . ') { ' . $this->padding . '(' . $json . '); }'; } echo $json; } /** * Add Entity to output queue * * @param Model\Entity $entity */ protected function addEntity(Model\Entity $entity) { if ($entity instanceof Model\Aggregator) { $this->json['entity'] = self::convertAggregator($entity); } else { $this->json['entity'] = self::convertEntity($entity); } } /** * Converts entity to array for json_encode() * * @param Model\Entity $entity * @return array */ protected static function convertEntity(Model\Entity $entity) { $jsonEntity = array(); $jsonEntity['uuid'] = (string) $entity->getUuid(); $jsonEntity['type'] = $entity->getType(); foreach ($entity->getProperties() as $key => $value) { $jsonEntity[$key] = $value; } return $jsonEntity; } /** * Converts aggregator to array for json_encode * * @param Model\Aggregator $aggregator * @return array */ protected static function convertAggregator(Model\Aggregator $aggregator) { $jsonAggregator = self::convertEntity($aggregator); foreach ($aggregator->getChildren() as $entity) { if ($entity instanceof Model\Channel) { $jsonAggregator['children'][] = self::convertEntity($entity); } elseif ($entity instanceof Model\Aggregator) { $jsonAggregator['children'][] = self::convertAggregator($entity); } } return $jsonAggregator; } /** * Add debugging information include queries and messages to output queue * * @param Util\Debug $debug */ protected function addDebug(Util\Debug $debug) { $jsonDebug['time'] = $debug->getExecutionTime(); $jsonDebug['level'] = $debug->getLevel(); $jsonDebug['messages'] = $debug->getMessages(); $jsonDebug['queries'] = array_values($debug->getQueries()); $this->json['debug'] = $jsonDebug; } /** * Add exception to output queue * * @param \Exception $exception * @param boolean $debug */ protected function addException(\Exception $exception) { $exceptionType = explode('\\', get_class($exception)); $exceptionInfo = array( 'message' => $exception->getMessage(), 'type' => end($exceptionType), 'code' => $exception->getCode() ); if (Util\Debug::isActivated()) { $debugInfo = array( 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'backtrace' => $exception->getTrace() ); $this->json['exception'] = array_merge($exceptionInfo, $debugInfo); } else { $this->json['exception'] = $exceptionInfo; } } /** * Add data to output queue * * @param $interpreter */ protected function addData($interpreter) { $data = $interpreter->processData( // iterate through PDO resultset function($tuple) { return array( $tuple[0], View::formatNumber($tuple[1]), $tuple[2] ); } ); $min = $interpreter->getMin(); $max = $interpreter->getMax(); $average = $interpreter->getAverage(); $from = $interpreter->getFrom(); $to = $interpreter->getTo(); $this->json['data']['uuid'] = $interpreter->getEntity()->getUuid(); if (isset($from)) $this->json['data']['from'] = $from; if (isset($to)) $this->json['data']['to'] = $to; if (isset($min)) $this->json['data']['min'] = $min; if (isset($max)) $this->json['data']['max'] = $max; if (isset($average)) $this->json['data']['average'] = View::formatNumber($average); if ($interpreter instanceof Interpreter\MeterInterpreter) $this->json['data']['consumption'] = View::formatNumber($interpreter->getConsumption()); $this->json['data']['count'] = count($data); if (($interpreter->getTupleCount() > 0 || is_null($interpreter->getTupleCount())) && count($data) > 0) $this->json['data']['tuples'] = $data; } /** * */ protected function addArray($data, &$refNode) { if (is_null($refNode)) { $refNode = array(); } foreach ($data as $index => $value) { if ($value instanceof Util\JSON || is_array($value)) { $this->addArray($value, $refNode[$index]); } elseif ($value instanceof Model\Entity) { $refNode[$index] = self::convertEntity($value); } elseif (is_numeric($value)) { $refNode[$index] = View::formatNumber($value); } else { $refNode[$index] = $value; } } } /* * Setter & getter */ public function setPadding($padding) { $this->padding = $padding; } } ?>