Completed
Push — master ( 4b5c92...896769 )
by Adrien
16:06 queued 09:43
created

Root::_saveHeader()   F

Complexity

Conditions 14
Paths 480

Size

Total Lines 69
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 15.2612

Importance

Changes 0
Metric Value
cc 14
eloc 50
c 0
b 0
f 0
nc 480
nop 3
dl 0
loc 69
ccs 35
cts 43
cp 0.8139
crap 15.2612
rs 2.8222

How to fix   Long Method    Complexity   

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\Shared\OLE\PPS;
4
5
// vim: set expandtab tabstop=4 shiftwidth=4:
6
// +----------------------------------------------------------------------+
7
// | PHP Version 4                                                        |
8
// +----------------------------------------------------------------------+
9
// | Copyright (c) 1997-2002 The PHP Group                                |
10
// +----------------------------------------------------------------------+
11
// | This source file is subject to version 2.02 of the PHP license,      |
12
// | that is bundled with this package in the file LICENSE, and is        |
13
// | available at through the world-wide-web at                           |
14
// | http://www.php.net/license/2_02.txt.                                 |
15
// | If you did not receive a copy of the PHP license and are unable to   |
16
// | obtain it through the world-wide-web, please send a note to          |
17
// | [email protected] so we can mail you a copy immediately.               |
18
// +----------------------------------------------------------------------+
19
// | Author: Xavier Noguer <[email protected]>                              |
20
// | Based on OLE::Storage_Lite by Kawai, Takanori                        |
21
// +----------------------------------------------------------------------+
22
//
23
use PhpOffice\PhpSpreadsheet\Shared\OLE;
24
use PhpOffice\PhpSpreadsheet\Shared\OLE\PPS;
25
26
/**
27
 * Class for creating Root PPS's for OLE containers.
28
 *
29
 * @author   Xavier Noguer <[email protected]>
30
 *
31
 * @category PhpSpreadsheet
32
 */
