| Total Complexity | 67 |
| Total Lines | 412 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
Complex classes like PortalArticles_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.
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 PortalArticles_Controller, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 20 | class PortalArticles_Controller extends Action_Controller |
||
| 21 | { |
||
| 22 | /** |
||
| 23 | * This method is executed before any action handler. |
||
| 24 | * Loads common things for all methods |
||
| 25 | */ |
||
| 26 | public function pre_dispatch() |
||
| 30 | } |
||
| 31 | |||
| 32 | /** |
||
| 33 | * Default method |
||
| 34 | */ |
||
| 35 | public function action_index() |
||
| 52 | } |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Load all articles for selection, not used just yet |
||
| 56 | */ |
||
| 57 | public function action_sportal_articles() |
||
| 58 | { |
||
| 59 | global $context, $scripturl, $txt, $modSettings; |
||
| 60 | |||
| 61 | // Set up for pagination |
||
| 62 | $total_articles = sportal_get_articles_count(); |
||
| 63 | $per_page = min($total_articles, !empty($modSettings['sp_articles_per_page']) ? $modSettings['sp_articles_per_page'] : 10); |
||
| 64 | $start = !empty($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0; |
||
| 65 | |||
| 66 | if ($total_articles > $per_page) |
||
| 67 | { |
||
| 68 | $context['page_index'] = constructPageIndex($scripturl . '?action=portal;sa=articles;start=%1$d', $start, $total_articles, $per_page, true); |
||
| 69 | } |
||
| 70 | |||
| 71 | // Fetch the article page |
||
| 72 | $context['articles'] = sportal_get_articles(0, true, true, 'spa.id_article DESC', 0, $per_page, $start); |
||
| 73 | foreach ($context['articles'] as $article) |
||
| 74 | { |
||
| 75 | $context['articles'][$article['id']]['preview'] = censor($article['body']); |
||
| 76 | $context['articles'][$article['id']]['date'] = htmlTime($article['date']); |
||
| 77 | $context['articles'][$article['id']]['time'] = $article['date']; |
||
| 78 | |||
| 79 | // Parse and cut as needed |
||
| 80 | $context['articles'][$article['id']]['cut'] = sportal_parse_cutoff_content($context['articles'][$article['id']]['preview'], $article['type'], $modSettings['sp_articles_length'], $context['articles'][$article['id']]['article_id']); |
||
| 81 | } |
||
| 82 | |||
| 83 | // Auto video embedding enabled? |
||
| 84 | if (!empty($modSettings['enableVideoEmbeding'])) |
||
| 85 | { |
||
| 86 | addInlineJavascript(' |
||
| 87 | $(document).ready(function() { |
||
| 88 | $().linkifyvideo(oEmbedtext); |
||
| 89 | });', true |
||
| 90 | ); |
||
| 91 | } |
||
| 92 | |||
| 93 | $context['linktree'][] = array( |
||
| 94 | 'url' => $scripturl . '?action=portal;sa=articles', |
||
| 95 | 'name' => $txt['sp-articles'], |
||
| 96 | ); |
||
| 97 | |||
| 98 | $context['page_title'] = $txt['sp-articles']; |
||
| 99 | $context['sub_template'] = 'view_articles'; |
||
| 100 | } |
||
| 101 | |||
| 102 | /** |
||
| 103 | * Display a chosen article, called from frontpage hook |
||
| 104 | * |
||
| 105 | * - Update the stats, like #views etc |
||
| 106 | */ |
||
| 107 | public function action_sportal_article() |
||
| 108 | { |
||
| 109 | global $context, $scripturl, $user_info, $modSettings; |
||
| 110 | |||
| 111 | $article_id = !empty($_REQUEST['article']) ? $_REQUEST['article'] : 0; |
||
| 112 | |||
| 113 | if (!is_int($article_id)) |
||
| 114 | { |
||
| 115 | $article_id = Util::htmlspecialchars($article_id, ENT_QUOTES); |
||
| 116 | } |
||
| 117 | |||
| 118 | // Fetch and render the article |
||
| 119 | $context['article'] = sportal_get_articles($article_id, true, true); |
||
| 120 | if (empty($context['article']['id'])) |
||
| 121 | { |
||
| 122 | throw new Elk_Exception('error_sp_article_not_found', false); |
||
| 123 | } |
||
| 124 | |||
| 125 | $context['article']['style'] = sportal_select_style($context['article']['styles']); |
||
| 126 | $context['article']['body'] = censor($context['article']['body']); |
||
| 127 | $context['article']['body'] = sportal_parse_content($context['article']['body'], $context['article']['type'], 'return'); |
||
| 128 | |||
| 129 | // Fetch attachments, if there are any |
||
| 130 | if (!empty($modSettings['attachmentEnable']) && !empty($context['article']['has_attachments'])) |
||
| 131 | { |
||
| 132 | loadJavascriptFile('topic.js'); |
||
| 133 | $context['article']['attachment'] = sportal_load_attachment_context($context['article']['id']); |
||
| 134 | } |
||
| 135 | |||
| 136 | // Set up for the comment pagination |
||
| 137 | $total_comments = sportal_get_article_comment_count($context['article']['id']); |
||
| 138 | $per_page = min($total_comments, !empty($modSettings['sp_articles_comments_per_page']) ? $modSettings['sp_articles_comments_per_page'] : 20); |
||
| 139 | $start = !empty($_REQUEST['comments']) ? (int) $_REQUEST['comments'] : 0; |
||
| 140 | |||
| 141 | if ($total_comments > $per_page) |
||
| 142 | { |
||
| 143 | $context['page_index'] = constructPageIndex($scripturl . '?article=' . $context['article']['article_id'] . ';comments=%1$d', $start, $total_comments, $per_page, true); |
||
| 144 | } |
||
| 145 | |||
| 146 | // Load in all the comments for the article |
||
| 147 | $context['article']['comments'] = sportal_get_comments($context['article']['id'], $per_page, $start); |
||
| 148 | |||
| 149 | // Prepare the final template details |
||
| 150 | $context['article']['time'] = $context['article']['date']; |
||
| 151 | $context['article']['date'] = htmlTime($context['article']['date']); |
||
| 152 | $context['article']['can_comment'] = $context['user']['is_logged']; |
||
| 153 | $context['article']['can_moderate'] = allowedTo('sp_admin') || allowedTo('sp_manage_articles'); |
||
| 154 | |||
| 155 | // Commenting, new or an update perhaps |
||
| 156 | if ($context['article']['can_comment'] && !empty($_POST['body'])) |
||
| 157 | { |
||
| 158 | checkSession(); |
||
| 159 | sp_prevent_flood('spacp', false); |
||
| 160 | |||
| 161 | require_once(SUBSDIR . '/Post.subs.php'); |
||
| 162 | |||
| 163 | // Prep the body / comment |
||
| 164 | $body = Util::htmlspecialchars(trim($_POST['body'])); |
||
| 165 | $preparse = PreparseCode::instance(); |
||
| 166 | $preparse->preparsecode($body, false); |
||
| 167 | |||
| 168 | // Update or add a new comment |
||
| 169 | $parser = ParserWrapper::instance(); |
||
| 170 | if (!empty($body) && trim(strip_tags($parser->parseMessage($body, false), '<img>')) !== '') |
||
| 171 | { |
||
| 172 | if (!empty($_POST['comment'])) |
||
| 173 | { |
||
| 174 | list ($comment_id, $author_id,) = sportal_fetch_article_comment((int) $_POST['comment']); |
||
| 175 | if (empty($comment_id) || (!$context['article']['can_moderate'] && $user_info['id'] != $author_id)) |
||
| 176 | { |
||
| 177 | throw new Elk_Exception('error_sp_cannot_comment_modify', false); |
||
| 178 | } |
||
| 179 | |||
| 180 | sportal_modify_article_comment($comment_id, $body); |
||
| 181 | } |
||
| 182 | else |
||
| 183 | { |
||
| 184 | sportal_create_article_comment($context['article']['id'], $body); |
||
| 185 | } |
||
| 186 | } |
||
| 187 | |||
| 188 | // Set a anchor |
||
| 189 | $anchor = '#comment' . (!empty($comment_id) ? $comment_id : ($total_comments > 0 ? $total_comments - 1 : 1)); |
||
| 190 | redirectexit('article=' . $context['article']['article_id'] . $anchor); |
||
| 191 | } |
||
| 192 | |||
| 193 | // Prepare to edit an existing comment |
||
| 194 | if ($context['article']['can_comment'] && !empty($_GET['modify'])) |
||
| 195 | { |
||
| 196 | checkSession('get'); |
||
| 197 | |||
| 198 | list ($comment_id, $author_id, $body) = sportal_fetch_article_comment((int) $_GET['modify']); |
||
| 199 | if (empty($comment_id) || (!$context['article']['can_moderate'] && $user_info['id'] != $author_id)) |
||
| 200 | { |
||
| 201 | throw new Elk_Exception('error_sp_cannot_comment_modify', false); |
||
| 202 | } |
||
| 203 | |||
| 204 | require_once(SUBSDIR . '/Post.subs.php'); |
||
| 205 | |||
| 206 | $context['article']['comment'] = array( |
||
| 207 | 'id' => $comment_id, |
||
| 208 | 'body' => str_replace(array('"', '<', '>', ' '), array('"', '<', '>', ' '), un_preparsecode($body)), |
||
| 209 | ); |
||
| 210 | } |
||
| 211 | |||
| 212 | // Want to delete a comment? |
||
| 213 | if ($context['article']['can_comment'] && !empty($_GET['delete'])) |
||
| 214 | { |
||
| 215 | checkSession('get'); |
||
| 216 | |||
| 217 | if (sportal_delete_article_comment((int) $_GET['delete']) === false) |
||
| 218 | { |
||
| 219 | throw new Elk_Exception('error_sp_cannot_comment_delete', false); |
||
| 220 | } |
||
| 221 | |||
| 222 | redirectexit('article=' . $context['article']['article_id']); |
||
| 223 | } |
||
| 224 | |||
| 225 | // Increase the article view counter |
||
| 226 | if (empty($_SESSION['last_viewed_article']) || $_SESSION['last_viewed_article'] != $context['article']['id']) |
||
| 227 | { |
||
| 228 | sportal_increase_viewcount('article', $context['article']['id']); |
||
| 229 | $_SESSION['last_viewed_article'] = $context['article']['id']; |
||
| 230 | } |
||
| 231 | |||
| 232 | // Build the breadcrumbs |
||
| 233 | $context['linktree'] = array_merge($context['linktree'], array( |
||
| 234 | array( |
||
| 235 | 'url' => $scripturl . '?category=' . $context['article']['category']['category_id'], |
||
| 236 | 'name' => $context['article']['category']['name'], |
||
| 237 | ), |
||
| 238 | array( |
||
| 239 | 'url' => $scripturl . '?article=' . $context['article']['article_id'], |
||
| 240 | 'name' => $context['article']['title'], |
||
| 241 | ) |
||
| 242 | )); |
||
| 243 | |||
| 244 | // Auto video embedding enabled? |
||
| 245 | if (!empty($modSettings['enableVideoEmbeding'])) |
||
| 246 | { |
||
| 247 | addInlineJavascript(' |
||
| 248 | $(document).ready(function() { |
||
| 249 | $().linkifyvideo(oEmbedtext); |
||
| 250 | });', true |
||
| 251 | ); |
||
| 252 | } |
||
| 253 | |||
| 254 | // Needed for basic Lightbox functionality |
||
| 255 | loadJavascriptFile('topic.js', ['defer' => false]); |
||
| 256 | |||
| 257 | $context['description'] = trim(preg_replace('~<[^>]+>~', ' ', $context['article']['body'])); |
||
| 258 | $context['description'] = Util::shorten_text(preg_replace('~\s\s+| |"|'~', ' ', $context['description']), 384, true); |
||
| 259 | |||
| 260 | // Off to the template we go |
||
| 261 | $context['page_title'] = $context['article']['title']; |
||
| 262 | $context['sub_template'] = 'view_article'; |
||
| 263 | } |
||
| 264 | |||
| 265 | /** |
||
| 266 | * Downloads / shows an article attachment |
||
| 267 | * |
||
| 268 | * It requires the view_attachments permission. |
||
| 269 | * It disables the session parser, and clears any previous output. |
||
| 270 | * It is accessed via the query string ?action=portal;sa=spattach. |
||
| 271 | */ |
||
| 272 | public function action_sportal_attach() |
||
| 432 | } |
||
| 433 | } |
||
| 434 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.