Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer\Exception;
/**
* Exception thrown when deserialization fails
*
* This exception is thrown when an error occurs during the deserialization process,
* such as when trying to deserialize invalid or malformed data.
*/
class DeserializeException extends SerializerException
{
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer\Exception;
/**
* Exception thrown when serialization fails
*
* This exception is thrown when an error occurs during the serialization process,
* such as when trying to serialize resources or other non-serializable data.
*/
class SerializeException extends SerializerException
{
}

View File

@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer\Exception;
/**
* Base exception for all serializer-related exceptions
*
* This exception is thrown when an error occurs during serialization or deserialization.
*/
use App\Framework\Exception\FrameworkException;
class SerializerException extends FrameworkException
{
}

View File

@@ -0,0 +1,210 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer\Json;
use App\Framework\Serializer\Exception\DeserializeException;
use App\Framework\Serializer\Exception\SerializeException;
use App\Framework\Serializer\Serializer;
use JsonException;
/**
* JSON serializer implementation
*
* This class provides functionality to serialize and deserialize data to/from JSON format.
* It combines features from both the Cache and Filesystem JsonSerializer implementations.
*
* Robustness and performance optimizations:
* - Uses a hybrid approach for JSON deserialization:
* - For small JSON strings (≤1KB): Direct decoding for better performance
* - For large JSON strings (>1KB): Validation before decoding for better error messages
* - Provides more specific error messages for invalid JSON
* - Handles edge cases like empty strings and deeply nested structures
* - Improves error reporting with detailed validation failures
*/
final readonly class JsonSerializer implements Serializer
{
/**
* Constructor
*
* @param JsonSerializerConfig $config Configuration for the serializer
*/
public function __construct(
private JsonSerializerConfig $config = new JsonSerializerConfig()
) {
}
/**
* {@inheritdoc}
*
* @throws SerializeException If serialization fails
*/
public function serialize(mixed $data): string
{
try {
// Memory protection for serialization too
$memoryUsage = memory_get_usage(true);
$memoryLimit = $this->parseMemoryLimit();
if ($memoryUsage > ($memoryLimit * 0.6)) {
// Log what we're trying to serialize when memory is high
error_log("HIGH MEMORY WARNING during JSON serialization: " .
round($memoryUsage / 1024 / 1024, 2) . "MB used. " .
"Data type: " . gettype($data));
// For arrays, log the size
if (is_array($data)) {
error_log("Array size: " . count($data) . " elements");
error_log("Array keys: " . implode(', ', array_keys($data)));
}
throw new SerializeException(
"Cannot serialize data - memory usage too high: " .
round($memoryUsage / 1024 / 1024, 2) . "MB used of " .
round($memoryLimit / 1024 / 1024, 2) . "MB limit"
);
}
$json = json_encode($data, $this->config->flags | JSON_THROW_ON_ERROR, $this->config->depth);
if ($json === false) {
// This should never happen with JSON_THROW_ON_ERROR, but just in case
throw new SerializeException('Failed to encode JSON: ' . json_last_error_msg());
}
// Log large serializations
$jsonSize = strlen($json);
if ($jsonSize > 100 * 1024) { // >100KB
error_log("Large JSON serialization: " . round($jsonSize / 1024, 2) . "KB");
}
return $json;
} catch (JsonException $e) {
throw new SerializeException('Failed to encode JSON: ' . $e->getMessage(), 0, $e);
}
}
/**
* {@inheritdoc}
*
* Hybrid approach for optimal performance and robustness:
* - For small JSON strings (≤1KB): Uses direct decoding for better performance
* - For large JSON strings (>1KB): Uses validation before decoding for better error messages
* - Memory protection for very large JSON strings (>100KB)
*
* This approach balances performance and robustness:
* - Small strings benefit from faster direct decoding
* - Large, complex strings benefit from better error reporting
* - All inputs get appropriate exception handling
* - Very large strings get memory protection
*
* @throws DeserializeException If JSON validation or deserialization fails
*/
public function deserialize(string $data): mixed
{
if (empty($data)) {
return null;
}
$dataSize = strlen($data);
// EMERGENCY: Ultra-strict memory limits to prevent 512MB exhaustion
if ($dataSize > 1024) { // >1KB - very strict now
// Force garbage collection before processing any JSON >1KB
gc_collect_cycles();
// Check available memory
$memoryUsage = memory_get_usage(true);
$memoryLimit = $this->parseMemoryLimit();
// Emergency: If we're using >200MB, refuse any JSON processing
if ($memoryUsage > 200 * 1024 * 1024) {
throw new DeserializeException(
"EMERGENCY: Cannot deserialize JSON - memory usage critical: " .
round($memoryUsage / 1024 / 1024, 2) . "MB used"
);
}
// Emergency: JSON >5KB is forbidden when memory >100MB
if ($dataSize > 5 * 1024 && $memoryUsage > 100 * 1024 * 1024) {
throw new DeserializeException(
"EMERGENCY: Cannot deserialize JSON ({$dataSize} bytes) - memory usage too high: " .
round($memoryUsage / 1024 / 1024, 2) . "MB used"
);
}
// Emergency: JSON >20KB is completely forbidden
if ($dataSize > 20 * 1024) {
throw new DeserializeException(
"EMERGENCY: JSON too large ({$dataSize} bytes) - maximum 20KB allowed"
);
}
}
// For large JSON strings (>1KB), validate first for better error messages
// For small strings, decode directly for better performance
if ($dataSize > 1024) {
// Validate JSON before decoding for better error messages
if (! json_validate($data, JSON_THROW_ON_ERROR)) {
// This should never happen with JSON_THROW_ON_ERROR, but just in case
throw new DeserializeException('Invalid JSON: ' . json_last_error_msg());
}
}
try {
$startMemory = memory_get_usage(true);
$result = json_decode($data, true, $this->config->depth, JSON_THROW_ON_ERROR);
$endMemory = memory_get_usage(true);
// Log memory usage for large deserializations
if ($dataSize > 10 * 1024) { // >10KB
$memoryUsed = $endMemory - $startMemory;
if ($memoryUsed > 5 * 1024 * 1024) { // >5MB memory growth
error_log("Large JSON deserialization: {$dataSize} bytes JSON used {$memoryUsed} bytes memory");
}
}
return $result;
} catch (JsonException $e) {
throw new DeserializeException('Failed to decode JSON: ' . $e->getMessage(), 0, $e);
}
}
/**
* Parse memory_limit ini setting to bytes
*/
private function parseMemoryLimit(): int
{
$memoryLimit = ini_get('memory_limit');
if ($memoryLimit === '-1') {
return PHP_INT_MAX; // No limit
}
$value = (int) $memoryLimit;
$unit = strtolower(substr($memoryLimit, -1));
return match($unit) {
'g' => $value * 1024 * 1024 * 1024,
'm' => $value * 1024 * 1024,
'k' => $value * 1024,
default => $value
};
}
/**
* {@inheritdoc}
*/
public function getMimeType(): string
{
return 'application/json';
}
/**
* {@inheritdoc}
*/
public function getFileExtension(): string
{
return 'json';
}
}

View File

@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer\Json;
/**
* Configuration for JSON serializer
*
* This class encapsulates the configuration options for the JSON serializer.
*/
final readonly class JsonSerializerConfig
{
/**
* Constructor
*
* @param int $flags JSON encoding flags
* @param int $depth Maximum depth for encoding/decoding
*/
public function __construct(
public int $flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
public int $depth = 512
) {
}
/**
* Creates a config with compact formatting (no pretty printing)
*
* @return self
*/
public static function compact(): self
{
return new self(JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
/**
* Creates a config with pretty printing enabled
*
* @return self
*/
public static function pretty(): self
{
return new self(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
/**
* Creates a config with minimal options (no special flags)
*
* @return self
*/
public static function minimal(): self
{
return new self(0);
}
}

View File

@@ -0,0 +1,144 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer\Php;
use App\Framework\Serializer\Exception\DeserializeException;
use App\Framework\Serializer\Exception\SerializeException;
use App\Framework\Serializer\Serializer;
/**
* PHP serializer implementation
*
* This class provides functionality to serialize and deserialize data using PHP's native
* serialization functions. It includes security features to control which classes can be
* unserialized, helping to prevent PHP object injection vulnerabilities.
*/
final readonly class PhpSerializer implements Serializer
{
/**
* Constructor
*
* @param PhpSerializerConfig $config Configuration for the serializer
*/
public function __construct(
private PhpSerializerConfig $config = new PhpSerializerConfig()
) {
}
/**
* {@inheritdoc}
*
* @throws SerializeException If serialization fails or if data contains resources
*/
public function serialize(mixed $data): string
{
// Check for resources in the data
if ($this->containsResource($data)) {
throw new SerializeException('Failed to serialize data: Resources cannot be serialized');
}
try {
return serialize($data);
} catch (\Exception $e) {
throw new SerializeException('Failed to serialize data: ' . $e->getMessage(), 0, $e);
}
}
/**
* Checks if the data contains any resources
*
* @param mixed $data The data to check
* @return bool True if the data contains resources, false otherwise
*/
private function containsResource(mixed $data): bool
{
if (is_resource($data)) {
return true;
}
if (is_array($data)) {
if (array_any($data, fn ($value) => $this->containsResource($value))) {
return true;
}
}
if (is_object($data)) {
if (array_any(get_object_vars($data), fn ($value) => $this->containsResource($value))) {
return true;
}
}
return false;
}
/**
* {@inheritdoc}
*
* This method uses a custom error handler to catch PHP errors during unserialization
* and convert them to exceptions. The error handler is carefully designed to:
* - Only handle errors from unserialize() to minimize the impact of changing the global error handler
* - Call the previous error handler for other errors
* - Restore the original error handler in both success and error paths
*
* @throws DeserializeException If deserialization fails
*/
public function deserialize(string $data): mixed
{
if (empty($data)) {
return null;
}
// Store the previous error handler so we can restore it later
$previousErrorHandler = set_error_handler(function ($severity, $message, $file, $line) {
// Only handle errors from unserialize() to minimize the impact of changing the global error handler
if (str_contains($message, 'unserialize')) {
throw new \ErrorException($message, 0, $severity, $file, $line);
}
// For other errors, call the previous error handler if it exists
if ($previousErrorHandler = set_error_handler(function () {})) {
restore_error_handler();
call_user_func($previousErrorHandler, $severity, $message, $file, $line);
}
// Otherwise, use the default error handler
return false;
});
try {
$result = unserialize($data, $this->config->getOptions());
// Special case: if unserialize returns false, we need to check if the original data
// was actually serialized false, or if there was an error
if ($result === false && $data !== serialize(false)) {
throw new DeserializeException('Failed to unserialize data');
}
restore_error_handler();
return $result;
} catch (\Throwable $e) {
restore_error_handler();
throw new DeserializeException('Failed to unserialize data: ' . $e->getMessage(), 0, $e);
}
}
/**
* {@inheritdoc}
*/
public function getMimeType(): string
{
return 'application/x-php-serialized';
}
/**
* {@inheritdoc}
*/
public function getFileExtension(): string
{
return 'ser';
}
}

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer\Php;
/**
* Configuration for PHP serializer
*
* This class encapsulates the configuration options for the PHP serializer.
*/
final readonly class PhpSerializerConfig
{
/**
* Constructor
*
* @param bool|array $allowedClasses Controls which classes are allowed to be unserialized.
* If false, no classes are allowed.
* If true, all classes are allowed.
* If array, only the specified classes are allowed.
* @param int $maxDepth Maximum depth of nested objects to deserialize
*/
public function __construct(
public bool|array $allowedClasses = false,
public int $maxDepth = 4096
) {
}
/**
* Creates a config with safe deserialization (only specified classes allowed)
*
* @param array $allowedClasses List of class names that are allowed to be unserialized
* @param int $maxDepth Maximum depth of nested objects to deserialize
* @return self
*/
public static function safe(array $allowedClasses = [], int $maxDepth = 4096): self
{
return new self($allowedClasses, $maxDepth);
}
/**
* Creates a config with unsafe deserialization (all classes allowed)
*
* @param int $maxDepth Maximum depth of nested objects to deserialize
* @return self
*/
public static function unsafe(int $maxDepth = 4096): self
{
return new self(true, $maxDepth);
}
/**
* Returns the options array for use with unserialize()
*
* @return array{allowed_classes: array|bool, max_depth: int} The options array
*/
public function getOptions(): array
{
return [
'allowed_classes' => $this->allowedClasses,
'max_depth' => $this->maxDepth,
];
}
}

View File

@@ -0,0 +1,344 @@
# Serializer Module
The Serializer module provides a unified way to serialize and deserialize data in various formats. It supports JSON and PHP serialization with plans to add more formats in the future.
## Features
- Unified interface for all serializers
- Type-safe serialization and deserialization
- Robust error handling
- Configurable serialization options
- Factory methods for common configurations
## Usage
### Basic Usage
```php
use App\Framework\Serializer\SerializerFactory;
// Create a JSON serializer with default settings (pretty print)
$serializer = SerializerFactory::createJsonSerializer();
// Serialize data
$data = ['name' => 'John', 'age' => 30];
$json = $serializer->serialize($data);
// Deserialize data
$deserializedData = $serializer->deserialize($json);
```
### Serialization Options
The module provides several factory methods for common serialization configurations:
```php
// Pretty-printed JSON (default)
$prettySerializer = SerializerFactory::createPrettyJsonSerializer();
$prettyJson = $prettySerializer->serialize($data);
// Result: {
// "name": "John",
// "age": 30
// }
// Compact JSON (no whitespace)
$compactSerializer = SerializerFactory::createCompactJsonSerializer();
$compactJson = $compactSerializer->serialize($data);
// Result: {"name":"John","age":30}
// Minimal JSON (no special flags)
$minimalSerializer = SerializerFactory::createMinimalJsonSerializer();
$minimalJson = $minimalSerializer->serialize($data);
// Result: {"name":"John","age":30}
```
### Custom Configuration
You can create a serializer with custom configuration:
```php
// Custom JSON serializer with specific flags
$customSerializer = SerializerFactory::createCustomJsonSerializer(
JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE,
256 // Max depth
);
// Serialize an array as an object
$data = ['a', 'b', 'c'];
$json = $customSerializer->serialize($data);
// Result: {"0":"a","1":"b","2":"c"}
```
### Using Config Objects Directly
You can also create and use config objects directly:
```php
use App\Framework\Serializer\Json\JsonSerializer;
use App\Framework\Serializer\Json\JsonSerializerConfig;
// Create a config object
$config = new JsonSerializerConfig(
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES,
512
);
// Create a serializer with the config
$serializer = new JsonSerializer($config);
// Or use the factory methods on the config class
$compactConfig = JsonSerializerConfig::compact();
$prettyConfig = JsonSerializerConfig::pretty();
$minimalConfig = JsonSerializerConfig::minimal();
// Create serializers with these configs
$compactSerializer = new JsonSerializer($compactConfig);
$prettySerializer = new JsonSerializer($prettyConfig);
$minimalSerializer = new JsonSerializer($minimalConfig);
```
### Exception Handling
The serializer module provides a dedicated exception hierarchy for better error handling:
- `SerializerException`: Base exception for all serializer-related exceptions
- `SerializeException`: Thrown when serialization fails
- `DeserializeException`: Thrown when deserialization fails
Example of handling deserialization errors:
```php
use App\Framework\Serializer\SerializerFactory;
use App\Framework\Serializer\Exception\SerializeException;
use App\Framework\Serializer\Exception\DeserializeException;
$serializer = SerializerFactory::createJsonSerializer();
try {
// Try to deserialize invalid JSON
$data = $serializer->deserialize('{"name": "John", }'); // Invalid JSON
} catch (DeserializeException $e) {
// Handle deserialization errors
echo "Deserialization error: " . $e->getMessage();
} catch (SerializeException $e) {
// Handle serialization errors
echo "Serialization error: " . $e->getMessage();
} catch (SerializerException $e) {
// Handle other serializer-related errors
echo "Serializer error: " . $e->getMessage();
}
```
### MIME Type and File Extension
The serializer provides methods to get the MIME type and file extension:
```php
$serializer = SerializerFactory::createJsonSerializer();
// Get MIME type
$mimeType = $serializer->getMimeType(); // "application/json"
// Get file extension
$extension = $serializer->getFileExtension(); // "json"
```
## Migration from Legacy Serializers
If you're using the legacy serializers, here's how to migrate:
### From Cache JsonSerializer
```php
// Old code
use App\Framework\Cache\Serializer\JsonSerializer;
$serializer = new JsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->unserialize($json);
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createJsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->deserialize($json);
```
### From Filesystem JsonSerializer
```php
// Old code
use App\Framework\Filesystem\Serializers\JsonSerializer;
$serializer = new JsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->deserialize($json);
// Factory methods
$compactSerializer = JsonSerializer::compact();
$prettySerializer = JsonSerializer::pretty();
$minimalSerializer = JsonSerializer::minimal();
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createJsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->deserialize($json);
// Factory methods
$compactSerializer = SerializerFactory::createCompactJsonSerializer();
$prettySerializer = SerializerFactory::createPrettyJsonSerializer();
$minimalSerializer = SerializerFactory::createMinimalJsonSerializer();
```
## Direct Usage of JsonSerializer
If you need direct access to the JsonSerializer class:
```php
use App\Framework\Serializer\Json\JsonSerializer;
// Create with default settings
$serializer = new JsonSerializer();
// Create with custom settings
$serializer = new JsonSerializer(
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES,
512
);
// Use factory methods
$compactSerializer = JsonSerializer::compact();
$prettySerializer = JsonSerializer::pretty();
$minimalSerializer = JsonSerializer::minimal();
```
## PHP Serialization
The module also provides PHP serialization capabilities with a focus on security.
### Basic Usage
```php
use App\Framework\Serializer\SerializerFactory;
// Create a PHP serializer with default settings (safe with no allowed classes)
$serializer = SerializerFactory::createPhpSerializer();
// Serialize data
$data = ['name' => 'John', 'age' => 30];
$serialized = $serializer->serialize($data);
// Deserialize data
$deserializedData = $serializer->deserialize($serialized);
```
### Security Considerations
PHP serialization can be a security risk if used improperly, as it allows arbitrary code execution through object deserialization. The PHP serializer in this module is designed with security in mind:
- By default, no classes are allowed to be unserialized (only primitive types and arrays)
- You can explicitly specify which classes are allowed to be unserialized
- You can create an unsafe serializer if you need to deserialize any class (use with caution)
### Safe and Unsafe Deserialization
```php
use App\Framework\Serializer\SerializerFactory;
// Safe serializer with specific allowed classes
$safeSerializer = SerializerFactory::createSafePhpSerializer(['stdClass', 'DateTime']);
// Unsafe serializer (allows all classes - use with caution)
$unsafeSerializer = SerializerFactory::createUnsafePhpSerializer();
```
### Custom Configuration
You can create a serializer with custom options:
```php
use App\Framework\Serializer\SerializerFactory;
// Custom PHP serializer with specific allowed classes and max depth
$customSerializer = SerializerFactory::createCustomPhpSerializer(
['MyClass', 'MyOtherClass'], // allowed classes
4096 // max depth (optional, defaults to 4096)
);
```
### Using PhpSerializer with Config Objects
You can create and use PHP serializer config objects directly:
```php
use App\Framework\Serializer\Php\PhpSerializer;
use App\Framework\Serializer\Php\PhpSerializerConfig;
// Create with default settings (safe with no allowed classes)
$serializer = new PhpSerializer();
// Create a config object with custom options
$config = new PhpSerializerConfig(
['MyClass'], // allowed classes
4096 // max depth (optional, defaults to 4096)
);
// Create a serializer with the config
$serializer = new PhpSerializer($config);
// Or use the factory methods on the config class
$safeConfig = PhpSerializerConfig::safe(
['stdClass'], // allowed classes
4096 // max depth (optional, defaults to 4096)
);
$unsafeConfig = PhpSerializerConfig::unsafe(
4096 // max depth (optional, defaults to 4096)
);
// Create serializers with these configs
$safeSerializer = new PhpSerializer($safeConfig);
$unsafeSerializer = new PhpSerializer($unsafeConfig);
```
### Migration from Legacy PHP Serializers
If you're using the legacy PHP serializers, here's how to migrate:
#### From Cache PhpSerializer
```php
// Old code
use App\Framework\Cache\Serializer\PhpSerializer;
$serializer = new PhpSerializer();
$serialized = $serializer->serialize($data);
$data = $serializer->unserialize($serialized);
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createUnsafePhpSerializer(); // For backward compatibility
$serialized = $serializer->serialize($data);
$data = $serializer->deserialize($serialized);
```
#### From Filesystem PhpSerializer
```php
// Old code
use App\Framework\Filesystem\Serializers\PhpSerializer;
$serializer = new PhpSerializer();
$serialized = $serializer->serialize($data);
$data = $serializer->deserialize($data);
// Factory methods
$safeSerializer = PhpSerializer::safe(['stdClass']);
$unsafeSerializer = PhpSerializer::unsafe();
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createPhpSerializer();
$serialized = $serializer->serialize($data);
$data = $serializer->deserialize($serialized);
// Factory methods
$safeSerializer = SerializerFactory::createSafePhpSerializer(['stdClass']);
$unsafeSerializer = SerializerFactory::createUnsafePhpSerializer();
```

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer;
/**
* Base interface for all serializers
*
* This interface defines the core functionality that all serializers must implement.
* It combines the essential methods from both the Cache and Filesystem serializer interfaces.
*/
interface Serializer
{
/**
* Serializes data to a string representation
*
* @param mixed $data The data to serialize
* @return string The serialized data as a string
* @throws \App\Framework\Serializer\Exception\SerializeException If serialization fails
*/
public function serialize(mixed $data): string;
/**
* Deserializes a string representation back to data
*
* @param string $data The string to deserialize
* @return mixed The deserialized data
* @throws \App\Framework\Serializer\Exception\DeserializeException If deserialization fails
*/
public function deserialize(string $data): mixed;
/**
* Returns the MIME type for the serialized data
*
* @return string The MIME type
*/
public function getMimeType(): string;
/**
* Returns the standard file extension for the serialized data
*
* @return string The file extension without the leading dot
*/
public function getFileExtension(): string;
}

View File

@@ -0,0 +1,113 @@
<?php
declare(strict_types=1);
namespace App\Framework\Serializer;
use App\Framework\Serializer\Json\JsonSerializer;
use App\Framework\Serializer\Json\JsonSerializerConfig;
use App\Framework\Serializer\Php\PhpSerializer;
use App\Framework\Serializer\Php\PhpSerializerConfig;
/**
* Factory for creating serializer instances
*
* This class provides methods for creating various serializer instances.
*/
final class SerializerFactory
{
/**
* Creates a JSON serializer with default settings
*
* @return Serializer
*/
public static function createJsonSerializer(): Serializer
{
return new JsonSerializer();
}
/**
* Creates a JSON serializer with pretty printing
*
* @return Serializer
*/
public static function createPrettyJsonSerializer(): Serializer
{
return new JsonSerializer(JsonSerializerConfig::pretty());
}
/**
* Creates a JSON serializer with compact output
*
* @return Serializer
*/
public static function createCompactJsonSerializer(): Serializer
{
return new JsonSerializer(JsonSerializerConfig::compact());
}
/**
* Creates a JSON serializer with minimal settings
*
* @return Serializer
*/
public static function createMinimalJsonSerializer(): Serializer
{
return new JsonSerializer(JsonSerializerConfig::minimal());
}
/**
* Creates a JSON serializer with custom settings
*
* @param int $flags JSON encoding flags
* @param int $depth Maximum depth for encoding/decoding
* @return Serializer
*/
public static function createCustomJsonSerializer(int $flags, int $depth = 512): Serializer
{
return new JsonSerializer(new JsonSerializerConfig($flags, $depth));
}
/**
* Creates a PHP serializer with default settings (safe with no allowed classes)
*
* @return Serializer
*/
public static function createPhpSerializer(): Serializer
{
return new PhpSerializer();
}
/**
* Creates a PHP serializer with safe deserialization (only specified classes allowed)
*
* @param array $allowedClasses List of class names that are allowed to be unserialized
* @return Serializer
*/
public static function createSafePhpSerializer(array $allowedClasses = []): Serializer
{
return new PhpSerializer(PhpSerializerConfig::safe($allowedClasses));
}
/**
* Creates a PHP serializer with unsafe deserialization (all classes allowed)
*
* @return Serializer
*/
public static function createUnsafePhpSerializer(): Serializer
{
return new PhpSerializer(PhpSerializerConfig::unsafe());
}
/**
* Creates a PHP serializer with custom options
*
* @param bool|array $allowedClasses Controls which classes are allowed to be unserialized
* @param int $maxDepth Maximum depth of nested objects to deserialize
* @return Serializer
*/
public static function createCustomPhpSerializer(bool|array $allowedClasses, int $maxDepth = 4096): Serializer
{
return new PhpSerializer(new PhpSerializerConfig($allowedClasses, $maxDepth));
}
}