Passed
Push — feature/code-analysis ( e964aa...4fe35d )
by Jonathan
14:33
created

CertificateImageFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage Certificates
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2021-2022, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
declare(strict_types=1);
14
15
namespace MyArtJaub\Webtrees\Module\Certificates\Factories;
16
17
use Fig\Http\Message\StatusCodeInterface;
18
use Fisharebest\Webtrees\Auth;
19
use Fisharebest\Webtrees\MediaFile;
20
use Fisharebest\Webtrees\Webtrees;
21
use Fisharebest\Webtrees\Contracts\ImageFactoryInterface;
22
use Fisharebest\Webtrees\Contracts\UserInterface;
23
use Fisharebest\Webtrees\Factories\ImageFactory;
24
use Intervention\Image\AbstractFont;
25
use Intervention\Image\Image;
26
use Intervention\Image\Exception\NotReadableException;
27
use League\Flysystem\FilesystemException;
28
use League\Flysystem\UnableToReadFile;
29
use MyArtJaub\Webtrees\Module\Certificates\Model\Certificate;
30
use MyArtJaub\Webtrees\Module\Certificates\Model\Watermark;
31
use MyArtJaub\Webtrees\Module\Certificates\Services\CertificateFilesystemService;
32
use Psr\Http\Message\ResponseInterface;
33
use BadMethodCallException;
34
use InvalidArgumentException;
35
use Throwable;
36
37
/**
38
 * Make a certificate image (from a certificate file).
39
 */
