Passed
Push — master ( 0ca024...56f4a4 )
by Evgenii
01:30
created

Imagenator   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 250
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 32
eloc 84
c 3
b 0
f 1
dl 0
loc 250
rs 9.84
1
<?php
2
3
namespace floor12\imagenator;
4
5
use floor12\imagenator\exception\FontNotFoundException;
6
use floor12\imagenator\exception\ImageNotFoundException;
7
use floor12\imagenator\exception\ImageNotLoadedException;
8
use floor12\imagenator\exception\InvalidFontSizeException;
9
use floor12\imagenator\exception\InvalidHexColorException;
10
use floor12\imagenator\exception\InvalidPositionValueException;
11
use floor12\imagenator\exception\InvalidRowHeightException;
12
13
class Imagenator
14
{
15
    const DEFAULT_IMAGE = __DIR__ . '/../assets/default.png';
16
    /**
17
     * @var string Path to TTF font file
18
     */
19
    protected $font = __DIR__ . '/../assets/Rubik.ttf';
20
    /**
21
     * @var string
22
     */
23
    protected $text = "Dont forget to put some text here :-)";
24
    /**
25
     * @var resource
26
     */
27
    protected $image;
28
    /**
29
     * @var int
30
     */
31
    protected $imageWidth;
32
    /**
33
     * @var int
34
     */
35
    protected $imageHeight;
36
    /**
37
     * @var int
38
     */
39
    protected $rowHeight = 8;
40
    /**
41
     * @var int
42
     */
43
    protected $marginTopInPercents = 50;
44
    /**
45
     * @var int
46
     */
47
    protected $paddingLeftRightInPercents = 5;
48
    /**
49
     * @var int Default color is white
50
     */
51
    private $textColor = '16777215';
52
    /**
53
     * @var int
54
     */
55
    private $fontSizeInPercents = 5;
56
    /**
57
     * @var array
58
     */
59
    private $rows = [];
60
    /**
61
     * @var float|int
62
     */
63
    private $positionX;
64
    /**
65
     * @var float|int
66
     */
67
    private $positionStartY;
68
    /**
69
     * @var float|int
70
     */
71
    private $rowHeightInPx;
72
    /**
73
     * @var float|int
74
     */
75
    private $fontSizeInPx;
76
77
    /**
78
     * Imagenator constructor.
79
     * @param string $backgroundImagePath
80
     * @throws ImageNotFoundException
81
     */
82
    public function __construct(string $backgroundImagePath = self::DEFAULT_IMAGE)
83
    {
84
        $this->loadImage($backgroundImagePath);
85
    }
86
87
    /**
88
     * @param string $backgroundImagePath
89
     * @throws ImageNotFoundException
90
     * @throws ImageNotLoadedException
91
     */
92
    protected function loadImage(string $backgroundImagePath)
93
    {
94
        if (!file_exists($backgroundImagePath))
95
            throw new ImageNotFoundException();
96
        $this->image = imagecreatefrompng($backgroundImagePath);
97
        if ($this->image == null)
98
            throw new ImageNotLoadedException();
99
        list($this->imageWidth, $this->imageHeight) = getimagesize($backgroundImagePath);
100
    }
101
102
    /**
103
     * @param string $resultImagePath
104
     * @return bool
105
     * @throws FontNotFoundException
106
     */
107
    public function generate(string $resultImagePath): bool
108
    {
109
        $this->calculateParams();
110
        $this->prepareRows();
111
        $this->putRowsToImage();
112
        return $this->saveImage($resultImagePath);
113
    }
114
115
    /**
116
     * @param string $pathToSave
117
     * @return bool
118
     */
119
    protected function saveImage(string $pathToSave): bool
120
    {
121
        return imagepng($this->image, $pathToSave) && imagedestroy($this->image);
122
    }
123
124
    protected function calculateParams()
125
    {
126
        $this->positionStartY = intval($this->imageHeight / 100 * $this->marginTopInPercents);
127
        $this->rowHeightInPx = intval($this->imageHeight / 100 * $this->rowHeight);
128
        $this->fontSizeInPx = intval($this->imageHeight / 100 * $this->fontSizeInPercents);
129
        $this->positionX = intval($this->imageWidth / 100 * $this->paddingLeftRightInPercents);
130
    }
131
132
    /**
133
     * @throws FontNotFoundException
134
     */
135
    protected function prepareRows(): void
136
    {
137
        if (!file_exists($this->font))
138
            throw new FontNotFoundException();
139
140
        $wordsArray = explode(' ', $this->text);
141
        $validRowWidth = $this->imageWidth - $this->positionX * 2;
142
        $currentRow = 0;
143
144
        foreach ($wordsArray as $word) {
145
            $testRow = isset($this->rows[$currentRow]) ? array_merge($this->rows[$currentRow], [$word]) : [$word];
146
            $imageBox = imagettfbbox($this->fontSizeInPx, 0, $this->font, implode('', $testRow));
147
            if ($imageBox[2] >= $validRowWidth) {
148
                $lastWord = end($this->rows[$currentRow]);
149
                if (mb_strlen($lastWord) <= 2) {
150
                    $this->rows[$currentRow + 1][] = array_pop($this->rows[$currentRow]);
151
                }
152
                $this->rows[++$currentRow][] = $word;
153
            } else {
154
                $this->rows[$currentRow][] = $word;
155
            }
156
        }
157
    }
158
159
    /**
160
     *
161
     */
162
    protected function putRowsToImage()
163
    {
164
        foreach ($this->rows as $rowNumber => $row) {
165
            $string = implode(' ', $row);
166
            $positionY = intval($this->positionStartY + ($rowNumber * $this->rowHeightInPx));
167
            imagettftext($this->image, $this->fontSizeInPx, 0, $this->positionX, $positionY, $this->textColor, $this->font, $string);
168
        }
169
    }
170
171
    /**
172
     * @param string $text
173
     * @return self
174
     */
175
    public
176
    function setText(string $text): self
177
    {
178
        $this->text = $text;
179
        return $this;
180
    }
181
182
    /**
183
     * @param string $font
184
     * @return self
185
     */
186
    public
187
    function setFont(string $font): self
188
    {
189
        $this->font = $font;
190
        return $this;
191
    }
192
193
    /**
194
     * @param string $colorInHex
195
     * @return self
196
     * @throws InvalidHexColorException
197
     */
198
    public
199
    function setColor(string $colorInHex): self
200
    {
201
        $colorInHex = str_replace('#', '', $colorInHex);
202
203
        if (!ctype_xdigit($colorInHex) || strlen($colorInHex) !== 6)
204
            throw new InvalidHexColorException();
205
206
        $red = intval(hexdec(substr($colorInHex, 0, 2))));
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected ')' on line 206 at column 56
Loading history...
207
        $green = intval(hexdec(substr($colorInHex, 2, 2)));
208
        $blue = intval(hexdec(substr($colorInHex, 4, 2)));
209
        $this->textColor = imagecolorallocate($this->image, $red, $green, $blue);
210
        return $this;
211
    }
