Completed
Push — master ( 5fb76c...11bae5 )
by Mark
32s queued 28s
created

Formula::convertCellReferences()   B

Complexity

Conditions 10
Paths 73

Size

Total Lines 57
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 10.0158

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 57
ccs 35
cts 37
cp 0.9459
rs 7.6666
c 0
b 0
f 0
cc 10
nc 73
nop 2
crap 10.0158

How to fix   Long Method    Complexity   

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 PhpOffice\PhpSpreadsheet\Writer\Ods;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6
use PhpOffice\PhpSpreadsheet\DefinedName;
7
8
class Formula
9
{
10
    /** @var array */
11
    private $definedNames = [];
12
13
    /**
14
     * @param DefinedName[] $definedNames
15
     */
16 24
    public function __construct(array $definedNames)
17
    {
18 24
        foreach ($definedNames as $definedName) {
19 2
            $this->definedNames[] = $definedName->getName();
20
        }
21
    }
22
23 6
    public function convertFormula(string $formula, string $worksheetName = ''): string
24
    {
25 6
        $formula = $this->convertCellReferences($formula, $worksheetName);
26 6
        $formula = $this->convertDefinedNames($formula);
27
28 6
        if (substr($formula, 0, 1) !== '=') {
29
            $formula = '=' . $formula;
30
        }
31
32 6
        return 'of:' . $formula;
33
    }
34
35 6
    private function convertDefinedNames(string $formula): string
36
    {
37 6
        $splitCount = preg_match_all(
38 6
            '/' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '/mui',
39 6
            $formula,
40 6
            $splitRanges,
41 6
            PREG_OFFSET_CAPTURE
42 6
        );
43
44 6
        $lengths = array_map('strlen', array_column($splitRanges[0], 0));
45 6
        $offsets = array_column($splitRanges[0], 1);
46 6
        $values = array_column($splitRanges[0], 0);
47
48 6
        while ($splitCount > 0) {
49 6
            --$splitCount;
50 6
            $length = $lengths[$splitCount];
51 6
            $offset = $offsets[$splitCount];
52 6
            $value = $values[$splitCount];
53
54 6
            if (in_array($value, $this->definedNames, true)) {
55 1
                $formula = substr($formula, 0, $offset) . '$$' . $value . substr($formula, $offset + $length);
56
            }
57
        }
58
59 6
        return $formula;
60
    }
61
62 6
    private function convertCellReferences(string $formula, string $worksheetName): string
63
    {
64 6
        $splitCount = preg_match_all(
65 6
            '/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/mui',
66 6
            $formula,
67 6
            $splitRanges,
68 6
            PREG_OFFSET_CAPTURE
69 6
        );
70
71 6
        $lengths = array_map('strlen', array_column($splitRanges[0], 0));
72 6
        $offsets = array_column($splitRanges[0], 1);
73
74 6
        $worksheets = $splitRanges[2];
75 6
        $columns = $splitRanges[6];
76 6
        $rows = $splitRanges[7];
77
78
        // Replace any commas in the formula with semi-colons for Ods
79
        // If by chance there are commas in worksheet names, then they will be "fixed" again in the loop
80
        //    because we've already extracted worksheet names with our preg_match_all()
81 6
        $formula = str_replace(',', ';', $formula);
82 6
        while ($splitCount > 0) {
83 4
            --$splitCount;
84 4
            $length = $lengths[$splitCount];
85 4
            $offset = $offsets[$splitCount];
86 4
            $worksheet = $worksheets[$splitCount][0];
87 4
            $column = $columns[$splitCount][0];
88 4
            $row = $rows[$splitCount][0];
89
90 4
            $newRange = '';
91 4
            if (empty($worksheet)) {
92 4
                if (($offset === 0) || ($formula[$offset - 1] !== ':')) {
93
                    // We need a worksheet
94 4
                    $worksheet = $worksheetName;
95
                }
96
            } else {
97
                $worksheet = str_replace("''", "'", trim($worksheet, "'"));
98
            }
99 4
            if (!empty($worksheet)) {
100
                $newRange = "['" . str_replace("'", "''", $worksheet) . "'";
101 4
            } elseif (substr($formula, $offset - 1, 1) !== ':') {
102 4
                $newRange = '[';
103
            }
104 4
            $newRange .= '.';
105
106 4
            if (!empty($column)) {
107 4
                $newRange .= $column;
108
            }
109 4
            if (!empty($row)) {
110 4
                $newRange .= $row;
111
            }
112
            // close the wrapping [] unless this is the first part of a range
113 4
            $newRange .= substr($formula, $offset + $length, 1) !== ':' ? ']' : '';
114
115 4
            $formula = substr($formula, 0, $offset) . $newRange . substr($formula, $offset + $length);
116
        }
117
118 6
        return $formula;
119
    }
120
}
121