Completed
Push — develop ( 3560f1...5fce89 )
by Adrien
21:58 queued 15:06
created

Ods::save()   C

Complexity

Conditions 8
Paths 13

Size

Total Lines 41
Code Lines 23

Duplication

Lines 12
Ratio 29.27 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
cc 8
eloc 23
nc 13
nop 1
dl 12
loc 41
rs 5.3846
c 0
b 0
f 0
ccs 0
cts 24
cp 0
crap 72
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer;
4
5
use PhpOffice\PhpSpreadsheet\Spreadsheet;
6
7
/**
8
 * Copyright (c) 2006 - 2015 PhpSpreadsheet.
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
 *
24
 * @category   PhpSpreadsheet
25
 *
26
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
27
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
28
 */
29
class Ods extends BaseWriter implements IWriter
30
{
31
    /**
32
     * Private writer parts.
33
     *
34
     * @var Ods\WriterPart[]
35
     */
36
    private $writerParts = [];
37
38
    /**
39
     * Private PhpSpreadsheet.
40
     *
41
     * @var PhpSpreadsheet
42
     */
43
    private $spreadSheet;
44
45
    /**
46
     * Create a new Ods.
47
     *
48
     * @param \PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet
49
     */
50 2
    public function __construct(\PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet = null)
51
    {
52 2
        $this->setSpreadsheet($spreadsheet);
53
54
        $writerPartsArray = [
55 2
            'content' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Content::class,
56
            'meta' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Meta::class,
57
            'meta_inf' => \PhpOffice\PhpSpreadsheet\Writer\Ods\MetaInf::class,
58
            'mimetype' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype::class,
59
            'settings' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Settings::class,
60
            'styles' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Styles::class,
61
            'thumbnails' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Thumbnails::class,
62
        ];
63
64 2
        foreach ($writerPartsArray as $writer => $class) {
65 2
            $this->writerParts[$writer] = new $class($this);
66
        }
67 2
    }
68
69
    /**
70
     * Get writer part.
71
     *
72
     * @param string $pPartName Writer part name
73
     *
74
     * @return Ods\WriterPart|null
75
     */
76 View Code Duplication
    public function getWriterPart($pPartName = '')
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...
77
    {
78
        if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) {
79
            return $this->writerParts[strtolower($pPartName)];
80
        }
81
82
        return null;
83
    }
84
85
    /**
86
     * Save PhpSpreadsheet to file.
87
     *
88
     * @param string $pFilename
89
     *
90
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
91
     */
92
    public function save($pFilename = null)
93
    {
94
        if (!$this->spreadSheet) {
95
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('PhpSpreadsheet object unassigned.');
96
        }
97
98
        // garbage collect
99
        $this->spreadSheet->garbageCollect();
100
101
        // If $pFilename is php://output or php://stdout, make it a temporary file...
102
        $originalFilename = $pFilename;
103 View Code Duplication
        if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
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...
104
            $pFilename = @tempnam(\PhpOffice\PhpSpreadsheet\Shared\File::sysGetTempDir(), 'phpxltmp');
105
            if ($pFilename == '') {
106
                $pFilename = $originalFilename;
107
            }
108
        }
109
110
        $objZip = $this->createZip($pFilename);
111
112
        $objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart as the method writeManifest() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Ods\MetaInf. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
113
        $objZip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart as the method writeThumbnail() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Ods\Thumbnails. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
114
        $objZip->addFromString('content.xml', $this->getWriterPart('content')->write());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart as the method write() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Ods\Content, PhpOffice\PhpSpreadsheet\Writer\Ods\Meta, PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype, PhpOffice\PhpSpreadsheet\Writer\Ods\Settings, PhpOffice\PhpSpreadsheet\Writer\Ods\Styles. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
115
        $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->write());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart as the method write() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Ods\Content, PhpOffice\PhpSpreadsheet\Writer\Ods\Meta, PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype, PhpOffice\PhpSpreadsheet\Writer\Ods\Settings, PhpOffice\PhpSpreadsheet\Writer\Ods\Styles. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
