Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / View / Renderer / JsonRenderer.php
blob60a1952040e7207e2443f73774fed47c071ab108
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\View\Renderer;
12 use JsonSerializable;
13 use Traversable;
14 use Zend\Json\Json;
15 use Zend\Stdlib\ArrayUtils;
16 use Zend\View\Exception;
17 use Zend\View\Model\JsonModel;
18 use Zend\View\Model\ModelInterface as Model;
19 use Zend\View\Renderer\RendererInterface as Renderer;
20 use Zend\View\Resolver\ResolverInterface as Resolver;
22 /**
23 * JSON renderer
25 class JsonRenderer implements Renderer, TreeRendererInterface
27 /**
28 * Whether or not to merge child models with no capture-to value set
29 * @var bool
31 protected $mergeUnnamedChildren = false;
33 /**
34 * @var Resolver
36 protected $resolver;
38 /**
39 * JSONP callback (if set, wraps the return in a function call)
41 * @var string
43 protected $jsonpCallback = null;
45 /**
46 * Return the template engine object, if any
48 * If using a third-party template engine, such as Smarty, patTemplate,
49 * phplib, etc, return the template engine object. Useful for calling
50 * methods on these objects, such as for setting filters, modifiers, etc.
52 * @return mixed
54 public function getEngine()
56 return $this;
59 /**
60 * Set the resolver used to map a template name to a resource the renderer may consume.
62 * @todo Determine use case for resolvers when rendering JSON
63 * @param Resolver $resolver
64 * @return Renderer
66 public function setResolver(Resolver $resolver)
68 $this->resolver = $resolver;
71 /**
72 * Set flag indicating whether or not to merge unnamed children
74 * @param bool $mergeUnnamedChildren
75 * @return JsonRenderer
77 public function setMergeUnnamedChildren($mergeUnnamedChildren)
79 $this->mergeUnnamedChildren = (bool) $mergeUnnamedChildren;
80 return $this;
83 /**
84 * Set the JSONP callback function name
86 * @param string $callback
87 * @return JsonRenderer
89 public function setJsonpCallback($callback)
91 $callback = (string) $callback;
92 if (!empty($callback)) {
93 $this->jsonpCallback = $callback;
95 return $this;
98 /**
99 * Returns whether or not the jsonpCallback has been set
101 * @return bool
103 public function hasJsonpCallback()
105 return (null !== $this->jsonpCallback);
109 * Should we merge unnamed children?
111 * @return bool
113 public function mergeUnnamedChildren()
115 return $this->mergeUnnamedChildren;
119 * Renders values as JSON
121 * @todo Determine what use case exists for accepting both $nameOrModel and $values
122 * @param string|Model $nameOrModel The script/resource process, or a view model
123 * @param null|array|\ArrayAccess $values Values to use during rendering
124 * @throws Exception\DomainException
125 * @return string The script output.
127 public function render($nameOrModel, $values = null)
129 // use case 1: View Models
130 // Serialize variables in view model
131 if ($nameOrModel instanceof Model) {
132 if ($nameOrModel instanceof JsonModel) {
133 $children = $this->recurseModel($nameOrModel, false);
134 $this->injectChildren($nameOrModel, $children);
135 $values = $nameOrModel->serialize();
136 } else {
137 $values = $this->recurseModel($nameOrModel);
138 $values = Json::encode($values);
141 if ($this->hasJsonpCallback()) {
142 $values = $this->jsonpCallback . '(' . $values . ');';
144 return $values;
147 // use case 2: $nameOrModel is populated, $values is not
148 // Serialize $nameOrModel
149 if (null === $values) {
150 if (!is_object($nameOrModel) || $nameOrModel instanceof JsonSerializable) {
151 $return = Json::encode($nameOrModel);
152 } elseif ($nameOrModel instanceof Traversable) {
153 $nameOrModel = ArrayUtils::iteratorToArray($nameOrModel);
154 $return = Json::encode($nameOrModel);
155 } else {
156 $return = Json::encode(get_object_vars($nameOrModel));
159 if ($this->hasJsonpCallback()) {
160 $return = $this->jsonpCallback . '(' . $return . ');';
162 return $return;
165 // use case 3: Both $nameOrModel and $values are populated
166 throw new Exception\DomainException(sprintf(
167 '%s: Do not know how to handle operation when both $nameOrModel and $values are populated',
168 __METHOD__
173 * Can this renderer render trees of view models?
175 * Yes.
177 * @return true
179 public function canRenderTrees()
181 return true;
185 * Retrieve values from a model and recurse its children to build a data structure
187 * @param Model $model
188 * @param bool $mergeWithVariables Whether or not to merge children with
189 * the variables of the $model
190 * @return array
192 protected function recurseModel(Model $model, $mergeWithVariables = true)
194 $values = array();
195 if ($mergeWithVariables) {
196 $values = $model->getVariables();
199 if ($values instanceof Traversable) {
200 $values = ArrayUtils::iteratorToArray($values);
203 if (!$model->hasChildren()) {
204 return $values;
207 $mergeChildren = $this->mergeUnnamedChildren();
208 foreach ($model as $child) {
209 $captureTo = $child->captureTo();
210 if (!$captureTo && !$mergeChildren) {
211 // We don't want to do anything with this child
212 continue;
215 $childValues = $this->recurseModel($child);
216 if ($captureTo) {
217 // Capturing to a specific key
218 // TODO please complete if append is true. must change old
219 // value to array and append to array?
220 $values[$captureTo] = $childValues;
221 } elseif ($mergeChildren) {
222 // Merging values with parent
223 $values = array_replace_recursive($values, $childValues);
226 return $values;
230 * Inject discovered child model values into parent model
232 * @todo detect collisions and decide whether to append and/or aggregate?
233 * @param Model $model
234 * @param array $children
236 protected function injectChildren(Model $model, array $children)
238 foreach ($children as $child => $value) {
239 // TODO detect collisions and decide whether to append and/or aggregate?
240 $model->setVariable($child, $value);