33
class Root extends PPS
34
{
35
    /**
36
     * @var resource
37
     */
38
    private $fileHandle;
39
40
    /**
41
     * @var int
42
     */
43
    private $smallBlockSize;
44
45
    /**
46
     * @var int
47
     */
48
    private $bigBlockSize;
49
50
    /**
51
     * @param int $time_1st A timestamp
52
     * @param int $time_2nd A timestamp
53
     * @param File[] $raChild
54
     */
55 51
    public function __construct($time_1st, $time_2nd, $raChild)
56
    {
57 51
        parent::__construct(null, OLE::ascToUcs('Root Entry'), OLE::OLE_PPS_TYPE_ROOT, null, null, null, $time_1st, $time_2nd, null, $raChild);
58 51
    }
59
60
    /**
61
     * Method for saving the whole OLE container (including files).
62
     * In fact, if called with an empty argument (or '-'), it saves to a
63
     * temporary file and then outputs it's contents to stdout.
64
     * If a resource pointer to a stream created by fopen() is passed
65
     * it will be used, but you have to close such stream by yourself.
66
     *
67
     * @param resource $fileHandle the name of the file or stream where to save the OLE container
68
     *
69
     * @return bool true on success
70
     */
71 51
    public function save($fileHandle)
72
    {
73 51
        $this->fileHandle = $fileHandle;
74
75
        // Initial Setting for saving
76 51
        $this->bigBlockSize = pow(
77 51
            2,
78 51
            (isset($this->bigBlockSize)) ? self::adjust2($this->bigBlockSize) : 9
79
        );
80 51
        $this->smallBlockSize = pow(
81 51
            2,
82 51
            (isset($this->smallBlockSize)) ? self::adjust2($this->smallBlockSize) : 6
83
        );
84
85
        // Make an array of PPS's (for Save)
86 51
        $aList = [];
87 51
        PPS::_savePpsSetPnt($aList, [$this]);
88
        // calculate values for header
89 51
        [$iSBDcnt, $iBBcnt, $iPPScnt] = $this->_calcSize($aList); //, $rhInfo);
90
        // Save Header
91 51
        $this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
0 ignored issues
show
Bug introduced by
$iSBDcnt of type double is incompatible with the type integer expected by parameter $iSBDcnt of PhpOffice\PhpSpreadsheet...PPS\Root::_saveHeader(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
        $this->_saveHeader(/** @scrutinizer ignore-type */ $iSBDcnt, $iBBcnt, $iPPScnt);
Loading history...
Bug introduced by
$iPPScnt of type double is incompatible with the type integer expected by parameter $iPPScnt of PhpOffice\PhpSpreadsheet...PPS\Root::_saveHeader(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
        $this->_saveHeader($iSBDcnt, $iBBcnt, /** @scrutinizer ignore-type */ $iPPScnt);
Loading history...
Bug introduced by
$iBBcnt of type double is incompatible with the type integer expected by parameter $iBBcnt of PhpOffice\PhpSpreadsheet...PPS\Root::_saveHeader(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
        $this->_saveHeader($iSBDcnt, /** @scrutinizer ignore-type */ $iBBcnt, $iPPScnt);
Loading history...
92
93
        // Make Small Data string (write SBD)
94 51
        $this->_data = $this->_makeSmallData($aList);
95
96
        // Write BB
97 51
        $this->_saveBigData($iSBDcnt, $aList);
0 ignored issues
show
Bug introduced by
$iSBDcnt of type double is incompatible with the type integer expected by parameter $iStBlk of PhpOffice\PhpSpreadsheet...PS\Root::_saveBigData(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

97
        $this->_saveBigData(/** @scrutinizer ignore-type */ $iSBDcnt, $aList);
Loading history...
98
        // Write PPS
99 51
        $this->_savePps($aList);
100
        // Write Big Block Depot and BDList and Adding Header informations
101 51
        $this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
0 ignored issues
show
Bug introduced by
$iPPScnt of type double is incompatible with the type integer expected by parameter $iPpsCnt of PhpOffice\PhpSpreadsheet...LE\PPS\Root::_saveBbd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        $this->_saveBbd($iSBDcnt, $iBBcnt, /** @scrutinizer ignore-type */ $iPPScnt);
Loading history...
Bug introduced by
$iSBDcnt of type double is incompatible with the type integer expected by parameter $iSbdSize of PhpOffice\PhpSpreadsheet...LE\PPS\Root::_saveBbd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        $this->_saveBbd(/** @scrutinizer ignore-type */ $iSBDcnt, $iBBcnt, $iPPScnt);
Loading history...
Bug introduced by
$iBBcnt of type double is incompatible with the type integer expected by parameter $iBsize of PhpOffice\PhpSpreadsheet...LE\PPS\Root::_saveBbd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        $this->_saveBbd($iSBDcnt, /** @scrutinizer ignore-type */ $iBBcnt, $iPPScnt);
Loading history...
102
103 51
        return true;
104
    }
105
106
    /**
107
     * Calculate some numbers.
108
     *
109
     * @param array $raList Reference to an array of PPS's
110
     *
111
     * @return float[] The array of numbers
112
     */
113 51
    public function _calcSize(&$raList)
114
    {
115
        // Calculate Basic Setting
116 51
        [$iSBDcnt, $iBBcnt, $iPPScnt] = [0, 0, 0];
117 51
        $iSmallLen = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $iSmallLen is dead and can be removed.
Loading history...
118 51
        $iSBcnt = 0;
119 51
        $iCount = count($raList);
120 51
        for ($i = 0; $i < $iCount; ++$i) {
121 51
            if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
122 51
                $raList[$i]->Size = $raList[$i]->getDataLen();
123 51
                if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) {
124 51
                    $iSBcnt += floor($raList[$i]->Size / $this->smallBlockSize)
125 51
                                  + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0);
126
                } else {
127 21
                    $iBBcnt += (floor($raList[$i]->Size / $this->bigBlockSize) +
128 21
                        (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0));
129
                }
130
            }
131
        }
132 51
        $iSmallLen = $iSBcnt * $this->smallBlockSize;
133 51
        $iSlCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
134 51
        $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt) ? 1 : 0);
135 51
        $iBBcnt += (floor($iSmallLen / $this->bigBlockSize) +
136 51
                      (($iSmallLen % $this->bigBlockSize) ? 1 : 0));
137 51
        $iCnt = count($raList);
138 51
        $iBdCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
139 51
        $iPPScnt = (floor($iCnt / $iBdCnt) + (($iCnt % $iBdCnt) ? 1 : 0));
140
141 51
        return [$iSBDcnt, $iBBcnt, $iPPScnt];
142
    }
