fix: isolate PHP-pdftk dependency

I identified some issues with the follow log:

```
[PHP] Warning: include(): Failed opening '<redacted>/apps/richdocuments/vendor/composer/../mikehaertl/php-pdftk/src/Pdf.php' for inclusion (include_path='<redacted>/3rdparty/pear/archive_tar:/<redacted>/3rdparty/pear/console_getopt:<redacted>/3rdparty/pear/pear-core-minimal/src:/<redacted>/3rdparty/pear/pear_exception:/<redacted>/apps') at /<redacted>/lib/composer/composer/ClassLoader.php#576
	GET /ocs/v2.php/apps/libresign/api/v1/file/validate/file_id/2556
```

It's only occurr when use the app richdocuments, I saw that the package
mikehaertl/php-pdftk also is used by this app and because this the
autoload was mixed.

To solve this issue I used the package humbug/php-scoper that isolate
the dependency into a different namespace.

I also followed this article:

https://arthur-schiwon.de/isolating-nextcloud-app-dependencies-php-scoper

And the follow search results to see implementation examples:

https://github.com/search?q=OCA+path%3Ascoper.inc.php&type=code
https://github.com/search?q=org%3Anextcloud+path%3Ascoper.inc.php&type=code

Considering that we already have tests to cover the usage of pdftk,
isn't necessary to add new tests, if the test pass, this change worked
fine because loaded the isolated packages and the isolated packages made
the necessary.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
This commit is contained in:
Vitor Mattos 2025-09-03 09:07:15 -03:00
parent 4d88215054
commit 07a231aea2
No known key found for this signature in database
GPG key ID: 6FECE2AD4809003A
11 changed files with 1654 additions and 64 deletions

1
.gitignore vendored
View file

@ -17,3 +17,4 @@ node_modules/
*.phar
/src/__test__/coverage
/appinfo/install-*.json
/lib/Vendor/

View file

@ -21,5 +21,6 @@ $config
->notPath('src')
->notPath('vendor')
->notPath('vendor-bin')
->notPath('Vendor')
->in(__DIR__);
return $config;

View file

