Completed
Push — develop ( e6c95b...1c5db4 )
by Adrien
32:25
created

Style::getProtection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet;
4
5
/**
6
 * Copyright (c) 2006 - 2016 PhpSpreadsheet.
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 *
22
 * @category   PhpSpreadsheet
23
 *
24
 * @copyright  Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
25
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
26
 */
27
class Style extends Style\Supervisor implements IComparable
28
{
29
    /**
30
     * Font.
31
     *
32
     * @var Style\Font
33
     */
34
    protected $font;
35
36
    /**
37
     * Fill.
38
     *
39
     * @var Style\Fill
40
     */
41
    protected $fill;
42
43
    /**
44
     * Borders.
45
     *
46
     * @var Style\Borders
47
     */
48
    protected $borders;
49
50
    /**
51
     * Alignment.
52
     *
53
     * @var Style\Alignment
54
     */
55
    protected $alignment;
56
57
    /**
58
     * Number Format.
59
     *
60
     * @var Style\NumberFormat
61
     */
62
    protected $numberFormat;
63
64
    /**
65
     * Conditional styles.
66
     *
67
     * @var Style\Conditional[]
68
     */
69
    protected $conditionalStyles;
70
71
    /**
72
     * Protection.
73
     *
74
     * @var Style\Protection
75
     */
76
    protected $protection;
77
78
    /**
79
     * Index of style in collection. Only used for real style.
80
     *
81
     * @var int
82
     */
83
    protected $index;
84
85
    /**
86
     * Use Quote Prefix when displaying in cell editor. Only used for real style.
87
     *
88
     * @var bool
89
     */
90
    protected $quotePrefix = false;
91
92
    /**
93
     * Create a new Style.
94
     *
95
     * @param bool $isSupervisor Flag indicating if this is a supervisor or not
96
     *         Leave this value at default unless you understand exactly what
97
     *    its ramifications are
98
     * @param bool $isConditional Flag indicating if this is a conditional style or not
99
     *       Leave this value at default unless you understand exactly what
100
     *    its ramifications are
101
     */
102 80
    public function __construct($isSupervisor = false, $isConditional = false)
103
    {
104
        // Supervisor?
105 80
        $this->isSupervisor = $isSupervisor;
106
107
        // Initialise values
108 80
        $this->conditionalStyles = [];
109 80
        $this->font = new Style\Font($isSupervisor, $isConditional);
110 80
        $this->fill = new Style\Fill($isSupervisor, $isConditional);
111 80
        $this->borders = new Style\Borders($isSupervisor, $isConditional);
112 80
        $this->alignment = new Style\Alignment($isSupervisor, $isConditional);
113 80
        $this->numberFormat = new Style\NumberFormat($isSupervisor, $isConditional);
114 80
        $this->protection = new Style\Protection($isSupervisor, $isConditional);
115
116
        // bind parent if we are a supervisor
117 80
        if ($isSupervisor) {
118 80
            $this->font->bindParent($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<PhpOffice\PhpSpreadsheet\Style>, but the function expects a object<PhpOffice\PhpSpreadsheet\Style\Style>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
119 80
            $this->fill->bindParent($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<PhpOffice\PhpSpreadsheet\Style>, but the function expects a object<PhpOffice\PhpSpreadsheet\Style\Style>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
120 80
            $this->borders->bindParent($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<PhpOffice\PhpSpreadsheet\Style>, but the function expects a object<PhpOffice\PhpSpreadsheet\Style\Style>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
121 80
            $this->alignment->bindParent($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<PhpOffice\PhpSpreadsheet\Style>, but the function expects a object<PhpOffice\PhpSpreadsheet\Style\Style>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
122 80
            $this->numberFormat->bindParent($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<PhpOffice\PhpSpreadsheet\Style>, but the function expects a object<PhpOffice\PhpSpreadsheet\Style\Style>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
123 80
            $this->protection->bindParent($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<PhpOffice\PhpSpreadsheet\Style>, but the function expects a object<PhpOffice\PhpSpreadsheet\Style\Style>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
124
        }
125 80
    }
126
127
    /**
128
     * Get the shared style component for the currently active cell in currently active sheet.
129
     * Only used for style supervisor.
130
     *
131
     * @return Style
132
     */
133 3
    public function getSharedComponent()
134
    {
135 3
        $activeSheet = $this->getActiveSheet();
136 3
        $selectedCell = $this->getActiveCell(); // e.g. 'A1'
137
138 3
        if ($activeSheet->cellExists($selectedCell)) {
139 3
            $xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex();
140
        } else {
141 1
            $xfIndex = 0;
142
        }
143
144 3
        return $this->parent->getCellXfByIndex($xfIndex);
0 ignored issues
show
Bug introduced by
The method getCellXfByIndex() does not seem to exist on object<PhpOffice\PhpSpreadsheet\Style>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
145
    }
146
147
    /**
148
     * Get parent. Only used for style supervisor.
149
     *
150
     * @return Spreadsheet
151
     */
152
    public function getParent()
153
    {
154
        return $this->parent;
155
    }
156
157
    /**
158
     * Build style array from subcomponents.
159
     *
160
     * @param array $array
161
     *
162
     * @return array
163
     */
164
    public function getStyleArray($array)
165
    {
166
        return ['quotePrefix' => $array];
167
    }
168
169
    /**
170
     * Apply styles from array.
171
     *
172
     * <code>
173
     * $spreadsheet->getActiveSheet()->getStyle('B2')->applyFromArray(
174
     *         array(
175
     *             'font'    => array(
176
     *                 'name'      => 'Arial',
177
     *                 'bold'      => true,
178
     *                 'italic'    => false,
179
     *                 'underline' => \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLE,
180
     *                 'strikethrough'    => false,
181
     *                 'color'     => array(
182
     *                     'rgb' => '808080'
183
     *                 )
184
     *             ),
185
     *             'borders' => array(
186
     *                 'bottom'     => array(
187
     *                     'borderStyle' => Border::BORDER_DASHDOT,
188
     *                     'color' => array(
189
     *                         'rgb' => '808080'
190
     *                     )
191
     *                 ),
192
     *                 'top'     => array(
193
     *                     'borderStyle' => Border::BORDER_DASHDOT,
194
     *                     'color' => array(
195
     *                         'rgb' => '808080'
196
     *                     )
197
     *                 )
198
     *             ),
199
     *             'quotePrefix'    => true
200
     *         )
201
     * );
202
     * </code>
203
     *
204
     * @param array $pStyles Array containing style information
205
     * @param bool $pAdvanced advanced mode for setting borders
206
     *
207
     * @throws Exception
208
     *
209
     * @return Style
210
     */
211 41
    public function applyFromArray(array $pStyles, $pAdvanced = true)
212
    {
213 41
        if ($this->isSupervisor) {
214 40
            $pRange = $this->getSelectedCells();
215
216
            // Uppercase coordinate
217 40
            $pRange = strtoupper($pRange);
218
219
            // Is it a cell range or a single cell?
220 40 View Code Duplication
            if (strpos($pRange, ':') === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221 30
                $rangeA = $pRange;
222 30
                $rangeB = $pRange;
223
            } else {
224 26
                list($rangeA, $rangeB) = explode(':', $pRange);
225
            }
226
227
            // Calculate range outer borders
228 40
            $rangeStart = Cell::coordinateFromString($rangeA);
229 40
            $rangeEnd = Cell::coordinateFromString($rangeB);
230
231
            // Translate column into index
232 40
            $rangeStart[0] = Cell::columnIndexFromString($rangeStart[0]) - 1;
233 40
            $rangeEnd[0] = Cell::columnIndexFromString($rangeEnd[0]) - 1;
234
235
            // Make sure we can loop upwards on rows and columns
236 40 View Code Duplication
            if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
237
                $tmp = $rangeStart;
238
                $rangeStart = $rangeEnd;
239
                $rangeEnd = $tmp;
240
            }
241
242
            // ADVANCED MODE:
243 40
            if ($pAdvanced && isset($pStyles['borders'])) {
244
                // 'allBorders' is a shorthand property for 'outline' and 'inside' and
245
                //        it applies to components that have not been set explicitly
246 17 View Code Duplication
                if (isset($pStyles['borders']['allBorders'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247 1
                    foreach (['outline', 'inside'] as $component) {
248 1
                        if (!isset($pStyles['borders'][$component])) {
249 1
                            $pStyles['borders'][$component] = $pStyles['borders']['allBorders'];
250
                        }
251
                    }
252 1
                    unset($pStyles['borders']['allBorders']); // not needed any more
253
                }
254
                // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left'
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
255
                //        it applies to components that have not been set explicitly
256 17 View Code Duplication
                if (isset($pStyles['borders']['outline'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257 13
                    foreach (['top', 'right', 'bottom', 'left'] as $component) {
258 13
                        if (!isset($pStyles['borders'][$component])) {
259 13
                            $pStyles['borders'][$component] = $pStyles['borders']['outline'];
260
                        }
261
                    }
262 13
                    unset($pStyles['borders']['outline']); // not needed any more
263
                }
264
                // 'inside' is a shorthand property for 'vertical' and 'horizontal'
265
                //        it applies to components that have not been set explicitly
266 17 View Code Duplication
                if (isset($pStyles['borders']['inside'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
267 1
                    foreach (['vertical', 'horizontal'] as $component) {
268 1
                        if (!isset($pStyles['borders'][$component])) {
269 1
                            $pStyles['borders'][$component] = $pStyles['borders']['inside'];
270
                        }
271
                    }
272 1
                    unset($pStyles['borders']['inside']); // not needed any more
273
                }
274
                // width and height characteristics of selection, 1, 2, or 3 (for 3 or more)
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
275 17
                $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3);
276 17
                $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3);
277
278
                // loop through up to 3 x 3 = 9 regions
279 17
                for ($x = 1; $x <= $xMax; ++$x) {
280
                    // start column index for region
281 17
                    $colStart = ($x == 3) ?
282 13
                        Cell::stringFromColumnIndex($rangeEnd[0])
283 17
                            : Cell::stringFromColumnIndex($rangeStart[0] + $x - 1);
284
                    // end column index for region
285 17
                    $colEnd = ($x == 1) ?
286 17
                        Cell::stringFromColumnIndex($rangeStart[0])
287 17
                            : Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x);
288
289 17
                    for ($y = 1; $y <= $yMax; ++$y) {
290
                        // which edges are touching the region
291 17
                        $edges = [];
292 17
                        if ($x == 1) {
293
                            // are we at left edge
294 17
                            $edges[] = 'left';
295
                        }
296 17
                        if ($x == $xMax) {
297
                            // are we at right edge
298 17
                            $edges[] = 'right';
299
                        }
300 17
                        if ($y == 1) {
301
                            // are we at top edge?
302 17
                            $edges[] = 'top';
303
                        }
304 17
                        if ($y == $yMax) {
305
                            // are we at bottom edge?
306 17
                            $edges[] = 'bottom';
307
                        }
308
309
                        // start row index for region
310 17
                        $rowStart = ($y == 3) ?
311 17
                            $rangeEnd[1] : $rangeStart[1] + $y - 1;
312
313
                        // end row index for region
314 17
                        $rowEnd = ($y == 1) ?
315 17
                            $rangeStart[1] : $rangeEnd[1] - $yMax + $y;
316
317
                        // build range for region
318 17
                        $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd;
319
320
                        // retrieve relevant style array for region
321 17
                        $regionStyles = $pStyles;
322 17
                        unset($regionStyles['borders']['inside']);
323
324
                        // what are the inner edges of the region when looking at the selection
325 17
                        $innerEdges = array_diff(['top', 'right', 'bottom', 'left'], $edges);
326
327
                        // inner edges that are not touching the region should take the 'inside' border properties if they have been set
328 17
                        foreach ($innerEdges as $innerEdge) {
329
                            switch ($innerEdge) {
330 15
                                case 'top':
331 15 View Code Duplication
                                case 'bottom':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
332
                                    // should pick up 'horizontal' border property if set
333 15
                                    if (isset($pStyles['borders']['horizontal'])) {
334
                                        $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal'];
335
                                    } else {
336 15
                                        unset($regionStyles['borders'][$innerEdge]);
337
                                    }
338 15
                                    break;
339 15
                                case 'left':
340 15 View Code Duplication
                                case 'right':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
341
                                    // should pick up 'vertical' border property if set
342 15
                                    if (isset($pStyles['borders']['vertical'])) {
343
                                        $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical'];
344
                                    } else {
345 15
                                        unset($regionStyles['borders'][$innerEdge]);
346
                                    }
347 15
                                    break;
348
                            }
349
                        }
350
351
                        // apply region style to region by calling applyFromArray() in simple mode
352 17
                        $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false);
353
                    }
354
                }
355
356 17
                return $this;
357
            }
358
359
            // SIMPLE MODE:
360
            // Selection type, inspect
361 40
            if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) {
362
                $selectionType = 'COLUMN';
363 40
            } elseif (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) {
364
                $selectionType = 'ROW';
365
            } else {
366 40
                $selectionType = 'CELL';
367
            }
368
369
            // First loop through columns, rows, or cells to find out which styles are affected by this operation
370
            switch ($selectionType) {
371 40
                case 'COLUMN':
372
                    $oldXfIndexes = [];
373 View Code Duplication
                    for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
374
                        $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true;
375
                    }
376
                    break;
377 40
                case 'ROW':
378
                    $oldXfIndexes = [];
379
                    for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
380
                        if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) {
381
                            $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style
382
                        } else {
383
                            $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true;
384
                        }
385
                    }
386
                    break;
387 40
                case 'CELL':
388 40
                    $oldXfIndexes = [];
389 40
                    for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
390 40 View Code Duplication
                        for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
391 40
                            $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true;
392
                        }
393
                    }
394 40
                    break;
395
            }
396
397
            // clone each of the affected styles, apply the style array, and add the new styles to the workbook
398 40
            $workbook = $this->getActiveSheet()->getParent();
399 40
            foreach ($oldXfIndexes as $oldXfIndex => $dummy) {
0 ignored issues
show
Bug introduced by
The variable $oldXfIndexes does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
400 40
                $style = $workbook->getCellXfByIndex($oldXfIndex);
401 40
                $newStyle = clone $style;
402 40
                $newStyle->applyFromArray($pStyles);
403
404 40
                if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) {
405
                    // there is already such cell Xf in our collection
406 30
                    $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$newXfIndexes was never initialized. Although not strictly required by PHP, it is generally a good practice to add $newXfIndexes = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
407
                } else {
408
                    // we don't have such a cell Xf, need to add
409 40
                    $workbook->addCellXf($newStyle);
410 40
                    $newXfIndexes[$oldXfIndex] = $newStyle->getIndex();
0 ignored issues
show
Bug introduced by
The variable $newXfIndexes does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
411
                }
412
            }
413
414
            // Loop through columns, rows, or cells again and update the XF index
415
            switch ($selectionType) {
416 40 View Code Duplication
                case 'COLUMN':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
417
                    for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
418
                        $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col);
419
                        $oldXfIndex = $columnDimension->getXfIndex();
420
                        $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
421
                    }
422
                    break;
423 40 View Code Duplication
                case 'ROW':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
424
                    for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
425
                        $rowDimension = $this->getActiveSheet()->getRowDimension($row);
426
                        $oldXfIndex = $rowDimension->getXfIndex() === null ?
427
                            0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style
428
                        $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
429
                    }
430
                    break;
431 40
                case 'CELL':
432 40
                    for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
433 40
                        for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
434 40
                            $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row);
