- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-
- namespace Zend\View\Renderer;
-
- use JsonSerializable;
- use Traversable;
- use Zend\Json\Json;
- use Zend\Stdlib\ArrayUtils;
- use Zend\View\Exception;
- use Zend\View\Model\JsonModel;
- use Zend\View\Model\ModelInterface as Model;
- use Zend\View\Renderer\RendererInterface as Renderer;
- use Zend\View\Resolver\ResolverInterface as Resolver;
-
- /**
- * JSON renderer
- */
- class JsonRenderer implements Renderer, TreeRendererInterface
- {
- /**
- * Whether or not to merge child models with no capture-to value set
- * @var bool
- */
- protected $mergeUnnamedChildren = false;
-
- /**
- * @var Resolver
- */
- protected $resolver;
-
- /**
- * JSONP callback (if set, wraps the return in a function call)
- *
- * @var string
- */
- protected $jsonpCallback = null;
-
- /**
- * Return the template engine object, if any
- *
- * If using a third-party template engine, such as Smarty, patTemplate,
- * phplib, etc, return the template engine object. Useful for calling
- * methods on these objects, such as for setting filters, modifiers, etc.
- *
- * @return mixed
- */
- public function getEngine()
- {
- return $this;
- }
-
- /**
- * Set the resolver used to map a template name to a resource the renderer may consume.
- *
- * @todo Determine use case for resolvers when rendering JSON
- * @param Resolver $resolver
- * @return Renderer
- */
- public function setResolver(Resolver $resolver)
- {
- $this->resolver = $resolver;
- }
-
- /**
- * Set flag indicating whether or not to merge unnamed children
- *
- * @param bool $mergeUnnamedChildren
- * @return JsonRenderer
- */
- public function setMergeUnnamedChildren($mergeUnnamedChildren)
- {
- $this->mergeUnnamedChildren = (bool) $mergeUnnamedChildren;
- return $this;
- }
-
- /**
- * Set the JSONP callback function name
- *
- * @param string $callback
- * @return JsonRenderer
- */
- public function setJsonpCallback($callback)
- {
- $callback = (string) $callback;
- if (!empty($callback)) {
- $this->jsonpCallback = $callback;
- }
- return $this;
- }
-
- /**
- * Returns whether or not the jsonpCallback has been set
- *
- * @return bool
- */
- public function hasJsonpCallback()
- {
- return (null !== $this->jsonpCallback);
- }
-
- /**
- * Should we merge unnamed children?
- *
- * @return bool
- */
- public function mergeUnnamedChildren()
- {
- return $this->mergeUnnamedChildren;
- }
-
- /**
- * Renders values as JSON
- *
- * @todo Determine what use case exists for accepting both $nameOrModel and $values
- * @param string|Model $nameOrModel The script/resource process, or a view model
- * @param null|array|\ArrayAccess $values Values to use during rendering
- * @throws Exception\DomainException
- * @return string The script output.
- */
- public function render($nameOrModel, $values = null)
- {
- // use case 1: View Models
- // Serialize variables in view model
- if ($nameOrModel instanceof Model) {
- if ($nameOrModel instanceof JsonModel) {
- $children = $this->recurseModel($nameOrModel, false);
- $this->injectChildren($nameOrModel, $children);
- $values = $nameOrModel->serialize();
- } else {
- $values = $this->recurseModel($nameOrModel);
- $values = Json::encode($values);
- }
-
- if ($this->hasJsonpCallback()) {
- $values = $this->jsonpCallback . '(' . $values . ');';
- }
- return $values;
- }
-
- // use case 2: $nameOrModel is populated, $values is not
- // Serialize $nameOrModel
- if (null === $values) {
- if (!is_object($nameOrModel) || $nameOrModel instanceof JsonSerializable) {
- $return = Json::encode($nameOrModel);
- } elseif ($nameOrModel instanceof Traversable) {
- $nameOrModel = ArrayUtils::iteratorToArray($nameOrModel);
- $return = Json::encode($nameOrModel);
- } else {
- $return = Json::encode(get_object_vars($nameOrModel));
- }
-
- if ($this->hasJsonpCallback()) {
- $return = $this->jsonpCallback . '(' . $return . ');';
- }
- return $return;
- }
-
- // use case 3: Both $nameOrModel and $values are populated
- throw new Exception\DomainException(sprintf(
- '%s: Do not know how to handle operation when both $nameOrModel and $values are populated',
- __METHOD__
- ));
- }
-
- /**
- * Can this renderer render trees of view models?
- *
- * Yes.
- *
- * @return true
- */
- public function canRenderTrees()
- {
- return true;
- }
-
- /**
- * Retrieve values from a model and recurse its children to build a data structure
- *
- * @param Model $model
- * @param bool $mergeWithVariables Whether or not to merge children with
- * the variables of the $model
- * @return array
- */
- protected function recurseModel(Model $model, $mergeWithVariables = true)
- {
- $values = array();
- if ($mergeWithVariables) {
- $values = $model->getVariables();
- }
-
- if ($values instanceof Traversable) {
- $values = ArrayUtils::iteratorToArray($values);
- }
-
- if (!$model->hasChildren()) {
- return $values;
- }
-
- $mergeChildren = $this->mergeUnnamedChildren();
- foreach ($model as $child) {
- $captureTo = $child->captureTo();
- if (!$captureTo && !$mergeChildren) {
- // We don't want to do anything with this child
- continue;
- }
-
- $childValues = $this->recurseModel($child);
- if ($captureTo) {
- // Capturing to a specific key
- // TODO please complete if append is true. must change old
- // value to array and append to array?
- $values[$captureTo] = $childValues;
- } elseif ($mergeChildren) {
- // Merging values with parent
- $values = array_replace_recursive($values, $childValues);
- }
- }
- return $values;
- }
-
- /**
- * Inject discovered child model values into parent model
- *
- * @todo detect collisions and decide whether to append and/or aggregate?
- * @param Model $model
- * @param array $children
- */
- protected function injectChildren(Model $model, array $children)
- {
- foreach ($children as $child => $value) {
- // TODO detect collisions and decide whether to append and/or aggregate?
- $model->setVariable($child, $value);
- }
- }
- }
# |
Change |
User |
Description |
Committed |
|
#1
|
18334 |
Liz Lam |
initial add of jambox |
9 years ago
|
|