Issues (2882)

src/Dev/TaskRunner.php (2 issues)

Severity
1
<?php
2
3
namespace SilverStripe\Dev;
4
5
use SilverStripe\Control\Controller;
6
use SilverStripe\Control\Director;
7
use SilverStripe\Control\HTTPRequest;
8
use SilverStripe\Core\ClassInfo;
9
use SilverStripe\Core\Convert;
10
use SilverStripe\Core\Injector\Injector;
11
use SilverStripe\Security\Permission;
12
use SilverStripe\Security\Security;
13
use ReflectionClass;
14
15
class TaskRunner extends Controller
16
{
17
18
    private static $url_handlers = array(
0 ignored issues
show
The private property $url_handlers is not used, and could be removed.
Loading history...
19
        '' => 'index',
20
        '$TaskName' => 'runTask'
21
    );
22
23
    private static $allowed_actions = array(
0 ignored issues
show
The private property $allowed_actions is not used, and could be removed.
Loading history...
24
        'index',
25
        'runTask',
26
    );
27
28
    protected function init()
29
    {
30
        parent::init();
31
32
        $allowAllCLI = DevelopmentAdmin::config()->get('allow_all_cli');
33
        $canAccess = (
34
            Director::isDev()
35
            // We need to ensure that DevelopmentAdminTest can simulate permission failures when running
36
            // "dev/tasks" from CLI.
37
            || (Director::is_cli() && $allowAllCLI)
38
            || Permission::check("ADMIN")
39
        );
40
        if (!$canAccess) {
41
            Security::permissionFailure($this);
42
        }
43
    }
44
45
    public function index()
46
    {
47
        $tasks = $this->getTasks();
48
49
        // Web mode
50
        if (!Director::is_cli()) {
51
            $renderer = new DebugView();
52
            echo $renderer->renderHeader();
53
            echo $renderer->renderInfo("SilverStripe Development Tools: Tasks", Director::absoluteBaseURL());
54
            $base = Director::absoluteBaseURL();
55
56
            echo "<div class=\"options\">";
57
            echo "<ul>";
58
            foreach ($tasks as $task) {
59
                echo "<li><p>";
60
                echo "<a href=\"{$base}dev/tasks/" . $task['segment'] . "\">" . $task['title'] . "</a><br />";
61
                echo "<span class=\"description\">" . $task['description'] . "</span>";
62
                echo "</p></li>\n";
63
            }
64
            echo "</ul></div>";
65
66
            echo $renderer->renderFooter();
67
        // CLI mode
68
        } else {
69
            echo "SILVERSTRIPE DEVELOPMENT TOOLS: Tasks\n--------------------------\n\n";
70
            foreach ($tasks as $task) {
71
                echo " * $task[title]: sake dev/tasks/" . $task['segment'] . "\n";
72
            }
73
        }
74
    }
75
76
    /**
77
     * Runs a BuildTask
78
     * @param HTTPRequest $request
79
     */
80
    public function runTask($request)
81
    {
82
        $name = $request->param('TaskName');
83
        $tasks = $this->getTasks();
84
85
        $title = function ($content) {
86
            printf(Director::is_cli() ? "%s\n\n" : '<h1>%s</h1>', $content);
87
        };
88
89
        $message = function ($content) {
90
            printf(Director::is_cli() ? "%s\n" : '<p>%s</p>', $content);
91
        };
92
93
        foreach ($tasks as $task) {
94
            if ($task['segment'] == $name) {
95
                /** @var BuildTask $inst */
96
                $inst = Injector::inst()->create($task['class']);
97
                $title(sprintf('Running Task %s', $inst->getTitle()));
98
99
                if (!$inst->isEnabled()) {
100
                    $message('The task is disabled');
101
                    return;
102
                }
103
104
                $inst->run($request);
105
                return;
106
            }
107
        }
108
109
        $message(sprintf('The build task "%s" could not be found', Convert::raw2xml($name)));
110
    }
111
112
    /**
113
     * @return array Array of associative arrays for each task (Keys: 'class', 'title', 'description')
114
     */
115
    protected function getTasks()
116
    {
117
        $availableTasks = array();
118
119
        $taskClasses = ClassInfo::subclassesFor(BuildTask::class);
120
        // remove the base class
121
        array_shift($taskClasses);
122
123
        foreach ($taskClasses as $class) {
124
            if (!$this->taskEnabled($class)) {
125
                continue;
126
            }
127
128
            $singleton = BuildTask::singleton($class);
129
130
            $desc = (Director::is_cli())
131
                ? Convert::html2raw($singleton->getDescription())
132
                : $singleton->getDescription();
133
134
            $availableTasks[] = array(
135
                'class' => $class,
136
                'title' => $singleton->getTitle(),
137
                'segment' => $singleton->config()->segment ?: str_replace('\\', '-', $class),
138
                'description' => $desc,
139
            );
140
        }
141
142
        return $availableTasks;
143
    }
144
145
    /**
146
     * @param string $class
147
     * @return boolean
148
     */
149
    protected function taskEnabled($class)
150
    {
151
        $reflectionClass = new ReflectionClass($class);
152
        if ($reflectionClass->isAbstract()) {
153
            return false;
154
        } elseif (!singleton($class)->isEnabled()) {
155
            return false;
156
        }
157
158
        return true;
159
    }
160
}
161