Completed
Push — develop ( f99eb8...c5339b )
by Adrien
31:45
created

Rels   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 392
Duplicated Lines 10.97 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 90.91%

Importance

Changes 0
Metric Value
dl 43
loc 392
rs 9.6
c 0
b 0
f 0
ccs 150
cts 165
cp 0.9091
wmc 32
lcom 1
cbo 4

6 Methods

Rating   Name   Duplication   Size   Complexity  
B writeRelationships() 5 65 4
B writeWorkbookRelationships() 5 67 4
C writeWorksheetRelationships() 5 83 9
B writeDrawingRelationships() 5 55 8
B writeHeaderFooterDrawingRelationships() 5 32 3
A writeRelationship() 18 18 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
 *
24
 * @copyright  Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
25
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
26
 */
27
class Rels extends WriterPart
28
{
29
    /**
30
     * Write relationships to XML format.
31
     *
32
     * @param \PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet
33
     *
34
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
35
     *
36
     * @return string XML Output
37
     */
38 56
    public function writeRelationships(\PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet = null)
39
    {
40
        // Create XML writer
41 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...
42 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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
43
            $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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
44
        } else {
45 56
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
46
        }
47
48
        // XML header
49 56
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
50
51
        // Relationships
52 56
        $objWriter->startElement('Relationships');
53 56
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
54
55 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...
56 56
        if (!empty($customPropertyList)) {
57
            // Relationship docProps/app.xml
58 2
            $this->writeRelationship(
59
                $objWriter,
60 2
                4,
61 2
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties',
62 2
                'docProps/custom.xml'
63
            );
64
        }
65
66
        // Relationship docProps/app.xml
67 56
        $this->writeRelationship(
68
            $objWriter,
69 56
            3,
70 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties',
71 56
            'docProps/app.xml'
72
        );
73
74
        // Relationship docProps/core.xml
75 56
        $this->writeRelationship(
76
            $objWriter,
77 56
            2,
78 56
            'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
79 56
            'docProps/core.xml'
80
        );
81
82
        // Relationship xl/workbook.xml
83 56
        $this->writeRelationship(
84
            $objWriter,
85 56
            1,
86 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument',
87 56
            'xl/workbook.xml'
88
        );
89
        // a custom UI in workbook ?
90 56
        if ($spreadsheet->hasRibbon()) {
91
            $this->writeRelationShip(
92
                $objWriter,
93
                5,
94
                'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility',
95
                $spreadsheet->getRibbonXMLData('target')
96
            );
97
        }
98
99 56
        $objWriter->endElement();
100
101 56
        return $objWriter->getData();
102
    }
103
104
    /**
105
     * Write workbook relationships to XML format.
106
     *
107
     * @param \PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet
108
     *
109
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
110
     *
111
     * @return string XML Output
112
     */
113 56
    public function writeWorkbookRelationships(\PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet = null)
114
    {
115
        // Create XML writer
116 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...
117 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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
118
            $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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
119
        } else {
120 56
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
121
        }
122
123
        // XML header
124 56
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
125
126
        // Relationships
127 56
        $objWriter->startElement('Relationships');
128 56
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
129
130
        // Relationship styles.xml
131 56
        $this->writeRelationship(
132
            $objWriter,
133 56
            1,
134 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles',
135 56
            'styles.xml'
136
        );
137
138
        // Relationship theme/theme1.xml
139 56
        $this->writeRelationship(
140
            $objWriter,
141 56
            2,
142 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme',
143 56
            'theme/theme1.xml'
144
        );
145
146
        // Relationship sharedStrings.xml
147 56
        $this->writeRelationship(
148
            $objWriter,
149 56
            3,
150 56
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings',
151 56
            'sharedStrings.xml'
152
        );
153
154
        // Relationships with sheets
155 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...
156 56
        for ($i = 0; $i < $sheetCount; ++$i) {
157 56
            $this->writeRelationship(
158
                $objWriter,
159 56
                ($i + 1 + 3),
160 56
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet',
161 56
                'worksheets/sheet' . ($i + 1) . '.xml'
162
            );
163
        }