143
144
    /**
145
     * Helper function for caculating a magic value for block sizes.
146
     *
147
     * @param int $i2 The argument
148
     *
149
     * @see save()
150
     *
151
     * @return float
152
     */
153
    private static function adjust2($i2)
154
    {
155
        $iWk = log($i2) / log(2);
156
157
        return ($iWk > floor($iWk)) ? floor($iWk) + 1 : $iWk;
158
    }
159
160
    /**
161
     * Save OLE header.
162
     *
163
     * @param int $iSBDcnt
164
     * @param int $iBBcnt
165
     * @param int $iPPScnt
166
     */
167 51
    public function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
168
    {
169 51
        $FILE = $this->fileHandle;
170
171
        // Calculate Basic Setting
172 51
        $iBlCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
173 51
        $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
174
175 51
        $iBdExL = 0;
176 51
        $iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
177 51
        $iAllW = $iAll;
178 51
        $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
179 51
        $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
180
181
        // Calculate BD count
182 51
        if ($iBdCnt > $i1stBdL) {
183
            while (1) {
184
                ++$iBdExL;
185
                ++$iAllW;
186
                $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
187
                $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
188
                if ($iBdCnt <= ($iBdExL * $iBlCnt + $i1stBdL)) {
189
                    break;
190
                }
191
            }
192
        }
193
194
        // Save Header
195 51
        fwrite(
196
            $FILE,
197
            "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
198
            . "\x00\x00\x00\x00"
199
            . "\x00\x00\x00\x00"
200
            . "\x00\x00\x00\x00"
201
            . "\x00\x00\x00\x00"
202 51
            . pack('v', 0x3b)
203 51
            . pack('v', 0x03)
204 51
            . pack('v', -2)
205 51
            . pack('v', 9)
206 51
            . pack('v', 6)
207 51
            . pack('v', 0)
208 51
            . "\x00\x00\x00\x00"
209 51
            . "\x00\x00\x00\x00"
210 51
            . pack('V', $iBdCnt)
211 51
            . pack('V', $iBBcnt + $iSBDcnt) //ROOT START
212 51
            . pack('V', 0)
213 51
            . pack('V', 0x1000)
214 51
            . pack('V', $iSBDcnt ? 0 : -2) //Small Block Depot
215 51
            . pack('V', $iSBDcnt)
216
        );
217
        // Extra BDList Start, Count
218 51
        if ($iBdCnt < $i1stBdL) {
219 51
            fwrite(
220
                $FILE,
221 51
                pack('V', -2) // Extra BDList Start
222 51
                . pack('V', 0)// Extra BDList Count
223
            );
224
        } else {
225
            fwrite($FILE, pack('V', $iAll + $iBdCnt) . pack('V', $iBdExL));
226
        }
227
228
        // BDList
229 51
        for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) {
230 51
            fwrite($FILE, pack('V', $iAll + $i));
231
        }
232 51
        if ($i < $i1stBdL) {
233 51
            $jB = $i1stBdL - $i;
234 51
            for ($j = 0; $j < $jB; ++$j) {
235 51
                fwrite($FILE, (pack('V', -1)));
236
            }
237
        }
238 51
    }
