create-prisma-php-app 1.28.7 → 2.0.0-alpha.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.
@@ -3,6 +3,14 @@
3
3
  namespace Lib\Prisma\Classes;
4
4
 
5
5
  use Lib\Validator;
6
+ use ReflectionClass;
7
+ use InvalidArgumentException;
8
+ use DateTime;
9
+ use Brick\Math\BigDecimal;
10
+ use Brick\Math\BigInteger;
11
+ use ReflectionUnionType;
12
+ use ReflectionNamedType;
13
+ use Exception;
6
14
 
7
15
  enum ArrayType: string
8
16
  {
@@ -24,7 +32,7 @@ final class PPHPUtility
24
32
  * @param string $modelName The name of the model being checked.
25
33
  * @param string $timestamp The timestamp field name to be ignored during the check.
26
34
  *
27
- * @throws \Exception If a field does not exist in the model or if the selection format is incorrect.
35
+ * @throws Exception If a field does not exist in the model or if the selection format is incorrect.
28
36
  */
29
37
  public static function checkFieldsExistWithReferences(
30
38
  array $select,
@@ -41,17 +49,17 @@ final class PPHPUtility
41
49
 
42
50
  if (is_numeric($key) && is_string($value)) {
43
51
  if (array_key_exists($value, $fields))
44
- throw new \Exception("The '$value' is indexed, waiting example: ['$value' => true]");
52
+ throw new Exception("The '$value' is indexed, waiting example: ['$value' => true]");
45
53
  }
46
54
 
47
55
  if (isset($value) && empty($value) || !is_bool($value)) {
48
56
  if (is_string($key) && !array_key_exists($key, $fields)) {
49
- throw new \Exception("The field '$key' does not exist in the $modelName model.");
57
+ throw new Exception("The field '$key' does not exist in the $modelName model.");
50
58
  }
51
59
 
52
60
  if (is_string($key) && array_key_exists($key, $fields)) {
53
61
  if (!is_bool($value) && !is_array($value)) {
54
- throw new \Exception("The '$key' is indexed, waiting example: ['$key' => true]");
62
+ throw new Exception("The '$key' is indexed, waiting example: ['$key' => true]");
55
63
  }
56
64
  }
57
65
 
@@ -67,7 +75,7 @@ final class PPHPUtility
67
75
  $relatedEntityFields[$key] = [$key];
68
76
  } else {
69
77
  if (!is_bool($value) || empty($value)) {
70
- throw new \Exception("The '$key' is indexed, waiting example: ['$key' => true] or ['$key' => ['select' => ['field1' => true, 'field2' => true]]]");
78
+ throw new Exception("The '$key' is indexed, waiting example: ['$key' => true] or ['$key' => ['select' => ['field1' => true, 'field2' => true]]]");
71
79
  }
72
80
  }
73
81
  }
@@ -78,7 +86,7 @@ final class PPHPUtility
78
86
 
79
87
  if (!array_key_exists($fieldName, $fields)) {
80
88
  $availableFields = implode(', ', array_keys($fields));
81
- throw new \Exception("The field '$fieldName' does not exist in the $modelName model. Available fields are: $availableFields");
89
+ throw new Exception("The field '$fieldName' does not exist in the $modelName model. Available fields are: $availableFields");
82
90
  }
83
91
 
84
92
  if (
@@ -116,19 +124,19 @@ final class PPHPUtility
116
124
  * @param array $fields The array of fields available in the model.
117
125
  * @param string $modelName The name of the model being checked.
118
126
  *
119
- * @throws \Exception If a field in the select array does not exist in the fields array.
127
+ * @throws Exception If a field in the select array does not exist in the fields array.
120
128
  */
121
129
  public static function checkFieldsExist(array $select, array $fields, string $modelName)
122
130
  {
123
131
  foreach ($select as $key => $value) {
124
132
  if (is_numeric($key) && is_string($value)) {
125
- if (array_key_exists($value, $fields))
126
- throw new \Exception("The '$value' is indexed, waiting example: ['$value' => true]");
133
+ if (self::fieldExists($key, $fields))
134
+ throw new Exception("The '$value' is indexed, waiting example: ['$value' => true]");
127
135
  }
128
136
 
129
137
  if (isset($value) && empty($value) || !is_bool($value)) {
130
- if (is_string($key) && !array_key_exists($key, $fields)) {
131
- throw new \Exception("The field '$key' does not exist in the $modelName model.");
138
+ if (is_string($key) && !self::fieldExists($key, $fields)) {
139
+ throw new Exception("The field '$key' does not exist in the $modelName model.");
132
140
  }
133
141
 
134
142
  if (is_array($value) && !empty($value)) {
@@ -136,11 +144,12 @@ final class PPHPUtility
136
144
  $isRelatedModel = false;
137
145
 
138
146
  foreach ($fields as $field) {
139
- $relation = $field['decorators']['relation'] ?? null;
140
- $inverseRelation = $field['decorators']['inverseRelation'] ?? null;
141
- $implicitRelation = $field['decorators']['implicitRelation'] ?? null;
147
+ $isObject = $field['kind'] === 'object' ? true : false;
148
+ $fieldName = $field['name'];
142
149
 
143
- if (isset($relation['name']) && $relation['name'] == $key || isset($inverseRelation['fromField']) && $inverseRelation['fromField'] == $key || isset($implicitRelation['fromField']) && $implicitRelation['fromField'] == $key) $isRelatedModel = true;
150
+ if ($isObject && $fieldName === $key) {
151
+ $isRelatedModel = true;
152
+ }
144
153
  }
145
154
 
146
155
  if ($isRelatedModel) continue;
@@ -148,8 +157,8 @@ final class PPHPUtility
148
157
  $keys = array_keys($value);
149
158
  foreach ($keys as $fieldName) {
150
159
  $fieldName = trim($fieldName);
151
- if (!array_key_exists($fieldName, $fields)) {
152
- throw new \Exception("The field '$fieldName' does not exist in the $modelName model.");
160
+ if (!self::fieldExists($fieldName, $fields)) {
161
+ throw new Exception("The field '$fieldName' does not exist in the $modelName model.");
153
162
  }
154
163
  }
155
164
  }
@@ -159,13 +168,23 @@ final class PPHPUtility
159
168
 
160
169
  foreach (explode(',', $key) as $fieldName) {
161
170
  $fieldName = trim($fieldName);
162
- if (!array_key_exists($fieldName, $fields)) {
163
- throw new \Exception("The field '$fieldName' does not exist in the $modelName model.");
171
+ if (!self::fieldExists($fieldName, $fields)) {
172
+ throw new Exception("The field '$fieldName' does not exist in the $modelName model.");
164
173
  }
165
174
  }
166
175
  }
167
176
  }
168
177
 
178
+ private static function fieldExists(string $key, array $fields): bool
179
+ {
180
+ foreach ($fields as $field) {
181
+ if (isset($field['name']) && $field['name'] === $key) {
182
+ return true;
183
+ }
184
+ }
185
+ return false;
186
+ }
187
+
169
188
  /**
170
189
  * Checks the contents of an array and determines its type.
171
190
  *
@@ -202,7 +221,7 @@ final class PPHPUtility
202
221
  * @param array $fields The array of fields in the model.
203
222
  * @param string $modelName The name of the model being processed.
204
223
  *
205
- * @throws \Exception If an include value is indexed incorrectly or if a field does not exist in the model.
224
+ * @throws Exception If an include value is indexed incorrectly or if a field does not exist in the model.
206
225
  */
207
226
  public static function checkIncludes(array $include, array &$relatedEntityFields, array &$includes, array $fields, string $modelName)
208
227
  {
@@ -215,7 +234,7 @@ final class PPHPUtility
215
234
  self::processIncludeValue($key, $value, $relatedEntityFields, $fields, $modelName, $key);
216
235
 
217
236
  if (is_numeric($key) && is_string($value)) {
218
- throw new \Exception("The '$value' is indexed, waiting example: ['$value' => true]");
237
+ throw new Exception("The '$value' is indexed, waiting example: ['$value' => true]");
219
238
  }
220
239
 
221
240
  if (isset($value) && empty($value) || !is_bool($value)) {
@@ -223,7 +242,7 @@ final class PPHPUtility
223
242
  }
224
243
 
225
244
  if (!array_key_exists($key, $fields)) {
226
- throw new \Exception("The field '$key' does not exist in the $modelName model.");
245
+ throw new Exception("The field '$key' does not exist in the $modelName model.");
227
246
  }
228
247
 
229
248
  $includes[$key] = $value;
@@ -249,7 +268,7 @@ final class PPHPUtility
249
268
  }
250
269
  } else {
251
270
  if (!is_bool($value) || empty($value)) {
252
- throw new \Exception("The '$value' is indexed, waiting example: ['$value' => true] or ['$value' => ['select' => ['field1' => true, 'field2' => true]]]");
271
+ throw new Exception("The '$value' is indexed, waiting example: ['$value' => true] or ['$value' => ['select' => ['field1' => true, 'field2' => true]]]");
253
272
  }
254
273
  }
255
274
  }
@@ -357,7 +376,7 @@ final class PPHPUtility
357
376
  break;
358
377
  default:
359
378
  // Handle other conditions or log an error/warning for unsupported conditions
360
- throw new \Exception("Unsupported condition: $condition");
379
+ throw new Exception("Unsupported condition: $condition");
361
380
  break;
362
381
  }
363
382
  }
@@ -392,13 +411,13 @@ final class PPHPUtility
392
411
  * @param array $fields The array of allowed field names.
393
412
  * @param string $modelName The name of the model being checked.
394
413
  *
395
- * @throws \Exception If an invalid key is found in the data array.
414
+ * @throws Exception If an invalid key is found in the data array.
396
415
  */
397
416
  public static function checkForInvalidKeys(array $data, array $fields, string $modelName)
398
417
  {
399
418
  foreach ($data as $key => $value) {
400
419
  if (!empty($key) && !in_array($key, $fields)) {
401
- throw new \Exception("The field '$key' does not exist in the $modelName model. Accepted fields: " . implode(', ', $fields));
420
+ throw new Exception("The field '$key' does not exist in the $modelName model. Accepted fields: " . implode(', ', $fields));
402
421
  }
403
422
  }
404
423
  }
@@ -569,7 +588,7 @@ final class PPHPUtility
569
588
  * @param string $dbType The type of the database (e.g., 'mysql', 'pgsql').
570
589
  * @param object|null $model The model object containing metadata about the relations.
571
590
  *
572
- * @throws \Exception If relation metadata is not defined or if required fields/references are missing.
591
+ * @throws Exception If relation metadata is not defined or if required fields/references are missing.
573
592
  */
574
593
  public static function buildJoinsRecursively(
575
594
  array $include,
@@ -579,18 +598,19 @@ final class PPHPUtility
579
598
  mixed $pdo,
580
599
  string $dbType,
581
600
  ?object $model = null,
582
- string $defaultJoinType = 'INNER JOIN' // Default join type
601
+ string $defaultJoinType = 'INNER JOIN',
602
+ string $pathPrefix = ''
583
603
  ) {
584
604
  foreach ($include as $relationName => $relationOptions) {
585
-
586
605
  $joinType = isset($relationOptions['join.type'])
587
606
  ? strtoupper($relationOptions['join.type']) . ' JOIN'
588
607
  : $defaultJoinType;
589
608
 
590
609
  if (!in_array($joinType, ['INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN'], true)) {
591
- throw new \Exception("Invalid join type: $joinType (expected 'INNER JOIN', 'LEFT JOIN', or 'RIGHT JOIN')");
610
+ throw new Exception("Invalid join type: $joinType (expected 'INNER JOIN', 'LEFT JOIN', or 'RIGHT JOIN')");
592
611
  }
593
- // Check for nested includes (like ['include' => [ ... ]])
612
+
613
+ // Extract nested includes
594
614
  $nestedInclude = [];
595
615
  if (is_array($relationOptions) && isset($relationOptions['include']) && is_array($relationOptions['include'])) {
596
616
  $nestedInclude = $relationOptions['include'];
@@ -598,87 +618,69 @@ final class PPHPUtility
598
618
  $isNested = !empty($nestedInclude);
599
619
 
600
620
  // 1. Fetch metadata
601
- if (!isset($model->fields[$relationName]['decorators'])) {
602
- throw new \Exception(
603
- "Relation metadata not defined for '$relationName' in " . get_class($model)
604
- );
621
+ if (!isset($model->fields[$relationName])) {
622
+ throw new Exception("Relation metadata not defined for '$relationName' in " . get_class($model));
605
623
  }
606
- $decorator = $model->fields[$relationName]['decorators'];
607
624
 
608
- // 2. Determine the actual DB table
609
- $joinTable = $decorator['relation']['relationTableName']
610
- ?? $decorator['inverseRelation']['toTableName']
611
- ?? $decorator['implicitRelation']['tableName']
612
- ?? null;
613
- if (!$joinTable) {
614
- throw new \Exception("No valid table name found for relation '$relationName'.");
625
+ // 2. Identify related class
626
+ $relatedClassName = "Lib\\Prisma\\Classes\\" . $model->fields[$relationName]['type'] ?? null;
627
+ $relatedClass = new $relatedClassName($pdo);
628
+ if (!$relatedClass) {
629
+ throw new Exception("Could not instantiate class for relation '$relationName'.");
615
630
  }
616
631
 
617
- // 3. Figure out the relation type in one place
618
- $relationType = $decorator['relation']['type']
619
- ?? $decorator['inverseRelation']['type']
620
- ?? $decorator['implicitRelation']['type']
621
- ?? null;
622
- // Decide the alias separator: OneToOne/ManyToOne => '.', else '._.'
623
- $separator = ($relationType === 'OneToOne' || $relationType === 'ManyToOne')
624
- ? '.'
625
- : '._.';
632
+ // 3. Determine DB table
633
+ $joinTable = $relatedClass->tableName ?? null;
634
+ if (!$joinTable) {
635
+ throw new Exception("No valid table name found for relation '$relationName'.");
636
+ }
626
637
 
627
638
  $newAliasQuoted = PPHPUtility::quoteColumnName($dbType, $relationName);
628
639
 
629
- // 4. Build the ON condition
630
- $joinCondition = '';
631
- if (isset($decorator['relation'])) {
632
- $relationField = $decorator['relation']['references'][0] ?? null;
633
- $referenceKey = $decorator['relation']['fields'][0] ?? null;
640
+ // 5. Build the ON condition
641
+ $joinConditions = [];
642
+ $fieldsRelatedWithKeys = $model->fieldsRelatedWithKeys[$relationName] ?? null;
643
+ if ($fieldsRelatedWithKeys) {
644
+ $relationToFields = $fieldsRelatedWithKeys['relationToFields'] ?? [];
645
+ $relationFromFields = $fieldsRelatedWithKeys['relationFromFields'] ?? [];
634
646
 
635
- if (!$relationField || !$referenceKey) {
636
- throw new \Exception("Missing 'references' or 'fields' for relation '$relationName'.");
647
+ if (count($relationToFields) !== count($relationFromFields)) {
648
+ throw new Exception("Mismatched 'references' and 'fields' for '$relationName'.");
637
649
  }
638
650
 
639
- // The join pattern is the same whether OneToOne, ManyToOne, etc.
640
- $joinCondition = sprintf(
641
- '%s.%s = %s.%s',
642
- $parentAlias,
643
- PPHPUtility::quoteColumnName($dbType, $referenceKey),
644
- $newAliasQuoted,
645
- PPHPUtility::quoteColumnName($dbType, $relationField)
646
- );
647
- } elseif (isset($decorator['inverseRelation'])) {
648
- $relationField = $decorator['inverseRelation']['fields'][0] ?? null;
649
- $referenceKey = $decorator['inverseRelation']['references'][0] ?? null;
651
+ foreach ($relationToFields as $index => $toField) {
652
+ $fromField = $relationFromFields[$index] ?? null;
653
+ if (!$toField || !$fromField) {
654
+ throw new Exception("Missing references/fields for '$relationName' at index $index.");
655
+ }
650
656
 
651
- if (!$relationField || !$referenceKey) {
652
- throw new \Exception("Missing 'fields' or 'references' for inverseRelation '$relationName'.");
653
- }
657
+ $fromFieldExists = array_key_exists($fromField, $model->fields);
654
658
 
655
- $joinCondition = sprintf(
656
- '%s.%s = %s.%s',
657
- $parentAlias,
658
- PPHPUtility::quoteColumnName($dbType, $referenceKey),
659
- $newAliasQuoted,
660
- PPHPUtility::quoteColumnName($dbType, $relationField)
661
- );
662
- } elseif (isset($decorator['implicitRelation'])) {
663
- $relationField = $decorator['implicitRelation']['fields'][0] ?? null;
664
- $referenceKey = $decorator['implicitRelation']['references'][0] ?? null;
665
-
666
- if (!$relationField || !$referenceKey) {
667
- throw new \Exception("Missing 'fields' or 'references' for implicitRelation '$relationName'.");
659
+ if ($fromFieldExists) {
660
+ $joinConditions[] = sprintf(
661
+ '%s.%s = %s.%s',
662
+ $parentAlias,
663
+ PPHPUtility::quoteColumnName($dbType, $fromField),
664
+ $newAliasQuoted,
665
+ PPHPUtility::quoteColumnName($dbType, $toField)
666
+ );
667
+ } else {
668
+ $joinConditions[] = sprintf(
669
+ '%s.%s = %s.%s',
670
+ $parentAlias,
671
+ PPHPUtility::quoteColumnName($dbType, $toField),
672
+ $newAliasQuoted,
673
+ PPHPUtility::quoteColumnName($dbType, $fromField)
674
+ );
675
+ }
668
676
  }
669
-
670
- $joinCondition = sprintf(
671
- '%s.%s = %s.%s',
672
- $parentAlias,
673
- PPHPUtility::quoteColumnName($dbType, $referenceKey),
674
- $newAliasQuoted,
675
- PPHPUtility::quoteColumnName($dbType, $relationField)
676
- );
677
677
  } else {
678
- throw new \Exception("Relation or inverseRelation not properly defined for '$relationName'.");
678
+ throw new Exception("Relation '$relationName' not properly defined.");
679
679
  }
680
680
 
681
- // 5. Add the JOIN statement dynamically
681
+ $joinCondition = implode(' AND ', $joinConditions);
682
+
683
+ // 6. Add the JOIN statement
682
684
  $joinTableQuoted = PPHPUtility::quoteColumnName($dbType, $joinTable);
683
685
  $joins[] = sprintf(
684
686
  '%s %s AS %s ON %s',
@@ -688,18 +690,19 @@ final class PPHPUtility
688
690
  $joinCondition
689
691
  );
690
692
 
691
- // 6. Identify the related class
692
- $relatedClass = PPHPFactory::getRelatedClass($relationName, $pdo) ?? null;
693
- if (!$relatedClass) {
694
- throw new \Exception("Could not instantiate class for relation '$relationName'.");
695
- }
693
+ // 7. ADD COLUMNS (with the *full path prefix*).
694
+ // e.g. if pathPrefix="" and relationName="post", then childPathPrefix="post".
695
+ // if pathPrefix="post" and relationName="categories", => "post.categories".
696
+ $childPathPrefix = $pathPrefix
697
+ ? $pathPrefix . '.' . $relationName
698
+ : $relationName;
696
699
 
697
- // 7. Add columns from the joined table
698
700
  $fieldsOnly = $relatedClass->fieldsOnly ?? [];
699
701
  foreach ($fieldsOnly as $field) {
700
702
  $quotedField = PPHPUtility::quoteColumnName($dbType, $field);
701
- $columnAlias = sprintf('%s%s%s', $relationName, $separator, $field);
703
+ $columnAlias = $childPathPrefix . '.' . $field; // e.g. "post.categories.id"
702
704
  $columnAliasQuoted = PPHPUtility::quoteColumnName($dbType, $columnAlias);
705
+
703
706
  $selectFields[] = sprintf(
704
707
  '%s.%s AS %s',
705
708
  $newAliasQuoted,
@@ -712,14 +715,140 @@ final class PPHPUtility
712
715
  if ($isNested) {
713
716
  self::buildJoinsRecursively(
714
717
  $nestedInclude,
715
- $newAliasQuoted,
718
+ $newAliasQuoted, // use this for the next level's JOIN
716
719
  $joins,
717
720
  $selectFields,
718
721
  $pdo,
719
722
  $dbType,
720
- $relatedClass
723
+ $relatedClass,
724
+ $defaultJoinType,
725
+ $childPathPrefix // pass down the updated path
721
726
  );
722
727
  }
723
728
  }
724
729
  }
730
+
731
+ public static function arrayToObjectRecursive($data)
732
+ {
733
+ // If it's not an array, there's nothing to convert; just return as-is
734
+ if (!is_array($data)) {
735
+ return $data;
736
+ }
737
+
738
+ // Convert each item in the array and then convert the array itself
739
+ foreach ($data as $key => $value) {
740
+ $data[$key] = self::arrayToObjectRecursive($value);
741
+ }
742
+
743
+ return (object) $data;
744
+ }
745
+
746
+ public static function arrayToClassRecursive(array $data, string $class)
747
+ {
748
+ if (!class_exists($class)) {
749
+ throw new InvalidArgumentException("Class {$class} does not exist.");
750
+ }
751
+
752
+ $reflection = new ReflectionClass($class);
753
+ $instance = $reflection->newInstanceWithoutConstructor();
754
+ $properties = $reflection->getProperties();
755
+
756
+ foreach ($properties as $property) {
757
+ $propertyName = $property->getName();
758
+
759
+ if (array_key_exists($propertyName, $data)) {
760
+ $propertyType = $property->getType();
761
+ $typeNames = [];
762
+
763
+ if ($propertyType instanceof ReflectionUnionType) {
764
+ $typeNames = array_map(fn($t) => $t->getName(), $propertyType->getTypes());
765
+ } elseif ($propertyType instanceof ReflectionNamedType) {
766
+ $typeNames[] = $propertyType->getName();
767
+ }
768
+
769
+ if (in_array(DateTime::class, $typeNames)) {
770
+ $instance->$propertyName = (new DateTime($data[$propertyName]))->format('Y-m-d H:i:s');
771
+ } elseif (in_array(BigDecimal::class, $typeNames)) {
772
+ $instance->$propertyName = BigDecimal::of($data[$propertyName]);
773
+ } elseif (in_array(BigInteger::class, $typeNames)) {
774
+ $instance->$propertyName = BigInteger::of($data[$propertyName]);
775
+ } elseif (count(array_intersect($typeNames, ['int', 'float', 'string', 'bool'])) > 0) {
776
+ $instance->$propertyName = $data[$propertyName];
777
+ } elseif (in_array('array', $typeNames) && isset($data[$propertyName]) && is_array($data[$propertyName])) {
778
+ // Check array type
779
+ $arrayType = self::checkArrayContents($data[$propertyName]);
780
+
781
+ // Handle array-to-object conversion
782
+ $docComment = $property->getDocComment();
783
+ if ($docComment && preg_match('/@var\s+([^\s\[\]]+)\[]/', $docComment, $matches)) {
784
+ $elementType = $matches[1];
785
+ if (class_exists($elementType)) {
786
+ if ($arrayType === ArrayType::Indexed) {
787
+ $instance->$propertyName = array_map(
788
+ fn($item) => self::arrayToClassRecursive($item, $elementType),
789
+ $data[$propertyName]
790
+ );
791
+ } else {
792
+ // If associative, keep as array
793
+ $instance->$propertyName = $data[$propertyName];
794
+ }
795
+ } else {
796
+ $instance->$propertyName = $data[$propertyName]; // Default to raw array
797
+ }
798
+ } else {
799
+ $instance->$propertyName = $data[$propertyName]; // Default to raw array
800
+ }
801
+ } else {
802
+ foreach ($typeNames as $typeName) {
803
+ if (class_exists($typeName)) {
804
+ if (is_array($data[$propertyName])) {
805
+ $arrayType = self::checkArrayContents($data[$propertyName]);
806
+
807
+ if ($arrayType === ArrayType::Associative) {
808
+ $instance->$propertyName = self::arrayToClassRecursive($data[$propertyName], $typeName);
809
+ } elseif ($arrayType === ArrayType::Indexed) {
810
+ $instance->$propertyName = array_map(
811
+ fn($item) => self::arrayToClassRecursive($item, $typeName),
812
+ $data[$propertyName] ?? []
813
+ );
814
+ }
815
+ } elseif ($data[$propertyName] instanceof $typeName) {
816
+ $instance->$propertyName = $data[$propertyName];
817
+ }
818
+ break;
819
+ }
820
+ }
821
+ }
822
+ }
823
+ }
824
+
825
+ return $instance;
826
+ }
827
+
828
+ /**
829
+ * Recursively sets a value in a multi-dimensional array
830
+ * based on an array of keys. E.g.:
831
+ * setNestedValue($arr, ['post','categories','id'], 'some-id')
832
+ * becomes
833
+ * $arr['post']['categories']['id'] = 'some-id';
834
+ */
835
+ public static function setNestedValue(array &$array, array $keys, $value)
836
+ {
837
+ // Take the first key from the array
838
+ $key = array_shift($keys);
839
+
840
+ // If this key doesn't exist yet, initialize it
841
+ if (!isset($array[$key])) {
842
+ // Decide if you want an empty array or some default
843
+ $array[$key] = [];
844
+ }
845
+
846
+ // If there are no more keys left, this is where we set the final value
847
+ if (empty($keys)) {
848
+ $array[$key] = $value;
849
+ } else {
850
+ // Otherwise, we recurse deeper
851
+ self::setNestedValue($array[$key], $keys, $value);
852
+ }
853
+ }
725
854
  }
@@ -4,17 +4,21 @@ namespace Lib\Prisma\Model;
4
4
 
5
5
  interface IModel
6
6
  {
7
+ // public function aggregate(array $operation);
8
+ // public function createMany(array $data);
9
+ // public function createManyAndReturn(array $data);
7
10
  public function create(array $data);
8
- public function createMany(array $data);
11
+ // public function deleteMany(array $criteria);
12
+ // public function delete(array $criteria);
13
+ // public function findFirst(array $criteria);
14
+ // public function findFirstOrThrow(array $criteria);
15
+ // public function findMany(array $criteria);
9
16
  public function findUnique(array $criteria);
10
- public function findMany(array $criteria);
11
- public function findFirst(array $criteria);
12
- public function update(array $data);
13
- public function updateMany(array $data);
14
- public function delete(array $criteria);
15
- public function deleteMany(array $criteria);
16
- public function upsert(array $data);
17
- public function aggregate(array $operation);
18
- public function groupBy(array $by);
19
- public function count(array $criteria);
17
+ // public function findUniqueOrThrow(array $criteria);
18
+ // public function groupBy(array $by);
19
+ // public function updateMany(array $data);
20
+ // public function updateManyAndReturn(array $data);
21
+ // public function update(array $data);
22
+ // public function upsert(array $data);
23
+ // public function count(array $criteria);
20
24
  }
@@ -40,7 +40,6 @@ class PrismaSettings
40
40
  $this->projectRootPath = $data['projectRootPath'] ?? '';
41
41
  $this->phpEnvironment = $data['phpEnvironment'] ?? '';
42
42
  $this->phpRootPathExe = $data['phpRootPathExe'] ?? '';
43
- $this->phpGenerateClassPath = $data['phpGenerateClassPath'] ?? '';
44
43
  $this->bsTarget = $data['bsTarget'] ?? '';
45
44
  $this->bsPathRewrite = new BSPathRewrite($data['bsPathRewrite'] ?? []);
46
45
  $this->backendOnly = $data['backendOnly'] ?? false;
@@ -84,12 +83,20 @@ class PrismaPHPSettings
84
83
  */
85
84
  public static array $includeFiles = [];
86
85
 
86
+ /**
87
+ * The local storage key for the app state.
88
+ *
89
+ * @var string
90
+ */
91
+ public static string $localStoreKey;
92
+
87
93
  public static function init(): void
88
94
  {
89
95
  self::$option = self::getPrismaSettings();
90
96
  self::$routeFiles = self::getRoutesFileList();
91
97
  self::$classLogFiles = self::getClassesLogFiles();
92
98
  self::$includeFiles = self::getIncludeFiles();
99
+ self::$localStoreKey = self::getLocalStorageKey();
93
100
  }
94
101
 
95
102
  /**
@@ -119,26 +126,54 @@ class PrismaPHPSettings
119
126
  private static function getRoutesFileList(): array
120
127
  {
121
128
  $jsonFileName = SETTINGS_PATH . '/files-list.json';
122
- $routeFiles = file_exists($jsonFileName) ? json_decode(file_get_contents($jsonFileName), true) : [];
129
+ if (!file_exists($jsonFileName)) {
130
+ return [];
131
+ }
132
+
133
+ $jsonContent = file_get_contents($jsonFileName);
134
+ if ($jsonContent === false || empty(trim($jsonContent))) {
135
+ return [];
136
+ }
123
137
 
124
- return $routeFiles;
138
+ $routeFiles = json_decode($jsonContent, true);
139
+ return is_array($routeFiles) ? $routeFiles : [];
125
140
  }
126
141
 
127
142
  private static function getClassesLogFiles(): array
128
143
  {
129
144
  $jsonFileName = SETTINGS_PATH . '/class-imports.json';
130
- $classLogFiles = file_exists($jsonFileName) ? json_decode(file_get_contents($jsonFileName), true) : [];
145
+ if (!file_exists($jsonFileName)) {
146
+ return [];
147
+ }
131
148
 
132
- return $classLogFiles;
149
+ $jsonContent = file_get_contents($jsonFileName);
150
+ if ($jsonContent === false || empty(trim($jsonContent))) {
151
+ return [];
152
+ }
153
+
154
+ $classLogFiles = json_decode($jsonContent, true);
155
+ return is_array($classLogFiles) ? $classLogFiles : [];
133
156
  }
134
157
 
135
158
  private static function getIncludeFiles(): array
136
159
  {
137
160
  $jsonFileName = SETTINGS_PATH . "/request-data.json";
138
- $includeFiles = file_exists($jsonFileName)
139
- ? json_decode(file_get_contents($jsonFileName), true)
140
- : [];
161
+ if (!file_exists($jsonFileName)) {
162
+ return [];
163
+ }
164
+
165
+ $jsonContent = file_get_contents($jsonFileName);
166
+ if ($jsonContent === false || empty(trim($jsonContent))) {
167
+ return [];
168
+ }
169
+
170
+ $includeFiles = json_decode($jsonContent, true);
171
+ return is_array($includeFiles) ? $includeFiles : [];
172
+ }
141
173
 
142
- return $includeFiles;
174
+ private static function getLocalStorageKey(): string
175
+ {
176
+ $localStorageKey = $_ENV['LOCALSTORE_KEY'] ?? 'pphp_local_store_59e13';
177
+ return strtolower(preg_replace('/\s+/', '_', trim($localStorageKey)));
143
178
  }
144
179
  }