435 40
                            $oldXfIndex = $cell->getXfIndex();
436 40
                            $cell->setXfIndex($newXfIndexes[$oldXfIndex]);
437
                        }
438
                    }
439 40
                    break;
440
            }
441
        } else {
442
            // not a supervisor, just apply the style array directly on style object
443 41
            if (isset($pStyles['fill'])) {
444 18
                $this->getFill()->applyFromArray($pStyles['fill']);
445
            }
446 41
            if (isset($pStyles['font'])) {
447 23
                $this->getFont()->applyFromArray($pStyles['font']);
448
            }
449 41
            if (isset($pStyles['borders'])) {
450 18
                $this->getBorders()->applyFromArray($pStyles['borders']);
451
            }
452 41
            if (isset($pStyles['alignment'])) {
453 21
                $this->getAlignment()->applyFromArray($pStyles['alignment']);
454
            }
455 41
            if (isset($pStyles['numberFormat'])) {
456 30
                $this->getNumberFormat()->applyFromArray($pStyles['numberFormat']);
457
            }
458 41
            if (isset($pStyles['protection'])) {
459 13
                $this->getProtection()->applyFromArray($pStyles['protection']);
460
            }
461 41
            if (isset($pStyles['quotePrefix'])) {
462 1
                $this->quotePrefix = $pStyles['quotePrefix'];
463
            }
464
        }
