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 layoutView 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 layoutView, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 8 | class layoutView extends layout |
||
| 9 | { |
||
| 10 | /** |
||
| 11 | * Initialization |
||
| 12 | * @return void |
||
| 13 | */ |
||
| 14 | function init() |
||
| 15 | { |
||
| 16 | $this->setTemplatePath($this->module_path.'tpl'); |
||
|
|
|||
| 17 | } |
||
| 18 | |||
| 19 | /** |
||
| 20 | * Pop-up layout details(conf/info.xml) |
||
| 21 | * @return void |
||
| 22 | */ |
||
| 23 | View Code Duplication | function dispLayoutInfo() |
|
| 24 | { |
||
| 25 | // Get the layout information |
||
| 26 | $oLayoutModel = getModel('layout'); |
||
| 27 | $layout_info = $oLayoutModel->getLayoutInfo(Context::get('selected_layout')); |
||
| 28 | if(!$layout_info) exit(); |
||
| 29 | Context::set('layout_info', $layout_info); |
||
| 30 | // Set the layout to be pop-up |
||
| 31 | $this->setLayoutFile('popup_layout'); |
||
| 32 | // Set a template file |
||
| 33 | $this->setTemplateFile('layout_detail_info'); |
||
| 34 | } |
||
| 35 | |||
| 36 | /** |
||
| 37 | * Preview a layout with module. |
||
| 38 | * |
||
| 39 | * @return Object |
||
| 40 | */ |
||
| 41 | public function dispLayoutPreviewWithModule() |
||
| 42 | { |
||
| 43 | $content = ''; |
||
| 44 | $layoutSrl = Context::get('layout_srl'); |
||
| 45 | |||
| 46 | $module = Context::get('module_name'); |
||
| 47 | $mid = Context::get('target_mid'); |
||
| 48 | $skin = Context::get('skin'); |
||
| 49 | $skinType = Context::get('skin_type'); |
||
| 50 | |||
| 51 | try |
||
| 52 | { |
||
| 53 | // admin check |
||
| 54 | // this act is admin view but in normal view because do not load admin css/js files |
||
| 55 | $logged_info = Context::get('logged_info'); |
||
| 56 | if($logged_info->is_admin != 'Y') |
||
| 57 | { |
||
| 58 | throw new Exception(Context::getLang('msg_invalid_request')); |
||
| 59 | } |
||
| 60 | |||
| 61 | // if module is 'ARTiCLE' and from site design setting, make content directly |
||
| 62 | if($module == 'ARTICLE' && !$mid) |
||
| 63 | { |
||
| 64 | $oDocumentModel = getModel('document'); |
||
| 65 | $oDocument = $oDocumentModel->getDocument(0, true); |
||
| 66 | |||
| 67 | $t = Context::getLang('article_preview_title'); |
||
| 68 | |||
| 69 | $c = ''; |
||
| 70 | for($i = 0; $i < 4; $i++) |
||
| 71 | { |
||
| 72 | $c .= '<p>'; |
||
| 73 | for($j = 0; $j < 20; $j++) |
||
| 74 | { |
||
| 75 | $c .= Context::getLang('article_preview_content') . ' '; |
||
| 76 | } |
||
| 77 | $c .= '</p>'; |
||
| 78 | } |
||
| 79 | |||
| 80 | $attr = new stdClass(); |
||
| 81 | $attr->title = $t; |
||
| 82 | $attr->content = $c; |
||
| 83 | $attr->document_srl = -1; |
||
| 84 | $oDocument->setAttribute($attr, FALSE); |
||
| 85 | |||
| 86 | Context::set('oDocument', $oDocument); |
||
| 87 | |||
| 88 | if ($skinType == 'M') |
||
| 89 | { |
||
| 90 | $templatePath = _XE_PATH_ . 'modules/page/m.skins/' . $skin; |
||
| 91 | $templateFile = 'mobile'; |
||
| 92 | } |
||
| 93 | else |
||
| 94 | { |
||
| 95 | $templatePath = _XE_PATH_ . 'modules/page/skins/' . $skin; |
||
| 96 | $templateFile = 'content'; |
||
| 97 | } |
||
| 98 | |||
| 99 | $oTemplate = TemplateHandler::getInstance(); |
||
| 100 | $content = $oTemplate->compile($templatePath, $templateFile); |
||
| 101 | } |
||
| 102 | |||
| 103 | // else use real module |
||
| 104 | else |
||
| 105 | { |
||
| 106 | $content = $this->procRealModule($module, $mid, $skin, $skinType); |
||
| 107 | } |
||
| 108 | Context::set('content', $content); |
||
| 109 | |||
| 110 | // find layout |
||
| 111 | if($layoutSrl) |
||
| 112 | { |
||
| 113 | if($layoutSrl == -1) |
||
| 114 | { |
||
| 115 | $site_srl = ($oModule) ? $oModule->module_info->site_srl : 0; |
||
| 116 | $designInfoFile = sprintf(_XE_PATH_ . 'files/site_design/design_%s.php', $site_srl); |
||
| 117 | include($designInfoFile); |
||
| 118 | |||
| 119 | if($skinType == 'M') |
||
| 120 | { |
||
| 121 | $layoutSrl = $designInfo->mlayout_srl; |
||
| 122 | } |
||
| 123 | else |
||
| 124 | { |
||
| 125 | $layoutSrl = $designInfo->layout_srl; |
||
| 126 | } |
||
| 127 | } |
||
| 128 | |||
| 129 | $oLayoutModel = getModel('layout'); |
||
| 130 | $layoutInfo = $oLayoutModel->getLayout($layoutSrl); |
||
| 131 | |||
| 132 | // If there is no layout, pass it. |
||
| 133 | if($layoutInfo) |
||
| 134 | { |
||
| 135 | // Adhoc... |
||
| 136 | |||
| 137 | // Input extra_vars into $layout_info |
||
| 138 | View Code Duplication | if($layoutInfo->extra_var_count) |
|
| 139 | { |
||
| 140 | |||
| 141 | foreach($layoutInfo->extra_var as $var_id => $val) |
||
| 142 | { |
||
| 143 | if($val->type == 'image') |
||
| 144 | { |
||
| 145 | if(strncmp('./files/attach/images/', $val->value, 22) === 0) |
||
| 146 | { |
||
| 147 | $val->value = Context::getRequestUri() . substr($val->value, 2); |
||
| 148 | } |
||
| 149 | } |
||
| 150 | $layoutInfo->{$var_id} = $val->value; |
||
| 151 | } |
||
| 152 | } |
||
| 153 | |||
| 154 | // Set menus into context |
||
| 155 | if($layoutInfo->menu_count) |
||
| 156 | { |
||
| 157 | foreach($layoutInfo->menu as $menu_id => $menu) |
||
| 158 | { |
||
| 159 | // set default menu set(included home menu) |
||
| 160 | View Code Duplication | if(!$menu->menu_srl || $menu->menu_srl == -1) |
|
| 161 | { |
||
| 162 | $oMenuAdminController = getAdminController('menu'); |
||
| 163 | $homeMenuCacheFile = $oMenuAdminController->getHomeMenuCacheFile(); |
||
| 164 | |||
| 165 | if(file_exists($homeMenuCacheFile)) |
||
| 166 | { |
||
| 167 | include($homeMenuCacheFile); |
||
| 168 | } |
||
| 169 | |||
| 170 | if(!$menu->menu_srl) |
||
| 171 | { |
||
| 172 | $menu->xml_file = str_replace('.xml.php', $homeMenuSrl . '.xml.php', $menu->xml_file); |
||
| 173 | $menu->php_file = str_replace('.php', $homeMenuSrl . '.php', $menu->php_file); |
||
| 174 | $layoutInfo->menu->{$menu_id}->menu_srl = $homeMenuSrl; |
||
| 175 | } |
||
| 176 | else |
||
| 177 | { |
||
| 178 | $menu->xml_file = str_replace($menu->menu_srl, $homeMenuSrl, $menu->xml_file); |
||
| 179 | $menu->php_file = str_replace($menu->menu_srl, $homeMenuSrl, $menu->php_file); |
||
| 180 | } |
||
| 181 | } |
||
| 182 | |||
| 183 | $menu->php_file = FileHandler::getRealPath($menu->php_file); |
||
| 184 | if(FileHandler::exists($menu->php_file)) |
||
| 185 | { |
||
| 186 | include($menu->php_file); |
||
| 187 | } |
||
| 188 | Context::set($menu_id, $menu); |
||
| 189 | } |
||
| 190 | } |
||
| 191 | |||
| 192 | Context::set('layout_info', $layoutInfo); |
||
| 193 | } |
||
| 194 | } |
||
| 195 | } |
||
| 196 | catch(Exception $e) |
||
| 197 | { |
||
| 198 | $content = '<div class="message error"><p id="preview_error">' . $e->getMessage() . '</p></div>'; |
||
| 199 | Context::set('content', $content); |
||
| 200 | $layoutSrl = 0; |
||
| 201 | } |
||
| 202 | |||
| 203 | // Compile |
||
| 204 | $oTemplate = TemplateHandler::getInstance(); |
||
| 205 | Context::clearHtmlHeader(); |
||
| 206 | |||
| 207 | if($layoutInfo) |
||
| 208 | { |
||
| 209 | $layout_path = $layoutInfo->path; |
||
| 210 | $editLayoutTPL = $this->getRealLayoutFile($layoutSrl); |
||
| 211 | $editLayoutCSS = $this->getRealLayoutCSS($layoutSrl); |
||
| 212 | if($editLayoutCSS != '') |
||
| 213 | { |
||
| 214 | Context::addCSSFile($editLayoutCSS); |
||
| 215 | } |
||
| 216 | $layout_file = 'layout'; |
||
| 217 | $oModuleModel = getModel('module'); |
||
| 218 | $part_config = $oModuleModel->getModulePartConfig('layout', $layoutSrl); |
||
| 219 | Context::addHtmlHeader($part_config->header_script); |
||
| 220 | } |
||
| 221 | else |
||
| 222 | { |
||
| 223 | $layout_path = './common/tpl'; |
||
| 224 | $layout_file = 'default_layout'; |
||
| 225 | } |
||
| 226 | |||
| 227 | $layout_tpl = $oTemplate->compile($layout_path, $layout_file, $editLayoutTPL); |
||
| 228 | Context::set('layout','none'); |
||
| 229 | |||
| 230 | // Convert widgets and others |
||
| 231 | $oContext = Context::getInstance(); |
||
| 232 | Context::set('layout_tpl', $layout_tpl); |
||
| 233 | $this->setTemplatePath($this->module_path.'tpl'); |
||
| 234 | $this->setTemplateFile('layout_preview'); |
||
| 235 | } |
||
| 236 | |||
| 237 | /** |
||
| 238 | * Get content of real module |
||
| 239 | * |
||
| 240 | * @param string $module module name |
||
| 241 | * @param string $mid module id |
||
| 242 | * @param string $skin skin name |
||
| 243 | * @param string $skinType PC(P) or mobile(M) |
||
| 244 | * @return string content of real module |
||
| 245 | */ |
||
| 246 | private function procRealModule($module, $mid, $skin, $skinType) |
||
| 247 | { |
||
| 248 | // if form site design and preview module, find target module |
||
| 249 | if($module && !$mid) |
||
| 250 | { |
||
| 251 | $args = new stdClass(); |
||
| 252 | $args->module = $module; |
||
| 253 | $output = executeQuery('layout.getOneModuleInstanceByModuleName', $args); |
||
| 254 | if(!$output->toBool()) |
||
| 255 | { |
||
| 256 | throw new Exception($output->getMessage()); |
||
| 257 | } |
||
| 258 | |||
| 259 | // if there is no module instance, error... |
||
| 260 | if(!$output->data) |
||
| 261 | { |
||
| 262 | throw new Exception(Context::getLang('msg_unabled_preview')); |
||
| 263 | } |
||
| 264 | |||
| 265 | $mid = current($output->data)->mid; |
||
| 266 | } |
||
| 267 | |||
| 268 | // if form site design and preview layout, find start module |
||
| 269 | elseif(!$module && !$mid) |
||
| 270 | { |
||
| 271 | $oModuleModel = getModel('module'); |
||
| 272 | $columnList = array('modules.mid', 'sites.index_module_srl'); |
||
| 273 | $startModuleInfo = $oModuleModel->getSiteInfo(0, $columnList); |
||
| 274 | $mid = $startModuleInfo->mid; |
||
| 275 | } |
||
| 276 | |||
| 277 | $oModuleHandler = new ModuleHandler('', '', $mid, '', ''); |
||
| 278 | |||
| 279 | // Adhoc... |
||
| 280 | $oModuleHandler->act = ''; |
||
| 281 | |||
| 282 | $oModuleHandler->init(); |
||
| 283 | |||
| 284 | // Adhoc... |
||
| 285 | $oModuleHandler->module_info->use_mobile = 'Y'; |
||
| 286 | $oModuleHandler->module_info->is_skin_fix = 'Y'; |
||
| 287 | $oModuleHandler->module_info->is_mskin_fix = 'Y'; |
||
| 288 | |||
| 289 | if($skinType == 'M') |
||
| 290 | { |
||
| 291 | Mobile::setMobile(TRUE); |
||
| 292 | $oModuleHandler->module_info->mskin = $skin; |
||
| 293 | } |
||
| 294 | else |
||
| 295 | { |
||
| 296 | Mobile::setMobile(FALSE); |
||
| 297 | $oModuleHandler->module_info->skin = $skin; |
||
| 298 | } |
||
| 299 | |||
| 300 | // Proc module |
||
| 301 | $oModule = $oModuleHandler->procModule(); |
||
| 302 | if(!$oModule->toBool()) |
||
| 303 | { |
||
| 304 | throw new Exception(Context::getLang('not_support_layout_preview')); |
||
| 305 | } |
||
| 306 | |||
| 307 | // get module html |
||
| 308 | require_once(_XE_PATH_ . "classes/display/HTMLDisplayHandler.php"); |
||
| 309 | $handler = new HTMLDisplayHandler(); |
||
| 310 | return $handler->toDoc($oModule); |
||
| 311 | } |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Preview a layout |
||
| 315 | * @return void|Object (void : success, Object : fail) |
||
| 316 | */ |
||
| 317 | function dispLayoutPreview() |
||
| 384 | |||
| 385 | private function getRealLayoutFile($layoutSrl) |
||
| 386 | { |
||
| 387 | $oLayoutModel = getModel('layout'); |
||
| 388 | $layoutFile = $oLayoutModel->getUserLayoutHtml($layoutSrl); |
||
| 400 | |||
| 401 | private function getRealLayoutCSS($layoutSrl) |
||
| 416 | |||
| 417 | |||
| 418 | |||
| 419 | } |
||
| 420 | /* End of file layout.view.php */ |
||
| 422 |
This check looks for access to properties that are not accessible from the current context.
If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.