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:
Complex classes like Root often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Root, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
34 | class Root extends PPS |
||
35 | { |
||
36 | /** |
||
37 | * Directory for temporary files. |
||
38 | * |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $tempDirectory = null; |
||
42 | |||
43 | /** |
||
44 | * @param int $time_1st A timestamp |
||
45 | * @param int $time_2nd A timestamp |
||
46 | * @param File[] $raChild |
||
47 | */ |
||
48 | 39 | public function __construct($time_1st, $time_2nd, $raChild) |
|
54 | |||
55 | /** |
||
56 | * Method for saving the whole OLE container (including files). |
||
57 | * In fact, if called with an empty argument (or '-'), it saves to a |
||
58 | * temporary file and then outputs it's contents to stdout. |
||
59 | * If a resource pointer to a stream created by fopen() is passed |
||
60 | * it will be used, but you have to close such stream by yourself. |
||
61 | * |
||
62 | * @param string|resource $filename the name of the file or stream where to save the OLE container |
||
63 | * |
||
64 | * @throws WriterException |
||
65 | * |
||
66 | * @return bool true on success |
||
67 | */ |
||
68 | 39 | public function save($filename) |
|
121 | |||
122 | /** |
||
123 | * Calculate some numbers. |
||
124 | * |
||
125 | * @param array $raList Reference to an array of PPS's |
||
126 | * |
||
127 | * @return float[] The array of numbers |
||
128 | */ |
||
129 | 39 | public function _calcSize(&$raList) |
|
159 | |||
160 | /** |
||
161 | * Helper function for caculating a magic value for block sizes. |
||
162 | * |
||
163 | * @param int $i2 The argument |
||
164 | * |
||
165 | * @see save() |
||
166 | * |
||
167 | * @return float |
||
168 | */ |
||
169 | private static function adjust2($i2) |
||
170 | { |
||
171 | $iWk = log($i2) / log(2); |
||
172 | |||
173 | return ($iWk > floor($iWk)) ? floor($iWk) + 1 : $iWk; |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Save OLE header. |
||
178 | * |
||
179 | * @param int $iSBDcnt |
||
180 | * @param int $iBBcnt |
||
181 | * @param int $iPPScnt |
||
182 | */ |
||
183 | 39 | public function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt) |
|
184 | { |
||
185 | 39 | $FILE = $this->_FILEH_; |
|
186 | |||
187 | // Calculate Basic Setting |
||
188 | 39 | $iBlCnt = $this->_BIG_BLOCK_SIZE / OLE::OLE_LONG_INT_SIZE; |
|
189 | 39 | $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE::OLE_LONG_INT_SIZE; |
|
190 | |||
191 | 39 | $iBdExL = 0; |
|
192 | 39 | $iAll = $iBBcnt + $iPPScnt + $iSBDcnt; |
|
193 | 39 | $iAllW = $iAll; |
|
194 | 39 | $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0); |
|
195 | 39 | $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0); |
|
196 | |||
197 | // Calculate BD count |
||
198 | 39 | View Code Duplication | if ($iBdCnt > $i1stBdL) { |
199 | while (1) { |
||
200 | ++$iBdExL; |
||
201 | ++$iAllW; |
||
202 | $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0); |
||
203 | $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0); |
||
204 | if ($iBdCnt <= ($iBdExL * $iBlCnt + $i1stBdL)) { |
||
205 | break; |
||
206 | } |
||
207 | } |
||
208 | } |
||
209 | |||
210 | // Save Header |
||
211 | 39 | fwrite( |
|
212 | 39 | $FILE, |
|
213 | "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" |
||
214 | . "\x00\x00\x00\x00" |
||
215 | . "\x00\x00\x00\x00" |
||
216 | . "\x00\x00\x00\x00" |
||
217 | . "\x00\x00\x00\x00" |
||
218 | 39 | . pack('v', 0x3b) |
|
219 | 39 | . pack('v', 0x03) |
|
220 | 39 | . pack('v', -2) |
|
221 | 39 | . pack('v', 9) |
|
222 | 39 | . pack('v', 6) |
|
223 | 39 | . pack('v', 0) |
|
224 | 39 | . "\x00\x00\x00\x00" |
|
225 | 39 | . "\x00\x00\x00\x00" |
|
226 | 39 | . pack('V', $iBdCnt) |
|
227 | 39 | . pack('V', $iBBcnt + $iSBDcnt) //ROOT START |
|
228 | 39 | . pack('V', 0) |
|
229 | 39 | . pack('V', 0x1000) |
|
230 | 39 | . pack('V', $iSBDcnt ? 0 : -2) //Small Block Depot |
|
231 | 39 | . pack('V', $iSBDcnt) |
|
232 | ); |
||
233 | // Extra BDList Start, Count |
||
234 | 39 | if ($iBdCnt < $i1stBdL) { |
|
235 | 39 | fwrite( |
|
236 | 39 | $FILE, |
|
237 | 39 | pack('V', -2) // Extra BDList Start |
|
238 | 39 | . pack('V', 0)// Extra BDList Count |
|
239 | ); |
||
240 | } else { |
||
241 | fwrite($FILE, pack('V', $iAll + $iBdCnt) . pack('V', $iBdExL)); |
||
242 | } |
||
243 | |||
244 | // BDList |
||
245 | 39 | for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) { |
|
246 | 39 | fwrite($FILE, pack('V', $iAll + $i)); |
|
247 | } |
||
248 | 39 | if ($i < $i1stBdL) { |
|
249 | 39 | $jB = $i1stBdL - $i; |
|
250 | 39 | View Code Duplication | for ($j = 0; $j < $jB; ++$j) { |
251 | 39 | fwrite($FILE, (pack('V', -1))); |
|
252 | } |
||
253 | } |
||
254 | 39 | } |
|
255 | |||
256 | /** |
||
257 | * Saving big data (PPS's with data bigger than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL). |
||
258 | * |
||
259 | * @param int $iStBlk |
||
260 | * @param array &$raList Reference to array of PPS's |
||
261 | */ |
||
262 | 39 | public function _saveBigData($iStBlk, &$raList) |
|
286 | |||
287 | /** |
||
288 | * get small data (PPS's with data smaller than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL). |
||
289 | * |
||
290 | * @param array &$raList Reference to array of PPS's |
||
291 | */ |
||
292 | 39 | public function _makeSmallData(&$raList) |
|
336 | |||
337 | /** |
||
338 | * Saves all the PPS's WKs. |
||
339 | * |
||
340 | * @param array $raList Reference to an array with all PPS's |
||
341 | */ |
||
342 | 39 | public function _savePps(&$raList) |
|
356 | |||
357 | /** |
||
358 | * Saving Big Block Depot. |
||
359 | * |
||
360 | * @param int $iSbdSize |
||
361 | * @param int $iBsize |
||
362 | * @param int $iPpsCnt |
||
363 | */ |
||
364 | 39 | public function _saveBbd($iSbdSize, $iBsize, $iPpsCnt) |
|
444 | } |
||
445 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: