Completed
Push — develop ( 8cf911...93ccf7 )
by Adrien
33:03
created

Drawing::allDrawings()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 9
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 19
ccs 9
cts 9
cp 1
crap 3
rs 9.4285
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Excel2007;
4
5
use PhpOffice\PhpSpreadsheet\Chart;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, PhpOffice\PhpSpreadsheet\Writer\Excel2007\Chart.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
7
/**
8
 * Copyright (c) 2006 - 2016 PhpSpreadsheet
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23
 *
24
 * @category   PhpSpreadsheet
25
 * @copyright  Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
26
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
27
 * @version    ##VERSION##, ##DATE##
28
 */
29
class Drawing extends WriterPart
30
{
31
    /**
32
     * Write drawings to XML format
33
     *
34
     * @param     \PhpOffice\PhpSpreadsheet\Worksheet    $pWorksheet
35
     * @param    int                    &$chartRef        Chart ID
36
     * @param    bool                $includeCharts    Flag indicating if we should include drawing details for charts
37
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
38
     * @return string          XML Output
39
     */
40 21
    public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet, &$chartRef, $includeCharts = false)
0 ignored issues
show
Unused Code introduced by
The parameter $chartRef is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
41
    {
42
        // Create XML writer
43 21
        $objWriter = null;
0 ignored issues
show
Unused Code introduced by
$objWriter is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
44 21 View Code Duplication
        if ($this->getParentWriter()->getUseDiskCaching()) {
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...
Bug introduced by
It seems like you code against a concrete implementation and not the interface PhpOffice\PhpSpreadsheet\Writer\IWriter as the method getUseDiskCaching() does only exist in the following implementations of said interface: PhpOffice\PhpSpreadsheet\Writer\BaseWriter, PhpOffice\PhpSpreadsheet\Writer\CSV, PhpOffice\PhpSpreadsheet\Writer\Excel2007, PhpOffice\PhpSpreadsheet\Writer\Excel5, PhpOffice\PhpSpreadsheet\Writer\HTML, PhpOffice\PhpSpreadsheet\Writer\OpenDocument, PhpOffice\PhpSpreadsheet\Writer\PDF\Core, PhpOffice\PhpSpreadsheet\Writer\PDF\DomPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\MPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\TcPDF.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
45
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface PhpOffice\PhpSpreadsheet\Writer\IWriter as the method getDiskCachingDirectory() does only exist in the following implementations of said interface: PhpOffice\PhpSpreadsheet\Writer\BaseWriter, PhpOffice\PhpSpreadsheet\Writer\CSV, PhpOffice\PhpSpreadsheet\Writer\Excel2007, PhpOffice\PhpSpreadsheet\Writer\Excel5, PhpOffice\PhpSpreadsheet\Writer\HTML, PhpOffice\PhpSpreadsheet\Writer\OpenDocument, PhpOffice\PhpSpreadsheet\Writer\PDF\Core, PhpOffice\PhpSpreadsheet\Writer\PDF\DomPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\MPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\TcPDF.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
46
        } else {
47 21
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
48
        }
49
50
        // XML header
51 21
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
52
53
        // xdr:wsDr
54 21
        $objWriter->startElement('xdr:wsDr');
55 21
        $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
56 21
        $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
57
58
        // Loop through images and write drawings
59 21
        $i = 1;
60 21
        $iterator = $pWorksheet->getDrawingCollection()->getIterator();
0 ignored issues
show
Bug introduced by
The method getIterator cannot be called on $pWorksheet->getDrawingCollection() (of type array<integer,object<Php...Worksheet\BaseDrawing>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
61 21
        while ($iterator->valid()) {
62 9
            $this->writeDrawing($objWriter, $iterator->current(), $i);
63
64 9
            $iterator->next();
65 9
            ++$i;
66
        }
67
68 21
        if ($includeCharts) {
69 13
            $chartCount = $pWorksheet->getChartCount();
70
            // Loop through charts and write the chart position
71 13
            if ($chartCount > 0) {
72 13
                for ($c = 0; $c < $chartCount; ++$c) {
73 13
                    $this->writeChart($objWriter, $pWorksheet->getChartByIndex($c), $c + $i);
0 ignored issues
show
Security Bug introduced by
It seems like $pWorksheet->getChartByIndex($c) targeting PhpOffice\PhpSpreadsheet...heet::getChartByIndex() can also be of type false; however, PhpOffice\PhpSpreadsheet...7\Drawing::writeChart() does only seem to accept null|object<PhpOffice\PhpSpreadsheet\Chart>, did you maybe forget to handle an error condition?
Loading history...
74
                }
75
            }
76
        }
77
78 21
        $objWriter->endElement();
79
80
        // Return
81 21
        return $objWriter->getData();
82
    }
83
84
    /**
85
     * Write drawings to XML format
86
     *
87
     * @param     \PhpOffice\PhpSpreadsheet\Shared\XMLWriter    $objWriter         XML Writer
88
     * @param     Chart                $pChart
89
     * @param     int                            $pRelationId
90
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
91
     */
92 13
    public function writeChart(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, Chart $pChart = null, $pRelationId = -1)
93
    {
94 13
        $tl = $pChart->getTopLeftPosition();
0 ignored issues
show
Bug introduced by
It seems like $pChart is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
95 13
        $tl['colRow'] = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($tl['cell']);
96 13
        $br = $pChart->getBottomRightPosition();
97 13
        $br['colRow'] = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($br['cell']);
98
99 13
        $objWriter->startElement('xdr:twoCellAnchor');
0 ignored issues
show
Bug introduced by
It seems like $objWriter is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
100
101 13
        $objWriter->startElement('xdr:from');
102 13
        $objWriter->writeElement('xdr:col', \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($tl['colRow'][0]) - 1);
103 13
        $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['xOffset']));
