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 FirePHP 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 FirePHP, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
58 | class FirePHP { |
||
59 | |||
60 | /** |
||
61 | * FirePHP version |
||
62 | * |
||
63 | * @var string |
||
64 | */ |
||
65 | const VERSION = '0.3'; |
||
66 | |||
67 | /** |
||
68 | * Firebug LOG level |
||
69 | * |
||
70 | * Logs a message to firebug console. |
||
71 | * |
||
72 | * @var string |
||
73 | */ |
||
74 | const LOG = 'LOG'; |
||
75 | |||
76 | /** |
||
77 | * Firebug INFO level |
||
78 | * |
||
79 | * Logs a message to firebug console and displays an info icon before the message. |
||
80 | * |
||
81 | * @var string |
||
82 | */ |
||
83 | const INFO = 'INFO'; |
||
84 | |||
85 | /** |
||
86 | * Firebug WARN level |
||
87 | * |
||
88 | * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. |
||
89 | * |
||
90 | * @var string |
||
91 | */ |
||
92 | const WARN = 'WARN'; |
||
93 | |||
94 | /** |
||
95 | * Firebug ERROR level |
||
96 | * |
||
97 | * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. |
||
98 | * |
||
99 | * @var string |
||
100 | */ |
||
101 | const ERROR = 'ERROR'; |
||
102 | |||
103 | /** |
||
104 | * Dumps a variable to firebug's server panel |
||
105 | * |
||
106 | * @var string |
||
107 | */ |
||
108 | const DUMP = 'DUMP'; |
||
109 | |||
110 | /** |
||
111 | * Displays a stack trace in firebug console |
||
112 | * |
||
113 | * @var string |
||
114 | */ |
||
115 | const TRACE = 'TRACE'; |
||
116 | |||
117 | /** |
||
118 | * Displays an exception in firebug console |
||
119 | * |
||
120 | * Increments the firebug error count. |
||
121 | * |
||
122 | * @var string |
||
123 | */ |
||
124 | const EXCEPTION = 'EXCEPTION'; |
||
125 | |||
126 | /** |
||
127 | * Displays an table in firebug console |
||
128 | * |
||
129 | * @var string |
||
130 | */ |
||
131 | const TABLE = 'TABLE'; |
||
132 | |||
133 | /** |
||
134 | * Starts a group in firebug console |
||
135 | * |
||
136 | * @var string |
||
137 | */ |
||
138 | const GROUP_START = 'GROUP_START'; |
||
139 | |||
140 | /** |
||
141 | * Ends a group in firebug console |
||
142 | * |
||
143 | * @var string |
||
144 | */ |
||
145 | const GROUP_END = 'GROUP_END'; |
||
146 | |||
147 | /** |
||
148 | * Singleton instance of FirePHP |
||
149 | * |
||
150 | * @var FirePHP |
||
151 | */ |
||
152 | protected static $instance = null; |
||
153 | |||
154 | /** |
||
155 | * Flag whether we are logging from within the exception handler |
||
156 | * |
||
157 | * @var boolean |
||
158 | */ |
||
159 | protected $inExceptionHandler = false; |
||
160 | |||
161 | /** |
||
162 | * Flag whether to throw PHP errors that have been converted to ErrorExceptions |
||
163 | * |
||
164 | * @var boolean |
||
165 | */ |
||
166 | protected $throwErrorExceptions = true; |
||
167 | |||
168 | /** |
||
169 | * Flag whether to convert PHP assertion errors to Exceptions |
||
170 | * |
||
171 | * @var boolean |
||
172 | */ |
||
173 | protected $convertAssertionErrorsToExceptions = true; |
||
174 | |||
175 | /** |
||
176 | * Flag whether to throw PHP assertion errors that have been converted to Exceptions |
||
177 | * |
||
178 | * @var boolean |
||
179 | */ |
||
180 | protected $throwAssertionExceptions = false; |
||
181 | |||
182 | /** |
||
183 | * Wildfire protocol message index |
||
184 | * |
||
185 | * @var int |
||
186 | */ |
||
187 | protected $messageIndex = 1; |
||
188 | |||
189 | /** |
||
190 | * Options for the library |
||
191 | * |
||
192 | * @var array |
||
193 | */ |
||
194 | protected $options = array('maxObjectDepth' => 10, |
||
195 | 'maxArrayDepth' => 20, |
||
196 | 'useNativeJsonEncode' => true, |
||
197 | 'includeLineNumbers' => true); |
||
198 | |||
199 | /** |
||
200 | * Filters used to exclude object members when encoding |
||
201 | * |
||
202 | * @var array |
||
203 | */ |
||
204 | protected $objectFilters = array(); |
||
205 | |||
206 | /** |
||
207 | * A stack of objects used to detect recursion during object encoding |
||
208 | * |
||
209 | * @var object |
||
210 | */ |
||
211 | protected $objectStack = array(); |
||
212 | |||
213 | /** |
||
214 | * Flag to enable/disable logging |
||
215 | * |
||
216 | * @var boolean |
||
217 | */ |
||
218 | protected $enabled = true; |
||
219 | |||
220 | /** |
||
221 | * The object constructor |
||
222 | */ |
||
223 | function __construct() { |
||
225 | |||
226 | /** |
||
227 | * When the object gets serialized only include specific object members. |
||
228 | * |
||
229 | * @return array |
||
230 | */ |
||
231 | public function __sleep() { |
||
234 | |||
235 | /** |
||
236 | * Gets singleton instance of FirePHP |
||
237 | * |
||
238 | * @param boolean $AutoCreate |
||
239 | * @return FirePHP |
||
240 | */ |
||
241 | public static function getInstance($AutoCreate=false) { |
||
247 | |||
248 | /** |
||
249 | * Creates FirePHP object and stores it for singleton access |
||
250 | * |
||
251 | * @return FirePHP |
||
252 | */ |
||
253 | public static function init() { |
||
256 | |||
257 | /** |
||
258 | * Enable and disable logging to Firebug |
||
259 | * |
||
260 | * @param boolean $Enabled TRUE to enable, FALSE to disable |
||
261 | * @return void |
||
262 | */ |
||
263 | public function setEnabled($Enabled) { |
||
266 | |||
267 | /** |
||
268 | * Check if logging is enabled |
||
269 | * |
||
270 | * @return boolean TRUE if enabled |
||
271 | */ |
||
272 | public function getEnabled() { |
||
275 | |||
276 | /** |
||
277 | * Specify a filter to be used when encoding an object |
||
278 | * |
||
279 | * Filters are used to exclude object members. |
||
280 | * |
||
281 | * @param string $Class The class name of the object |
||
282 | * @param array $Filter An array of members to exclude |
||
283 | * @return void |
||
284 | */ |
||
285 | public function setObjectFilter($Class, $Filter) { |
||
288 | |||
289 | /** |
||
290 | * Set some options for the library |
||
291 | * |
||
292 | * Options: |
||
293 | * - maxObjectDepth: The maximum depth to traverse objects (default: 10) |
||
294 | * - maxArrayDepth: The maximum depth to traverse arrays (default: 20) |
||
295 | * - useNativeJsonEncode: If true will use json_encode() (default: true) |
||
296 | * - includeLineNumbers: If true will include line numbers and filenames (default: true) |
||
297 | * |
||
298 | * @param array $Options The options to be set |
||
299 | * @return void |
||
300 | */ |
||
301 | public function setOptions($Options) { |
||
304 | |||
305 | /** |
||
306 | * Get options from the library |
||
307 | * |
||
308 | * @return array The currently set options |
||
309 | */ |
||
310 | public function getOptions() { |
||
313 | |||
314 | /** |
||
315 | * Register FirePHP as your error handler |
||
316 | * |
||
317 | * Will throw exceptions for each php error. |
||
318 | * |
||
319 | * @return mixed Returns a string containing the previously defined error handler (if any) |
||
320 | */ |
||
321 | public function registerErrorHandler($throwErrorExceptions=true) |
||
332 | |||
333 | /** |
||
334 | * FirePHP's error handler |
||
335 | * |
||
336 | * Throws exception for each php error that will occur. |
||
337 | * |
||
338 | * @param int $errno |
||
339 | * @param string $errstr |
||
340 | * @param string $errfile |
||
341 | * @param int $errline |
||
342 | * @param array $errcontext |
||
343 | */ |
||
344 | public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) |
||
361 | |||
362 | /** |
||
363 | * Register FirePHP as your exception handler |
||
364 | * |
||
365 | * @return mixed Returns the name of the previously defined exception handler, |
||
366 | * or NULL on error. |
||
367 | * If no previous handler was defined, NULL is also returned. |
||
368 | */ |
||
369 | public function registerExceptionHandler() |
||
373 | |||
374 | /** |
||
375 | * FirePHP's exception handler |
||
376 | * |
||
377 | * Logs all exceptions to your firebug console and then stops the script. |
||
378 | * |
||
379 | * @param Exception $Exception |
||
380 | * @throws Exception |
||
381 | */ |
||
382 | function exceptionHandler($Exception) { |
||
392 | |||
393 | /** |
||
394 | * Register FirePHP driver as your assert callback |
||
395 | * |
||
396 | * @param boolean $convertAssertionErrorsToExceptions |
||
397 | * @param boolean $throwAssertionExceptions |
||
398 | * @return mixed Returns the original setting or FALSE on errors |
||
399 | */ |
||
400 | public function registerAssertionHandler($convertAssertionErrorsToExceptions=true, $throwAssertionExceptions=false) |
||
411 | |||
412 | /** |
||
413 | * FirePHP's assertion handler |
||
414 | * |
||
415 | * Logs all assertions to your firebug console and then stops the script. |
||
416 | * |
||
417 | * @param string $file File source of assertion |
||
418 | * @param int $line Line source of assertion |
||
419 | * @param mixed $code Assertion code |
||
420 | */ |
||
421 | public function assertionHandler($file, $line, $code) |
||
440 | |||
441 | /** |
||
442 | * Set custom processor url for FirePHP |
||
443 | * |
||
444 | * @param string $URL |
||
445 | */ |
||
446 | public function setProcessorUrl($URL) |
||
450 | |||
451 | /** |
||
452 | * Set custom renderer url for FirePHP |
||
453 | * |
||
454 | * @param string $URL |
||
455 | */ |
||
456 | public function setRendererUrl($URL) |
||
460 | |||
461 | /** |
||
462 | * Start a group for following messages. |
||
463 | * |
||
464 | * Options: |
||
465 | * Collapsed: [true|false] |
||
466 | * Color: [#RRGGBB|ColorName] |
||
467 | * |
||
468 | * @param string $Name |
||
469 | * @param array $Options OPTIONAL Instructions on how to log the group |
||
470 | * @return true |
||
471 | * @throws Exception |
||
472 | */ |
||
473 | public function group($Name, $Options=null) { |
||
490 | |||
491 | /** |
||
492 | * Ends a group you have started before |
||
493 | * |
||
494 | * @return true |
||
495 | * @throws Exception |
||
496 | */ |
||
497 | public function groupEnd() { |
||
500 | |||
501 | /** |
||
502 | * Log object with label to firebug console |
||
503 | * |
||
504 | * @see FirePHP::LOG |
||
505 | * @param mixes $Object |
||
506 | * @param string $Label |
||
507 | * @return true |
||
508 | * @throws Exception |
||
509 | */ |
||
510 | public function log($Object, $Label=null) { |
||
513 | |||
514 | /** |
||
515 | * Log object with label to firebug console |
||
516 | * |
||
517 | * @see FirePHP::INFO |
||
518 | * @param mixes $Object |
||
519 | * @param string $Label |
||
520 | * @return true |
||
521 | * @throws Exception |
||
522 | */ |
||
523 | public function info($Object, $Label=null) { |
||
526 | |||
527 | /** |
||
528 | * Log object with label to firebug console |
||
529 | * |
||
530 | * @see FirePHP::WARN |
||
531 | * @param mixes $Object |
||
532 | * @param string $Label |
||
533 | * @return true |
||
534 | * @throws Exception |
||
535 | */ |
||
536 | public function warn($Object, $Label=null) { |
||
539 | |||
540 | /** |
||
541 | * Log object with label to firebug console |
||
542 | * |
||
543 | * @see FirePHP::ERROR |
||
544 | * @param mixes $Object |
||
545 | * @param string $Label |
||
546 | * @return true |
||
547 | * @throws Exception |
||
548 | */ |
||
549 | public function error($Object, $Label=null) { |
||
552 | |||
553 | /** |
||
554 | * Dumps key and variable to firebug server panel |
||
555 | * |
||
556 | * @see FirePHP::DUMP |
||
557 | * @param string $Key |
||
558 | * @param mixed $Variable |
||
559 | * @return true |
||
560 | * @throws Exception |
||
561 | */ |
||
562 | public function dump($Key, $Variable) { |
||
565 | |||
566 | /** |
||
567 | * Log a trace in the firebug console |
||
568 | * |
||
569 | * @see FirePHP::TRACE |
||
570 | * @param string $Label |
||
571 | * @return true |
||
572 | * @throws Exception |
||
573 | */ |
||
574 | public function trace($Label) { |
||
577 | |||
578 | /** |
||
579 | * Log a table in the firebug console |
||
580 | * |
||
581 | * @see FirePHP::TABLE |
||
582 | * @param string $Label |
||
583 | * @param string $Table |
||
584 | * @return true |
||
585 | * @throws Exception |
||
586 | */ |
||
587 | public function table($Label, $Table) { |
||
590 | |||
591 | /** |
||
592 | * Check if FirePHP is installed on client |
||
593 | * |
||
594 | * @return boolean |
||
595 | */ |
||
596 | public function detectClientExtension() { |
||
604 | |||
605 | /** |
||
606 | * Log varible to Firebug |
||
607 | * |
||
608 | * @see http://www.firephp.org/Wiki/Reference/Fb |
||
609 | * @param mixed $Object The variable to be logged |
||
610 | * @return true Return TRUE if message was added to headers, FALSE otherwise |
||
611 | * @throws Exception |
||
612 | */ |
||
613 | public function fb($Object) { |
||
875 | |||
876 | /** |
||
877 | * Standardizes path for windows systems. |
||
878 | * |
||
879 | * @param string $Path |
||
880 | * @return string |
||
881 | */ |
||
882 | protected function _standardizePath($Path) { |
||
885 | |||
886 | /** |
||
887 | * Escape trace path for windows systems |
||
888 | * |
||
889 | * @param array $Trace |
||
890 | * @return array |
||
891 | */ |
||
892 | protected function _escapeTrace($Trace) { |
||
904 | |||
905 | /** |
||
906 | * Escape file information of trace for windows systems |
||
907 | * |
||
908 | * @param string $File |
||
909 | * @return string |
||
910 | */ |
||
911 | protected function _escapeTraceFile($File) { |
||
922 | |||
923 | /** |
||
924 | * Send header |
||
925 | * |
||
926 | * @param string $Name |
||
927 | * @param string_type $Value |
||
928 | */ |
||
929 | protected function setHeader($Name, $Value) { |
||
932 | |||
933 | /** |
||
934 | * Get user agent |
||
935 | * |
||
936 | * @return string|false |
||
937 | */ |
||
938 | protected function getUserAgent() { |
||
942 | |||
943 | /** |
||
944 | * Returns a new exception |
||
945 | * |
||
946 | * @param string $Message |
||
947 | * @return Exception |
||
948 | */ |
||
949 | protected function newException($Message) { |
||
952 | |||
953 | /** |
||
954 | * Encode an object into a JSON string |
||
955 | * |
||
956 | * Uses PHP's jeson_encode() if available |
||
957 | * |
||
958 | * @param object $Object The object to be encoded |
||
959 | * @return string The JSON string |
||
960 | */ |
||
961 | public function jsonEncode($Object, $skipObjectEncode=false) |
||
975 | |||
976 | /** |
||
977 | * Encodes a table by encoding each row and column with encodeObject() |
||
978 | * |
||
979 | * @param array $Table The table to be encoded |
||
980 | * @return array |
||
981 | */ |
||
982 | protected function encodeTable($Table) { |
||
1002 | |||
1003 | /** |
||
1004 | * Encodes an object including members with |
||
1005 | * protected and private visibility |
||
1006 | * |
||
1007 | * @param BaseObject $Object The object to be encoded |
||
1008 | * @param int $Depth The current traversal depth |
||
1009 | * @return array All members of the object |
||
1010 | */ |
||
1011 | protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1) |
||
1143 | |||
1144 | /** |
||
1145 | * Returns true if $string is valid UTF-8 and false otherwise. |
||
1146 | * |
||
1147 | * @param mixed $str String to be tested |
||
1148 | * @return boolean |
||
1149 | */ |
||
1150 | protected static function is_utf8($str) { |
||
1175 | |||
1176 | /** |
||
1177 | * Converts to and from JSON format. |
||
1178 | * |
||
1179 | * JSON (JavaScript Object Notation) is a lightweight data-interchange |
||
1180 | * format. It is easy for humans to read and write. It is easy for machines |
||
1181 | * to parse and generate. It is based on a subset of the JavaScript |
||
1182 | * Programming Language, Standard ECMA-262 3rd Edition - December 1999. |
||
1183 | * This feature can also be found in Python. JSON is a text format that is |
||
1184 | * completely language independent but uses conventions that are familiar |
||
1185 | * to programmers of the C-family of languages, including C, C++, C#, Java, |
||
1186 | * JavaScript, Perl, TCL, and many others. These properties make JSON an |
||
1187 | * ideal data-interchange language. |
||
1188 | * |
||
1189 | * This package provides a simple encoder and decoder for JSON notation. It |
||
1190 | * is intended for use with client-side Javascript applications that make |
||
1191 | * use of HTTPRequest to perform server communication functions - data can |
||
1192 | * be encoded into JSON notation for use in a client-side javascript, or |
||
1193 | * decoded from incoming Javascript requests. JSON format is native to |
||
1194 | * Javascript, and can be directly eval()'ed with no further parsing |
||
1195 | * overhead |
||
1196 | * |
||
1197 | * All strings should be in ASCII or UTF-8 format! |
||
1198 | * |
||
1199 | * LICENSE: Redistribution and use in source and binary forms, with or |
||
1200 | * without modification, are permitted provided that the following |
||
1201 | * conditions are met: Redistributions of source code must retain the |
||
1202 | * above copyright notice, this list of conditions and the following |
||
1203 | * disclaimer. Redistributions in binary form must reproduce the above |
||
1204 | * copyright notice, this list of conditions and the following disclaimer |
||
1205 | * in the documentation and/or other materials provided with the |
||
1206 | * distribution. |
||
1207 | * |
||
1208 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||
1209 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||
1210 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
||
1211 | * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
1212 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
||
1213 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
||
1214 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
1215 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
||
1216 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
||
1217 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
||
1218 | * DAMAGE. |
||
1219 | * |
||
1220 | * @category |
||
1221 | * @package Services_JSON |
||
1222 | * @author Michal Migurski <[email protected]> |
||
1223 | * @author Matt Knapp <mdknapp[at]gmail[dot]com> |
||
1224 | * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> |
||
1225 | * @author Christoph Dorn <[email protected]> |
||
1226 | * @copyright 2005 Michal Migurski |
||
1227 | * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ |
||
1228 | * @license http://www.opensource.org/licenses/bsd-license.php |
||
1229 | * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 |
||
1230 | */ |
||
1231 | |||
1232 | |||
1233 | /** |
||
1234 | * Keep a list of objects as we descend into the array so we can detect recursion. |
||
1235 | */ |
||
1236 | private $json_objectStack = array(); |
||
1237 | |||
1238 | |||
1239 | /** |
||
1240 | * convert a string from one UTF-8 char to one UTF-16 char |
||
1241 | * |
||
1242 | * Normally should be handled by mb_convert_encoding, but |
||
1243 | * provides a slower PHP-only method for installations |
||
1244 | * that lack the multibye string extension. |
||
1245 | * |
||
1246 | * @param string $utf8 UTF-8 character |
||
1247 | * @return string UTF-16 character |
||
1248 | * @access private |
||
1249 | */ |
||
1250 | private function json_utf82utf16($utf8) |
||
1282 | |||
1283 | /** |
||
1284 | * encodes an arbitrary variable into JSON format |
||
1285 | * |
||
1286 | * @param mixed $var any number, boolean, string, array, or object to be encoded. |
||
1287 | * see argument 1 to Services_JSON() above for array-parsing behavior. |
||
1288 | * if var is a strng, note that encode() always expects it |
||
1289 | * to be in ASCII or UTF-8 format! |
||
1290 | * |
||
1291 | * @return mixed JSON string representation of input var or an error if a problem occurs |
||
1292 | * @access public |
||
1293 | */ |
||
1294 | private function json_encode($var) |
||
1499 | |||
1500 | /** |
||
1501 | * array-walking function for use in generating JSON-formatted name-value pairs |
||
1502 | * |
||
1503 | * @param string $name name of key to use |
||
1504 | * @param mixed $value reference to an array element to be encoded |
||
1505 | * |
||
1506 | * @return string JSON-formatted name-value pair, like '"name":value' |
||
1507 | * @access private |
||
1508 | */ |
||
1509 | private function json_name_value($name, $value) |
||
1529 | } |
||
1530 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.