Issues (94)

src/AdminiRootController.php (4 issues)

1
<?php
2
3
namespace LeKoala\Admini;
4
5
use SilverStripe\Control\Director;
6
use SilverStripe\Control\Controller;
7
use SilverStripe\Core\Config\Config;
8
use SilverStripe\Control\HTTPRequest;
9
use SilverStripe\Control\HTTPResponse;
10
use SilverStripe\Core\Injector\Injector;
11
use SilverStripe\View\TemplateGlobalProvider;
12
13
class AdminiRootController extends Controller implements TemplateGlobalProvider
14
{
15
16
    /**
17
     * Fallback admin URL in case this cannot be infered from Director.rules
18
     *
19
     * @var string
20
     * @config
21
     */
22
    private static $url_base = 'admini';
0 ignored issues
show
The private property $url_base is not used, and could be removed.
Loading history...
23
24
    /**
25
     * Convenience function to return the admin route config.
26
     * Looks for the {@link Director::$rules} for the current admin Controller.
27
     *
28
     * @return string
29
     */
30
    public static function get_admin_route()
31
    {
32
        $rules = Director::config()->get('rules');
33
        $adminRoute = array_search(__CLASS__, $rules);
34
        return $adminRoute ?: static::config()->get('url_base');
35
    }
36
37
    /**
38
     * Returns the root admin URL for the site with trailing slash
39
     *
40
     * @return string
41
     */
42
    public static function admin_url()
43
    {
44
        return self::get_admin_route() . '/';
45
    }
46
47
    /**
48
     * Useful when used alongside regular admin
49
     *
50
     * @return string
51
     */
52
    public static function get_current_admin_route()
53
    {
54
        $route = self::get_admin_route();
55
        if (Controller::has_curr()) {
56
            $curr = Controller::curr();
57
            $request = $curr->getRequest()->getURL();
58
            $firstSegment = explode("/", $request)[0] ?? null;
59
60
            // Force route to admin if it's the current segment
61
            if ($firstSegment == "admin") {
62
                $route = $firstSegment;
63
            }
64
        }
65
        return $route;
66
    }
67
68
    public static function force_redirect($segment, $fallbackRoute = null)
69
    {
70
        if ($fallbackRoute === null) {
71
            $fallbackRoute = self::get_current_admin_route();
72
        }
73
        header('Location: ' . $fallbackRoute . '/' . $segment);
74
        exit();
75
    }
76
77
    /**
78
     * @var string
79
     * @config
80
     * The LeftAndMain child that will be used as the initial panel to display if none is selected (i.e. if you
81
     * visit /admin)
82
     */
83
    private static $default_panel = SecurityAdmin::class;
0 ignored issues
show
The private property $default_panel is not used, and could be removed.
Loading history...
84
85
    /**
86
     * @var array
87
     * @internal
88
     *
89
     * Holds an array of url_pattern => controller k/v pairs, the same as Director::rules. However this is built
90
     * dynamically from introspecting on all the classes that derive from LeftAndMain.
91
     *
92
     * Don't access this directly - always access via the rules() accessor below, which will build this array
93
     * the first time it's accessed
94
     */
95
    private static $adminRules = null;
96
97
    /**
98
     * Gets a list of url_pattern => controller k/v pairs for each LeftAndMain derived controller
99
     */
100
    public static function rules()
101
    {
102
        if (self::$adminRules === null) {
0 ignored issues
show
The condition self::adminRules === null is always false.
Loading history...
103
            self::$adminRules = array();
104
105
            // Map over the array calling add_rule_for_controller on each
106
            $classes = CMSMenu::get_cms_classes(null, true, CMSMenu::URL_PRIORITY);
107
            array_map(array(__CLASS__, 'add_rule_for_controller'), $classes);
108
        }
109
        return self::$adminRules;
110
    }
111
112
    /**
113
     * Add the appropriate k/v pair to self::$rules for the given controller.
114
     *
115
     * @param string $controllerClass Name of class
116
     */
117
    protected static function add_rule_for_controller($controllerClass)
118
    {
119
        $config = Config::forClass($controllerClass);
120
        $urlSegment = $config->get('url_segment');
121
        $urlRule    = $config->get('url_rule');
122
123
        if ($urlSegment) {
124
            // Make director rule
125
            if ($urlRule[0] == '/') {
126
                $urlRule = substr($urlRule, 1);
127
            }
128
            $rule = $urlSegment . '//' . $urlRule;
129
130
            // ensure that the first call to add_rule_for_controller for a rule takes precedence
131
            if (!isset(self::$adminRules[$rule])) {
132
                self::$adminRules[$rule] = $controllerClass;
133
            }
134
        }
135
    }
136
137
    public function handleRequest(HTTPRequest $request): HTTPResponse
138
    {
139
        // If this is the final portion of the request (i.e. the URL is just /admin), direct to the default panel
140
        if ($request->allParsed()) {
141
            $segment = Config::forClass($this->config()->get('default_panel'))
142
                ->get('url_segment');
143
144
            $this->redirect(Controller::join_links(self::admin_url(), $segment, '/'));
145
            return $this->getResponse();
146
        }
147
148
        // Otherwise
149
        $rules = self::rules();
150
        foreach ($rules as $pattern => $controller) {
151
            if (($arguments = $request->match($pattern, true)) !== false) {
0 ignored issues
show
The assignment to $arguments is dead and can be removed.
Loading history...
152
                /** @var LeftAndMain $controllerObj */
153
                $controllerObj = Injector::inst()->create($controller);
154
                return $controllerObj->handleRequest($request);
155
            }
156
        }
157
158
        // Fall back to methods defined on LeftAndMain
159
        $controllerObj = Injector::inst()->create(LeftAndMain::class);
160
        return $controllerObj->handleRequest($request);
161
    }
162
163
    /**
164
     * @return array Returns an array of strings of the method names of methods on the call that should be exposed
165
     * as global variables in the templates.
166
     */
167
    public static function get_template_global_variables()
168
    {
169
        return array(
170
            'adminiURL' => 'admin_url'
171
        );
172
    }
173
}
174