Completed
Push — develop ( 2b41bd...39b55d )
by Adrien
22:48
created

Rels::writeWorksheetRelationships()   C

Complexity

Conditions 9
Paths 96

Size

Total Lines 83
Code Lines 52

Duplication

Lines 5
Ratio 6.02 %

Code Coverage

Tests 44
CRAP Score 9.0008

Importance

Changes 0
Metric Value
cc 9
eloc 52
nc 96
nop 3
dl 5
loc 83
ccs 44
cts 45
cp 0.9778
crap 9.0008
rs 5.48
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
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
 * @copyright  Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
24
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
25
 * @version    ##VERSION##, ##DATE##
26
 */
27
class Rels extends WriterPart
28
{
29
    /**
30
     * Write relationships to XML format
31
     *
32
     * @param \PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet
33
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
34
     * @return string  XML Output
35
     */
36 56
    public function writeRelationships(\PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet = null)
37
    {
38
        // Create XML writer
39 56
        $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...
40 56 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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
41
            $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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
42
        } else {
43 56
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
44
        }
45
46
        // XML header
47 56
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
48
49
        // Relationships
50 56
        $objWriter->startElement('Relationships');
51 56
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
52
53 56
        $customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
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...
54 56
        if (!empty($customPropertyList)) {
55
            // Relationship docProps/app.xml
56 2
            $this->writeRelationship(
57
                $objWriter,
58 2
                4,
59 2
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties',
60 2
                'docProps/custom.xml'
61
            );
62
        }
63
64
        // Relationship docProps/app.xml
65 56
        $this->writeRelationship(
66
            $objWriter,
67 56
            3,
68 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties',
69 56
            'docProps/app.xml'
70
        );
71
72
        // Relationship docProps/core.xml
73 56
        $this->writeRelationship(
74
            $objWriter,
75 56
            2,
76 56
            'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
77 56
            'docProps/core.xml'
78
        );
79
80
        // Relationship xl/workbook.xml
81 56
        $this->writeRelationship(
82
            $objWriter,
83 56
            1,
84 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument',
85 56
            'xl/workbook.xml'
86
        );
87
        // a custom UI in workbook ?
88 56
        if ($spreadsheet->hasRibbon()) {
89
            $this->writeRelationShip(
90
                $objWriter,
91
                5,
92
                'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility',
93
                $spreadsheet->getRibbonXMLData('target')
94
            );
95
        }
96
97 56
        $objWriter->endElement();
98
99 56
        return $objWriter->getData();
100
    }
101
102
    /**
103
     * Write workbook relationships to XML format
104
     *
105
     * @param \PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet
106
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
107
     * @return string  XML Output
108
     */
109 56
    public function writeWorkbookRelationships(\PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet = null)
110
    {
111
        // Create XML writer
112 56
        $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...
113 56 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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
114
            $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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
115
        } else {
116 56
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
117
        }
118
119
        // XML header
120 56
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
121
122
        // Relationships
123 56
        $objWriter->startElement('Relationships');
124 56
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
125
126
        // Relationship styles.xml
127 56
        $this->writeRelationship(
128
            $objWriter,
129 56
            1,
130 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles',
131 56
            'styles.xml'
132
        );
133
134
        // Relationship theme/theme1.xml
135 56
        $this->writeRelationship(
136
            $objWriter,
137 56
            2,
138 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme',
139 56
            'theme/theme1.xml'
140
        );
141
142
        // Relationship sharedStrings.xml
143 56
        $this->writeRelationship(
144
            $objWriter,
145 56
            3,
146 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings',
147 56
            'sharedStrings.xml'
148
        );
149
150
        // Relationships with sheets
151 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...
152 56
        for ($i = 0; $i < $sheetCount; ++$i) {
153 56
            $this->writeRelationship(
154
                $objWriter,
155 56
                ($i + 1 + 3),
156 56
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet',
157 56
                'worksheets/sheet' . ($i + 1) . '.xml'
158
            );
159
        }