164
        // Relationships for vbaProject if needed
165
        // id : just after the last sheet
166 56
        if ($spreadsheet->hasMacros()) {
167
            $this->writeRelationShip(
168
                $objWriter,
169
                ($i + 1 + 3),
170
                'http://schemas.microsoft.com/office/2006/relationships/vbaProject',
171
                'vbaProject.bin'
172
            );
173
            ++$i; //increment i if needed for an another relation
174
        }
175
176 56
        $objWriter->endElement();
177
178 56
        return $objWriter->getData();
179
    }
180
181
    /**
182
     * Write worksheet relationships to XML format.
183
     *
184
     * Numbering is as follows:
185
     *     rId1                 - Drawings
186
     *  rId_hyperlink_x     - Hyperlinks
187
     *
188
     * @param \PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet
189
     * @param int $pWorksheetId
190
     * @param bool $includeCharts Flag indicating if we should write charts
191
     *
192
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
193
     *
194
     * @return string XML Output
195
     */
196 56
    public function writeWorksheetRelationships(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet = null, $pWorksheetId = 1, $includeCharts = false)
197
    {
198
        // Create XML writer
199 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...
200 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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
201
            $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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
202
        } else {
203 56
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
204
        }
205
206
        // XML header
207 56
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
208
209
        // Relationships
210 56
        $objWriter->startElement('Relationships');
211 56
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
212
213
        // Write drawing relationships?
214 56
        $d = 0;
215 56
        if ($includeCharts) {
216 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...
217
        } else {
218 43
            $charts = [];
219
        }
220 56
        if (($pWorksheet->getDrawingCollection()->count() > 0) ||
221 48
            (count($charts) > 0)) {
222 22
            $this->writeRelationship(
223
                $objWriter,
224 22
                ++$d,
225 22
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing',
226 22
                '../drawings/drawing' . $pWorksheetId . '.xml'
227
            );
228
        }
229
230
        // Write hyperlink relationships?
231 56
        $i = 1;
232 56
        foreach ($pWorksheet->getHyperlinkCollection() as $hyperlink) {
233 9
            if (!$hyperlink->isInternal()) {
234 9
                $this->writeRelationship(
235
                    $objWriter,
236 9
                    '_hyperlink_' . $i,
237 9
                    'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
238 9
                    $hyperlink->getUrl(),
239 9
                    'External'
240
                );
241
242 9
                ++$i;
243
            }
244
        }
245
246
        // Write comments relationship?
247 56
        $i = 1;
248 56
        if (count($pWorksheet->getComments()) > 0) {
249 9
            $this->writeRelationship(
250
                $objWriter,
251 9
                '_comments_vml' . $i,
252 9
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing',
253 9
                '../drawings/vmlDrawing' . $pWorksheetId . '.vml'
254
            );
255
256 9
            $this->writeRelationship(
257
                $objWriter,
258 9
                '_comments' . $i,
259 9
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments',
260 9
                '../comments' . $pWorksheetId . '.xml'
261
            );
262
        }
263
264
        // Write header/footer relationship?
265 56
        $i = 1;
266 56
        if (count($pWorksheet->getHeaderFooter()->getImages()) > 0) {
267 1
            $this->writeRelationship(
268
                $objWriter,
269 1
                '_headerfooter_vml' . $i,
270 1
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing',
271 1
                '../drawings/vmlDrawingHF' . $pWorksheetId . '.vml'
272
            );
273
        }
274
275 56
        $objWriter->endElement();
276
277 56
        return $objWriter->getData();
278
    }
279
280
    /**
281
     * Write drawing relationships to XML format.
282
     *
283
     * @param \PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet
284
     * @param int &$chartRef Chart ID
285
     * @param bool $includeCharts Flag indicating if we should write charts
286
     *
287
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
288
     *
289
     * @return string XML Output
290
     */
