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:
| 1 | <?php |
||
| 45 | class OC_Template extends \OC\Template\Base { |
||
| 46 | |||
| 47 | /** @var string */ |
||
| 48 | private $renderAs; // Create a full page? |
||
| 49 | |||
| 50 | /** @var string */ |
||
| 51 | private $path; // The path to the template |
||
| 52 | |||
| 53 | /** @var array */ |
||
| 54 | private $headers = array(); //custom headers |
||
| 55 | |||
| 56 | /** @var string */ |
||
| 57 | protected $app; // app id |
||
| 58 | |||
| 59 | protected static $initTemplateEngineFirstRun = true; |
||
| 60 | |||
| 61 | /** |
||
| 62 | * Constructor |
||
| 63 | * |
||
| 64 | * @param string $app app providing the template |
||
| 65 | * @param string $name of the template file (without suffix) |
||
| 66 | * @param string $renderAs If $renderAs is set, OC_Template will try to |
||
| 67 | * produce a full page in the according layout. For |
||
| 68 | * now, $renderAs can be set to "guest", "user" or |
||
| 69 | * "admin". |
||
| 70 | * @param bool $registerCall = true |
||
| 71 | */ |
||
| 72 | public function __construct( $app, $name, $renderAs = "", $registerCall = true ) { |
||
| 73 | // Read the selected theme from the config file |
||
| 74 | self::initTemplateEngine($renderAs); |
||
| 75 | |||
| 76 | $theme = OC_Util::getTheme(); |
||
| 77 | |||
| 78 | $requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : ''; |
||
| 79 | |||
| 80 | $parts = explode('/', $app); // fix translation when app is something like core/lostpassword |
||
| 81 | $l10n = \OC::$server->getL10N($parts[0]); |
||
| 82 | /** @var \OCP\Defaults $themeDefaults */ |
||
| 83 | $themeDefaults = \OC::$server->query(\OCP\Defaults::class); |
||
| 84 | |||
| 85 | list($path, $template) = $this->findTemplate($theme, $app, $name); |
||
| 86 | |||
| 87 | // Set the private data |
||
| 88 | $this->renderAs = $renderAs; |
||
| 89 | $this->path = $path; |
||
| 90 | $this->app = $app; |
||
| 91 | |||
| 92 | parent::__construct($template, $requestToken, $l10n, $themeDefaults); |
||
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * @param string $renderAs |
||
| 97 | */ |
||
| 98 | public static function initTemplateEngine($renderAs) { |
||
| 99 | if (self::$initTemplateEngineFirstRun){ |
||
| 100 | |||
| 101 | //apps that started before the template initialization can load their own scripts/styles |
||
| 102 | //so to make sure this scripts/styles here are loaded first we use OC_Util::addScript() with $prepend=true |
||
| 103 | //meaning the last script/style in this list will be loaded first |
||
| 104 | if (\OC::$server->getSystemConfig()->getValue ('installed', false) && $renderAs !== 'error' && !\OCP\Util::needUpgrade()) { |
||
| 105 | if (\OC::$server->getConfig ()->getAppValue ( 'core', 'backgroundjobs_mode', 'ajax' ) == 'ajax') { |
||
| 106 | OC_Util::addScript ( 'backgroundjobs', null, true ); |
||
| 107 | } |
||
| 108 | } |
||
| 109 | |||
| 110 | OC_Util::addStyle('jquery-ui-fixes',null,true); |
||
| 111 | OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui',null,true); |
||
| 112 | OC_Util::addStyle('server', null, true); |
||
| 113 | OC_Util::addVendorStyle('select2/select2', null, true); |
||
| 114 | OC_Util::addStyle('jquery.ocdialog'); |
||
| 115 | OC_Util::addTranslations("core", null, true); |
||
| 116 | OC_Util::addScript('search', 'search', true); |
||
| 117 | OC_Util::addScript('merged-template-prepend', null, true); |
||
| 118 | OC_Util::addScript('jquery-ui-fixes'); |
||
| 119 | OC_Util::addScript('files/fileinfo'); |
||
| 120 | OC_Util::addScript('files/client'); |
||
| 121 | OC_Util::addScript('contactsmenu'); |
||
| 122 | |||
| 123 | if (\OC::$server->getConfig()->getSystemValue('debug')) { |
||
| 124 | // Add the stuff we need always |
||
| 125 | // following logic will import all vendor libraries that are |
||
| 126 | // specified in core/js/core.json |
||
| 127 | $fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json'); |
||
| 128 | if($fileContent !== false) { |
||
| 129 | $coreDependencies = json_decode($fileContent, true); |
||
| 130 | foreach(array_reverse($coreDependencies['vendor']) as $vendorLibrary) { |
||
| 131 | //remove trailing ".js" as addVendorScript will append it |
||
| 132 | OC_Util::addVendorScript( |
||
| 133 | substr($vendorLibrary, 0, strlen($vendorLibrary) - 3),null,true); |
||
| 134 | } |
||
| 135 | } else { |
||
| 136 | throw new \Exception('Cannot read core/js/core.json'); |
||
| 137 | } |
||
| 138 | } else { |
||
| 139 | // Import all (combined) default vendor libraries |
||
| 140 | OC_Util::addVendorScript('core', null, true); |
||
| 141 | } |
||
| 142 | |||
| 143 | if (\OC::$server->getRequest()->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE])) { |
||
| 144 | // polyfill for btoa/atob for IE friends |
||
| 145 | OC_Util::addVendorScript('base64/base64'); |
||
| 146 | // shim for the davclient.js library |
||
| 147 | \OCP\Util::addScript('files/iedavclient'); |
||
| 148 | } |
||
| 149 | |||
| 150 | self::$initTemplateEngineFirstRun = false; |
||
| 151 | } |
||
| 152 | |||
| 153 | } |
||
| 154 | |||
| 155 | |||
| 156 | /** |
||
| 157 | * find the template with the given name |
||
| 158 | * @param string $name of the template file (without suffix) |
||
| 159 | * |
||
| 160 | * Will select the template file for the selected theme. |
||
| 161 | * Checking all the possible locations. |
||
| 162 | * @param string $theme |
||
| 163 | * @param string $app |
||
| 164 | * @return string[] |
||
| 165 | */ |
||
| 166 | protected function findTemplate($theme, $app, $name) { |
||
| 178 | |||
| 179 | /** |
||
| 180 | * Add a custom element to the header |
||
| 181 | * @param string $tag tag name of the element |
||
| 182 | * @param array $attributes array of attributes for the element |
||
| 183 | * @param string $text the text content for the element. If $text is null then the |
||
| 184 | * element will be written as empty element. So use "" to get a closing tag. |
||
| 185 | */ |
||
| 186 | View Code Duplication | public function addHeader($tag, $attributes, $text=null) { |
|
| 193 | |||
| 194 | /** |
||
| 195 | * Process the template |
||
| 196 | * @return boolean|string |
||
| 197 | * |
||
| 198 | * This function process the template. If $this->renderAs is set, it |
||
| 199 | * will produce a full page. |
||
| 200 | */ |
||
| 201 | public function fetchPage($additionalParams = null) { |
||
| 229 | |||
| 230 | /** |
||
| 231 | * Include template |
||
| 232 | * |
||
| 233 | * @param string $file |
||
| 234 | * @param array|null $additionalParams |
||
| 235 | * @return string returns content of included template |
||
| 236 | * |
||
| 237 | * Includes another template. use <?php echo $this->inc('template'); ?> to |
||
| 238 | * do this. |
||
| 239 | */ |
||
| 240 | public function inc( $file, $additionalParams = null ) { |
||
| 243 | |||
| 244 | /** |
||
| 245 | * Shortcut to print a simple page for users |
||
| 246 | * @param string $application The application we render the template for |
||
| 247 | * @param string $name Name of the template |
||
| 248 | * @param array $parameters Parameters for the template |
||
| 249 | * @return boolean|null |
||
| 250 | */ |
||
| 251 | View Code Duplication | public static function printUserPage( $application, $name, $parameters = array() ) { |
|
| 258 | |||
| 259 | /** |
||
| 260 | * Shortcut to print a simple page for admins |
||
| 261 | * @param string $application The application we render the template for |
||
| 262 | * @param string $name Name of the template |
||
| 263 | * @param array $parameters Parameters for the template |
||
| 264 | * @return bool |
||
| 265 | */ |
||
| 266 | View Code Duplication | public static function printAdminPage( $application, $name, $parameters = array() ) { |
|
| 273 | |||
| 274 | /** |
||
| 275 | * Shortcut to print a simple page for guests |
||
| 276 | * @param string $application The application we render the template for |
||
| 277 | * @param string $name Name of the template |
||
| 278 | * @param array|string $parameters Parameters for the template |
||
| 279 | * @return bool |
||
| 280 | */ |
||
| 281 | View Code Duplication | public static function printGuestPage( $application, $name, $parameters = array() ) { |
|
| 288 | |||
| 289 | /** |
||
| 290 | * Print a fatal error page and terminates the script |
||
| 291 | * @param string $error_msg The error message to show |
||
| 292 | * @param string $hint An optional hint message - needs to be properly escaped |
||
| 293 | */ |
||
| 294 | public static function printErrorPage( $error_msg, $hint = '' ) { |
||
| 321 | |||
| 322 | /** |
||
| 323 | * print error page using Exception details |
||
| 324 | * @param Exception | Throwable $exception |
||
| 325 | */ |
||
| 326 | public static function printExceptionErrorPage($exception, $fetchPage = false) { |
||
| 357 | |||
| 358 | /** |
||
| 359 | * This is only here to reduce the dependencies in case of an exception to |
||
| 360 | * still be able to print a plain error message. |
||
| 361 | * |
||
| 362 | * Returns the used HTTP protocol. |
||
| 363 | * |
||
| 364 | * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0. |
||
| 365 | * @internal Don't use this - use AppFramework\Http\Request->getHttpProtocol instead |
||
| 366 | */ |
||
| 367 | View Code Duplication | protected static function getHttpProtocol() { |
|
| 379 | } |
||
| 380 |
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.