Completed
Push — master ( dd67d5...87ef89 )
by Dan
02:57
created

CommandsHelper::createCloud()   C

Complexity

Conditions 9
Paths 19

Size

Total Lines 91
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 91
rs 5.1434
cc 9
eloc 56
nc 19
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SixtyNine\Cloud\Command;
4
5
use Imagine\Image\ImageInterface;
6
use SixtyNine\Cloud\Builder\CloudBuilder;
7
use SixtyNine\Cloud\Builder\FiltersBuilder;
8
use SixtyNine\Cloud\Builder\PalettesBuilder;
9
use SixtyNine\Cloud\Builder\WordsListBuilder;
10
use SixtyNine\Cloud\Color\ColorGeneratorInterface;
11
use SixtyNine\Cloud\Color\RandomColorGenerator;
12
use SixtyNine\Cloud\Color\RotateColorGenerator;
13
use SixtyNine\Cloud\Factory\FontsFactory;
14
use SixtyNine\Cloud\Factory\PlacerFactory;
15
use SixtyNine\Cloud\FontSize\BoostFontSizeGenerator;
16
use SixtyNine\Cloud\FontSize\DimFontSizeGenerator;
17
use SixtyNine\Cloud\FontSize\FontSizeGeneratorInterface;
18
use SixtyNine\Cloud\FontSize\LinearFontSizeGenerator;
19
use SixtyNine\Cloud\Placer\PlacerInterface;
20
use SixtyNine\Cloud\Renderer\CloudRenderer;
21
use Symfony\Component\Console\Input\InputInterface;
22
23
class CommandsHelper
24
{
25
    protected $allowedFontSizeBoosts = array('linear', 'dim', 'boost');
26
    protected $allowedPaletteTypes = array('cycle', 'random');
27
    protected $allowedOutputFormats = array('gif', 'jpeg', 'png');
28
29
    /**
30
     * @param string $name
31
     * @return PlacerInterface
32
     * @throws \InvalidArgumentException
33
     */
34
    public function getPlacer($name)
35
    {
36
        $availablePlacers = PlacerFactory::getInstance()->getPlacersNames();
37
38
        if ($name) {
39
            if (!in_array($name, $availablePlacers)) {
40
                throw new \InvalidArgumentException('Word placer not found: ' . $name);
41
            }
42
            return $name;
43
        }
44
45
        if (!count($availablePlacers)) {
46
            throw new \InvalidArgumentException('No word placers available');
47
        }
48
49
        return $availablePlacers[0];
50
    }
51
52
    /**
53
     * @param FontsFactory $factory
54
     * @param string $font
55
     * @return string
56
     * @throws \InvalidArgumentException
57
     */
58
    public function getFont(FontsFactory $factory, $font)
59
    {
60
        if ($font) {
61
            return $font;
62
        }
63
64
        if (0 === count($factory->getFonts())) {
65
            throw new \InvalidArgumentException('No font file found');
66
        }
67
68
        return $factory->getFonts()[0];
69
    }
70
71
    /**
72
     * @param string $type
73
     * @return FontSizeGeneratorInterface
74
     * @throws \InvalidArgumentException
75
     */
76
    public function getFontSizeGenerator($type = 'linear')
77
    {
78
        if (!in_array($type, $this->allowedFontSizeBoosts)) {
79
            throw new \InvalidArgumentException('Invalid font size boost: ' . $type);
80
        }
81
82
        $generatorClass = LinearFontSizeGenerator::class;
83
        if ($type === 'dim') {
84
            $generatorClass = DimFontSizeGenerator::class;
85
        }
86
        if ($type === 'boost') {
87
            $generatorClass = BoostFontSizeGenerator::class;
88
        }
89
90
        return new $generatorClass();
91
    }
92
93
    /**
94
     * @param string $paletteName
95
     * @param string $paletteType
96
     * @param string $palettesFile
97
     * @return bool|ColorGeneratorInterface
98
     * @throws \InvalidArgumentException
99
     */
100
    public function getColorGenerator($paletteName, $paletteType, $palettesFile = null)
101
    {
102
        if ($paletteName && $paletteType) {
103
104
            if (!in_array($paletteType, $this->allowedPaletteTypes)) {
105
                throw new \InvalidArgumentException('Palette type must be either "cycle" or "random"');
106
            }
107
108
            $file = $palettesFile
109
                ? $palettesFile
110
                : __DIR__ . '/../Resources/palettes.yml'
111
            ;
112
            $paletteBuilder = PalettesBuilder::create()->importPalettes($file);
113
114
            $palette = $paletteBuilder->getNamedPalette($paletteName);
115
            $generatorClass = ($paletteType === 'cycle')
116
                ? RotateColorGenerator::class
117
                : RandomColorGenerator::class
118
            ;
119
            return new $generatorClass($palette);
120
        }
121
122
        return false;
123
    }
124
125
    /**
126
     * @param ImageInterface $image
127
     * @param string $outputFormat
128
     * @param string $outputFile
129
     * @throws \InvalidArgumentException
130
     */
131
    public function output(ImageInterface $image, $outputFormat, $outputFile = null)
132
    {
133
        if (!in_array($outputFormat, $this->allowedOutputFormats)) {
134
            throw new \InvalidArgumentException('Invalid output format: ' . $outputFormat);
135
        }
136
137
        if ($outputFile) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $outputFile of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
138
            $image->save($outputFile, array('format' => $outputFormat));
139
            return;
140
        }
141
142
        echo $image->get($outputFormat);
143
    }