212
213
    /**
214
     * @param int $size
215
     * @return Imagenator
216
     * @throws InvalidFontSizeException
217
     */
218
    public
219
    function setFontSize(int $size)
220
    {
221
        if ($size < 1 || $size > 20)
222
            throw new InvalidFontSizeException();
223
        $this->fontSizeInPercents = $size;
224
        return $this;
225
    }
226
227
    /**
228
     * @param int $percent
229
     * @return Imagenator
230
     * @throws InvalidPositionValueException
231
     */
232
    public
233
    function setPadding(int $percent)
234
    {
235
        if ($percent < 1 || $percent > 100)
236
            throw new InvalidPositionValueException();
237
        $this->paddingLeftRightInPercents = $percent;
238
        return $this;
239
    }
240
241
    /**
242
     * @param int $percent
243
     * @return Imagenator
244
     * @throws InvalidPositionValueException
245
     */
246
    public function setMarginTopInPercents(int $percent)
247
    {
248
        if ($percent < 1 || $percent > 100)
249
            throw new InvalidPositionValueException();
250
        $this->marginTopInPercents = $percent;
251
        return $this;
252
    }
253
254
    /**
255
     * @param int $percent
256
     * @return Imagenator
257
     * @throws InvalidRowHeightException
258
     */
259
    public
260
    function setRowHeight(int $percent)
261
    {
262
        if ($percent < 1 || $percent > 30)
263
            throw new InvalidRowHeightException();
264
        $this->rowHeight = $percent;
265
        return $this;
266
    }
267
}
268