translatable) { foreach ($locales as $locale) { $res = static::validateField( $locale["id"], $schemaField, $recordFields, $recordEdges, ); $errors[] = $res; } } } return collect($errors) ->filter(fn($err) => $err !== null) ->values() ->toArray(); } /** * * @param Field $schemaField * @param RecordField[] $recordFields * @param Edge[] $recordEdges * @return array */ public static function validateField( string $locale, Field $schemaField, array $recordFields, array $recordEdges, ): ?RecordError { // General Validations $error = static::validateRequired( $locale, $schemaField, $recordFields, $recordEdges, ); if (!empty($error)) { return $error; } // Type specific $error = match ($schemaField->type) { "text" => static::validateText( $locale, $schemaField, $recordFields, ), "relation" => static::validateRelation( $locale, $schemaField, $recordEdges, ), default => static::validateText( $locale, $schemaField, $recordFields, ), }; return $error; } /** * * @param Field $schemaField * @param RecordField[] $recordFields * @param Edge[] $recordEdges * @return ?RecordError */ public static function validateRequired( string $locale, Field $schemaField, array $recordFields, array $recordEdges, ): ?RecordError { if ($schemaField->required === false) { return null; } return match ($schemaField->type) { "relation" => static::validateRequiredRelation( $locale, $schemaField, $recordEdges, ), default => static::validateRequiredField( $locale, $schemaField, $recordFields, ), }; } private static function validateRequiredField( string $locale, Field $schemaField, array $recordFields, ): ?RecordError { $recordField = static::findField($recordFields, $schemaField, $locale); if (empty($recordField) || empty($recordField->value)) { return new RecordError( $schemaField->id, $locale, "This field is required", ); } return null; } private static function validateRequiredRelation( string $locale, Field $schemaField, array $recordEdges, ): ?RecordError { if ( collect($recordEdges) ->where("fieldId", $schemaField->id) ->where("locale", $locale) ->where("mode", RecordMode::DRAFT) ->isEmpty() ) { return new RecordError( $schemaField->id, $locale, "This field is required", ); } return null; } /** * * @param Field $schemaField * @param RecordField[] $recordFields * @return ?RecordError */ public static function validateText( string $locale, Field $schemaField, array $recordFields, ): ?RecordError { $recordField = static::findField($recordFields, $schemaField, $locale); if (empty($recordField)) { // We have already checked for required fields so only validate existing return null; } $rules = ""; if ($schemaField->props->min > 0) { $rules = "min:" . $schemaField->props->min; } if ($schemaField->props->max > 0) { $rules = "max:" . $schemaField->props->max; } if (empty($rules)) { return null; } $validator = Validator::make( ["value" => $recordField->value], [ "value" => $rules, ], ); if ($validator->fails()) { return new RecordError( $schemaField->id, $locale, $validator->errors()->first(), ); } return null; } /** * * @param Field $schemaField * @param Edge[] $recordEdges * @return ?RecordError */ public static function validateRelation( string $locale, Field $schemaField, array $recordEdges, ): ?RecordError { $count = collect($recordEdges) ->where("fieldId", $schemaField->id) ->where("locale", $locale) ->where("mode", RecordMode::DRAFT) ->count(); if ($schemaField->props->min > 0) { if ($count < $schemaField->props->min) { return new RecordError( $schemaField->id, $locale, "You have to have at least {$schemaField->props->min} related records", ); } } if ($schemaField->props->max > 0) { if ($count > $schemaField->props->max) { return new RecordError( $schemaField->id, $locale, "You have to have at most {$schemaField->props->max} related records", ); } } return null; } private static function findField( array $recordFields, Field $schemaField, string $locale, ): ?RecordField { return collect($recordFields)->first( fn(RecordField $field) => $field->fieldId === $schemaField->id && $field->locale === $locale && $field->mode === RecordMode::DRAFT, ); } }