| Total Complexity | 133 |
| Total Lines | 1084 |
| Duplicated Lines | 0 % |
| Changes | 8 | ||
| Bugs | 0 | Features | 1 |
Complex classes like ManagePortalArticles_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 ManagePortalArticles_Controller, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 20 | class ManagePortalArticles_Controller extends Action_Controller |
||
| 21 | { |
||
| 22 | /** @var bool|int hold the article id if existing */ |
||
| 23 | protected $_is_aid; |
||
| 24 | |||
| 25 | /** @var array */ |
||
| 26 | protected $_attachments; |
||
| 27 | |||
| 28 | /** @var ErrorContext */ |
||
| 29 | protected $article_errors; |
||
| 30 | |||
| 31 | /** @var AttachmentErrorContext */ |
||
| 32 | protected $attach_errors; |
||
| 33 | |||
| 34 | /** |
||
| 35 | * This method is executed before any action handler. |
||
| 36 | * Loads common things for all methods |
||
| 37 | */ |
||
| 38 | public function pre_dispatch() |
||
| 39 | { |
||
| 40 | // We'll need the utility functions from here. |
||
| 41 | require_once(SUBSDIR . '/PortalAdmin.subs.php'); |
||
| 42 | require_once(SUBSDIR . '/Portal.subs.php'); |
||
| 43 | require_once(SUBSDIR . '/PortalArticle.subs.php'); |
||
| 44 | } |
||
| 45 | |||
| 46 | /** |
||
| 47 | * Main article dispatcher. |
||
| 48 | * |
||
| 49 | * This function checks permissions and passes control through. |
||
| 50 | */ |
||
| 51 | public function action_index() |
||
| 52 | { |
||
| 53 | global $context, $txt; |
||
| 54 | |||
| 55 | // You need to be an admin or have manage article permissions |
||
| 56 | if (!allowedTo('sp_admin')) |
||
| 57 | { |
||
| 58 | isAllowedTo('sp_manage_articles'); |
||
| 59 | } |
||
| 60 | |||
| 61 | loadTemplate('PortalAdminArticles'); |
||
| 62 | |||
| 63 | // These are all the actions that we know |
||
| 64 | $subActions = array( |
||
| 65 | 'list' => array($this, 'action_list'), |
||
| 66 | 'add' => array($this, 'action_edit'), |
||
| 67 | 'edit' => array($this, 'action_edit'), |
||
| 68 | 'status' => array($this, 'action_status'), |
||
| 69 | 'delete' => array($this, 'action_delete'), |
||
| 70 | ); |
||
| 71 | |||
| 72 | // Start up the controller, provide a hook since we can |
||
| 73 | $action = new Action('portal_articles'); |
||
| 74 | |||
| 75 | // Set up the tab data |
||
| 76 | $context[$context['admin_menu_name']]['tab_data'] = array( |
||
| 77 | 'title' => $txt['sp_admin_articles_title'], |
||
| 78 | 'help' => 'sp_ArticlesArea', |
||
| 79 | 'description' => $txt['sp_admin_articles_desc'], |
||
| 80 | 'tabs' => array( |
||
| 81 | 'list' => array(), |
||
| 82 | 'add' => array(), |
||
| 83 | ), |
||
| 84 | ); |
||
| 85 | |||
| 86 | // By default we want to list articles |
||
| 87 | $subAction = $action->initialize($subActions, 'list'); |
||
| 88 | $context['sub_action'] = $subAction; |
||
| 89 | |||
| 90 | // Call the right function for this sub-action |
||
| 91 | $action->dispatch($subAction); |
||
| 92 | } |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Show a listing of articles in the system |
||
| 96 | */ |
||
| 97 | public function action_list() |
||
| 98 | { |
||
| 99 | global $context, $scripturl, $txt, $modSettings; |
||
| 100 | |||
| 101 | // Build the listoption array to display the categories |
||
| 102 | $listOptions = array( |
||
| 103 | 'id' => 'portal_articles', |
||
| 104 | 'title' => $txt['sp_admin_articles_list'], |
||
| 105 | 'items_per_page' => $modSettings['defaultMaxMessages'], |
||
| 106 | 'no_items_label' => $txt['error_sp_no_articles'], |
||
| 107 | 'base_href' => $scripturl . '?action=admin;area=portalarticles;sa=list;', |
||
| 108 | 'default_sort_col' => 'title', |
||
| 109 | 'get_items' => array( |
||
| 110 | 'function' => array($this, 'list_spLoadArticles'), |
||
| 111 | ), |
||
| 112 | 'get_count' => array( |
||
| 113 | 'function' => array($this, 'list_spCountArticles'), |
||
| 114 | ), |
||
| 115 | 'columns' => array( |
||
| 116 | 'title' => array( |
||
| 117 | 'header' => array( |
||
| 118 | 'value' => $txt['sp_admin_articles_col_title'], |
||
| 119 | ), |
||
| 120 | 'data' => array( |
||
| 121 | 'db' => 'title', |
||
| 122 | ), |
||
| 123 | 'sort' => array( |
||
| 124 | 'default' => 'title', |
||
| 125 | 'reverse' => 'title DESC', |
||
| 126 | ), |
||
| 127 | ), |
||
| 128 | 'namespace' => array( |
||
| 129 | 'header' => array( |
||
| 130 | 'value' => $txt['sp_admin_articles_col_namespace'], |
||
| 131 | ), |
||
| 132 | 'data' => array( |
||
| 133 | 'db' => 'article_id', |
||
| 134 | ), |
||
| 135 | 'sort' => array( |
||
| 136 | 'default' => 'article_namespace', |
||
| 137 | 'reverse' => 'article_namespace DESC', |
||
| 138 | ), |
||
| 139 | ), |
||
| 140 | 'category' => array( |
||
| 141 | 'header' => array( |
||
| 142 | 'value' => $txt['sp_admin_articles_col_category'], |
||
| 143 | ), |
||
| 144 | 'data' => array( |
||
| 145 | 'db' => 'category_name', |
||
| 146 | ), |
||
| 147 | 'sort' => array( |
||
| 148 | 'default' => 'name', |
||
| 149 | 'reverse' => 'name DESC', |
||
| 150 | ), |
||
| 151 | ), |
||
| 152 | 'author' => array( |
||
| 153 | 'header' => array( |
||
| 154 | 'value' => $txt['sp_admin_articles_col_author'], |
||
| 155 | ), |
||
| 156 | 'data' => array( |
||
| 157 | 'db' => 'author_name', |
||
| 158 | ), |
||
| 159 | 'sort' => array( |
||
| 160 | 'default' => 'author_name', |
||
| 161 | 'reverse' => 'author_name DESC', |
||
| 162 | ), |
||
| 163 | ), |
||
| 164 | 'type' => array( |
||
| 165 | 'header' => array( |
||
| 166 | 'value' => $txt['sp_admin_articles_col_type'], |
||
| 167 | ), |
||
| 168 | 'data' => array( |
||
| 169 | 'db' => 'type', |
||
| 170 | ), |
||
| 171 | 'sort' => array( |
||
| 172 | 'default' => 'type', |
||
| 173 | 'reverse' => 'type DESC', |
||
| 174 | ), |
||
| 175 | ), |
||
| 176 | 'date' => array( |
||
| 177 | 'header' => array( |
||
| 178 | 'value' => $txt['sp_admin_articles_col_date'], |
||
| 179 | ), |
||
| 180 | 'data' => array( |
||
| 181 | 'db' => 'date', |
||
| 182 | ), |
||
| 183 | 'sort' => array( |
||
| 184 | 'default' => 'date', |
||
| 185 | 'reverse' => 'date DESC', |
||
| 186 | ), |
||
| 187 | ), |
||
| 188 | 'status' => array( |
||
| 189 | 'header' => array( |
||
| 190 | 'value' => $txt['sp_admin_articles_col_status'], |
||
| 191 | 'class' => 'centertext', |
||
| 192 | ), |
||
| 193 | 'data' => array( |
||
| 194 | 'db' => 'status_image', |
||
| 195 | 'class' => 'centertext', |
||
| 196 | ), |
||
| 197 | 'sort' => array( |
||
| 198 | 'default' => 'status', |
||
| 199 | 'reverse' => 'status DESC', |
||
| 200 | ), |
||
| 201 | ), |
||
| 202 | 'action' => array( |
||
| 203 | 'header' => array( |
||
| 204 | 'value' => $txt['sp_admin_articles_col_actions'], |
||
| 205 | 'class' => 'centertext', |
||
| 206 | ), |
||
| 207 | 'data' => array( |
||
| 208 | 'sprintf' => array( |
||
| 209 | 'format' => ' |
||
| 210 | <a href="?action=admin;area=portalarticles;sa=edit;article_id=%1$s;' . $context['session_var'] . '=' . $context['session_id'] . '" accesskey="e">' . sp_embed_image('edit') . '</a> |
||
| 211 | <a href="?action=admin;area=portalarticles;sa=delete;article_id=%1$s;' . $context['session_var'] . '=' . $context['session_id'] . '" onclick="return confirm(' . JavaScriptEscape($txt['sp_admin_articles_delete_confirm']) . ') && submitThisOnce(this);" accesskey="d">' . sp_embed_image('trash') . '</a>', |
||
| 212 | 'params' => array( |
||
| 213 | 'id' => true, |
||
| 214 | ), |
||
| 215 | ), |
||
| 216 | 'class' => 'centertext nowrap', |
||
| 217 | ), |
||
| 218 | ), |
||
| 219 | 'check' => array( |
||
| 220 | 'header' => array( |
||
| 221 | 'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check" />', |
||
| 222 | 'class' => 'centertext', |
||
| 223 | ), |
||
| 224 | 'data' => array( |
||
| 225 | 'function' => function ($row) |
||
| 226 | { |
||
| 227 | return '<input type="checkbox" name="remove[]" value="' . $row['id'] . '" class="input_check" />'; |
||
| 228 | }, |
||
| 229 | 'class' => 'centertext', |
||
| 230 | ), |
||
| 231 | ), |
||
| 232 | ), |
||
| 233 | 'form' => array( |
||
| 234 | 'href' => $scripturl . '?action=admin;area=portalarticles;sa=delete', |
||
| 235 | 'include_sort' => true, |
||
| 236 | 'include_start' => true, |
||
| 237 | 'hidden_fields' => array( |
||
| 238 | $context['session_var'] => $context['session_id'], |
||
| 239 | ), |
||
| 240 | ), |
||
| 241 | 'additional_rows' => array( |
||
| 242 | array( |
||
| 243 | 'class' => 'submitbutton', |
||
| 244 | 'position' => 'below_table_data', |
||
| 245 | 'value' => '<a class="linkbutton" href="?action=admin;area=portalarticles;sa=add;' . $context['session_var'] . '=' . $context['session_id'] . '" accesskey="a">' . $txt['sp_admin_articles_add'] . '</a> |
||
| 246 | <input type="submit" name="remove_articles" value="' . $txt['sp_admin_articles_remove'] . '" />', |
||
| 247 | ), |
||
| 248 | ), |
||
| 249 | ); |
||
| 250 | |||
| 251 | // Set the context values |
||
| 252 | $context['page_title'] = $txt['sp_admin_articles_title']; |
||
| 253 | $context['sub_template'] = 'show_list'; |
||
| 254 | $context['default_list'] = 'portal_articles'; |
||
| 255 | |||
| 256 | // Create the list. |
||
| 257 | require_once(SUBSDIR . '/GenericList.class.php'); |
||
| 258 | createList($listOptions); |
||
| 259 | } |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Callback for createList(), |
||
| 263 | * Returns the number of articles in the system |
||
| 264 | */ |
||
| 265 | public function list_spCountArticles() |
||
| 266 | { |
||
| 267 | return sp_count_articles(); |
||
| 268 | } |
||
| 269 | |||
| 270 | /** |
||
| 271 | * Callback for createList() |
||
| 272 | * Returns an array of articles |
||
| 273 | * |
||
| 274 | * @param int $start |
||
| 275 | * @param int $items_per_page |
||
| 276 | * @param string $sort |
||
| 277 | * |
||
| 278 | * @return array |
||
| 279 | */ |
||
| 280 | public function list_spLoadArticles($start, $items_per_page, $sort) |
||
| 281 | { |
||
| 282 | return sp_load_articles($start, $items_per_page, $sort); |
||
| 283 | } |
||
| 284 | |||
| 285 | /** |
||
| 286 | * Edits an existing OR adds a new article to the system |
||
| 287 | * |
||
| 288 | * - Handles the previewing of an article |
||
| 289 | * - Handles article attachments |
||
| 290 | */ |
||
| 291 | public function action_edit() |
||
| 292 | { |
||
| 293 | global $context, $txt; |
||
| 294 | |||
| 295 | // Load dependency's, prepare error checking |
||
| 296 | $this->editInit(); |
||
| 297 | |||
| 298 | // Want to save the work? |
||
| 299 | if (!empty($_POST['submit']) && !$this->article_errors->hasErrors() && !$this->attach_errors->hasErrors()) |
||
| 300 | { |
||
| 301 | // If the session has timed out, let the user re-submit their form. |
||
| 302 | if (checkSession('post', '', false) !== '') |
||
| 303 | { |
||
| 304 | $this->article_errors->addError('session_timeout'); |
||
| 305 | |||
| 306 | // Disable the preview and the save |
||
| 307 | unset($_POST['preview'], $_POST['submit']); |
||
| 308 | |||
| 309 | return $this->action_edit(); |
||
| 310 | } |
||
| 311 | |||
| 312 | // Check for errors and if none Save it |
||
| 313 | $this->_sportal_admin_article_edit_save(); |
||
| 314 | } |
||
| 315 | |||
| 316 | // Prepare the form fields, preview, errors, etc |
||
| 317 | $this->prepareArticleForm(); |
||
| 318 | |||
| 319 | // On to the editor |
||
| 320 | if ($context['article']['type'] === 'bbc') |
||
| 321 | { |
||
| 322 | $context['article']['body'] = PreparseCode::instance()->un_preparsecode($context['article']['body']); |
||
| 323 | $context['article']['body'] = str_replace(array('"', '<', '>', ' '), array('"', '<', '>', ' '), $context['article']['body']); |
||
| 324 | } |
||
| 325 | |||
| 326 | $this->prepareEditor(); |
||
| 327 | |||
| 328 | // Final bits for the template, category's, styles and permission profiles |
||
| 329 | $this->loadProfileContext(); |
||
| 330 | |||
| 331 | // Attachments |
||
| 332 | if ($context['attachments']['can']['post']) |
||
| 333 | { |
||
| 334 | $this->article_attachment(); |
||
| 335 | $this->article_attachment_dd(); |
||
| 336 | } |
||
| 337 | |||
| 338 | // Set the globals, spplugin will be called with editor init to set mode |
||
| 339 | addConversionJS($context['article']['type']); |
||
| 340 | |||
| 341 | // Finally the main template |
||
| 342 | loadTemplate('PortalAdminArticles'); |
||
| 343 | $context['sub_template'] = 'articles'; |
||
| 344 | |||
| 345 | // The article above/below template |
||
| 346 | $template_layers = Template_Layers::instance(); |
||
| 347 | $template_layers->add('articles_edit'); |
||
| 348 | |||
| 349 | // Page out values |
||
| 350 | $context[$context['admin_menu_name']]['current_subsection'] = 'add'; |
||
| 351 | $context['article']['style'] = sportal_select_style($context['article']['styles']); |
||
| 352 | $context['is_new'] = $this->_is_aid; |
||
| 353 | $context['article']['body'] = sportal_parse_content($context['article']['body'], $context['article']['type'], 'return'); |
||
| 354 | $context['page_title'] = !$this->_is_aid ? $txt['sp_admin_articles_add'] : $txt['sp_admin_articles_edit']; |
||
| 355 | |||
| 356 | return true; |
||
| 357 | } |
||
| 358 | |||
| 359 | /** |
||
| 360 | * Loads in dependency's for saving or editing an article |
||
| 361 | */ |
||
| 362 | private function editInit() |
||
| 363 | { |
||
| 364 | global $modSettings, $context; |
||
| 365 | |||
| 366 | $this->_is_aid = empty($_REQUEST['article_id']) ? false : (int) $_REQUEST['article_id']; |
||
| 367 | |||
| 368 | // Going to use editor, attachment and post functions |
||
| 369 | require_once(SUBSDIR . '/Post.subs.php'); |
||
| 370 | require_once(SUBSDIR . '/Editor.subs.php'); |
||
| 371 | require_once(SUBSDIR . '/Attachments.subs.php'); |
||
| 372 | |||
| 373 | loadLanguage('Post'); |
||
| 374 | loadLanguage('Errors'); |
||
| 375 | |||
| 376 | // Errors are likely |
||
| 377 | $this->article_errors = ErrorContext::context('article', 0); |
||
| 378 | $this->attach_errors = AttachmentErrorContext::context(); |
||
| 379 | $this->attach_errors->activate(); |
||
| 380 | |||
| 381 | $context['attachments']['can']['post'] = !empty($modSettings['attachmentEnable']) && $modSettings['attachmentEnable'] == 1 && (allowedTo('post_attachment')); |
||
| 382 | } |
||
| 383 | |||
| 384 | /** |
||
| 385 | * Does the actual saving of the article data |
||
| 386 | * |
||
| 387 | * - Validates the data is safe to save |
||
| 388 | * - Updates existing articles or creates new ones |
||
| 389 | */ |
||
| 390 | private function _sportal_admin_article_edit_save() |
||
| 391 | { |
||
| 392 | global $context, $txt, $modSettings; |
||
| 393 | |||
| 394 | checkSession(); |
||
| 395 | |||
| 396 | // Use our standard validation functions in a few spots |
||
| 397 | require_once(SUBSDIR . '/DataValidator.class.php'); |
||
| 398 | $validator = new Data_Validator(); |
||
| 399 | |||
| 400 | // If it exists, load the current data |
||
| 401 | if ($this->_is_aid) |
||
| 402 | { |
||
| 403 | $_POST['article_id'] = $this->_is_aid; |
||
| 404 | $context['article'] = sportal_get_articles($this->_is_aid); |
||
| 405 | } |
||
| 406 | |||
| 407 | // Clean and Review the post data for compliance |
||
| 408 | $validator->sanitation_rules(array( |
||
| 409 | 'title' => 'trim|Util::htmlspecialchars', |
||
| 410 | 'namespace' => 'trim|Util::htmlspecialchars', |
||
| 411 | 'article_id' => 'intval', |
||
| 412 | 'category_id' => 'intval', |
||
| 413 | 'permissions' => 'intval', |
||
| 414 | 'styles' => 'intval', |
||
| 415 | 'type' => 'trim', |
||
| 416 | 'content' => 'trim' |
||
| 417 | )); |
||
| 418 | $validator->validation_rules(array( |
||
| 419 | 'title' => 'required', |
||
| 420 | 'namespace' => 'alpha_numeric|required', |
||
| 421 | 'type' => 'required', |
||
| 422 | 'content' => 'required' |
||
| 423 | )); |
||
| 424 | $validator->text_replacements(array( |
||
| 425 | 'title' => $txt['sp_admin_articles_col_title'], |
||
| 426 | 'namespace' => $txt['sp_admin_articles_col_namespace'], |
||
| 427 | 'content' => $txt['sp_admin_articles_col_body'] |
||
| 428 | )); |
||
| 429 | |||
| 430 | // If you messed this up, tell them why |
||
| 431 | if (!$validator->validate($_POST)) |
||
| 432 | { |
||
| 433 | foreach ($validator->validation_errors() as $id => $error) |
||
| 434 | { |
||
| 435 | $this->article_errors->addError($error); |
||
| 436 | } |
||
| 437 | } |
||
| 438 | |||
| 439 | // Lets make sure this namespace (article id) is unique |
||
| 440 | $has_duplicate = sp_duplicate_articles($validator->article_id, $validator->namespace); |
||
| 441 | if (!empty($has_duplicate)) |
||
| 442 | { |
||
| 443 | $this->article_errors->addError('sp_error_article_namespace_duplicate'); |
||
| 444 | } |
||
| 445 | |||
| 446 | // And we can't have just a numeric namespace (article id) |
||
| 447 | if (preg_replace('~[0-9]+~', '', $validator->namespace) === '') |
||
| 448 | { |
||
| 449 | $this->article_errors->addError('sp_error_article_namespace_numeric'); |
||
| 450 | } |
||
| 451 | |||
| 452 | // Posting some PHP code, and allowed? Then we need to validate it will run |
||
| 453 | if ($_POST['type'] === 'php' && !empty($_POST['content']) && empty($modSettings['sp_disable_php_validation'])) |
||
| 454 | { |
||
| 455 | $validator_php = new Data_Validator(); |
||
| 456 | $validator_php->validation_rules(array('content' => 'php_syntax')); |
||
| 457 | |||
| 458 | // Bad PHP code |
||
| 459 | if (!$validator_php->validate(array('content' => $_POST['content']))) |
||
| 460 | { |
||
| 461 | $this->article_errors->addError($validator_php->validation_errors()); |
||
| 462 | } |
||
| 463 | } |
||
| 464 | |||
| 465 | // Check / Prep attachments |
||
| 466 | $this->processArticleAttachments(); |
||
| 467 | |||
| 468 | // None shall pass ... with errors |
||
| 469 | if ($this->article_errors->hasErrors() || $this->attach_errors->hasErrors()) |
||
| 470 | { |
||
| 471 | unset($_POST['submit']); |
||
| 472 | |||
| 473 | return false; |
||
| 474 | } |
||
| 475 | |||
| 476 | // No errors then, prepare the data for saving |
||
| 477 | $article_info = array( |
||
| 478 | 'id' => $validator->article_id, |
||
| 479 | 'id_category' => $validator->category_id, |
||
| 480 | 'namespace' => $validator->namespace, |
||
| 481 | 'title' => $validator->title, |
||
| 482 | 'body' => Util::htmlspecialchars($_POST['content'], ENT_QUOTES), |
||
| 483 | 'type' => in_array($validator->type, array('bbc', 'html', 'php', 'markdown')) ? $_POST['type'] : 'bbc', |
||
| 484 | 'permissions' => $validator->permissions, |
||
| 485 | 'styles' => $validator->styles, |
||
| 486 | 'status' => !empty($_POST['status']) ? 1 : 0, |
||
| 487 | ); |
||
| 488 | |||
| 489 | if ($article_info['type'] === 'bbc') |
||
| 490 | { |
||
| 491 | PreparseCode::instance()->preparsecode($article_info['body'], false); |
||
| 492 | } |
||
| 493 | |||
| 494 | // Bind attachments to the article if existing, create any needed thumbnails, |
||
| 495 | // move them to the sp attachment directory |
||
| 496 | $attachIDs = $this->finalizeArticleAttachments($article_info); |
||
| 497 | |||
| 498 | // Save the article |
||
| 499 | $this->_is_aid = sp_save_article($article_info, empty($this->_is_aid)); |
||
| 500 | |||
| 501 | // If this was a new article, with attachments, bind them to one another. |
||
| 502 | if (empty($validator->article_id) && !empty($attachIDs)) |
||
| 503 | { |
||
| 504 | bindArticleAttachments($this->_is_aid, $attachIDs); |
||
| 505 | } |
||
| 506 | |||
| 507 | // And return to the listing |
||
| 508 | redirectexit('action=admin;area=portalarticles'); |
||
| 509 | } |
||
| 510 | |||
| 511 | /** |
||
| 512 | * Save attachments based on the form inputs |
||
| 513 | * |
||
| 514 | * - Remove existing ones that have been "unchecked" in the form |
||
| 515 | * - Performs security, size, type, etc checks |
||
| 516 | * - Moves files to the current attachment directory, we will move it again to sp attachment in |
||
| 517 | * the following steps. |
||
| 518 | */ |
||
| 519 | private function processArticleAttachments() |
||
| 520 | { |
||
| 521 | global $user_info, $context, $modSettings; |
||
| 522 | |||
| 523 | // First see if they are trying to delete current attachments. |
||
| 524 | if (isset($_POST['attach_del'])) |
||
| 525 | { |
||
| 526 | $keep_temp = array(); |
||
| 527 | $keep_ids = array(); |
||
| 528 | foreach ($_POST['attach_del'] as $idRemove) |
||
| 529 | { |
||
| 530 | $attachID = getAttachmentIdFromPublic($idRemove); |
||
| 531 | |||
| 532 | if (strpos($attachID, 'post_tmp_' . $user_info['id']) !== false) |
||
| 533 | { |
||
| 534 | $keep_temp[] = $attachID; |
||
| 535 | } |
||
| 536 | else |
||
| 537 | { |
||
| 538 | $keep_ids[] = (int) $attachID; |
||
| 539 | } |
||
| 540 | } |
||
| 541 | |||
| 542 | if (isset($_SESSION['temp_attachments'])) |
||
| 543 | { |
||
| 544 | foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) |
||
| 545 | { |
||
| 546 | if ((isset($_SESSION['temp_attachments']['post']['files'], $attachment['name']) |
||
| 547 | && in_array($attachment['name'], $_SESSION['temp_attachments']['post']['files'])) |
||
| 548 | || in_array($attachID, $keep_temp) |
||
| 549 | || strpos($attachID, 'post_tmp_' . $user_info['id']) === false |
||
| 550 | ) |
||
| 551 | { |
||
| 552 | continue; |
||
| 553 | } |
||
| 554 | |||
| 555 | unset($_SESSION['temp_attachments'][$attachID]); |
||
| 556 | @unlink($attachment['tmp_name']); |
||
| 557 | } |
||
| 558 | } |
||
| 559 | |||
| 560 | if (!empty($this->_is_aid)) |
||
| 561 | { |
||
| 562 | $attachmentQuery = array( |
||
| 563 | 'id_article' => $this->_is_aid, |
||
| 564 | 'not_id_attach' => $keep_ids, |
||
| 565 | 'id_folder' => $modSettings['sp_articles_attachment_dir'], |
||
| 566 | ); |
||
| 567 | removeArticleAttachments($attachmentQuery); |
||
| 568 | } |
||
| 569 | } |
||
| 570 | |||
| 571 | // Upload any new attachments. |
||
| 572 | $context['attachments']['can']['post'] = (allowedTo('post_attachment') |
||
| 573 | || ($modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'))); |
||
| 574 | if ($context['attachments']['can']['post']) |
||
| 575 | { |
||
| 576 | list($context['attachments']['quantity'], $context['attachments']['total_size']) = attachmentsSizeForArticle($this->_is_aid); |
||
|
|
|||
| 577 | processAttachments(); |
||
| 578 | } |
||
| 579 | } |
||
| 580 | |||
| 581 | /** |
||
| 582 | * Handle the final processing of attachments, including any thumbnail generation |
||
| 583 | * and linking attachments to the specific article. Saves the articles in the SP |
||
| 584 | * attachment directory. |
||
| 585 | */ |
||
| 586 | private function finalizeArticleAttachments(&$article_info) |
||
| 587 | { |
||
| 588 | global $context, $user_info, $modSettings, $ignore_temp; |
||
| 589 | |||
| 590 | $attachIDs = array(); |
||
| 591 | if (empty($ignore_temp) && $context['attachments']['can']['post'] && !empty($_SESSION['temp_attachments'])) |
||
| 592 | { |
||
| 593 | foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) |
||
| 594 | { |
||
| 595 | if ($attachID !== 'initial_error' && strpos($attachID, 'post_tmp_' . $user_info['id']) === false) |
||
| 596 | { |
||
| 597 | continue; |
||
| 598 | } |
||
| 599 | |||
| 600 | // If there was an initial error just show that message. |
||
| 601 | if ($attachID === 'initial_error') |
||
| 602 | { |
||
| 603 | unset($_SESSION['temp_attachments']); |
||
| 604 | break; |
||
| 605 | } |
||
| 606 | |||
| 607 | // No errors, then try to create the attachment |
||
| 608 | if (empty($attachment['errors'])) |
||
| 609 | { |
||
| 610 | // Load the attachmentOptions array with the data needed to create an attachment |
||
| 611 | $attachmentOptions = array( |
||
| 612 | 'article' => !empty($this->_is_aid) ? $this->_is_aid : 0, |
||
| 613 | 'poster' => $user_info['id'], |
||
| 614 | 'name' => $attachment['name'], |
||
| 615 | 'tmp_name' => $attachment['tmp_name'], |
||
| 616 | 'size' => $attachment['size'] ?? 0, |
||
| 617 | 'mime_type' => $attachment['type'] ?? '', |
||
| 618 | 'id_folder' => $modSettings['sp_articles_attachment_dir'], |
||
| 619 | 'approved' => true, |
||
| 620 | 'errors' => array(), |
||
| 621 | ); |
||
| 622 | |||
| 623 | if (createArticleAttachment($attachmentOptions)) |
||
| 624 | { |
||
| 625 | $attachIDs[] = $attachmentOptions['id']; |
||
| 626 | if (!empty($attachmentOptions['thumb'])) |
||
| 627 | { |
||
| 628 | $attachIDs[] = $attachmentOptions['thumb']; |
||
| 629 | } |
||
| 630 | |||
| 631 | // Replace ila attach tags with the new valid attachment id and [spattach] tag |
||
| 632 | $article_info['body'] = preg_replace('~\[attach(.*?)\]' . $attachment['public_attachid'] . '\[\/attach\]~', '[spattach$1]' . $attachmentOptions['id'] . '[/spattach]', $article_info['body']); |
||
| 633 | } |
||
| 634 | } |
||
| 635 | // We have errors on this file, build out the issues for display to the user |
||
| 636 | else |
||
| 637 | { |
||
| 638 | @unlink($attachment['tmp_name']); |
||
| 639 | } |
||
| 640 | } |
||
| 641 | |||
| 642 | unset($_SESSION['temp_attachments']); |
||
| 643 | } |
||
| 644 | |||
| 645 | return $attachIDs; |
||
| 646 | } |
||
| 647 | |||
| 648 | /** |
||
| 649 | * Setup the add/edit article template values |
||
| 650 | */ |
||
| 651 | private function prepareArticleForm() |
||
| 652 | { |
||
| 653 | global $txt, $context; |
||
| 654 | |||
| 655 | $context['attachments']['current'] = array(); |
||
| 656 | |||
| 657 | // Just taking a look before you save, or tried to save with errors? |
||
| 658 | if (!empty($_POST['preview']) || $this->article_errors->hasErrors() || $this->attach_errors->hasErrors()) |
||
| 659 | { |
||
| 660 | $context['article'] = $this->_sportal_admin_article_preview(); |
||
| 661 | |||
| 662 | // If there are attachment errors. Let's show a list to the user. |
||
| 663 | if ($this->attach_errors->hasErrors()) |
||
| 664 | { |
||
| 665 | loadTemplate('Errors'); |
||
| 666 | $errors = $this->attach_errors->prepareErrors(); |
||
| 667 | foreach ($errors as $key => $error) |
||
| 668 | { |
||
| 669 | $context['attachment_error_keys'][] = $key . '_error'; |
||
| 670 | $context[$key . '_error'] = $error; |
||
| 671 | } |
||
| 672 | } |
||
| 673 | |||
| 674 | // Showing errors or a preview? |
||
| 675 | if ($this->article_errors->hasErrors()) |
||
| 676 | { |
||
| 677 | $context['article_errors'] = array( |
||
| 678 | 'errors' => $this->article_errors->prepareErrors(), |
||
| 679 | 'type' => $this->article_errors->getErrorType() == 0 ? 'minor' : 'serious', |
||
| 680 | 'title' => $txt['sp_form_errors_detected'], |
||
| 681 | ); |
||
| 682 | } |
||
| 683 | |||
| 684 | // Preview needs a flag |
||
| 685 | if (!empty($_POST['preview'])) |
||
| 686 | { |
||
| 687 | // We reuse this template for the preview |
||
| 688 | loadTemplate('PortalArticles'); |
||
| 689 | $context['preview'] = true; |
||
| 690 | |||
| 691 | // The editor will steal focus so we have to delay |
||
| 692 | addInlineJavascript('setTimeout(() => $("html, body").animate({scrollTop: $("#preview_section").offset().top}, 250), 750);', true); |
||
| 693 | } |
||
| 694 | } |
||
| 695 | // Something new? |
||
| 696 | elseif (!$this->_is_aid) |
||
| 697 | { |
||
| 698 | $context['article'] = array( |
||
| 699 | 'id' => 0, |
||
| 700 | 'article_id' => 'article' . random_int(1, 5000), |
||
| 701 | 'category' => array('id' => 0), |
||
| 702 | 'title' => $txt['sp_articles_default_title'], |
||
| 703 | 'body' => '', |
||
| 704 | 'type' => 'bbc', |
||
| 705 | 'permissions' => 3, |
||
| 706 | 'styles' => 4, |
||
| 707 | 'status' => 1, |
||
| 708 | ); |
||
| 709 | } |
||
| 710 | // Something used |
||
| 711 | else |
||
| 712 | { |
||
| 713 | $_REQUEST['article_id'] = $this->_is_aid; |
||
| 714 | $context['article'] = sportal_get_articles($this->_is_aid); |
||
| 715 | $attach = sportal_get_articles_attachments($this->_is_aid, true); |
||
| 716 | $context['attachments']['current'] = !empty($attach[$this->_is_aid]) ? $attach[$this->_is_aid] : array(); |
||
| 717 | } |
||
| 718 | } |
||
| 719 | |||
| 720 | /** |
||
| 721 | * Sets up for an article preview |
||
| 722 | */ |
||
| 723 | private function _sportal_admin_article_preview() |
||
| 767 | } |
||
| 768 | |||
| 769 | /** |
||
| 770 | * Sets up editor options as needed for SP, temporarily ignores any user options |
||
| 771 | * so we can enable it in the proper mode bbc/php/html |
||
| 772 | */ |
||
| 773 | private function prepareEditor() |
||
| 774 | { |
||
| 775 | global $context, $options; |
||
| 776 | |||
| 777 | if ($context['article']['type'] !== 'bbc') |
||
| 778 | { |
||
| 779 | // Override user preferences for wizzy mode if they don't need it |
||
| 780 | $temp_editor = !empty($options['wysiwyg_default']); |
||
| 781 | $options['wysiwyg_default'] = false; |
||
| 782 | } |
||
| 783 | |||
| 784 | // Fire up the editor with the values |
||
| 785 | $editorOptions = array( |
||
| 786 | 'id' => 'content', |
||
| 787 | 'value' => $context['article']['body'], |
||
| 788 | 'width' => '100%', |
||
| 789 | 'height' => '275px', |
||
| 790 | 'preview_type' => 1, |
||
| 791 | ); |
||
| 792 | $editorOptions['plugin_addons'] = array(); |
||
| 793 | $editorOptions['plugin_addons'][] = 'spplugin'; |
||
| 794 | create_control_richedit($editorOptions); |
||
| 795 | $context['post_box_name'] = $editorOptions['id']; |
||
| 796 | $context['post_box_class'] = $context['article']['type'] !== 'bbc' ? 'sceditor-container' : 'sp-sceditor-container'; |
||
| 797 | $context['attached'] = ''; |
||
| 798 | |||
| 799 | // Restore their settings |
||
| 800 | if (isset($temp_editor)) |
||
| 801 | { |
||
| 802 | $options['wysiwyg_default'] = $temp_editor; |
||
| 803 | } |
||
| 804 | } |
||
| 805 | |||
| 806 | /** |
||
| 807 | * Loads in permission, visibility and style profiles for use in the template |
||
| 808 | * If unable to load profiles, simply dies as "somethings broke"tm |
||
| 809 | */ |
||
| 810 | private function loadProfileContext() |
||
| 811 | { |
||
| 812 | global $context; |
||
| 813 | |||
| 814 | $context['article']['permission_profiles'] = sportal_get_profiles(null, 1, 'name'); |
||
| 815 | if (empty($context['article']['permission_profiles'])) |
||
| 816 | { |
||
| 817 | throw new Elk_Exception('error_sp_no_permission_profiles', false); |
||
| 818 | } |
||
| 819 | |||
| 820 | $context['article']['style_profiles'] = sportal_get_profiles(null, 2, 'name'); |
||
| 821 | if (empty($context['article']['permission_profiles'])) |
||
| 822 | { |
||
| 823 | throw new Elk_Exception('error_sp_no_style_profiles', false); |
||
| 824 | } |
||
| 825 | |||
| 826 | $context['article']['categories'] = sportal_get_categories(); |
||
| 827 | if (empty($context['article']['categories'])) |
||
| 828 | { |
||
| 829 | throw new Elk_Exception('error_sp_no_category', false); |
||
| 830 | } |
||
| 831 | } |
||
| 832 | |||
| 833 | /** |
||
| 834 | * Handles the checking of uploaded attachments and loads valid ones |
||
| 835 | * into context |
||
| 836 | */ |
||
| 837 | private function article_attachment() |
||
| 838 | { |
||
| 839 | global $context, $txt; |
||
| 840 | |||
| 841 | // If there are attachments, calculate the total size and how many. |
||
| 842 | $this->_attachments = array(); |
||
| 843 | $this->_attachments['total_size'] = 0; |
||
| 844 | $this->_attachments['quantity'] = 0; |
||
| 845 | |||
| 846 | // If this isn't a new article, account for any current attachments. |
||
| 847 | if ($this->_is_aid && !empty($context['attachments'])) |
||
| 848 | { |
||
| 849 | $this->_attachments['quantity'] = count($context['attachments']['current']); |
||
| 850 | foreach ($context['attachments']['current'] as $attachment) |
||
| 851 | { |
||
| 852 | $this->_attachments['total_size'] += $attachment['size']; |
||
| 853 | } |
||
| 854 | } |
||
| 855 | |||
| 856 | // Any failed/aborted attachments left in session that we should clear |
||
| 857 | if (!empty($_SESSION['temp_attachments']) && empty($_POST['preview']) && empty($_POST['submit']) && !$this->_is_aid) |
||
| 858 | { |
||
| 859 | foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) |
||
| 860 | { |
||
| 861 | unset($_SESSION['temp_attachments'][$attachID]); |
||
| 862 | @unlink($attachment['tmp_name']); |
||
| 863 | } |
||
| 864 | } |
||
| 865 | // New attachments to add |
||
| 866 | elseif (!empty($_SESSION['temp_attachments'])) |
||
| 867 | { |
||
| 868 | foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) |
||
| 869 | { |
||
| 870 | // PHP upload error means we drop the file |
||
| 871 | if ($attachID === 'initial_error') |
||
| 872 | { |
||
| 873 | $txt['error_attach_initial_error'] = $txt['attach_no_upload'] . '<div class="attachmenterrors">' . (is_array($attachment) ? vsprintf($txt[$attachment[0]], $attachment[1]) : $txt[$attachment]) . '</div>'; |
||
| 874 | $this->attach_errors->addError('attach_initial_error'); |
||
| 875 | unset($_SESSION['temp_attachments']); |
||
| 876 | break; |
||
| 877 | } |
||
| 878 | |||
| 879 | // Show any errors which might have occurred. |
||
| 880 | if (!empty($attachment['errors'])) |
||
| 881 | { |
||
| 882 | $txt['error_attach_errors'] = empty($txt['error_attach_errors']) ? '<br />' : ''; |
||
| 883 | $txt['error_attach_errors'] .= vsprintf($txt['attach_warning'], $attachment['name']) . '<div class="attachmenterrors">'; |
||
| 884 | foreach ($attachment['errors'] as $error) |
||
| 885 | { |
||
| 886 | $txt['error_attach_errors'] .= (is_array($error) ? vsprintf($txt[$error[0]], $error[1]) : $txt[$error]) . '<br />'; |
||
| 887 | } |
||
| 888 | $txt['error_attach_errors'] .= '</div>'; |
||
| 889 | |||
| 890 | $this->attach_errors->addError('attach_errors'); |
||
| 891 | |||
| 892 | // Take out the trash. |
||
| 893 | unset($_SESSION['temp_attachments'][$attachID]); |
||
| 894 | @unlink($attachment['tmp_name']); |
||
| 895 | |||
| 896 | continue; |
||
| 897 | } |
||
| 898 | |||
| 899 | // In session but the file is missing, then some house cleaning |
||
| 900 | if (isset($attachment['tmp_name']) && !file_exists($attachment['tmp_name'])) |
||
| 901 | { |
||
| 902 | unset($_SESSION['temp_attachments'][$attachID]); |
||
| 903 | continue; |
||
| 904 | } |
||
| 905 | |||
| 906 | $this->_attachments['name'] = !empty($this->_attachments['name']) ? $this->_attachments['name'] : ''; |
||
| 907 | $this->_attachments['size'] = !empty($this->_attachments['size']) ? $this->_attachments['size'] : 0; |
||
| 908 | $this->_attachments['quantity']++; |
||
| 909 | $this->_attachments['total_size'] += $this->_attachments['size']; |
||
| 910 | |||
| 911 | $context['attachments']['current'][] = array( |
||
| 912 | 'name' => '<span class="underline">' . htmlspecialchars($this->_attachments['name'], ENT_COMPAT) . '</span>', |
||
| 913 | 'size' => $this->_attachments['size'], |
||
| 914 | 'id' => $attachID, |
||
| 915 | 'unchecked' => false, |
||
| 916 | 'approved' => 1, |
||
| 917 | ); |
||
| 918 | } |
||
| 919 | } |
||
| 920 | } |
||
| 921 | |||
| 922 | /** |
||
| 923 | * Prepares template values for the attachment area such as space left, |
||
| 924 | * types allowed, etc. |
||
| 925 | * |
||
| 926 | * Prepares the D&D JS initialization values |
||
| 927 | */ |
||
| 928 | private function article_attachment_dd() |
||
| 929 | { |
||
| 930 | global $context, $modSettings, $txt; |
||
| 931 | |||
| 932 | // If they've unchecked an attachment, they may still want to attach that many more files, but don't allow more than num_allowed_attachments. |
||
| 933 | $context['attachments']['num_allowed'] = empty($modSettings['attachmentNumPerPostLimit']) ? 50 : min($modSettings['attachmentNumPerPostLimit'] - count($context['attachments']['current']), $modSettings['attachmentNumPerPostLimit']); |
||
| 934 | $context['attachments']['can']['post_unapproved'] = allowedTo('post_attachment'); |
||
| 935 | $context['attachments']['restrictions'] = array(); |
||
| 936 | $context['attachments']['ila_enabled'] = true; |
||
| 937 | |||
| 938 | if (!empty($modSettings['attachmentCheckExtensions'])) |
||
| 939 | { |
||
| 940 | $context['attachments']['allowed_extensions'] = strtr(strtolower($modSettings['attachmentExtensions']), array(',' => ', ')); |
||
| 941 | } |
||
| 942 | else |
||
| 943 | { |
||
| 944 | $context['attachments']['allowed_extensions'] = ''; |
||
| 945 | } |
||
| 946 | |||
| 947 | $context['attachments']['templates'] = array( |
||
| 948 | 'existing' => 'template_article_existing_attachments', |
||
| 949 | 'add_new' => 'template_article_new_attachments', |
||
| 950 | ); |
||
| 951 | |||
| 952 | $attachmentRestrictionTypes = array('attachmentNumPerPostLimit', 'attachmentPostLimit', 'attachmentSizeLimit'); |
||
| 953 | foreach ($attachmentRestrictionTypes as $type) |
||
| 954 | { |
||
| 955 | if (!empty($modSettings[$type])) |
||
| 956 | { |
||
| 957 | $context['attachments']['restrictions'][] = sprintf($txt['attach_restrict_' . $type], comma_format($modSettings[$type], 0)); |
||
| 958 | |||
| 959 | // Show some numbers. If they exist. |
||
| 960 | if ($type === 'attachmentNumPerPostLimit' && $this->_attachments['quantity'] > 0) |
||
| 961 | { |
||
| 962 | $context['attachments']['restrictions'][] = sprintf($txt['attach_remaining'], $modSettings['attachmentNumPerPostLimit'] - $this->_attachments['quantity']); |
||
| 963 | } |
||
| 964 | elseif ($type === 'attachmentPostLimit' && $this->_attachments['total_size'] > 0) |
||
| 965 | { |
||
| 966 | $context['attachments']['restrictions'][] = sprintf($txt['attach_available'], comma_format(round(max($modSettings['attachmentPostLimit'] - ($this->_attachments['total_size'] / 1028), 0)), 0)); |
||
| 967 | } |
||
| 968 | } |
||
| 969 | } |
||
| 970 | |||
| 971 | // The portal articles always allow "ila" style attachments, so show that insert interface |
||
| 972 | addInlineJavascript(' |
||
| 973 | let IlaDropEvents = { |
||
| 974 | UploadSuccess: function($button, data) { |
||
| 975 | let inlineAttach = ElkInlineAttachments(\'#postAttachment2,#postAttachment\', \'' . $context['post_box_name'] . '\', { |
||
| 976 | trigger: $(\'<div class="share icon i-share" />\'), |
||
| 977 | template: ' . JavaScriptEscape('<div class="insertoverlay"> |
||
| 978 | <input type="button" class="button" value="' . $txt['insert'] . '"> |
||
| 979 | <ul data-group="tabs" class="tabs"> |
||
| 980 | <li data-tab="size">' . $txt['ila_opt_size'] . '</li><li data-tab="align">' . $txt['ila_opt_align'] . '</li> |
||
| 981 | </ul> |
||
| 982 | <div class="container" data-visual="size"> |
||
| 983 | <label><input data-size="thumb" type="radio" name="imgmode">' . $txt['ila_opt_size_thumb'] . '</label> |
||
| 984 | <label><input data-size="full" type="radio" name="imgmode">' . $txt['ila_opt_size_full'] . '</label> |
||
| 985 | <label><input data-size="cust" type="radio" name="imgmode">' . $txt['ila_opt_size_cust'] . '</label> |
||
| 986 | <div class="customsize"> |
||
| 987 | <input type="range" class="range" min="100" max="500"><input type="text" class="visualizesize" disabled="disabled"> |
||
| 988 | </div> |
||
| 989 | </div> |
||
| 990 | <div class="container" data-visual="align"> |
||
| 991 | <label><input data-align="none" type="radio" name="align">' . $txt['ila_opt_align_none'] . '</label> |
||
| 992 | <label><input data-align="left" type="radio" name="align">' . $txt['ila_opt_align_left'] . '</label> |
||
| 993 | <label><input data-align="center" type="radio" name="align">' . $txt['ila_opt_align_center'] . '</label> |
||
| 994 | <label><input data-align="right" type="radio" name="align">' . $txt['ila_opt_align_right'] . '</label> |
||
| 995 | </div> |
||
| 996 | </div>') . ' |
||
| 997 | }); |
||
| 998 | inlineAttach.addInterface($button, data.attachid); |
||
| 999 | }, |
||
| 1000 | RemoveSuccess: function(attachid) { |
||
| 1001 | var inlineAttach = ElkInlineAttachments(\'#postAttachment2,#postAttachment\', \'' . $context['post_box_name'] . '\', { |
||
| 1002 | trigger: $(\'<div class="share icon i-share" />\') |
||
| 1003 | }); |
||
| 1004 | inlineAttach.removeAttach(attachid); |
||
| 1005 | } |
||
| 1006 | };', true); |
||
| 1007 | |||
| 1008 | // Load up the drag and drop attachment magic |
||
| 1009 | addInlineJavascript(' |
||
| 1010 | var dropAttach = dragDropAttachment({ |
||
| 1011 | board: 0, |
||
| 1012 | allowedExtensions: ' . JavaScriptEscape($context['attachments']['allowed_extensions']) . ', |
||
| 1013 | totalSizeAllowed: ' . JavaScriptEscape(empty($modSettings['attachmentPostLimit']) ? '' : $modSettings['attachmentPostLimit']) . ', |
||
| 1014 | individualSizeAllowed: ' . JavaScriptEscape(empty($modSettings['attachmentSizeLimit']) ? '' : $modSettings['attachmentSizeLimit']) . ', |
||
| 1015 | numOfAttachmentAllowed: ' . $context['attachments']['num_allowed'] . ', |
||
| 1016 | totalAttachSizeUploaded: ' . (isset($context['attachments']['total_size']) && !empty($context['attachments']['total_size']) ? $context['attachments']['total_size'] : 0) . ', |
||
| 1017 | numAttachUploaded: ' . (isset($context['attachments']['quantity']) && !empty($context['attachments']['quantity']) ? $context['attachments']['quantity'] : 0) . ', |
||
| 1018 | fileDisplayTemplate: \'<div class="statusbar"><div class="info"></div><div class="progressBar"><div></div></div><div class="control icon i-close"></div></div>\', |
||
| 1019 | oTxt: ({ |
||
| 1020 | allowedExtensions : ' . JavaScriptEscape(sprintf($txt['cant_upload_type'], $context['attachments']['allowed_extensions'])) . ', |
||
| 1021 | totalSizeAllowed : ' . JavaScriptEscape($txt['attach_max_total_file_size']) . ', |
||
| 1022 | individualSizeAllowed : ' . JavaScriptEscape(sprintf($txt['file_too_big'], comma_format($modSettings['attachmentSizeLimit'], 0))) . ', |
||
| 1023 | numOfAttachmentAllowed : ' . JavaScriptEscape(sprintf($txt['attachments_limit_per_post'], $modSettings['attachmentNumPerPostLimit'])) . ', |
||
| 1024 | postUploadError : ' . JavaScriptEscape($txt['post_upload_error']) . ', |
||
| 1025 | areYouSure: ' . JavaScriptEscape($txt['ila_confirm_removal']) . ', |
||
| 1026 | }), |
||
| 1027 | existingSelector: ".inline_insert", |
||
| 1028 | events: IlaDropEvents' . (!empty($this->_is_aid) ? ', |
||
| 1029 | article: ' . $this->_is_aid : '') . ' |
||
| 1030 | });', true); |
||
| 1031 | } |
||
| 1032 | |||
| 1033 | /** |
||
| 1034 | * Toggle an articles active status on/off |
||
| 1035 | */ |
||
| 1036 | public function action_status() |
||
| 1037 | { |
||
| 1038 | global $context; |
||
| 1039 | |||
| 1040 | checkSession(isset($_REQUEST['xml']) ? '' : 'get'); |
||
| 1041 | |||
| 1042 | $article_id = !empty($_REQUEST['article_id']) ? (int) $_REQUEST['article_id'] : 0; |
||
| 1043 | $state = sp_changeState('article', $article_id); |
||
| 1044 | |||
| 1045 | // Doing this the ajax way? |
||
| 1046 | if (isset($_REQUEST['xml'])) |
||
| 1047 | { |
||
| 1048 | $context['item_id'] = $article_id; |
||
| 1049 | $context['status'] = !empty($state) ? 'active' : 'deactive'; |
||
| 1050 | |||
| 1051 | // Clear out any template layers, add the xml response |
||
| 1052 | loadTemplate('PortalAdmin'); |
||
| 1053 | $template_layers = Template_Layers::instance(); |
||
| 1054 | $template_layers->removeAll(); |
||
| 1055 | $context['sub_template'] = 'change_status'; |
||
| 1056 | |||
| 1057 | obExit(); |
||
| 1058 | } |
||
| 1059 | |||
| 1060 | redirectexit('action=admin;area=portalarticles'); |
||
| 1061 | } |
||
| 1062 | |||
| 1063 | /** |
||
| 1064 | * Remove an article from the system |
||
| 1065 | * |
||
| 1066 | * - Removes the article |
||
| 1067 | * - Removes attachments associated with an article |
||
| 1068 | * - Updates category totals to reflect removed items |
||
| 1069 | */ |
||
| 1070 | public function action_delete() |
||
| 1104 | } |
||
| 1105 | } |
||
| 1106 |