Skip to content

refactor: fix and micro-optimize code in Format #9583

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion system/Format/Exceptions/FormatException.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static function forInvalidFormatter(string $class)
* Thrown in JSONFormatter when the json_encode produces
* an error code other than JSON_ERROR_NONE and JSON_ERROR_RECURSION.
*
* @param string $error The error message
* @param string|null $error The error message
*
* @return static
*/
Expand Down
13 changes: 1 addition & 12 deletions system/Format/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,8 @@
*/
class Format
{
/**
* Configuration instance
*
* @var FormatConfig
*/
protected $config;

/**
* Constructor.
*/
public function __construct(FormatConfig $config)
public function __construct(protected FormatConfig $config)
{
$this->config = $config;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions system/Format/FormatterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ interface FormatterInterface
/**
* Takes the given data and formats it.
*
* @param array|object|string $data
* @param array<array-key, mixed>|object|string $data
*
* @return false|string
* @return false|non-empty-string
*/
public function format($data);
}
8 changes: 5 additions & 3 deletions system/Format/JSONFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ class JSONFormatter implements FormatterInterface
/**
* Takes the given data and formats it.
*
* @param array|bool|float|int|object|string|null $data
* @param array<array-key, mixed>|object|string $data
*
* @return false|string (JSON string | false)
* @return false|non-empty-string
*/
public function format($data)
{
Expand All @@ -37,7 +37,9 @@ public function format($data)
$options = $config->formatterOptions['application/json'] ?? JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
$options |= JSON_PARTIAL_OUTPUT_ON_ERROR;

$options = ENVIRONMENT === 'production' ? $options : $options | JSON_PRETTY_PRINT;
if (ENVIRONMENT !== 'production') {
$options |= JSON_PRETTY_PRINT;
}

$result = json_encode($data, $options, 512);

Expand Down
7 changes: 4 additions & 3 deletions system/Format/XMLFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ class XMLFormatter implements FormatterInterface
/**
* Takes the given data and formats it.
*
* @param array|bool|float|int|object|string|null $data
* @param array<array-key, mixed>|object|string $data
*
* @return false|string (XML string | false)
* @return false|non-empty-string
*/
public function format($data)
{
Expand All @@ -56,7 +56,8 @@ public function format($data)
*
* @see http://www.codexworld.com/convert-array-to-xml-in-php/
*
* @param SimpleXMLElement $output
* @param array<array-key, mixed> $data
* @param SimpleXMLElement $output
*
* @return void
*/
Expand Down
54 changes: 19 additions & 35 deletions tests/system/Format/JSONFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

namespace CodeIgniter\Format;

use CodeIgniter\Exceptions\RuntimeException;
use CodeIgniter\Format\Exceptions\FormatException;
use CodeIgniter\Test\CIUnitTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;

/**
Expand All @@ -31,51 +32,34 @@ protected function setUp(): void
$this->jsonFormatter = new JSONFormatter();
}

public function testBasicJSON(): void
/**
* @param array<string, string> $data
*/
#[DataProvider('provideFormattingToJson')]
public function testFormattingToJson(array $data, string $expected): void
{
$data = [
'foo' => 'bar',
];

$expected = '{
"foo": "bar"
}';

$this->assertSame($expected, $this->jsonFormatter->format($data));
}

public function testUnicodeOutput(): void
/**
* @return iterable<string, array{0: array<string, string>, 1: string}>
*/
public static function provideFormattingToJson(): iterable
{
$data = [
'foo' => 'База данни грешка',
];
yield 'empty array' => [[], '[]'];

$expected = '{
"foo": "База данни грешка"
}';
yield 'simple array' => [['foo' => 'bar'], "{\n \"foo\": \"bar\"\n}"];

$this->assertSame($expected, $this->jsonFormatter->format($data));
}
yield 'unicode array' => [['foo' => 'База данни грешка'], "{\n \"foo\": \"База данни грешка\"\n}"];

public function testKeepsURLs(): void
{
$data = [
'foo' => 'https://www.example.com/foo/bar',
];

$expected = '{
"foo": "https://www.example.com/foo/bar"
}';

$this->assertSame($expected, $this->jsonFormatter->format($data));
yield 'url array' => [['foo' => 'https://www.example.com/foo/bar'], "{\n \"foo\": \"https://www.example.com/foo/bar\"\n}"];
}

