Skip to content
This repository was archived by the owner on Dec 11, 2025. It is now read-only.

Commit d7e8f5e

Browse files
feat: Add custom signature option
1 parent 824b0ee commit d7e8f5e

File tree

11 files changed

+339
-362
lines changed

11 files changed

+339
-362
lines changed

composer.json

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,63 @@
11
{
2-
"name": "fostercommerce/imgproxy",
3-
"description": "A PHP library for generating imgproxy URLs with processing options.",
4-
"type": "library",
5-
"version": "0.1.0",
6-
"keywords": [
7-
"imgproxy",
8-
"php",
9-
"library",
10-
"image",
11-
"processing"
12-
],
13-
"license": "MIT",
14-
"authors": [
15-
{
16-
"name": "Foster Commerce",
17-
"homepage": "https://www.fostercommerce.com"
18-
}
19-
],
20-
"support": {
21-
"email": "support@fostercomerce.com",
22-
"issues": "https://github.com/fostercommerce/imgproxy-php/issues?state=open",
23-
"source": "https://github.com/fostercommerce/imgproxy-php",
24-
"docs": "https://github.com/fostercommerce/imgproxy-php/blob/develop/README.md"
25-
},
26-
"require": {
27-
"php": ">=8.2.0"
28-
},
29-
"require-dev": {
30-
"fostercommerce/ecs": "dev-main",
31-
"fostercommerce/rector": "dev-main",
32-
"pestphp/pest": "^3.8",
33-
"phpstan/phpstan": "^1.12"
34-
},
35-
"autoload": {
36-
"psr-4": {
37-
"fostercommerce\\imgproxy\\": "src/"
38-
}
39-
},
40-
"autoload-dev": {
41-
"psr-4": {
42-
"fostercommerce\\imgproxy\\tests\\": "tests/"
43-
}
44-
},
45-
"config": {
46-
"sort-packages": true,
47-
"allow-plugins": {
48-
"yiisoft/yii2-composer": true,
49-
"craftcms/plugin-installer": true,
50-
"pestphp/pest-plugin": true
51-
}
52-
},
53-
"prefer-stable": true,
54-
"minimum-stability": "dev",
55-
"scripts": {
56-
"phpstan": "phpstan --memory-limit=1G",
57-
"ecs:check": "ecs check --ansi --memory-limit=1G",
58-
"ecs:fix": "ecs check --ansi --fix --memory-limit=1G",
59-
"rector:fix": "rector process --config rector.php",
60-
"rector:dry-run": "rector process --dry-run --config rector.php",
61-
"test": "pest"
62-
}
63-
}
2+
"name": "fostercommerce/imgproxy",
3+
"description": "A PHP library for generating imgproxy URLs with processing options.",
4+
"type": "library",
5+
"version": "1.0.0",
6+
"keywords": [
7+
"imgproxy",
8+
"php",
9+
"library",
10+
"image",
11+
"processing"
12+
],
13+
"license": "MIT",
14+
"authors": [
15+
{
16+
"name": "Foster Commerce",
17+
"homepage": "https://www.fostercommerce.com"
18+
}
19+
],
20+
"support": {
21+
"email": "support@fostercomerce.com",
22+
"issues": "https://github.com/fostercommerce/imgproxy-php/issues?state=open",
23+
"source": "https://github.com/fostercommerce/imgproxy-php",
24+
"docs": "https://github.com/fostercommerce/imgproxy-php/blob/develop/README.md"
25+
},
26+
"require": {
27+
"php": ">=8.2.0"
28+
},
29+
"require-dev": {
30+
"fostercommerce/ecs": "dev-main",
31+
"fostercommerce/rector": "dev-main",
32+
"pestphp/pest": "^3.8",
33+
"phpstan/phpstan": "^1.12"
34+
},
35+
"autoload": {
36+
"psr-4": {
37+
"fostercommerce\\imgproxy\\": "src/"
38+
}
39+
},
40+
"autoload-dev": {
41+
"psr-4": {
42+
"fostercommerce\\imgproxy\\tests\\": "tests/"
43+
}
44+
},
45+
"config": {
46+
"sort-packages": true,
47+
"allow-plugins": {
48+
"yiisoft/yii2-composer": true,
49+
"craftcms/plugin-installer": true,
50+
"pestphp/pest-plugin": true
51+
}
52+
},
53+
"prefer-stable": true,
54+
"minimum-stability": "dev",
55+
"scripts": {
56+
"phpstan": "phpstan --memory-limit=1G",
57+
"ecs:check": "ecs check --ansi --memory-limit=1G",
58+
"ecs:fix": "ecs check --ansi --fix --memory-limit=1G",
59+
"rector:fix": "rector process --config rector.php",
60+
"rector:dry-run": "rector process --dry-run --config rector.php",
61+
"test": "pest"
62+
}
63+
}