465
466 41
        return $this;
467
    }
468
469
    /**
470
     * Get Fill.
471
     *
472
     * @return Style\Fill
473
     */
474 65
    public function getFill()
475
    {
476 65
        return $this->fill;
477
    }
478
479
    /**
480
     * Get Font.
481
     *
482
     * @return Style\Font
483
     */
484 65
    public function getFont()
485
    {
486 65
        return $this->font;
487
    }
488
489
    /**
490
     * Set font.
491
     *
492
     * @param Style\Font $font
493
     *
494
     * @return Style
495
     */
496 4
    public function setFont(Style\Font $font)
497
    {
498 4
        $this->font = $font;
499
500 4
        return $this;
501
    }
502
503
    /**
504
     * Get Borders.
505
     *
506
     * @return Style\Borders
507
     */
508 63
    public function getBorders()
509
    {
510 63
        return $this->borders;
511
    }
512
513
    /**
514
     * Get Alignment.
515
     *
516
     * @return Style\Alignment
517
     */
518 63
    public function getAlignment()
519
    {
520 63
        return $this->alignment;
521
    }
522
523
    /**
524
     * Get Number Format.
525
     *
526
     * @return Style\NumberFormat
527
     */
528 71
    public function getNumberFormat()
529
    {
530 71
        return $this->numberFormat;
531
    }