public function testJSONError(): void
public function testJSONFormatterThrowsError(): void
{
$this->expectException(RuntimeException::class);
$this->expectException(FormatException::class);
$this->expectExceptionMessage('Malformed UTF-8 characters, possibly incorrectly encoded');

$data = ["\xB1\x31"];
$expected = 'Boom';
$this->assertSame($expected, $this->jsonFormatter->format($data));
$this->assertSame('Boom', $this->jsonFormatter->format(["\xB1\x31"]));
}
}
6 changes: 6 additions & 0 deletions tests/system/Format/XMLFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ public function testValidatingXmlTags(): void
$this->assertSame($expected, $this->xmlFormatter->format($data));
}

/**
* @param array<string, string> $input
*/
#[DataProvider('provideValidatingInvalidTags')]
public function testValidatingInvalidTags(string $expected, array $input): void
{
Expand All @@ -116,6 +119,9 @@ public function testValidatingInvalidTags(string $expected, array $input): void
$this->assertSame($expectedXML, $this->xmlFormatter->format($input));
}

/**
* @return iterable<int, array{0: string, 1: array<string, string>}>
*/
public static function provideValidatingInvalidTags(): iterable
{
return [
Expand Down
2 changes: 1 addition & 1 deletion utils/phpstan-baseline/loader.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# total 3262 errors
# total 3256 errors
includes:
- argument.type.neon
- assign.propertyType.neon
Expand Down
32 changes: 1 addition & 31 deletions utils/phpstan-baseline/missingType.iterableValue.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# total 1571 errors
# total 1565 errors

parameters:
ignoreErrors:
Expand Down Expand Up @@ -3052,26 +3052,6 @@ parameters:
count: 1
path: ../../system/Filters/PerformanceMetrics.php

-
message: '#^Method CodeIgniter\\Format\\FormatterInterface\:\:format\(\) has parameter \$data with no value type specified in iterable type array\.$#'
count: 1
path: ../../system/Format/FormatterInterface.php

-
message: '#^Method CodeIgniter\\Format\\JSONFormatter\:\:format\(\) has parameter \$data with no value type specified in iterable type array\.$#'
count: 1
path: ../../system/Format/JSONFormatter.php

-
message: '#^Method CodeIgniter\\Format\\XMLFormatter\:\:arrayToXML\(\) has parameter \$data with no value type specified in iterable type array\.$#'
count: 1
path: ../../system/Format/XMLFormatter.php

-
message: '#^Method CodeIgniter\\Format\\XMLFormatter\:\:format\(\) has parameter \$data with no value type specified in iterable type array\.$#'
count: 1
path: ../../system/Format/XMLFormatter.php

-
message: '#^Method CodeIgniter\\HTTP\\CLIRequest\:\:getArgs\(\) return type has no value type specified in iterable type array\.$#'
count: 1
Expand Down Expand Up @@ -6517,16 +6497,6 @@ parameters:
count: 1
path: ../../tests/system/Filters/InvalidCharsTest.php

-
message: '#^Method CodeIgniter\\Format\\XMLFormatterTest\:\:provideValidatingInvalidTags\(\) return type has no value type specified in iterable type iterable\.$#'
count: 1
path: ../../tests/system/Format/XMLFormatterTest.php

-
message: '#^Method CodeIgniter\\Format\\XMLFormatterTest\:\:testValidatingInvalidTags\(\) has parameter \$input with no value type specified in iterable type array\.$#'
count: 1
path: ../../tests/system/Format/XMLFormatterTest.php

-
message: '#^Method CodeIgniter\\HTTP\\IncomingRequestTest\:\:provideCanGrabGetRawInputVar\(\) return type has no value type specified in iterable type iterable\.$#'
count: 1
Expand Down
Loading