1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Core |
4
|
|
|
* |
5
|
|
|
* Risolutoの中核部分に関するメソッドが含まれているクラス |
6
|
|
|
* |
7
|
|
|
* @package risoluto |
8
|
|
|
* @author Risoluto Developers |
9
|
|
|
* @license http://opensource.org/licenses/bsd-license.php new BSD license |
10
|
|
|
* @copyright (C) 2008-2015 Risoluto Developers / All Rights Reserved. |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
//------------------------------------------------------// |
14
|
|
|
// 名前空間の定義 |
15
|
|
|
//------------------------------------------------------// |
16
|
|
|
namespace Risoluto; |
17
|
|
|
|
18
|
|
|
class Core |
19
|
|
|
{ |
20
|
|
|
//------------------------------------------------------// |
21
|
|
|
// クラスメソッド定義 |
22
|
|
|
//------------------------------------------------------// |
23
|
|
|
use RisolutoErrorLogTrait; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* perform() |
27
|
|
|
* |
28
|
|
|
* 指定されたアプリケーションを呼び出す |
29
|
|
|
* |
30
|
|
|
* @access public |
31
|
|
|
* |
32
|
|
|
* @param void |
33
|
|
|
* |
34
|
|
|
* @return void |
35
|
|
|
*/ |
36
|
|
|
public function perform() |
37
|
|
|
{ |
38
|
|
|
//------------------------------------------------------// |
39
|
|
|
// アプリケーションクラスをロードし実行する |
40
|
|
|
//------------------------------------------------------// |
41
|
|
|
// クラスインスタンスを生成し、実行する |
42
|
|
|
try { |
43
|
|
|
// 呼び出すクラスを決定する |
44
|
|
|
$call = $this->findCallClass(); |
45
|
|
|
|
46
|
|
|
// インスタンスの生成 |
47
|
|
|
$targetInstance = new $call[ 'load' ]; |
48
|
|
|
|
49
|
|
|
// イニシャライズメソッドをコール |
50
|
|
View Code Duplication |
if (method_exists( $targetInstance, 'init' )) { |
|
|
|
|
51
|
|
|
$targetInstance->init( $call[ 'param' ] ); |
52
|
|
|
} else { |
53
|
|
|
// メソッドが存在しなければ例外をThrow |
54
|
|
|
throw new \Exception( $this->coreError( 'error', 'notfound', 'Init()' ) ); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
// HTTPのメソッドに応じて適切なコントローラをコール |
58
|
|
|
switch ($_SERVER[ 'REQUEST_METHOD' ]) { |
59
|
|
|
// GETの場合 |
60
|
|
|
case 'GET': |
61
|
|
|
if (method_exists( $targetInstance, 'playGet' )) { |
62
|
|
|
$targetInstance->playGet(); |
63
|
|
|
} else { |
64
|
|
|
$this->playFuncCall( $targetInstance ); |
65
|
|
|
} |
66
|
|
|
break; |
67
|
|
|
|
68
|
|
|
// POSTの場合 |
69
|
|
|
case 'POST': |
70
|
|
|
if (method_exists( $targetInstance, 'playPost' )) { |
71
|
|
|
$targetInstance->playPost(); |
72
|
|
|
} else { |
73
|
|
|
$this->playFuncCall( $targetInstance ); |
74
|
|
|
} |
75
|
|
|
break; |
76
|
|
|
|
77
|
|
|
// PUTの場合 |
78
|
|
|
case 'PUT': |
79
|
|
|
if (method_exists( $targetInstance, 'playPut' )) { |
80
|
|
|
$targetInstance->playPut(); |
81
|
|
|
} else { |
82
|
|
|
$this->playFuncCall( $targetInstance ); |
83
|
|
|
} |
84
|
|
|
break; |
85
|
|
|
|
86
|
|
|
// DELETEの場合 |
87
|
|
|
case 'DELETE': |
88
|
|
|
if (method_exists( $targetInstance, 'playDelete' )) { |
89
|
|
|
$targetInstance->playDelete(); |
90
|
|
|
} else { |
91
|
|
|
$this->playFuncCall( $targetInstance ); |
92
|
|
|
} |
93
|
|
|
break; |
94
|
|
|
|
95
|
|
|
// OPTIONの場合 |
96
|
|
|
case 'OPTION': |
97
|
|
|
if (method_exists( $targetInstance, 'playOption' )) { |
98
|
|
|
$targetInstance->playOption(); |
99
|
|
|
} else { |
100
|
|
|
$this->playFuncCall( $targetInstance ); |
101
|
|
|
} |
102
|
|
|
break; |
103
|
|
|
|
104
|
|
|
// HEADの場合 |
105
|
|
|
case 'HEAD': |
106
|
|
|
if (method_exists( $targetInstance, 'playHead' )) { |
107
|
|
|
$targetInstance->playHead(); |
108
|
|
|
} else { |
109
|
|
|
$this->playFuncCall( $targetInstance ); |
110
|
|
|
} |
111
|
|
|
break; |
112
|
|
|
|
113
|
|
|
// TRACEの場合 |
114
|
|
|
case 'TRACE': |
115
|
|
|
if (method_exists( $targetInstance, 'playTrace' )) { |
116
|
|
|
$targetInstance->playTrace(); |
117
|
|
|
} else { |
118
|
|
|
$this->playFuncCall( $targetInstance ); |
119
|
|
|
} |
120
|
|
|
break; |
121
|
|
|
|
122
|
|
|
// CONNECTの場合 |
123
|
|
|
case 'CONNECT': |
124
|
|
|
if (method_exists( $targetInstance, 'playConnect' )) { |
125
|
|
|
$targetInstance->playConnect(); |
126
|
|
|
} else { |
127
|
|
|
$this->playFuncCall( $targetInstance ); |
128
|
|
|
} |
129
|
|
|
break; |
130
|
|
|
|
131
|
|
|
// デフォルトの場合 |
132
|
|
|
default: |
133
|
|
|
$this->playFuncCall( $targetInstance ); |
134
|
|
|
break; |
135
|
|
|
} |
136
|
|
|
} catch ( \Exception $e ) { |
137
|
|
|
// エラーハンドリングメソッドをコール |
138
|
|
|
if (!empty( $targetInstance )) { |
139
|
|
|
if (method_exists( $targetInstance, 'error' )) { |
140
|
|
|
$targetInstance->error( $e ); |
141
|
|
|
} else { |
142
|
|
|
// メソッドが存在しなければ強制終了 |
143
|
|
|
die( $this->coreError( 'error', 'notfound', 'Error()' ) ); |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
} finally { |
147
|
|
|
// クリーニングメソッドをコール |
148
|
|
|
if (!empty( $targetInstance )) { |
149
|
|
|
if (method_exists( $targetInstance, 'clean' )) { |
150
|
|
|
$targetInstance->clean(); |
151
|
|
|
} else { |
152
|
|
|
// メソッドが存在しなければ強制終了 |
153
|
|
|
die( $this->coreError( 'error', 'notfound', 'Clean()' ) ); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* playFuncCall($targetInstance) |
161
|
|
|
* |
162
|
|
|
* play()メソッドをコールする(存在しない場合は例外をThrow) |
163
|
|
|
* |
164
|
|
|
* @access private |
165
|
|
|
* |
166
|
|
|
* @param object $targetInstance クラスインスタンス |
167
|
|
|
* |
168
|
|
|
* @return void |
169
|
|
|
* |
170
|
|
|
* @throws \Exception |
171
|
|
|
*/ |
172
|
|
|
private function playFuncCall( $targetInstance ) |
173
|
|
|
{ |
174
|
|
View Code Duplication |
if (method_exists( $targetInstance, 'play' )) { |
|
|
|
|
175
|
|
|
$targetInstance->play(); |
176
|
|
|
} else { |
177
|
|
|
// メソッドが存在しなければ例外をThrow |
178
|
|
|
throw new \Exception( $this->coreError( 'error', 'notfound', 'play*()' ) ); |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* fixSeqParam($value = '') |
184
|
|
|
* |
185
|
|
|
* $_GET['seq']の値から不適切な文字を排除する |
186
|
|
|
* |
187
|
|
|
* @access private |
188
|
|
|
* |
189
|
|
|
* @param String $value $_GET['seq']の値 |
190
|
|
|
* |
191
|
|
|
* @return String 適切な状態に加工した$_GET['seq'] |
192
|
|
|
*/ |
193
|
|
|
private function fixSeqParam( $value = '' ) |
194
|
|
|
{ |
195
|
|
|
// 検出対象のリスト |
196
|
|
|
$searches = [ '/\.+/', '/_+/', '/\//', '/\¥/', '/\\\\/', '/[[:blank:]]/', '/[[:cntrl:]]/' ]; |
197
|
|
|
|
198
|
|
|
// 対応する置換文字のリスト |
199
|
|
|
$replacement = [ '.', '_', '', '', '', '', '' ]; |
200
|
|
|
|
201
|
|
|
// 不正な値を除去 |
202
|
|
|
$retval = preg_replace( $searches, $replacement, $value ); |
203
|
|
|
|
204
|
|
|
return $retval; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* isDisabled($dirpath, $target) |
209
|
|
|
* |
210
|
|
|
* 無効指定されているかを判定する |
211
|
|
|
* |
212
|
|
|
* @access private |
213
|
|
|
* |
214
|
|
|
* @param String $dirpath 無効指定ファイルの存在チェックを行うパス |
215
|
|
|
* @param String $target 無効指定チェック対象となるクラス(RisolutoApps\からのフル指定) |
216
|
|
|
* |
217
|
|
|
* @return Boolean true:無効指定されている/false:無効指定されていない |
218
|
|
|
*/ |
219
|
|
|
private function isDisabled( $dirpath, $target ) |
220
|
|
|
{ |
221
|
|
|
// 変数の初期化 |
222
|
|
|
$retval = false; |
223
|
|
|
$ignorefile = $dirpath . '/RisolutoIgnore'; |
224
|
|
|
|
225
|
|
|
// 無効指定ファイルが存在するかをチェック |
226
|
|
|
clearstatcache( true ); |
227
|
|
|
if (file_exists( $ignorefile ) and is_file( $ignorefile ) and is_readable( $ignorefile )) { |
228
|
|
|
// ファイルの内容を読み込む |
229
|
|
|
$ignorelist = file( $ignorefile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); |
230
|
|
|
|
231
|
|
|
// 無効指定されているかを判定(空の場合は全指定されているとみなす) |
232
|
|
|
if (empty( $ignorelist ) or in_array( $target, $ignorelist )) { |
233
|
|
|
$retval = true; |
234
|
|
|
} |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
return $retval; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* findCallClass() |
242
|
|
|
* |
243
|
|
|
* 呼び出すクラスを決定する |
244
|
|
|
* |
245
|
|
|
* @access private |
246
|
|
|
* |
247
|
|
|
* @param void |
248
|
|
|
* |
249
|
|
|
* @return array 呼び出すクラスの情報等 |
250
|
|
|
*/ |
251
|
|
|
private function findCallClass() |
252
|
|
|
{ |
253
|
|
|
// コンフィグファイルの読み込み |
254
|
|
|
$conf = new Conf; |
255
|
|
|
$conf->parse( RISOLUTO_CONF . 'risoluto.ini' ); |
256
|
|
|
|
257
|
|
|
// デフォルトの情報をセット |
258
|
|
|
$load = $conf->getIni( 'SEQ', 'default' ); |
259
|
|
|
$param = [ ]; |
260
|
|
|
|
261
|
|
|
// $_GET['seq']の値をチェックする |
262
|
|
|
$seq = $this->fixSeqParam( ( isset( $_GET[ 'seq' ] ) ) ? $_GET[ 'seq' ] : '' ); |
263
|
|
|
|
264
|
|
|
// GETパラメタ中の情報(「seq」)が指定されていればそれを採用 |
265
|
|
|
if (isset( $seq ) and !empty( $seq )) { |
266
|
|
|
// 「.」が付いていたらそこで分割 |
267
|
|
|
if (strpos( '.', $seq ) === false) { |
268
|
|
|
$sep = explode( '.', $seq ); |
269
|
|
|
|
270
|
|
|
// 分割後、1つめの要素は画面指定とみなし、2つめ以降の要素はパラメタと見なす |
271
|
|
|
$load = 'RisolutoApps\\' . $sep[ 0 ]; |
272
|
|
|
|
273
|
|
|
unset( $sep[ 0 ] ); |
274
|
|
|
foreach ($sep as $dat) { |
275
|
|
|
$param[ ] = $dat; |
276
|
|
|
} |
277
|
|
|
// 「.」が付いていなければそのまま採用する |
278
|
|
|
} else { |
279
|
|
|
$load = 'RisolutoApps\\' . $seq; |
280
|
|
|
$param = [ ]; |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
// $load中の「_」を「\」に置換 |
284
|
|
|
$load = str_replace( '_', '\\', $load ); |
285
|
|
|
|
286
|
|
|
// 指定されたアプリケーションが存在していないか無効指定されていたらエラーとする |
287
|
|
|
$target = RISOLUTO_APPS . str_replace( '\\', DIRECTORY_SEPARATOR, $load ) . '.php'; |
288
|
|
|
clearstatcache( true ); |
289
|
|
|
if (!file_exists( $target ) or !is_file( $target ) or !is_readable( $target ) or $this->isDisabled( dirname( $target ), |
290
|
|
|
$load ) |
291
|
|
|
) { |
292
|
|
|
// ログにも記録しておく |
293
|
|
|
$this->coreError( 'warn', 'classnotfound', $load . ' (Path: ' . $target . ' ) / Go to Error page.' ); |
294
|
|
|
|
295
|
|
|
$load = $conf->getIni( 'SEQ', 'error' ); |
296
|
|
|
$param = [ ]; |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
// サービスストップファイルが存在するかロードアベレージが一定値以上ならサービスストップ |
301
|
|
|
$loadavg = sys_getloadavg(); |
302
|
|
|
$max_loadavg = $conf->getIni( 'LIMITS', 'max_loadavg' ); |
303
|
|
|
clearstatcache( true ); |
304
|
|
|
if (file_exists( RISOLUTO_SYSROOT . 'ServiceStop' ) or ( !empty( $max_loadavg ) and $loadavg[ 0 ] > $max_loadavg )) { |
305
|
|
|
// ログにも記録しておく |
306
|
|
|
$this->coreError( 'warn', 'servicestop', |
307
|
|
|
'Current Loadavg: ' . $loadavg[ 0 ] . ' / Setting: ' . $max_loadavg ); |
308
|
|
|
|
309
|
|
|
$load = $conf->getIni( 'SEQ', 'servicestop' ); |
310
|
|
|
$param = [ ]; |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
// 決定した情報を返却する |
314
|
|
|
$retval = [ |
315
|
|
|
'load' => $load, |
316
|
|
|
'param' => $param |
317
|
|
|
]; |
318
|
|
|
|
319
|
|
|
return $retval; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* coreError($error_level = 'error', $key = '', $optional_text = 'unknown') |
324
|
|
|
* |
325
|
|
|
* クラス内で発生したエラーに対するエラーメッセージを生成する |
326
|
|
|
* |
327
|
|
|
* @access private |
328
|
|
|
* |
329
|
|
|
* @param string $error_level エラーレベル |
330
|
|
|
* @param string $key エラーを示すキー文字列 |
331
|
|
|
* @param string $optional_text オプションの文字列 |
332
|
|
|
* |
333
|
|
|
* @return string エラーメッセージ |
334
|
|
|
*/ |
335
|
|
|
private function coreError( $error_level = 'error', $key = '', $optional_text = 'unknown' ) |
336
|
|
|
{ |
337
|
|
|
// 引数の値に応じてエラーメッセージをセットする |
338
|
|
|
switch ($key) { |
339
|
|
|
// 未定義エラーの場合 |
340
|
|
|
case 'notfound': |
341
|
|
|
$msg = 'Required method is not exists - ' . $optional_text; |
342
|
|
|
break; |
343
|
|
|
|
344
|
|
|
// URLで指定されたアプリケーションが存在しないか無効指定されている場合 |
345
|
|
|
case 'classnotfound': |
346
|
|
|
$msg = 'Class not found or disabled - ' . $optional_text; |
347
|
|
|
break; |
348
|
|
|
|
349
|
|
|
// サービスストップが発生した場合 |
350
|
|
|
case 'servicestop': |
351
|
|
|
$msg = 'Auto Service Stop - ' . $optional_text; |
352
|
|
|
break; |
353
|
|
|
|
354
|
|
|
|
355
|
|
|
// 未定義のエラーの場合 |
356
|
|
|
default: |
357
|
|
|
$msg = 'Unknown Error occurred'; |
358
|
|
|
break; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
// ログ出力しエラーメッセージを返却 |
362
|
|
|
$this->risolutoErrorLog( $error_level, '[' . __CLASS__ . '/]' . $msg ); |
363
|
|
|
|
364
|
|
|
return $msg; |
365
|
|
|
} |
366
|
|
|
} |
367
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.