Failed Conditions
Push — master ( 735103...6a4138 )
by Adrien
12:48
created

Root::makeSmallData()   B

Complexity

Conditions 10
Paths 16

Size

Total Lines 43
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 10.0056

Importance

Changes 0
Metric Value
cc 10
eloc 26
c 0
b 0
f 0
nc 16
nop 1
dl 0
loc 43
ccs 25
cts 26
cp 0.9615
crap 10.0056
rs 7.6666

How to fix   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
class Root extends PPS
32
{
33
    /**
34
     * @var resource
35
     */
36
    private $fileHandle;
37
38
    /**
39
     * @var int
40
     */
41
    private $smallBlockSize;
42
43
    /**
44
     * @var int
45
     */
46
    private $bigBlockSize;
47
48
    /**
49
     * @param int $time_1st A timestamp
50
     * @param int $time_2nd A timestamp
51
     * @param File[] $raChild
52
     */
53
    public function __construct($time_1st, $time_2nd, $raChild)
54
    {
55 51
        parent::__construct(null, OLE::ascToUcs('Root Entry'), OLE::OLE_PPS_TYPE_ROOT, null, null, null, $time_1st, $time_2nd, null, $raChild);
56
    }
57 51
58 51
    /**
59
     * Method for saving the whole OLE container (including files).
60
     * In fact, if called with an empty argument (or '-'), it saves to a
61
     * temporary file and then outputs it's contents to stdout.
62
     * If a resource pointer to a stream created by fopen() is passed
63
     * it will be used, but you have to close such stream by yourself.
64
     *
65
     * @param resource $fileHandle the name of the file or stream where to save the OLE container
66
     *
67
     * @return bool true on success
68
     */
69
    public function save($fileHandle)
70
    {
71 51
        $this->fileHandle = $fileHandle;
72
73 51
        // Initial Setting for saving
74
        $this->bigBlockSize = 2 ** (
75
            (isset($this->bigBlockSize)) ? self::adjust2($this->bigBlockSize) : 9
76 51
            );
77 51
        $this->smallBlockSize = 2 ** (
78 51
            (isset($this->smallBlockSize)) ? self::adjust2($this->smallBlockSize) : 6
79
            );
80 51
81 51
        // Make an array of PPS's (for Save)
82 51
        $aList = [];
83
        PPS::savePpsSetPnt($aList, [$this]);
84
        // calculate values for header
85
        [$iSBDcnt, $iBBcnt, $iPPScnt] = $this->calcSize($aList); //, $rhInfo);
86 51
        // Save Header
87 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

87
        $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

87
        $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

87
        $this->saveHeader($iSBDcnt, /** @scrutinizer ignore-type */ $iBBcnt, $iPPScnt);
Loading history...
88
89 51
        // Make Small Data string (write SBD)
90
        $this->_data = $this->makeSmallData($aList);
91 51
92
        // Write BB
93
        $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...PPS\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

93
        $this->saveBigData(/** @scrutinizer ignore-type */ $iSBDcnt, $aList);
Loading history...
94 51
        // Write PPS
95
        $this->savePps($aList);
96
        // Write Big Block Depot and BDList and Adding Header informations
97 51
        $this->saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
0 ignored issues
show
Bug introduced by
$iSBDcnt of type double is incompatible with the type integer expected by parameter $iSbdSize of PhpOffice\PhpSpreadsheet...OLE\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

97
        $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...OLE\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

97
        $this->saveBbd($iSBDcnt, /** @scrutinizer ignore-type */ $iBBcnt, $iPPScnt);
Loading history...
Bug introduced by
$iPPScnt of type double is incompatible with the type integer expected by parameter $iPpsCnt of PhpOffice\PhpSpreadsheet...OLE\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

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