40
class CertificateImageFactory extends ImageFactory implements ImageFactoryInterface
41
{
42
    /**
43
     * @var CertificateFilesystemService $filesystem_service
44
     */
45
    private $filesystem_service;
46
47
    /**
48
     * Constructor for the Certificate Image Factory
49
     *
50
     * @param CertificateFilesystemService $filesystem_service
51
     */
52
    public function __construct(CertificateFilesystemService $filesystem_service)
53
    {
54
        $this->filesystem_service = $filesystem_service;
55
    }
56
57
    /**
58
     * Check is a file MIME type is supported by the system.
59
     *
60
     * @param string $mime
61
     * @return bool
62
     */
63
    public function isMimeTypeSupported(string $mime): bool
64
    {
65
        return array_key_exists($mime, self::SUPPORTED_FORMATS);
66
    }
67
68
    /**
69
     * Create a full-size version of a certificate.
70
     *
71
     * @param Certificate $certificate
72
     * @param bool $add_watermark
73
     * @param Watermark $watermark
74
     * @throws InvalidArgumentException
75
     * @return ResponseInterface
76
     */
77
    public function certificateFileResponse(
78
        Certificate $certificate,
79
        bool $add_watermark = false,
80
        Watermark $watermark = null
81
    ): ResponseInterface {
82
        $filesystem =  $this->filesystem_service->filesystem($certificate->tree());
83
        $filename   = $certificate->path();
84
85
        if (!$add_watermark) {
86
            return $this->fileResponse($filesystem, $filename, false);
87
        }
88
89
        try {
90
            $image = $this->imageManager()->make($filesystem->readStream($filename));
91
            $image = $this->autorotateImage($image);
92
93
            if ($watermark == null) {
94
                throw new InvalidArgumentException('Watermark data not defined');
95
            }
96
97
            $width = $image->width();
98
            $height = $image->height();
99
100
            $watermark->adjustSize($width);
101
            $watermark_x = (int) ceil($watermark->textLengthEstimate() * 1.5);
102
            $watermark_y = $watermark->size() * 12 + 1;
103
104
            $font_definition = function (AbstractFont $font) use ($watermark): void {
105
                $font->file(Webtrees::ROOT_DIR . 'resources/fonts/DejaVuSans.ttf');
106
                $font->color($watermark->color());
107
                $font->size($watermark->size());
108
                $font->valign('top');
109
            };
110
111
            for ($i = min((int) ceil($width * 0.1), $watermark_x); $i < $width; $i += $watermark_x) {
112
                for ($j = min((int) ceil($height * 0.1), $watermark_y); $j < $height; $j += $watermark_y) {
113
                    $image = $image->text($watermark->text(), $i, $j, $font_definition);
114
                }
115
            }
116
117
            $format  = static::SUPPORTED_FORMATS[$image->mime()] ?? 'jpg';
118
            $quality = $this->extractImageQuality($image, static::GD_DEFAULT_IMAGE_QUALITY);
119
            $data    = (string) $image->encode($format, $quality);
120
121
            return $this->imageResponse($data, $image->mime(), '');
122
        } catch (NotReadableException $ex) {
123
            return $this->replacementImageResponse(pathinfo($filename, PATHINFO_EXTENSION))
0 ignored issues
show
Bug introduced by
It seems like pathinfo($filename, MyAr...ies\PATHINFO_EXTENSION) can also be of type array; however, parameter $text of Fisharebest\Webtrees\Fac...lacementImageResponse() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

123
            return $this->replacementImageResponse(/** @scrutinizer ignore-type */ pathinfo($filename, PATHINFO_EXTENSION))
Loading history...
124
            ->withHeader('X-Image-Exception', $ex->getMessage());
125
        } catch (FilesystemException | UnableToReadFile $ex) {
126
            return $this->replacementImageResponse((string) StatusCodeInterface::STATUS_NOT_FOUND);
127
        } catch (Throwable $ex) {
128
            return $this->replacementImageResponse((string) StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR)
129
            ->withHeader('X-Image-Exception', $ex->getMessage());
130
        }
131
    }
132
133
    /**
134
     * Does a full-sized certificate need a watermark?
135
     *
136
     * @param Certificate $certificate
137
     * @param UserInterface $user
138
     * @return bool
139
     */
140
    public function certificateNeedsWatermark(Certificate $certificate, UserInterface $user): bool
141
    {
142
        $tree = $certificate->tree();
143
        $watermark_level = (int) ($tree->getPreference('MAJ_CERTIF_SHOW_NO_WATERMARK', (string) Auth::PRIV_HIDE));
144
145
        return Auth::accessLevel($tree, $user) > $watermark_level;
146
    }
147
148
    /**
149
     * Neutralise the methods associated with MediaFile.
150
     */
151
152
    /**
153
     * {@inheritDoc}
154
     * @see \Fisharebest\Webtrees\Factories\ImageFactory::mediaFileResponse()
155
     */
156
    public function mediaFileResponse(MediaFile $media_file, bool $add_watermark, bool $download): ResponseInterface
157
    {
158
        throw new BadMethodCallException("Invalid method for Certificates");
159
    }
160
161
    /**
162
     * {@inheritDoc}
163
     * @see \Fisharebest\Webtrees\Factories\ImageFactory::mediaFileThumbnailResponse()
164
     */
165
    public function mediaFileThumbnailResponse(
166
        MediaFile $media_file,
167
        int $width,
168
        int $height,
169
        string $fit,
170
        bool $add_watermark
171
    ): ResponseInterface {
172
        throw new BadMethodCallException("Invalid method for Certificates");
173
    }
174
175
    /**
176
     * {@inheritDoc}
177
     * @see \Fisharebest\Webtrees\Factories\ImageFactory::createWatermark()
178
     */
179
    public function createWatermark(int $width, int $height, MediaFile $media_file): Image
180
    {
181
182
        throw new BadMethodCallException("Invalid method for Certificates");
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     * @see \Fisharebest\Webtrees\Factories\ImageFactory::fileNeedsWatermark()
188
     */
189
    public function fileNeedsWatermark(MediaFile $media_file, UserInterface $user): bool
190
    {
191
        throw new BadMethodCallException("Invalid method for Certificates");
192
    }
193
194
    /**
195
     * {@inheritDoc}
196
     * @see \Fisharebest\Webtrees\Factories\ImageFactory::thumbnailNeedsWatermark()
197
     */
198
    public function thumbnailNeedsWatermark(MediaFile $media_file, UserInterface $user): bool
199
    {
200
        throw new BadMethodCallException("Invalid method for Certificates");
201
    }
202
}
203