532
533
    /**
534
     * Get Conditional Styles. Only used on supervisor.
535
     *
536
     * @return Style\Conditional[]
537
     */
538 2
    public function getConditionalStyles()
539
    {
540 2
        return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell());
541
    }
542
543
    /**
544
     * Set Conditional Styles. Only used on supervisor.
545
     *
546
     * @param Style\Conditional[] $pValue Array of conditional styles
547
     *
548
     * @return Style
549
     */
550 2
    public function setConditionalStyles(array $pValue)
551
    {
552 2
        $this->getActiveSheet()->setConditionalStyles($this->getSelectedCells(), $pValue);
553
554 2
        return $this;
555
    }
556
557
    /**
558
     * Get Protection.
559
     *
560
     * @return Style\Protection
561
     */
562 62
    public function getProtection()
563
    {
564 62
        return $this->protection;
565
    }
566
567
    /**
568
     * Get quote prefix.
569
     *
570
     * @return bool
571
     */
572 56
    public function getQuotePrefix()
573
    {
574 56
        if ($this->isSupervisor) {
575
            return $this->getSharedComponent()->getQuotePrefix();
576
        }
577
578 56
        return $this->quotePrefix;
579
    }
580
581
    /**
582
     * Set quote prefix.
583
     *
584
     * @param bool $pValue
585
     */
