Test Failed
Push — master ( 817d84...d52e3d )
by Raffael
05:44
created

Burl::setOptions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15

Duplication

Lines 15
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 15
loc 15
ccs 0
cts 8
cp 0
rs 9.7666
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 12
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * balloon
7
 *
8
 * @copyright   Copryright (c) 2012-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Balloon\App\Burl\Converter\Adapter;
13
14
use Balloon\Converter\Adapter\AdapterInterface;
15
use Balloon\Converter\Exception;
16
use Balloon\Filesystem\Node\File;
17
use GuzzleHttp\ClientInterface as GuzzleHttpClientInterface;
18
use GuzzleHttp\Psr7\StreamWrapper;
19
use Imagick;
20
use Psr\Log\LoggerInterface;
21
22
class Burl implements AdapterInterface
23
{
24
    /**
25
     * Preview format.
26
     */
27
    const PREVIEW_FORMAT = 'png';
28
29
    /**
30
     * preview max size.
31
     *
32
     * @var int
33
     */
34
    protected $preview_max_size = 500;
35
36
    /**
37
     * GuzzleHttpClientInterface.
38
     *
39
     * @var GuzzleHttpClientInterface
40
     */
41
    protected $client;
42
43
    /**
44
     * LoggerInterface.
45
     *
46
     * @var LoggerInterface
47
     */
48
    protected $logger;
49
50
    /**
51
     * Formats.
52
     *
53
     * @var array
54
     */
55
    protected $formats = [
56
        'burl' => 'application/vnd.balloon.burl',
57
    ];
58
59
    /**
60
     * One way formats.
61
     *
62
     * @param array
63
     */
64
    protected $target_formats = [
65
        'pdf' => 'application/pdf',
66
        'jpg' => 'image/jpeg',
67
        'jpeg' => 'image/jpeg',
68
        'png' => 'image/png',
69
    ];
70
71
    /**
72
     * Initialize.
73
     */
74
    public function __construct(GuzzleHttpClientInterface $client, LoggerInterface $logger, array $config = [])
75
    {
76
        $this->client = $client;
77
        $this->logger = $logger;
78
        $this->setOptions($config);
79
    }
80
81
    /**
82
     * Set options.
83
     */
84 View Code Duplication
    public function setOptions(array $config = []): AdapterInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
85
    {
86
        foreach ($config as $option => $value) {
87
            switch ($option) {
88
                case 'preview_max_size':
89
                    $this->preview_max_size = (int) $value;
90
91
                    break;
92
                default:
93
                    throw new Exception('invalid option '.$option.' given');
94
            }
95
        }
96
97
        return $this;
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    public function match(File $file): bool
104
    {
105
        foreach ($this->formats as $format => $mimetype) {
106
            if ($file->getContentType() === $mimetype) {
107
                return true;
108
            }
109
        }
110
111
        return false;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function matchPreview(File $file): bool
118
    {
119
        return $this->match($file);
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function getSupportedFormats(File $file): array
126
    {
127
        return array_keys($this->target_formats);
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133 View Code Duplication
    public function createPreview(File $file)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
134
    {
135
        try {
136
            $result = $this->getImage(\stream_get_contents($file->get()), self::PREVIEW_FORMAT);
137
        } catch (Exception $e) {
138
            throw new Exception('failed create preview');
139
        }
140
141
        $desth = tmpfile();
142
        stream_copy_to_stream($result, $desth);
143
        $dest = stream_get_meta_data($desth)['uri'];
144
        $image = new Imagick($dest);
145
146
        $width = $image->getImageWidth();
147
        $height = $image->getImageHeight();
148
149
        if ($height <= $width && $width > $this->preview_max_size) {
150
            $image->scaleImage($this->preview_max_size, 0);
151
        } elseif ($height > $this->preview_max_size) {
152
            $image->scaleImage(0, $this->preview_max_size);
153
        }
154
155
        $image->writeImage($dest);
156
        rewind($desth);
157
158
        return $desth;
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164
    public function convert(File $file, string $format)
165
    {
166
        switch ($format) {
167
            case 'pdf':
168
                return $this->getPdf(\stream_get_contents($file->get()));
169
            case 'png':
170
                return $this->getImage(\stream_get_contents($file->get()), 'png');
171
            case 'jpg':
172
            case 'jpeg':
173
                return $this->getImage(\stream_get_contents($file->get()), 'jpeg');
174
            default:
175
                throw new Exception('target format ['.$format.'] not supported');
176
        }
177
    }
178
179
    /**
180
     * Get screenshot of url.
181
     */
182
    protected function getImage(string $url, string $format)
183
    {
184
        $options = [
185
            'fullPage' => false,
186
            'type' => $format,
187
        ];
188
        if ('jpeg' === $format) {
189
            $options['quality'] = 75;
190
        }
191
192
        $this->logger->debug('request screenshot from [/screenshot] using url ['.$url.']', [
193
            'category' => get_class($this),
194
        ]);
195
196
        $response = $this->client->request(
197
            'POST',
198
            'screenshot',
199
            [
200
                'json' => [
201
                    'url' => $url,
202
                    'options' => $options,
203
                ],
204
            ]
205
        );
206
207
        $this->logger->debug('screenshot create request ended with status code ['.$response->getStatusCode().']', [
208
            'category' => get_class($this),
209
        ]);
210
211
        return StreamWrapper::getResource($response->getBody());
212
    }
213
214
    /**
215
     * Get pdf of url contents.
216
     */
217 View Code Duplication
    protected function getPdf(string $url)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218
    {
219
        $this->logger->debug('request pdf from [/pdf] using url ['.$url.']', [
220
            'category' => get_class($this),
221
        ]);
222
223
        $response = $this->client->request(
224
            'POST',
225
            'pdf',
226
            [
227
                'json' => [
228
                    'url' => $url,
229
                    'options' => [
230
                        'printBackground' => false,
231
                        'format' => 'A4',
232
                    ],
233
                ],
234
            ]
235
        );
236
237
        $this->logger->debug('pdf create request ended with status code ['.$response->getStatusCode().']', [
238
            'category' => get_class($this),
239
        ]);
240
241
        return StreamWrapper::getResource($response->getBody());
242
    }
243
}
244