1 <?php
2 /**
3 * @package Joomla.Libraries
4 * @subpackage Component
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE.txt
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * View-based component routing class
14 *
15 * @since 3.5
16 */
17 abstract class JComponentRouterView extends JComponentRouterBase
18 {
19 /**
20 * Name of the router of the component
21 *
22 * @var string
23 * @since 3.5
24 */
25 protected $name;
26
27 /**
28 * Array of rules
29 *
30 * @var JComponentRouterRulesInterface[]
31 * @since 3.5
32 */
33 protected $rules = array();
34
35 /**
36 * Views of the component
37 *
38 * @var JComponentRouterViewconfiguration[]
39 * @since 3.5
40 */
41 protected $views = array();
42
43 /**
44 * Register the views of a component
45 *
46 * @param JComponentRouterViewconfiguration $view View configuration object
47 *
48 * @return void
49 *
50 * @since 3.5
51 */
52 public function registerView(JComponentRouterViewconfiguration $view)
53 {
54 $this->views[$view->name] = $view;
55 }
56
57 /**
58 * Return an array of registered view objects
59 *
60 * @return JComponentRouterViewconfiguration[] Array of registered view objects
61 *
62 * @since 3.5
63 */
64 public function getViews()
65 {
66 return $this->views;
67 }
68
69 /**
70 * Get the path of views from target view to root view
71 * including content items of a nestable view
72 *
73 * @param array $query Array of query elements
74 *
75 * @return array List of views including IDs of content items
76 *
77 * @since 3.5
78 */
79 public function getPath($query)
80 {
81 $views = $this->getViews();
82 $result = array();
83
84 // Get the right view object
85 if (isset($query['view']) && isset($views[$query['view']]))
86 {
87 $viewobj = $views[$query['view']];
88 }
89
90 // Get the path from the current item to the root view with all IDs
91 if (isset($viewobj))
92 {
93 $path = array_reverse($viewobj->path);
94 $start = true;
95 $childkey = false;
96
97 foreach ($path as $element)
98 {
99 $view = $views[$element];
100
101 if ($start)
102 {
103 $key = $view->key;
104 $start = false;
105 }
106 else
107 {
108 $key = $childkey;
109 }
110
111 $childkey = $view->parent_key;
112
113 if (($key || $view->key) && is_callable(array($this, 'get' . ucfirst($view->name) . 'Segment')))
114 {
115 if (isset($query[$key]))
116 {
117 $result[$view->name] = call_user_func_array(array($this, 'get' . ucfirst($view->name) . 'Segment'), array($query[$key], $query));
118 }
119 elseif (isset($query[$view->key]))
120 {
121 $result[$view->name] = call_user_func_array(array($this, 'get' . ucfirst($view->name) . 'Segment'), array($query[$view->key], $query));
122 }
123 else
124 {
125 $result[$view->name] = array();
126 }
127 }
128 else
129 {
130 $result[$view->name] = true;
131 }
132 }
133 }
134
135 return $result;
136 }
137
138 /**
139 * Get all currently attached rules
140 *
141 * @return JComponentRouterRulesInterface[] All currently attached rules in an array
142 *
143 * @since 3.5
144 */
145 public function getRules()
146 {
147 return $this->rules;
148 }
149
150 /**
151 * Add a number of router rules to the object
152 *
153 * @param JComponentRouterRulesInterface[] $rules Array of JComponentRouterRulesInterface objects
154 *
155 * @return void
156 *
157 * @since 3.5
158 */
159 public function attachRules($rules)
160 {
161 foreach ($rules as $rule)
162 {
163 $this->attachRule($rule);
164 }
165 }
166
167 /**
168 * Attach a build rule
169 *
170 * @param JComponentRouterRulesInterface $rule The function to be called.
171 *
172 * @return void
173 *
174 * @since 3.5
175 */
176 public function attachRule(JComponentRouterRulesInterface $rule)
177 {
178 $this->rules[] = $rule;
179 }
180
181 /**
182 * Remove a build rule
183 *
184 * @param JComponentRouterRulesInterface $rule The rule to be removed.
185 *
186 * @return boolean Was a rule removed?
187 *
188 * @since 3.5
189 */
190 public function detachRule(JComponentRouterRulesInterface $rule)
191 {
192 foreach ($this->rules as $id => $r)
193 {
194 if ($r == $rule)
195 {
196 unset($this->rules[$id]);
197
198 return true;
199 }
200 }
201
202 return false;
203 }
204
205 /**
206 * Generic method to preprocess a URL
207 *
208 * @param array $query An associative array of URL arguments
209 *
210 * @return array The URL arguments to use to assemble the subsequent URL.
211 *
212 * @since 3.5
213 */
214 public function preprocess($query)
215 {
216 // Process the parsed variables based on custom defined rules
217 foreach ($this->rules as $rule)
218 {
219 $rule->preprocess($query);
220 }
221
222 return $query;
223 }
224
225 /**
226 * Build method for URLs
227 *
228 * @param array &$query Array of query elements
229 *
230 * @return array Array of URL segments
231 *
232 * @since 3.5
233 */
234 public function build(&$query)
235 {
236 $segments = array();
237
238 // Process the parsed variables based on custom defined rules
239 foreach ($this->rules as $rule)
240 {
241 $rule->build($query, $segments);
242 }
243
244 return $segments;
245 }
246
247 /**
248 * Parse method for URLs
249 *
250 * @param array &$segments Array of URL string-segments
251 *
252 * @return array Associative array of query values
253 *
254 * @since 3.5
255 */
256 public function parse(&$segments)
257 {
258 $vars = array();
259
260 // Process the parsed variables based on custom defined rules
261 foreach ($this->rules as $rule)
262 {
263 $rule->parse($segments, $vars);
264 }
265
266 return $vars;
267 }
268
269 /**
270 * Method to return the name of the router
271 *
272 * @return string Name of the router
273 *
274 * @since 3.5
275 */
276 public function getName()
277 {
278 if (empty($this->name))
279 {
280 $r = null;
281
282 if (!preg_match('/(.*)Router/i', get_class($this), $r))
283 {
284 throw new Exception('JLIB_APPLICATION_ERROR_ROUTER_GET_NAME', 500);
285 }
286
287 $this->name = strtolower($r[1]);
288 }
289
290 return $this->name;
291 }
292 }
293