@ -1,5 +1,6 @@
{
"require": {
"bamarni/composer-bin-plugin": "^1.8",
"endroid/qr-code": "^5.0",
"jsignpdf/jsignpdf-php": "^1.2",
"libresign/whatosami": "^0.0.2",
@ -12,7 +13,6 @@
"wobeto/email-blur": "^1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8",
"nextcloud/ocp": "dev-master",
"roave/security-advisories": "dev-latest"
},
@ -38,9 +38,11 @@
"psalm:update-baseline": "psalm --threads=$(nproc) --update-baseline --set-baseline=tests/psalm-baseline.xml",
"post-install-cmd": [
"@composer bin all install --ansi",
"composer dump-autoload"
"php -d error_reporting=E_ALL\\&~E_DEPRECATED\\&~E_USER_DEPRECATED vendor-bin/php-scoper/vendor/humbug/php-scoper/bin/php-scoper add-prefix --force",
"composer dump-autoload -o"
],
"post-update-cmd": [
"php -d error_reporting=E_ALL\\&~E_DEPRECATED\\&~E_USER_DEPRECATED vendor-bin/php-scoper/vendor/humbug/php-scoper/bin/php-scoper add-prefix --force",
"composer dump-autoload"
],
"test:unit": "vendor/bin/phpunit -c tests/php/phpunit.xml --no-coverage --colors=always --fail-on-warning --fail-on-risky --display-deprecations --display-phpunit-deprecations",
@ -54,7 +56,10 @@
},
"autoload": {
"psr-4": {
"OCA\\Libresign\\": "lib/"
"OCA\\Libresign\\": "lib/",
"OCA\\Libresign\\Vendor\\mikehaertl\\pdftk\\": "lib/Vendor/php-pdftk/src/",
"OCA\\Libresign\\Vendor\\mikehaertl\\shellcommand\\": "lib/Vendor/php-shellcommand/src/",
"OCA\\Libresign\\Vendor\\mikehaertl\\tmp\\": "lib/Vendor/php-tmpfile/src/"
}
},
"autoload-dev": {

116
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f56e565d14eb917a9d07179f11b66c7b",
"content-hash": "c0ae632fd27f9e2bd867e714cbd765d7",
"packages": [
{
"name": "bacon/bacon-qr-code",
@ -60,6 +60,63 @@
},
"time": "2024-10-01T13:55:55+00:00"
},
{
"name": "bamarni/composer-bin-plugin",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/bamarni/composer-bin-plugin.git",
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0",
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"composer/composer": "^2.0",
"ext-json": "*",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^8.5 || ^9.5",
"symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
"symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
"symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0"
},
"type": "composer-plugin",
"extra": {
"class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin"
},
"autoload": {
"psr-4": {
"Bamarni\\Composer\\Bin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "No conflicts for your bin dependencies",
"keywords": [
"composer",
"conflict",
"dependency",
"executable",
"isolation",
"tool"
],
"support": {
"issues": "https://github.com/bamarni/composer-bin-plugin/issues",
"source": "https://github.com/bamarni/composer-bin-plugin/tree/1.8.2"
},
"time": "2022-10-31T08:38:03+00:00"
},
{
"name": "dasprid/enum",
"version": "1.0.6",
@ -1582,63 +1639,6 @@
}
],
"packages-dev": [
{
"name": "bamarni/composer-bin-plugin",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/bamarni/composer-bin-plugin.git",
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0",
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"composer/composer": "^2.0",
"ext-json": "*",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^8.5 || ^9.5",
"symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
"symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
"symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0"
},
"type": "composer-plugin",
"extra": {
"class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin"
},
"autoload": {
"psr-4": {
"Bamarni\\Composer\\Bin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "No conflicts for your bin dependencies",
"keywords": [
"composer",
"conflict",
"dependency",
"executable",
"isolation",
"tool"
],
"support": {
"issues": "https://github.com/bamarni/composer-bin-plugin/issues",
"source": "https://github.com/bamarni/composer-bin-plugin/tree/1.8.2"
},
"time": "2022-10-31T08:38:03+00:00"
},
{
"name": "nextcloud/ocp",
"version": "dev-master",

View file

@ -8,11 +8,11 @@ declare(strict_types=1);
namespace OCA\Libresign\Handler\PdfTk;
use mikehaertl\pdftk\Command;
use mikehaertl\pdftk\Pdf as BasePdf;
use OCA\Libresign\AppInfo\Application;
use OCA\Libresign\Exception\LibresignException;
use OCA\Libresign\Helper\JavaHelper;
use OCA\Libresign\Vendor\mikehaertl\pdftk\Command;
use OCA\Libresign\Vendor\mikehaertl\pdftk\Pdf as BasePdf;
use OCP\IAppConfig;
use OCP\IL10N;
use RuntimeException;

View file

@ -14,6 +14,7 @@
<directory name="lib" />
<ignoreFiles>
<directory name="vendor" />
<directory name="lib/Vendor" />
<directory name="lib/Handler/Templates" />
</ignoreFiles>
</projectFiles>

View file

@ -26,5 +26,6 @@ return RectorConfig::configure()
->withTypeCoverageLevel(0)
->withSkip([
ReadOnlyPropertyRector::class,
__DIR__ . '/lib/Vendor',
]);
;

25
scoper.inc.php Normal file
View file

@ -0,0 +1,25 @@
<?php
/**
* SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
declare(strict_types=1);
use Isolated\Symfony\Component\Finder\Finder;
// based on Arthur Schiwon blogpost:
// https://arthur-schiwon.de/isolating-nextcloud-app-dependencies-php-scoper
return [
'prefix' => 'OCA\\Libresign\\Vendor',
'output-dir' => 'lib/Vendor',
'finders' => [
Finder::create()->files()
->exclude([
'vendor-bin'
])
->in('vendor/mikehaertl'),
],
];

View file

@ -49,7 +49,7 @@ final class PdfTest extends \OCA\Libresign\Tests\Unit\TestCase {
public function testApplyStampReturnsBufferWhenSuccess(): void {
$pdf = $this->getInstance(['configureCommand', 'multiStamp']);
$mock = $this->createMock(\mikehaertl\pdftk\Pdf::class);
$mock = $this->createMock(\OCA\Libresign\Vendor\mikehaertl\pdftk\Pdf::class);
$mock->method('toString')->willReturn('%PDF-1.4 fake');
$pdf->method('multiStamp')->willReturn($mock);

View file

@ -0,0 +1,10 @@
{
"require": {
"humbug/php-scoper": "0.18.7"
},
"config": {
"platform": {
"php": "8.1"
}
}
}

1546
vendor-bin/php-scoper/composer.lock generated Normal file

File diff suppressed because it is too large Load diff