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.
@@ -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() ?? null;
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
- $this->validator->validateString($to);
71
- $this->validator->validateString($subject);
72
- $this->validator->validateString($body);
73
- $this->validator->validateString($name);
74
- $this->validator->validateString($altBody);
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);
@@ -7,7 +7,7 @@ namespace Lib;
7
7
  */
8
8
  class StateManager
9
9
  {
10
- private const APP_STATE = 'appState';
10
+ private const APP_STATE = 'app_state_F989A';
11
11
  private $state;
12
12
  private $listeners;
13
13
 
@@ -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
@@ -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>
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "1.11.543",
3
+ "version": "1.11.600",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
package/dist/.env DELETED
File without changes