116
        $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->write());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart as the method write() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Ods\Content, PhpOffice\PhpSpreadsheet\Writer\Ods\Meta, PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype, PhpOffice\PhpSpreadsheet\Writer\Ods\Settings, PhpOffice\PhpSpreadsheet\Writer\Ods\Styles. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
117
        $objZip->addFromString('settings.xml', $this->getWriterPart('settings')->write());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart as the method write() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Ods\Content, PhpOffice\PhpSpreadsheet\Writer\Ods\Meta, PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype, PhpOffice\PhpSpreadsheet\Writer\Ods\Settings, PhpOffice\PhpSpreadsheet\Writer\Ods\Styles. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
118
        $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->write());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart as the method write() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Ods\Content, PhpOffice\PhpSpreadsheet\Writer\Ods\Meta, PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype, PhpOffice\PhpSpreadsheet\Writer\Ods\Settings, PhpOffice\PhpSpreadsheet\Writer\Ods\Styles. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
119
120
        // Close file
121
        if ($objZip->close() === false) {
122
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("Could not close zip file $pFilename.");
123
        }
124
125
        // If a temporary file was used, copy it to the correct file stream
126 View Code Duplication
        if ($originalFilename != $pFilename) {
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...
127
            if (copy($pFilename, $originalFilename) === false) {
128
                throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("Could not copy temporary zip file $pFilename to $originalFilename.");
129
            }
130
            @unlink($pFilename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
131
        }
132
    }
133
134
    /**
135
     * Create zip object.
136
     *
137
     * @param string $pFilename
138
     *
139
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
140
     *
141
     * @return ZipArchive
142
     */
143
    private function createZip($pFilename)
144
    {
145
        // Create new ZIP file and open it for writing
146
        $zipClass = \PhpOffice\PhpSpreadsheet\Settings::getZipClass();
147
        $objZip = new $zipClass();
148
149
        // Retrieve OVERWRITE and CREATE constants from the instantiated zip class
150
        // This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP
151
        $ro = new \ReflectionObject($objZip);
152
        $zipOverWrite = $ro->getConstant('OVERWRITE');
153
        $zipCreate = $ro->getConstant('CREATE');
154
155
        if (file_exists($pFilename)) {
156
            unlink($pFilename);
157
        }
158
        // Try opening the ZIP file
159 View Code Duplication
        if ($objZip->open($pFilename, $zipOverWrite) !== true) {
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...
160
            if ($objZip->open($pFilename, $zipCreate) !== true) {
161
                throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("Could not open $pFilename for writing.");
162
            }
163
        }
164
165
        return $objZip;
166
    }
167
168
    /**
169
     * Get Spreadsheet object.
170
     *
171
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
172
     *
173
     * @return Spreadsheet
174
     */
175 2
    public function getSpreadsheet()
176
    {
177 2
        if ($this->spreadSheet !== null) {
178 2
            return $this->spreadSheet;
179
        }
180
        throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('No PhpSpreadsheet assigned.');
181
    }
182
183
    /**
184
     * Set Spreadsheet object.
185
     *
186
     * @param \PhpOffice\PhpSpreadsheet\Spreadsheet $spreadsheet PhpSpreadsheet object
187
     *
188
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
189
     *
190
     * @return self
191
     */
192 2
    public function setSpreadsheet(\PhpOffice\PhpSpreadsheet\SpreadSheet $spreadsheet = null)
193
    {
194 2
        $this->spreadSheet = $spreadsheet;
0 ignored issues
show
Documentation Bug introduced by
It seems like $spreadsheet can also be of type object<PhpOffice\PhpSpreadsheet\Spreadsheet>. However, the property $spreadSheet is declared as type object<PhpOffice\PhpSpre...\Writer\PhpSpreadsheet>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
195
196 2
        return $this;
197
    }
198
}
199