586 9
    public function setQuotePrefix($pValue)
587
    {
588 9
        if ($pValue == '') {
589 8
            $pValue = false;
590
        }
591 9
        if ($this->isSupervisor) {
592 1
            $styleArray = ['quotePrefix' => $pValue];
593 1
            $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
594
        } else {
595 8
            $this->quotePrefix = (bool) $pValue;
596
        }
597
598 9
        return $this;
599
    }
600
601
    /**
602
     * Get hash code.
603
     *
604
     * @return string Hash code
605
     */
606 70
    public function getHashCode()
607
    {
608 70
        $hashConditionals = '';
609 70
        foreach ($this->conditionalStyles as $conditional) {
610
            $hashConditionals .= $conditional->getHashCode();
611
        }
612
613 70
        return md5(
614 70
            $this->fill->getHashCode() .
615 70
            $this->font->getHashCode() .
616 70
            $this->borders->getHashCode() .
617 70
            $this->alignment->getHashCode() .
618 70
            $this->numberFormat->getHashCode() .
619 70
            $hashConditionals .
620 70
            $this->protection->getHashCode() .
621 70
            ($this->quotePrefix ? 't' : 'f') .
622 70
            __CLASS__
623
        );
624
    }
625
626
    /**
627
     * Get own index in style collection.
628
     *
629
     * @return int
630
     */
631 43
    public function getIndex()
632
    {
633 43
        return $this->index;
634
    }
635
636
    /**
637
     * Set own index in style collection.
638
     *
639
     * @param int $pValue
640
     */
641 80
    public function setIndex($pValue)
642
    {
643 80
        $this->index = $pValue;
644 80
    }
645
}
646