239
240
    /**
241
     * Saving big data (PPS's with data bigger than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
242
     *
243
     * @param int $iStBlk
244
     * @param array &$raList Reference to array of PPS's
245
     */
246 51
    public function _saveBigData($iStBlk, &$raList)
247
    {
248 51
        $FILE = $this->fileHandle;
249
250
        // cycle through PPS's
251 51
        $iCount = count($raList);
252 51
        for ($i = 0; $i < $iCount; ++$i) {
253 51
            if ($raList[$i]->Type != OLE::OLE_PPS_TYPE_DIR) {
254 51
                $raList[$i]->Size = $raList[$i]->getDataLen();
255 51
                if (($raList[$i]->Size >= OLE::OLE_DATA_SIZE_SMALL) || (($raList[$i]->Type == OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) {
256 51
                    fwrite($FILE, $raList[$i]->_data);
257
258 51
                    if ($raList[$i]->Size % $this->bigBlockSize) {
259 48
                        fwrite($FILE, str_repeat("\x00", $this->bigBlockSize - ($raList[$i]->Size % $this->bigBlockSize)));
260
                    }
261
                    // Set For PPS
262 51
                    $raList[$i]->startBlock = $iStBlk;
263
                    $iStBlk +=
264 51
                            (floor($raList[$i]->Size / $this->bigBlockSize) +
265 51
                                (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0));
266
                }
267
            }
268
        }
269 51
    }
270
271
    /**
272
     * get small data (PPS's with data smaller than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
273
     *
274
     * @param array &$raList Reference to array of PPS's
275
     *
276
     * @return string
277
     */
278 51
    public function _makeSmallData(&$raList)
279
    {
280 51
        $sRes = '';
281 51
        $FILE = $this->fileHandle;
282 51
        $iSmBlk = 0;
283
284 51
        $iCount = count($raList);
285 51
        for ($i = 0; $i < $iCount; ++$i) {
286
            // Make SBD, small data string
287 51
            if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
288 51
                if ($raList[$i]->Size <= 0) {
289
                    continue;
290
                }
291 51
                if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) {
292 51
                    $iSmbCnt = floor($raList[$i]->Size / $this->smallBlockSize)
293 51
                                  + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0);
294
                    // Add to SBD
295 51
                    $jB = $iSmbCnt - 1;
296 51
                    for ($j = 0; $j < $jB; ++$j) {
297 51
                        fwrite($FILE, pack('V', $j + $iSmBlk + 1));
298
                    }
299 51
                    fwrite($FILE, pack('V', -2));
300
301
                    // Add to Data String(this will be written for RootEntry)
302 51
                    $sRes .= $raList[$i]->_data;
303 51
                    if ($raList[$i]->Size % $this->smallBlockSize) {
304 51
                        $sRes .= str_repeat("\x00", $this->smallBlockSize - ($raList[$i]->Size % $this->smallBlockSize));
305
                    }
306
                    // Set for PPS
307 51
                    $raList[$i]->startBlock = $iSmBlk;
308 51
                    $iSmBlk += $iSmbCnt;
309
                }
310
            }
311
        }
312 51
        $iSbCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
313 51
        if ($iSmBlk % $iSbCnt) {
314 51
            $iB = $iSbCnt - ($iSmBlk % $iSbCnt);
315 51
            for ($i = 0; $i < $iB; ++$i) {
316 51
                fwrite($FILE, pack('V', -1));
317
            }
318
        }
319
320 51
        return $sRes;
321
    }
322
323
    /**
324
     * Saves all the PPS's WKs.
325
     *
326
     * @param array $raList Reference to an array with all PPS's
327
     */
328 51
    public function _savePps(&$raList)