ecs.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
return ECSConfig::configure()
88
->withPaths([
99
__DIR__ . '/src',
10+
__DIR__ . '/tests',
1011
__FILE__,
1112
]);

phpstan.neon

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
parameters:
2-
paths:
3-
- src
4-
level: 9
2+
paths:
3+
- src
4+
level: 9

phpunit.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
<testsuite name="Unit">
99
<directory>tests/Unit</directory>
1010
</testsuite>
11-
<testsuite name="Feature">
12-
<directory>tests/Feature</directory>
13-
</testsuite>
1411
</testsuites>
1512
<source>
1613
<include>

rector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
return RectorConfig::configure()
77
->withPaths([
88
__DIR__ . '/src',
9+
__DIR__ . '/tests',
910
__FILE__,
1011
]);

src/UrlBuilder.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,20 @@ class UrlBuilder
1414
* @param string|null $key Key for signing URLs
1515
* @param string|null $salt Salt for signing URLs
1616
* @param bool $encode Whether to base64 encode source URLs
17+
* @param string|null $customSignature Custom signature to use if key and salt are not provided
1718
*/
1819
public function __construct(
1920
string $baseUrl,
2021
protected ?string $key = null,
2122
protected ?string $salt = null,
22-
protected bool $encode = true
23+
protected bool $encode = true,
24+
protected ?string $customSignature = null,
2325
) {
2426
$this->baseUrl = rtrim($baseUrl, '/');
2527
}
2628

2729
/**
28-
* Build URL for processing an image
30+
* Build the URL for processing an image
2931
*
3032
* @param string $sourceUrl The source image URL
3133
* @param Options|null $options Processing options
@@ -38,7 +40,7 @@ public function buildUrl(string $sourceUrl, ?Options $options = null, ?string $e
3840
$optionsString = (string) $options;
3941

4042
// Prepare path to be signed
41-
$path = '/' . $optionsString;
43+
$path = $optionsString === '' ? '' : '/' . $optionsString;
4244

4345
if ($this->encode) {
4446
// Base64 encode the source URL
@@ -63,7 +65,7 @@ public function buildUrl(string $sourceUrl, ?Options $options = null, ?string $e
6365
}
6466

6567
// Generate signature if key and salt are provided
66-
$signature = $this->key && $this->salt ? $this->generateSignature($path) : 'unsafe';
68+
$signature = $this->key && $this->salt ? $this->generateSignature($path) : ($this->customSignature ?? 'unsafe');
6769

6870
return $this->baseUrl . '/' . $signature . $path;
6971
}

tests/Feature/.gitkeep

Whitespace-only changes.

tests/Pest.php

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,5 @@
11
<?php
22

3-
/*
4-
|--------------------------------------------------------------------------
5-
| Test Case
6-
|--------------------------------------------------------------------------
7-
|
8-
| The closure you provide to your test functions is always bound to a specific PHPUnit test
9-
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
10-
| need to change it using the "uses()" function to bind a different classes or traits.
11-
|
12-
*/
13-
14-
// uses(Tests\TestCase::class)->in('Feature');
15-
163
/*
174
|--------------------------------------------------------------------------
185
| Expectations
@@ -24,38 +11,34 @@
2411
|
2512
*/
2613

27-
expect()->extend('toBeOptions', function () {
28-
return $this->toBeInstanceOf(\fostercommerce\imgproxy\Options::class);
29-
});
14+
expect()->extend('toBeOptions', fn () => $this->toBeInstanceOf(\fostercommerce\imgproxy\Options::class));
3015

