Failed Conditions
Pull Request — master (#4127)
by Owen
12:31
created

CurrencyBase::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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

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