104 13
        $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1);
105 13
        $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['yOffset']));
106 13
        $objWriter->endElement();
107 13
        $objWriter->startElement('xdr:to');
108 13
        $objWriter->writeElement('xdr:col', \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($br['colRow'][0]) - 1);
109 13
        $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['xOffset']));
110 13
        $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1);
111 13
        $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['yOffset']));
112 13
        $objWriter->endElement();
113
114 13
        $objWriter->startElement('xdr:graphicFrame');
115 13
        $objWriter->writeAttribute('macro', '');
116 13
        $objWriter->startElement('xdr:nvGraphicFramePr');
117 13
        $objWriter->startElement('xdr:cNvPr');
118 13
        $objWriter->writeAttribute('name', 'Chart ' . $pRelationId);
119 13
        $objWriter->writeAttribute('id', 1025 * $pRelationId);
120 13
        $objWriter->endElement();
121 13
        $objWriter->startElement('xdr:cNvGraphicFramePr');
122 13
        $objWriter->startElement('a:graphicFrameLocks');
123 13
        $objWriter->endElement();
124 13
        $objWriter->endElement();
125 13
        $objWriter->endElement();
126
127 13
        $objWriter->startElement('xdr:xfrm');
128 13
        $objWriter->startElement('a:off');
129 13
        $objWriter->writeAttribute('x', '0');
130 13
        $objWriter->writeAttribute('y', '0');
131 13
        $objWriter->endElement();
132 13
        $objWriter->startElement('a:ext');
133 13
        $objWriter->writeAttribute('cx', '0');
134 13
        $objWriter->writeAttribute('cy', '0');
135 13
        $objWriter->endElement();
136 13
        $objWriter->endElement();
137
138 13
        $objWriter->startElement('a:graphic');
139 13
        $objWriter->startElement('a:graphicData');
140 13
        $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
141 13
        $objWriter->startElement('c:chart');
142 13
        $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
143 13
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
144 13
        $objWriter->writeAttribute('r:id', 'rId' . $pRelationId);
145 13
        $objWriter->endElement();
146 13
        $objWriter->endElement();
147 13
        $objWriter->endElement();
148 13
        $objWriter->endElement();
149
150 13
        $objWriter->startElement('xdr:clientData');
151 13
        $objWriter->endElement();
152
153 13
        $objWriter->endElement();
154 13
    }
155
156
    /**
157
     * Write drawings to XML format
158
     *
159
     * @param     \PhpOffice\PhpSpreadsheet\Shared\XMLWriter            $objWriter         XML Writer
160
     * @param     \PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing        $pDrawing
161
     * @param     int                                    $pRelationId
162
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
163
     */
164 9
    public function writeDrawing(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, \PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing $pDrawing = null, $pRelationId = -1)
165
    {
166 9
        if ($pRelationId >= 0) {
167
            // xdr:oneCellAnchor
168 9
            $objWriter->startElement('xdr:oneCellAnchor');
0 ignored issues
show
Bug introduced by
It seems like $objWriter is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
169
            // Image location
170 9
            $aCoordinates = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($pDrawing->getCoordinates());
0 ignored issues
show
Bug introduced by
It seems like $pDrawing is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
171 9
            $aCoordinates[0] = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($aCoordinates[0]);
172
173
            // xdr:from
174 9
            $objWriter->startElement('xdr:from');
175 9
            $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
176 9
            $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetX()));
177 9
            $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
178 9
            $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetY()));
179 9
            $objWriter->endElement();
180
181
            // xdr:ext
182 9
            $objWriter->startElement('xdr:ext');
183 9
            $objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getWidth()));
184 9
            $objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getHeight()));
185 9
            $objWriter->endElement();
186
187
            // xdr:pic
188 9
            $objWriter->startElement('xdr:pic');
189
190
            // xdr:nvPicPr
191 9
            $objWriter->startElement('xdr:nvPicPr');
192
193
            // xdr:cNvPr
194 9
            $objWriter->startElement('xdr:cNvPr');
195 9
            $objWriter->writeAttribute('id', $pRelationId);
196 9
            $objWriter->writeAttribute('name', $pDrawing->getName());
197 9
            $objWriter->writeAttribute('descr', $pDrawing->getDescription());
198 9
            $objWriter->endElement();
199
200
            // xdr:cNvPicPr
201 9
            $objWriter->startElement('xdr:cNvPicPr');
202
203
            // a:picLocks
204 9
            $objWriter->startElement('a:picLocks');
205 9
            $objWriter->writeAttribute('noChangeAspect', '1');
206 9
            $objWriter->endElement();
207
208 9
            $objWriter->endElement();
209
210 9
            $objWriter->endElement();
211
212
            // xdr:blipFill
213 9
            $objWriter->startElement('xdr:blipFill');
214
215
            // a:blip
216 9
            $objWriter->startElement('a:blip');
217 9
            $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
218 9
            $objWriter->writeAttribute('r:embed', 'rId' . $pRelationId);
219 9
            $objWriter->endElement();
220
221
            // a:stretch
222 9
            $objWriter->startElement('a:stretch');
223 9
            $objWriter->writeElement('a:fillRect', null);
224 9
            $objWriter->endElement();
225
226 9
            $objWriter->endElement();
227
228
            // xdr:spPr
229 9
            $objWriter->startElement('xdr:spPr');
230
231
            // a:xfrm
232 9
            $objWriter->startElement('a:xfrm');
233 9
            $objWriter->writeAttribute('rot', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($pDrawing->getRotation()));
234 9
            $objWriter->endElement();
235
236
            // a:prstGeom
237 9
            $objWriter->startElement('a:prstGeom');
238 9
            $objWriter->writeAttribute('prst', 'rect');
239
240
            // a:avLst
241 9
            $objWriter->writeElement('a:avLst', null);
242
243 9
            $objWriter->endElement();
244
245 9
            if ($pDrawing->getShadow()->getVisible()) {
246
                // a:effectLst
247 5
                $objWriter->startElement('a:effectLst');
248
249
                // a:outerShdw
250 5
                $objWriter->startElement('a:outerShdw');
251 5
                $objWriter->writeAttribute('blurRad', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius()));
252 5
                $objWriter->writeAttribute('dist', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance()));
253 5
                $objWriter->writeAttribute('dir', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($pDrawing->getShadow()->getDirection()));
254 5
                $objWriter->writeAttribute('algn', $pDrawing->getShadow()->getAlignment());
255 5
                $objWriter->writeAttribute('rotWithShape', '0');
256
257
                // a:srgbClr
258 5
                $objWriter->startElement('a:srgbClr');
259 5
                $objWriter->writeAttribute('val', $pDrawing->getShadow()->getColor()->getRGB());
260
261
                // a:alpha
262 5
                $objWriter->startElement('a:alpha');
263 5
                $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000);
264 5
                $objWriter->endElement();
265
266 5
                $objWriter->endElement();
267
268 5
                $objWriter->endElement();
269
270 5
                $objWriter->endElement();
271
            }
272
/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
273
274
                // a:scene3d
275
                $objWriter->startElement('a:scene3d');
276
277
                    // a:camera
278
                    $objWriter->startElement('a:camera');
279
                    $objWriter->writeAttribute('prst', 'orthographicFront');
280
                    $objWriter->endElement();
281
282
                    // a:lightRig
283
                    $objWriter->startElement('a:lightRig');
284
                    $objWriter->writeAttribute('rig', 'twoPt');
285
                    $objWriter->writeAttribute('dir', 't');
286
287
                        // a:rot
288
                        $objWriter->startElement('a:rot');
289
                        $objWriter->writeAttribute('lat', '0');
290
                        $objWriter->writeAttribute('lon', '0');
291
                        $objWriter->writeAttribute('rev', '0');
292
                        $objWriter->endElement();
293
294
                    $objWriter->endElement();
295
296
                $objWriter->endElement();
297
*/
298
/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
299
                // a:sp3d
300
                $objWriter->startElement('a:sp3d');
301
302
                    // a:bevelT
303
                    $objWriter->startElement('a:bevelT');
304
                    $objWriter->writeAttribute('w', '25400');
305
                    $objWriter->writeAttribute('h', '19050');
306
                    $objWriter->endElement();
307
308
                    // a:contourClr
309
                    $objWriter->startElement('a:contourClr');
310
311
                        // a:srgbClr
312
                        $objWriter->startElement('a:srgbClr');
313
                        $objWriter->writeAttribute('val', 'FFFFFF');
314
                        $objWriter->endElement();
315
316
                    $objWriter->endElement();
317
318
                $objWriter->endElement();
319
*/
320 9
            $objWriter->endElement();
321
322 9
            $objWriter->endElement();
323
324
            // xdr:clientData
325 9
            $objWriter->writeElement('xdr:clientData', null);
326
327 9
            $objWriter->endElement();
328
        } else {
329
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('Invalid parameters passed.');
330
        }
331 9
    }
332
333
    /**
334
     * Write VML header/footer images to XML format
335
     *
336
     * @param     \PhpOffice\PhpSpreadsheet\Worksheet                $pWorksheet
337
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
338
     * @return string                          XML Output
339
     */
340 1
    public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet = null)
