DevelopmentAdmin.php
6.08 KB
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<?php
/**
* Base class for development tools.
*
* Configured in framework/_config/dev.yml, with the config key registeredControllers being
* used to generate the list of links for /dev.
*
* @todo documentation for how to add new unit tests and tasks
* @todo do we need buildDefaults and generatesecuretoken? if so, register in the list
* @todo cleanup errors() it's not even an allowed action, so can go
* @todo cleanup index() html building
* @package framework
* @subpackage dev
*/
class DevelopmentAdmin extends Controller {
private static $url_handlers = array(
'' => 'index',
'build/defaults' => 'buildDefaults',
'generatesecuretoken' => 'generatesecuretoken',
'$Action' => 'runRegisteredController',
);
private static $allowed_actions = array(
'index',
'buildDefaults',
'runRegisteredController',
'generatesecuretoken',
);
public function init() {
parent::init();
// Special case for dev/build: Defer permission checks to DatabaseAdmin->init() (see #4957)
$requestedDevBuild = (stripos($this->request->getURL(), 'dev/build') === 0);
// We allow access to this controller regardless of live-status or ADMIN permission only
// if on CLI. Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
$canAccess = (
$requestedDevBuild
|| Director::isDev()
|| Director::is_cli()
// Its important that we don't run this check if dev/build was requested
|| Permission::check("ADMIN")
);
if(!$canAccess) return Security::permissionFailure($this);
// check for valid url mapping
// lacking this information can cause really nasty bugs,
// e.g. when running Director::test() from a FunctionalTest instance
global $_FILE_TO_URL_MAPPING;
if(Director::is_cli()) {
if(isset($_FILE_TO_URL_MAPPING)) {
$fullPath = $testPath = BASE_PATH;
while($testPath && $testPath != "/" && !preg_match('/^[A-Z]:\\\\$/', $testPath)) {
$matched = false;
if(isset($_FILE_TO_URL_MAPPING[$testPath])) {
$matched = true;
break;
}
$testPath = dirname($testPath);
}
if(!$matched) {
echo 'Warning: You probably want to define '.
'an entry in $_FILE_TO_URL_MAPPING that covers "' . Director::baseFolder() . '"' . "\n";
}
}
else {
echo 'Warning: You probably want to define $_FILE_TO_URL_MAPPING in '.
'your _ss_environment.php as instructed on the "sake" page of the doc.silverstripe.org wiki'."\n";
}
}
// Backwards compat: Default to "draft" stage, which is important
// for tasks like dev/build which call DataObject->requireDefaultRecords(),
// but also for other administrative tasks which have assumptions about the default stage.
Versioned::reading_stage('Stage');
}
public function index() {
// Web mode
if(!Director::is_cli()) {
$renderer = DebugView::create();
$renderer->writeHeader();
$renderer->writeInfo("SilverStripe Development Tools", Director::absoluteBaseURL());
$base = Director::baseURL();
echo '<div class="options"><ul>';
$evenOdd = "odd";
foreach(self::get_links() as $action => $description) {
echo "<li class=\"$evenOdd\"><a href=\"{$base}dev/$action\"><b>/dev/$action:</b>"
. " $description</a></li>\n";
$evenOdd = ($evenOdd == "odd") ? "even" : "odd";
}
$renderer->writeFooter();
// CLI mode
} else {
echo "SILVERSTRIPE DEVELOPMENT TOOLS\n--------------------------\n\n";
echo "You can execute any of the following commands:\n\n";
foreach(self::get_links() as $action => $description) {
echo " sake dev/$action: $description\n";
}
echo "\n\n";
}
}
public function runRegisteredController(SS_HTTPRequest $request){
$controllerClass = null;
$baseUrlPart = $request->param('Action');
$reg = Config::inst()->get(__CLASS__, 'registered_controllers');
if(isset($reg[$baseUrlPart])){
$controllerClass = $reg[$baseUrlPart]['controller'];
}
if($controllerClass && class_exists($controllerClass)){
return $controllerClass::create();
}
$msg = 'Error: no controller registered in '.__CLASS__.' for: '.$request->param('Action');
if(Director::is_cli()){
// in CLI we cant use httpError because of a bug with stuff being in the output already, see DevAdminControllerTest
throw new Exception($msg);
}else{
$this->httpError(500, $msg);
}
}
/*
* Internal methods
*/
/**
* @return array of url => description
*/
protected static function get_links(){
$links = array();
$reg = Config::inst()->get(__CLASS__, 'registered_controllers');
foreach($reg as $registeredController){
foreach($registeredController['links'] as $url => $desc){
$links[$url] = $desc;
}
}
return $links;
}
protected function getRegisteredController($baseUrlPart){
$reg = Config::inst()->get(__CLASS__, 'registered_controllers');
if(isset($reg[$baseUrlPart])){
$controllerClass = $reg[$baseUrlPart]['controller'];
return $controllerClass;
}
return null;
}
/*
* Unregistered (hidden) actions
*/
/**
* Build the default data, calling requireDefaultRecords on all
* DataObject classes
* Should match the $url_handlers rule:
* 'build/defaults' => 'buildDefaults',
*/
public function buildDefaults() {
$da = DatabaseAdmin::create();
if (!Director::is_cli()) {
$renderer = DebugView::create();
$renderer->writeHeader();
$renderer->writeInfo("Defaults Builder", Director::absoluteBaseURL());
echo "<div style=\"margin: 0 2em\">";
}
$da->buildDefaults();
if (!Director::is_cli()) {
echo "</div>";
$renderer->writeFooter();
}
}
/**
* Generate a secure token which can be used as a crypto key.
* Returns the token and suggests PHP configuration to set it.
*/
public function generatesecuretoken() {
$generator = Injector::inst()->create('RandomGenerator');
$token = $generator->randomToken('sha1');
$body = <<<TXT
Generated new token. Please add the following code to your YAML configuration:
Security:
token: $token
TXT;
$response = new SS_HTTPResponse($body);
return $response->addHeader('Content-Type', 'text/plain');
}
public function errors() {
$this->redirect("Debug_");
}
}