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 PHPTAL_Php_TalesInternal 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 PHPTAL_Php_TalesInternal, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
51 | class PHPTAL_Php_TalesInternal implements PHPTAL_Tales |
||
52 | { |
||
53 | const DEFAULT_KEYWORD = 'new PHPTAL_DefaultKeyword'; |
||
54 | const NOTHING_KEYWORD = 'new PHPTAL_NothingKeyword'; |
||
55 | |||
56 | static public function true($src, $nothrow) |
||
60 | |||
61 | /** |
||
62 | * not: |
||
63 | * |
||
64 | * not: Expression |
||
65 | * |
||
66 | * evaluate the expression string (recursively) as a full expression, |
||
67 | * and returns the boolean negation of its value |
||
68 | * |
||
69 | * return boolean based on the following rules: |
||
70 | * |
||
71 | * 1. integer 0 is false |
||
72 | * 2. integer > 0 is true |
||
73 | * 3. an empty string or other sequence is false |
||
74 | * 4. a non-empty string or other sequence is true |
||
75 | * 5. a non-value (e.g. void, None, Nil, NULL, etc) is false |
||
76 | * 6. all other values are implementation-dependent. |
||
77 | * |
||
78 | * Examples: |
||
79 | * |
||
80 | * not: exists: foo/bar/baz |
||
81 | * not: php: object.hasChildren() |
||
82 | * not: string:${foo} |
||
83 | * not: foo/bar/booleancomparable |
||
84 | */ |
||
85 | static public function not($expression, $nothrow) |
||
89 | |||
90 | |||
91 | /** |
||
92 | * path: |
||
93 | * |
||
94 | * PathExpr ::= Path [ '|' Path ]* |
||
95 | * Path ::= variable [ '/' URL_Segment ]* |
||
96 | * variable ::= Name |
||
97 | * |
||
98 | * Examples: |
||
99 | * |
||
100 | * path: username |
||
101 | * path: user/name |
||
102 | * path: object/method/10/method/member |
||
103 | * path: object/${dynamicmembername}/method |
||
104 | * path: maybethis | path: maybethat | path: default |
||
105 | * |
||
106 | * PHPTAL: |
||
107 | * |
||
108 | * 'default' may lead to some 'difficult' attributes implementation |
||
109 | * |
||
110 | * For example, the tal:content will have to insert php code like: |
||
111 | * |
||
112 | * if (isset($ctx->maybethis)) { |
||
113 | * echo $ctx->maybethis; |
||
114 | * } |
||
115 | * elseif (isset($ctx->maybethat) { |
||
116 | * echo $ctx->maybethat; |
||
117 | * } |
||
118 | * else { |
||
119 | * // process default tag content |
||
120 | * } |
||
121 | * |
||
122 | * @returns string or array |
||
123 | */ |
||
124 | static public function path($expression, $nothrow=false) |
||
199 | |||
200 | /** |
||
201 | * check if part of exprssion (/foo/ or /foo${bar}/) is alphanumeric |
||
202 | */ |
||
203 | private static function checkExpressionPart($expression) |
||
208 | |||
209 | /** |
||
210 | * string: |
||
211 | * |
||
212 | * string_expression ::= ( plain_string | [ varsub ] )* |
||
213 | * varsub ::= ( '$' Path ) | ( '${' Path '}' ) |
||
214 | * plain_string ::= ( '$$' | non_dollar )* |
||
215 | * non_dollar ::= any character except '$' |
||
216 | * |
||
217 | * Examples: |
||
218 | * |
||
219 | * string:my string |
||
220 | * string:hello, $username how are you |
||
221 | * string:hello, ${user/name} |
||
222 | * string:you have $$130 in your bank account |
||
223 | */ |
||
224 | static public function string($expression, $nothrow=false) |
||
228 | |||
229 | /** |
||
230 | * @param string $tales_prefix prefix added to all TALES in the string |
||
231 | */ |
||
232 | static public function parseString($expression, $nothrow, $tales_prefix) |
||
347 | |||
348 | /** |
||
349 | * php: modifier. |
||
350 | * |
||
351 | * Transform the expression into a regular PHP expression. |
||
352 | */ |
||
353 | static public function php($src) |
||
357 | |||
358 | /** |
||
359 | * phptal-internal-php-block: modifier for emulation of <?php ?> in attributes. |
||
360 | * |
||
361 | * Please don't use it in the templates! |
||
362 | */ |
||
363 | static public function phptal_internal_php_block($src) |
||
378 | |||
379 | /** |
||
380 | * exists: modifier. |
||
381 | * |
||
382 | * Returns the code required to invoke Context::exists() on specified path. |
||
383 | */ |
||
384 | static public function exists($src, $nothrow) |
||
390 | |||
391 | /** |
||
392 | * number: modifier. |
||
393 | * |
||
394 | * Returns the number as is. |
||
395 | */ |
||
396 | static public function number($src, $nothrow) |
||
401 | |||
402 | /** |
||
403 | * json: modifier. Serializes anything as JSON. |
||
404 | */ |
||
405 | static public function json($src, $nothrow) |
||
409 | |||
410 | /** |
||
411 | * urlencode: modifier. Escapes a string. |
||
412 | */ |
||
413 | static public function urlencode($src, $nothrow) |
||
417 | |||
418 | /** |
||
419 | * translates TALES expression with alternatives into single PHP expression. |
||
420 | * Identical to compileToPHPExpressions() for singular expressions. |
||
421 | * |
||
422 | * @see PHPTAL_Php_TalesInternal::compileToPHPExpressions() |
||
423 | * @return string |
||
424 | */ |
||
425 | public static function compileToPHPExpression($expression, $nothrow=false) |
||
433 | |||
434 | /* |
||
435 | * helper function for compileToPHPExpression |
||
436 | * @access private |
||
437 | */ |
||
438 | private static function convertExpressionsToExpression(array $array, $nothrow) |
||
448 | |||
449 | /** |
||
450 | * returns PHP code that will evaluate given TALES expression. |
||
451 | * e.g. "string:foo${bar}" may be transformed to "'foo'.phptal_escape($ctx->bar)" |
||
452 | * |
||
453 | * Expressions with alternatives ("foo | bar") will cause it to return array |
||
454 | * Use PHPTAL_Php_TalesInternal::compileToPHPExpression() if you always want string. |
||
455 | * |
||
456 | * @param bool $nothrow if true, invalid expression will return NULL (at run time) rather than throwing exception |
||
457 | * |
||
458 | * @return string or array |
||
459 | */ |
||
460 | public static function compileToPHPExpressions($expression, $nothrow=false) |
||
490 | |||
491 | private static function verifyPHPExpressions($typePrefix,$expressions) |
||
503 | } |
||
504 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.