341
    {
342
        // Create XML writer
343 1
        $objWriter = null;
0 ignored issues
show
Unused Code introduced by
$objWriter is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
344 1 View Code Duplication
        if ($this->getParentWriter()->getUseDiskCaching()) {
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...
Bug introduced by
It seems like you code against a concrete implementation and not the interface PhpOffice\PhpSpreadsheet\Writer\IWriter as the method getUseDiskCaching() does only exist in the following implementations of said interface: PhpOffice\PhpSpreadsheet\Writer\BaseWriter, PhpOffice\PhpSpreadsheet\Writer\CSV, PhpOffice\PhpSpreadsheet\Writer\Excel2007, PhpOffice\PhpSpreadsheet\Writer\Excel5, PhpOffice\PhpSpreadsheet\Writer\HTML, PhpOffice\PhpSpreadsheet\Writer\OpenDocument, PhpOffice\PhpSpreadsheet\Writer\PDF\Core, PhpOffice\PhpSpreadsheet\Writer\PDF\DomPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\MPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\TcPDF.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
345
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface PhpOffice\PhpSpreadsheet\Writer\IWriter as the method getDiskCachingDirectory() does only exist in the following implementations of said interface: PhpOffice\PhpSpreadsheet\Writer\BaseWriter, PhpOffice\PhpSpreadsheet\Writer\CSV, PhpOffice\PhpSpreadsheet\Writer\Excel2007, PhpOffice\PhpSpreadsheet\Writer\Excel5, PhpOffice\PhpSpreadsheet\Writer\HTML, PhpOffice\PhpSpreadsheet\Writer\OpenDocument, PhpOffice\PhpSpreadsheet\Writer\PDF\Core, PhpOffice\PhpSpreadsheet\Writer\PDF\DomPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\MPDF, PhpOffice\PhpSpreadsheet\Writer\PDF\TcPDF.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
346
        } else {
347 1
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
348
        }
349
350
        // XML header
351 1
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
352
353
        // Header/footer images
354 1
        $images = $pWorksheet->getHeaderFooter()->getImages();
0 ignored issues
show
Bug introduced by
It seems like $pWorksheet is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
355
356
        // xml
357 1
        $objWriter->startElement('xml');
358 1
        $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml');
359 1
        $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office');
360 1
        $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel');
361
362
        // o:shapelayout
363 1
        $objWriter->startElement('o:shapelayout');
364 1
        $objWriter->writeAttribute('v:ext', 'edit');
365
366
        // o:idmap
367 1
        $objWriter->startElement('o:idmap');
368 1
        $objWriter->writeAttribute('v:ext', 'edit');
369 1
        $objWriter->writeAttribute('data', '1');
370 1
        $objWriter->endElement();
371
372 1
        $objWriter->endElement();
373
374
        // v:shapetype
375 1
        $objWriter->startElement('v:shapetype');
376 1
        $objWriter->writeAttribute('id', '_x0000_t75');
377 1
        $objWriter->writeAttribute('coordsize', '21600,21600');
378 1
        $objWriter->writeAttribute('o:spt', '75');
379 1
        $objWriter->writeAttribute('o:preferrelative', 't');
380 1
        $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe');
381 1
        $objWriter->writeAttribute('filled', 'f');
382 1
        $objWriter->writeAttribute('stroked', 'f');
383
384
        // v:stroke
385 1
        $objWriter->startElement('v:stroke');
386 1
        $objWriter->writeAttribute('joinstyle', 'miter');
387 1
        $objWriter->endElement();
388
389
        // v:formulas
390 1
        $objWriter->startElement('v:formulas');
391
392
        // v:f
393 1
        $objWriter->startElement('v:f');
394 1
        $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0');
395 1
        $objWriter->endElement();
396
397
        // v:f
398 1
        $objWriter->startElement('v:f');
399 1
        $objWriter->writeAttribute('eqn', 'sum @0 1 0');
400 1
        $objWriter->endElement();
401
402
        // v:f
403 1
        $objWriter->startElement('v:f');
404 1
        $objWriter->writeAttribute('eqn', 'sum 0 0 @1');
405 1
        $objWriter->endElement();
406
407
        // v:f
408 1
        $objWriter->startElement('v:f');
409 1
        $objWriter->writeAttribute('eqn', 'prod @2 1 2');
410 1
        $objWriter->endElement();
411
412
        // v:f
413 1
        $objWriter->startElement('v:f');
414 1
        $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth');
415 1
        $objWriter->endElement();
416
417
        // v:f
418 1
        $objWriter->startElement('v:f');
419 1
        $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight');
420 1
        $objWriter->endElement();
421
422
        // v:f
423 1
        $objWriter->startElement('v:f');
424 1
        $objWriter->writeAttribute('eqn', 'sum @0 0 1');
425 1
        $objWriter->endElement();
426
427
        // v:f
428 1
        $objWriter->startElement('v:f');
429 1
        $objWriter->writeAttribute('eqn', 'prod @6 1 2');
430 1
        $objWriter->endElement();
431
432
        // v:f
433 1
        $objWriter->startElement('v:f');
434 1
        $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth');
435 1
        $objWriter->endElement();
436
437
        // v:f
438 1
        $objWriter->startElement('v:f');
439 1
        $objWriter->writeAttribute('eqn', 'sum @8 21600 0');
440 1
        $objWriter->endElement();
441
442
        // v:f
443 1
        $objWriter->startElement('v:f');
444 1
        $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight');
445 1
        $objWriter->endElement();
446
447
        // v:f
448 1
        $objWriter->startElement('v:f');
449 1
        $objWriter->writeAttribute('eqn', 'sum @10 21600 0');
450 1
        $objWriter->endElement();
451
452 1
        $objWriter->endElement();
453
454
        // v:path
455 1
        $objWriter->startElement('v:path');
456 1
        $objWriter->writeAttribute('o:extrusionok', 'f');
457 1
        $objWriter->writeAttribute('gradientshapeok', 't');
458 1
        $objWriter->writeAttribute('o:connecttype', 'rect');
459 1
        $objWriter->endElement();
460
461
        // o:lock
462 1
        $objWriter->startElement('o:lock');
463 1
        $objWriter->writeAttribute('v:ext', 'edit');
464 1
        $objWriter->writeAttribute('aspectratio', 't');
465 1
        $objWriter->endElement();
466
467 1
        $objWriter->endElement();
468
469
        // Loop through images
470 1
        foreach ($images as $key => $value) {
471 1
            $this->writeVMLHeaderFooterImage($objWriter, $key, $value);
472
        }
473
474 1
        $objWriter->endElement();
475
476
        // Return
477 1
        return $objWriter->getData();
478
    }
