create-prisma-php-app 4.0.0-alpha.51 → 4.0.0-alpha.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap.php +3 -3
- package/dist/src/Lib/Auth/Auth.php +1 -1
- package/dist/src/Lib/CacheHandler.php +1 -1
- package/dist/src/Lib/ErrorHandler.php +1 -1
- package/dist/src/Lib/Middleware/AuthMiddleware.php +1 -1
- package/dist/src/Lib/StateManager.php +1 -1
- package/dist/src/app/index.php +1 -1
- package/dist/src/app/layout.php +2 -2
- package/package.json +1 -1
- package/dist/src/Lib/MainLayout.php +0 -230
- package/dist/src/Lib/PrismaPHPSettings.php +0 -181
- package/dist/src/Lib/Request.php +0 -479
package/dist/bootstrap.php
CHANGED
|
@@ -18,12 +18,12 @@ if (session_status() === PHP_SESSION_NONE) {
|
|
|
18
18
|
session_start();
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
use
|
|
22
|
-
use
|
|
21
|
+
use PPHP\Request;
|
|
22
|
+
use PPHP\PrismaPHPSettings;
|
|
23
23
|
use Lib\StateManager;
|
|
24
24
|
use Lib\Middleware\AuthMiddleware;
|
|
25
25
|
use Lib\Auth\Auth;
|
|
26
|
-
use
|
|
26
|
+
use PPHP\MainLayout;
|
|
27
27
|
use PPHP\PHPX\TemplateCompiler;
|
|
28
28
|
use Lib\CacheHandler;
|
|
29
29
|
use Lib\ErrorHandler;
|
package/dist/src/app/index.php
CHANGED
package/dist/src/app/layout.php
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?php
|
|
2
2
|
|
|
3
|
-
use
|
|
4
|
-
use
|
|
3
|
+
use PPHP\MainLayout;
|
|
4
|
+
use PPHP\Request;
|
|
5
5
|
|
|
6
6
|
MainLayout::$title = !empty(MainLayout::$title) ? MainLayout::$title : 'Create Prisma PHP App';
|
|
7
7
|
MainLayout::$description = !empty(MainLayout::$description) ? MainLayout::$description : 'Generated by create Prisma PHP App';
|
package/package.json
CHANGED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Lib;
|
|
6
|
-
|
|
7
|
-
use Lib\Set;
|
|
8
|
-
|
|
9
|
-
class MainLayout
|
|
10
|
-
{
|
|
11
|
-
public static string $title = '';
|
|
12
|
-
public static string $description = '';
|
|
13
|
-
public static string $children = '';
|
|
14
|
-
public static string $childLayoutChildren = '';
|
|
15
|
-
public static string $html = '';
|
|
16
|
-
|
|
17
|
-
/** @var Set<string>|null */
|
|
18
|
-
private static ?Set $headScripts = null;
|
|
19
|
-
/** @var Set<string>|null */
|
|
20
|
-
private static ?Set $footerScripts = null;
|
|
21
|
-
private static array $customMetadata = [];
|
|
22
|
-
|
|
23
|
-
private static array $processedScripts = [];
|
|
24
|
-
|
|
25
|
-
public static function init(): void
|
|
26
|
-
{
|
|
27
|
-
if (self::$headScripts === null) {
|
|
28
|
-
self::$headScripts = new Set();
|
|
29
|
-
}
|
|
30
|
-
if (self::$footerScripts === null) {
|
|
31
|
-
self::$footerScripts = new Set();
|
|
32
|
-
}
|
|
33
|
-
self::$processedScripts = [];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Adds one or more scripts to the head section if they are not already present.
|
|
38
|
-
*
|
|
39
|
-
* @param string ...$scripts The scripts to be added to the head section.
|
|
40
|
-
* @return void
|
|
41
|
-
*/
|
|
42
|
-
public static function addHeadScript(string ...$scripts): void
|
|
43
|
-
{
|
|
44
|
-
foreach ($scripts as $script) {
|
|
45
|
-
self::$headScripts->add($script);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Adds one or more scripts to the footer section if they are not already present.
|
|
51
|
-
*
|
|
52
|
-
* @param string ...$scripts One or more scripts to be added to the footer.
|
|
53
|
-
* @return void
|
|
54
|
-
*/
|
|
55
|
-
public static function addFooterScript(string ...$scripts): void
|
|
56
|
-
{
|
|
57
|
-
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
|
58
|
-
$callerClass = $trace[1]['class'] ?? 'Unknown';
|
|
59
|
-
|
|
60
|
-
foreach ($scripts as $script) {
|
|
61
|
-
$scriptKey = md5(trim($script));
|
|
62
|
-
|
|
63
|
-
if (strpos($script, '<script') !== false) {
|
|
64
|
-
$taggedScript = "<!-- class:" . $callerClass . " -->\n" . $script;
|
|
65
|
-
if (!isset(self::$processedScripts[$scriptKey])) {
|
|
66
|
-
self::$footerScripts->add($taggedScript);
|
|
67
|
-
self::$processedScripts[$scriptKey] = true;
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
if (!isset(self::$processedScripts[$scriptKey])) {
|
|
71
|
-
self::$footerScripts->add($script);
|
|
72
|
-
self::$processedScripts[$scriptKey] = true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Generates all the head scripts with dynamic attributes.
|
|
80
|
-
*
|
|
81
|
-
* This method iterates over all registered head scripts and adds a custom dynamic attribute
|
|
82
|
-
* based on the tag type (script, link, or style).
|
|
83
|
-
*
|
|
84
|
-
* @return string The concatenated head scripts with dynamic attributes.
|
|
85
|
-
*/
|
|
86
|
-
public static function outputHeadScripts(): string
|
|
87
|
-
{
|
|
88
|
-
$headScriptsArray = self::$headScripts->values();
|
|
89
|
-
$headScriptsWithAttributes = array_map(function ($tag) {
|
|
90
|
-
if (strpos($tag, '<script') !== false) {
|
|
91
|
-
return str_replace('<script', '<script pp-dynamic-script="81D7D"', $tag);
|
|
92
|
-
} elseif (strpos($tag, '<link') !== false) {
|
|
93
|
-
return str_replace('<link', '<link pp-dynamic-link="81D7D"', $tag);
|
|
94
|
-
} elseif (strpos($tag, '<style') !== false) {
|
|
95
|
-
return str_replace('<style', '<style pp-dynamic-style="81D7D"', $tag);
|
|
96
|
-
}
|
|
97
|
-
return $tag;
|
|
98
|
-
}, $headScriptsArray);
|
|
99
|
-
|
|
100
|
-
return implode("\n", $headScriptsWithAttributes);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Generates all the footer scripts.
|
|
105
|
-
*
|
|
106
|
-
* @return string The concatenated footer scripts.
|
|
107
|
-
*/
|
|
108
|
-
public static function outputFooterScripts(): string
|
|
109
|
-
{
|
|
110
|
-
$processed = [];
|
|
111
|
-
$componentCounter = 0;
|
|
112
|
-
|
|
113
|
-
foreach (self::$footerScripts->values() as $script) {
|
|
114
|
-
if (preg_match('/<!-- class:([^\s]+) -->/', $script, $matches)) {
|
|
115
|
-
$rawClassName = $matches[1];
|
|
116
|
-
$script = preg_replace('/<!-- class:[^\s]+ -->\s*/', '', $script, 1);
|
|
117
|
-
|
|
118
|
-
if (str_starts_with(trim($script), '<script')) {
|
|
119
|
-
$script = preg_replace_callback(
|
|
120
|
-
'/<script\b([^>]*)>/i',
|
|
121
|
-
function ($m) use ($rawClassName, &$componentCounter) {
|
|
122
|
-
$attrs = $m[1];
|
|
123
|
-
$scriptHash = substr(md5($m[0]), 0, 8);
|
|
124
|
-
$encodedClass = 's' . base_convert(sprintf('%u', crc32($rawClassName . $componentCounter . $scriptHash)), 10, 36);
|
|
125
|
-
$componentCounter++;
|
|
126
|
-
|
|
127
|
-
if (!str_contains($attrs, 'pp-component=')) {
|
|
128
|
-
$attrs .= " pp-component=\"{$encodedClass}\"";
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (!preg_match('/\btype\s*=\s*(["\'])[^\1]*\1|\btype\s*=\s*\S+/i', $attrs)) {
|
|
132
|
-
$attrs .= ' type="text/php"';
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return "<script{$attrs}>";
|
|
136
|
-
},
|
|
137
|
-
$script,
|
|
138
|
-
1
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
$processed[] = $script;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return implode("\n", $processed);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Clears all head scripts.
|
|
151
|
-
*
|
|
152
|
-
* @return void
|
|
153
|
-
*/
|
|
154
|
-
public static function clearHeadScripts(): void
|
|
155
|
-
{
|
|
156
|
-
self::$headScripts->clear();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Clears all footer scripts.
|
|
161
|
-
*
|
|
162
|
-
* @return void
|
|
163
|
-
*/
|
|
164
|
-
public static function clearFooterScripts(): void
|
|
165
|
-
{
|
|
166
|
-
self::$footerScripts->clear();
|
|
167
|
-
self::$processedScripts = [];
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Adds custom metadata.
|
|
172
|
-
*
|
|
173
|
-
* @param string $key The metadata key.
|
|
174
|
-
* @param string $value The metadata value.
|
|
175
|
-
* @return void
|
|
176
|
-
*/
|
|
177
|
-
public static function addCustomMetadata(string $key, string $value): void
|
|
178
|
-
{
|
|
179
|
-
self::$customMetadata[$key] = $value;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Retrieves custom metadata by key.
|
|
184
|
-
*
|
|
185
|
-
* @param string $key The metadata key.
|
|
186
|
-
* @return string|null The metadata value or null if the key does not exist.
|
|
187
|
-
*/
|
|
188
|
-
public static function getCustomMetadata(string $key): ?string
|
|
189
|
-
{
|
|
190
|
-
return self::$customMetadata[$key] ?? null;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Generates the metadata as meta tags for the head section.
|
|
195
|
-
*
|
|
196
|
-
* This method includes default tags for charset and viewport, a title tag,
|
|
197
|
-
* and additional metadata. If a description is not already set in the custom metadata,
|
|
198
|
-
* it will use the class's description property.
|
|
199
|
-
*
|
|
200
|
-
* @return string The concatenated meta tags.
|
|
201
|
-
*/
|
|
202
|
-
public static function outputMetadata(): string
|
|
203
|
-
{
|
|
204
|
-
$metadataContent = [
|
|
205
|
-
'<meta charset="UTF-8">',
|
|
206
|
-
'<meta name="viewport" content="width=device-width, initial-scale=1.0">',
|
|
207
|
-
];
|
|
208
|
-
$metadataContent[] = '<title>' . htmlspecialchars(self::$title) . '</title>';
|
|
209
|
-
|
|
210
|
-
if (!isset(self::$customMetadata['description'])) {
|
|
211
|
-
self::$customMetadata['description'] = self::$description;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
foreach (self::$customMetadata as $key => $value) {
|
|
215
|
-
$metadataContent[] = '<meta name="' . htmlspecialchars($key) . '" content="' . htmlspecialchars($value) . '" pp-dynamic-meta="81D7D">';
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return implode("\n", $metadataContent);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Clears all custom metadata.
|
|
223
|
-
*
|
|
224
|
-
* @return void
|
|
225
|
-
*/
|
|
226
|
-
public static function clearCustomMetadata(): void
|
|
227
|
-
{
|
|
228
|
-
self::$customMetadata = [];
|
|
229
|
-
}
|
|
230
|
-
}
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Lib;
|
|
6
|
-
|
|
7
|
-
use Exception;
|
|
8
|
-
|
|
9
|
-
class BSPathRewrite
|
|
10
|
-
{
|
|
11
|
-
public string $pattern;
|
|
12
|
-
public string $replacement;
|
|
13
|
-
|
|
14
|
-
public function __construct(array $data)
|
|
15
|
-
{
|
|
16
|
-
$this->pattern = $data['pattern'] ?? '';
|
|
17
|
-
$this->replacement = $data['replacement'] ?? '';
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
class PrismaSettings
|
|
22
|
-
{
|
|
23
|
-
public string $projectName;
|
|
24
|
-
public string $projectRootPath;
|
|
25
|
-
public string $phpEnvironment;
|
|
26
|
-
public string $phpRootPathExe;
|
|
27
|
-
public string $phpGenerateClassPath;
|
|
28
|
-
public string $bsTarget;
|
|
29
|
-
public BSPathRewrite $bsPathRewrite;
|
|
30
|
-
public bool $backendOnly;
|
|
31
|
-
public bool $swaggerDocs;
|
|
32
|
-
public bool $tailwindcss;
|
|
33
|
-
public bool $websocket;
|
|
34
|
-
public bool $prisma;
|
|
35
|
-
public bool $docker;
|
|
36
|
-
public string $version;
|
|
37
|
-
public array $excludeFiles;
|
|
38
|
-
|
|
39
|
-
public function __construct(array $data)
|
|
40
|
-
{
|
|
41
|
-
$this->projectName = $data['projectName'] ?? '';
|
|
42
|
-
$this->projectRootPath = $data['projectRootPath'] ?? '';
|
|
43
|
-
$this->phpEnvironment = $data['phpEnvironment'] ?? '';
|
|
44
|
-
$this->phpRootPathExe = $data['phpRootPathExe'] ?? '';
|
|
45
|
-
$this->bsTarget = $data['bsTarget'] ?? '';
|
|
46
|
-
$this->bsPathRewrite = new BSPathRewrite($data['bsPathRewrite'] ?? []);
|
|
47
|
-
$this->backendOnly = $data['backendOnly'] ?? false;
|
|
48
|
-
$this->swaggerDocs = $data['swaggerDocs'] ?? false;
|
|
49
|
-
$this->tailwindcss = $data['tailwindcss'] ?? false;
|
|
50
|
-
$this->websocket = $data['websocket'] ?? false;
|
|
51
|
-
$this->prisma = $data['prisma'] ?? false;
|
|
52
|
-
$this->docker = $data['docker'] ?? false;
|
|
53
|
-
$this->version = $data['version'] ?? '';
|
|
54
|
-
$this->excludeFiles = $data['excludeFiles'] ?? [];
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
class PrismaPHPSettings
|
|
59
|
-
{
|
|
60
|
-
/**
|
|
61
|
-
* The settings from the prisma-php.json file.
|
|
62
|
-
*
|
|
63
|
-
* @var PrismaSettings
|
|
64
|
-
*/
|
|
65
|
-
public static PrismaSettings $option;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* The list of route files from the files-list.json file.
|
|
69
|
-
*
|
|
70
|
-
* @var array
|
|
71
|
-
*/
|
|
72
|
-
public static array $routeFiles = [];
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* The list of class log files.
|
|
76
|
-
*
|
|
77
|
-
* @var array
|
|
78
|
-
*/
|
|
79
|
-
public static array $classLogFiles = [];
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* The list of include files.
|
|
83
|
-
*
|
|
84
|
-
* @var array
|
|
85
|
-
*/
|
|
86
|
-
public static array $includeFiles = [];
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* The local storage key for the app state.
|
|
90
|
-
*
|
|
91
|
-
* @var string
|
|
92
|
-
*/
|
|
93
|
-
public static string $localStoreKey;
|
|
94
|
-
|
|
95
|
-
public static function init(): void
|
|
96
|
-
{
|
|
97
|
-
self::$option = self::getPrismaSettings();
|
|
98
|
-
self::$routeFiles = self::getRoutesFileList();
|
|
99
|
-
self::$classLogFiles = self::getClassesLogFiles();
|
|
100
|
-
self::$includeFiles = self::getIncludeFiles();
|
|
101
|
-
self::$localStoreKey = self::getLocalStorageKey();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Get Prisma settings from the JSON file.
|
|
106
|
-
*
|
|
107
|
-
* @return PrismaSettings
|
|
108
|
-
* @throws Exception if the JSON file cannot be decoded.
|
|
109
|
-
*/
|
|
110
|
-
private static function getPrismaSettings(): PrismaSettings
|
|
111
|
-
{
|
|
112
|
-
$prismaPHPSettingsJson = DOCUMENT_PATH . '/prisma-php.json';
|
|
113
|
-
|
|
114
|
-
if (!file_exists($prismaPHPSettingsJson)) {
|
|
115
|
-
throw new Exception("Settings file not found: $prismaPHPSettingsJson");
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
$jsonContent = file_get_contents($prismaPHPSettingsJson);
|
|
119
|
-
$decodedJson = json_decode($jsonContent, true);
|
|
120
|
-
|
|
121
|
-
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
122
|
-
throw new Exception("Failed to decode JSON: " . json_last_error_msg());
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return new PrismaSettings($decodedJson);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private static function getRoutesFileList(): array
|
|
129
|
-
{
|
|
130
|
-
$jsonFileName = SETTINGS_PATH . '/files-list.json';
|
|
131
|
-
if (!file_exists($jsonFileName)) {
|
|
132
|
-
return [];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
$jsonContent = file_get_contents($jsonFileName);
|
|
136
|
-
if ($jsonContent === false || empty(trim($jsonContent))) {
|
|
137
|
-
return [];
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
$routeFiles = json_decode($jsonContent, true);
|
|
141
|
-
return is_array($routeFiles) ? $routeFiles : [];
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private static function getClassesLogFiles(): array
|
|
145
|
-
{
|
|
146
|
-
$jsonFileName = SETTINGS_PATH . '/class-imports.json';
|
|
147
|
-
if (!file_exists($jsonFileName)) {
|
|
148
|
-
return [];
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
$jsonContent = file_get_contents($jsonFileName);
|
|
152
|
-
if ($jsonContent === false || empty(trim($jsonContent))) {
|
|
153
|
-
return [];
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
$classLogFiles = json_decode($jsonContent, true);
|
|
157
|
-
return is_array($classLogFiles) ? $classLogFiles : [];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private static function getIncludeFiles(): array
|
|
161
|
-
{
|
|
162
|
-
$jsonFileName = SETTINGS_PATH . "/request-data.json";
|
|
163
|
-
if (!file_exists($jsonFileName)) {
|
|
164
|
-
return [];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
$jsonContent = file_get_contents($jsonFileName);
|
|
168
|
-
if ($jsonContent === false || empty(trim($jsonContent))) {
|
|
169
|
-
return [];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
$includeFiles = json_decode($jsonContent, true);
|
|
173
|
-
return is_array($includeFiles) ? $includeFiles : [];
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private static function getLocalStorageKey(): string
|
|
177
|
-
{
|
|
178
|
-
$localStorageKey = $_ENV['LOCALSTORE_KEY'] ?? 'pphp_local_store_59e13';
|
|
179
|
-
return strtolower(preg_replace('/\s+/', '_', trim($localStorageKey)));
|
|
180
|
-
}
|
|
181
|
-
}
|
package/dist/src/Lib/Request.php
DELETED
|
@@ -1,479 +0,0 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Lib;
|
|
6
|
-
|
|
7
|
-
use Lib\Headers\Boom;
|
|
8
|
-
use ArrayObject;
|
|
9
|
-
use stdClass;
|
|
10
|
-
use Lib\PrismaPHPSettings;
|
|
11
|
-
|
|
12
|
-
class Request
|
|
13
|
-
{
|
|
14
|
-
/**
|
|
15
|
-
* The base URL for the application.
|
|
16
|
-
*
|
|
17
|
-
* @var string
|
|
18
|
-
*/
|
|
19
|
-
public const baseUrl = '/src/app';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @var stdClass $params A static property to hold request parameters.
|
|
23
|
-
*
|
|
24
|
-
* This property is used to hold request parameters that are passed to the request.
|
|
25
|
-
*
|
|
26
|
-
* Example usage:
|
|
27
|
-
* The parameters can be accessed using the following syntax:
|
|
28
|
-
* ```php
|
|
29
|
-
* $id = Request::$params['id'];
|
|
30
|
-
* OR
|
|
31
|
-
* $id = Request::$params->id;
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
public static ArrayObject $params;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @var stdClass $dynamicParams A static property to hold dynamic parameters.
|
|
38
|
-
*
|
|
39
|
-
* This property is used to hold dynamic parameters that are passed to the request.
|
|
40
|
-
*
|
|
41
|
-
* Example usage:
|
|
42
|
-
* Single parameter:
|
|
43
|
-
* ```php
|
|
44
|
-
* $id = Request::$dynamicParams['id'];
|
|
45
|
-
* OR
|
|
46
|
-
* $id = Request::$dynamicParams->id;
|
|
47
|
-
* ```
|
|
48
|
-
*
|
|
49
|
-
* Multiple parameters:
|
|
50
|
-
* ```php
|
|
51
|
-
* $dynamicParams = Request::$dynamicParams;
|
|
52
|
-
* echo '<pre>';
|
|
53
|
-
* print_r($dynamicParams);
|
|
54
|
-
* echo '</pre>';
|
|
55
|
-
* ```
|
|
56
|
-
*
|
|
57
|
-
* The above code will output the dynamic parameters as an array, which can be useful for debugging purposes.
|
|
58
|
-
*/
|
|
59
|
-
public static ArrayObject $dynamicParams;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @var stdClass $localStorage A static property to hold request parameters.
|
|
63
|
-
*
|
|
64
|
-
* This property is used to hold request parameters that are passed to the request.
|
|
65
|
-
*
|
|
66
|
-
* Example usage:
|
|
67
|
-
* The parameters can be accessed using the following syntax:
|
|
68
|
-
* ```php
|
|
69
|
-
* $id = Request::$localStorage['id'];
|
|
70
|
-
* OR
|
|
71
|
-
* $id = Request::$localStorage->id;
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
public static ArrayObject $localStorage;
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @var mixed $data Holds request data (e.g., JSON body).
|
|
78
|
-
*/
|
|
79
|
-
public static mixed $data = null;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @var string $pathname Holds the request pathname.
|
|
83
|
-
*/
|
|
84
|
-
public static string $pathname = '';
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @var string $uri Holds the request URI.
|
|
88
|
-
*/
|
|
89
|
-
public static string $uri = '';
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @var string $decodedUri Holds the decoded request URI.
|
|
93
|
-
*/
|
|
94
|
-
public static string $decodedUri = '';
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @var string $referer Holds the referer of the request.
|
|
98
|
-
*/
|
|
99
|
-
public static string $referer = '';
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* @var string $method Holds the request method.
|
|
103
|
-
*/
|
|
104
|
-
public static string $method = '';
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* @var string $contentType Holds the content type of the request.
|
|
108
|
-
*/
|
|
109
|
-
public static string $contentType = '';
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* @var string $protocol The protocol used for the request.
|
|
113
|
-
*/
|
|
114
|
-
public static string $protocol = '';
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* @var string $domainName The domain name of the request.
|
|
118
|
-
*/
|
|
119
|
-
public static string $domainName = '';
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* @var string $scriptName The script name of the request.
|
|
123
|
-
*/
|
|
124
|
-
public static string $scriptName = '';
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @var string $documentUrl The full document URL of the request.
|
|
128
|
-
*/
|
|
129
|
-
public static string $documentUrl = '';
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* @var string $fileToInclude The file to include in the request.
|
|
133
|
-
*/
|
|
134
|
-
public static string $fileToInclude = '';
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* @var bool $isGet Indicates if the request method is GET.
|
|
138
|
-
*/
|
|
139
|
-
public static bool $isGet = false;
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @var bool $isPost Indicates if the request method is POST.
|
|
143
|
-
*/
|
|
144
|
-
public static bool $isPost = false;
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* @var bool $isPut Indicates if the request method is PUT.
|
|
148
|
-
*/
|
|
149
|
-
public static bool $isPut = false;
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @var bool $isDelete Indicates if the request method is DELETE.
|
|
153
|
-
*/
|
|
154
|
-
public static bool $isDelete = false;
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* @var bool $isPatch Indicates if the request method is PATCH.
|
|
158
|
-
*/
|
|
159
|
-
public static bool $isPatch = false;
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* @var bool $isHead Indicates if the request method is HEAD.
|
|
163
|
-
*/
|
|
164
|
-
public static bool $isHead = false;
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* @var bool $isOptions Indicates if the request method is OPTIONS.
|
|
168
|
-
*/
|
|
169
|
-
public static bool $isOptions = false;
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* @var bool $isAjax Indicates if the request is an AJAX request.
|
|
173
|
-
*/
|
|
174
|
-
public static bool $isAjax = false;
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Indicates whether the request is a wire request.
|
|
178
|
-
*
|
|
179
|
-
* @var bool
|
|
180
|
-
*/
|
|
181
|
-
public static bool $isWire = false;
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Indicates whether the request is an X-File request.
|
|
185
|
-
*
|
|
186
|
-
* @var bool
|
|
187
|
-
*/
|
|
188
|
-
public static bool $isXFileRequest = false;
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* @var string $requestedWith Holds the value of the X-Requested-With header.
|
|
192
|
-
*/
|
|
193
|
-
public static string $requestedWith = '';
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* @var string $remoteAddr Holds the remote address of the request.
|
|
197
|
-
*/
|
|
198
|
-
public static string $remoteAddr = '';
|
|
199
|
-
|
|
200
|
-
public static function init(): void
|
|
201
|
-
{
|
|
202
|
-
self::$params = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
|
|
203
|
-
self::$dynamicParams = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
|
|
204
|
-
|
|
205
|
-
self::$referer = $_SERVER['HTTP_REFERER'] ?? 'Unknown';
|
|
206
|
-
self::$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
|
207
|
-
self::$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
|
|
208
|
-
self::$domainName = $_SERVER['HTTP_HOST'] ?? '';
|
|
209
|
-
self::$scriptName = dirname($_SERVER['SCRIPT_NAME']);
|
|
210
|
-
self::$requestedWith = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '';
|
|
211
|
-
|
|
212
|
-
self::$isGet = self::$method === 'GET';
|
|
213
|
-
self::$isPost = self::$method === 'POST';
|
|
214
|
-
self::$isPut = self::$method === 'PUT';
|
|
215
|
-
self::$isDelete = self::$method === 'DELETE';
|
|
216
|
-
self::$isPatch = self::$method === 'PATCH';
|
|
217
|
-
self::$isHead = self::$method === 'HEAD';
|
|
218
|
-
self::$isOptions = self::$method === 'OPTIONS';
|
|
219
|
-
|
|
220
|
-
self::$isWire = self::isWireRequest();
|
|
221
|
-
self::$isAjax = self::isAjaxRequest();
|
|
222
|
-
self::$isXFileRequest = self::isXFileRequest();
|
|
223
|
-
self::$params = self::getParams();
|
|
224
|
-
self::$localStorage = self::getLocalStorage();
|
|
225
|
-
self::$protocol = self::getProtocol();
|
|
226
|
-
self::$documentUrl = self::$protocol . self::$domainName . self::$scriptName;
|
|
227
|
-
self::$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? 'Unknown';
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Determines if the current request is an AJAX request.
|
|
232
|
-
*
|
|
233
|
-
* @return bool True if the request is an AJAX request, false otherwise.
|
|
234
|
-
*/
|
|
235
|
-
private static function isAjaxRequest(): bool
|
|
236
|
-
{
|
|
237
|
-
// Check for standard AJAX header
|
|
238
|
-
if (
|
|
239
|
-
!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
|
|
240
|
-
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'
|
|
241
|
-
) {
|
|
242
|
-
return true;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Check for common AJAX content types
|
|
246
|
-
if (!empty($_SERVER['CONTENT_TYPE'])) {
|
|
247
|
-
$ajaxContentTypes = [
|
|
248
|
-
'application/json',
|
|
249
|
-
'application/x-www-form-urlencoded',
|
|
250
|
-
'multipart/form-data',
|
|
251
|
-
];
|
|
252
|
-
|
|
253
|
-
foreach ($ajaxContentTypes as $contentType) {
|
|
254
|
-
if (stripos($_SERVER['CONTENT_TYPE'], $contentType) !== false) {
|
|
255
|
-
return true;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Check for common AJAX request methods
|
|
261
|
-
$ajaxMethods = ['POST', 'PUT', 'PATCH', 'DELETE'];
|
|
262
|
-
if (
|
|
263
|
-
!empty($_SERVER['REQUEST_METHOD']) &&
|
|
264
|
-
in_array(strtoupper($_SERVER['REQUEST_METHOD']), $ajaxMethods, true)
|
|
265
|
-
) {
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Checks if the request is a wire request.
|
|
274
|
-
*/
|
|
275
|
-
private static function isWireRequest(): bool
|
|
276
|
-
{
|
|
277
|
-
$headers = array_change_key_case(getallheaders(), CASE_LOWER);
|
|
278
|
-
return isset($headers['http_pphp_wire_request']) && strtolower($headers['http_pphp_wire_request']) === 'true';
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Checks if the request is an X-File request.
|
|
283
|
-
*
|
|
284
|
-
* @return bool True if the request is an X-File request, false otherwise.
|
|
285
|
-
*/
|
|
286
|
-
private static function isXFileRequest(): bool
|
|
287
|
-
{
|
|
288
|
-
$serverFetchSite = $_SERVER['HTTP_SEC_FETCH_SITE'] ?? '';
|
|
289
|
-
if (isset($serverFetchSite) && $serverFetchSite === 'same-origin') {
|
|
290
|
-
$headers = array_change_key_case(getallheaders(), CASE_LOWER);
|
|
291
|
-
return isset($headers['http_pphp_x_file_request']) && $headers['http_pphp_x_file_request'] === 'true';
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return false;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Get the request parameters.
|
|
299
|
-
*
|
|
300
|
-
* @return ArrayObject The request parameters as an ArrayObject with properties.
|
|
301
|
-
*/
|
|
302
|
-
private static function getParams(): ArrayObject
|
|
303
|
-
{
|
|
304
|
-
$params = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
|
|
305
|
-
|
|
306
|
-
switch (self::$method) {
|
|
307
|
-
case 'GET':
|
|
308
|
-
$params = new ArrayObject($_GET, ArrayObject::ARRAY_AS_PROPS);
|
|
309
|
-
break;
|
|
310
|
-
default:
|
|
311
|
-
// Handle JSON input with different variations (e.g., application/json, application/ld+json, etc.)
|
|
312
|
-
if (preg_match('#^application/(|\S+\+)json($|[ ;])#', self::$contentType)) {
|
|
313
|
-
$jsonInput = file_get_contents('php://input');
|
|
314
|
-
if ($jsonInput !== false && !empty($jsonInput)) {
|
|
315
|
-
self::$data = json_decode($jsonInput, true);
|
|
316
|
-
if (json_last_error() === JSON_ERROR_NONE) {
|
|
317
|
-
$params = new ArrayObject(self::$data, ArrayObject::ARRAY_AS_PROPS);
|
|
318
|
-
} else {
|
|
319
|
-
Boom::badRequest('Invalid JSON body')->toResponse();
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Handle URL-encoded input
|
|
325
|
-
if (stripos(self::$contentType, 'application/x-www-form-urlencoded') !== false) {
|
|
326
|
-
$rawInput = file_get_contents('php://input');
|
|
327
|
-
if ($rawInput !== false && !empty($rawInput)) {
|
|
328
|
-
parse_str($rawInput, $parsedParams);
|
|
329
|
-
$params = new ArrayObject($parsedParams, ArrayObject::ARRAY_AS_PROPS);
|
|
330
|
-
} else {
|
|
331
|
-
$params = new ArrayObject($_POST, ArrayObject::ARRAY_AS_PROPS);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
break;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
return $params;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Retrieves the local storage data from the session or initializes it if not present.
|
|
342
|
-
*
|
|
343
|
-
* This method checks if the local storage data is available in the static data array or the session.
|
|
344
|
-
* If the data is found, it is decoded from JSON if necessary and returned as an ArrayObject.
|
|
345
|
-
* If the data is not found, an empty ArrayObject is returned.
|
|
346
|
-
*
|
|
347
|
-
* @return ArrayObject The local storage data as an ArrayObject.
|
|
348
|
-
*/
|
|
349
|
-
private static function getLocalStorage(): ArrayObject
|
|
350
|
-
{
|
|
351
|
-
$sessionKey = PrismaPHPSettings::$localStoreKey;
|
|
352
|
-
$localStorage = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
|
|
353
|
-
|
|
354
|
-
if (isset(self::$data[$sessionKey])) {
|
|
355
|
-
$data = self::$data[$sessionKey];
|
|
356
|
-
|
|
357
|
-
if (is_array($data)) {
|
|
358
|
-
$_SESSION[$sessionKey] = $data;
|
|
359
|
-
$localStorage = new ArrayObject($data, ArrayObject::ARRAY_AS_PROPS);
|
|
360
|
-
} else {
|
|
361
|
-
$decodedData = json_decode($data, true);
|
|
362
|
-
|
|
363
|
-
if (json_last_error() === JSON_ERROR_NONE) {
|
|
364
|
-
$_SESSION[$sessionKey] = $data;
|
|
365
|
-
$localStorage = new ArrayObject($decodedData, ArrayObject::ARRAY_AS_PROPS);
|
|
366
|
-
} else {
|
|
367
|
-
Boom::badRequest('Invalid JSON body')->toResponse();
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
} else {
|
|
371
|
-
if (isset($_SESSION[$sessionKey])) {
|
|
372
|
-
$sessionData = $_SESSION[$sessionKey];
|
|
373
|
-
|
|
374
|
-
if (is_array($sessionData)) {
|
|
375
|
-
$localStorage = new ArrayObject($sessionData, ArrayObject::ARRAY_AS_PROPS);
|
|
376
|
-
} else {
|
|
377
|
-
$decodedData = json_decode($sessionData, true);
|
|
378
|
-
|
|
379
|
-
if (json_last_error() === JSON_ERROR_NONE) {
|
|
380
|
-
$localStorage = new ArrayObject($decodedData, ArrayObject::ARRAY_AS_PROPS);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
return $localStorage;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Get the protocol of the request.
|
|
391
|
-
*/
|
|
392
|
-
private static function getProtocol(): string
|
|
393
|
-
{
|
|
394
|
-
return (
|
|
395
|
-
(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
|
|
396
|
-
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') ||
|
|
397
|
-
($_SERVER['SERVER_PORT'] == 443)
|
|
398
|
-
) ? "https://" : "http://";
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Get the Bearer token from the Authorization header.
|
|
403
|
-
*/
|
|
404
|
-
public static function getBearerToken(): ?string
|
|
405
|
-
{
|
|
406
|
-
$headers = array_change_key_case(getallheaders(), CASE_LOWER);
|
|
407
|
-
$authHeader = $headers['authorization'] ?? $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? null;
|
|
408
|
-
|
|
409
|
-
if ($authHeader && preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
|
|
410
|
-
return $matches[1];
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return null;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Handle preflight OPTIONS request.
|
|
418
|
-
*/
|
|
419
|
-
public static function handlePreflight(): void
|
|
420
|
-
{
|
|
421
|
-
if (self::$method === 'OPTIONS') {
|
|
422
|
-
header('HTTP/1.1 200 OK');
|
|
423
|
-
exit;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* Check if the request method is allowed.
|
|
429
|
-
*/
|
|
430
|
-
public static function checkAllowedMethods(): void
|
|
431
|
-
{
|
|
432
|
-
if (!in_array(self::$method, ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'])) {
|
|
433
|
-
Boom::methodNotAllowed()->toResponse();
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Redirects the client to a specified URL.
|
|
439
|
-
*
|
|
440
|
-
* This method handles both normal and AJAX/wire requests. For normal requests,
|
|
441
|
-
* it sends a standard HTTP redirection header. For AJAX/wire requests, it outputs
|
|
442
|
-
* a custom redirect message.
|
|
443
|
-
*
|
|
444
|
-
* @param string $url The URL to redirect to.
|
|
445
|
-
* @param bool $replace Whether to replace the current header. Default is true.
|
|
446
|
-
* @param int $responseCode The HTTP response code to use for the redirection. Default is 0.
|
|
447
|
-
*
|
|
448
|
-
* @return void
|
|
449
|
-
*/
|
|
450
|
-
public static function redirect(string $url, bool $replace = true, int $responseCode = 0): void
|
|
451
|
-
{
|
|
452
|
-
if (ob_get_length()) {
|
|
453
|
-
ob_clean();
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
ob_start();
|
|
457
|
-
|
|
458
|
-
if (!self::$isWire && !self::$isAjax) {
|
|
459
|
-
header("Location: $url", $replace, $responseCode);
|
|
460
|
-
} else {
|
|
461
|
-
echo "redirect_7F834=$url";
|
|
462
|
-
ob_end_flush();
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
exit;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
public static function getDecodedUrl(string $uri): string
|
|
469
|
-
{
|
|
470
|
-
$parsedUrl = parse_url($uri);
|
|
471
|
-
|
|
472
|
-
$queryString = isset($parsedUrl['query']) ? '?' . urldecode($parsedUrl['query']) : '';
|
|
473
|
-
$path = $parsedUrl['path'] ?? '';
|
|
474
|
-
|
|
475
|
-
$decodedUrl = urldecode($path . $queryString);
|
|
476
|
-
|
|
477
|
-
return $decodedUrl;
|
|
478
|
-
}
|
|
479
|
-
}
|