Skip to content
Closed
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
1 change: 1 addition & 0 deletions app/Config/Mimes.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ class Mimes
'image/x-png',
],
'webp' => 'image/webp',
'avif' => 'image/avif',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'css' => [
Expand Down
2 changes: 1 addition & 1 deletion app/Config/Publisher.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ class Publisher extends BasePublisher
*/
public $restrictions = [
ROOTPATH => '*',
FCPATH => '#\.(s?css|js|map|html?|xml|json|webmanifest|ttf|eot|woff2?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
FCPATH => '#\.(s?css|js|map|html?|xml|json|webmanifest|ttf|eot|woff2?|gif|jpe?g|tiff?|png|webp|avif|bmp|ico|svg)$#i',
];
}
2 changes: 1 addition & 1 deletion system/Config/Publisher.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Publisher extends BaseConfig
*/
public $restrictions = [
ROOTPATH => '*',
FCPATH => '#\.(?css|js|map|htm?|xml|json|webmanifest|tff|eot|woff?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
FCPATH => '#\.(?css|js|map|htm?|xml|json|webmanifest|tff|eot|woff?|gif|jpe?g|tiff?|png|webp|avif|bmp|ico|svg)$#i',
];

/**
Expand Down
3 changes: 2 additions & 1 deletion system/Images/Handlers/BaseHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ abstract class BaseHandler implements ImageHandlerInterface
protected $supportTransparency = [
IMAGETYPE_PNG,
IMAGETYPE_WEBP,
IMAGETYPE_AVIF,
];

/**
Expand Down Expand Up @@ -682,7 +683,7 @@ abstract public function getVersion();
*
* @return bool
*/
abstract public function save(?string $target = null, int $quality = 90);
abstract public function save(?string $target = null, int $quality = 90, int $speed = -1);

/**
* Does the driver-specific processing of the image.
Expand Down
23 changes: 20 additions & 3 deletions system/Images/Handlers/GDHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ protected function process(string $action)

$dest = $create($this->width, $this->height);

// for png and webp we can actually preserve transparency
// for png, webp and avif we can actually preserve transparency
if (in_array($this->image()->imageType, $this->supportTransparency, true)) {
imagealphablending($dest, false);
imagesavealpha($dest, true);
Expand All @@ -202,7 +202,7 @@ protected function process(string $action)
*
* @param non-empty-string|null $target
*/
public function save(?string $target = null, int $quality = 90): bool
public function save(?string $target = null, int $quality = 90, int $speed = -1): bool
{
$original = $target;
$target = ($target === null || $target === '') ? $this->image()->getPathname() : $target;
Expand All @@ -222,7 +222,7 @@ public function save(?string $target = null, int $quality = 90): bool

$this->ensureResource();

// for png and webp we can actually preserve transparency
// for png, webp and avif we can actually preserve transparency
if (in_array($this->image()->imageType, $this->supportTransparency, true)) {
imagepalettetotruecolor($this->resource);
imagealphablending($this->resource, false);
Expand Down Expand Up @@ -270,6 +270,16 @@ public function save(?string $target = null, int $quality = 90): bool
}
break;

case IMAGETYPE_AVIF:
if (! function_exists('imageavif')) {
throw ImageException::forInvalidImageCreate(lang('Images.avifNotSupported'));
}

if (! @imageavif($this->resource, $target, $quality, $speed)) {
throw ImageException::forSaveFailed();
}
break;

default:
throw ImageException::forInvalidImageCreate();
}
Expand Down Expand Up @@ -361,6 +371,13 @@ protected function getImageResource(string $path, int $imageType)

return imagecreatefromwebp($path);

case IMAGETYPE_AVIF:
if (! function_exists('imagecreatefromavif')) {
throw ImageException::forInvalidImageCreate(lang('Images.avifNotSupported'));
}

return imagecreatefromavif($path);

default:
throw ImageException::forInvalidImageCreate('Ima');
}
Expand Down
1 change: 1 addition & 0 deletions system/Images/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public function getProperties(bool $return = false)
IMAGETYPE_JPEG => 'jpeg',
IMAGETYPE_PNG => 'png',
IMAGETYPE_WEBP => 'webp',
IMAGETYPE_AVIF => 'avif',
];

