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 Font 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 Font, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | class Font |
||
28 | { |
||
29 | /* Methods for resolving autosize value */ |
||
30 | const AUTOSIZE_METHOD_APPROX = 'approx'; |
||
31 | const AUTOSIZE_METHOD_EXACT = 'exact'; |
||
32 | |||
33 | private static $autoSizeMethods = [ |
||
34 | self::AUTOSIZE_METHOD_APPROX, |
||
35 | self::AUTOSIZE_METHOD_EXACT, |
||
36 | ]; |
||
37 | |||
38 | /** Character set codes used by BIFF5-8 in Font records */ |
||
39 | const CHARSET_ANSI_LATIN = 0x00; |
||
40 | const CHARSET_SYSTEM_DEFAULT = 0x01; |
||
41 | const CHARSET_SYMBOL = 0x02; |
||
42 | const CHARSET_APPLE_ROMAN = 0x4D; |
||
43 | const CHARSET_ANSI_JAPANESE_SHIFTJIS = 0x80; |
||
44 | const CHARSET_ANSI_KOREAN_HANGUL = 0x81; |
||
45 | const CHARSET_ANSI_KOREAN_JOHAB = 0x82; |
||
46 | const CHARSET_ANSI_CHINESE_SIMIPLIFIED = 0x86; // gb2312 |
||
47 | const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88; // big5 |
||
48 | const CHARSET_ANSI_GREEK = 0xA1; |
||
49 | const CHARSET_ANSI_TURKISH = 0xA2; |
||
50 | const CHARSET_ANSI_VIETNAMESE = 0xA3; |
||
51 | const CHARSET_ANSI_HEBREW = 0xB1; |
||
52 | const CHARSET_ANSI_ARABIC = 0xB2; |
||
53 | const CHARSET_ANSI_BALTIC = 0xBA; |
||
54 | const CHARSET_ANSI_CYRILLIC = 0xCC; |
||
55 | const CHARSET_ANSI_THAI = 0xDD; |
||
56 | const CHARSET_ANSI_LATIN_II = 0xEE; |
||
57 | const CHARSET_OEM_LATIN_I = 0xFF; |
||
58 | |||
59 | // XXX: Constants created! |
||
60 | /** Font filenames */ |
||
61 | const ARIAL = 'arial.ttf'; |
||
62 | const ARIAL_BOLD = 'arialbd.ttf'; |
||
63 | const ARIAL_ITALIC = 'ariali.ttf'; |
||
64 | const ARIAL_BOLD_ITALIC = 'arialbi.ttf'; |
||
65 | |||
66 | const CALIBRI = 'CALIBRI.TTF'; |
||
67 | const CALIBRI_BOLD = 'CALIBRIB.TTF'; |
||
68 | const CALIBRI_ITALIC = 'CALIBRII.TTF'; |
||
69 | const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF'; |
||
70 | |||
71 | const COMIC_SANS_MS = 'comic.ttf'; |
||
72 | const COMIC_SANS_MS_BOLD = 'comicbd.ttf'; |
||
73 | |||
74 | const COURIER_NEW = 'cour.ttf'; |
||
75 | const COURIER_NEW_BOLD = 'courbd.ttf'; |
||
76 | const COURIER_NEW_ITALIC = 'couri.ttf'; |
||
77 | const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf'; |
||
78 | |||
79 | const GEORGIA = 'georgia.ttf'; |
||
80 | const GEORGIA_BOLD = 'georgiab.ttf'; |
||
81 | const GEORGIA_ITALIC = 'georgiai.ttf'; |
||
82 | const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf'; |
||
83 | |||
84 | const IMPACT = 'impact.ttf'; |
||
85 | |||
86 | const LIBERATION_SANS = 'LiberationSans-Regular.ttf'; |
||
87 | const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf'; |
||
88 | const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf'; |
||
89 | const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf'; |
||
90 | |||
91 | const LUCIDA_CONSOLE = 'lucon.ttf'; |
||
92 | const LUCIDA_SANS_UNICODE = 'l_10646.ttf'; |
||
93 | |||
94 | const MICROSOFT_SANS_SERIF = 'micross.ttf'; |
||
95 | |||
96 | const PALATINO_LINOTYPE = 'pala.ttf'; |
||
97 | const PALATINO_LINOTYPE_BOLD = 'palab.ttf'; |
||
98 | const PALATINO_LINOTYPE_ITALIC = 'palai.ttf'; |
||
99 | const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf'; |
||
100 | |||
101 | const SYMBOL = 'symbol.ttf'; |
||
102 | |||
103 | const TAHOMA = 'tahoma.ttf'; |
||
104 | const TAHOMA_BOLD = 'tahomabd.ttf'; |
||
105 | |||
106 | const TIMES_NEW_ROMAN = 'times.ttf'; |
||
107 | const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf'; |
||
108 | const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf'; |
||
109 | const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf'; |
||
110 | |||
111 | const TREBUCHET_MS = 'trebuc.ttf'; |
||
112 | const TREBUCHET_MS_BOLD = 'trebucbd.ttf'; |
||
113 | const TREBUCHET_MS_ITALIC = 'trebucit.ttf'; |
||
114 | const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf'; |
||
115 | |||
116 | const VERDANA = 'verdana.ttf'; |
||
117 | const VERDANA_BOLD = 'verdanab.ttf'; |
||
118 | const VERDANA_ITALIC = 'verdanai.ttf'; |
||
119 | const VERDANA_BOLD_ITALIC = 'verdanaz.ttf'; |
||
120 | |||
121 | /** |
||
122 | * AutoSize method |
||
123 | * |
||
124 | * @var string |
||
125 | */ |
||
126 | private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX; |
||
127 | |||
128 | /** |
||
129 | * Path to folder containing TrueType font .ttf files |
||
130 | * |
||
131 | * @var string |
||
132 | */ |
||
133 | private static $trueTypeFontPath = null; |
||
134 | |||
135 | /** |
||
136 | * How wide is a default column for a given default font and size? |
||
137 | * Empirical data found by inspecting real Excel files and reading off the pixel width |
||
138 | * in Microsoft Office Excel 2007. |
||
139 | * |
||
140 | * @var array |
||
141 | */ |
||
142 | public static $defaultColumnWidths = [ |
||
143 | 'Arial' => [ |
||
144 | 1 => ['px' => 24, 'width' => 12.00000000], |
||
145 | 2 => ['px' => 24, 'width' => 12.00000000], |
||
146 | 3 => ['px' => 32, 'width' => 10.66406250], |
||
147 | 4 => ['px' => 32, 'width' => 10.66406250], |
||
148 | 5 => ['px' => 40, 'width' => 10.00000000], |
||
149 | 6 => ['px' => 48, 'width' => 9.59765625], |
||
150 | 7 => ['px' => 48, 'width' => 9.59765625], |
||
151 | 8 => ['px' => 56, 'width' => 9.33203125], |
||
152 | 9 => ['px' => 64, 'width' => 9.14062500], |
||
153 | 10 => ['px' => 64, 'width' => 9.14062500], |
||
154 | ], |
||
155 | 'Calibri' => [ |
||
156 | 1 => ['px' => 24, 'width' => 12.00000000], |
||
157 | 2 => ['px' => 24, 'width' => 12.00000000], |
||
158 | 3 => ['px' => 32, 'width' => 10.66406250], |
||
159 | 4 => ['px' => 32, 'width' => 10.66406250], |
||
160 | 5 => ['px' => 40, 'width' => 10.00000000], |
||
161 | 6 => ['px' => 48, 'width' => 9.59765625], |
||
162 | 7 => ['px' => 48, 'width' => 9.59765625], |
||
163 | 8 => ['px' => 56, 'width' => 9.33203125], |
||
164 | 9 => ['px' => 56, 'width' => 9.33203125], |
||
165 | 10 => ['px' => 64, 'width' => 9.14062500], |
||
166 | 11 => ['px' => 64, 'width' => 9.14062500], |
||
167 | ], |
||
168 | 'Verdana' => [ |
||
169 | 1 => ['px' => 24, 'width' => 12.00000000], |
||
170 | 2 => ['px' => 24, 'width' => 12.00000000], |
||
171 | 3 => ['px' => 32, 'width' => 10.66406250], |
||
172 | 4 => ['px' => 32, 'width' => 10.66406250], |
||
173 | 5 => ['px' => 40, 'width' => 10.00000000], |
||
174 | 6 => ['px' => 48, 'width' => 9.59765625], |
||
175 | 7 => ['px' => 48, 'width' => 9.59765625], |
||
176 | 8 => ['px' => 64, 'width' => 9.14062500], |
||
177 | 9 => ['px' => 72, 'width' => 9.00000000], |
||
178 | 10 => ['px' => 72, 'width' => 9.00000000], |
||
179 | ], |
||
180 | ]; |
||
181 | |||
182 | /** |
||
183 | * Set autoSize method |
||
184 | * |
||
185 | * @param string $pValue |
||
186 | * @return bool Success or failure |
||
187 | */ |
||
188 | 2 | public static function setAutoSizeMethod($pValue = self::AUTOSIZE_METHOD_APPROX) |
|
197 | |||
198 | /** |
||
199 | * Get autoSize method |
||
200 | * |
||
201 | * @return string |
||
202 | */ |
||
203 | 1 | public static function getAutoSizeMethod() |
|
207 | |||
208 | /** |
||
209 | * Set the path to the folder containing .ttf files. There should be a trailing slash. |
||
210 | * Typical locations on variout some platforms: |
||
211 | * <ul> |
||
212 | * <li>C:/Windows/Fonts/</li> |
||
213 | * <li>/usr/share/fonts/truetype/</li> |
||
214 | * <li>~/.fonts/</li> |
||
215 | * </ul> |
||
216 | * |
||
217 | * @param string $pValue |
||
218 | */ |
||
219 | public static function setTrueTypeFontPath($pValue = '') |
||
223 | |||
224 | /** |
||
225 | * Get the path to the folder containing .ttf files. |
||
226 | * |
||
227 | * @return string |
||
228 | */ |
||
229 | public static function getTrueTypeFontPath() |
||
233 | |||
234 | /** |
||
235 | * Calculate an (approximate) OpenXML column width, based on font size and text contained |
||
236 | * |
||
237 | * @param \PhpSpreadsheet\Style\Font $font Font object |
||
238 | * @param \PhpSpreadsheet\RichText|string $cellText Text to calculate width |
||
239 | * @param int $rotation Rotation angle |
||
240 | * @param \PhpSpreadsheet\Style\Font|null $defaultFont Font object |
||
241 | * @return int Column width |
||
242 | */ |
||
243 | public static function calculateColumnWidth(\PhpSpreadsheet\Style\Font $font, $cellText = '', $rotation = 0, \PhpSpreadsheet\Style\Font $defaultFont = null) |
||
287 | |||
288 | /** |
||
289 | * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle |
||
290 | * |
||
291 | * @param string $text |
||
292 | * @param \PhpSpreadsheet\Style\Font |
||
293 | * @param int $rotation |
||
294 | * @throws \PhpSpreadsheet\Exception |
||
295 | * @return int |
||
296 | */ |
||
297 | public static function getTextWidthPixelsExact($text, \PhpSpreadsheet\Style\Font $font, $rotation = 0) |
||
319 | |||
320 | /** |
||
321 | * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle |
||
322 | * |
||
323 | * @param string $columnText |
||
324 | * @param \PhpSpreadsheet\Style\Font $font |
||
325 | * @param int $rotation |
||
326 | * @return int Text width in pixels (no padding added) |
||
327 | */ |
||
328 | public static function getTextWidthPixelsApprox($columnText, \PhpSpreadsheet\Style\Font $font = null, $rotation = 0) |
||
375 | |||
376 | /** |
||
377 | * Calculate an (approximate) pixel size, based on a font points size |
||
378 | * |
||
379 | * @param int $fontSizeInPoints Font size (in points) |
||
380 | * @return int Font size (in pixels) |
||
381 | */ |
||
382 | 16 | public static function fontSizeToPixels($fontSizeInPoints = 11) |
|
386 | |||
387 | /** |
||
388 | * Calculate an (approximate) pixel size, based on inch size |
||
389 | * |
||
390 | * @param int $sizeInInch Font size (in inch) |
||
391 | * @return int Size (in pixels) |
||
392 | */ |
||
393 | 5 | public static function inchSizeToPixels($sizeInInch = 1) |
|
397 | |||
398 | /** |
||
399 | * Calculate an (approximate) pixel size, based on centimeter size |
||
400 | * |
||
401 | * @param int $sizeInCm Font size (in centimeters) |
||
402 | * @return float Size (in pixels) |
||
403 | */ |
||
404 | 5 | public static function centimeterSizeToPixels($sizeInCm = 1) |
|
408 | |||
409 | /** |
||
410 | * Returns the font path given the font |
||
411 | * |
||
412 | * @param \PhpSpreadsheet\Style\Font $font |
||
413 | * @return string Path to TrueType font file |
||
414 | */ |
||
415 | public static function getTrueTypeFontFileFromFont($font) |
||
520 | |||
521 | /** |
||
522 | * Returns the associated charset for the font name. |
||
523 | * |
||
524 | * @param string $name Font name |
||
525 | * @return int Character set code |
||
526 | */ |
||
527 | public static function getCharsetFromFontName($name) |
||
543 | |||
544 | /** |
||
545 | * Get the effective column width for columns without a column dimension or column with width -1 |
||
546 | * For example, for Calibri 11 this is 9.140625 (64 px) |
||
547 | * |
||
548 | * @param \PhpSpreadsheet\Style\Font $font The workbooks default font |
||
549 | * @param bool $pPixels true = return column width in pixels, false = return in OOXML units |
||
550 | * @return mixed Column width |
||
551 | */ |
||
552 | public static function getDefaultColumnWidthByFont(\PhpSpreadsheet\Style\Font $font, $pPixels = false) |
||
575 | |||
576 | /** |
||
577 | * Get the effective row height for rows without a row dimension or rows with height -1 |
||
578 | * For example, for Calibri 11 this is 15 points |
||
579 | * |
||
580 | * @param \PhpSpreadsheet\Style\Font $font The workbooks default font |
||
581 | * @return float Row height in points |
||
582 | */ |
||
583 | public static function getDefaultRowHeightByFont(\PhpSpreadsheet\Style\Font $font) |
||
726 | } |
||
727 |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: