Completed
Pull Request — feat/html-splitter (#182)
by Nuno
14:37 queued 10:11
created

NodeCollection::findWeight()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Scout Extended.
7
 *
8
 * (c) Algolia Team <[email protected]>
9
 *
10
 *  For the full copyright and license information, please view the LICENSE
11
 *  file that was distributed with this source code.
12
 */
13
14
namespace Algolia\ScoutExtended\Splitters\HtmlSplitter;
15
16
/**
17
 * @internal
18
 */
19
final class NodeCollection
20
{
21
    /**
22
     * Collection of \Algolia\ScoutExtended\Splitters\HtmlSplitter\Node.
23
     *
24
     * @var array
25
     */
26
    private $nodes = [];
27
28
    /**
29
     * Clone of \Algolia\ScoutExtended\Splitters\HtmlSplitter\NodeCollection.
30
     *
31
     * @var array
32
     */
33
    private $cloneNodes = [];
34
35
    /**
36
     * The list of html tags.
37
     *
38
     * @var string[]
39
     */
40
    private $tags = [];
41
42
    /**
43
     * String.
44
     */
45
    private const IMPORTANCE = 'importance';
46
47
    /**
48
     * String.
49
     */
50
    private const PARAGRAPH = 'p';
51
52
    /**
53
     * NodeCollection constructor.
54
     *
55
     * @param array|null $tags
56
     */
57 5
    public function __construct(array $tags = null)
58
    {
59 5
        if ($tags !== null) {
60 5
            $this->tags = $tags;
61
        }
62 5
    }
63
64
    /**
65
     * Add object to collection.
66
     *
67
     * @param Node $node
68
     */
69 5
    public function push(Node $node): void
70
    {
71 5
        if ($this->lengthNodes() === 0) {
72 5
            $this->nodes[] = $node;
73 5
            $this->cloneNodes();
74 5
        } elseif ($this->findWeight($node) > $this->findWeight(end($this->nodes))) {
75 3
            $this->nodes[] = $node;
76 3
            $this->cloneNodes();
77
        } else {
78 4
            array_pop($this->nodes);
79 4
            $this->push($node);
80
        }
81 5
    }
82
83
    /**
84
     * Convert to array.
85
     *
86
     * @return array
87
     */
88 5
    public function toArray(): array
89
    {
90 5
        $array = [];
91 5
        foreach ($this->cloneNodes as $nodes) {
92 5
            foreach ($nodes as $node) {
93 5
                if ($node instanceof Node) {
94 5
                    $object[$node->getTag()] = $node->getContent();
95
                } else {
96 5
                    $object[self::IMPORTANCE] = $node;
97 5
                    $array[] = $object;
98 5
                    $object = [];
99
                }
100
            }
101
        }
102
103 5
        return $array;
104
    }
105
106
    /**
107
     * Importance need to be add after to avoid polluted queue.
108
     *
109
     * @return void
110
     */
111 5
    private function cloneNodes(): void
112
    {
113 5
        $this->cloneNodes[] = $this->nodes;
114 5
        $this->cloneNodes[] = [self::IMPORTANCE => $this->importanceWeight(end($this->nodes))];
115 5
    }
116
117
    /**
118
     * Importance formula.
119
     * Give integer from tags ranking.
120
     *
121
     * @param Node $node
122
     *
123
     * @return int
124
     */
125 5
    private function importanceWeight(Node $node): int
126
    {
127 5
        if ($node->getTag() === self::PARAGRAPH) {
128 3
            $object = prev($this->nodes);
129 3
            if (empty(end($this->nodes)) || $this->lengthNodes() === 1) {
130
                return 0;
131
            }
132
133 3
            return (count($this->tags) - 1) + $this->findWeight($object);
134
        }
135
136 5
        return $this->findWeight($node);
137
    }
138
139
    /**
140
     * Find weight of current nodes.
141
     *
142
     * @param Node $node
143
     *
144
     * @return int
145
     */
146 5
    private function findWeight(Node $node): int
147
    {
148 5
        return (int) array_search($node->getTag(), $this->tags, true);
149
    }
150
151
    /**
152
     * Give the length of the collection.
153
     *
154
     * @return int
155
     */
156 5
    private function lengthNodes(): int
157
    {
158 5
        return count($this->nodes);
159
    }
160
}
161