From 47e8f98c164ff14b5e921851db99d03e97d0a15e Mon Sep 17 00:00:00 2001 From: Benjamin Gehrels Date: Tue, 3 Oct 2023 06:54:34 +0200 Subject: [PATCH] Fix build failures for the cake 5 upgrade (#326) * cake 5 upgrade - upgrade to PhpUnit 10, which is needed when working with CakePHP 5, and fixing the PHPUnit tests afterwards * cake 5 upgrade - The request handler component has been removed from Cake, so no need to have special logic for it * cake 5 upgrade - Fix style issues reported by phpcs * cake 5 upgrade - Fix Coding Standard & Static Analysis Errors / Warnings * cake 5 upgrade - Static code analysis A warns that $fileInfo->getPathInfo() might return null on errors leading to a possible NPE. Static code analysis B does not know that $fileInfo->getPathInfo() might return null and therefore complains that the comparison is always true. Fix one of them, ignore the other * cake 5 upgrade - readd psalm and phpstan to fix the build * cake 5 upgrade - psalm 4 does not have support for intersecion types, so let's update to psalm 5 * cake 5 upgrade - psalm 5.0 throws a "Could not get class storage for cake\cache\cacheengineinterface" error, so let's upgrade to a more current version * cake 5 upgrade - phpunit 10 remoced the --verbose option * cake 5 upgrade - no need for dev versions anymore, as cake 5 is declared stable * cake 5 upgrade - update to mpdf 8.1.6, because it's the first minor release to support psr log 3 * cake 5 upgrade - implement pr feedback * cake 5 upgrade - upgrade to cakephp 5.0.1 and remove the temporary workaround for a php 5.0.0 bug again * cake 5 upgrade - adapt the PdfView for content type negotiation * Fix CS error * Fix CS error --------- Co-authored-by: bgehrels Co-authored-by: ADmad --- .github/workflows/ci.yml | 8 ++-- composer.json | 8 ++-- config/bootstrap.php | 16 -------- phpunit.xml.dist | 38 ++++++------------- src/{Plugin.php => CakePdfPlugin.php} | 9 ++++- src/Pdf/CakePdf.php | 12 ++++-- src/View/PdfView.php | 16 ++++++-- .../TestCase/Pdf/Engine/DomPdfEngineTest.php | 23 ++++++----- tests/TestCase/Pdf/Engine/MpdfEngineTest.php | 5 ++- 9 files changed, 67 insertions(+), 68 deletions(-) delete mode 100644 config/bootstrap.php rename src/{Plugin.php => CakePdfPlugin.php} (73%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b2fe683..7c90b67d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: - name: Run PHPUnit run: | if [[ ${{ matrix.php-version }} == '8.1' ]]; then - vendor/bin/phpunit --verbose --coverage-clover=coverage.xml + vendor/bin/phpunit --coverage-clover=coverage.xml else vendor/bin/phpunit fi @@ -74,7 +74,7 @@ jobs: php-version: '8.1' extensions: mbstring, intl coverage: none - tools: cs2pr + tools: cs2pr, vimeo/psalm:5.15, phpstan:1.8 - name: Composer Install run: composer install @@ -84,8 +84,8 @@ jobs: - name: Run psalm if: success() || failure() - run: vendor/bin/psalm --output-format=github + run: psalm --output-format=github - name: Run phpstan if: success() || failure() - run: vendor/bin/phpstan analyse + run: phpstan analyse diff --git a/composer.json b/composer.json index 7d9c05c6..53d70c8c 100644 --- a/composer.json +++ b/composer.json @@ -6,12 +6,12 @@ "license": "MIT", "require": { "php": ">=8.1", - "cakephp/cakephp": "^5.0" + "cakephp/cakephp": "^5.0.1" }, "require-dev": { - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^10.3", "dompdf/dompdf": "^2.0", - "mpdf/mpdf": "^8.0.4", + "mpdf/mpdf": "^8.1.6", "tecnickcom/tcpdf": "^6.3", "cakephp/cakephp-codesniffer": "^5.0" }, @@ -33,7 +33,7 @@ "TestApp\\": "tests/test_app/src/" } }, - "minimum-stability": "dev", + "minimum-stability": "stable", "scripts": { "check": [ "@test", diff --git a/config/bootstrap.php b/config/bootstrap.php deleted file mode 100644 index b5f82d14..00000000 --- a/config/bootstrap.php +++ /dev/null @@ -1,16 +0,0 @@ -on( - 'Controller.initialize', - function (Event $event) { - $controller = $event->getSubject(); - if ($controller->components()->has('RequestHandler')) { - $controller->RequestHandler->setConfig('viewClassMap.pdf', 'CakePdf.Pdf'); - } - } - ); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 24af0446..4d13ca52 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,27 +1,13 @@ - - - - - ./tests/TestCase - - - - - - ./src/ - - + + + + + ./tests/TestCase + + + + + ./src/ + + diff --git a/src/Plugin.php b/src/CakePdfPlugin.php similarity index 73% rename from src/Plugin.php rename to src/CakePdfPlugin.php index be71a1fe..6bcb90ee 100644 --- a/src/Plugin.php +++ b/src/CakePdfPlugin.php @@ -5,8 +5,15 @@ use Cake\Core\BasePlugin; -class Plugin extends BasePlugin +class CakePdfPlugin extends BasePlugin { + /** + * Do bootstrap or not + * + * @var bool + */ + protected bool $bootstrapEnabled = false; + /** * Load routes or not * diff --git a/src/Pdf/CakePdf.php b/src/Pdf/CakePdf.php index 4523e306..7a97c2c9 100644 --- a/src/Pdf/CakePdf.php +++ b/src/Pdf/CakePdf.php @@ -332,6 +332,7 @@ public function html(?string $html = null): mixed /** * Writes output to file * + * @throws \Cake\Core\Exception\CakeException * @param string $destination Absolute file path to write to * @param bool $create Create file if it does not exist (if true) * @param string|null $html Html to write @@ -347,7 +348,12 @@ public function write(string $destination, bool $create = true, ?string $html = return (bool)file_put_contents($destination, $output); } - if (!$fileInfo->getPathInfo()->getRealPath()) { + $splFileInfo = $fileInfo->getPathInfo(); + /** @phpstan-ignore-next-line */ + if ($splFileInfo === null) { + throw new CakeException('Failed to retrieve path information'); + } + if (!$splFileInfo->getRealPath()) { mkdir($fileInfo->getPath(), 0777, true); } @@ -357,11 +363,11 @@ public function write(string $destination, bool $create = true, ?string $html = /** * Load PdfEngine * - * @param array|string $name Classname of pdf engine without `Engine` suffix. For example `CakePdf.DomPdf` + * @param array|string|null $name Classname of pdf engine without `Engine` suffix. For example `CakePdf.DomPdf` * @throws \Cake\Core\Exception\CakeException * @return \CakePdf\Pdf\Engine\AbstractPdfEngine|null */ - public function engine(string|array|null $name = null): ?AbstractPdfEngine + public function engine(array|string|null $name = null): ?AbstractPdfEngine { if ($name === null) { return $this->_engineClass; diff --git a/src/View/PdfView.php b/src/View/PdfView.php index b4abd005..554a39c6 100644 --- a/src/View/PdfView.php +++ b/src/View/PdfView.php @@ -46,9 +46,9 @@ class PdfView extends View /** * Constructor * - * @param \Cake\Http\ServerRequest $request Request instance. - * @param \Cake\Http\Response $response Response instance. - * @param \Cake\Event\EventManager $eventManager Event manager instance. + * @param \Cake\Http\ServerRequest|null $request Request instance. + * @param \Cake\Http\Response|null $response Response instance. + * @param \Cake\Event\EventManager|null $eventManager Event manager instance. * @param array $viewOptions View options. See View::$_passedVars for list of * options which get set as class properties. * @throws \Cake\Core\Exception\CakeException @@ -82,6 +82,14 @@ public function __construct( $this->renderer($pdfConfig); } + /** + * @inheritDoc + */ + public static function contentType(): string + { + return 'application/pdf'; + } + /** * Return CakePdf instance, optionally set engine to be used * @@ -104,7 +112,7 @@ public function renderer(?array $config = null): ?CakePdf * @param string|false|null $layout The layout being rendered. * @return string The rendered view. */ - public function render(?string $template = null, false|string|null $layout = null): string + public function render(?string $template = null, string|false|null $layout = null): string { $content = parent::render($template, $layout); diff --git a/tests/TestCase/Pdf/Engine/DomPdfEngineTest.php b/tests/TestCase/Pdf/Engine/DomPdfEngineTest.php index 8aa5898f..15c7d81c 100644 --- a/tests/TestCase/Pdf/Engine/DomPdfEngineTest.php +++ b/tests/TestCase/Pdf/Engine/DomPdfEngineTest.php @@ -27,7 +27,7 @@ public function setUp(): void */ public function testReceiveOptions() { - $engineClass = $this->getMockClass(DomPdfEngine::class, ['_createInstance']); + $engineClass = $this->getMockBuilder(DomPdfEngine::class)->disableOriginalConstructor()->onlyMethods(['_createInstance'])->getMock()::class; $Pdf = new CakePdf([ 'engine' => [ @@ -65,8 +65,7 @@ public function testReceiveOptions() */ public function testSetOptions() { - $engineClass = $this->getMockClass(DomPdfEngine::class, ['_output']); - + $engineClass = $this->getMockBuilder(DomPdfEngine::class)->disableOriginalConstructor()->onlyMethods(['_output'])->getMock()::class; $Pdf = new CakePdf([ 'engine' => [ 'className' => '\\' . $engineClass, @@ -114,11 +113,14 @@ public function testOutput() */ public function testControlFlow() { - $engineClass = $this->getMockClass(DomPdfEngine::class, [ - '_createInstance', - '_render', - '_output', - ]); + $engineClass = $this->getMockBuilder(DomPdfEngine::class) + ->disableOriginalConstructor() + ->onlyMethods([ + '_createInstance', + '_render', + '_output', + ]) + ->getMock()::class; $Pdf = new CakePdf([ 'engine' => '\\' . $engineClass, @@ -149,7 +151,10 @@ public function testControlFlow() */ public function testDompdfControlFlow() { - $engineClass = $this->getMockClass(DomPdfEngine::class, ['_createInstance']); + $engineClass = $this->getMockBuilder(DomPdfEngine::class) + ->disableOriginalConstructor() + ->onlyMethods(['_createInstance']) + ->getMock()::class; $Pdf = new CakePdf([ 'engine' => '\\' . $engineClass, diff --git a/tests/TestCase/Pdf/Engine/MpdfEngineTest.php b/tests/TestCase/Pdf/Engine/MpdfEngineTest.php index 4e697a54..6f9e07d0 100644 --- a/tests/TestCase/Pdf/Engine/MpdfEngineTest.php +++ b/tests/TestCase/Pdf/Engine/MpdfEngineTest.php @@ -27,7 +27,10 @@ public function setUp(): void */ public function testSetOptions() { - $engineClass = $this->getMockClass(MpdfEngine::class, ['_createInstance']); + $engineClass = $this->getMockBuilder(MpdfEngine::class) + ->disableOriginalConstructor() + ->onlyMethods(['_createInstance']) + ->getMock()::class; $Pdf = new CakePdf([ 'engine' => [