$mime = 'image/' . ($types[$vals[2]] ?? 'jpg');
Expand Down
1 change: 1 addition & 0 deletions system/Language/en/Images.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
'jpgNotSupported' => 'JPG images are not supported.',
'pngNotSupported' => 'PNG images are not supported.',
'webpNotSupported' => 'WEBP images are not supported.',
'avifNotSupported' => 'AVIF images are not supported.',
'fileNotSupported' => 'The supplied file is not a supported image type.',
'unsupportedImageCreate' => 'Your server does not support the required functionality to process this type of image.',
'jpgOrPngRequired' => 'The image resize protocol specified in your preferences only works with JPEG or PNG image types.',
Expand Down
6 changes: 6 additions & 0 deletions tests/system/AutoReview/CreateNewChangelogTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ protected function setUp(): void
#[DataProvider('provideCreateNewChangelog')]
public function testCreateNewChangelog(string $mode): void
{
$output = exec('git status --porcelain | wc -l');

if ($output !== '0') {
$this->markTestSkipped('You have uncommitted operations that will be erased by this test.');
}

$currentVersion = $this->currentVersion;
$newVersion = $this->incrementVersion($currentVersion, $mode);

Expand Down
49 changes: 39 additions & 10 deletions tests/system/Images/GDHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,14 @@ public function testMoreText(): void

public function testImageCreation(): void
{
foreach (['gif', 'jpeg', 'png', 'webp'] as $type) {
foreach (['gif', 'jpeg', 'png', 'webp', 'avif'] as $type) {
if ($type === 'webp' && ! function_exists('imagecreatefromwebp')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
$this->expectExceptionMessage('Your server does not support the GD function required to process a webp image.');
}
if ($type === 'avif' && ! function_exists('imagecreatefromavif')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process an avif image.');
}

$this->handler->withFile($this->origin . 'ci-logo.' . $type);
Expand All @@ -334,10 +338,14 @@ public function testImageCreation(): void

public function testImageCopy(): void
{
foreach (['gif', 'jpeg', 'png', 'webp'] as $type) {
foreach (['gif', 'jpeg', 'png', 'webp', 'avif'] as $type) {
if ($type === 'webp' && ! function_exists('imagecreatefromwebp')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
$this->expectExceptionMessage('Your server does not support the GD function required to process a webp image.');
}
if ($type === 'avif' && ! function_exists('imagecreatefromavif')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process an avif image.');
}

$this->handler->withFile($this->origin . 'ci-logo.' . $type);
Expand All @@ -353,9 +361,13 @@ public function testImageCopy(): void

public function testImageCopyWithNoTargetAndMaxQuality(): void
{
foreach (['gif', 'jpeg', 'png', 'webp'] as $type) {
foreach (['gif', 'jpeg', 'png', 'webp', 'avif'] as $type) {
$this->handler->withFile($this->origin . 'ci-logo.' . $type);
$this->handler->save(null, 100);
if($type === 'avif') {
$this->handler->save(null, 100, 10);
} else {
$this->handler->save(null, 100);
}
$this->assertFileExists($this->origin . 'ci-logo.' . $type);

$this->assertSame(
Expand All @@ -367,10 +379,14 @@ public function testImageCopyWithNoTargetAndMaxQuality(): void

public function testImageCompressionGetResource(): void
{
foreach (['gif', 'jpeg', 'png', 'webp'] as $type) {
foreach (['gif', 'jpeg', 'png', 'webp', 'avif'] as $type) {
if ($type === 'webp' && ! function_exists('imagecreatefromwebp')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
$this->expectExceptionMessage('Your server does not support the GD function required to process a webp image.');
}
if ($type === 'avif' && ! function_exists('imagecreatefromavif')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process an avif image.');
}

$this->handler->withFile($this->origin . 'ci-logo.' . $type);
Expand All @@ -387,10 +403,14 @@ public function testImageCompressionGetResource(): void

public function testImageCompressionWithResource(): void
{
foreach (['gif', 'jpeg', 'png', 'webp'] as $type) {
foreach (['gif', 'jpeg', 'png', 'webp', 'avif'] as $type) {
if ($type === 'webp' && ! function_exists('imagecreatefromwebp')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
$this->expectExceptionMessage('Your server does not support the GD function required to process a webp image.');
}
if ($type === 'avif' && ! function_exists('imagecreatefromavif')) {
$this->expectException(ImageException::class);
$this->expectExceptionMessage('Your server does not support the GD function required to process an avif image.');
}

$this->handler->withFile($this->origin . 'ci-logo.' . $type)
Expand Down Expand Up @@ -423,6 +443,15 @@ public function testImageConvertPngToWebp(): void
$this->assertSame(IMAGETYPE_WEBP, exif_imagetype($saved));
}

public function testImageConvertPngToAvif(): void
{
$this->handler->withFile($this->origin . 'rocket.png');
$this->handler->convert(IMAGETYPE_AVIF);
$saved = $this->start . 'work/rocket.avif';
$this->handler->save($saved);
$this->assertSame(IMAGETYPE_AVIF, exif_imagetype($saved));
}

public function testImageReorientLandscape(): void
{
for ($i = 0; $i <= 8; $i++) {
Expand Down
55 changes: 34 additions & 21 deletions tests/system/Models/UpdateModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use CodeIgniter\Entity\Entity;
use CodeIgniter\Exceptions\InvalidArgumentException;
use Config\Database;
use DateTimeInterface;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
use stdClass;
Expand Down Expand Up @@ -208,13 +209,17 @@ public function testUpdateBatchValidationFail(): void
public function testUpdateBatchWithEntity(): void
{
$entity1 = new class () extends Entity {
protected $id;
protected $name;
protected $email;
protected $country;
protected $deleted;
protected $created_at;
protected $updated_at;
protected int $id;
protected string $name;
protected string $email;
protected string $country;
protected bool $deleted;
protected DateTimeInterface $created_at;
protected DateTimeInterface $updated_at;

/**
* @var array{'datamap': array{}, 'dates': array{string, string, string}, 'casts': array{}}
*/
protected $_options = [
'datamap' => [],
'dates' => [
Expand All @@ -227,13 +232,17 @@ public function testUpdateBatchWithEntity(): void
};

$entity2 = new class () extends Entity {
protected $id;
protected $name;
protected $email;
protected $country;
protected $deleted;
protected $created_at;
protected $updated_at;
protected int $id;
protected string $name;
protected string $email;
protected string $country;
protected bool $deleted;
protected DateTimeInterface $created_at;
protected DateTimeInterface $updated_at;

/**
* @var array{'datamap': array{}, 'dates': array{string, string, string}, 'casts': array{}}
*/
protected $_options = [
'datamap' => [],
'dates' => [
Expand Down Expand Up @@ -399,13 +408,17 @@ public function testUpdateWithEntityNoAllowedFields(): void
$this->createModel(UserModel::class);

$entity = new class () extends Entity {
protected $id;
protected $name;
protected $email;
protected $country;
protected $deleted;
protected $created_at;
protected $updated_at;
protected int $id;
protected string $name;
protected string $email;
protected string $country;
protected bool $deleted;
protected DateTimeInterface $created_at;
protected DateTimeInterface $updated_at;

/**
* @var array{'datamap': array{}, 'dates': array{string, string, string}, 'casts': array{}}
*/
protected $_options = [
'datamap' => [],
'dates' => [
Expand Down
2 changes: 1 addition & 1 deletion user_guide_src/source/database/query_builder.rst
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ searches.
.. literalinclude:: query_builder/039.php

If you want to control where the wildcard (**%**) is placed, you can use
an optional third argument. Your options are ``before``, ``after`` and
an optional third argument. Your options are ``none``, ``before``, ``after`` and
``both`` (which is the default).

.. literalinclude:: query_builder/040.php
Expand Down
1 change: 1 addition & 0 deletions user_guide_src/source/database/query_builder/040.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

$builder->like('title', 'match', 'none'); // Produces: WHERE `title` LIKE 'match' ESCAPE '!'
$builder->like('title', 'match', 'before'); // Produces: WHERE `title` LIKE '%match' ESCAPE '!'
$builder->like('title', 'match', 'after'); // Produces: WHERE `title` LIKE 'match%' ESCAPE '!'
$builder->like('title', 'match', 'both'); // Produces: WHERE `title` LIKE '%match%' ESCAPE '!'
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 2116 errors
# total 2092 errors

includes:
- argument.type.neon
Expand Down
Loading