forked from zendframework/zendframework
/
Forward.php
130 lines (111 loc) · 3.97 KB
/
Forward.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php
namespace Zend\Mvc\Controller\Plugin;
use Zend\Di\Locator,
Zend\Mvc\InjectApplicationEvent,
Zend\Mvc\Exception,
Zend\Mvc\LocatorAware,
Zend\Mvc\MvcEvent,
Zend\Mvc\Router\RouteMatch,
Zend\Stdlib\Dispatchable;
class Forward extends AbstractPlugin
{
protected $event;
protected $locator;
protected $maxNestedForwards = 10;
protected $numNestedForwards = 0;
public function setMaxNestedForwards($maxNestedForwards)
{
$this->maxNestedForwards = (int) $maxNestedForwards;
return $this;
}
/**
* Dispatch another controller
*
* @param string $name Controller name; either a class name or an alias used in the DI container or service locator
* @param null|array $params Parameters with which to seed a custom RouteMatch object for the new controller
* @return mixed
* @throws Exception\DomainException if composed controller does not define InjectApplicationEvent
* or Locator aware; or if the discovered controller is not dispatchable
*/
public function dispatch($name, array $params = null)
{
$event = $this->getEvent();
$locator = $this->getLocator();
$controller = $locator->get($name);
if (!$controller instanceof Dispatchable) {
throw new Exception\DomainException('Can only forward to Dispatchable classes; class of type ' . get_class($controller) . ' received');
}
if ($controller instanceof InjectApplicationEvent) {
$controller->setEvent($event);
}
if ($controller instanceof LocatorAware) {
$controller->setLocator($locator);
}
// Allow passing parameters to seed the RouteMatch with
$cachedMatches = false;
if ($params) {
$matches = new RouteMatch($params);
$cachedMatches = $event->getRouteMatch();
$event->setRouteMatch($matches);
}
if ($this->numNestedForwards > $this->maxNestedForwards) {
throw new Exception\DomainException("Circular forwarding detected: greater than $this->maxNestedForwards nested forwards");
}
$this->numNestedForwards++;
$return = $controller->dispatch($event->getRequest(), $event->getResponse());
$this->numNestedForwards--;
if ($cachedMatches) {
$event->setRouteMatch($cachedMatches);
}
return $return;
}
/**
* Get the locator
*
* @return Locator
* @throws Exception\DomainException if unable to find locator
*/
protected function getLocator()
{
if ($this->locator) {
return $this->locator;
}
$controller = $this->getController();
if (!$controller instanceof LocatorAware) {
throw new Exception\DomainException('Forward plugin requires controller implements LocatorAware');
}
$locator = $controller->getLocator();
if (!$locator instanceof Locator) {
throw new Exception\DomainException('Forward plugin requires controller composes Locator');
}
$this->locator = $locator;
return $this->locator;
}
/**
* Get the event
*
* @return MvcEvent
* @throws Exception\DomainException if unable to find event
*/
protected function getEvent()
{
if ($this->event) {
return $this->event;
}
$controller = $this->getController();
if (!$controller instanceof InjectApplicationEvent) {
throw new Exception\DomainException('Redirect plugin requires a controller that implements InjectApplicationEvent');
}
$event = $controller->getEvent();
if (!$event instanceof MvcEvent) {
$params = array();
if ($event) {
$params = $event->getParams();
}
$event = new MvcEvent();
$event->setParams($params);
}
$this->event = $event;
return $this->event;
}
}