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 |
||
| 18 | class main_controller |
||
| 19 | { |
||
| 20 | /** @var \phpbb\config\config */ |
||
| 21 | protected $config; |
||
| 22 | /** @var \phpbb\controller\helper */ |
||
| 23 | protected $helper; |
||
| 24 | /** @var \phpbb\template\template */ |
||
| 25 | protected $template; |
||
| 26 | /** @var \phpbb\user */ |
||
| 27 | protected $user; |
||
| 28 | /** @var string phpBB root path */ |
||
| 29 | protected $root_path; |
||
| 30 | /** @var string phpEx */ |
||
| 31 | protected $php_ext; |
||
| 32 | |||
| 33 | /** @var \phpbb\request\request */ |
||
| 34 | private $request; |
||
| 35 | |||
| 36 | /** @var \phpbb\db\driver\driver_interface */ |
||
| 37 | private $db; |
||
| 38 | |||
| 39 | /** @var \phpbb\auth\auth */ |
||
| 40 | private $auth; |
||
| 41 | |||
| 42 | /** @var \paul999\ajaxshoutbox\actions\Delete */ |
||
| 43 | private $delete; |
||
| 44 | |||
| 45 | /** @var string */ |
||
| 46 | private $table; |
||
| 47 | |||
| 48 | /** @var string */ |
||
| 49 | private $usertable; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * @param \phpbb\config\config $config |
||
| 53 | * @param \phpbb\controller\helper $helper |
||
| 54 | * @param \phpbb\template\template $template |
||
| 55 | * @param \phpbb\user $user |
||
| 56 | * @param \phpbb\request\request $request |
||
| 57 | * @param \phpbb\db\driver\driver_interface $db |
||
| 58 | * @param \phpbb\auth\auth $auth |
||
| 59 | * @param \paul999\ajaxshoutbox\actions\delete $delete |
||
| 60 | * @param string $root_path |
||
| 61 | * @param string $php_ext |
||
| 62 | * @param string $table |
||
| 63 | * @param string $usertable |
||
| 64 | */ |
||
| 65 | public function __construct(\phpbb\config\config $config, \phpbb\controller\helper $helper, |
||
| 66 | \phpbb\template\template $template, \phpbb\user $user, \phpbb\request\request $request, |
||
| 67 | \phpbb\db\driver\driver_interface $db, \phpbb\auth\auth $auth, |
||
| 68 | \paul999\ajaxshoutbox\actions\delete $delete, |
||
| 69 | $root_path, $php_ext, $table, $usertable) |
||
| 70 | { |
||
| 71 | $this->config = $config; |
||
| 72 | $this->helper = $helper; |
||
| 73 | $this->template = $template; |
||
| 74 | $this->user = $user; |
||
| 75 | $this->request = $request; |
||
| 76 | $this->db = $db; |
||
| 77 | $this->auth = $auth; |
||
| 78 | $this->delete = $delete; |
||
| 79 | $this->root_path = $root_path; |
||
| 80 | $this->php_ext = $php_ext; |
||
| 81 | $this->table = $table; |
||
| 82 | $this->usertable = $usertable; |
||
| 83 | |||
| 84 | $this->user->add_lang_ext("paul999/ajaxshoutbox", "ajax_shoutbox"); |
||
| 85 | } |
||
| 86 | |||
| 87 | /** |
||
| 88 | * Validate the push connection with shoutbox-app.com |
||
| 89 | * |
||
| 90 | * @param $id |
||
| 91 | * |
||
| 92 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 93 | */ |
||
| 94 | public function validate($id) |
||
| 95 | { |
||
| 96 | $result = array(); |
||
| 97 | |||
| 98 | // Language used here won't be seen by the user. |
||
| 99 | // It is used on shoutbox-app.com to specify the result. |
||
| 100 | // Do not change. |
||
| 101 | if ($this->config['ajaxshoutbox_push_enabled']) |
||
| 102 | { |
||
| 103 | if ($id == $this->config['ajaxshoutbox_validation_id']) |
||
| 104 | { |
||
| 105 | $result['ok'] = 'ok'; |
||
| 106 | $result['key'] = $this->config['ajaxshoutbox_validation_id']; |
||
| 107 | } |
||
| 108 | else |
||
| 109 | { |
||
| 110 | $result['error'] = 'Incorrect key'; |
||
| 111 | } |
||
| 112 | } |
||
| 113 | else |
||
| 114 | { |
||
| 115 | $result['error'] = 'disabled'; |
||
| 116 | } |
||
| 117 | |||
| 118 | return new JsonResponse(array($result)); |
||
| 119 | } |
||
| 120 | |||
| 121 | /** |
||
| 122 | * Post a new message to the shoutbox. |
||
| 123 | * |
||
| 124 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 125 | */ |
||
| 126 | public function post() |
||
| 127 | { |
||
| 128 | // We always disallow guests to post in the shoutbox. |
||
| 129 | if (!$this->auth->acl_get('u_shoutbox_post') || $this->user->data['user_id'] == ANONYMOUS) |
||
| 130 | { |
||
| 131 | return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_NO_PERMISSION', 403); |
||
| 132 | } |
||
| 133 | |||
| 134 | if (!check_form_key('ajaxshoutbox_posting', 3600 * 12)) // Allow 12 hours. |
||
| 135 | { |
||
| 136 | return $this->error('AJAX_SHOUTBOX_ERROR', 'FORM_INVALID', 500); |
||
| 137 | } |
||
| 138 | |||
| 139 | if ($this->request->is_ajax()) |
||
| 140 | { |
||
| 141 | $message = $msg = trim($this->request->variable('text_shoutbox', '', true)); |
||
| 142 | |||
| 143 | if (empty($message)) |
||
| 144 | { |
||
| 145 | return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_MESSAGE_EMPTY', 500); |
||
| 146 | } |
||
| 147 | |||
| 148 | $uid = $bitfield = $options = ''; |
||
| 149 | $allow_bbcode = $this->auth->acl_get('u_shoutbox_bbcode'); |
||
| 150 | $allow_urls = $allow_smilies = true; |
||
| 151 | |||
| 152 | if (!function_exists('generate_text_for_storage')) |
||
| 153 | { |
||
| 154 | include($this->root_path . 'includes/functions_content.' . $this->php_ext); |
||
| 155 | } |
||
| 156 | |||
| 157 | generate_text_for_storage($message, $uid, $bitfield, $options, $allow_bbcode, $allow_urls, $allow_smilies); |
||
| 158 | |||
| 159 | $insert = array( |
||
| 160 | 'post_message' => $message, |
||
| 161 | 'post_time' => time(), |
||
| 162 | 'user_id' => $this->user->data['user_id'], |
||
| 163 | 'bbcode_options' => $options, |
||
| 164 | 'bbcode_bitfield' => $bitfield, |
||
| 165 | 'bbcode_uid' => $uid, |
||
| 166 | ); |
||
| 167 | $sql = 'INSERT INTO ' . $this->table . ' ' . $this->db->sql_build_array('INSERT', $insert); |
||
| 168 | $this->db->sql_query($sql); |
||
| 169 | |||
| 170 | return new JsonResponse(array('OK')); |
||
| 171 | } |
||
| 172 | else |
||
| 173 | { |
||
| 174 | return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_ONLY_AJAX', 500); |
||
| 175 | } |
||
| 176 | } |
||
| 177 | |||
| 178 | /** |
||
| 179 | * Delete a post from the client. |
||
| 180 | * |
||
| 181 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 182 | */ |
||
| 183 | public function delete() |
||
| 184 | { |
||
| 185 | $id = $this->request->variable('id', 0, false, \phpbb\request\request_interface::POST); |
||
| 186 | |||
| 187 | if (!$id) |
||
| 188 | { |
||
| 189 | return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_MISSING_ID', 500); |
||
| 190 | } |
||
| 191 | |||
| 192 | if (!check_form_key('ajaxshoutbox_delete_' . $id)) // Every delete form has its unique form key, based on ID. |
||
| 193 | { |
||
| 194 | return $this->error('AJAX_SHOUTBOX_ERROR', 'FORM_INVALID', 500); |
||
| 195 | } |
||
| 196 | |||
| 197 | try |
||
| 198 | { |
||
| 199 | $this->delete->delete_post($id); |
||
| 200 | } |
||
| 201 | catch (\paul999\ajaxshoutbox\exceptions\shoutbox_exception $exception) |
||
| 202 | { |
||
| 203 | return $this->error('AJAX_SHOUTBOX_ERROR', $exception->getMessage(), 500); |
||
| 204 | } |
||
| 205 | return new JsonResponse(array('OK')); |
||
| 206 | } |
||
| 207 | |||
| 208 | /** |
||
| 209 | * Get the last 10 shouts |
||
| 210 | * |
||
| 211 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 212 | */ |
||
| 213 | public function getAll() |
||
| 214 | { |
||
| 215 | if (!$this->auth->acl_get('u_shoutbox_view')) |
||
| 216 | { |
||
| 217 | return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_NO_PERMISSION', 403); |
||
| 218 | } |
||
| 219 | |||
| 220 | $sql = 'SELECT c.*, u.username, u.user_colour FROM |
||
| 221 | ' . $this->table . ' c, |
||
| 222 | ' . $this->usertable . ' u |
||
| 223 | WHERE |
||
| 224 | u.user_id = c.user_id |
||
| 225 | ORDER BY post_time DESC'; |
||
| 226 | $result = $this->db->sql_query_limit($sql, 10); |
||
| 227 | |||
| 228 | return $this->returnPosts($result); |
||
| 229 | } |
||
| 230 | |||
| 231 | /** |
||
| 232 | * Get all shouts since a specific shout ID. |
||
| 233 | * |
||
| 234 | * @param int $id Last selected ID. |
||
| 235 | * |
||
| 236 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 237 | */ |
||
| 238 | View Code Duplication | public function getAfter($id) |
|
| 259 | |||
| 260 | /** |
||
| 261 | * Get 10 shouts before the current shout ID. |
||
| 262 | * |
||
| 263 | * @param $id |
||
| 264 | * |
||
| 265 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 266 | */ |
||
| 267 | View Code Duplication | public function getBefore($id) |
|
| 288 | |||
| 289 | /** |
||
| 290 | * Loop over a SQL result set, and generate a JSON array based on the post data. |
||
| 291 | * |
||
| 292 | * @param mixed $result return the data for the posts |
||
| 293 | * @param bool $reverse |
||
| 294 | * |
||
| 295 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 296 | */ |
||
| 297 | private function returnPosts($result, $reverse = true) |
||
| 309 | |||
| 310 | /** |
||
| 311 | * Generate a array with the specific post for this shout. |
||
| 312 | * |
||
| 313 | * @param array $row Input row |
||
| 314 | * |
||
| 315 | * @return array output |
||
| 316 | */ |
||
| 317 | private function getPost($row) |
||
| 342 | |||
| 343 | /** |
||
| 344 | * Send a error to the user. |
||
| 345 | * |
||
| 346 | * Important: phpBB (<= 3.1.2) handles non 200 status as error. |
||
| 347 | * Due to the way this is implemented, phpBB will display the browser |
||
| 348 | * generated error, instead of the user returned error. |
||
| 349 | * This method will result in a 200 OK, but the correct status is in |
||
| 350 | * the JsonResponse.status. |
||
| 351 | * |
||
| 352 | * @param string $title |
||
| 353 | * @param string $message |
||
| 354 | * @param integer $status |
||
| 355 | * |
||
| 356 | * @return \Symfony\Component\HttpFoundation\JsonResponse |
||
| 357 | */ |
||
| 358 | private function error($title, $message, $status) |
||
| 368 | |||
| 369 | /** |
||
| 370 | * Add a secret token and returns it as array with creation_time and form_token. |
||
| 371 | * |
||
| 372 | * Based on phpBB's add_form_key. Compatible with check_form_key. |
||
| 373 | * |
||
| 374 | * IMPORTANT: The original event is not included, because the form is build before the event, |
||
| 375 | * while this function returns the (Possible modified) data after the event. |
||
| 376 | * |
||
| 377 | * @param string $form_name The name of the form; has to match the name used in check_form_key, otherwise no |
||
| 378 | * restrictions apply |
||
| 379 | * |
||
| 380 | * @return array |
||
| 381 | */ |
||
| 382 | function add_form_key($form_name) |
||
| 393 | } |
||
| 394 |
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.