329
    {
330
        // Save each PPS WK
331 51
        $iC = count($raList);
332 51
        for ($i = 0; $i < $iC; ++$i) {
333 51
            fwrite($this->fileHandle, $raList[$i]->_getPpsWk());
334
        }
335
        // Adjust for Block
336 51
        $iCnt = count($raList);
337 51
        $iBCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
338 51
        if ($iCnt % $iBCnt) {
339
            fwrite($this->fileHandle, str_repeat("\x00", ($iBCnt - ($iCnt % $iBCnt)) * OLE::OLE_PPS_SIZE));
340
        }
341 51
    }
342
343
    /**
344
     * Saving Big Block Depot.
345
     *
346
     * @param int $iSbdSize
347
     * @param int $iBsize
348
     * @param int $iPpsCnt
349
     */
350 51
    public function _saveBbd($iSbdSize, $iBsize, $iPpsCnt)
351
    {
352 51
        $FILE = $this->fileHandle;
353
        // Calculate Basic Setting
354 51
        $iBbCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
355 51
        $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
356
357 51
        $iBdExL = 0;
358 51
        $iAll = $iBsize + $iPpsCnt + $iSbdSize;
359 51
        $iAllW = $iAll;
360 51
        $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
361 51
        $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
362
        // Calculate BD count
363 51
        if ($iBdCnt > $i1stBdL) {
364
            while (1) {
365
                ++$iBdExL;
366
                ++$iAllW;
367
                $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
368
                $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
369
                if ($iBdCnt <= ($iBdExL * $iBbCnt + $i1stBdL)) {
370
                    break;
371
                }
372
            }
373
        }
374
375
        // Making BD
376
        // Set for SBD
377 51
        if ($iSbdSize > 0) {
378 51
            for ($i = 0; $i < ($iSbdSize - 1); ++$i) {
379
                fwrite($FILE, pack('V', $i + 1));
380
            }
381 51
            fwrite($FILE, pack('V', -2));
382
        }
383
        // Set for B
384 51
        for ($i = 0; $i < ($iBsize - 1); ++$i) {
385 51
            fwrite($FILE, pack('V', $i + $iSbdSize + 1));
386
        }
387 51
        fwrite($FILE, pack('V', -2));
388
389
        // Set for PPS
390 51
        for ($i = 0; $i < ($iPpsCnt - 1); ++$i) {
391
            fwrite($FILE, pack('V', $i + $iSbdSize + $iBsize + 1));
392
        }
393 51
        fwrite($FILE, pack('V', -2));
394
        // Set for BBD itself ( 0xFFFFFFFD : BBD)
395 51
        for ($i = 0; $i < $iBdCnt; ++$i) {
396 51
            fwrite($FILE, pack('V', 0xFFFFFFFD));
397
        }
398
        // Set for ExtraBDList
399 51
        for ($i = 0; $i < $iBdExL; ++$i) {
400
            fwrite($FILE, pack('V', 0xFFFFFFFC));
401
        }
402
        // Adjust for Block
403 51
        if (($iAllW + $iBdCnt) % $iBbCnt) {
404 51
            $iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt));
405 51
            for ($i = 0; $i < $iBlock; ++$i) {
406 51
                fwrite($FILE, pack('V', -1));
407
            }
408
        }
409
        // Extra BDList
410 51
        if ($iBdCnt > $i1stBdL) {
411
            $iN = 0;
412
            $iNb = 0;
413
            for ($i = $i1stBdL; $i < $iBdCnt; $i++, ++$iN) {
414
                if ($iN >= ($iBbCnt - 1)) {
415
                    $iN = 0;
416
                    ++$iNb;
417
                    fwrite($FILE, pack('V', $iAll + $iBdCnt + $iNb));
418
                }
419
                fwrite($FILE, pack('V', $iBsize + $iSbdSize + $iPpsCnt + $i));
420
            }
421
            if (($iBdCnt - $i1stBdL) % ($iBbCnt - 1)) {
422
                $iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1));
423
                for ($i = 0; $i < $iB; ++$i) {
424
                    fwrite($FILE, pack('V', -1));
425
                }
426
            }
427
            fwrite($FILE, pack('V', -2));
428
        }
429 51
    }
430
}
431