create-prisma-php-app 1.11.543 → 1.11.600
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/composer.json +2 -1
- package/dist/bootstrap.php +170 -63
- package/dist/index.js +50 -32
- package/dist/prisma/schema.prisma +2 -0
- package/dist/prisma-client-php/index.enc +1 -1
- package/dist/prisma-php.js +161 -100
- package/dist/settings/public-functions.php +7 -0
- package/dist/src/Lib/Auth/Auth.php +236 -2
- package/dist/src/Lib/FormHandler.php +308 -0
- package/dist/src/Lib/Middleware/AuthMiddleware.php +1 -1
- package/dist/src/Lib/PHPMailer/Mailer.php +5 -8
- package/dist/src/Lib/StateManager.php +1 -1
- package/dist/src/Lib/Validator.php +28 -0
- package/dist/src/app/index.php +2 -2
- package/dist/tsconfig.json +3 -1
- package/package.json +1 -1
- package/dist/.env +0 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Lib;
|
|
4
|
+
|
|
5
|
+
use Lib\StateManager;
|
|
6
|
+
use Lib\Validator;
|
|
7
|
+
|
|
8
|
+
class FormHandler
|
|
9
|
+
{
|
|
10
|
+
private $data;
|
|
11
|
+
private $errors;
|
|
12
|
+
private $validated;
|
|
13
|
+
private $isPost;
|
|
14
|
+
private $pathname;
|
|
15
|
+
private StateManager $stateManager;
|
|
16
|
+
private const FORM_STATE = 'pphp_form_state_977A9';
|
|
17
|
+
private const FORM_INPUT_REGISTER = 'pphp_form_input_register_7A16F';
|
|
18
|
+
private const FORM_INPUT_ERRORS = 'pphp_form_input_errors_CBF6C';
|
|
19
|
+
|
|
20
|
+
public function __construct($formData = [])
|
|
21
|
+
{
|
|
22
|
+
global $isPost, $pathname;
|
|
23
|
+
|
|
24
|
+
$this->isPost = $isPost;
|
|
25
|
+
$this->pathname = $pathname;
|
|
26
|
+
$this->data = $formData;
|
|
27
|
+
$this->errors = [];
|
|
28
|
+
$this->validated = false;
|
|
29
|
+
|
|
30
|
+
$this->stateManager = new StateManager();
|
|
31
|
+
|
|
32
|
+
if ($this->stateManager->getState(self::FORM_INPUT_REGISTER)) {
|
|
33
|
+
$this->getData();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Validates the form data.
|
|
39
|
+
*
|
|
40
|
+
* @return bool True if the form data is valid, false otherwise.
|
|
41
|
+
*/
|
|
42
|
+
public function validate(): bool
|
|
43
|
+
{
|
|
44
|
+
return empty($this->errors) && $this->validated;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public function addError($field, $message)
|
|
48
|
+
{
|
|
49
|
+
$this->errors[$field] = $message;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Retrieves the form data and performs validation if the form was submitted.
|
|
54
|
+
*
|
|
55
|
+
* @return mixed An object containing the form data.
|
|
56
|
+
*/
|
|
57
|
+
public function getData(): mixed
|
|
58
|
+
{
|
|
59
|
+
if ($this->isPost) {
|
|
60
|
+
if ($inputField = $this->stateManager->getState(self::FORM_INPUT_REGISTER)) {
|
|
61
|
+
foreach ($inputField as $field => $fieldData) {
|
|
62
|
+
$this->data[$field] = Validator::validateString($this->data[$field] ?? '');
|
|
63
|
+
$this->validateField($field, $fieldData['rules']);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
$formDataInfo = [
|
|
68
|
+
'data' => $this->data,
|
|
69
|
+
'errors' => $this->errors,
|
|
70
|
+
'validated' => true
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
$this->stateManager->resetState(self::FORM_INPUT_ERRORS, true);
|
|
74
|
+
$this->stateManager->setState([self::FORM_INPUT_ERRORS => $formDataInfo], true);
|
|
75
|
+
$this->stateManager->setState([self::FORM_STATE => $formDataInfo], true);
|
|
76
|
+
|
|
77
|
+
redirect($this->pathname);
|
|
78
|
+
} else {
|
|
79
|
+
if ($state = $this->stateManager->getState(self::FORM_STATE)) {
|
|
80
|
+
$this->data = $state['data'] ?? [];
|
|
81
|
+
$this->errors = $state['errors'] ?? [];
|
|
82
|
+
$this->validated = $state['validated'] ?? false;
|
|
83
|
+
|
|
84
|
+
$this->stateManager->resetState([self::FORM_STATE, self::FORM_INPUT_REGISTER], true);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return new \ArrayObject($this->data, \ArrayObject::ARRAY_AS_PROPS);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Retrieves the validation errors from the form state.
|
|
93
|
+
*
|
|
94
|
+
* @param string|null $field The name of the field to get errors for. If null, all errors are returned.
|
|
95
|
+
* @return mixed If a field name is provided, returns the error message for that field or an empty string if no error.
|
|
96
|
+
* If no field name is provided, returns an associative array of all errors or an empty array if no errors.
|
|
97
|
+
* If the form has not been validated yet, returns an empty string.
|
|
98
|
+
*/
|
|
99
|
+
public function getErrors(string $field = null): mixed
|
|
100
|
+
{
|
|
101
|
+
$state = $this->stateManager->getState(self::FORM_INPUT_ERRORS);
|
|
102
|
+
|
|
103
|
+
if ($this->validated && $state) {
|
|
104
|
+
if ($field) {
|
|
105
|
+
return $state['errors'][$field] ?? '';
|
|
106
|
+
}
|
|
107
|
+
return $state['errors'] ?? [];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return '';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Validates a form field based on the provided rules.
|
|
115
|
+
*
|
|
116
|
+
* @param string $field The name of the field to validate.
|
|
117
|
+
* @param array $rules An associative array of rules to apply. Each key is the rule name, and the value is the rule options.
|
|
118
|
+
* The options can be a scalar value or an array with 'value' and 'message' keys.
|
|
119
|
+
* The 'value' key is the value to compare with, and the 'message' key is the custom error message.
|
|
120
|
+
*
|
|
121
|
+
* Supported rules:
|
|
122
|
+
* - text, search, email, password, number, date, color, range, tel, url, time, datetime-local, month, week, file
|
|
123
|
+
* - required, min, max, minLength, maxLength, pattern, autocomplete, readonly, disabled, placeholder, autofocus, multiple, accept, size, step, list
|
|
124
|
+
*
|
|
125
|
+
* Custom error messages can be provided for each rule. If not provided, a default message is used.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* $form->validateField('email', [
|
|
129
|
+
* 'required' => ['value' => true, 'message' => 'Email is required.'],
|
|
130
|
+
* 'email' => ['value' => true, 'message' => 'Please enter a valid email address.']
|
|
131
|
+
* ]);
|
|
132
|
+
*
|
|
133
|
+
* @return void
|
|
134
|
+
*/
|
|
135
|
+
public function validateField($field, $rules)
|
|
136
|
+
{
|
|
137
|
+
$value = Validator::validateString($this->data[$field] ?? null);
|
|
138
|
+
foreach ($rules as $rule => $options) {
|
|
139
|
+
$ruleValue = $options;
|
|
140
|
+
$customMessage = null;
|
|
141
|
+
|
|
142
|
+
if (is_array($options)) {
|
|
143
|
+
$ruleValue = $options['value'];
|
|
144
|
+
$customMessage = $options['message'] ?? null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
switch ($rule) {
|
|
148
|
+
case 'text':
|
|
149
|
+
case 'search':
|
|
150
|
+
if (!is_string($value)) $this->addError($field, $customMessage ?? 'Must be a string.');
|
|
151
|
+
break;
|
|
152
|
+
case 'email':
|
|
153
|
+
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) $this->addError($field, $customMessage ?? 'Invalid email format.');
|
|
154
|
+
break;
|
|
155
|
+
case 'number':
|
|
156
|
+
if (!is_numeric($value)) $this->addError($field, $customMessage ?? 'Must be a number.');
|
|
157
|
+
break;
|
|
158
|
+
case 'date':
|
|
159
|
+
if (!\DateTime::createFromFormat('Y-m-d', $value)) $this->addError($field, $customMessage ?? 'Invalid date format.');
|
|
160
|
+
break;
|
|
161
|
+
case 'range':
|
|
162
|
+
if (!is_numeric($value) || $value < $ruleValue[0] || $value > $ruleValue[1]) $this->addError($field, $customMessage ?? "Must be between $ruleValue[0] and $ruleValue[1].");
|
|
163
|
+
break;
|
|
164
|
+
case 'url':
|
|
165
|
+
if (!filter_var($value, FILTER_VALIDATE_URL)) $this->addError($field, $customMessage ?? 'Invalid URL format.');
|
|
166
|
+
break;
|
|
167
|
+
case 'datetime-local':
|
|
168
|
+
if (!\DateTime::createFromFormat('Y-m-d\TH:i', $value)) $this->addError($field, $customMessage ?? 'Invalid datetime-local format.');
|
|
169
|
+
break;
|
|
170
|
+
case 'file':
|
|
171
|
+
if (!is_uploaded_file($value)) $this->addError($field, $customMessage ?? 'Invalid file format.');
|
|
172
|
+
break;
|
|
173
|
+
case 'required':
|
|
174
|
+
if (empty($value)) $this->addError($field, $customMessage ?? 'This field is required.');
|
|
175
|
+
break;
|
|
176
|
+
case 'min':
|
|
177
|
+
if ($value < $ruleValue) $this->addError($field, $customMessage ?? "Must be at least $ruleValue.");
|
|
178
|
+
break;
|
|
179
|
+
case 'max':
|
|
180
|
+
if ($value > $ruleValue) $this->addError($field, $customMessage ?? "Must be at most $ruleValue.");
|
|
181
|
+
break;
|
|
182
|
+
case 'minLength':
|
|
183
|
+
if (strlen($value) < $ruleValue) $this->addError($field, $customMessage ?? "Must be at least $ruleValue characters.");
|
|
184
|
+
break;
|
|
185
|
+
case 'maxLength':
|
|
186
|
+
if (strlen($value) > $ruleValue) $this->addError($field, $customMessage ?? "Must be at most $ruleValue characters.");
|
|
187
|
+
break;
|
|
188
|
+
case 'pattern':
|
|
189
|
+
if (!preg_match("/$ruleValue/", $value)) $this->addError($field, $customMessage ?? 'Invalid format.');
|
|
190
|
+
break;
|
|
191
|
+
case 'accept':
|
|
192
|
+
if (!in_array($value, explode(',', $ruleValue))) $this->addError($field, $customMessage ?? 'Invalid file format.');
|
|
193
|
+
break;
|
|
194
|
+
case 'autocomplete':
|
|
195
|
+
if (!in_array($value, ['on', 'off'])) $this->addError($field, $customMessage ?? 'Invalid autocomplete value.');
|
|
196
|
+
break;
|
|
197
|
+
default:
|
|
198
|
+
// Optionally handle unknown rules or log them
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Registers a form field and its validation rules, and updates the form state.
|
|
206
|
+
*
|
|
207
|
+
* @param string $fieldName The name of the form field.
|
|
208
|
+
* @param array $rules Validation rules for the field.
|
|
209
|
+
* @return string HTML attributes for the field.
|
|
210
|
+
*/
|
|
211
|
+
public function register($fieldName, $rules = []): string
|
|
212
|
+
{
|
|
213
|
+
$value = Validator::validateString($this->data[$fieldName] ?? '');
|
|
214
|
+
$attributes = "name=\"$fieldName\" value=\"$value\"";
|
|
215
|
+
|
|
216
|
+
if (!array_intersect(array_keys($rules), ['text', 'email', 'password', 'number', 'date', 'color', 'range', 'tel', 'url', 'search', 'time', 'datetime-local', 'month', 'week'])) {
|
|
217
|
+
$rules['text'] = ['value' => true];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
foreach ($rules as $rule => $ruleValue) {
|
|
221
|
+
$attributes .= $this->parseRule($rule, $ruleValue);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
$inputField = $this->stateManager->getState(self::FORM_INPUT_REGISTER) ?? [];
|
|
225
|
+
$inputField[$fieldName] = [
|
|
226
|
+
'value' => $value,
|
|
227
|
+
'attributes' => $attributes,
|
|
228
|
+
'rules' => $rules
|
|
229
|
+
];
|
|
230
|
+
$this->stateManager->setState([self::FORM_INPUT_REGISTER => $inputField], true);
|
|
231
|
+
|
|
232
|
+
return $attributes;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private function parseRule($rule, $ruleValue)
|
|
236
|
+
{
|
|
237
|
+
$attribute = '';
|
|
238
|
+
$ruleParam = is_array($ruleValue) ? $ruleValue['value'] : $ruleValue;
|
|
239
|
+
|
|
240
|
+
switch ($rule) {
|
|
241
|
+
case 'text':
|
|
242
|
+
case 'search':
|
|
243
|
+
case 'email':
|
|
244
|
+
case 'password':
|
|
245
|
+
case 'number':
|
|
246
|
+
case 'date':
|
|
247
|
+
case 'color':
|
|
248
|
+
case 'range':
|
|
249
|
+
case 'tel':
|
|
250
|
+
case 'url':
|
|
251
|
+
case 'time':
|
|
252
|
+
case 'datetime-local':
|
|
253
|
+
case 'month':
|
|
254
|
+
case 'week':
|
|
255
|
+
case 'file':
|
|
256
|
+
$attribute .= " type=\"$rule\"";
|
|
257
|
+
break;
|
|
258
|
+
case 'required':
|
|
259
|
+
$attribute .= " required";
|
|
260
|
+
break;
|
|
261
|
+
case 'min':
|
|
262
|
+
case 'max':
|
|
263
|
+
$attribute .= " $rule=\"$ruleParam\"";
|
|
264
|
+
break;
|
|
265
|
+
case 'minLength':
|
|
266
|
+
case 'maxLength':
|
|
267
|
+
$attribute .= " $rule=\"{$ruleParam}\"";
|
|
268
|
+
break;
|
|
269
|
+
case 'pattern':
|
|
270
|
+
$attribute .= " pattern=\"$ruleParam\"";
|
|
271
|
+
break;
|
|
272
|
+
case 'autocomplete':
|
|
273
|
+
$attribute .= " autocomplete=\"$ruleParam\"";
|
|
274
|
+
break;
|
|
275
|
+
case 'readonly':
|
|
276
|
+
$attribute .= " readonly";
|
|
277
|
+
break;
|
|
278
|
+
case 'disabled':
|
|
279
|
+
$attribute .= " disabled";
|
|
280
|
+
break;
|
|
281
|
+
case 'placeholder':
|
|
282
|
+
$attribute .= " placeholder=\"$ruleParam\"";
|
|
283
|
+
break;
|
|
284
|
+
case 'autofocus':
|
|
285
|
+
$attribute .= " autofocus";
|
|
286
|
+
break;
|
|
287
|
+
case 'multiple':
|
|
288
|
+
$attribute .= " multiple";
|
|
289
|
+
break;
|
|
290
|
+
case 'accept':
|
|
291
|
+
$attribute .= " accept=\"$ruleParam\"";
|
|
292
|
+
break;
|
|
293
|
+
case 'size':
|
|
294
|
+
$attribute .= " size=\"$ruleParam\"";
|
|
295
|
+
break;
|
|
296
|
+
case 'step':
|
|
297
|
+
$attribute .= " step=\"$ruleParam\"";
|
|
298
|
+
break;
|
|
299
|
+
case 'list':
|
|
300
|
+
$attribute .= " list=\"$ruleParam\"";
|
|
301
|
+
break;
|
|
302
|
+
default:
|
|
303
|
+
// Optionally handle unknown rules or log them
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
return $attribute;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -72,7 +72,7 @@ class AuthMiddleware
|
|
|
72
72
|
$roleBasedRoutes = AuthConfig::$roleBasedRoutes ?? [];
|
|
73
73
|
foreach ($roleBasedRoutes as $pattern => $data) {
|
|
74
74
|
if (self::getUriRegex($pattern, $requestUri)) {
|
|
75
|
-
$userRole = $auth->getPayload()
|
|
75
|
+
$userRole = Auth::ROLE_NAME ? $auth->getPayload()[Auth::ROLE_NAME] : $auth->getPayload();
|
|
76
76
|
if ($userRole !== null && AuthConfig::checkAuthRole($userRole, $data[AuthConfig::ROLE_IDENTIFIER])) {
|
|
77
77
|
return true;
|
|
78
78
|
}
|
|
@@ -9,14 +9,11 @@ use Lib\Validator;
|
|
|
9
9
|
class Mailer
|
|
10
10
|
{
|
|
11
11
|
private PHPMailer $mail;
|
|
12
|
-
private Validator $validator;
|
|
13
12
|
|
|
14
13
|
public function __construct()
|
|
15
14
|
{
|
|
16
15
|
$this->mail = new PHPMailer(true);
|
|
17
16
|
$this->setup();
|
|
18
|
-
|
|
19
|
-
$this->validator = new Validator();
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
private function setup(): void
|
|
@@ -67,11 +64,11 @@ class Mailer
|
|
|
67
64
|
public function send(string $to, string $subject, string $body, string $name = '', string $altBody = ''): bool
|
|
68
65
|
{
|
|
69
66
|
try {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
Validator::validateString($to);
|
|
68
|
+
Validator::validateString($subject);
|
|
69
|
+
Validator::validateString($body);
|
|
70
|
+
Validator::validateString($name);
|
|
71
|
+
Validator::validateString($altBody);
|
|
75
72
|
|
|
76
73
|
$this->mail->addAddress($to, $name);
|
|
77
74
|
$this->mail->isHTML(true);
|
|
@@ -77,6 +77,34 @@ class Validator
|
|
|
77
77
|
return static::validateInt($value); // Placeholder
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
public static function validateDate($value)
|
|
81
|
+
{
|
|
82
|
+
$date = \DateTime::createFromFormat('Y-m-d', $value);
|
|
83
|
+
if ($date && $date->format('Y-m-d') === $value) {
|
|
84
|
+
return $value;
|
|
85
|
+
} else {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public static function validateEmail($value)
|
|
91
|
+
{
|
|
92
|
+
if ($value === null) {
|
|
93
|
+
return '';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return filter_var($value, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public static function validateUrl($value)
|
|
100
|
+
{
|
|
101
|
+
if ($value === null) {
|
|
102
|
+
return '';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return filter_var($value, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
|
|
106
|
+
}
|
|
107
|
+
|
|
80
108
|
public static function validateUnsupported($value)
|
|
81
109
|
{
|
|
82
110
|
// Placeholder for future data types
|
package/dist/src/app/index.php
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="flex flex-col min-h-[100vh]">
|
|
2
2
|
<header class="px-4 lg:px-6 h-14 flex items-center">
|
|
3
|
-
<a class="flex items-center justify-center" href="
|
|
3
|
+
<a class="flex items-center justify-center" href="/">
|
|
4
4
|
<img class="h-10 w-10" src="<?= $baseUrl ?>assets/images/prisma-php.png" alt="Prisma PHP">
|
|
5
5
|
<span class="sr-only">Prisma PHP</span>
|
|
6
6
|
</a>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<p class="mx-auto max-w-[700px] text-gray-500 md:text-xl dark:text-gray-400">
|
|
30
30
|
The Next Generation ORM for PHP
|
|
31
31
|
</p>
|
|
32
|
-
<a class="inline-flex h-10 items-center justify-center rounded-md bg-gray-900 px-8 text-sm font-medium text-gray-50 shadow transition-colors hover:bg-gray-900/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-gray-950 disabled:pointer-events-none disabled:opacity-50 dark:bg-gray-50 dark:text-gray-900 dark:hover:bg-gray-50/90 dark:focus-visible:ring-gray-300" href="https://prismaphp.tsnc.tech/docs?doc=get-started">
|
|
32
|
+
<a class="inline-flex h-10 items-center justify-center rounded-md bg-gray-900 px-8 text-sm font-medium text-gray-50 shadow transition-colors hover:bg-gray-900/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-gray-950 disabled:pointer-events-none disabled:opacity-50 dark:bg-gray-50 dark:text-gray-900 dark:hover:bg-gray-50/90 dark:focus-visible:ring-gray-300" href="https://prismaphp.tsnc.tech/docs?doc=get-started" target="_blank">
|
|
33
33
|
Get Started
|
|
34
34
|
</a>
|
|
35
35
|
</div>
|
package/dist/tsconfig.json
CHANGED
|
@@ -105,5 +105,7 @@
|
|
|
105
105
|
/* Completeness */
|
|
106
106
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
|
107
107
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
|
108
|
-
}
|
|
108
|
+
},
|
|
109
|
+
"include": [],
|
|
110
|
+
"exclude": ["node_modules"]
|
|
109
111
|
}
|
package/package.json
CHANGED
package/dist/.env
DELETED
|
File without changes
|