TextOnlyComparator::getMatchRatio()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 12
nc 2
nop 1
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 2
rs 9.8666
c 0
b 0
f 0
1
<?php
2
/**
3
 * (c) Steve Nebes <[email protected]>
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
declare(strict_types=1);
10
11
namespace SN\DaisyDiff\Html\Ancestor;
12
13
use SN\DaisyDiff\Html\Dom\TagNode;
14
use SN\DaisyDiff\Html\Dom\TextNode;
15
use SN\DaisyDiff\RangeDifferencer\Core\LCSSettings;
16
use SN\DaisyDiff\RangeDifferencer\RangeComparatorInterface;
17
use SN\DaisyDiff\RangeDifferencer\RangeDifferencer;
18
19
/**
20
 * A comparator that compares only the elements of text inside a given tag.
21
 */
22
class TextOnlyComparator implements RangeComparatorInterface
23
{
24
    /** @var TextNode[] */
25
    private $leafs = [];
26
27
    /**
28
     * Default values.
29
     *
30
     * @param TagNode $tree
31
     */
32 8
    public function __construct(TagNode $tree)
33
    {
34 8
        $this->addRecursive($tree);
35 8
    }
36
37
    /**
38
     * @param TagNode $tree
39
     */
40 8
    private function addRecursive(TagNode $tree): void
41
    {
42 8
        foreach ($tree as $child) {
43 8
            if ($child instanceof TagNode) {
44 8
                $this->addRecursive($child);
45 8
            } elseif ($child instanceof TextNode) {
46 8
                $this->leafs[] = $child;
47
            }
48
        }
49 8
    }
50
51
    /**
52
     * @return int
53
     */
54 4
    public function getRangeCount(): int
55
    {
56 4
        return \count($this->leafs);
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 4
    public function rangesEqual(int $thisIndex, RangeComparatorInterface $other, int $otherIndex): bool
63
    {
64 4
        if ($other instanceof TextOnlyComparator) {
65 4
            return $this->getLeaf($thisIndex)->isSameText($other->getLeaf($otherIndex));
66
        }
67
68
        return false; // @codeCoverageIgnore
69
    }
70
71
    /**
72
     * @param int $index
73
     * @return TextNode
74
     *
75
     * @throws \OutOfBoundsException
76
     */
77 5
    public function getLeaf(int $index): TextNode
78
    {
79 5
        if (isset($this->leafs[$index])) {
80 4
            return $this->leafs[$index];
81
        }
82
83 1
        throw new \OutOfBoundsException(\sprintf('Index: %d, Size: %d', $index, \count($this->leafs)));
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 1
    public function skipRangeComparison(int $length, int $maxLength, RangeComparatorInterface $other): bool
90
    {
91 1
        return false;
92
    }
93
94
    /**
95
     * @param TextOnlyComparator $other
96
     * @return float
97
     */
98 3
    public function getMatchRatio(TextOnlyComparator $other): float
99
    {
100 3
        $settings = new LCSSettings();
101 3
        $settings->setUseGreedyMethod(true);
102 3
        $settings->setPowLimit(1.5);
103 3
        $settings->setTooLong(150 * 150);
104
105 3
        $differences = RangeDifferencer::findDifferences($other, $this, $settings);
106 3
        $distanceOther = 0;
107 3
        $distanceThis = 0;
108
109 3
        foreach ($differences as $d) {
110 3
            $distanceOther += $d->getLeftLength();
111 3
            $distanceThis += $d->getRightLength();
112
        }
113
114 3
        return (float) ((0.0 + $distanceOther) / $other->getRangeCount() +
115 3
                (0.0 + $distanceThis) / $this->getRangeCount()) / 2;
116
    }
117
}
118