Completed
Push — master ( a57611...81b80f )
by Dan
09:00 queued 06:05
created

CommandsHelper::createCloud()   C

Complexity

Conditions 8
Paths 32

Size

Total Lines 91
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 91
rs 5.574
c 1
b 0
f 0
cc 8
eloc 56
nc 32
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
use Webmozart\Assert\Assert;
23
24
class CommandsHelper
25
{
26
    protected $allowedFontSizeBoosts = array('linear', 'dim', 'boost');
27
    protected $allowedPaletteTypes = array('cycle', 'random');
28
    protected $allowedOutputFormats = array('gif', 'jpeg', 'png');
29
30
    /**
31
     * @param string $name
32
     * @return PlacerInterface
33
     * @throws \InvalidArgumentException
34
     */
35
    public function getPlacer($name)
36
    {
37
        $availablePlacers = PlacerFactory::getInstance()->getPlacersNames();
38
39
        if ($name) {
40
            Assert::oneOf($name, $availablePlacers, 'Word placer not found: ' . $name);
41
            return $name;
42
        }
43
44
        Assert::notEmpty($availablePlacers, 'No word placers available');
45
        return $availablePlacers[0];
46
    }
47
48
    /**
49
     * @param FontsFactory $factory
50
     * @param string $font
51
     * @return string
52
     * @throws \InvalidArgumentException
53
     */
54
    public function getFont(FontsFactory $factory, $font)
55
    {
56
        if ($font) {
57
            return $font;
58
        }
59
60
        Assert::notEmpty($factory->getFonts(), 'No font file found');
61
        return $factory->getFonts()[0];
62
    }
63
64
    /**
65
     * @param string $type
66
     * @return FontSizeGeneratorInterface
67
     * @throws \InvalidArgumentException
68
     */
69
    public function getFontSizeGenerator($type = 'linear')
70
    {
71
        Assert::oneOf($type, $this->allowedFontSizeBoosts, 'Invalid font size boost: ' . $type);
72
73
        $generatorClass = LinearFontSizeGenerator::class;
74
        if ($type === 'dim') {
75
            $generatorClass = DimFontSizeGenerator::class;
76
        }
77
        if ($type === 'boost') {
78
            $generatorClass = BoostFontSizeGenerator::class;
79
        }
80
81
        return new $generatorClass();
82
    }
83
84
    /**
85
     * @param string $paletteName
86
     * @param string $paletteType
87
     * @param string $palettesFile
88
     * @return bool|ColorGeneratorInterface
89
     * @throws \InvalidArgumentException
90
     */
91
    public function getColorGenerator($paletteName, $paletteType, $palettesFile = null)
92
    {
93
        if ($paletteName && $paletteType) {
94
95
            Assert::oneOf($paletteType, $this->allowedPaletteTypes, 'Palette type must be either "cycle" or "random"');
96
97
            $file = $palettesFile
98
                ? $palettesFile
99
                : __DIR__ . '/../Resources/palettes.yml'
100
            ;
101
            $paletteBuilder = PalettesBuilder::create()->importPalettes($file);
102
103
            $palette = $paletteBuilder->getNamedPalette($paletteName);
104
            $generatorClass = ($paletteType === 'cycle')
105
                ? RotateColorGenerator::class
106
                : RandomColorGenerator::class
107
            ;
108
            return new $generatorClass($palette);
109
        }
110
111
        return false;
112
    }
113
114
    /**
115
     * @param ImageInterface $image
116
     * @param string $outputFormat
117
     * @param string $outputFile
118
     * @throws \InvalidArgumentException
119
     */
120
    public function output(ImageInterface $image, $outputFormat, $outputFile = null)
121
    {
122
        Assert::oneOf($outputFormat, $this->allowedOutputFormats, 'Invalid output format: ' . $outputFormat);
123
124
        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...
125
            $image->save($outputFile, array('format' => $outputFormat));
126
            return;
127
        }
128
129
        echo $image->get($outputFormat);
130
    }
131
132
    /**
133
     * @param CloudBuilder $cloudBuilder
134
     * @param FontsFactory $factory
135
     * @param PlacerInterface $placer
136
     * @param bool $renderBoxes
137
     * @return \Imagine\Gd\Image|ImageInterface
138
     */
139
    protected function render(CloudBuilder $cloudBuilder, FontsFactory $factory, PlacerInterface $placer = null, $renderBoxes = false)
140
    {
141
        $renderer = new CloudRenderer();
142
        $image = $renderer->render($cloudBuilder->build(), $factory, $renderBoxes);
143
144
        if ($placer) {
145
            $renderer->renderUsher($image, $placer, '#FF0000');
146
        }
147
148
        return $image;
149
    }
