Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
tao_actions_Breadcrumbs
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 6
420
0.00% covered (danger)
0.00%
0 / 1
 parseRoute
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getRoutes
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 returnData
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 requestService
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
56
 breadcrumbs
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 load
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2017 (original work) Open Assessment Technologies SA;
19 */
20
21use oat\tao\model\routing\Resolver;
22use oat\tao\model\mvc\Breadcrumbs;
23
24/**
25 * Controller that will serve breadcrumbs depending on context routes.
26 * For each context route a service will be requested to get the breadcrumbs.
27 *
28 * To provide a breadcrumbs service you must register a class that implements `oat\tao\model\mvc\Breadcrumbs`, and
29 * use a service identifier with respect to this format: `<extension>/<controller>/breadcrumbs`. Hence this service
30 * will be invoked each time a breadcrumbs request is made against an action under `<extension>/<controller>`.
31 * The `breadcrumbs()` method will have to provide the breadcrumb related to the route, an optionally a list of
32 * related links. @see breadcrumbs() for more explanations.
33 *
34 * You can also override this controller and provide your own `breadcrumbs()` method, in order to provide default
35 * breadcrumbs. By default there is none.
36 *
37 * @author Jean-Sébastien Conan <jean-sebastien@taotesting.com>
38 * @package oat\tao\actions
39 *
40 */
41class tao_actions_Breadcrumbs extends \tao_actions_CommonModule implements Breadcrumbs
42{
43    /**
44     * Parses the provided context route
45     * @param string $route
46     * @return array
47     */
48    protected function parseRoute($route)
49    {
50        $parsedRoute = parse_url($route);
51
52        if (isset($parsedRoute['query'])) {
53            parse_str($parsedRoute['query'], $parsedRoute['params']);
54        } else {
55            $parsedRoute['params'] = [];
56        }
57
58        $resolvedRoute = new Resolver(new \common_http_Request($route));
59        $this->propagate($resolvedRoute);
60        $parsedRoute['extension']         = $resolvedRoute->getExtensionId();
61        $parsedRoute['controller']        = $resolvedRoute->getControllerShortName();
62        $parsedRoute['controller_class']  = $resolvedRoute->getControllerClass();
63        $parsedRoute['action']            = $resolvedRoute->getMethodName();
64
65        return $parsedRoute;
66    }
67
68    /**
69     * Gets the provided context route
70     * @return array|mixed|null|string
71     * @throws common_exception_MissingParameter
72     */
73    protected function getRoutes()
74    {
75        $route = $this->getRequestParameter('route');
76        if (empty($route)) {
77            throw new \common_exception_MissingParameter('You must specify a route');
78        }
79
80        if (!is_array($route)) {
81            $route = [$route];
82        }
83
84        return $route;
85    }
86
87    /**
88     * Sends the data to the client using the preferred format
89     * @param $data
90     */
91    protected function returnData($data)
92    {
93        if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false) {
94            $this->returnJson([
95                'success' => true,
96                'data' => $data,
97            ]);
98        } else {
99            $this->setData('breadcrumbs', $data);
100            $this->setView('blocks/breadcrumbs.tpl', 'tao');
101        }
102    }
103
104    /**
105     * Calls a service to get the breadcrumbs for a particular route.
106     * To provide a breadcrumbs service you must register a class that implements `oat\tao\model\mvc\Breadcrumbs`, and
107     * use a service identifier with respect to this format: `<extension>/<controller>/breadcrumbs`. Hence this service
108     * will be invoked each time a breadcrumbs request is made against an action under `<extension>/<controller>`.
109     * You can also override the Breadcrumbs controller and provide your own `breadcrumbs()` method, in order to
110     * provide default values. By default there is no default breadcrumbs.
111     * @param string $route
112     * @param array $parsedRoute
113     * @return array
114     * @throws common_exception_NoImplementation
115     */
116    protected function requestService($route, $parsedRoute)
117    {
118        $serviceName = null;
119        if ($parsedRoute['extension'] && $parsedRoute['controller'] && $parsedRoute['action']) {
120            $serviceName = $parsedRoute['extension'] . '/' . $parsedRoute['controller'] . '/breadcrumbs';
121        }
122
123        if ($serviceName && $this->getServiceLocator()->has($serviceName)) {
124            $service = $this->getServiceLocator()->get($serviceName);
125        } else {
126            $service = $this;
127        }
128
129        if ($service instanceof Breadcrumbs) {
130            return $service->breadcrumbs($route, $parsedRoute);
131        } else {
132            throw new common_exception_NoImplementation(
133                'Class ' . get_class($service) . ' does not implement the Breadcrumbs interface!'
134            );
135        }
136    }
137
138    /**
139     * Builds breadcrumbs for a particular route.
140     * @param string $route - The route URL
141     * @param array $parsedRoute - The parsed URL (@see parse_url), augmented with extension, controller and action
142     * @return array|null - The breadcrumb related to the route, or `null` if none. Must contains:
143     * - id: the route id
144     * - url: the route url
145     * - label: the label displayed for the breadcrumb
146     * - entries: a list of related links, using the same format as above
147     */
148    public function breadcrumbs($route, $parsedRoute)
149    {
150        // default behavior: no breadcrumb
151        return null;
152    }
153
154    /**
155     * Loads all the breadcrumbs for a particular context route
156     */
157    public function load()
158    {
159        $data = [];
160        $routes = $this->getRoutes();
161        foreach ($routes as $route) {
162            $parsedRoute = $this->parseRoute($route);
163            $routeData = $this->requestService($route, $parsedRoute);
164
165            if ($routeData !== null) {
166                // When the routeData contains more entry. (if it's a numeric array)
167                if (array_values($routeData) === $routeData) {
168                    $data = array_merge($data, $routeData);
169                } else {
170                    $data[] = $routeData;
171                }
172            }
173        }
174        $this->returnData($data);
175    }
176}