Total Complexity | 68 |
Total Lines | 432 |
Duplicated Lines | 0 % |
Changes | 4 | ||
Bugs | 0 | Features | 0 |
Complex classes like AdminPageFramework_Debug_Base 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.
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 AdminPageFramework_Debug_Base, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class AdminPageFramework_Debug_Base extends AdminPageFramework_FrameworkUtility { |
||
20 | |||
21 | /** |
||
22 | * @var int |
||
23 | * @since 3.8.19 |
||
24 | */ |
||
25 | static public $iLegibleArrayDepthLimit = 50; |
||
26 | |||
27 | /** |
||
28 | * Character length limit to truncate. |
||
29 | */ |
||
30 | static public $iLegibleStringCharacterLimit = 99999; |
||
31 | |||
32 | /** |
||
33 | * Returns a legible value representation with value details. |
||
34 | * @param mixed $mValue |
||
35 | * @param integer $iStringLengthLimit |
||
36 | * @param integer $iArrayDepthLimit |
||
37 | * @return string |
||
38 | * @since 3.8.9 |
||
39 | */ |
||
40 | static protected function _getLegibleDetails( $mValue, $iStringLengthLimit=0, $iArrayDepthLimit=0 ) { |
||
41 | if ( is_array( $mValue ) ) { |
||
42 | return '(array, length: ' . count( $mValue ).') ' |
||
43 | . self::getAsString( print_r( self::___getLegibleDetailedArray( $mValue, $iStringLengthLimit, $iArrayDepthLimit ) , true ) ); |
||
44 | } |
||
45 | return self::getAsString( print_r( self::getLegibleDetailedValue( $mValue, $iStringLengthLimit ), true ) ); |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * Returns a object name if it is an object. Otherwise, the value itself. |
||
50 | * This is used to convert objects into a string in array-walk functions |
||
51 | * as objects tent to get large when they are converted to a string representation. |
||
52 | * @since 3.8.9 |
||
53 | * @since 3.8.32 Changed the visibility scope to public from private to be passed as a callback for outside the current class scope. |
||
54 | * And renamed from `___getObjectName()`. |
||
55 | * @param mixed $mItem |
||
56 | * @return mixed |
||
57 | */ |
||
58 | static public function getObjectName( $mItem ) { |
||
59 | if ( is_object( $mItem ) ) { |
||
60 | return '(object) ' . get_class( $mItem ); |
||
61 | } |
||
62 | return $mItem; |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Returns a string representation of the given value with no variable details. |
||
67 | * |
||
68 | * @param $mValue |
||
69 | * @param integer $iStringLengthLimit |
||
70 | * @param integer $iArrayDepthLimit |
||
71 | * @return string |
||
72 | * @since 3.8.9 |
||
73 | * @since 3.8.22 Added the `$sStringLengthLimit` and `$iArrayDepthLimit` parameters. |
||
74 | */ |
||
75 | static protected function _getLegible( $mValue, $iStringLengthLimit=0, $iArrayDepthLimit=0 ) { |
||
76 | |||
77 | $iArrayDepthLimit = $iArrayDepthLimit ? $iArrayDepthLimit : self::$iLegibleArrayDepthLimit; |
||
78 | $mValue = is_object( $mValue ) |
||
79 | ? ( method_exists( $mValue, '__toString' ) |
||
80 | ? ( string ) $mValue // cast string |
||
81 | : ( array ) $mValue // cast array |
||
82 | ) |
||
83 | : $mValue; |
||
84 | $mValue = is_array( $mValue ) |
||
85 | ? self::getArrayMappedRecursive( |
||
86 | array( __CLASS__, 'getObjectName' ), |
||
87 | self::_getSlicedByDepth( $mValue, $iArrayDepthLimit ), |
||
88 | array() |
||
89 | ) |
||
90 | : $mValue; |
||
91 | $mValue = is_string( $mValue ) |
||
92 | ? self::___getLegibleString( $mValue, $iStringLengthLimit, false ) |
||
93 | : $mValue; |
||
94 | return self::_getArrayRepresentationSanitized( self::getAsString( print_r( $mValue, true ) ) ); |
||
95 | |||
96 | } |
||
97 | |||
98 | /** |
||
99 | * @since 3.8.9 |
||
100 | * @param callable $asoCallable |
||
101 | * @return string |
||
102 | */ |
||
103 | static private function ___getLegibleDetailedCallable( $asoCallable ) { |
||
104 | return '(callable) ' . self::___getCallableName( $asoCallable ); |
||
105 | } |
||
106 | /** |
||
107 | * @since 3.8.9 |
||
108 | * @param callable $asoCallable |
||
109 | * @return string |
||
110 | */ |
||
111 | static public function ___getCallableName( $asoCallable ) { |
||
123 | |||
124 | } |
||
125 | |||
126 | /** |
||
127 | * @since 3.8.9 |
||
128 | * @param object $oObject |
||
129 | * @return string |
||
130 | */ |
||
131 | static private function ___getLegibleDetailedObject( $oObject ) { |
||
132 | |||
133 | if ( method_exists( $oObject, '__toString' ) ) { |
||
134 | return ( string ) $oObject; |
||
135 | } |
||
136 | return '(object) ' . get_class( $oObject ) . ' ' . count( get_object_vars( $oObject ) ) . ' properties.'; |
||
137 | |||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Returns an array representation with value types in each element. |
||
142 | * The element deeper than 10 dimensions will be dropped. |
||
143 | * @param array $aArray |
||
144 | * @param integer $iStringLengthLimit |
||
145 | * @param integer $iDepthLimit |
||
146 | * @return array |
||
147 | * @since 3.8.9 |
||
148 | * @since 3.8.22 Added the `$iDepthLimit` parameter |
||
149 | * @since 3.8.22 Changed the scope to private from public. |
||
150 | * @since 3.8.22 Renamed from `_getLegibleArray()`. |
||
151 | */ |
||
152 | static private function ___getLegibleDetailedArray( array $aArray, $iStringLengthLimit=0, $iDepthLimit=0 ) { |
||
153 | $_iDepthLimit = $iDepthLimit ? $iDepthLimit : self::$iLegibleArrayDepthLimit; |
||
154 | return self::getArrayMappedRecursive( |
||
155 | array( __CLASS__, 'getLegibleDetailedValue' ), |
||
156 | self::_getSlicedByDepth( $aArray, $_iDepthLimit ), |
||
157 | array( $iStringLengthLimit ) |
||
158 | ); |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * @param mixed $mItem |
||
163 | * @param integer $iStringLengthLimit |
||
164 | * @return string |
||
165 | * @since 3.8.22 Renamed from `_getLegibleValue()`. |
||
166 | * @since 3.8.9 |
||
167 | * @since 3.8.32 Changed the visibility scope to public from private to be passed as a callback for outside the current class scope. |
||
168 | * And renamed from `___getLegibleDetailedValue()`. |
||
169 | */ |
||
170 | static public function getLegibleDetailedValue( $mItem, $iStringLengthLimit ) { |
||
171 | if ( is_callable( $mItem ) ) { |
||
172 | return self::___getLegibleDetailedCallable( $mItem ); |
||
173 | } |
||
174 | return is_scalar( $mItem ) |
||
175 | ? self::___getLegibleDetailedScalar( $mItem, $iStringLengthLimit ) |
||
176 | : self::___getLegibleDetailedNonScalar( $mItem ); |
||
177 | } |
||
178 | /** |
||
179 | * @since 3.8.9 |
||
180 | * @since 3.8.22 Renamed from `_getLegibleNonScalar()`. |
||
181 | * @return string |
||
182 | * @param mixed $mNonScalar |
||
183 | */ |
||
184 | static private function ___getLegibleDetailedNonScalar( $mNonScalar ) { |
||
185 | |||
186 | $_sType = gettype( $mNonScalar ); |
||
187 | if ( is_null( $mNonScalar ) ) { |
||
188 | return '(null)'; |
||
189 | } |
||
190 | if ( is_object( $mNonScalar ) ) { |
||
191 | return self::___getLegibleDetailedObject( $mNonScalar ); |
||
192 | } |
||
193 | if ( is_array( $mNonScalar ) ) { |
||
194 | return '(' . $_sType . ') ' . count( $mNonScalar ) . ' elements'; |
||
195 | } |
||
196 | return '(' . $_sType . ') ' . ( string ) $mNonScalar; |
||
197 | |||
198 | } |
||
199 | /** |
||
200 | * @since 3.8.9 |
||
201 | * @since 3.8.22 Renamed from `_getLegibleScalar()`. |
||
202 | * @param integer|float|boolean|string $sScalar |
||
203 | * @param integer $iStringLengthLimit |
||
204 | * @return string |
||
205 | */ |
||
206 | static private function ___getLegibleDetailedScalar( $sScalar, $iStringLengthLimit ) { |
||
207 | if ( is_bool( $sScalar ) ) { |
||
208 | return '(boolean) ' . ( $sScalar ? 'true' : 'false' ); |
||
209 | } |
||
210 | return is_string( $sScalar ) |
||
211 | ? self::___getLegibleString( $sScalar, $iStringLengthLimit, true ) |
||
212 | : '(' . gettype( $sScalar ) . ', length: ' . self::___getValueLength( $sScalar ) . ') ' . $sScalar; |
||
213 | } |
||
214 | /** |
||
215 | * Returns a length of a value. |
||
216 | * @internal |
||
217 | * @since 3.5.3 |
||
218 | * @return integer|null For string or integer, the string length. For array, the element lengths. For other types, null. |
||
219 | * @param mixed $mValue |
||
220 | */ |
||
221 | static private function ___getValueLength( $mValue ) { |
||
230 | } |
||
231 | /** |
||
232 | * @param string $sString |
||
233 | * @param integer $iLengthLimit |
||
234 | * @param boolean $bShowDetails |
||
235 | * @return string |
||
236 | */ |
||
237 | static private function ___getLegibleString( $sString, $iLengthLimit, $bShowDetails=true ) { |
||
255 | |||
256 | } |
||
257 | |||
258 | /** |
||
259 | * @param string $sString |
||
260 | * @since 3.8.9 |
||
261 | * @return string |
||
262 | */ |
||
263 | static protected function _getArrayRepresentationSanitized( $sString ) { |
||
277 | ); |
||
278 | |||
279 | } |
||
280 | |||
281 | /** |
||
282 | * Slices an array by the given depth. |
||
283 | * @param array $aSubject |
||
284 | * @param int $iDepth |
||
285 | * @param string $sMore |
||
286 | * @return array |
||
287 | * @since 3.8.22 |
||
288 | */ |
||
289 | static public function getSlicedByDepth( array $aSubject, $iDepth=0, $sMore='(array truncated) ...' ) { |
||
290 | return self::_getSlicedByDepth( $aSubject, $iDepth, $sMore ); |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * Slices an array by the given depth. |
||
295 | * |
||
296 | * @param array $aSubject |
||
297 | * @param int $iDepth |
||
298 | * @param string $sMore |
||
299 | * |
||
300 | * @return array |
||
301 | * @since 3.4.4 |
||
302 | * @since 3.8.9 Changed it not to convert an object into an array. |
||
303 | * @since 3.8.9 Changed the scope to private. |
||
304 | * @since 3.8.9 Renamed from `getSliceByDepth()`. |
||
305 | * @since 3.8.22 Show a message when truncated by depth. |
||
306 | * @since 3.8.22 Added the `$sMore` parameter. |
||
307 | * @internal |
||
308 | */ |
||
309 | static private function _getSlicedByDepth( array $aSubject, $iDepth=0, $sMore='(array truncated) ...' ) { |
||
310 | |||
311 | foreach ( $aSubject as $_sKey => $_vValue ) { |
||
312 | |||
313 | if ( is_array( $_vValue ) ) { |
||
314 | |||
315 | $_iDepth = $iDepth; |
||
316 | if ( $iDepth > 0 ) { |
||
317 | $aSubject[ $_sKey ] = self::_getSlicedByDepth( $_vValue, --$iDepth ); |
||
318 | $iDepth = $_iDepth; |
||
319 | continue; |
||
320 | } |
||
321 | |||
322 | if ( strlen( $sMore ) ) { |
||
323 | $aSubject[ $_sKey ] = $sMore; |
||
324 | continue; |
||
325 | } |
||
326 | unset( $aSubject[ $_sKey ] ); |
||
327 | |||
328 | } |
||
329 | |||
330 | } |
||
331 | return $aSubject; |
||
332 | |||
333 | } |
||
334 | |||
335 | /** |
||
336 | * @param integer $iSkip The number of skipping records. This is used when the caller does not want to include the self function/method. |
||
337 | * @param null|mixed $_deprecated |
||
338 | * @return string |
||
339 | * @since 3.8.22 |
||
340 | * @since 3.8.23 Deprecated the `$oException` parameter. |
||
341 | */ |
||
342 | static public function getStackTrace( $iSkip=0, $_deprecated=null ) { |
||
343 | |||
344 | $_iSkip = 1; // need to skip this method trace itself |
||
345 | $_oException = new Exception(); |
||
346 | |||
347 | // Backward compatibility. |
||
348 | if ( is_object( $iSkip ) && $iSkip instanceof Exception ) { |
||
|
|||
349 | $_oException = $iSkip; |
||
350 | $iSkip = ( integer ) $_deprecated; |
||
351 | } |
||
352 | |||
353 | $_iSkip = $_iSkip + $iSkip; |
||
354 | |||
355 | $_aTraces = array(); |
||
356 | $_aFrames = $_oException->getTrace(); |
||
357 | $_aFrames = array_slice( $_aFrames, $_iSkip ); |
||
358 | foreach ( array_reverse( $_aFrames ) as $_iIndex => $_aFrame ) { |
||
359 | |||
360 | $_aFrame = $_aFrame + array( |
||
361 | 'file' => null, 'line' => null, 'function' => null, |
||
362 | 'class' => null, 'args' => array(), |
||
363 | ); |
||
364 | $_sArguments = self::___getArgumentsOfEachStackTrace( $_aFrame[ 'args' ] ); |
||
365 | $_aTraces[] = sprintf( |
||
366 | "#%s %s(%s): %s(%s)", |
||
367 | $_iIndex + 1, |
||
368 | $_aFrame[ 'file' ], |
||
369 | $_aFrame[ 'line' ], |
||
370 | isset( $_aFrame[ 'class' ] ) ? $_aFrame[ 'class' ] . '->' . $_aFrame[ 'function' ] : $_aFrame[ 'function' ], |
||
371 | $_sArguments |
||
372 | ); |
||
373 | |||
374 | } |
||
375 | return implode( PHP_EOL, $_aTraces ) . PHP_EOL; |
||
376 | |||
377 | } |
||
378 | /** |
||
379 | * @param array $aTraceArguments |
||
380 | * @return string |
||
381 | * @since 3.8.22 |
||
382 | * @internal |
||
383 | */ |
||
384 | static private function ___getArgumentsOfEachStackTrace( array $aTraceArguments ) { |
||
385 | |||
386 | $_aArguments = array(); |
||
387 | foreach ( $aTraceArguments as $_mArgument ) { |
||
388 | $_sType = gettype( $_mArgument ); |
||
389 | $_sType = str_replace( |
||
390 | array( 'resource (closed)', 'unknown type', 'integer', 'double', ), |
||
391 | array( 'resource', 'unknown', 'scalar', 'scalar', ), |
||
392 | $_sType |
||
393 | ); |
||
394 | $_sMethodName = "___getStackTraceArgument_{$_sType}"; |
||
395 | $_aArguments[] = method_exists( __CLASS__, $_sMethodName ) |
||
396 | ? self::{$_sMethodName}( $_mArgument ) |
||
397 | : $_sType; |
||
398 | } |
||
399 | return join(", ", $_aArguments ); |
||
400 | } |
||
401 | /** |
||
402 | * @since 3.8.22 |
||
403 | * @param mixed $mArgument |
||
404 | * @internal |
||
405 | * @return string |
||
406 | */ |
||
407 | static private function ___getStackTraceArgument_string( $mArgument ) { |
||
408 | $_sString = self::___getLegibleString( $mArgument, 200, true ); |
||
409 | return "'" . $_sString . "'"; |
||
410 | } |
||
411 | static private function ___getStackTraceArgument_scalar( $mArgument ) { |
||
412 | return $mArgument; |
||
413 | } |
||
414 | static private function ___getStackTraceArgument_boolean( $mArgument ) { |
||
415 | return ( $mArgument ) ? "true" : "false"; |
||
416 | } |
||
417 | static private function ___getStackTraceArgument_NULL( $mArgument ) { |
||
418 | return 'NULL'; |
||
419 | } |
||
420 | static private function ___getStackTraceArgument_object( $mArgument ) { |
||
421 | return 'Object(' . get_class( $mArgument ) . ')'; |
||
422 | } |
||
423 | static private function ___getStackTraceArgument_resource( $mArgument ) { |
||
424 | return get_resource_type( $mArgument ); |
||
425 | } |
||
426 | static private function ___getStackTraceArgument_unknown( $mArgument ) { |
||
428 | } |
||
429 | static private function ___getStackTraceArgument_array( $mArgument ) { |
||
430 | $_sOutput = ''; |
||
431 | $_iMax = 10; |
||
432 | $_iTotal = count( $mArgument ); |
||
433 | $_iIndex = 0; |
||
434 | foreach( $mArgument as $_sKey => $_mValue ) { |
||
435 | $_iIndex++; |
||
451 | } |
||
452 | |||
453 | } |