feat: encode images to webp for telegram mini app

This commit is contained in:
Nikita Kiselev
2025-07-20 23:35:30 +03:00
parent db24be6f92
commit c282b6ea3b
9 changed files with 445 additions and 56 deletions

View File

@@ -1,10 +1,11 @@
<?php
use App\Adapters\OcImageTool;
use App\Adapters\OcModelCatalogProductAdapter;
use App\ApplicationFactory;
use Cart\Currency;
use Cart\Tax;
use Openguru\OpenCartFramework\ImageTool\ImageTool;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
$sysLibPath = rtrim(DIR_SYSTEM, '/') . '/library/oc_telegram_shop';
$basePath = rtrim(DIR_APPLICATION, '/') . '/..';
@@ -55,9 +56,8 @@ class Controllerextensiontgshophandle extends Controller
return new OcModelCatalogProductAdapter($this->model_catalog_product);
});
$app->bind(OcImageTool::class, function () {
$this->load->model('tool/image');
return new OcImageTool($this->model_tool_image);
$app->bind(ImageToolInterface::class, function () {
return new ImageTool(DIR_IMAGE);
});
$this->load->model('checkout/order');

View File

@@ -19,7 +19,8 @@
"php": "^7.4",
"ext-pdo": "*",
"psr/container": "^2.0",
"ext-json": "*"
"ext-json": "*",
"intervention/image": "^2.7"
},
"require-dev": {
"roave/security-advisories": "dev-latest"

View File

@@ -4,8 +4,208 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "775a9a548899d07b9c007ecf3afe4e44",
"content-hash": "4c731e75f55435f8b300c557fdfabfed",
"packages": [
{
"name": "guzzlehttp/psr7",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16",
"reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0"
},
"provide": {
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "0.9.0",
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.7.1"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
"type": "tidelift"
}
],
"time": "2025-03-27T12:30:47+00:00"
},
{
"name": "intervention/image",
"version": "2.7.2",
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
"reference": "04be355f8d6734c826045d02a1079ad658322dad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad",
"reference": "04be355f8d6734c826045d02a1079ad658322dad",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"guzzlehttp/psr7": "~1.1 || ^2.0",
"php": ">=5.4.0"
},
"require-dev": {
"mockery/mockery": "~0.9.2",
"phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15"
},
"suggest": {
"ext-gd": "to use GD library based image processing.",
"ext-imagick": "to use Imagick based image processing.",
"intervention/imagecache": "Caching extension for the Intervention Image library"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Image": "Intervention\\Image\\Facades\\Image"
},
"providers": [
"Intervention\\Image\\ImageServiceProvider"
]
},
"branch-alias": {
"dev-master": "2.4-dev"
}
},
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src/Intervention/Image"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@intervention.io",
"homepage": "https://intervention.io/"
}
],
"description": "Image handling and manipulation library with support for Laravel integration",
"homepage": "http://image.intervention.io/",
"keywords": [
"gd",
"image",
"imagick",
"laravel",
"thumbnail",
"watermark"
],
"support": {
"issues": "https://github.com/Intervention/image/issues",
"source": "https://github.com/Intervention/image/tree/2.7.2"
},
"funding": [
{
"url": "https://paypal.me/interventionio",
"type": "custom"
},
{
"url": "https://github.com/Intervention",
"type": "github"
}
],
"time": "2022-05-21T17:30:32+00:00"
},
{
"name": "psr/container",
"version": "2.0.2",
@@ -58,6 +258,158 @@
"source": "https://github.com/php-fig/container/tree/2.0.2"
},
"time": "2021-11-05T16:47:00+00:00"
},
{
"name": "psr/http-factory",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"shasum": ""
},
"require": {
"php": ">=7.1",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory"
},
"time": "2024-04-15T12:06:14+00:00"
},
{
"name": "psr/http-message",
"version": "2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/2.0"
},
"time": "2023-04-04T09:54:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"support": {
"issues": "https://github.com/ralouphie/getallheaders/issues",
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
"time": "2019-03-08T08:55:37+00:00"
}
],
"packages-dev": [
@@ -1026,7 +1378,8 @@
"prefer-lowest": false,
"platform": {
"php": "^7.4",
"ext-pdo": "*"
"ext-pdo": "*",
"ext-json": "*"
},
"platform-dev": [],
"plugin-api-version": "2.6.0"

View File

@@ -0,0 +1,57 @@
<?php
namespace Openguru\OpenCartFramework\ImageTool;
use Intervention\Image\ImageManager;
class ImageTool implements ImageToolInterface
{
private string $imageDir;
private string $siteUrl;
private ImageManager $manager;
public function __construct(string $imageDir, string $siteUrl = '/')
{
$this->imageDir = rtrim($imageDir, '/') . '/';
$this->siteUrl = $siteUrl;
$driver = extension_loaded('imagick') ? 'imagick' : 'gd';
$this->manager = new ImageManager(['driver' => $driver]);
}
public function resize(string $path, int $width, int $height, ?string $default = null): ?string
{
$filename = is_file($this->imageDir . $path) ? $path : $default;
if (! $filename || ! is_file($this->imageDir . $filename)) {
return null;
}
$realPath = realpath($this->imageDir . $filename);
if (strpos($realPath, realpath($this->imageDir)) !== 0) {
return null; // безопасность
}
$extless = utf8_substr($filename, 0, utf8_strrpos($filename, '.'));
$imageNew = 'cache/' . $extless . '-' . $width . 'x' . $height . '.webp';
$fullNewPath = $this->imageDir . $imageNew;
$fullOldPath = $this->imageDir . $filename;
if (! is_file($fullNewPath) || filemtime($fullOldPath) > filemtime($fullNewPath)) {
$dirPath = dirname($fullNewPath);
if (! is_dir($dirPath)) {
mkdir($dirPath, 0777, true);
}
$image = $this->manager->make($fullOldPath)->resize($width, $height, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
$image->encode('webp', 75)->save($fullNewPath, 75, 'webp');
}
return rtrim($this->siteUrl, '/') . '/image/' . str_replace($this->imageDir, '', $fullNewPath);
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Openguru\OpenCartFramework\ImageTool;
interface ImageToolInterface
{
public function resize(string $path, int $width, int $height, ?string $default = null): ?string;
}

View File

@@ -1,30 +0,0 @@
<?php
namespace App\Adapters;
use Proxy;
use RuntimeException;
class OcImageTool
{
private Proxy $image;
public function __construct(Proxy $image)
{
$this->image = $image;
}
public function resize(string $path, int $width, int $height, ?string $default = null): ?string
{
if ($path && is_file(DIR_IMAGE . $path)) {
$image = $path;
return $this->image->resize($image, $width, $height);
}
if ($default && is_file(DIR_IMAGE . $default)) {
return $this->image->resize($default, $width, $height);
}
return null;
}
}

View File

@@ -20,7 +20,7 @@ class ApplicationFactory
QueryBuilderServiceProvider::class,
CacheServiceProvider::class,
RouteServiceProvider::class,
AppServiceProvider::class
AppServiceProvider::class,
]);
}
}