160
        // Relationships for vbaProject if needed
161
        // id : just after the last sheet
162 56
        if ($spreadsheet->hasMacros()) {
163
            $this->writeRelationShip(
164
                $objWriter,
165
                ($i + 1 + 3),
166
                'http://schemas.microsoft.com/office/2006/relationships/vbaProject',
167
                'vbaProject.bin'
168
            );
169
            ++$i; //increment i if needed for an another relation
170
        }
171
172 56
        $objWriter->endElement();
173
174 56
        return $objWriter->getData();
175
    }
176
177
    /**
178
     * Write worksheet relationships to XML format
179
     *
180
     * Numbering is as follows:
181
     *     rId1                 - Drawings
182
     *  rId_hyperlink_x     - Hyperlinks
183
     *
184
     * @param     \PhpOffice\PhpSpreadsheet\Worksheet    $pWorksheet
185
     * @param     int                    $pWorksheetId
186
     * @param    bool                $includeCharts    Flag indicating if we should write charts
187
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
188
     * @return string          XML Output
189
     */
190 56
    public function writeWorksheetRelationships(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet = null, $pWorksheetId = 1, $includeCharts = false)
191
    {
192
        // Create XML writer
193 56
        $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...
194 56 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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
195
            $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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
196
        } else {
197 56
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
198
        }
199
200
        // XML header
201 56
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
202
203
        // Relationships
204 56
        $objWriter->startElement('Relationships');
205 56
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
206
207
        // Write drawing relationships?
208 56
        $d = 0;
209 56
        if ($includeCharts) {
210 14
            $charts = $pWorksheet->getChartCollection();
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...
211
        } else {
212 43
            $charts = [];
213
        }
214 56
        if (($pWorksheet->getDrawingCollection()->count() > 0) ||
215 56
            (count($charts) > 0)) {
216 21
            $this->writeRelationship(
217
                $objWriter,
218 21
                ++$d,
219 21
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing',
220 21
                '../drawings/drawing' . $pWorksheetId . '.xml'
221
            );
222
        }
223
224
        // Write hyperlink relationships?
225 56
        $i = 1;
226 56
        foreach ($pWorksheet->getHyperlinkCollection() as $hyperlink) {
227 8
            if (!$hyperlink->isInternal()) {
228 8
                $this->writeRelationship(
229
                    $objWriter,
230 8
                    '_hyperlink_' . $i,
231 8
                    'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
232 8
                    $hyperlink->getUrl(),
233 8
                    'External'
234
                );
235
236 8
                ++$i;
237
            }
238
        }
239
240
        // Write comments relationship?
241 56
        $i = 1;
242 56
        if (count($pWorksheet->getComments()) > 0) {
243 9
            $this->writeRelationship(
244
                $objWriter,
245 9
                '_comments_vml' . $i,
246 9
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing',
247 9
                '../drawings/vmlDrawing' . $pWorksheetId . '.vml'
248
            );
249
250 9
            $this->writeRelationship(
251
                $objWriter,
252 9
                '_comments' . $i,
253 9
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments',
254 9
                '../comments' . $pWorksheetId . '.xml'
255
            );
256
        }
257
258
        // Write header/footer relationship?
259 56
        $i = 1;
260 56
        if (count($pWorksheet->getHeaderFooter()->getImages()) > 0) {
261 1
            $this->writeRelationship(
262
                $objWriter,
263 1
                '_headerfooter_vml' . $i,
264 1
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing',
265 1
                '../drawings/vmlDrawingHF' . $pWorksheetId . '.vml'
266
            );
267
        }
268
269 56
        $objWriter->endElement();
270
271 56
        return $objWriter->getData();
272
    }
273
274
    /**
275
     * Write drawing relationships to XML format
276
     *
277
     * @param     \PhpOffice\PhpSpreadsheet\Worksheet    $pWorksheet
278
     * @param    int                    &$chartRef        Chart ID
279
     * @param    bool                $includeCharts    Flag indicating if we should write charts
280
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
281
     * @return string          XML Output
282
     */
