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 admin_controller 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 admin_controller, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class admin_controller |
||
19 | { |
||
20 | /** @var array Form data */ |
||
21 | protected $data = array(); |
||
22 | |||
23 | /** @var \phpbb\template\template */ |
||
24 | protected $template; |
||
25 | |||
26 | /** @var \phpbb\language\language */ |
||
27 | protected $language; |
||
28 | |||
29 | /** @var \phpbb\request\request */ |
||
30 | protected $request; |
||
31 | |||
32 | /** @var \phpbb\ads\ad\manager */ |
||
33 | protected $manager; |
||
34 | |||
35 | /** @var \phpbb\config\db_text */ |
||
36 | protected $config_text; |
||
37 | |||
38 | /** @var \phpbb\config\config */ |
||
39 | protected $config; |
||
40 | |||
41 | /** @var \phpbb\group\helper */ |
||
42 | protected $group_helper; |
||
43 | |||
44 | /** @var \phpbb\ads\controller\admin_input */ |
||
45 | protected $input; |
||
46 | |||
47 | /** @var \phpbb\ads\controller\helper */ |
||
48 | protected $helper; |
||
49 | |||
50 | /** @var \phpbb\ads\analyser\manager */ |
||
51 | protected $analyser; |
||
52 | |||
53 | /** @var string Custom form action */ |
||
54 | protected $u_action; |
||
55 | |||
56 | /** @var \auth_admin Auth admin */ |
||
57 | protected $auth_admin; |
||
58 | |||
59 | /** |
||
60 | * Constructor |
||
61 | * |
||
62 | * @param \phpbb\template\template $template Template object |
||
63 | * @param \phpbb\language\language $language Language object |
||
64 | * @param \phpbb\request\request $request Request object |
||
65 | * @param \phpbb\ads\ad\manager $manager Advertisement manager object |
||
66 | * @param \phpbb\config\db_text $config_text Config text object |
||
67 | * @param \phpbb\config\config $config Config object |
||
68 | * @param \phpbb\group\helper $group_helper Group helper object |
||
69 | * @param \phpbb\ads\controller\admin_input $input Admin input object |
||
70 | * @param \phpbb\ads\controller\helper $helper Helper object |
||
71 | * @param \phpbb\ads\analyser\manager $analyser Ad code analyser object |
||
72 | * @param string $root_path phpBB root path |
||
73 | * @param string $php_ext PHP extension |
||
74 | */ |
||
75 | 33 | public function __construct(\phpbb\template\template $template, \phpbb\language\language $language, \phpbb\request\request $request, \phpbb\ads\ad\manager $manager, \phpbb\config\db_text $config_text, \phpbb\config\config $config, \phpbb\group\helper $group_helper, \phpbb\ads\controller\admin_input $input, \phpbb\ads\controller\helper $helper, \phpbb\ads\analyser\manager $analyser, $root_path, $php_ext) |
|
76 | { |
||
77 | 33 | $this->template = $template; |
|
78 | 33 | $this->language = $language; |
|
79 | 33 | $this->request = $request; |
|
80 | 33 | $this->manager = $manager; |
|
81 | 33 | $this->config_text = $config_text; |
|
82 | 33 | $this->config = $config; |
|
83 | 33 | $this->group_helper = $group_helper; |
|
84 | 33 | $this->input = $input; |
|
85 | 33 | $this->helper = $helper; |
|
86 | 33 | $this->analyser = $analyser; |
|
87 | |||
88 | 33 | $this->language->add_lang('posting'); // Used by banner_upload() file errors |
|
89 | 33 | $this->language->add_lang('acp', 'phpbb/ads'); |
|
90 | |||
91 | 33 | $this->template->assign_var('S_PHPBB_ADS', true); |
|
92 | |||
93 | 33 | if (!class_exists('auth_admin')) |
|
94 | 33 | { |
|
95 | 1 | include($root_path . 'includes/acp/auth.' . $php_ext); |
|
96 | 1 | } |
|
97 | 33 | $this->auth_admin = new \auth_admin(); |
|
98 | 33 | } |
|
99 | |||
100 | /** |
||
101 | * Set page url |
||
102 | * |
||
103 | * @param string $u_action Custom form action |
||
104 | * @return void |
||
105 | */ |
||
106 | 27 | public function set_page_url($u_action) |
|
107 | { |
||
108 | 27 | $this->u_action = $u_action; |
|
109 | 27 | } |
|
110 | |||
111 | /** |
||
112 | * Get ACP page title for Ads module |
||
113 | * |
||
114 | * @return string Language string for Ads ACP module |
||
115 | */ |
||
116 | 1 | public function get_page_title() |
|
117 | { |
||
118 | 1 | return $this->language->lang('ACP_PHPBB_ADS_TITLE'); |
|
119 | } |
||
120 | |||
121 | /** |
||
122 | * Process user request for settings mode |
||
123 | * |
||
124 | * @return void |
||
125 | */ |
||
126 | 3 | public function mode_settings() |
|
127 | { |
||
128 | 3 | if ($this->request->is_set_post('submit')) |
|
129 | 3 | { |
|
130 | // Validate form key |
||
131 | 2 | if (check_form_key('phpbb_ads')) |
|
132 | 2 | { |
|
133 | 1 | $this->config->set('phpbb_ads_adblocker_message', $this->request->variable('adblocker_message', 0)); |
|
134 | 1 | $this->config->set('phpbb_ads_enable_views', $this->request->variable('enable_views', 0)); |
|
135 | 1 | $this->config->set('phpbb_ads_enable_clicks', $this->request->variable('enable_clicks', 0)); |
|
136 | 1 | $this->config_text->set('phpbb_ads_hide_groups', json_encode($this->request->variable('hide_groups', array(0)))); |
|
137 | |||
138 | 1 | $this->success('ACP_AD_SETTINGS_SAVED'); |
|
139 | } |
||
140 | |||
141 | 1 | $this->error('FORM_INVALID'); |
|
142 | } |
||
143 | |||
144 | 1 | $hide_groups = json_decode($this->config_text->get('phpbb_ads_hide_groups'), true); |
|
145 | 1 | $groups = $this->manager->load_groups(); |
|
146 | 1 | View Code Duplication | foreach ($groups as $group) |
147 | { |
||
148 | 1 | $this->template->assign_block_vars('groups', array( |
|
149 | 1 | 'ID' => $group['group_id'], |
|
150 | 1 | 'NAME' => $this->group_helper->get_name($group['group_name']), |
|
151 | 1 | 'S_SELECTED' => in_array($group['group_id'], $hide_groups), |
|
152 | 1 | )); |
|
153 | 1 | } |
|
154 | |||
155 | 1 | $this->template->assign_vars(array( |
|
156 | 1 | 'U_ACTION' => $this->u_action, |
|
157 | 1 | 'ADBLOCKER_MESSAGE' => $this->config['phpbb_ads_adblocker_message'], |
|
158 | 1 | 'ENABLE_VIEWS' => $this->config['phpbb_ads_enable_views'], |
|
159 | 1 | 'ENABLE_CLICKS' => $this->config['phpbb_ads_enable_clicks'], |
|
160 | 1 | )); |
|
161 | 1 | } |
|
162 | |||
163 | /** |
||
164 | * Process user request for manage mode |
||
165 | * |
||
166 | * @return void |
||
167 | */ |
||
168 | 29 | public function mode_manage() |
|
182 | |||
183 | /** |
||
184 | * Add an advertisement |
||
185 | * |
||
186 | * @return void |
||
187 | */ |
||
188 | 16 | protected function action_add() |
|
189 | { |
||
190 | 6 | $action = $this->get_submitted_action(); |
|
191 | 6 | if ($action !== false) |
|
192 | 6 | { |
|
193 | 5 | $this->data = $this->input->get_form_data(); |
|
194 | 5 | $this->{$action}(); |
|
195 | 4 | $this->helper->assign_data($this->data, $this->input->get_errors()); |
|
196 | 16 | } |
|
197 | else |
||
198 | { |
||
199 | 1 | $this->helper->assign_locations(); |
|
200 | } |
||
201 | |||
202 | // Set output vars for display in the template |
||
203 | 5 | $this->template->assign_vars(array( |
|
204 | 5 | 'S_ADD_AD' => true, |
|
205 | 5 | 'U_BACK' => $this->u_action, |
|
206 | 5 | 'U_ACTION' => "{$this->u_action}&action=add", |
|
207 | 5 | 'PICKER_DATE_FORMAT' => ext::DATE_FORMAT, |
|
208 | 5 | 'U_FIND_USERNAME' => $this->helper->get_find_username_link(), |
|
209 | 5 | )); |
|
210 | 5 | } |
|
211 | |||
212 | /** |
||
213 | * Edit an advertisement |
||
214 | * |
||
215 | * @return void |
||
216 | */ |
||
217 | 7 | protected function action_edit() |
|
218 | { |
||
219 | 7 | $ad_id = $this->request->variable('id', 0); |
|
220 | 7 | $action = $this->get_submitted_action(); |
|
221 | 7 | if ($action !== false) |
|
222 | 7 | { |
|
223 | 5 | $this->data = $this->input->get_form_data(); |
|
224 | 5 | $this->{$action}(); |
|
225 | 3 | } |
|
226 | else |
||
227 | { |
||
228 | 2 | $this->data = $this->manager->get_ad($ad_id); |
|
229 | 2 | if (empty($this->data)) |
|
230 | 2 | { |
|
231 | 1 | $this->error('ACP_AD_DOES_NOT_EXIST'); |
|
232 | } |
||
233 | // Load ad template locations |
||
234 | 1 | $this->data['ad_locations'] = $this->manager->get_ad_locations($ad_id); |
|
235 | } |
||
236 | |||
237 | // Set output vars for display in the template |
||
238 | 4 | $this->template->assign_vars(array( |
|
239 | 4 | 'S_EDIT_AD' => true, |
|
240 | 4 | 'EDIT_ID' => $ad_id, |
|
241 | 4 | 'U_BACK' => $this->u_action, |
|
242 | 4 | 'U_ACTION' => "{$this->u_action}&action=edit&id=$ad_id", |
|
243 | 4 | 'PICKER_DATE_FORMAT' => ext::DATE_FORMAT, |
|
244 | 4 | 'U_FIND_USERNAME' => $this->helper->get_find_username_link(), |
|
245 | 4 | )); |
|
246 | 4 | $this->helper->assign_data($this->data, $this->input->get_errors()); |
|
247 | 4 | } |
|
248 | |||
249 | /** |
||
250 | * Enable an advertisement |
||
251 | * |
||
252 | * @return void |
||
253 | */ |
||
254 | 4 | protected function action_enable() |
|
255 | { |
||
256 | 4 | $this->ad_enable(true); |
|
257 | 1 | } |
|
258 | |||
259 | /** |
||
260 | * Disable an advertisement |
||
261 | * |
||
262 | * @return void |
||
263 | */ |
||
264 | 4 | protected function action_disable() |
|
265 | { |
||
266 | 4 | $this->ad_enable(false); |
|
267 | 1 | } |
|
268 | |||
269 | /** |
||
270 | * Delete an advertisement |
||
271 | * |
||
272 | * @return void |
||
273 | */ |
||
274 | 3 | protected function action_delete() |
|
275 | { |
||
276 | 3 | $ad_id = $this->request->variable('id', 0); |
|
277 | if ($ad_id) |
||
278 | 3 | { |
|
279 | 3 | if (confirm_box(true)) |
|
280 | 3 | { |
|
281 | // Get ad data so that we can log ad name |
||
282 | 2 | $ad_data = $this->manager->get_ad($ad_id); |
|
283 | |||
284 | // Delete ad and it's template locations |
||
285 | 2 | $this->manager->delete_ad_locations($ad_id); |
|
286 | 2 | $success = $this->manager->delete_ad($ad_id); |
|
287 | |||
288 | 2 | $this->toggle_permission($ad_data['ad_owner']); |
|
289 | |||
290 | // Only notify user on error or if not ajax |
||
291 | 2 | if (!$success) |
|
292 | 2 | { |
|
293 | 1 | $this->error('ACP_AD_DELETE_ERRORED'); |
|
294 | } |
||
295 | else |
||
296 | { |
||
297 | 1 | $this->helper->log('DELETE', $ad_data['ad_name']); |
|
298 | |||
299 | 1 | if (!$this->request->is_ajax()) |
|
300 | 1 | { |
|
301 | 1 | $this->success('ACP_AD_DELETE_SUCCESS'); |
|
302 | } |
||
303 | } |
||
304 | } |
||
305 | else |
||
306 | { |
||
307 | 1 | confirm_box(false, $this->language->lang('CONFIRM_OPERATION'), build_hidden_fields(array( |
|
308 | 1 | 'id' => $ad_id, |
|
309 | 1 | 'i' => $this->request->variable('i', ''), |
|
310 | 1 | 'mode' => $this->request->variable('mode', ''), |
|
311 | 1 | 'action' => 'delete', |
|
312 | 1 | ))); |
|
313 | } |
||
314 | 1 | } |
|
315 | 1 | } |
|
316 | |||
317 | /** |
||
318 | * Display the list of all ads |
||
319 | * |
||
320 | * @return void |
||
321 | */ |
||
322 | 1 | protected function list_ads() |
|
323 | { |
||
324 | 1 | foreach ($this->manager->get_all_ads() as $row) |
|
325 | { |
||
326 | 1 | $ad_enabled = (int) $row['ad_enabled']; |
|
327 | 1 | $ad_expired = $this->helper->is_expired($row); |
|
328 | |||
329 | 1 | View Code Duplication | if ($ad_expired && $ad_enabled) |
|
|||
330 | 1 | { |
|
331 | 1 | $ad_enabled = 0; |
|
332 | 1 | $this->manager->update_ad($row['ad_id'], array('ad_enabled' => 0)); |
|
333 | 1 | } |
|
334 | |||
335 | 1 | $this->template->assign_block_vars($ad_expired ? 'expired' : 'ads', array( |
|
336 | 1 | 'NAME' => $row['ad_name'], |
|
337 | 1 | 'PRIORITY' => $row['ad_priority'], |
|
338 | 1 | 'END_DATE' => $row['ad_end_date'], |
|
339 | 1 | 'VIEWS' => $row['ad_views'], |
|
340 | 1 | 'CLICKS' => $row['ad_clicks'], |
|
341 | 1 | 'VIEWS_LIMIT' => $row['ad_views_limit'], |
|
342 | 1 | 'CLICKS_LIMIT' => $row['ad_clicks_limit'], |
|
343 | 1 | 'S_EXPIRED' => $ad_expired, |
|
344 | 1 | 'S_ENABLED' => $ad_enabled, |
|
345 | 1 | 'U_ENABLE' => $this->u_action . '&action=' . ($ad_enabled ? 'disable' : 'enable') . '&id=' . $row['ad_id'], |
|
346 | 1 | 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['ad_id'], |
|
347 | 1 | 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['ad_id'], |
|
348 | 1 | )); |
|
349 | 1 | } |
|
350 | |||
351 | // Set output vars for display in the template |
||
352 | 1 | $this->template->assign_vars(array( |
|
353 | 1 | 'U_ACTION_ADD' => $this->u_action . '&action=add', |
|
354 | 1 | 'S_VIEWS_ENABLED' => $this->config['phpbb_ads_enable_views'], |
|
355 | 1 | 'S_CLICKS_ENABLED' => $this->config['phpbb_ads_enable_clicks'], |
|
356 | 1 | )); |
|
357 | 1 | } |
|
358 | |||
359 | /** |
||
360 | * Get what action user wants to do with the form. |
||
361 | * Possible options are: |
||
362 | * - preview ad code |
||
363 | * - upload banner to display in an ad code |
||
364 | * - analyse ad code |
||
365 | * - submit form (either add or edit an ad) |
||
366 | * |
||
367 | * @return string|false Action name or false when no action was submitted |
||
368 | */ |
||
369 | 13 | protected function get_submitted_action() |
|
382 | |||
383 | /** |
||
384 | * Enable/disable an advertisement |
||
385 | * |
||
386 | * @param bool $enable Enable or disable the advertisement? |
||
387 | * @return void |
||
388 | */ |
||
389 | 6 | protected function ad_enable($enable) |
|
417 | |||
418 | /** |
||
419 | * Submit action "preview". |
||
420 | * Prepare advertisement preview. |
||
421 | * |
||
422 | * @return void |
||
423 | */ |
||
424 | 2 | protected function preview() |
|
428 | |||
429 | /** |
||
430 | * Submit action "upload_banner". |
||
431 | * Upload banner and append it to the ad code. |
||
432 | * |
||
433 | * @return void |
||
434 | */ |
||
435 | 1 | protected function upload_banner() |
|
439 | |||
440 | /** |
||
441 | * Submit action "analyse_ad_code". |
||
442 | * Upload banner and append it to the ad code. |
||
443 | * |
||
444 | * @return void |
||
445 | */ |
||
446 | 1 | protected function analyse_ad_code() |
|
450 | |||
451 | /** |
||
452 | * Submit action "submit_add". |
||
453 | * Add new ad. |
||
454 | * |
||
455 | * @return void |
||
456 | */ |
||
457 | 2 | protected function submit_add() |
|
458 | { |
||
459 | 2 | if (!$this->input->has_errors()) |
|
460 | 2 | { |
|
470 | |||
471 | /** |
||
472 | * Submit action "submit_edit". |
||
473 | * Edit ad. |
||
474 | * |
||
475 | * @return void |
||
476 | */ |
||
477 | 4 | protected function submit_edit() |
|
502 | |||
503 | /** |
||
504 | * Print success message. |
||
505 | * |
||
506 | * @param string $msg Message lang key |
||
507 | */ |
||
508 | 6 | protected function success($msg) |
|
512 | |||
513 | /** |
||
514 | * Print error message. |
||
515 | * |
||
516 | * @param string $msg Message lang key |
||
517 | */ |
||
518 | 6 | protected function error($msg) |
|
522 | |||
523 | /** |
||
524 | * Try to remove or add permission to see UCP module. |
||
525 | * Permission is only removed when user has no more ads. |
||
526 | * Permission is only added when user has at least one ad. |
||
527 | * |
||
528 | * @param int $user_id User ID to try to remove permission |
||
529 | * |
||
530 | * @return void |
||
531 | */ |
||
532 | 4 | protected function toggle_permission($user_id) |
|
538 | } |
||
539 |
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.