-
Notifications
You must be signed in to change notification settings - Fork 0
/
package.php
448 lines (381 loc) · 13.2 KB
/
package.php
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
<?php
# 2018-08-08 在命令行之中快速查找php的配置文件位置
/**
* echo "<?php echo phpinfo(); ?>" | php | grep php.ini
*
*/
/**
* 为了减轻Imports函数的性能影响而设置的一个帮助函数对象
*/
class bootstrapLoader {
/**
* 当前已经加载的模块字典表
*
* ``[moduleName => path.php]``
*
* @var array
*/
public static $loaded = [];
/**
* Add loaded script path and its module name
*
* @param string $module
* @param string[] $files
*/
public static function push($module, $files) {
self::$loaded[$module] = $files;
}
/**
* 使用这个函数来判断目标模块是否已经被加载
*
* @param string $module 命名空间(不是文件路径)
*
* @return boolean
*/
public static function isLoaded($module) {
return array_key_exists($module, self::$loaded);
}
/**
* 最简单的加载函数,直接进行字符替换后加载模块文档
*
* **注意,这个函数仅适合于框架初始化的时候使用,其他的时候请使用``Imports``全局函数来加载模块**
*
* @param string $module The module name, VisualBasic namespace reference liked string text.
*/
public static function imports($module) {
$file = str_replace(".", "/", $module);
$php = PHP_DOTNET . "/$file.php";
include_once $php;
self::$loaded[$module] = $php;
}
}
#region "Constants"
// APP_DEBUG常数在引用这个文件之前必须首先进行定义
if (!defined('APP_DEBUG')) {
/**
* 这个常数会影响框架的调试器的输出行为,默认是关闭调试器
*/
define("APP_DEBUG", false);
}
if (!defined("FRAMEWORK_DEBUG")) {
/**
* 进行框架内部的调试使用的一个常量
*/
define("FRAMEWORK_DEBUG", false);
}
/**
* Php script running in a cli environment?
*/
define("IS_CLI", php_sapi_name() === 'cli');
/**
* 当前的源代码版本编号
*/
define("GIT_COMMIT", "5199591d44fdf133d33ad97495bfbfa881327af6");
if (IS_CLI && FRAMEWORK_DEBUG) {
# 2018-10-12 很奇怪,在终端中调试输出的第一行肯定会有一个空格
# 这个多于的空格会影响输出的格式
# 在这里跳过第一行
$time = date('Y-m-d H:i:s', time());
echo "\n";
echo " [$time]\n";
echo " ............................................................\n";
echo " ............................................................\n";
echo " ..............TT.................TNT....TT..TNNNNTTNNNNNNT..\n";
echo " ..............E..................hNh....h...h........E......\n";
echo " ..............E..................hhE....h...h........E......\n";
echo " .....TTTNNT..TTTNNT..TTTNNT.....TT.NT..TT..TT.......TT......\n";
echo " .....EN...E..EN..Th..EN...E.....h..Eh..h...hNNNE....h.......\n";
echo " .....E....E..E...TT..E....E.....h..TE..h...h........h.......\n";
echo " ....TT....h.TT...E..TT....h....TT...N.TT..TT.......TT.......\n";
echo " ....E....h..h....h..E....h.....h....Ehh...h........h........\n";
echo " ....NT..hT..h...TT..NT..hT.Th..h....TNh...h........h........\n";
echo " ...TThNNT..TT...h..TThNNT..ET.TT.....NT..TNNNNT...TT........\n";
echo " ...h...............h........................................\n";
echo " ...h...............h........................................\n";
echo " ..TT..............TT........................................\n";
echo " ............................................................\n";
echo "\n";
echo " -------------============ PHP.NET ============--------------\n\n";
echo " Repository: https://github.com/GCModeller-Cloud/php-dotnet\n";
echo " Version: " . GIT_COMMIT . "\n";
echo " Author: xieguigang <[email protected]>\n";
echo "\n\n";
}
if (!IS_CLI) {
# send a fake information header
header("X-Powered-By: ASP.NET");
# server header not working
# header("Server: IIS Docker");
}
if (!defined("SITE_PATH")) {
if (array_key_exists("DOCUMENT_ROOT", $_SERVER)) {
/**
* 当前的网站应用App的wwwroot文档根目录
*/
define("SITE_PATH", $_SERVER["DOCUMENT_ROOT"]);
} else {
# 如果是命令行环境的话,DOCUMENT_ROOT可能不存在
# 则这个时候就使用当前文件夹
define("SITE_PATH", getcwd());
}
}
if (array_key_exists("REQUEST_METHOD", $_SERVER)) {
# 2018-09-13
# 在命令行环境下,这个值是不存在的,会导致定义失败
# 所以在这里会需要先判断一下是否存在
# 如果REQUEST_METHOD不存在的话,则下面的两个常量都不会被定义,
# 则在下面的代码之中都会被定义为false
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
/**
* 当前的访问请求是否是一个POST请求
*/
define("IS_POST", true);
/**
* 当前的访问请求是否是一个GET请求
*/
define("IS_GET", false);
} else if ($_SERVER['REQUEST_METHOD'] === 'GET') {
/**
* 当前的访问请求是否是一个POST请求
*/
define("IS_POST", false);
/**
* 当前的访问请求是否是一个GET请求
*/
define("IS_GET", true);
}
# 20191205 disable php session management
/*
# 如果不是CLI环境,则尝试设置session
# 如果cookie不存在PHPSESSID则直接启动session
if (!empty($_COOKIE["PHPSESSID"])) {
// 在这里主要是为了防止对个站点共享同一个session
// 的时候,可能会造成因为对各站点的session id的cookie导致session信息丢失的问题
session_id($_COOKIE["PHPSESSID"]);
}
// for avoid the warning message
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
*/
}
if (!defined("IS_GET") && !defined("IS_POST")) {
/**
* 当前的访问请求是否是一个POST请求
*/
define("IS_POST", false);
/**
* 当前的访问请求是否是一个GET请求
*/
define("IS_GET", false);
}
if (IS_POST && (count($_POST) === 0)) {
# 2018-12-25 fix $_POST array empty bugs when recieved json object in server
#
# PHP does not process JSON requests automatically like it does with form-encoded
# or multipart requests. If you want to use JSON to send requests to PHP, you're
# basically doing it correctly with file_get_contents(). If you want to merge those
# variables into your global $_POST object you can, though I would not recommend
# doing this as it might be confusing to other developers.
#
# it's safe to overwrite the $_POST if the content-type is application/json
# because the $_POST var will be empty
#
# $headers = getallheaders();
# if ($headers["Content-Type"] == "application/json")
# $_POST = json_decode(file_get_contents("php://input"), true) ?: [];
#
# https://stackoverflow.com/questions/9516019/send-json-data-to-php-using-xmlhttprequest-w-o-jquery
#
$headers = getallheaders();
$contentType = "Content-Type";
if ($headers == false) {
$headers = [];
}
if (array_key_exists($contentType, $headers)) {
$contentType = strtolower($headers[$contentType]);
} else {
$contentType = "";
foreach(array_keys($headers) as $key) {
if (strtolower($key) == "content-type") {
$contentType = strtolower($headers[$key]);
break;
}
}
}
if ($contentType == "application/json" || $contentType == "text/json") {
$json = file_get_contents("php://input");
if (empty($json) || $json == "null" || $json == "NULL") {
$json = [];
} else {
$json = json_decode($json, true);
}
$_POST = $json;
}
}
#endregion
#region "file_loads"
/**
* PHP.NET框架的根文件夹位置
* 获取得到package.php这个文件的所处的文件夹的位置
*/
define("PHP_DOTNET", realpath( __DIR__ . "/Framework") );
bootstrapLoader::imports("Debugger.Ubench.Ubench");
# 加载框架之中的一些必要的模块,并进行性能计数
$load = new Ubench();
$load->run(function() {
# 加载核心文件
bootstrapLoader::imports("dotnet");
# 加载帮助函数模块
bootstrapLoader::imports("php.Utils");
bootstrapLoader::imports("bootstrap");
# 调试器必须要优先于其他模块进行加载,否则会出现
# Uncaught Error: Class 'dotnetDebugger' not found
# 的错误
bootstrapLoader::imports("Debugger.dotnetException");
bootstrapLoader::imports("Debugger.engine");
bootstrapLoader::imports("Debugger.view");
bootstrapLoader::imports("Debugger.console");
# 加载工具框架
bootstrapLoader::imports("System.IDisposable");
bootstrapLoader::imports("System.IO.File");
bootstrapLoader::imports("System.Diagnostics.StackTrace");
bootstrapLoader::imports("System.Text.StringBuilder");
bootstrapLoader::imports("Microsoft.VisualBasic.Strings");
bootstrapLoader::imports("Microsoft.VisualBasic.ApplicationServices.Debugger.Logging.LogFile");
bootstrapLoader::imports("MSDN");
# 加载Web框架部件
bootstrapLoader::imports("RFC7231.index");
bootstrapLoader::imports("Registry");
});
#endregion
if (APP_DEBUG) {
/**
* 当前SESSION之中的调试器会话的编号
*/
define("DEBUG_GUID", dotnetDebugger::getCurrentDebuggerGuid());
}
debugView::LogEvent("--- App start ---");
debugView::LogEvent("Load required modules in " . $load->getTime());
debugView::AddItem("benchmark.load", $load->getTime(true));
# PHP Warning: date(): It is not safe to rely on the system's timezone settings.
# You are *required* to use the date.timezone setting or the date_default_timezone_set() function.
# In case you used any of those methods and you are still getting this warning, you most likely
# misspelled the timezone identifier. We selected the timezone 'UTC' for now,
# but please set date.timezone to select your timezone.
date_default_timezone_set('Asia/Shanghai');
#region "global function"
/**
* Global function for load php.NET package modules.
*
* @param string $namespace php module file path
*/
function imports($namespace) {
// 因为为了从namespace解析出所需要加载的php文件会执行比较多的预处理操作
// 所以为了减轻模块的加载压力,在这里会使用这个帮助模块来避免
// 不必要的加载预处理操作
if (!bootstrapLoader::isLoaded($namespace)) {
return dotnet::Imports($namespace);
}
}
/**
* 在打印调试数据之后,脚本程序将会在这里退出执行
*
* @param mixed $dump Any php object for display in debug view
*/
function breakpoint($dump) {
header("Content-Type: text/html");
echo "<h3>Break Point:</h3>";
echo "<hr />";
echo StackTrace::GetCallStack()->ToString(true);
echo "<hr />";
echo "<h3>Object dumping data:</h3>";
echo "<pre><code>";
echo var_dump($dump);
echo "</code></pre>";
exit(0);
}
/**
* 对用户的浏览器进行重定向,支持路由规则。
* **注意,在使用这个函数进行重定向之后,脚本将会从这里退出执行**
*
* @param string $URL 目标URL字符串,可以支持诸如``{file/controller}``这样子的路由规则
*
*/
function Redirect($URL) {
header("Location: " . Router::AssignController($URL));
exit(0);
}
/**
* 判断目标对象值是否是空的?``empty``或者等于``false``都会被判断为Nothing
*
* @return boolean 判断目标对象值是否是空的?
*/
function IsNothing($obj) {
return empty($obj) || ($obj == false);
}
/**
* Write session value
*
* @param string $name The session variable name
* @param mixed $value Value
*/
function session($name, $value) {
$_SESSION[$name] = $value;
}
/**
* 重置当前的会话,将当前的绘制切换到所给定的会话中的
*
* @param string $new_ssID 将当前的会话切换到这个新编号所指定的会话中去
*/
function ResetSession($new_ssID) {
session_abort();
session_id($new_ssID);
session_start();
}
/**
* 主要是进行``Dispose``方法的自动调用
*/
function using(\System\IDisposable $obj, callable $procedure) {
$result = $procedure($obj);
$obj->Dispose();
return $result;
}
/**
* 对浏览器之中的cookie进行删除操作
* 这个函数支持批量处理模式
*
* @param string|array
*
* + 如果这个参数为string类型,则只会删除该名称的cookie
* + 如果这个参数为数组,则可以有两种模式:
* 1. tuple类型的: ``[cookie_name => domain]``
* 2. 批量cookie删除: ``[cookie_name => domain][]``
*/
function deleteCookies($cookies) {
if (is_string($cookies)) {
# 只删除单个cookie
setcookie($cookies, "", time() - 3600);
} else {
if (count($cookies) == 1) {
# 将[name => domain]转换为批量模式
$cookies = [$cookies];
}
# 执行批量删除
foreach($cookies as $cookie_name => $domain) {
setcookie($cookie_name, "", time() - 3600, "/", $domain);
}
}
}
/**
* Create a linq sequence object
*
* @param array $array
*
* @return IEnumerator
*/
function from($array) {
bootstrapLoader::imports("System.Linq.IEnumerator");
return new IEnumerator($array);
}
#endregion