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 main_menu 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 main_menu, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 15 | class main_menu extends module_base  | 
            ||
| 16 | { | 
            ||
| 17 | /**  | 
            ||
| 18 | * Allowed columns: Just sum up your options (Exp: left + right = 10)  | 
            ||
| 19 | * top 1  | 
            ||
| 20 | * left 2  | 
            ||
| 21 | * center 4  | 
            ||
| 22 | * right 8  | 
            ||
| 23 | * bottom 16  | 
            ||
| 24 | */  | 
            ||
| 25 | public $columns = 10;  | 
            ||
| 26 | |||
| 27 | /**  | 
            ||
| 28 | * Default modulename  | 
            ||
| 29 | */  | 
            ||
| 30 | public $name = 'M_MENU';  | 
            ||
| 31 | |||
| 32 | /**  | 
            ||
| 33 | * Default module-image:  | 
            ||
| 34 | 	* file must be in "{T_THEME_PATH}/images/portal/" | 
            ||
| 35 | */  | 
            ||
| 36 | public $image_src = 'portal_menu.png';  | 
            ||
| 37 | |||
| 38 | /**  | 
            ||
| 39 | * module-language file  | 
            ||
| 40 | 	* file must be in "language/{$user->lang}/mods/portal/" | 
            ||
| 41 | */  | 
            ||
| 42 | public $language = 'portal_main_menu_module';  | 
            ||
| 43 | |||
| 44 | /**  | 
            ||
| 45 | * custom acp template  | 
            ||
| 46 | * file must be in "adm/style/portal/"  | 
            ||
| 47 | */  | 
            ||
| 48 | public $custom_acp_tpl = 'acp_portal_menu';  | 
            ||
| 49 | |||
| 50 | /** @var bool Can include this module multiple times */  | 
            ||
| 51 | protected $multiple_includes = true;  | 
            ||
| 52 | |||
| 53 | /**  | 
            ||
| 54 | * constants  | 
            ||
| 55 | */  | 
            ||
| 56 | const LINK_CAT = 0;  | 
            ||
| 57 | const LINK_INT = 1;  | 
            ||
| 58 | const LINK_EXT = 2;  | 
            ||
| 59 | |||
| 60 | /** @var \phpbb\config\config */  | 
            ||
| 61 | protected $config;  | 
            ||
| 62 | |||
| 63 | /** @var \phpbb\db\driver\driver_interface */  | 
            ||
| 64 | protected $db;  | 
            ||
| 65 | |||
| 66 | /** @var \phpbb\request\request */  | 
            ||
| 67 | protected $request;  | 
            ||
| 68 | |||
| 69 | /** @var \phpbb\template\template */  | 
            ||
| 70 | protected $template;  | 
            ||
| 71 | |||
| 72 | /** @var string PHP file extension */  | 
            ||
| 73 | protected $php_ext;  | 
            ||
| 74 | |||
| 75 | /** @var string phpBB root path */  | 
            ||
| 76 | protected $phpbb_root_path;  | 
            ||
| 77 | |||
| 78 | /** @var \phpbb\user */  | 
            ||
| 79 | protected $user;  | 
            ||
| 80 | |||
| 81 | /** @var \phpbb\log\log phpBB log */  | 
            ||
| 82 | protected $log;  | 
            ||
| 83 | |||
| 84 | /**  | 
            ||
| 85 | * Construct a main menu object  | 
            ||
| 86 | *  | 
            ||
| 87 | * @param \phpbb\config\config $config phpBB config  | 
            ||
| 88 | * @param \phpbb\db\driver\driver_interface $db phpBB db driver  | 
            ||
| 89 | * @param \phpbb\request\request $request phpBB request  | 
            ||
| 90 | * @param \phpbb\template\template $template phpBB template  | 
            ||
| 91 | * @param string $phpbb_root_path phpBB root path  | 
            ||
| 92 | * @param string $phpEx php file extension  | 
            ||
| 93 | * @param \phpbb\user $user phpBB user object  | 
            ||
| 94 | * @param \phpbb\log\log $log phpBB log  | 
            ||
| 95 | */  | 
            ||
| 96 | View Code Duplication | public function __construct($config, $db, $request, $template, $phpbb_root_path, $phpEx, $user, $log)  | 
            |
| 97 | 	{ | 
            ||
| 98 | $this->config = $config;  | 
            ||
| 99 | $this->db = $db;  | 
            ||
| 100 | $this->request = $request;  | 
            ||
| 101 | $this->template = $template;  | 
            ||
| 102 | $this->phpbb_root_path = $phpbb_root_path;  | 
            ||
| 103 | $this->php_ext = $phpEx;  | 
            ||
| 104 | $this->user = $user;  | 
            ||
| 105 | $this->log = $log;  | 
            ||
| 106 | }  | 
            ||
| 107 | |||
| 108 | /**  | 
            ||
| 109 | 	* {@inheritdoc} | 
            ||
| 110 | */  | 
            ||
| 111 | public function get_template_side($module_id)  | 
            ||
| 112 | 	{ | 
            ||
| 113 | $portal_config = obtain_portal_config();  | 
            ||
| 114 | |||
| 115 | $links = json_decode($portal_config['board3_menu_array_' . $module_id], true);  | 
            ||
| 116 | |||
| 117 | 		$this->template->assign_block_vars('portal_menu', array('MODULE_ID' => $module_id)); | 
            ||
| 118 | |||
| 119 | // get user's groups  | 
            ||
| 120 | $groups_ary = get_user_groups();  | 
            ||
| 121 | |||
| 122 | for ($i = 0; $i < sizeof($links); $i++)  | 
            ||
| 123 | 		{ | 
            ||
| 124 | if ($links[$i]['type'] == self::LINK_CAT)  | 
            ||
| 125 | 			{ | 
            ||
| 126 | 				$this->template->assign_block_vars('portal_menu.category', array( | 
            ||
| 127 | 'CAT_TITLE' => (isset($this->user->lang[$links[$i]['title']])) ? $this->user->lang[$links[$i]['title']] : $links[$i]['title'],  | 
            ||
| 128 | ));  | 
            ||
| 129 | }  | 
            ||
| 130 | else  | 
            ||
| 131 | 			{ | 
            ||
| 132 | View Code Duplication | if ($links[$i]['type'] == self::LINK_INT)  | 
            |
| 133 | 				{ | 
            ||
| 134 | 					$links[$i]['url'] = str_replace('&', '&', $links[$i]['url']); // we need to do this in order to prevent XHTML validation errors | 
            ||
| 135 | $cur_url = append_sid($this->phpbb_root_path . $links[$i]['url']); // the user should know what kind of file it is  | 
            ||
| 136 | }  | 
            ||
| 137 | else  | 
            ||
| 138 | 				{ | 
            ||
| 139 | $cur_url = $links[$i]['url'];  | 
            ||
| 140 | }  | 
            ||
| 141 | |||
| 142 | 				$cur_permissions = explode(',', $links[$i]['permission']); | 
            ||
| 143 | $permission_check = array_intersect($groups_ary, $cur_permissions);  | 
            ||
| 144 | |||
| 145 | View Code Duplication | if (!empty($permission_check) || $links[$i]['permission'] == '')  | 
            |
| 146 | 				{ | 
            ||
| 147 | 					$this->template->assign_block_vars('portal_menu.category.links', array( | 
            ||
| 148 | 'LINK_TITLE' => (isset($this->user->lang[$links[$i]['title']])) ? $this->user->lang[$links[$i]['title']] : $links[$i]['title'],  | 
            ||
| 149 | 'LINK_URL' => $cur_url,  | 
            ||
| 150 | 'NEW_WINDOW' => ($links[$i]['type'] != self::LINK_INT && $this->config['board3_menu_url_new_window_' . $module_id]) ? true : false,  | 
            ||
| 151 | ));  | 
            ||
| 152 | }  | 
            ||
| 153 | }  | 
            ||
| 154 | }  | 
            ||
| 155 | |||
| 156 | return 'main_menu_side.html';  | 
            ||
| 157 | }  | 
            ||
| 158 | |||
| 159 | /**  | 
            ||
| 160 | 	* {@inheritdoc} | 
            ||
| 161 | */  | 
            ||
| 162 | View Code Duplication | public function get_template_acp($module_id)  | 
            |
| 163 | 	{ | 
            ||
| 164 | return array(  | 
            ||
| 165 | 'title' => 'ACP_PORTAL_MENU',  | 
            ||
| 166 | 'vars' => array(  | 
            ||
| 167 | 'legend1' => 'ACP_PORTAL_MENU',  | 
            ||
| 168 | 				'board3_menu_' . $module_id	=> array('lang' => 'ACP_PORTAL_MENU_MANAGE', 'validate' => 'string',	'type' => 'custom',	'explain' => true, 'method' => 'manage_links', 'submit' => 'update_links'), | 
            ||
| 169 | 				'board3_menu_url_new_window_' . $module_id => array('lang' => 'ACP_PORTAL_MENU_EXT_NEW_WINDOW', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), | 
            ||
| 170 | ),  | 
            ||
| 171 | );  | 
            ||
| 172 | }  | 
            ||
| 173 | |||
| 174 | /**  | 
            ||
| 175 | 	* {@inheritdoc} | 
            ||
| 176 | */  | 
            ||
| 177 | public function install($module_id)  | 
            ||
| 178 | 	{ | 
            ||
| 179 | // get the correct group IDs from the database  | 
            ||
| 180 | 		$in_ary = array('GUESTS', 'REGISTERED', 'REGISTERED_COPPA'); | 
            ||
| 181 | $groups_ary = array();  | 
            ||
| 182 | |||
| 183 | 		$sql = 'SELECT group_id, group_name FROM ' . GROUPS_TABLE . ' WHERE ' . $this->db->sql_in_set('group_name', $in_ary); | 
            ||
| 184 | $result = $this->db->sql_query($sql);  | 
            ||
| 185 | View Code Duplication | while ($row = $this->db->sql_fetchrow($result))  | 
            |
| 186 | 		{ | 
            ||
| 187 | $groups_ary[$row['group_name']] = $row['group_id'];  | 
            ||
| 188 | }  | 
            ||
| 189 | |||
| 190 | $links = array();  | 
            ||
| 191 | |||
| 192 | $links_titles = array(  | 
            ||
| 193 | 'M_CONTENT',  | 
            ||
| 194 | 'INDEX',  | 
            ||
| 195 | 'SEARCH',  | 
            ||
| 196 | 'REGISTER',  | 
            ||
| 197 | 'MEMBERLIST',  | 
            ||
| 198 | 'THE_TEAM',  | 
            ||
| 199 | 'M_HELP',  | 
            ||
| 200 | 'FAQ',  | 
            ||
| 201 | 'M_BBCODE',  | 
            ||
| 202 | 'M_TERMS',  | 
            ||
| 203 | 'M_PRV',  | 
            ||
| 204 | );  | 
            ||
| 205 | |||
| 206 | $links_types = array(  | 
            ||
| 207 | self::LINK_CAT,  | 
            ||
| 208 | self::LINK_INT,  | 
            ||
| 209 | self::LINK_INT,  | 
            ||
| 210 | self::LINK_INT,  | 
            ||
| 211 | self::LINK_INT,  | 
            ||
| 212 | self::LINK_INT,  | 
            ||
| 213 | self::LINK_CAT,  | 
            ||
| 214 | self::LINK_INT,  | 
            ||
| 215 | self::LINK_INT,  | 
            ||
| 216 | self::LINK_INT,  | 
            ||
| 217 | self::LINK_INT,  | 
            ||
| 218 | );  | 
            ||
| 219 | |||
| 220 | $links_urls = array(  | 
            ||
| 221 | '',  | 
            ||
| 222 | 'index.' . $this->php_ext,  | 
            ||
| 223 | 'search.' . $this->php_ext,  | 
            ||
| 224 | 'ucp.' . $this->php_ext . '?mode=register',  | 
            ||
| 225 | 'memberlist.' . $this->php_ext,  | 
            ||
| 226 | 'memberlist.' . $this->php_ext . '?mode=leaders',  | 
            ||
| 227 | '',  | 
            ||
| 228 | 'faq.' . $this->php_ext,  | 
            ||
| 229 | 'faq.' . $this->php_ext . '?mode=bbcode',  | 
            ||
| 230 | 'ucp.' . $this->php_ext . '?mode=terms',  | 
            ||
| 231 | 'ucp.' . $this->php_ext . '?mode=privacy',  | 
            ||
| 232 | );  | 
            ||
| 233 | |||
| 234 | $links_permissions = array(  | 
            ||
| 235 | '',  | 
            ||
| 236 | '',  | 
            ||
| 237 | '',  | 
            ||
| 238 | $groups_ary['GUESTS'],  | 
            ||
| 239 | $groups_ary['REGISTERED'] . ',' . $groups_ary['REGISTERED_COPPA'],  | 
            ||
| 240 | $groups_ary['REGISTERED'] . ',' . $groups_ary['REGISTERED_COPPA'],  | 
            ||
| 241 | '',  | 
            ||
| 242 | '',  | 
            ||
| 243 | '',  | 
            ||
| 244 | '',  | 
            ||
| 245 | '',  | 
            ||
| 246 | );  | 
            ||
| 247 | |||
| 248 | View Code Duplication | foreach ($links_urls as $i => $url)  | 
            |
| 249 | 		{ | 
            ||
| 250 | $links[] = array(  | 
            ||
| 251 | 'title' => $links_titles[$i],  | 
            ||
| 252 | 'url' => $links_urls[$i],  | 
            ||
| 253 | 'type' => $links_types[$i],  | 
            ||
| 254 | 'permission' => $links_permissions[$i],  | 
            ||
| 255 | );  | 
            ||
| 256 | }  | 
            ||
| 257 | |||
| 258 | $board3_menu_array = json_encode($links);  | 
            ||
| 259 | 		set_portal_config('board3_menu_array_' . $module_id, $board3_menu_array); | 
            ||
| 260 | 		$this->config->set('board3_menu_' . $module_id, ''); | 
            ||
| 261 | 		$this->config->set('board3_menu_url_new_window_' . $module_id, 0); | 
            ||
| 262 | |||
| 263 | return true;  | 
            ||
| 264 | }  | 
            ||
| 265 | |||
| 266 | /**  | 
            ||
| 267 | 	* {@inheritdoc} | 
            ||
| 268 | */  | 
            ||
| 269 | View Code Duplication | public function uninstall($module_id, $db)  | 
            |
| 270 | 	{ | 
            ||
| 271 | $del_config = array(  | 
            ||
| 272 | 'board3_menu_array_' . $module_id,  | 
            ||
| 273 | );  | 
            ||
| 274 | $sql = 'DELETE FROM ' . PORTAL_CONFIG_TABLE . '  | 
            ||
| 275 | 			WHERE ' . $db->sql_in_set('config_name', $del_config); | 
            ||
| 276 | |||
| 277 | $db->sql_query($sql);  | 
            ||
| 278 | |||
| 279 | $del_config = array(  | 
            ||
| 280 | 'board3_menu_' . $module_id,  | 
            ||
| 281 | 'board3_menu_url_new_window_' . $module_id,  | 
            ||
| 282 | );  | 
            ||
| 283 | $sql = 'DELETE FROM ' . CONFIG_TABLE . '  | 
            ||
| 284 | 			WHERE ' . $db->sql_in_set('config_name', $del_config); | 
            ||
| 285 | return $db->sql_query($sql);  | 
            ||
| 286 | }  | 
            ||
| 287 | |||
| 288 | /**  | 
            ||
| 289 | * Manage the menu links  | 
            ||
| 290 | *  | 
            ||
| 291 | * @param mixed $value Value of input  | 
            ||
| 292 | * @param string $key Key name  | 
            ||
| 293 | * @param int $module_id Module ID  | 
            ||
| 294 | *  | 
            ||
| 295 | * @return null  | 
            ||
| 296 | */  | 
            ||
| 297 | public function manage_links($value, $key, $module_id)  | 
            ||
| 514 | |||
| 515 | /**  | 
            ||
| 516 | * Update links  | 
            ||
| 517 | *  | 
            ||
| 518 | * @param string $key Key name  | 
            ||
| 519 | * @param int $module_id Module ID  | 
            ||
| 520 | *  | 
            ||
| 521 | * @return null  | 
            ||
| 522 | */  | 
            ||
| 523 | public function update_links($key, $module_id)  | 
            ||
| 527 | }  | 
            ||
| 528 | 
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.