291 22
    public function writeDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet, &$chartRef, $includeCharts = false)
292
    {
293
        // Create XML writer
294 22
        $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...
295 22 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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
296
            $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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
297
        } else {
298 22
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
299
        }
300
301
        // XML header
302 22
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
303
304
        // Relationships
305 22
        $objWriter->startElement('Relationships');
306 22
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
307
308
        // Loop through images and write relationships
309 22
        $i = 1;
310 22
        $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...
311 22
        while ($iterator->valid()) {
312 10
            if ($iterator->current() instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing
313 4
                || $iterator->current() instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) {
314
                // Write relationship for image drawing
315 10
                $this->writeRelationship(
316
                    $objWriter,
317
                    $i,
318 10
                    'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
319 10
                    '../media/' . str_replace(' ', '', $iterator->current()->getIndexedFilename())
320
                );
321
            }
322
323 10
            $iterator->next();
324 10
            ++$i;
325
        }
326
327 22
        if ($includeCharts) {
328
            // Loop through charts and write relationships
329 13
            $chartCount = $pWorksheet->getChartCount();
330 13
            if ($chartCount > 0) {
331 13
                for ($c = 0; $c < $chartCount; ++$c) {
332 13
                    $this->writeRelationship(
333
                        $objWriter,
334 13
                        $i++,
335 13
                        'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart',
336 13
                        '../charts/chart' . ++$chartRef . '.xml'
337
                    );
338
                }
339
            }
340
        }
341
342 22
        $objWriter->endElement();
343
344 22
        return $objWriter->getData();
345
    }
346
347
    /**
348
     * Write header/footer drawing relationships to XML format.
349
     *
350
     * @param \PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet
351
     *
352
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
353
     *
354
     * @return string XML Output
355
     */
356 1
    public function writeHeaderFooterDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet $pWorksheet = null)
357
    {
358
        // Create XML writer
359 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...
360 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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
361
            $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\Html, PhpOffice\PhpSpreadsheet\Writer\Ods, PhpOffice\PhpSpreadsheet\Writer\Pdf\Core, PhpOffice\PhpSpreadsheet\Writer\Pdf\DomPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\MPDF, PhpOffice\PhpSpreadsheet\Writer\Pdf\TcPDF, PhpOffice\PhpSpreadsheet\Writer\Xls, 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...
362
        } else {
363 1
            $objWriter = new \PhpOffice\PhpSpreadsheet\Shared\XMLWriter(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter::STORAGE_MEMORY);
364
        }
365
366
        // XML header
367 1
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
368
369
        // Relationships
370 1
        $objWriter->startElement('Relationships');
371 1
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
372
373
        // Loop through images and write relationships
374 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...
375
            // Write relationship for image drawing
376 1
            $this->writeRelationship(
377
                $objWriter,
378
                $key,
379 1
                'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
380 1
                '../media/' . $value->getIndexedFilename()
381
            );
382
        }
383
384 1
        $objWriter->endElement();
385
386 1
        return $objWriter->getData();
387
    }
388
389
    /**
390
     * Write Override content type.
391
     *
392
     * @param \PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter XML Writer
393
     * @param int $pId Relationship ID. rId will be prepended!
394
     * @param string $pType Relationship type
395
     * @param string $pTarget Relationship target
396
     * @param string $pTargetMode Relationship target mode
397
     *
398
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
399
     */
400 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...
401
    {
402 56
        if ($pType != '' && $pTarget != '') {
403
            // Write relationship
404 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...
405 56
            $objWriter->writeAttribute('Id', 'rId' . $pId);
406 56
            $objWriter->writeAttribute('Type', $pType);
407 56
            $objWriter->writeAttribute('Target', $pTarget);
408
409 56
            if ($pTargetMode != '') {
410 9
                $objWriter->writeAttribute('TargetMode', $pTargetMode);
411
            }
412
413 56
            $objWriter->endElement();
414
        } else {
415
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('Invalid parameters passed.');
416
        }
417 56
    }
418
}
419