150
151
    public function getFilterBuilder(
152
        $minWordLength,
153
        $maxWordLength,
154
        $changeCase = null,
155
        $noRemoveNumbers = false,
156
        $noRemoveUnwanted = false,
157
        $noRemoveTrailing = false
158
    ) {
159
        $filtersBuilder = FiltersBuilder::create()
160
            ->setMinLength($minWordLength)
161
            ->setMaxLength($maxWordLength)
162
            ->setRemoveNumbers(!$noRemoveNumbers)
163
            ->setRemoveUnwanted(!$noRemoveTrailing)
164
            ->setRemoveTrailing(!$noRemoveUnwanted)
165
        ;
166
167
        if ($changeCase && in_array($changeCase, $filtersBuilder->getAllowedCase())) {
168
            $filtersBuilder->setCase($changeCase);
169
        }
170
171
        return $filtersBuilder;
172
    }
173
174
    /**
175
     * @param string $type
176
     * @param InputInterface $input
177
     * @throws \InvalidArgumentException
178
     */
179
    public function createCloud($type, InputInterface $input)
180
    {
181
        Assert::oneOf($type, array('from-url', 'from-file'), 'Invalid type for createCloud: ' . $type);
182
183
        // Build the filters
184
        $filtersBuilder = $this->getFilterBuilder(
185
            $input->getOption('min-word-length'),
186
            $input->getOption('max-word-length'),
187
            $input->getOption('case'),
188
            $input->getOption('no-remove-numbers'),
189
            $input->getOption('no-remove-unwanted'),
190
            $input->getOption('no-remove-trailing')
191
        );
192
193
        // Create a placer
194
        $placerName = $this->getPlacer($input->getOption('placer'));
195
        $placer = PlacerFactory::getInstance()->getPlacer(
196
            $placerName,
197
            $input->getOption('width'),
198
            $input->getOption('height')
199
        );
200
201
        // Get the font file
202
        $fontsPath = $input->getOption('fonts-path')
203
            ? realpath($input->getOption('fonts-path'))
204
            : constant('BASE_PATH') . '/fonts'
205
        ;
206
        $factory = FontsFactory::create($fontsPath);
207
        $font = $this->getFont($factory, $input->getOption('font'));
208
209
        // Create the list builder
210
        $listBuilder = WordsListBuilder::create()
211
            ->setMaxWords($input->getOption('max-word-count'))
212
            ->setFilters($filtersBuilder->build())
213
            ->randomizeOrientation($input->getOption('vertical-probability'))
214
        ;
215
216
        if ($type === 'from-file') {
217
            $file = $input->getArgument('file');
218
            Assert::fileExists($file, 'File not found: ' . $file);
219
            $listBuilder->importWords(file_get_contents($file));
220
        } else {
221
            $listBuilder->importUrl($input->getArgument('url'));
222
        }
223
224
        $sortBy = $input->getOption('sort-by');
225
        $sortOrder = $input->getOption('sort-order');
226
227
        if ($sortBy && $sortOrder) {
228
            $listBuilder->sort($sortBy, $sortOrder);
229
        }
230
231
        // Apply a color generator if needed
232
        $colorGenerator = $this->getColorGenerator(
233
            $input->getOption('palette'),
234
            $input->getOption('palette-type'),
235
            $input->getOption('palettes-file')
236
        );
237
238
        if ($colorGenerator) {
239
            $listBuilder->randomizeColors($colorGenerator);
240
        }
241
242
        // Build the list
243
        $list = $listBuilder->build('list');
244
245
        // Create a cloud builder
246
        $cloudBuilder = CloudBuilder::create($factory)
247
            ->setBackgroundColor($input->getOption('background-color'))
248
            ->setDimension($input->getOption('width'), $input->getOption('height'))
249
            ->setFont($font)
250
            ->setFontSizes($input->getOption('min-font-size'), $input->getOption('max-font-size'))
251
            ->setPlacer($placerName)
252
            ->setSizeGenerator($this->getFontSizeGenerator($input->getOption('font-size-boost')))
253
            ->useList($list)
254
        ;
255
256
        if ($input->getOption('precise')) {
257
            $cloudBuilder->setPrecise();
258
        }
259
260
        // Render the cloud and show the bounding boxes and the usher if needed
261
        $image = $this->render(
262
            $cloudBuilder,
263
            $factory,
264
            $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...
265
            $input->getOption('render-boxes')
266
        );
267
268
        $this->output($image, $input->getOption('format'), $input->getOption('save-to-file'));
269
    }
270
}
271