283 21
    public function writeDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet, &$chartRef, $includeCharts = false)
284
    {
285
        // Create XML writer
286 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...
287 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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
288
            $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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
289
        } else {
290 21
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
291
        }
292
293
        // XML header
294 21
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
295
296
        // Relationships
297 21
        $objWriter->startElement('Relationships');
298 21
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
299
300
        // Loop through images and write relationships
301 21
        $i = 1;
302 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...
303 21
        while ($iterator->valid()) {
304 9
            if ($iterator->current() instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing
305 9
                || $iterator->current() instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) {
306
                // Write relationship for image drawing
307 9
                $this->writeRelationship(
308
                    $objWriter,
309
                    $i,
310 9
                    'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
311 9
                    '../media/' . str_replace(' ', '', $iterator->current()->getIndexedFilename())
312
                );
313
            }
314
315 9
            $iterator->next();
316 9
            ++$i;
317
        }
318
319 21
        if ($includeCharts) {
320
            // Loop through charts and write relationships
321 13
            $chartCount = $pWorksheet->getChartCount();
322 13
            if ($chartCount > 0) {
323 13
                for ($c = 0; $c < $chartCount; ++$c) {
324 13
                    $this->writeRelationship(
325
                        $objWriter,
326 13
                        $i++,
327 13
                        'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart',
328 13
                        '../charts/chart' . ++$chartRef . '.xml'
329
                    );
330
                }
331
            }
332
        }
333
334 21
        $objWriter->endElement();
335
336 21
        return $objWriter->getData();
337
    }
338
339
    /**
340
     * Write header/footer drawing relationships to XML format
341
     *
342
     * @param     \PhpOffice\PhpSpreadsheet\Worksheet            $pWorksheet
343
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
344
     * @return string                  XML Output
345
     */
346 1
    public function writeHeaderFooterDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet = null)
347
    {
348
        // Create XML writer
349 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...
350 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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
351
            $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\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, PhpOffice\PhpSpreadsheet\Writer\Xlsx.

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...
352
        } else {
353 1
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
354
        }
355
356
        // XML header
357 1
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
358
359
        // Relationships
360 1
        $objWriter->startElement('Relationships');
361 1
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
362
363
        // Loop through images and write relationships
364 1
        foreach ($pWorksheet->getHeaderFooter()->getImages() as $key => $value) {
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...
365
            // Write relationship for image drawing
366 1
            $this->writeRelationship(
367
                $objWriter,
368
                $key,
369 1
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
370 1
                '../media/' . $value->getIndexedFilename()
371
            );
372
        }
373
374 1
        $objWriter->endElement();
375
376 1
        return $objWriter->getData();
377
    }
378
379
    /**
380
     * Write Override content type
381
     *
382
     * @param     \PhpOffice\PhpSpreadsheet\Shared\XMLWriter     $objWriter         XML Writer
383
     * @param     int                            $pId            Relationship ID. rId will be prepended!
384
     * @param     string                        $pType            Relationship type
385
     * @param     string                         $pTarget        Relationship target
386
     * @param     string                         $pTargetMode    Relationship target mode
387
     * @throws     \PhpOffice\PhpSpreadsheet\Writer\Exception
388
     */
389 56 View Code Duplication
    private function writeRelationship(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
390
    {
391 56
        if ($pType != '' && $pTarget != '') {
392
            // Write relationship
393 56
            $objWriter->startElement('Relationship');
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...
394 56
            $objWriter->writeAttribute('Id', 'rId' . $pId);
395 56
            $objWriter->writeAttribute('Type', $pType);
396 56
            $objWriter->writeAttribute('Target', $pTarget);
397
398 56
            if ($pTargetMode != '') {
399 8
                $objWriter->writeAttribute('TargetMode', $pTargetMode);
400
            }
401
402 56
            $objWriter->endElement();
403
        } else {
404
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('Invalid parameters passed.');
405
        }
406 56
    }
407
}
408