Failed Conditions
Pull Request — master (#4127)
by Owen
39:04 queued 27:50
created

CurrencyBase::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
dl 0
loc 18
ccs 9
cts 9
cp 1
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 8
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard;
4
5
use NumberFormatter;
6
use PhpOffice\PhpSpreadsheet\Exception;
7
8
class CurrencyBase extends Number
9
{
10
    public const LEADING_SYMBOL = true;
11
12
    public const TRAILING_SYMBOL = false;
13
14
    public const SYMBOL_WITH_SPACING = true;
15
16
    public const SYMBOL_WITHOUT_SPACING = false;
17
18
    protected string $currencyCode = '$';
19
20
    protected bool $currencySymbolPosition = self::LEADING_SYMBOL;
21
22
    protected bool $currencySymbolSpacing = self::SYMBOL_WITHOUT_SPACING;
23
24
    protected const DEFAULT_STRIP_LEADING_RLM = false;
25
26
    protected bool $stripLeadingRLM = self::DEFAULT_STRIP_LEADING_RLM;
27
28
    public const DEFAULT_NEGATIVE = CurrencyNegative::minus;
29
30
    protected CurrencyNegative $negative = CurrencyNegative::minus;
31
32
    protected ?bool $overrideSpacing = null;
33
34
    protected ?CurrencyNegative $overrideNegative = null;
35
36
    // Not sure why original code uses nbsp
37
    private string $spaceOrNbsp = ' '; // or "\u{a0}"
38
39
    /**
40
     * @param string $currencyCode the currency symbol or code to display for this mask
41
     * @param int $decimals number of decimal places to display, in the range 0-30
42
     * @param bool $thousandsSeparator indicator whether the thousands separator should be used, or not
43
     * @param bool $currencySymbolPosition indicates whether the currency symbol comes before or after the value
44
     *              Possible values are Currency::LEADING_SYMBOL and Currency::TRAILING_SYMBOL
45
     * @param bool $currencySymbolSpacing indicates whether there is spacing between the currency symbol and the value
46
     *              Possible values are Currency::SYMBOL_WITH_SPACING and Currency::SYMBOL_WITHOUT_SPACING
47
     *              However, Currency always uses WITHOUT and Accounting always uses WITH
48
     * @param ?string $locale Set the locale for the currency format; or leave as the default null.
49
     *          If provided, Locale values must be a valid formatted locale string (e.g. 'en-GB', 'fr', uz-Arab-AF).
50
     *          Note that setting a locale will override any other settings defined in this class
51
     *          other than the currency code; or decimals (unless the decimals value is set to 0).
52
     * @param bool $stripLeadingRLM remove leading RLM added with
53
     *          ICU 72.1+.
54
     * @param CurrencyNegative $negative How to display negative numbers.
55
     *                         Always use parentheses for Accounting.
56
     *                         4 options for Currency.
57
     *
58
     * @throws Exception If a provided locale code is not a valid format
59
     */
60 56
    public function __construct(
61
        string $currencyCode = '$',
62
        int $decimals = 2,
63
        bool $thousandsSeparator = true,
64
        bool $currencySymbolPosition = self::LEADING_SYMBOL,
65
        bool $currencySymbolSpacing = self::SYMBOL_WITHOUT_SPACING,
66
        ?string $locale = null,
67
        bool $stripLeadingRLM = self::DEFAULT_STRIP_LEADING_RLM,
68
        CurrencyNegative $negative = CurrencyNegative::minus
69
    ) {
70 56
        $this->setCurrencyCode($currencyCode);
71 56
        $this->setThousandsSeparator($thousandsSeparator);
72 56
        $this->setDecimals($decimals);
73 56
        $this->setCurrencySymbolPosition($currencySymbolPosition);
74 56
        $this->setCurrencySymbolSpacing($currencySymbolSpacing);
75 56
        $this->setLocale($locale);
76 56
        $this->stripLeadingRLM = $stripLeadingRLM;
77 56
        $this->negative = $negative;
78
    }
79
80 56
    public function setCurrencyCode(string $currencyCode): void
81
    {
82 56
        $this->currencyCode = $currencyCode;
83
    }
84
85 56
    public function setCurrencySymbolPosition(bool $currencySymbolPosition = self::LEADING_SYMBOL): void
86
    {
87 56
        $this->currencySymbolPosition = $currencySymbolPosition;
88
    }
89
90 56
    public function setCurrencySymbolSpacing(bool $currencySymbolSpacing = self::SYMBOL_WITHOUT_SPACING): void
91
    {
92 56
        $this->currencySymbolSpacing = $currencySymbolSpacing;
93
    }
94
95 6
    public function setStripLeadingRLM(bool $stripLeadingRLM): void
96
    {
97 6
        $this->stripLeadingRLM = $stripLeadingRLM;
98
    }
99
100
    public function setNegative(CurrencyNegative $negative): void
101
    {
102
        $this->negative = $negative;
103
    }
104
105 20
    protected function getLocaleFormat(): string
106
    {
107 20
        $formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY);
108 19
        $mask = $formatter->format($this->stripLeadingRLM);
109 19
        if ($this->decimals === 0) {
110 9
            $mask = (string) preg_replace('/\.0+/miu', '', $mask);
111
        }
112
113 19
        return str_replace('¤', $this->formatCurrencyCode(), $mask);
114
    }
115
116 19
    private function formatCurrencyCode(): string
117
    {
118 19
        if ($this->locale === null) {
119
            return $this->currencyCode;
120
        }
121
122 19
        return "[\${$this->currencyCode}-{$this->locale}]";
123
    }
124
125 52
    public function format(): string
126
    {
127 52
        if ($this->localeFormat !== null) {
128 38
            return $this->localeFormat;
129
        }
130 14
        $symbolWithSpacing = $this->overrideSpacing ?? ($this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING);
131 14
        $negative = $this->overrideNegative ?? $this->negative;
132
133
        // format if positive
134 14
        $format = '_(';
135 14
        if ($this->currencySymbolPosition === self::LEADING_SYMBOL) {
136 7
            $format .= '"' . $this->currencyCode . '"';
137 7
            if (preg_match('/^[A-Z]{3}$/i', $this->currencyCode) === 1) {
138 1
                $format .= $this->spaceOrNbsp;
139
            }
140 7
            if (preg_match('/^[A-Z]{3}$/i', $this->currencyCode) === 1) {
141 1
                $format .= $this->spaceOrNbsp;
142
            }
143 7
            if ($symbolWithSpacing) {
144 4
                $format .= '*' . $this->spaceOrNbsp;
145
            }
146
        }
147 14
        $format .= $this->thousandsSeparator ? '#,##0' : '0';
148 14
        if ($this->decimals > 0) {
149 8
            $format .= '.' . str_repeat('0', $this->decimals);
150
        }
151 14
        if ($this->currencySymbolPosition === self::TRAILING_SYMBOL) {
152 8
            if ($symbolWithSpacing) {
153 4
                $format .= $this->spaceOrNbsp;
154 5
            } elseif (preg_match('/^[A-Z]{3}$/i', $this->currencyCode) === 1) {
155
                $format .= $this->spaceOrNbsp;
156
            }
157 8
            $format .= '[$' . $this->currencyCode . ']';
158
        }
159 14
        $format .= '_)';
160
161
        // format if negative
162 14
        $format .= ';_(';
163 14
        $format .= $negative->color();
164 14
        $negativeStart = $negative->start();
165 14
        if ($this->currencySymbolPosition === self::LEADING_SYMBOL) {
166 7
            if ($negativeStart === '-' && !$symbolWithSpacing) {
167 4
                $format .= $negativeStart;
168
            }
169 7
            $format .= '"' . $this->currencyCode . '"';
170 7
            if (preg_match('/^[A-Z]{3}$/i', $this->currencyCode) === 1) {
171 1
                $format .= $this->spaceOrNbsp;
172
            }
173 7
            if ($symbolWithSpacing) {
174 4
                $format .= '*' . $this->spaceOrNbsp;
175
            }
176 7
            if ($negativeStart === '\\(' || ($symbolWithSpacing && $negativeStart === '-')) {
177 4
                $format .= $negativeStart;
178
            }
179
        } else {
180 8
            $format .= $negative->start();
181
        }
182 14
        $format .= $this->thousandsSeparator ? '#,##0' : '0';
183 14
        if ($this->decimals > 0) {
184 8
            $format .= '.' . str_repeat('0', $this->decimals);
185
        }
186 14
        $format .= $negative->end();
187 14
        if ($this->currencySymbolPosition === self::TRAILING_SYMBOL) {
188 8
            if ($symbolWithSpacing) {
189
                // Do nothing - I can't figure out how to get
190
                // everything to align if I put any kind of space here.
191
                //$format .= "\u{2009}";
192 5
            } elseif (preg_match('/^[A-Z]{3}$/i', $this->currencyCode) === 1) {
193
                $format .= $this->spaceOrNbsp;
194
            }
195 8
            $format .= '[$' . $this->currencyCode . ']';
196
        }
197 14
        if ($this->currencySymbolPosition === self::TRAILING_SYMBOL) {
198 8
            $format .= '_)';
199 7
        } elseif ($symbolWithSpacing && $negativeStart === '-') {
200 1
            $format .= ' ';
201
        }
202
        // format if zero
203 14
        $format .= ';_(';
204 14
        if ($this->currencySymbolPosition === self::LEADING_SYMBOL) {
205 7
            $format .= '"' . $this->currencyCode . '"';
206
        }
207 14
        if ($symbolWithSpacing) {
208 7
            if ($this->currencySymbolPosition === self::LEADING_SYMBOL) {
209 4
                $format .= '*' . $this->spaceOrNbsp;
210
            }
211 7
            $format .= '"-"';
212 7
            if ($this->decimals > 0) {
213 4
                $format .= str_repeat('?', $this->decimals);
214
            }
215
        } else {
216 8
            if (preg_match('/^[A-Z]{3}$/i', $this->currencyCode) === 1) {
217 1
                $format .= $this->spaceOrNbsp;
218
            }
219 8
            $format .= '0';
220 8
            if ($this->decimals > 0) {
221 5
                $format .= '.' . str_repeat('0', $this->decimals);
222
            }
223
        }
224 14
        if ($this->currencySymbolPosition === self::TRAILING_SYMBOL) {
225 8
            if ($symbolWithSpacing) {
226 4
                $format .= $this->spaceOrNbsp;
227
            }
228 8
            $format .= '[$' . $this->currencyCode . ']';
229
        }
230 14
        $format .= '_)';
231
        // format if text
232 14
        $format .= ';_(@_)';
233
234 14
        return $format;
235
    }
236
}
237