479
480
    /**
481
     * Write VML comment to XML format
482
     *
483
     * @param     \PhpOffice\PhpSpreadsheet\Shared\XMLWriter        $objWriter             XML Writer
484
     * @param    string                            $pReference            Reference
485
     * @param     \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing    $pImage        Image
486
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
487
     */
488 1
    private function writeVMLHeaderFooterImage(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, $pReference = '', \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing $pImage = null)
489
    {
490
        // Calculate object id
491 1
        preg_match('{(\d+)}', md5($pReference), $m);
492 1
        $id = 1500 + (substr($m[1], 0, 2) * 1);
493
494
        // Calculate offset
495 1
        $width = $pImage->getWidth();
0 ignored issues
show
Bug introduced by
It seems like $pImage is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
496 1
        $height = $pImage->getHeight();
497 1
        $marginLeft = $pImage->getOffsetX();
498 1
        $marginTop = $pImage->getOffsetY();
499
500
        // v:shape
501 1
        $objWriter->startElement('v:shape');
0 ignored issues
show
Bug introduced by
It seems like $objWriter is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
502 1
        $objWriter->writeAttribute('id', $pReference);
503 1
        $objWriter->writeAttribute('o:spid', '_x0000_s' . $id);
504 1
        $objWriter->writeAttribute('type', '#_x0000_t75');
505 1
        $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1");
506
507
        // v:imagedata
508 1
        $objWriter->startElement('v:imagedata');
509 1
        $objWriter->writeAttribute('o:relid', 'rId' . $pReference);
510 1
        $objWriter->writeAttribute('o:title', $pImage->getName());
511 1
        $objWriter->endElement();
512
513
        // o:lock
514 1
        $objWriter->startElement('o:lock');
515 1
        $objWriter->writeAttribute('v:ext', 'edit');
516 1
        $objWriter->writeAttribute('rotation', 't');
517 1
        $objWriter->endElement();
518
519 1
        $objWriter->endElement();
520 1
    }
521
522
    /**
523
     * Get an array of all drawings
524
     *
525
     * @param      \PhpOffice\PhpSpreadsheet\SpreadSheet                $spreadsheet
526
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
527
     * @return     \PhpOffice\PhpSpreadsheet\Worksheet\Drawing[]        All drawings in PhpSpreadsheet
528
     */
529 56
    public function allDrawings(\PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet = null)
530
    {
531
        // Get an array of all drawings
532 56
        $aDrawings = [];
533
534
        // Loop through PhpSpreadsheet
535 56
        $sheetCount = $spreadsheet->getSheetCount();
0 ignored issues
show
Bug introduced by
It seems like $spreadsheet is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
536 56
        for ($i = 0; $i < $sheetCount; ++$i) {
537
            // Loop through images and add to array
538 56
            $iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator();
539 56
            while ($iterator->valid()) {
540 9
                $aDrawings[] = $iterator->current();
541
542 9
                $iterator->next();
543
            }
544
        }
545
546 56
        return $aDrawings;
547
    }
548
}
549