Completed
Push — master ( e3c021...83d39e )
by Dan
18:18 queued 08:09
created

WordsList::getWordsCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace SixtyNine\Cloud\Model;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use SixtyNine\Cloud\Color\ColorGeneratorInterface;
7
use SixtyNine\Cloud\Filters\Filters;
8
use JMS\Serializer\Annotation as JMS;
9
10
class WordsList
11
{
12
    const SORT_ALPHA = 'text';
13
    const SORT_COUNT = 'count';
14
    const SORT_ANGLE = 'angle';
15
16
    const SORT_ASC = 'asc';
17
    const SORT_DESC = 'desc';
18
19
    /**
20
     * @var string
21
     * @JMS\Type("string")
22
     */
23
    protected $name;
24
25
    /**
26
     * @var ArrayCollection
27
     * @JMS\Type("ArrayCollection<SixtyNine\Cloud\Model\Word>")
28
     */
29
    protected $words;
30
31
    /**
32
     * @var array
33
     * @JMS\Exclude()
34
     */
35
    protected $allowedSortBy = array(self::SORT_ALPHA, self::SORT_ANGLE, self::SORT_COUNT);
36
37
    /**
38
     * @var array
39
     * @JMS\Exclude()
40
     */
41
    protected $allowedSortOrder = array(self::SORT_ASC, self::SORT_DESC);
42
43
    /**
44
     * Constructor
45
     */
46 8
    public function __construct()
47
    {
48 8
        $this->words = new ArrayCollection();
49 8
    }
50
51
    /**
52
     * @param string $name
53
     * @return $this
54
     */
55 7
    public function setName($name)
56
    {
57 7
        $this->name = $name;
58 7
        return $this;
59
    }
60
61
    /**
62
     * @return string
63
     */
64 3
    public function getName()
65
    {
66 3
        return $this->name;
67
    }
68
69
    /**
70
     * Check if a Word with the same text already exists in the Cloud
71
     * @param string $text
72
     * @return null|Word
73
     */
74 7
    public function getWordForText($text)
75
    {
76
        /** @var Word $word */
77 7
        foreach ($this->words as $word) {
78 7
            if ($word->getText() === $text) {
79 7
                return $word;
80
            }
81
        }
82 7
        return null;
83
    }
84
85
    /**
86
     * @param Word $word
87
     * @return $this
88
     */
89 7
    public function addWord(Word $word)
90
    {
91 7
        if (!$this->words->contains($word)) {
92 7
            $this->words->add($word);
93
        }
94
95 7
        return $this;
96
    }
97
98
    /**
99
     * @param Word $word
100
     * @return $this
101
     */
102
    public function removeWord(Word $word)
103
    {
104
        $this->words->remove($word);
0 ignored issues
show
Documentation introduced by
$word is of type object<SixtyNine\Cloud\Model\Word>, but the function expects a string|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
105
        return $this;
106
    }
107
108
    /**
109
     * @return ArrayCollection
110
     */
111 6
    public function getWords()
112
    {
113 6
        return $this->words;
114
    }
115
116
    /**
117
     * @return ArrayCollection
118
     */
119 3
    public function getWordsOrdered()
120
    {
121 3
        $iterator = $this->words->getIterator();
122
        $iterator->uasort(function ($a, $b) {
123 3
            return ($a->getPosition() < $b->getPosition()) ? -1 : 1;
124 3
        });
125 3
        return new ArrayCollection(iterator_to_array($iterator));
126
    }
127
128
    /**
129
     * @param string $sortBy
130
     * @param string $sortOrder
131
     * @throws \InvalidArgumentException
132
     */
133
    public function sortWords($sortBy, $sortOrder)
134
    {
135
        if (!in_array($sortBy, $this->allowedSortBy)) {
136
            throw new \InvalidArgumentException('Invalid sort by: ' . $sortBy);
137
        }
138
139
        if (!in_array($sortOrder, $this->allowedSortOrder)) {
140
            throw new \InvalidArgumentException('Invalid sort order: ' - $sortOrder);
141
        }
142
143
        $sorter = function ($a, $b) use ($sortBy, $sortOrder) {
144
            $method = $sortBy === self::SORT_ANGLE
145
                ? 'getOrientation'
146
                : 'get' . ucfirst($sortBy)
147
            ;
148
149
            $attr1 = $a->$method();
150
            $attr2 = $b->$method();
151
152
            if ($sortOrder === self::SORT_ASC) {
153
                return $attr1 > $attr2;
154
            }
155
156
            return $attr1 < $attr2;
157
        };
158
159
160
        $iterator = $this->words->getIterator();
161
        $iterator->uasort($sorter);
162
163
        $index = 0;
164
        foreach ($iterator as $word) {
165
            $word->setPosition($index);
166
            $index++;
167
        }
168
    }
169
170
    /**
171
     * @return int
172
     * @JMS\VirtualProperty
173
     * @JMS\SerializedName("max-count")
174
     */
175 4
    public function getWordsMaxCount()
176
    {
177 4
        $max = 0;
178
        /** @var Word $word */
179 4
        foreach ($this->words as $word) {
180 4
            if ($word->getCount() > $max) {
181 4
                $max = $word->getCount();
182
            }
183
        }
184 4
        return $max;
185
    }
186
187
    /**
188
     * @return int
189
     * @JMS\VirtualProperty
190
     * @JMS\SerializedName("count")
191
     */
192 2
    public function getWordsCount()
193
    {
194 2
        return $this->words->count();
195
    }
196
197
    /**
198
     * @param string $words
199
     * @param Filters $filters
200
     * @param int $maxWords
201
     */
202 7
    public function importWords($words, Filters $filters = null, $maxWords = 100)
203
    {
204 7
        $array = preg_split("/[\n\r\t ]+/", $words);
205
206 7
        foreach ($array as $word) {
207 7
            $this->importWord($word, $filters);
208 7
            if ($maxWords && $this->words->count() >= $maxWords) {
209 7
                break;
210
            }
211
        }
212 7
    }
213
214
    /**
215
     * @param string $word
216
     * @param Filters $filters
217
     */
218 7
    public function importWord($word, Filters $filters = null)
219
    {
220 7
        if ($filters) {
221 6
            $word = $filters->apply($word);
222
223 6
            if (!$word) {
224 2
                return;
225
            }
226
        }
227
228 7
        $entity = $this->getWordForText($word);
0 ignored issues
show
Bug introduced by
It seems like $word defined by $filters->apply($word) on line 221 can also be of type boolean; however, SixtyNine\Cloud\Model\WordsList::getWordForText() does only seem to accept string, 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...
229
230 7
        if (!$entity) {
231 7
            $entity = new Word();
232
            $entity
233 7
                ->setList($this)
234 7
                ->setText($word)
0 ignored issues
show
Bug introduced by
It seems like $word defined by $filters->apply($word) on line 221 can also be of type boolean; however, SixtyNine\Cloud\Model\Word::setText() does only seem to accept string, 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...
235 7
                ->setOrientation(Word::DIR_HORIZONTAL)
236 7
                ->setColor('#000000')
237
            ;
238 7
            $this->addWord($entity);
239
        }
240
241 7
        $entity->setCount($entity->getCount() + 1);
242 7
    }
243
244
    /**
245
     * @param string $html
246
     * @param Filters $filters
247
     * @param int $maxWords
248
     */
249 1
    public function importHtml($html, Filters $filters = null, $maxWords = 100)
250
    {
251 1
        if (!$html) {
252
            return;
253
        }
254
255 1
        $d = new \DOMDocument;
256 1
        $mock = new \DOMDocument;
257 1
        libxml_use_internal_errors(true);
258 1
        $d->loadHTML($html);
259 1
        libxml_use_internal_errors(false);
260 1
        $body = $d->getElementsByTagName('body')->item(0);
261 1
        if ($body) {
262 1
            foreach ($body->childNodes as $child) {
263 1
                $mock->appendChild($mock->importNode($child, true));
264
            }
265
        }
266 1
        $text = html_entity_decode(strip_tags($mock->saveHTML()));
267 1
        $this->importWords($text, $filters, $maxWords);
268 1
    }
269
270
    /**
271
     * @param string $url
272
     * @param Filters $filters
273
     * @param int $maxWords
274
     */
275 1
    public function importUrl($url, Filters $filters = null, $maxWords = 100)
276
    {
277 1
        $this->importHtml(file_get_contents($url), $filters, $maxWords);
278 1
    }
279
280
    /**
281
     * Apply the given $filters to the $list.
282
     * @param Filters $filters
283
     */
284
    public function filterWords(Filters $filters)
285
    {
286
        /** @var Word $word */
287
        foreach ($this->getWords() as $word) {
288
            $filtered = $filters->apply($word->getText());
289
            if (!$filtered) {
290
                $this->words->remove($word);
291
                continue;
292
            }
293
            $word->setText($filtered);
294
        }
295
    }
296
297
    /**
298
     * @param int $verticalProbability
299
     */
300 3
    public function randomizeOrientation($verticalProbability = 50)
301
    {
302
        /** @var \SixtyNine\CloudBundle\Entity\Word $word */
303 3
        foreach ($this->getWords() as $word) {
304
305 3
            $orientation = random_int(0, 100) <= $verticalProbability
306 3
                ? Word::DIR_VERTICAL
307 3
                : Word::DIR_HORIZONTAL
308
            ;
309
310 3
            $word->setOrientation($orientation);
311
        }
312 3
    }
313
314
    /**
315
     * @param ColorGeneratorInterface $colorGenerator
316
     */
317 3
    public function randomizeColors(ColorGeneratorInterface $colorGenerator)
318
    {
319
        /** @var \SixtyNine\CloudBundle\Entity\Word $word */
320 3
        foreach ($this->getWords() as $word) {
321 3
            $word->setColor($colorGenerator->getNextColor());
322
        }
323 3
    }
324
325
}
326
327