View File

@@ -2,18 +2,18 @@
namespace App\Handlers;
use App\Adapters\OcImageTool;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
class CategoriesHandler
{
private Builder $queryBuilder;
private OcImageTool $imageTool;
private ImageToolInterface $ocImageTool;
public function __construct(Builder $queryBuilder, OcImageTool $ocImageTool)
public function __construct(Builder $queryBuilder, ImageToolInterface $ocImageTool)
{
$this->queryBuilder = $queryBuilder;
$this->ocImageTool = $ocImageTool;

View File

@@ -2,7 +2,6 @@
namespace App\Handlers;
use App\Adapters\OcImageTool;
use App\Adapters\OcModelCatalogProductAdapter;
use Cart\Currency;
use Cart\Tax;
@@ -10,6 +9,7 @@ use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
use Openguru\OpenCartFramework\Support\Arr;
@@ -21,7 +21,7 @@ class ProductsHandler
private Tax $tax;
private Settings $settings;
private OcModelCatalogProductAdapter $ocModelCatalogProduct;
private OcImageTool $ocImageTool;
private ImageToolInterface $ocImageTool;
public function __construct(
Builder $queryBuilder,
@@ -29,7 +29,7 @@ class ProductsHandler
Tax $tax,
Settings $settings,
OcModelCatalogProductAdapter $ocModelCatalogProduct,
OcImageTool $ocImageTool
ImageToolInterface $ocImageTool
) {
$this->queryBuilder = $queryBuilder;
$this->currency = $currency;