144
145
    /**
146
     * @param CloudBuilder $cloudBuilder
147
     * @param FontsFactory $factory
148
     * @param PlacerInterface $placer
149
     * @param bool $renderBoxes
150
     * @return \Imagine\Gd\Image|ImageInterface
151
     */
152
    protected function render(CloudBuilder $cloudBuilder, FontsFactory $factory, PlacerInterface $placer = null, $renderBoxes = false)
153
    {
154
        $renderer = new CloudRenderer();
155
        $image = $renderer->render($cloudBuilder->build(), $factory, $renderBoxes);
156
157
        if ($placer) {
158
            $renderer->renderUsher($image, $placer, '#FF0000');
159
        }
160
161
        return $image;
162
    }
163
164
    public function getFilterBuilder(
165
        $minWordLength,
166
        $maxWordLength,
167
        $changeCase = null,
168
        $noRemoveNumbers = false,
169
        $noRemoveUnwanted = false,
170
        $noRemoveTrailing = false
171
    ) {
172
        $filtersBuilder = FiltersBuilder::create()
173
            ->setMinLength($minWordLength)
174
            ->setMaxLength($maxWordLength)
175
            ->setRemoveNumbers(!$noRemoveNumbers)
176
            ->setRemoveUnwanted(!$noRemoveTrailing)
177
            ->setRemoveTrailing(!$noRemoveUnwanted)
178
        ;
179
180
        if ($changeCase && in_array($changeCase, $filtersBuilder->getAllowedCase())) {
181
            $filtersBuilder->setCase($changeCase);
182
        }
183
184
        return $filtersBuilder;
185
    }
186
187
    public function createCloud($type, InputInterface $input)
188
    {
189
        if (!in_array($type, array('from-url', 'from-file'))) {
190
            throw new \InvalidArgumentException('Invalid type for createCloud: ' . $type);
191
        }
192
193
        // Build the filters
194
        $filtersBuilder = $this->getFilterBuilder(
195
            $input->getOption('min-word-length'),
196
            $input->getOption('max-word-length'),
197
            $input->getOption('case'),
198
            $input->getOption('no-remove-numbers'),
199
            $input->getOption('no-remove-unwanted'),
200
            $input->getOption('no-remove-trailing')
201
        );
202
203
        // Create a placer
204
        $placerName = $this->getPlacer($input->getOption('placer'));
205
        $placer = PlacerFactory::getInstance()->getPlacer(
206
            $placerName,
207
            $input->getOption('width'),
208
            $input->getOption('height')
209
        );
210
211
        // Get the font file
212
        $fontsPath = $input->getOption('fonts-path')
213
            ? realpath($input->getOption('fonts-path'))
214
            : constant('BASE_PATH') . '/fonts'
215
        ;
216
        $factory = FontsFactory::create($fontsPath);
217
        $font = $this->getFont($factory, $input->getOption('font'));
218
219
        // Create the list builder
220
        $listBuilder = WordsListBuilder::create()
221
            ->setMaxWords($input->getOption('max-word-count'))
222
            ->setFilters($filtersBuilder->build())
223
            ->randomizeOrientation($input->getOption('vertical-probability'))
224
        ;
225
226
        if ($type === 'from-file') {
227
            $file = $input->getArgument('file');
228
            if (!file_exists($file)) {
229
                throw new \InvalidArgumentException('File not found: ' . $file);
230
            }
231
            $listBuilder->importWords(file_get_contents($file));
232
        } else {
233
            $listBuilder->importUrl($input->getArgument('url'));
234
        }
235
236
        $sortBy = $input->getOption('sort-by');
237
        $sortOrder = $input->getOption('sort-order');
238
239
        if ($sortBy && $sortOrder) {
240
            $listBuilder->sort($sortBy, $sortOrder);
241
        }
242
243
        // Apply a color generator if needed
244
        $colorGenerator = $this->getColorGenerator(
245
            $input->getOption('palette'),
246
            $input->getOption('palette-type'),
247
            $input->getOption('palettes-file')
248
        );
249
250
        if ($colorGenerator) {
251
            $listBuilder->randomizeColors($colorGenerator);
252
        }
253
254
        // Build the list
255
        $list = $listBuilder->build('list');
256
257
        // Create a cloud builder
258
        $cloudBuilder = CloudBuilder::create($factory)
259
            ->setBackgroundColor($input->getOption('background-color'))
260
            ->setDimension($input->getOption('width'), $input->getOption('height'))
261
            ->setFont($font)
262
            ->setFontSizes($input->getOption('min-font-size'), $input->getOption('max-font-size'))
263
            ->setPlacer($placerName)
264
            ->setSizeGenerator($this->getFontSizeGenerator($input->getOption('font-size-boost')))
265
            ->useList($list)
266
        ;
267
268
        // Render the cloud and show the bounding boxes and the usher if needed
269
        $image = $this->render(
270
            $cloudBuilder,
271
            $factory,
272
            $input->getOption('render-usher') ? $placer : null,
0 ignored issues
show
Bug introduced by
It seems like $input->getOption('rende...sher') ? $placer : null can also be of type object; however, SixtyNine\Cloud\Command\CommandsHelper::render() does only seem to accept null|object<SixtyNine\Cl...Placer\PlacerInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
273
            $input->getOption('render-boxes')
274
        );
275
276
        $this->output($image, $input->getOption('format'), $input->getOption('save-to-file'));
277
    }
278
}
279