31-
expect()->extend('toBeUrlBuilder', function () {
32-
return $this->toBeInstanceOf(\fostercommerce\imgproxy\UrlBuilder::class);
33-
});
16+
expect()->extend('toBeUrlBuilder', fn () => $this->toBeInstanceOf(\fostercommerce\imgproxy\UrlBuilder::class));
3417

3518
expect()->extend('toMatchSignedImgproxyUrl', function (string $baseUrl, string $optionsPattern, string $sourceUrl) {
36-
// Escape special regex characters in the baseUrl and sourceUrl
37-
$baseUrlEscaped = preg_quote($baseUrl, '~');
38-
$sourceUrlEscaped = preg_quote($sourceUrl, '~');
19+
// Escape special regex characters in the baseUrl and sourceUrl
20+
$baseUrlEscaped = preg_quote($baseUrl, '~');
21+
$sourceUrlEscaped = preg_quote($sourceUrl, '~');
3922

40-
// Create the pattern with optional extension
41-
$pattern = "~^{$baseUrlEscaped}/([A-Za-z0-9_-]+)/{$optionsPattern}/plain/{$sourceUrlEscaped}(@[a-z0-9]+)?$~";
23+
// Create the pattern with optional extension
24+
$pattern = "~^{$baseUrlEscaped}/([A-Za-z0-9_-]+)/{$optionsPattern}/plain/{$sourceUrlEscaped}(@[a-z0-9]+)?$~";
4225

43-
return $this->toMatch($pattern);
26+
return $this->toMatch($pattern);
4427
});
4528

4629
expect()->extend('toMatchSignedBase64ImgproxyUrl', function (string $baseUrl, string $optionsPattern, string $sourceUrl, ?string $extension = null) {
47-
// Escape special regex characters in the baseUrl
48-
$baseUrlEscaped = preg_quote($baseUrl, '~');
30+
// Escape special regex characters in the baseUrl
31+
$baseUrlEscaped = preg_quote($baseUrl, '~');
4932

50-
// Generate the base64 encoded source URL
51-
$encodedUrl = rtrim(strtr(base64_encode($sourceUrl), '+/', '-_'), '=');
52-
$encodedUrlEscaped = preg_quote($encodedUrl, '~');
33+
// Generate the base64 encoded source URL
34+
$encodedUrl = rtrim(strtr(base64_encode($sourceUrl), '+/', '-_'), '=');
35+
$encodedUrlEscaped = preg_quote($encodedUrl, '~');
5336

54-
// Create the pattern with optional extension
55-
$extensionPattern = $extension ? preg_quote('.' . $extension, '~') : '(\\.[a-z0-9]+)?';
56-
$pattern = "~^{$baseUrlEscaped}/([A-Za-z0-9_-]+)/{$optionsPattern}/{$encodedUrlEscaped}{$extensionPattern}$~";
37+
// Create the pattern with optional extension
38+
$extensionPattern = $extension !== null ? preg_quote('.' . $extension, '~') : '(\\.[a-z0-9]+)?';
39+
$pattern = "~^{$baseUrlEscaped}/([A-Za-z0-9_-]+)/{$optionsPattern}/{$encodedUrlEscaped}{$extensionPattern}$~";
5740

58-
return $this->toMatch($pattern);
41+
return $this->toMatch($pattern);
5942
});
6043

6144
/*
@@ -71,10 +54,10 @@
7154

7255
function createOptions(array $options = []): \fostercommerce\imgproxy\Options
7356
{
74-
return new \fostercommerce\imgproxy\Options($options);
57+
return new \fostercommerce\imgproxy\Options($options);
7558
}
7659

77-
function createUrlBuilder(string $baseUrl = 'https://imgproxy.example.com', ?string $key = null, ?string $salt = null, bool $encode = false): \fostercommerce\imgproxy\UrlBuilder
60+
function createUrlBuilder(string $baseUrl = 'https://imgproxy.example.com', ?string $key = null, ?string $salt = null, bool $encode = false, ?string $customSignature = null): \fostercommerce\imgproxy\UrlBuilder
7861
{
79-
return new \fostercommerce\imgproxy\UrlBuilder($baseUrl, $key, $salt, $encode);
62+
return new \fostercommerce\imgproxy\UrlBuilder($baseUrl, $key, $salt, $encode, $customSignature);
8063
}

tests/TestCase.php

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)