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 OC_Template 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 OC_Template, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 46 | class OC_Template extends \OC\Template\Base { |
||
| 47 | |||
| 48 | /** @var string */ |
||
| 49 | private $renderAs; // Create a full page? |
||
| 50 | |||
| 51 | /** @var string */ |
||
| 52 | private $path; // The path to the template |
||
| 53 | |||
| 54 | /** @var array */ |
||
| 55 | private $headers = array(); //custom headers |
||
| 56 | |||
| 57 | /** @var string */ |
||
| 58 | protected $app; // app id |
||
| 59 | |||
| 60 | protected static $initTemplateEngineFirstRun = true; |
||
| 61 | |||
| 62 | /** |
||
| 63 | * Constructor |
||
| 64 | * |
||
| 65 | * @param string $app app providing the template |
||
| 66 | * @param string $name of the template file (without suffix) |
||
| 67 | * @param string $renderAs If $renderAs is set, OC_Template will try to |
||
| 68 | * produce a full page in the according layout. For |
||
| 69 | * now, $renderAs can be set to "guest", "user" or |
||
| 70 | * "admin". |
||
| 71 | * @param bool $registerCall = true |
||
| 72 | */ |
||
| 73 | public function __construct( $app, $name, $renderAs = "", $registerCall = true ) { |
||
| 95 | |||
| 96 | /** |
||
| 97 | * @param string $renderAs |
||
| 98 | */ |
||
| 99 | public static function initTemplateEngine($renderAs) { |
||
| 155 | |||
| 156 | |||
| 157 | /** |
||
| 158 | * find the template with the given name |
||
| 159 | * @param string $name of the template file (without suffix) |
||
| 160 | * |
||
| 161 | * Will select the template file for the selected theme. |
||
| 162 | * Checking all the possible locations. |
||
| 163 | * @param string $theme |
||
| 164 | * @param string $app |
||
| 165 | * @return string[] |
||
| 166 | */ |
||
| 167 | protected function findTemplate($theme, $app, $name) { |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Add a custom element to the header |
||
| 182 | * @param string $tag tag name of the element |
||
| 183 | * @param array $attributes array of attributes for the element |
||
| 184 | * @param string $text the text content for the element. If $text is null then the |
||
| 185 | * element will be written as empty element. So use "" to get a closing tag. |
||
| 186 | */ |
||
| 187 | View Code Duplication | public function addHeader($tag, $attributes, $text=null) { |
|
| 194 | |||
| 195 | /** |
||
| 196 | * Process the template |
||
| 197 | * @return boolean|string |
||
| 198 | * |
||
| 199 | * This function process the template. If $this->renderAs is set, it |
||
| 200 | * will produce a full page. |
||
| 201 | */ |
||
| 202 | public function fetchPage($additionalParams = null) { |
||
| 203 | $data = parent::fetchPage($additionalParams); |
||
| 204 | |||
| 205 | if( $this->renderAs ) { |
||
| 206 | $page = new TemplateLayout($this->renderAs, $this->app); |
||
| 207 | |||
| 208 | // Add custom headers |
||
| 209 | $headers = ''; |
||
| 210 | foreach(OC_Util::$headers as $header) { |
||
| 211 | $headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']); |
||
| 212 | if ( strcasecmp($header['tag'], 'script') === 0 && in_array('src', array_map('strtolower', array_keys($header['attributes']))) ) { |
||
| 213 | $headers .= ' defer'; |
||
| 214 | } |
||
| 215 | foreach($header['attributes'] as $name=>$value) { |
||
| 216 | $headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"'; |
||
| 217 | } |
||
| 218 | if ($header['text'] !== null) { |
||
| 219 | $headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>'; |
||
| 220 | } else { |
||
| 221 | $headers .= '/>'; |
||
| 222 | } |
||
| 223 | } |
||
| 224 | |||
| 225 | $page->assign('headers', $headers); |
||
| 226 | |||
| 227 | $page->assign('content', $data); |
||
| 228 | return $page->fetchPage(); |
||
| 229 | } |
||
| 230 | |||
| 231 | return $data; |
||
| 232 | } |
||
| 233 | |||
| 234 | /** |
||
| 235 | * Include template |
||
| 236 | * |
||
| 237 | * @param string $file |
||
| 238 | * @param array|null $additionalParams |
||
| 239 | * @return string returns content of included template |
||
| 240 | * |
||
| 241 | * Includes another template. use <?php echo $this->inc('template'); ?> to |
||
| 242 | * do this. |
||
| 243 | */ |
||
| 244 | public function inc( $file, $additionalParams = null ) { |
||
| 247 | |||
| 248 | /** |
||
| 249 | * Shortcut to print a simple page for users |
||
| 250 | * @param string $application The application we render the template for |
||
| 251 | * @param string $name Name of the template |
||
| 252 | * @param array $parameters Parameters for the template |
||
| 253 | * @return boolean|null |
||
| 254 | */ |
||
| 255 | View Code Duplication | public static function printUserPage( $application, $name, $parameters = array() ) { |
|
| 262 | |||
| 263 | /** |
||
| 264 | * Shortcut to print a simple page for admins |
||
| 265 | * @param string $application The application we render the template for |
||
| 266 | * @param string $name Name of the template |
||
| 267 | * @param array $parameters Parameters for the template |
||
| 268 | * @return bool |
||
| 269 | */ |
||
| 270 | View Code Duplication | public static function printAdminPage( $application, $name, $parameters = array() ) { |
|
| 277 | |||
| 278 | /** |
||
| 279 | * Shortcut to print a simple page for guests |
||
| 280 | * @param string $application The application we render the template for |
||
| 281 | * @param string $name Name of the template |
||
| 282 | * @param array|string $parameters Parameters for the template |
||
| 283 | * @return bool |
||
| 284 | */ |
||
| 285 | View Code Duplication | public static function printGuestPage( $application, $name, $parameters = array() ) { |
|
| 292 | |||
| 293 | /** |
||
| 294 | * Print a fatal error page and terminates the script |
||
| 295 | * @param string $error_msg The error message to show |
||
| 296 | * @param string $hint An optional hint message - needs to be properly escaped |
||
| 297 | */ |
||
| 298 | public static function printErrorPage( $error_msg, $hint = '' ) { |
||
| 325 | |||
| 326 | /** |
||
| 327 | * print error page using Exception details |
||
| 328 | * @param Exception | Throwable $exception |
||
| 329 | */ |
||
| 330 | public static function printExceptionErrorPage($exception, $fetchPage = false) { |
||
| 361 | |||
| 362 | /** |
||
| 363 | * This is only here to reduce the dependencies in case of an exception to |
||
| 364 | * still be able to print a plain error message. |
||
| 365 | * |
||
| 366 | * Returns the used HTTP protocol. |
||
| 367 | * |
||
| 368 | * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0. |
||
| 369 | * @internal Don't use this - use AppFramework\Http\Request->getHttpProtocol instead |
||
| 370 | */ |
||
| 371 | View Code Duplication | protected static function getHttpProtocol() { |
|
| 383 | } |
||
| 384 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.