use zend router
[GitHub/Stricted/Domain-Control-Panel.git] / vendor / Zend / Mvc / Controller / Plugin / AcceptableViewModelSelector.php
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10 namespace Zend\Mvc\Controller\Plugin;
11
12 use Zend\Http\Header\Accept\FieldValuePart\AbstractFieldValuePart;
13 use Zend\Http\Request;
14 use Zend\Mvc\InjectApplicationEventInterface;
15 use Zend\Mvc\MvcEvent;
16 use Zend\Mvc\Exception\DomainException;
17 use Zend\Mvc\Exception\InvalidArgumentException;
18 use Zend\View\Model\ModelInterface;
19
20 /**
21 * Controller Plugin to assist in selecting an appropriate View Model type based on the
22 * User Agent's accept header.
23 */
24 class AcceptableViewModelSelector extends AbstractPlugin
25 {
26 /**
27 *
28 * @var string the Key to inject the name of a viewmodel with in an Accept Header
29 */
30 const INJECT_VIEWMODEL_NAME = '_internalViewModel';
31
32 /**
33 *
34 * @var \Zend\Mvc\MvcEvent
35 */
36 protected $event;
37
38 /**
39 *
40 * @var \Zend\Http\Request
41 */
42 protected $request;
43
44 /**
45 * Default array to match against.
46 *
47 * @var Array
48 */
49 protected $defaultMatchAgainst;
50
51 /**
52 *
53 * @var string Default ViewModel
54 */
55 protected $defaultViewModelName = 'Zend\View\Model\ViewModel';
56
57 /**
58 * Detects an appropriate viewmodel for request.
59 *
60 * @param array $matchAgainst (optional) The Array to match against
61 * @param bool $returnDefault (optional) If no match is available. Return default instead
62 * @param AbstractFieldValuePart|null $resultReference (optional) The object that was matched
63 * @throws InvalidArgumentException If the supplied and matched View Model could not be found
64 * @return ModelInterface|null
65 */
66 public function __invoke(
67 array $matchAgainst = null,
68 $returnDefault = true,
69 & $resultReference = null
70 ) {
71 return $this->getViewModel($matchAgainst, $returnDefault, $resultReference);
72 }
73
74 /**
75 * Detects an appropriate viewmodel for request.
76 *
77 * @param array $matchAgainst (optional) The Array to match against
78 * @param bool $returnDefault (optional) If no match is available. Return default instead
79 * @param AbstractFieldValuePart|null $resultReference (optional) The object that was matched
80 * @throws InvalidArgumentException If the supplied and matched View Model could not be found
81 * @return ModelInterface|null
82 */
83 public function getViewModel(
84 array $matchAgainst = null,
85 $returnDefault = true,
86 & $resultReference = null
87 ) {
88 $name = $this->getViewModelName($matchAgainst, $returnDefault, $resultReference);
89
90 if (!$name) {
91 return;
92 }
93
94 if (!class_exists($name)) {
95 throw new InvalidArgumentException('The supplied View Model could not be found');
96 }
97
98 return new $name();
99 }
100
101 /**
102 * Detects an appropriate viewmodel name for request.
103 *
104 * @param array $matchAgainst (optional) The Array to match against
105 * @param bool $returnDefault (optional) If no match is available. Return default instead
106 * @param AbstractFieldValuePart|null $resultReference (optional) The object that was matched.
107 * @return ModelInterface|null Returns null if $returnDefault = false and no match could be made
108 */
109 public function getViewModelName(
110 array $matchAgainst = null,
111 $returnDefault = true,
112 & $resultReference = null
113 ) {
114 $res = $this->match($matchAgainst);
115 if ($res) {
116 $resultReference = $res;
117 return $this->extractViewModelName($res);
118 }
119
120 if ($returnDefault) {
121 return $this->defaultViewModelName;
122 }
123 }
124
125 /**
126 * Detects an appropriate viewmodel name for request.
127 *
128 * @param array $matchAgainst (optional) The Array to match against
129 * @return AbstractFieldValuePart|null The object that was matched
130 */
131 public function match(array $matchAgainst = null)
132 {
133 $request = $this->getRequest();
134 $headers = $request->getHeaders();
135
136 if ((!$matchAgainst && !$this->defaultMatchAgainst) || !$headers->has('accept')) {
137 return;
138 }
139
140 if (!$matchAgainst) {
141 $matchAgainst = $this->defaultMatchAgainst;
142 }
143
144 $matchAgainstString = '';
145 foreach ($matchAgainst as $modelName => $modelStrings) {
146 foreach ((array) $modelStrings as $modelString) {
147 $matchAgainstString .= $this->injectViewModelName($modelString, $modelName);
148 }
149 }
150
151 /** @var $accept \Zend\Http\Header\Accept */
152 $accept = $headers->get('Accept');
153 if (($res = $accept->match($matchAgainstString)) === false) {
154 return;
155 }
156
157 return $res;
158 }
159
160 /**
161 * Set the default View Model (name) to return if no match could be made
162 * @param string $defaultViewModelName The default View Model name
163 * @return AcceptableViewModelSelector provides fluent interface
164 */
165 public function setDefaultViewModelName($defaultViewModelName)
166 {
167 $this->defaultViewModelName = (string) $defaultViewModelName;
168 return $this;
169 }
170
171 /**
172 * Set the default View Model (name) to return if no match could be made
173 * @return string
174 */
175 public function getDefaultViewModelName()
176 {
177 return $this->defaultViewModelName;
178 }
179
180 /**
181 * Set the default Accept Types and View Model combinations to match against if none are specified.
182 *
183 * @param array $matchAgainst (optional) The Array to match against
184 * @return AcceptableViewModelSelector provides fluent interface
185 */
186 public function setDefaultMatchAgainst(array $matchAgainst = null)
187 {
188 $this->defaultMatchAgainst = $matchAgainst;
189 return $this;
190 }
191
192 /**
193 * Get the default Accept Types and View Model combinations to match against if none are specified.
194 *
195 * @return array|null
196 */
197 public function getDefaultMatchAgainst()
198 {
199 return $this->defaultMatchAgainst;
200 }
201
202 /**
203 * Inject the viewmodel name into the accept header string
204 *
205 * @param string $modelAcceptString
206 * @param string $modelName
207 * @return string
208 */
209 protected function injectViewModelName($modelAcceptString, $modelName)
210 {
211 $modelName = str_replace('\\', '|', $modelName);
212 return $modelAcceptString . '; ' . self::INJECT_VIEWMODEL_NAME . '="' . $modelName . '", ';
213 }
214
215 /**
216 * Extract the viewmodel name from a match
217 * @param AbstractFieldValuePart $res
218 * @return string
219 */
220 protected function extractViewModelName(AbstractFieldValuePart $res)
221 {
222 $modelName = $res->getMatchedAgainst()->params[self::INJECT_VIEWMODEL_NAME];
223 return str_replace('|', '\\', $modelName);
224 }
225
226 /**
227 * Get the request
228 *
229 * @return Request
230 * @throws DomainException if unable to find request
231 */
232 protected function getRequest()
233 {
234 if ($this->request) {
235 return $this->request;
236 }
237
238 $event = $this->getEvent();
239 $request = $event->getRequest();
240 if (!$request instanceof Request) {
241 throw new DomainException(
242 'The event used does not contain a valid Request, but must.'
243 );
244 }
245
246 $this->request = $request;
247 return $request;
248 }
249
250 /**
251 * Get the event
252 *
253 * @return MvcEvent
254 * @throws DomainException if unable to find event
255 */
256 protected function getEvent()
257 {
258 if ($this->event) {
259 return $this->event;
260 }
261
262 $controller = $this->getController();
263 if (!$controller instanceof InjectApplicationEventInterface) {
264 throw new DomainException(
265 'A controller that implements InjectApplicationEventInterface '
266 . 'is required to use ' . __CLASS__
267 );
268 }
269
270 $event = $controller->getEvent();
271 if (!$event instanceof MvcEvent) {
272 $params = $event->getParams();
273 $event = new MvcEvent();
274 $event->setParams($params);
275 }
276 $this->event = $event;
277
278 return $this->event;
279 }
280 }