create-prisma-php-app 3.0.4 → 3.1.1
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 +35 -13
- package/dist/src/Lib/ErrorHandler.php +194 -0
- package/dist/src/Lib/IncludeTracker.php +2 -41
- package/dist/src/Lib/PHPX/Exceptions/ComponentValidationException.php +49 -0
- package/dist/src/Lib/PHPX/PHPX.php +6 -11
- package/dist/src/Lib/PHPX/TemplateCompiler.php +61 -99
- package/dist/src/Lib/PrismaPHPSettings.php +0 -19
- package/dist/src/app/error.php +1 -1
- package/dist/src/app/js/index.js +1 -1
- package/package.json +1 -1
- package/dist/settings/html-events.json +0 -118
package/dist/bootstrap.php
CHANGED
|
@@ -22,7 +22,7 @@ use Lib\ErrorHandler;
|
|
|
22
22
|
use Firebase\JWT\JWT;
|
|
23
23
|
use Firebase\JWT\Key;
|
|
24
24
|
|
|
25
|
-
final class Bootstrap
|
|
25
|
+
final class Bootstrap extends RuntimeException
|
|
26
26
|
{
|
|
27
27
|
public static string $contentToInclude = '';
|
|
28
28
|
public static array $layoutsToInclude = [];
|
|
@@ -35,12 +35,22 @@ final class Bootstrap
|
|
|
35
35
|
public static bool $secondRequestC69CD = false;
|
|
36
36
|
public static array $requestFilesData = [];
|
|
37
37
|
|
|
38
|
+
private string $context;
|
|
39
|
+
|
|
38
40
|
private static array $fileExistCache = [];
|
|
39
41
|
private static array $regexCache = [];
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
public function __construct(string $message, string $context = '', int $code = 0, ?Throwable $previous = null)
|
|
44
|
+
{
|
|
45
|
+
$this->context = $context;
|
|
46
|
+
parent::__construct($message, $code, $previous);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public function getContext(): string
|
|
50
|
+
{
|
|
51
|
+
return $this->context;
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
public static function run(): void
|
|
45
55
|
{
|
|
46
56
|
// Load environment variables
|
|
@@ -807,6 +817,10 @@ final class Bootstrap
|
|
|
807
817
|
|
|
808
818
|
public static function createUpdateRequestData(): void
|
|
809
819
|
{
|
|
820
|
+
if (Bootstrap::$contentToInclude === '') {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
|
|
810
824
|
$requestJsonData = SETTINGS_PATH . '/request-data.json';
|
|
811
825
|
|
|
812
826
|
if (file_exists($requestJsonData)) {
|
|
@@ -951,6 +965,9 @@ try {
|
|
|
951
965
|
ob_start();
|
|
952
966
|
require_once APP_PATH . '/not-found.php';
|
|
953
967
|
MainLayout::$childLayoutChildren = ob_get_clean();
|
|
968
|
+
|
|
969
|
+
http_response_code(404);
|
|
970
|
+
CacheHandler::$isCacheable = false;
|
|
954
971
|
}
|
|
955
972
|
|
|
956
973
|
// If the top-level layout is in use
|
|
@@ -1001,7 +1018,9 @@ try {
|
|
|
1001
1018
|
MainLayout::$html = TemplateCompiler::injectDynamicContent(MainLayout::$html);
|
|
1002
1019
|
MainLayout::$html = "<!DOCTYPE html>\n" . MainLayout::$html;
|
|
1003
1020
|
|
|
1004
|
-
if (
|
|
1021
|
+
if (
|
|
1022
|
+
http_response_code() === 200 && isset(Bootstrap::$requestFilesData[Request::$decodedUri]['fileName']) && $_ENV['CACHE_ENABLED'] === 'true'
|
|
1023
|
+
) {
|
|
1005
1024
|
CacheHandler::saveCache(Request::$decodedUri, MainLayout::$html);
|
|
1006
1025
|
}
|
|
1007
1026
|
|
|
@@ -1025,15 +1044,18 @@ try {
|
|
|
1025
1044
|
}
|
|
1026
1045
|
} catch (Throwable $e) {
|
|
1027
1046
|
if (Bootstrap::isAjaxOrXFileRequestOrRouteFile()) {
|
|
1028
|
-
$errorDetails =
|
|
1029
|
-
|
|
1030
|
-
|
|
1047
|
+
$errorDetails = json_encode([
|
|
1048
|
+
'success' => false,
|
|
1049
|
+
'error' => [
|
|
1050
|
+
'type' => get_class($e),
|
|
1051
|
+
'message' => $e->getMessage(),
|
|
1052
|
+
'file' => $e->getFile(),
|
|
1053
|
+
'line' => $e->getLine(),
|
|
1054
|
+
'trace' => $e->getTraceAsString()
|
|
1055
|
+
]
|
|
1056
|
+
]);
|
|
1031
1057
|
} else {
|
|
1032
|
-
$errorDetails =
|
|
1033
|
-
$errorDetails .= "<br>File: " . htmlspecialchars($e->getFile(), ENT_QUOTES, 'UTF-8');
|
|
1034
|
-
$errorDetails .= "<br>Line: " . htmlspecialchars((string)$e->getLine(), ENT_QUOTES, 'UTF-8');
|
|
1035
|
-
$errorDetails .= "<br/>TraceAsString: " . htmlspecialchars($e->getTraceAsString(), ENT_QUOTES, 'UTF-8');
|
|
1036
|
-
$errorDetails = "<div class='error'>{$errorDetails}</div>";
|
|
1058
|
+
$errorDetails = ErrorHandler::formatExceptionForDisplay($e);
|
|
1037
1059
|
}
|
|
1038
1060
|
ErrorHandler::modifyOutputLayoutForError($errorDetails);
|
|
1039
1061
|
}
|
|
@@ -4,6 +4,8 @@ namespace Lib;
|
|
|
4
4
|
|
|
5
5
|
use Bootstrap;
|
|
6
6
|
use Lib\MainLayout;
|
|
7
|
+
use Throwable;
|
|
8
|
+
use Lib\PHPX\Exceptions\ComponentValidationException;
|
|
7
9
|
|
|
8
10
|
class ErrorHandler
|
|
9
11
|
{
|
|
@@ -123,4 +125,196 @@ class ErrorHandler
|
|
|
123
125
|
}
|
|
124
126
|
exit;
|
|
125
127
|
}
|
|
128
|
+
|
|
129
|
+
public static function formatExceptionForDisplay(Throwable $exception): string
|
|
130
|
+
{
|
|
131
|
+
// Handle specific exception types
|
|
132
|
+
if ($exception instanceof ComponentValidationException) {
|
|
133
|
+
return self::formatComponentValidationError($exception);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Handle template compilation errors specifically
|
|
137
|
+
if (strpos($exception->getMessage(), 'Invalid prop') !== false) {
|
|
138
|
+
return self::formatTemplateCompilerError($exception);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Generic exception formatting
|
|
142
|
+
return self::formatGenericException($exception);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private static function formatComponentValidationError(ComponentValidationException $exception): string
|
|
146
|
+
{
|
|
147
|
+
$message = htmlspecialchars($exception->getMessage(), ENT_QUOTES, 'UTF-8');
|
|
148
|
+
$file = htmlspecialchars($exception->getFile(), ENT_QUOTES, 'UTF-8');
|
|
149
|
+
$line = $exception->getLine();
|
|
150
|
+
|
|
151
|
+
// Get the details from the ComponentValidationException
|
|
152
|
+
$propName = method_exists($exception, 'getPropName') ? $exception->getPropName() : 'unknown';
|
|
153
|
+
$componentName = method_exists($exception, 'getComponentName') ? $exception->getComponentName() : 'unknown';
|
|
154
|
+
$availableProps = method_exists($exception, 'getAvailableProps') ? $exception->getAvailableProps() : [];
|
|
155
|
+
|
|
156
|
+
$availablePropsString = !empty($availableProps) ? implode(', ', $availableProps) : 'none defined';
|
|
157
|
+
|
|
158
|
+
return <<<HTML
|
|
159
|
+
<div class="error-container max-w-4xl mx-auto mt-8 bg-red-50 border border-red-200 rounded-lg shadow-lg">
|
|
160
|
+
<div class="bg-red-100 px-6 py-4 border-b border-red-200">
|
|
161
|
+
<h2 class="text-xl font-bold text-red-800 flex items-center">
|
|
162
|
+
<svg class="w-6 h-6 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
|
163
|
+
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
|
|
164
|
+
</svg>
|
|
165
|
+
Component Validation Error
|
|
166
|
+
</h2>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<div class="p-6">
|
|
170
|
+
<div class="bg-white border border-red-200 rounded-lg p-4 mb-4">
|
|
171
|
+
<div class="mb-3">
|
|
172
|
+
<span class="inline-block bg-red-100 text-red-800 px-3 py-1 rounded-full text-sm font-medium">
|
|
173
|
+
Component: {$componentName}
|
|
174
|
+
</span>
|
|
175
|
+
<span class="inline-block bg-red-100 text-red-800 px-3 py-1 rounded-full text-sm font-medium ml-2">
|
|
176
|
+
Invalid Prop: {$propName}
|
|
177
|
+
</span>
|
|
178
|
+
</div>
|
|
179
|
+
<pre class="text-sm text-red-800 whitespace-pre-wrap font-mono">{$message}</pre>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<div class="text-sm text-gray-600 mb-4">
|
|
183
|
+
<strong>File:</strong> <code class="bg-gray-100 px-2 py-1 rounded text-xs">{$file}</code><br />
|
|
184
|
+
<strong>Line:</strong> <span class="bg-gray-100 px-2 py-1 rounded text-xs">{$line}</span>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
|
|
188
|
+
<h4 class="font-medium text-blue-800 mb-2">💡 Available Props:</h4>
|
|
189
|
+
<p class="text-blue-700 text-sm">
|
|
190
|
+
<code class="bg-blue-100 px-2 py-1 rounded text-xs">{$availablePropsString}</code>
|
|
191
|
+
</p>
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<div class="bg-green-50 border border-green-200 rounded-lg p-4 mb-4">
|
|
195
|
+
<h4 class="font-medium text-green-800 mb-2">🔧 Quick Fixes:</h4>
|
|
196
|
+
<ul class="text-green-700 text-sm space-y-1">
|
|
197
|
+
<li>• Remove the '<code>{$propName}</code>' prop from your template</li>
|
|
198
|
+
<li>• Add '<code>public \${$propName};</code>' to your <code>{$componentName}</code> component class</li>
|
|
199
|
+
<li>• Use data attributes: '<code>data-{$propName}</code>' instead</li>
|
|
200
|
+
</ul>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<details class="mt-4">
|
|
204
|
+
<summary class="cursor-pointer text-red-600 font-medium hover:text-red-800 select-none">
|
|
205
|
+
Show Stack Trace
|
|
206
|
+
</summary>
|
|
207
|
+
<div class="mt-3 bg-gray-50 border border-gray-200 rounded p-4">
|
|
208
|
+
<pre class="text-xs text-gray-700 overflow-auto whitespace-pre-wrap max-h-96">{$exception->getTraceAsString()}</pre>
|
|
209
|
+
</div>
|
|
210
|
+
</details>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
HTML;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private static function formatTemplateCompilerError(Throwable $exception): string
|
|
217
|
+
{
|
|
218
|
+
$message = htmlspecialchars($exception->getMessage(), ENT_QUOTES, 'UTF-8');
|
|
219
|
+
$file = htmlspecialchars($exception->getFile(), ENT_QUOTES, 'UTF-8');
|
|
220
|
+
$line = $exception->getLine();
|
|
221
|
+
|
|
222
|
+
// Extract the component validation error details
|
|
223
|
+
if (preg_match("/Invalid prop '([^']+)' passed to component '([^']+)'/", $exception->getMessage(), $matches)) {
|
|
224
|
+
$invalidProp = $matches[1];
|
|
225
|
+
$componentName = $matches[2];
|
|
226
|
+
|
|
227
|
+
return <<<HTML
|
|
228
|
+
<div class="error-container max-w-4xl mx-auto mt-8 bg-red-50 border border-red-200 rounded-lg shadow-lg">
|
|
229
|
+
<div class="bg-red-100 px-6 py-4 border-b border-red-200">
|
|
230
|
+
<h2 class="text-xl font-bold text-red-800 flex items-center">
|
|
231
|
+
<svg class="w-6 h-6 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
|
232
|
+
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
|
|
233
|
+
</svg>
|
|
234
|
+
Template Compilation Error
|
|
235
|
+
</h2>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<div class="p-6">
|
|
239
|
+
<div class="bg-white border border-red-200 rounded-lg p-4 mb-4">
|
|
240
|
+
<div class="mb-3">
|
|
241
|
+
<span class="inline-block bg-red-100 text-red-800 px-3 py-1 rounded-full text-sm font-medium">
|
|
242
|
+
Component: {$componentName}
|
|
243
|
+
</span>
|
|
244
|
+
<span class="inline-block bg-red-100 text-red-800 px-3 py-1 rounded-full text-sm font-medium ml-2">
|
|
245
|
+
Invalid Prop: {$invalidProp}
|
|
246
|
+
</span>
|
|
247
|
+
</div>
|
|
248
|
+
<p class="text-red-800 font-medium">{$message}</p>
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
<div class="text-sm text-gray-600 mb-4">
|
|
252
|
+
<strong>File:</strong> {$file}<br />
|
|
253
|
+
<strong>Line:</strong> {$line}
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
|
|
257
|
+
<h4 class="font-medium text-blue-800 mb-2">💡 Quick Fix:</h4>
|
|
258
|
+
<p class="text-blue-700 text-sm">
|
|
259
|
+
Either remove the '<code>{$invalidProp}</code>' prop from your template, or add it as a public property to your <code>{$componentName}</code> component class.
|
|
260
|
+
</p>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
<details class="mt-4">
|
|
264
|
+
<summary class="cursor-pointer text-red-600 font-medium hover:text-red-800 select-none">
|
|
265
|
+
Show Stack Trace
|
|
266
|
+
</summary>
|
|
267
|
+
<div class="mt-3 bg-gray-50 border border-gray-200 rounded p-4">
|
|
268
|
+
<pre class="text-xs text-gray-700 overflow-auto whitespace-pre-wrap">{$exception->getTraceAsString()}</pre>
|
|
269
|
+
</div>
|
|
270
|
+
</details>
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
HTML;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Fallback to generic formatting
|
|
277
|
+
return self::formatGenericException($exception);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
private static function formatGenericException(Throwable $exception): string
|
|
281
|
+
{
|
|
282
|
+
$type = htmlspecialchars(get_class($exception), ENT_QUOTES, 'UTF-8');
|
|
283
|
+
$message = htmlspecialchars($exception->getMessage(), ENT_QUOTES, 'UTF-8');
|
|
284
|
+
$file = htmlspecialchars($exception->getFile(), ENT_QUOTES, 'UTF-8');
|
|
285
|
+
$line = $exception->getLine();
|
|
286
|
+
|
|
287
|
+
return <<<HTML
|
|
288
|
+
<div class="error-container max-w-4xl mx-auto mt-8 bg-red-50 border border-red-200 rounded-lg shadow-lg">
|
|
289
|
+
<div class="bg-red-100 px-6 py-4 border-b border-red-200">
|
|
290
|
+
<h2 class="text-xl font-bold text-red-800 flex items-center">
|
|
291
|
+
<svg class="w-6 h-6 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
|
292
|
+
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
|
|
293
|
+
</svg>
|
|
294
|
+
{$type}
|
|
295
|
+
</h2>
|
|
296
|
+
</div>
|
|
297
|
+
|
|
298
|
+
<div class="p-6">
|
|
299
|
+
<div class="bg-white border border-red-200 rounded-lg p-4 mb-4">
|
|
300
|
+
<p class="text-red-800 font-medium break-words">{$message}</p>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div class="text-sm text-gray-600 mb-4">
|
|
304
|
+
<strong>File:</strong> <code class="bg-gray-100 px-2 py-1 rounded text-xs">{$file}</code><br />
|
|
305
|
+
<strong>Line:</strong> <span class="bg-gray-100 px-2 py-1 rounded text-xs">{$line}</span>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
<details class="mt-4">
|
|
309
|
+
<summary class="cursor-pointer text-red-600 font-medium hover:text-red-800 select-none">
|
|
310
|
+
Show Stack Trace
|
|
311
|
+
</summary>
|
|
312
|
+
<div class="mt-3 bg-gray-50 border border-gray-200 rounded p-4">
|
|
313
|
+
<pre class="text-xs text-gray-700 overflow-auto whitespace-pre-wrap max-h-96">{$exception->getTraceAsString()}</pre>
|
|
314
|
+
</div>
|
|
315
|
+
</details>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
HTML;
|
|
319
|
+
}
|
|
126
320
|
}
|
|
@@ -4,10 +4,6 @@ namespace Lib;
|
|
|
4
4
|
|
|
5
5
|
use RuntimeException;
|
|
6
6
|
use InvalidArgumentException;
|
|
7
|
-
use Lib\PrismaPHPSettings;
|
|
8
|
-
use DOMDocument;
|
|
9
|
-
use DOMElement;
|
|
10
|
-
use DOMXPath;
|
|
11
7
|
use Lib\PHPX\TemplateCompiler;
|
|
12
8
|
|
|
13
9
|
class IncludeTracker
|
|
@@ -15,7 +11,7 @@ class IncludeTracker
|
|
|
15
11
|
public static array $sections = [];
|
|
16
12
|
|
|
17
13
|
/**
|
|
18
|
-
* Includes and echoes a file wrapped in a unique pp-
|
|
14
|
+
* Includes and echoes a file wrapped in a unique pp-component container.
|
|
19
15
|
* Supported $mode values: 'include', 'include_once', 'require', 'require_once'
|
|
20
16
|
*
|
|
21
17
|
* @param string $filePath The path to the file to be included.
|
|
@@ -43,8 +39,6 @@ class IncludeTracker
|
|
|
43
39
|
$wrapped = self::wrapWithId($filePath, $html);
|
|
44
40
|
$fragDom = TemplateCompiler::convertToXml($wrapped);
|
|
45
41
|
|
|
46
|
-
self::prefixInlineHandlers($fragDom);
|
|
47
|
-
|
|
48
42
|
$newHtml = TemplateCompiler::innerXml($fragDom);
|
|
49
43
|
|
|
50
44
|
self::$sections[$filePath] = [
|
|
@@ -58,39 +52,6 @@ class IncludeTracker
|
|
|
58
52
|
private static function wrapWithId(string $filePath, string $html): string
|
|
59
53
|
{
|
|
60
54
|
$id = 's' . base_convert(sprintf('%u', crc32($filePath)), 10, 36);
|
|
61
|
-
return "<div pp-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private static function prefixInlineHandlers(DOMDocument $doc): void
|
|
65
|
-
{
|
|
66
|
-
$xp = new DOMXPath($doc);
|
|
67
|
-
|
|
68
|
-
/** @var DOMElement $el */
|
|
69
|
-
foreach ($xp->query('//*') as $el) {
|
|
70
|
-
$handlers = [];
|
|
71
|
-
|
|
72
|
-
foreach (iterator_to_array($el->attributes) as $attr) {
|
|
73
|
-
$name = $attr->name;
|
|
74
|
-
|
|
75
|
-
if (!str_starts_with($name, 'on')) {
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
$event = substr($name, 2);
|
|
80
|
-
if (
|
|
81
|
-
!in_array($event, PrismaPHPSettings::$htmlEvents, true) ||
|
|
82
|
-
trim($attr->value) === ''
|
|
83
|
-
) {
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
$handlers[$name] = $attr->value;
|
|
88
|
-
$el->removeAttribute($name);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
foreach ($handlers as $origName => $value) {
|
|
92
|
-
$el->setAttribute("pp-inc-{$origName}", $value);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
55
|
+
return "<div pp-component=\"$id\">\n$html\n</div>";
|
|
95
56
|
}
|
|
96
57
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Lib\PHPX\Exceptions;
|
|
4
|
+
|
|
5
|
+
use RuntimeException;
|
|
6
|
+
|
|
7
|
+
class ComponentValidationException extends RuntimeException
|
|
8
|
+
{
|
|
9
|
+
private string $propName;
|
|
10
|
+
private string $componentName;
|
|
11
|
+
private array $availableProps;
|
|
12
|
+
|
|
13
|
+
public function __construct(
|
|
14
|
+
string $propName,
|
|
15
|
+
string $componentName,
|
|
16
|
+
array $availableProps,
|
|
17
|
+
string $context = ''
|
|
18
|
+
) {
|
|
19
|
+
$this->propName = $propName;
|
|
20
|
+
$this->componentName = $componentName;
|
|
21
|
+
$this->availableProps = $availableProps;
|
|
22
|
+
|
|
23
|
+
$availableList = implode(', ', $availableProps);
|
|
24
|
+
|
|
25
|
+
$message = "Invalid prop '{$propName}' for component '{$componentName}'.\n";
|
|
26
|
+
$message .= "Available props: {$availableList}";
|
|
27
|
+
|
|
28
|
+
if ($context) {
|
|
29
|
+
$message .= "\n{$context}";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
parent::__construct($message);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public function getPropName(): string
|
|
36
|
+
{
|
|
37
|
+
return $this->propName;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public function getComponentName(): string
|
|
41
|
+
{
|
|
42
|
+
return $this->componentName;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public function getAvailableProps(): array
|
|
46
|
+
{
|
|
47
|
+
return $this->availableProps;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -19,11 +19,6 @@ class PHPX implements IPHPX
|
|
|
19
19
|
*/
|
|
20
20
|
public mixed $children;
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
* @var string The CSS class for custom styling.
|
|
24
|
-
*/
|
|
25
|
-
protected string $class;
|
|
26
|
-
|
|
27
22
|
/**
|
|
28
23
|
* @var array<string, mixed> The array representation of the HTML attributes.
|
|
29
24
|
*/
|
|
@@ -38,27 +33,27 @@ class PHPX implements IPHPX
|
|
|
38
33
|
{
|
|
39
34
|
$this->props = $props;
|
|
40
35
|
$this->children = $props['children'] ?? '';
|
|
41
|
-
$this->class = $props['class'] ?? '';
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
/**
|
|
45
39
|
* Combines and returns the CSS classes for the component.
|
|
46
40
|
*
|
|
47
41
|
* This method merges the provided classes, which can be either strings or arrays of strings,
|
|
48
|
-
*
|
|
49
|
-
* that the resulting CSS class string is optimized, with duplicate or conflicting
|
|
42
|
+
* without automatically including the component's `$class` property. It uses the `Utils::mergeClasses`
|
|
43
|
+
* method to ensure that the resulting CSS class string is optimized, with duplicate or conflicting
|
|
44
|
+
* classes removed.
|
|
50
45
|
*
|
|
51
46
|
* ### Features:
|
|
52
47
|
* - Accepts multiple arguments as strings or arrays of strings.
|
|
53
|
-
* -
|
|
48
|
+
* - Only merges the classes provided as arguments (does not include `$this->class` automatically).
|
|
54
49
|
* - Ensures the final CSS class string is well-formatted and free of conflicts.
|
|
55
50
|
*
|
|
56
51
|
* @param string|array ...$classes The CSS classes to be merged. Each argument can be a string or an array of strings.
|
|
57
|
-
* @return string A single CSS class string with the merged and optimized classes
|
|
52
|
+
* @return string A single CSS class string with the merged and optimized classes.
|
|
58
53
|
*/
|
|
59
54
|
protected function getMergeClasses(string|array ...$classes): string
|
|
60
55
|
{
|
|
61
|
-
$all = array_merge($classes
|
|
56
|
+
$all = array_merge($classes);
|
|
62
57
|
|
|
63
58
|
$expr = [];
|
|
64
59
|
foreach ($all as &$chunk) {
|