ManagePortalBlocks_Controller::action_edit()   F
last analyzed

Complexity

Conditions 90
Paths > 20000

Size

Total Lines 437
Code Lines 217

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 0
Metric Value
cc 90
eloc 217
nc 195168260
nop 0
dl 0
loc 437
rs 0
c 8
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @package SimplePortal ElkArte
5
 *
6
 * @author SimplePortal Team
7
 * @copyright 2015-2021 SimplePortal Team
8
 * @license BSD 3-clause
9
 * @version 1.0.0
10
 */
11
12
use BBC\PreparseCode;
13
14
/**
15
 * SimplePortal Blocks Administration controller class.
16
 * This class handles the adding/editing/listing of blocks
17
 */
18
class ManagePortalBlocks_Controller extends Action_Controller
19
{
20
	/**
21
	 * Main dispatcher.
22
	 *
23
	 * - This function checks permissions and passes control through.
24
	 */
25
	public function action_index()
26
	{
27
		global $context, $txt;
28
29
		// You need to be an admin or have block permissions
30
		if (!allowedTo('sp_admin'))
31
		{
32
			isAllowedTo('sp_manage_blocks');
33
		}
34
35
		// We'll need the utility functions from here.
36
		require_once(SUBSDIR . '/PortalAdmin.subs.php');
37
		require_once(SUBSDIR . '/Portal.subs.php');
38
		loadTemplate('PortalAdminBlocks');
39
40
		$subActions = array(
41
			'list' => array($this, 'action_list'),
42
			'header' => array($this, 'action_list'),
43
			'left' => array($this, 'action_list'),
44
			'top' => array($this, 'action_list'),
45
			'bottom' => array($this, 'action_list'),
46
			'right' => array($this, 'action_list'),
47
			'footer' => array($this, 'action_list'),
48
			'add' => array($this, 'action_edit'),
49
			'edit' => array($this, 'action_edit'),
50
			'delete' => array($this, 'action_delete'),
51
			'move' => array($this, 'action_move'),
52
			'statechange' => array($this, 'action_state_change'),
53
		);
54
55
		// Start up the controller, provide a hook since we can
56
		$action = new Action('portal_blocks');
57
58
		// Tabs for the menu
59
		$context[$context['admin_menu_name']]['tab_data'] = array(
60
			'title' => $txt['sp-blocksBlocks'],
61
			'help' => 'sp_BlocksArea',
62
			'description' => $txt['sp-adminBlockListDesc'],
63
			'tabs' => array(
64
				'list' => array(
65
					'description' => $txt['sp-adminBlockListDesc'],
66
				),
67
				'add' => array(
68
					'description' => $txt['sp-adminBlockAddDesc'],
69
				),
70
				'header' => array(
71
					'description' => $txt['sp-adminBlockHeaderListDesc'],
72
				),
73
				'left' => array(
74
					'description' => $txt['sp-adminBlockLeftListDesc'],
75
				),
76
				'top' => array(
77
					'description' => $txt['sp-adminBlockTopListDesc'],
78
				),
79
				'bottom' => array(
80
					'description' => $txt['sp-adminBlockBottomListDesc'],
81
				),
82
				'right' => array(
83
					'description' => $txt['sp-adminBlockRightListDesc'],
84
				),
85
				'footer' => array(
86
					'description' => $txt['sp-adminBlockFooterListDesc'],
87
				),
88
			),
89
		);
90
91
		// The default action will show the block list
92
		$subAction = $action->initialize($subActions, 'list');
93
		$context['sub_action'] = $subAction;
94
95
		// Call the right function for this sub-action
96
		$action->dispatch($subAction);
97
	}
98
99
	/**
100
	 * Show the Block List.
101
	 */
102
	public function action_list()
103
	{
104
		global $txt, $context, $scripturl;
105
106
		// We have 6 sides...like a cube!
107
		$context['sides'] = array(
108
			'header' => array(
109
				'id' => '5',
110
				'name' => 'adminHeader',
111
				'label' => $txt['sp-positionHeader'],
112
				'help' => 'sp-blocksHeaderList',
113
			),
114
			'left' => array(
115
				'id' => '1',
116
				'name' => 'adminLeft',
117
				'label' => $txt['sp-positionLeft'],
118
				'help' => 'sp-blocksLeftList',
119
			),
120
			'top' => array(
121
				'id' => '2',
122
				'name' => 'adminTop',
123
				'label' => $txt['sp-positionTop'],
124
				'help' => 'sp-blocksTopList',
125
			),
126
			'bottom' => array(
127
				'id' => '3',
128
				'name' => 'adminBottom',
129
				'label' => $txt['sp-positionBottom'],
130
				'help' => 'sp-blocksBottomList',
131
			),
132
			'right' => array(
133
				'id' => '4',
134
				'name' => 'adminRight',
135
				'label' => $txt['sp-positionRight'],
136
				'help' => 'sp-blocksRightList',
137
			),
138
			'footer' => array(
139
				'id' => '6',
140
				'name' => 'adminFooter',
141
				'label' => $txt['sp-positionFooter'],
142
				'help' => 'sp-blocksFooterList',
143
			),
144
		);
145
146
		$sides = array('header', 'left', 'top', 'bottom', 'right', 'footer');
147
148
		// Are we viewing any of the sub lists for an individual side?
149
		if (in_array($context['sub_action'], $sides))
150
		{
151
			// Remove any sides that we don't need to show. ;)
152
			foreach ($sides as $side)
153
			{
154
				if ($context['sub_action'] != $side)
155
				{
156
					unset($context['sides'][$side]);
157
				}
158
			}
159
160
			$context['sp_blocks_single_side_list'] = true;
161
		}
162
163
		// Columns to show.
164
		$context['columns'] = array(
165
			'label' => array(
166
				'width' => '40%',
167
				'label' => $txt['sp-adminColumnName'],
168
				'class' => 'first_th',
169
			),
170
			'type' => array(
171
				'width' => '30%',
172
				'label' => $txt['sp-adminColumnType'],
173
			),
174
			'status' => array(
175
				'width' => '10%',
176
				'label' => $txt['sp-blocksActive'],
177
				'class' => 'centertext',
178
			),
179
			'action' => array(
180
				'width' => '20%',
181
				'label' => $txt['sp-adminColumnAction'],
182
				'class' => 'centertext last_th',
183
			),
184
		);
185
186
		// Get the block info for each side.
187
		foreach ($context['sides'] as $side_id => $side)
188
		{
189
			$context['blocks'][$side['name']] = getBlockInfo($side['id']);
190
			foreach ($context['blocks'][$side['name']] as $block_id => $block)
191
			{
192
				$context['sides'][$side_id]['last'] = $block_id;
193
				$context['blocks'][$side['name']][$block_id]['status'] = '<a href="' . $scripturl . '?action=admin;area=portalblocks;sa=statechange;' . (empty($context['sp_blocks_single_side_list']) ? '' : 'redirect=' . $block['column'] . ';') . 'block_id=' . $block['id'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '"
194
					onclick="sp_change_status(\'' . $block['id']  . '\', \'block\');return false;">' .
195
					sp_embed_image(empty($block['state']) ? 'deactive' : 'active', (!empty($block['state']) ? $txt['sp-blocksDeactivate'] : $txt['sp-blocksActivate']), null, null, true, 'status_image_' . $block['id']) . '</a>';
0 ignored issues
show
Bug introduced by
'status_image_' . $block['id'] of type string is incompatible with the type integer|null expected by parameter $id of sp_embed_image(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

195
					sp_embed_image(empty($block['state']) ? 'deactive' : 'active', (!empty($block['state']) ? $txt['sp-blocksDeactivate'] : $txt['sp-blocksActivate']), null, null, true, /** @scrutinizer ignore-type */ 'status_image_' . $block['id']) . '</a>';
Loading history...
196
				$context['blocks'][$side['name']][$block_id]['actions'] = array(
197
					'edit' => '&nbsp;<a href="' . $scripturl . '?action=admin;area=portalblocks;sa=edit;block_id=' . $block['id'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '">' . sp_embed_image('modify') . '</a>',
198
					'delete' => '&nbsp;<a href="' . $scripturl . '?action=admin;area=portalblocks;sa=delete;block_id=' . $block['id'] . ';col=' . $block['column'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" onclick="return confirm(\'' . $txt['sp-deleteblock'] . '\');">' . sp_embed_image('trash') . '</a>',
199
				);
200
			}
201
		}
202
203
		// Call the sub template.
204
		createToken('admin-sort');
205
		$context['sub_template'] = 'block_list';
206
		$context['page_title'] = $txt['sp-adminBlockListName'];
207
	}
208
209
	/**
210
	 * Adding or editing a block.
211
	 */
212
	public function action_edit()
213
	{
214
		global $txt, $context, $modSettings, $boards;
215
216
		// Just in case, the admin could be doing something silly like editing a SP block while SP is disabled. ;)
217
		require_once(SUBSDIR . '/spblocks/SPAbstractBlock.class.php');
218
219
		$context['SPortal']['is_new'] = empty($_REQUEST['block_id']);
220
221
		// Convert HTML to BBC if needed
222
		$this->_fixBBC();
223
224
		// Passing the selected type via $_GET instead of $_POST?
225
		$start_parameters = $this->_getStartParameters();
226
227
		// Want use a block on the portal?
228
		if ($context['SPortal']['is_new'] && empty($_POST['selected_type']) && empty($_POST['add_block']))
229
		{
230
			// Gather the blocks we have available
231
			$context['SPortal']['block_types'] = getFunctionInfo();
232
233
			// Create a list of the blocks in use
234
			$in_use = getBlockInfo();
235
			foreach ($in_use as $block)
236
			{
237
				$context['SPortal']['block_inuse'][$block['type']] = array('state' => $block['state'], 'column' => $block['column']);
238
			}
239
240
			$context['location'] = array(1 => $txt['sp-positionLeft'], $txt['sp-positionTop'], $txt['sp-positionBottom'], $txt['sp-positionRight'], $txt['sp-positionHeader'], $txt['sp-positionFooter']);
241
242
			if (!empty($_REQUEST['col']))
243
			{
244
				$context['SPortal']['block']['column'] = $_REQUEST['col'];
245
			}
246
247
			$context['sub_template'] = 'block_select_type';
248
			$context['page_title'] = $txt['sp-blocksAdd'];
249
		}
250
		// Selecting a block to place in to service, load some initial values
251
		elseif ($context['SPortal']['is_new'] && !empty($_POST['selected_type']))
252
		{
253
			$block = sp_instantiate_block($_POST['selected_type'][0]);
254
			$context['SPortal']['block'] = array(
255
				'id' => 0,
256
				'label' => $txt['sp-blocksDefaultLabel'],
257
				'type' => $_POST['selected_type'][0],
258
				'type_text' => !empty($txt['sp_function_' . $_POST['selected_type'][0] . '_label']) ? $txt['sp_function_' . $_POST['selected_type'][0] . '_label'] : $txt['sp_function_unknown_label'],
259
				'column' => !empty($_POST['block_column']) ? $_POST['block_column'] : 0,
260
				'row' => 0,
261
				'permissions' => 3,
262
				'styles' => 4,
263
				'visibility' => 14,
264
				'state' => 1,
265
				'force_view' => 0,
266
				'parameters' => !empty($start_parameters) ? $start_parameters : array(),
267
				'options' => $block->parameters(),
268
				'list_blocks' => !empty($_POST['block_column']) ? getBlockInfo((int) $_POST['block_column']) : array(),
269
			);
270
		}
271
		// Saving the block to one of the zones
272
		elseif (!$context['SPortal']['is_new'] && empty($_POST['add_block']))
273
		{
274
			$_REQUEST['block_id'] = (int) $_REQUEST['block_id'];
275
			$context['SPortal']['block'] = current(getBlockInfo(null, $_REQUEST['block_id']));
276
277
			$block = sp_instantiate_block($context['SPortal']['block']['type']);
278
			$context['SPortal']['block'] += array(
279
				'options' => $block->parameters(),
280
				'list_blocks' => getBlockInfo($context['SPortal']['block']['column']),
281
			);
282
		}
283
284
		// Want to take a look at how this block will appear, well we try our best
285
		if (!empty($_POST['preview_block']) || isset($_SESSION['sp_error']))
286
		{
287
			// An error was generated on save, lets set things up like a preview and return to the preview
288
			if (isset($_SESSION['sp_error']))
289
			{
290
				$context['SPortal']['error'] = $_SESSION['sp_error'];
291
				$_POST = $_SESSION['sp_error_post'];
292
				$_POST['preview_block'] = true;
293
294
				// Clean up
295
				unset($_SESSION['sp_error'], $_SESSION['sp_error_post'], $_POST['add_block']);
296
			}
297
298
			// Just in case, the admin could be doing something silly like editing a SP block while SP is disabled. ;)
299
			require_once(BOARDDIR . '/SSI.php');
300
			sportal_init_headers();
301
			loadTemplate('Portal');
302
303
			// Start the block and get its parameters for display
304
			$block = sp_instantiate_block((string) $_POST['block_type']);
305
			$type_parameters = $block->parameters();
306
307
			if (!empty($_POST['parameters']) && is_array($_POST['parameters']) && !empty($type_parameters))
308
			{
309
				foreach ($type_parameters as $name => $type)
310
				{
311
					if (isset($_POST['parameters'][$name]))
312
					{
313
						$this->_prepare_parameters($type, $name);
314
					}
315
				}
316
			}
317
			else
318
			{
319
				$_POST['parameters'] = array();
320
			}
321
322
			// Prepare a preview with the form parameters
323
			$block->setup($_POST['parameters'], false);
324
325
			// Create all the information we know about this block
326
			$context['SPortal']['block'] = array(
327
				'id' => $_POST['block_id'],
328
				'label' => Util::htmlspecialchars($_POST['block_name'], ENT_QUOTES),
329
				'type' => $_POST['block_type'],
330
				'type_text' => !empty($txt['sp_function_' . $_POST['block_type'] . '_label']) ? $txt['sp_function_' . $_POST['block_type'] . '_label'] : $txt['sp_function_unknown_label'],
331
				'column' => $_POST['block_column'],
332
				'row' => !empty($_POST['block_row']) ? $_POST['block_row'] : 0,
333
				'placement' => !empty($_POST['placement']) && in_array($_POST['placement'], array('before', 'after')) ? $_POST['placement'] : '',
334
				'permissions' => $_POST['permissions'],
335
				'styles' => $_POST['styles'],
336
				'visibility' => $_POST['visibility'],
337
				'state' => !empty($_POST['block_active']),
338
				'force_view' => !empty($_POST['block_force']),
339
				'parameters' => !empty($_POST['parameters']) ? $_POST['parameters'] : array(),
340
				'options' => $block->parameters(),
341
				'list_blocks' => getBlockInfo($_POST['block_column']),
342
				'collapsed' => false,
343
				'instance' => $block,
344
			);
345
346
			if (strpos($modSettings['leftwidth'], '%') !== false || strpos($modSettings['leftwidth'], 'px') !== false)
347
			{
348
				$context['widths'][1] = $modSettings['leftwidth'];
349
			}
350
			else
351
			{
352
				$context['widths'][1] = $modSettings['leftwidth'] . 'px';
353
			}
354
355
			if (strpos($modSettings['rightwidth'], '%') !== false || strpos($modSettings['rightwidth'], 'px') !== false)
356
			{
357
				$context['widths'][4] = $modSettings['rightwidth'];
358
			}
359
			else
360
			{
361
				$context['widths'][4] = $modSettings['rightwidth'] . 'px';
362
			}
363
364
			if (strpos($context['widths'][1], '%') !== false)
365
			{
366
				$context['widths'][2] = $context['widths'][3] = 100 - ((int) $context['widths'][1] + (int) $context['widths'][4]) . '%';
367
				$context['widths'][5] = $context['widths'][6] = '100%';
368
			}
369
			elseif (strpos($context['widths'][1], 'px') !== false)
370
			{
371
				$context['widths'][2] = $context['widths'][3] = 960 - ((int) $context['widths'][1] + (int) $context['widths'][4]) . 'px';
372
				$context['widths'][5] = $context['widths'][6] = '960px';
373
			}
374
375
			$context['SPortal']['preview'] = true;
376
		}
377
378
		if (!empty($_POST['selected_type']) || !empty($_POST['preview_block']) || (!$context['SPortal']['is_new'] && empty($_POST['add_block'])))
379
		{
380
			// Only the admin can use PHP blocks
381
			if ($context['SPortal']['block']['type'] === 'sp_php' && !allowedTo('admin_forum'))
382
			{
383
				throw new Elk_Exception('cannot_admin_forum', false);
384
			}
385
386
			loadLanguage('SPortalHelp');
387
388
			// Load up the permissions
389
			$context['SPortal']['block']['permission_profiles'] = sportal_get_profiles(null, 1, 'name');
390
			if (empty($context['SPortal']['block']['permission_profiles']))
391
			{
392
				throw new Elk_Exception('error_sp_no_permission_profiles', false);
393
			}
394
395
			// Load in the style profiles
396
			$context['SPortal']['block']['style_profiles'] = sportal_get_profiles(null, 2, 'name');
397
			if (empty($context['SPortal']['block']['style_profiles']))
398
			{
399
				throw new Elk_Exception('error_sp_no_style_profiles', false);
400
			}
401
402
			// Load in the display profiles
403
			$context['SPortal']['block']['visibility_profiles'] = sportal_get_profiles(null, 3, 'name');
404
			if (empty($context['SPortal']['block']['visibility_profiles']))
405
			{
406
				throw new Elk_Exception('error_sp_no_visibility_profiles', false);
407
			}
408
409
			$context['SPortal']['block']['style'] = sportal_select_style($context['SPortal']['block']['styles']);
410
411
			// Prepare the Textcontent for BBC, only the first bbc will be detected correctly!
412
			$firstBBCFound = false;
413
			foreach ($context['SPortal']['block']['options'] as $name => $type)
414
			{
415
				// Selectable Boards :D
416
				if ($type === 'board_select' || $type === 'boards')
417
				{
418
					if (empty($boards))
419
					{
420
						require_once(SUBSDIR . '/Boards.subs.php');
421
						getBoardTree();
422
					}
423
424
					// Merge the array ;)
425
					if (!isset($context['SPortal']['block']['parameters'][$name]))
426
					{
427
						$context['SPortal']['block']['parameters'][$name] = array();
428
					}
429
					elseif (!empty($context['SPortal']['block']['parameters'][$name]) && is_array($context['SPortal']['block']['parameters'][$name]))
430
					{
431
						$context['SPortal']['block']['parameters'][$name] = implode('|', $context['SPortal']['block']['parameters'][$name]);
432
					}
433
434
					$context['SPortal']['block']['board_options'][$name] = array();
435
					$config_variable = !empty($context['SPortal']['block']['parameters'][$name]) ? $context['SPortal']['block']['parameters'][$name] : array();
436
					$config_variable = !is_array($config_variable) ? explode('|', $config_variable) : $config_variable;
437
					$context['SPortal']['block']['board_options'][$name] = array();
438
439
					// Create the list for this Item
440
					foreach ($boards as $board)
441
					{
442
						// Ignore the redirected boards :)
443
						if (!empty($board['redirect']))
444
						{
445
							continue;
446
						}
447
448
						$context['SPortal']['block']['board_options'][$name][$board['id']] = array(
449
							'value' => $board['id'],
450
							'text' => $board['name'],
451
							'selected' => in_array($board['id'], $config_variable),
452
						);
453
					}
454
				}
455
				// Prepare the Text content for BBC, only the first bbc will be correct detected!
456
				elseif ($type === 'bbc')
457
				{
458
					// ELK onlys supports one bbc correctly, multiple bbc do not work at the moment
459
					if (!$firstBBCFound)
460
					{
461
						$firstBBCFound = true;
462
463
						// Start Elk BBC System :)
464
						require_once(SUBSDIR . '/Editor.subs.php');
465
466
						// Prepare the output :D
467
						$form_message = !empty($context['SPortal']['block']['parameters'][$name]) ? $context['SPortal']['block']['parameters'][$name] : '';
468
469
						// But if it's in HTML world, turn them into htmlspecialchar's so they can be edited!
470
						if (strpos($form_message, '[html]') !== false)
471
						{
472
							$parts = preg_split('~(\[/code\]|\[code(?:=[^\]]+)?\])~i', $form_message, -1, PREG_SPLIT_DELIM_CAPTURE);
473
							for ($i = 0, $n = count($parts); $i < $n; $i++)
474
							{
475
								// It goes 0 = outside, 1 = begin tag, 2 = inside, 3 = close tag, repeat.
476
								if ($i % 4 == 0)
477
								{
478
									$parts[$i] = preg_replace_callback('~\[html\](.+?)\[/html\]~is', function ($m) {
479
										return '[html]' . preg_replace('~<br\s?/?>~i', '&lt;br /&gt;<br />', $m[1]) . '[/html]';
480
									}, $parts[$i]);
481
								}
482
							}
483
484
							$form_message = implode('', $parts);
485
						}
486
						$form_message = preg_replace('~<br(?: /)?' . '>~i', "\n", $form_message);
487
488
						// Prepare the data before i want them inside the textarea
489
						$form_message = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $form_message);
490
						$context['SPortal']['bbc'] = 'bbc_' . $name;
491
						$message_data = array(
492
							'id' => $context['SPortal']['bbc'],
493
							'width' => '95%',
494
							'height' => '200px',
495
							'value' => $form_message,
496
							'form' => 'sp_block',
497
						);
498
499
						// Run the ELK bbc editor routine
500
						create_control_richedit($message_data);
501
502
						// Store the updated data on the parameters
503
						$context['SPortal']['block']['parameters'][$name] = $form_message;
504
					}
505
					else
506
					{
507
						$context['SPortal']['block']['options'][$name] = 'textarea';
508
					}
509
				}
510
			}
511
512
			loadJavascriptFile('portal.js?sp100rc1');
513
			$context['sub_template'] = 'block_edit';
514
			$context['page_title'] = $context['SPortal']['is_new'] ? $txt['sp-blocksAdd'] : $txt['sp-blocksEdit'];
515
		}
516
517
		// Want to add / edit a block on the portal
518
		if (!empty($_POST['add_block']))
519
		{
520
			checkSession();
521
522
			// Only the admin can do php here
523
			if ($_POST['block_type'] === 'sp_php' && !allowedTo('admin_forum'))
524
			{
525
				throw new Elk_Exception('cannot_admin_forum', false);
526
			}
527
528
			// Make sure the block name is something safe
529
			if (!isset($_POST['block_name']) || Util::htmltrim(Util::htmlspecialchars($_POST['block_name'], ENT_QUOTES)) === '')
530
			{
531
				throw new Elk_Exception('error_sp_name_empty', false);
532
			}
533
534
			if ($_POST['block_type'] === 'sp_php' && !empty($_POST['parameters']['content']) && empty($modSettings['sp_disable_php_validation']))
535
			{
536
				require_once(SUBSDIR . '/DataValidator.class.php');
537
538
				$validator = new Data_Validator();
539
				$validator->validation_rules(array('content' => 'php_syntax'));
540
				$validator->validate(array('content' => $_POST['parameters']['content']));
541
				$error = $validator->validation_errors();
542
543
				if ($error)
544
				{
545
					$_SESSION['sp_error'] = $error[0];
546
					$_SESSION['sp_error_post'] = $_POST;
547
					redirectexit('action=admin;area=portalblocks;sa=' . $_REQUEST['sa'] . (!empty($_REQUEST['block_id']) ? ';block_id=' . $_REQUEST['block_id'] : ''));
548
				}
549
			}
550
551
			// If we have a block ID passed, we must be editing, so load the blocks current data
552
			if (!empty($_REQUEST['block_id']))
553
			{
554
				$current_data = current(getBlockInfo(null, $_REQUEST['block_id']));
555
			}
556
557
			// Where are we going to place this new block, before, after, no change
558
			if (!empty($_POST['placement']) && (($_POST['placement'] === 'before') || ($_POST['placement'] === 'after')))
559
			{
560
				if (!empty($current_data))
561
				{
562
					$current_row = $current_data['row'];
563
				}
564
				else
565
				{
566
					$current_row = null;
567
				}
568
569
				// Before or after the chosen block
570
				if ($_POST['placement'] === 'before')
571
				{
572
					$row = (int) $_POST['block_row'];
573
				}
574
				else
575
				{
576
					$row = (int) $_POST['block_row'] + 1;
577
				}
578
579
				if (!empty($current_row) && ($row > $current_row))
580
				{
581
					sp_update_block_row($current_row, $row - 1, $_POST['block_column']);
582
				}
583
				else
584
				{
585
					sp_update_block_row($current_row, $row, $_POST['block_column'], false);
586
				}
587
			}
588
			elseif (!empty($_POST['placement']) && $_POST['placement'] === 'nochange')
589
			{
590
				$row = 0;
591
			}
592
			else
593
			{
594
				$block_id = !empty($_REQUEST['block_id']) ? (int) $_REQUEST['block_id'] : 0;
595
				$row = sp_block_nextrow($_POST['block_column'], $block_id);
596
			}
597
598
			$block = sp_instantiate_block((string) $_POST['block_type']);
599
			$type_parameters = $block->parameters();
600
601
			if (!empty($_POST['parameters']) && is_array($_POST['parameters']) && !empty($type_parameters))
602
			{
603
				foreach ($type_parameters as $name => $type)
604
				{
605
					// Prepare BBC Content for ELK
606
					if (isset($_POST['parameters'][$name]))
607
					{
608
						$this->_prepare_parameters($type, $name);
609
					}
610
				}
611
			}
612
			else
613
			{
614
				$_POST['parameters'] = array();
615
			}
616
617
			$blockInfo = array(
618
				'id' => (int) $_POST['block_id'],
619
				'label' => Util::htmlspecialchars($_POST['block_name'], ENT_QUOTES),
620
				'type' => $_POST['block_type'],
621
				'col' => $_POST['block_column'],
622
				'row' => $row,
623
				'permissions' => (int) $_POST['permissions'],
624
				'styles' => (int) $_POST['styles'],
625
				'visibility' => (int) $_POST['visibility'],
626
				'state' => !empty($_POST['block_active']) ? 1 : 0,
627
				'force_view' => !empty($_POST['block_force']) ? 1 : 0,
628
			);
629
630
			// Insert a new block in to the portal
631
			if ($context['SPortal']['is_new'])
632
			{
633
				unset($blockInfo['id']);
634
				$blockInfo['id'] = sp_block_insert($blockInfo);
635
			}
636
			// Update one that is there
637
			else
638
			{
639
				sp_block_update($blockInfo);
640
			}
641
642
			// Save any parameters for the block
643
			if (!empty($_POST['parameters']))
644
			{
645
				sp_block_insert_parameters($_POST['parameters'], $blockInfo['id']);
646
			}
647
648
			redirectexit('action=admin;area=portalblocks');
649
		}
650
	}
651
652
	/**
653
	 * Moves get var to post for compatibility and get parameters to start params
654
	 *
655
	 * @return array
656
	 */
657
	private function _getStartParameters()
658
	{
659
		$start_parameters = array();
660
661
		if (!empty($_GET['selected_type']) && empty($_POST['selected_type']))
662
		{
663
			$_POST['selected_type'] = array($_GET['selected_type']);
664
665
			if (!empty($_GET['parameters']))
666
			{
667
				foreach ($_GET['parameters'] as $param)
668
				{
669
					if (isset($_GET[$param]))
670
					{
671
						$start_parameters[$param] = $_GET[$param];
672
					}
673
				}
674
			}
675
		}
676
677
		return $start_parameters;
678
	}
679
680
	/**
681
	 * Convert html to bbc
682
	 */
683
	private function _fixBBC()
684
	{
685
		// BBC Fix move the parameter to the correct position.
686
		if (!empty($_POST['bbc_name']))
687
		{
688
			$_POST['parameters'][$_POST['bbc_name']] = !empty($_POST[$_POST['bbc_parameter']]) ? $_POST[$_POST['bbc_parameter']] : '';
689
690
			// If we came from WYSIWYG then turn it back into BBC regardless.
691
			if (!empty($_REQUEST['bbc_' . $_POST['bbc_name'] . '_mode']) && isset($_POST['parameters'][$_POST['bbc_name']]))
692
			{
693
				require_once(SUBSDIR . '/Html2BBC.class.php');
694
				$bbc_converter = new Html_2_BBC($_POST['parameters'][$_POST['bbc_name']]);
695
				$_POST['parameters'][$_POST['bbc_name']] = $bbc_converter->get_bbc();
696
697
				// We need to unhtml it now as it gets done shortly.
698
				$_POST['parameters'][$_POST['bbc_name']] = un_htmlspecialchars($_POST['parameters'][$_POST['bbc_name']]);
699
			}
700
		}
701
	}
702
703
	/**
704
	 * Preparse the post parameters for use
705
	 *
706
	 * - Cleans them as needed an places them back in $_POST, yes ugly use of superglobals
707
	 *
708
	 * @param string $type
709
	 * @param string $name
710
	 */
711
	private function _prepare_parameters($type, $name)
712
	{
713
		if ($type === 'bbc')
714
		{
715
			$value = $_POST['parameters'][$name];
716
			require_once(SUBSDIR . '/Post.subs.php');
717
718
			// Prepare the message a bit for some additional testing.
719
			$value = Util::htmlspecialchars($value, ENT_QUOTES);
720
			PreparseCode::instance()->preparsecode($value, false);
721
722
			// Store now the correct and fixed value ;)
723
			$_POST['parameters'][$name] = $value;
724
		}
725
		elseif ($type === 'boards' || $type === 'board_select')
726
		{
727
			$_POST['parameters'][$name] = is_array($_POST['parameters'][$name]) ? implode('|', $_POST['parameters'][$name]) : $_POST['parameters'][$name];
728
		}
729
		elseif ($type === 'int' || $type === 'select')
730
		{
731
			$_POST['parameters'][$name] = (int) $_POST['parameters'][$name];
732
		}
733
		elseif ($type === 'text' || $type === 'textarea' || is_array($type))
734
		{
735
			$_POST['parameters'][$name] = Util::htmlspecialchars($_POST['parameters'][$name], ENT_QUOTES);
736
		}
737
		elseif ($type === 'check')
738
		{
739
			$_POST['parameters'][$name] = !empty($_POST['parameters'][$name]) ? 1 : 0;
740
		}
741
	}
742
743
	/**
744
	 * Reorders the blocks in response to a D&D ajax request
745
	 */
746
	public function action_blockorder()
747
	{
748
		global $context, $txt;
749
750
		// Start off with nothing
751
		$context['xml_data'] = array();
752
		$errors = array();
753
		$order = array();
754
755
		// Chances are
756
		loadLanguage('Errors');
757
		loadLanguage('SPortalAdmin');
758
759
		// You have to be allowed to do this
760
		$validation_token = validateToken('admin-sort', 'post', true, false);
761
		$validation_session = validateSession();
762
763
		if ($validation_session === true && $validation_token === true)
764
		{
765
			// No questions that we are reordering the blocks
766
			if (isset($_POST['order'], $_POST['received'], $_POST['moved']))
767
			{
768
				require_once(SUBSDIR . '/PortalAdmin.subs.php');
769
				require_once(SUBSDIR . '/Portal.subs.php');
770
771
				$target_side = (int) str_replace('side_', '', $_POST['received']);
772
				$block_id = (int) str_replace('block_', '', $_POST['moved']);
773
				list ($current_side,) = sp_block_get_position($block_id);
774
775
				// The block ids arrive in 1-n view order ...
776
				$blocks = $_POST['block'];
777
778
				// Find where the moved block is in the block stack
779
				$moved_key = array_search($block_id, $blocks);
780
				if ($moved_key !== false)
781
				{
782
					$check_above_row = 0;
783
					$check_below_row = 0;
784
785
					// Find the details about the blocks above and below our moved one
786
					if ($moved_key !== 0)
787
					{
788
						list ($check_above_side, $check_above_row) = sp_block_get_position($blocks[$moved_key - 1]);
789
					}
790
791
					if ($moved_key + 1 < count($blocks))
792
					{
793
						list ($check_below_side, $check_below_row) = sp_block_get_position($blocks[$moved_key + 1]);
794
					}
795
796
					// The block above is in the same side, so we place it after that block
797
					if (isset($check_above_side) && $check_above_side == $target_side)
798
					{
799
						$target_row = $check_above_row + 1;
800
					}
801
					// The block above is not in the same side, but the block below is, move it above that one
802
					elseif (isset($check_below_side) && $check_below_side == $target_side)
803
					{
804
						$target_row = $check_below_row;
805
					}
806
					// Perhaps the first in what was an empty side or "other"
807
					else
808
					{
809
						$target_row = sp_block_nextrow($target_side);
810
					}
811
812
					// Is the block moving sides?
813
					if ($current_side != $target_side)
814
					{
815
						sp_block_move_col($block_id, $target_side);
816
					}
817
818
					// Position it in right row in the side
819
					sp_blocks_move_row($block_id, $target_side, $target_row);
820
821
					// Update the sides that may have been affected
822
					foreach (array_unique(array($current_side, $target_side)) as $side)
823
					{
824
						fixColumnRows($side);
825
					}
826
827
					$order[] = array(
828
						'value' => $txt['sp-blocks_success_moving'],
829
					);
830
				}
831
				else
832
				{
833
					$errors[] = array('value' => $txt['sp-blocks_fail_moving']);
834
				}
835
			}
836
		}
837
		// Failed validation, tough to be you
838
		else
839
		{
840
			if (!empty($validation_session) && $validation_session !== true)
841
			{
842
				$errors[] = array('value' => $txt['session_verify_fail'] . ' (' . $validation_session . ')');
843
			}
844
845
			if (empty($validation_token))
846
			{
847
				$errors[] = array('value' => $txt['token_verify_fail']);
848
			}
849
		}
850
851
		// New generic token for use
852
		createToken('admin-sort');
853
		$tokens = array(
854
			array(
855
				'value' => $context['admin-sort_token'],
856
				'attributes' => array('type' => 'token'),
857
			),
858
			array(
859
				'value' => $context['admin-sort_token_var'],
860
				'attributes' => array('type' => 'token_var'),
861
			),
862
		);
863
864
		// Return the response
865
		$context['sub_template'] = 'generic_xml';
866
		$context['xml_data'] = array(
867
			'orders' => array(
868
				'identifier' => 'order',
869
				'children' => $order,
870
			),
871
			'tokens' => array(
872
				'identifier' => 'token',
873
				'children' => $tokens,
874
			),
875
			'errors' => array(
876
				'identifier' => 'error',
877
				'children' => $errors,
878
			),
879
		);
880
	}
881
882
	/**
883
	 * Function for moving a block
884
	 *
885
	 * - Moves a block to a new row and/or a new column
886
	 */
887
	public function action_move()
888
	{
889
		checkSession('get');
890
891
		// What block is being moved?
892
		if (empty($_REQUEST['block_id']))
893
		{
894
			throw new Elk_Exception('error_sp_id_empty', false);
895
		}
896
		else
897
		{
898
			$block_id = (int) $_REQUEST['block_id'];
899
		}
900
901
		// Can't move outside our known columns 1-6
902
		if (empty($_REQUEST['col']) || $_REQUEST['col'] < 1 || $_REQUEST['col'] > 6)
903
		{
904
			throw new Elk_Exception('error_sp_side_wrong', false);
905
		}
906
		else
907
		{
908
			$target_side = (int) $_REQUEST['col'];
909
		}
910
911
		// Specific row requested?
912
		if (empty($_REQUEST['row']))
913
		{
914
			$target_row = sp_block_nextrow($target_side);
915
		}
916
		else
917
		{
918
			$target_row = (int) $_REQUEST['row'];
919
		}
920
921
		// Get the blocks current position in the portal
922
		list ($current_side, $current_row) = sp_block_get_position($block_id);
923
924
		// Is a move needed, new row, new column?
925
		if ($current_side != $target_side || $current_row + 1 != $target_row)
926
		{
927
			// Shift the column
928
			if ($current_side != $target_side)
929
			{
930
				sp_block_move_col($block_id, $target_side);
931
			}
932
933
			// Position it in the column
934
			sp_blocks_move_row($block_id, $target_side, $target_row);
935
936
			foreach (array_unique(array($current_side, $target_side)) as $side)
937
			{
938
				fixColumnRows($side);
939
			}
940
		}
941
942
		redirectexit('action=admin;area=portalblocks');
943
	}
944
945
	/**
946
	 * Function for deleting a block.
947
	 */
948
	public function action_delete()
949
	{
950
		global $context;
951
952
		// Check if he can?
953
		checkSession('get');
954
955
		// Make sure ID is an integer.
956
		$_REQUEST['block_id'] = (int) $_REQUEST['block_id'];
957
958
		// Do we have that?
959
		if (empty($_REQUEST['block_id']))
960
		{
961
			throw new Elk_Exception('error_sp_id_empty', false);
962
		}
963
964
		// Make sure column ID is an integer too.
965
		$_REQUEST['col'] = (int) $_REQUEST['col'];
966
967
		// Only Admins can Remove PHP Blocks
968
		if (!allowedTo('admin_forum'))
969
		{
970
			$context['SPortal']['block'] = current(getBlockInfo(null, $_REQUEST['block_id']));
971
			if ($context['SPortal']['block']['type'] === 'sp_php' && !allowedTo('admin_forum'))
972
			{
973
				throw new Elk_Exception('cannot_admin_forum', false);
974
			}
975
		}
976
977
		// We don't need it anymore.
978
		sp_block_delete($_REQUEST['block_id']);
979
980
		// Fix column rows.
981
		fixColumnRows($_REQUEST['col']);
982
983
		// Return back to the block list.
984
		redirectexit('action=admin;area=portalblocks');
985
	}
986
987
	/**
988
	 * Pass this off to the state change function
989
	 */
990
	public function action_state_change()
991
	{
992
		global $context;
993
994
		checkSession(isset($_REQUEST['xml']) ? '' : 'get');
995
996
		$id = (int) $_REQUEST['block_id'];
997
		$state = sp_changeState('block', $id);
998
		$sides = array(1 => 'left', 2 => 'top', 3 => 'bottom', 4 => 'right');
999
		$list = !empty($_GET['redirect']) && isset($sides[$_GET['redirect']]) ? $sides[$_GET['redirect']] : 'list';
1000
1001
		// Doing this the ajax way?
1002
		if (isset($_REQUEST['xml']))
1003
		{
1004
			$context['item_id'] = $id;
1005
			$context['status'] = !empty($state) ? 'active' : 'deactive';
1006
1007
			// Clear out any template layers, add the xml response
1008
			loadTemplate('PortalAdmin');
1009
			$template_layers = Template_Layers::instance();
1010
			$template_layers->removeAll();
1011
			$context['sub_template'] = 'change_status';
1012
1013
			obExit();
1014
		}
1015
1016
		redirectexit('action=admin;area=portalblocks;sa=' . $list);
1017
	}
1018
}
1019