Passed
Pull Request — master (#151)
by Manuel
12:46
created

QrCode::setWriterByExtension()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 12
c 2
b 0
f 0
dl 0
loc 17
rs 9.8666
cc 4
nc 4
nop 1
1
<?php declare(strict_types=1);
2
3
namespace Sprain\SwissQrBill\QrCode;
4
5
use Endroid\QrCode\Encoding\Encoding;
6
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelMedium;
7
use Endroid\QrCode\Logo\Logo;
8
use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeEnlarge;
9
use Endroid\QrCode\QrCode as BaseQrCode;
10
use Endroid\QrCode\Writer\PngWriter;
11
use Endroid\QrCode\Writer\Result\ResultInterface;
12
use Endroid\QrCode\Writer\SvgWriter;
13
use Endroid\QrCode\Writer\WriterInterface;
14
use Sprain\SwissQrBill\QrCode\Exception\UnsupportedFileExtensionException;
15
16
final class QrCode
17
{
18
    public const FILE_FORMAT_PNG = 'png';
19
    public const FILE_FORMAT_SVG = 'svg';
20
21
    // A file extension is supported if the underlying library supports it,
22
    // including the possibility to add a logo in the center of the qr code.
23
    private const SUPPORTED_FILE_FORMATS = [
24
        self::FILE_FORMAT_PNG,
25
        self::FILE_FORMAT_SVG
26
    ];
27
28
    private const SWISS_CROSS_LOGO_FILE = __DIR__ . '/../../assets/swiss-cross.optimized.png';
29
    private const PX_QR_CODE = 543;    // recommended 46x46 mm in px @ 300dpi – in pixel based outputs the final image size may be slightly different, depending on the qr code contents
30
    private const PX_SWISS_CROSS = 83; // recommended 7x7 mm in px @ 300dpi
31
32
    private BaseQrCode $qrCode;
33
    private Logo $qrCodeLogo;
34
    private WriterInterface $qrCodeWriter;
35
36
    public static function create(string $data, ?string $fileFormat = null): self
37
    {
38
        if (null === $fileFormat) {
39
            $fileFormat = self::FILE_FORMAT_SVG;
40
        }
41
42
        return new self($data, $fileFormat);
43
    }
44
45
    private function __construct(string $data, string $fileFormat)
46
    {
47
        $this->qrCode = BaseQrCode::create($data)
48
            ->setEncoding(new Encoding('UTF-8'))
49
            ->setErrorCorrectionLevel(new ErrorCorrectionLevelMedium())
50
            ->setSize(self::PX_QR_CODE)
51
            ->setMargin(0)
52
            ->setRoundBlockSizeMode(new RoundBlockSizeModeEnlarge());
53
54
        $this->qrCodeLogo = Logo::create(self::SWISS_CROSS_LOGO_FILE)
55
            ->setResizeToWidth(self::PX_SWISS_CROSS);
56
57
        $this->setWriterByExtension($fileFormat);
58
    }
59
60
    public function writeFile(string $path): void
61
    {
62
        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
0 ignored issues
show
Bug introduced by
It seems like pathinfo($path, Sprain\S...ode\PATHINFO_EXTENSION) can also be of type array; however, parameter $string of strtolower() 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

62
        $extension = strtolower(/** @scrutinizer ignore-type */ pathinfo($path, PATHINFO_EXTENSION));
Loading history...
63
        $this->setWriterByExtension($extension);
64
        $this->getQrCodeResult()->saveToFile($path);
65
    }
66
67
    public function writeDataUri(): string
68
    {
69
        return $this->getQrCodeResult()->getDataUri();
70
    }
71
72
    public function getText(): string
73
    {
74
        return $this->qrCode->getData();
75
    }
76
77
    private function setWriterByExtension(string $extension): void
78
    {
79
        if (!in_array($extension, self::SUPPORTED_FILE_FORMATS)) {
80
            throw new UnsupportedFileExtensionException(sprintf(
81
                'The qr code file cannot be created. Only these file extensions are supported: %s. You provided: %s.',
82
                implode(', ', self::SUPPORTED_FILE_FORMATS),
83
                $extension
84
            ));
85
        }
86
87
        switch ($extension) {
88
            case self::FILE_FORMAT_SVG:
89
                $this->qrCodeWriter = new SvgWriter();
90
                break;
91
            case self::FILE_FORMAT_PNG:
92
            default:
93
                $this->qrCodeWriter = new PngWriter();
94
        }
95
    }
96
97
    private function getQrCodeResult(): ResultInterface
98
    {
99
        return $this->qrCodeWriter->write(
100
            $this->qrCode,
101
            $this->qrCodeLogo,
102
            null,
103
            [SvgWriter::WRITER_OPTION_FORCE_XLINK_HREF]
104
        );
105
    }
106
}
107