Completed
Pull Request — develop-stable (#68)
by Paul
03:11 queued 01:05
created

main_controller::post()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 51
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 3 Features 1
Metric Value
c 6
b 3
f 1
dl 0
loc 51
rs 6.9744
cc 7
eloc 27
nc 6
nop 0

How to fix   Long Method   

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
 * Ajax Shoutbox extension for the phpBB Forum Software package.
5
 *
6
 * @copyright (c) 2014 Paul Sohier <http://www.ajax-shoutbox.com>
7
 * @license       GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace paul999\ajaxshoutbox\controller;
12
13
use Symfony\Component\HttpFoundation\JsonResponse;
14
15
/**
16
 * Main controller
17
 */
18
class main_controller
19
{
20
	/** @var \phpbb\config\config */
21
	protected $config;
22
	/** @var \phpbb\controller\helper */
23
	protected $helper;
24
	/** @var \phpbb\template\template */
25
	protected $template;
26
	/** @var \phpbb\user */
27
	protected $user;
28
	/** @var string phpBB root path */
29
	protected $root_path;
30
	/** @var string phpEx */
31
	protected $php_ext;
32
33
	/** @var \phpbb\request\request */
34
	private $request;
35
36
	/** @var \phpbb\db\driver\driver_interface */
37
	private $db;
38
39
	/** @var \phpbb\auth\auth */
40
	private $auth;
41
42
	/** @var \phpbb\log\log  */
43
	private $log;
44
45
	/** @var \paul999\ajaxshoutbox\actions\Delete  */
46
	private $delete;
47
48
	/** @var  string */
49
	private $table;
50
51
	/** @var string */
52
	private $usertable;
53
54
	/**
55
	 * @param \phpbb\config\config                 $config
56
	 * @param \phpbb\controller\helper             $helper
57
	 * @param \phpbb\template\template             $template
58
	 * @param \phpbb\user                          $user
59
	 * @param \phpbb\request\request               $request
60
	 * @param \phpbb\db\driver\driver_interface    $db
61
	 * @param \phpbb\auth\auth                     $auth
62
	 * @param \phpbb\log\log                       $log
63
	 * @param \paul999\ajaxshoutbox\actions\delete $delete
64
	 * @param string                               $root_path
65
	 * @param string                               $php_ext
66
	 * @param string                               $table
67
	 * @param string                               $usertable
68
	 */
69
	public function __construct(\phpbb\config\config $config, \phpbb\controller\helper $helper,
70
								\phpbb\template\template $template, \phpbb\user $user, \phpbb\request\request $request,
71
								\phpbb\db\driver\driver_interface $db, \phpbb\auth\auth $auth, \phpbb\log\log $log,
72
								\paul999\ajaxshoutbox\actions\delete $delete,
73
								$root_path, $php_ext, $table, $usertable)
74
	{
75
		$this->config    = $config;
76
		$this->helper    = $helper;
77
		$this->template  = $template;
78
		$this->user      = $user;
79
		$this->request   = $request;
80
		$this->db        = $db;
81
		$this->auth      = $auth;
82
		$this->log       = $log;
83
		$this->delete    = $delete;
84
		$this->root_path = $root_path;
85
		$this->php_ext   = $php_ext;
86
		$this->table     = $table;
87
		$this->usertable = $usertable;
88
89
		$this->user->add_lang_ext("paul999/ajaxshoutbox", "ajax_shoutbox");
90
	}
91
92
	/**
93
	 * Validate the push connection with shoutbox-app.com
94
	 *
95
	 * @param $id
96
	 *
97
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
98
	 */
99
	public function validate($id)
100
	{
101
		$result = array();
102
103
		// Language used here won't be seen by the user.
104
		// It is used on shoutbox-app.com to specify the result.
105
		// Do not change.
106
		if ($this->config['ajaxshoutbox_push_enabled'])
107
		{
108
			if ($id == $this->config['ajaxshoutbox_validation_id'])
109
			{
110
				$result['ok'] = 'ok';
111
				$result['key'] = $this->config['ajaxshoutbox_validation_id'];
112
			}
113
			else
114
			{
115
				$result['error'] = 'Incorrect key';
116
			}
117
		}
118
		else
119
		{
120
			$result['error'] = 'disabled';
121
		}
122
123
		return new JsonResponse(array($result));
124
	}
125
126
	/**
127
	 * Post a new message to the shoutbox.
128
	 *
129
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
130
	 */
131
	public function post()
132
	{
133
		// We always disallow guests to post in the shoutbox.
134
		if (!$this->auth->acl_get('u_shoutbox_post') || $this->user->data['user_id'] == ANONYMOUS)
0 ignored issues
show
Bug introduced by
The property data cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
135
		{
136
			return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_NO_PERMISSION', 403);
137
		}
138
139
		if (!check_form_key('ajaxshoutbox_posting', 3600 * 12)) // Allow 12 hours.
140
		{
141
			return $this->error('AJAX_SHOUTBOX_ERROR', 'FORM_INVALID', 500);
142
		}
143
144
		if ($this->request->is_ajax())
145
		{
146
			$message = $msg     = trim($this->request->variable('text_shoutbox', '', true));
147
148
			if (empty($message))
149
			{
150
				return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_MESSAGE_EMPTY', 500);
151
			}
152
153
			$uid          = $bitfield = $options = '';
154
			$allow_bbcode = $this->auth->acl_get('u_shoutbox_bbcode');
155
			$allow_urls   = $allow_smilies = true;
156
157
			if (!function_exists('generate_text_for_storage'))
158
			{
159
				include($this->root_path . 'includes/functions_content.' . $this->php_ext);
160
			}
161
162
			generate_text_for_storage($message, $uid, $bitfield, $options, $allow_bbcode, $allow_urls, $allow_smilies);
163
164
			$insert = array(
165
				'post_message'    => $message,
166
				'post_time'       => time(),
167
				'user_id'         => $this->user->data['user_id'],
0 ignored issues
show
Bug introduced by
The property data cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
168
				'bbcode_options'  => $options,
169
				'bbcode_bitfield' => $bitfield,
170
				'bbcode_uid'      => $uid,
171
			);
172
			$sql    = 'INSERT INTO ' . $this->table . ' ' . $this->db->sql_build_array('INSERT', $insert);
173
			$this->db->sql_query($sql);
174
175
			return new JsonResponse(array('OK'));
176
		}
177
		else
178
		{
179
			return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_ONLY_AJAX', 500);
180
		}
181
	}
182
183
	/**
184
	 * Delete a post from the client.
185
	 *
186
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
187
	 */
188
	public function delete()
189
	{
190
		$id = $this->request->variable('id', 0, false, \phpbb\request\request_interface::POST);
191
192
		if (!$id)
193
		{
194
			return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_MISSING_ID', 500);
195
		}
196
197
		if (!check_form_key('ajaxshoutbox_delete_' . $id)) // Every delete form has its unique form key, based on ID.
198
		{
199
			return $this->error('AJAX_SHOUTBOX_ERROR', 'FORM_INVALID', 500);
200
		}
201
202
		try
203
		{
204
			$this->delete->delete_post($id);
205
		}
206
		catch (\paul999\ajaxshoutbox\exceptions\shoutbox_exception $exception)
207
		{
208
			return $this->error('AJAX_SHOUTBOX_ERROR', $exception->getMessage(), 500);
209
		}
210
		return new JsonResponse(array('OK'));
211
	}
212
213
	/**
214
	 * Get the last 10 shouts
215
	 *
216
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
217
	 */
218
	public function getAll()
219
	{
220
		if (!$this->auth->acl_get('u_shoutbox_view'))
221
		{
222
			return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_NO_PERMISSION', 403);
223
		}
224
225
		$sql    = 'SELECT c.*, u.username, u.user_colour FROM
226
					' . $this->table . ' c,
227
					' . $this->usertable . ' u
228
					WHERE
229
						u.user_id = c.user_id
230
					ORDER BY post_time DESC';
231
		$result = $this->db->sql_query_limit($sql, 10);
232
233
		return $this->returnPosts($result);
234
	}
235
236
	/**
237
	 * Get all shouts since a specific shout ID.
238
	 *
239
	 * @param int $id Last selected ID.
240
	 *
241
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
242
	 */
243 View Code Duplication
	public function getAfter($id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
244
	{
245
		if (!$this->auth->acl_get('u_shoutbox_view'))
246
		{
247
			return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_NO_PERMISSION', 403);
248
		}
249
250
		$sql    = 'SELECT c.*, u.username, u.user_colour FROM
251
				' . $this->table . ' c,
252
				' . $this->usertable . ' u
253
				WHERE post_time >= (
254
						SELECT post_time FROM ' . $this->table . '
255
						WHERE shout_id = ' . (int) $id . '
256
					)
257
					AND c.shout_id != ' . (int) $id . '
258
					AND u.user_id = c.user_id
259
				ORDER BY post_time DESC, shout_id DESC';
260
		$result = $this->db->sql_query($sql);
261
262
		return $this->returnPosts($result);
263
	}
264
265
	/**
266
	 * Get 10 shouts before the current shout ID.
267
	 *
268
	 * @param $id
269
	 *
270
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
271
	 */
272 View Code Duplication
	public function getBefore($id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
273
	{
274
		if (!$this->auth->acl_get('u_shoutbox_view'))
275
		{
276
			return $this->error('AJAX_SHOUTBOX_ERROR', 'AJAX_SHOUTBOX_NO_PERMISSION', 403);
277
		}
278
279
		$sql    = 'SELECT c.*, u.username, u.user_colour FROM
280
				' . $this->table . ' c,
281
				' . $this->usertable . ' u
282
				WHERE post_time <= (
283
						SELECT post_time FROM ' . $this->table . '
284
						WHERE shout_id = ' . (int) $id . '
285
					)
286
					AND c.shout_id != ' . (int) $id . '
287
					AND u.user_id = c.user_id
288
				ORDER BY post_time DESC, shout_id ASC';
289
		$result = $this->db->sql_query_limit($sql, 10);
290
291
		return $this->returnPosts($result, false);
292
	}
293
294
	/**
295
	 * Loop over a SQL result set, and generate a JSON array based on the post data.
296
	 *
297
	 * @param mixed $result return the data for the posts
298
	 * @param bool  $reverse
299
	 *
300
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
301
	 */
302
	private function returnPosts($result, $reverse = true)
303
	{
304
		$posts = array();
305
306
		while ($row = $this->db->sql_fetchrow($result))
307
		{
308
			$posts[] = $this->getPost($row);
309
		}
310
		$this->db->sql_freeresult($result);
311
312
		return new JsonResponse($reverse ? array_reverse($posts) : $posts);
313
	}
314
315
	/**
316
	 * Generate a array with the specific post for this shout.
317
	 *
318
	 * @param array $row Input row
319
	 *
320
	 * @return array output
321
	 */
322
	private function getPost($row)
323
	{
324
		if (!defined('PHPBB_USE_BOARD_URL_PATH'))
325
		{
326
			define('PHPBB_USE_BOARD_URL_PATH', true); // Require full URL to smilies.
327
		}
328
329
		$text = generate_text_for_display(
330
			$row['post_message'], $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']
331
		);
332
333
		$username = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']);
334
		$username = str_replace('./../../', generate_board_url() . '/', $username); // Fix paths
335
		$username = str_replace('./../', generate_board_url() . '/', $username); // Fix paths
336
337
		$result = array(
338
			'id'      => $row['shout_id'],
339
			'user'    => $username,
340
			'date'    => $this->user->format_date($row['post_time'], $this->user->data['user_ajaxshoutbox_format']),
0 ignored issues
show
Bug introduced by
The property data cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
341
			'message' => $text,
342
			'delete'  => ($this->auth->acl_get('m_shoutbox_delete') || ($this->auth->acl_get('u_shoutbox_delete') && $row['user_id'] == $this->user->data['user_id'])),
0 ignored issues
show
Bug introduced by
The property data cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
343
		);
344
345
		return array_merge($result, $this->add_form_key('ajaxshoutbox_delete_' . $row['shout_id']));
346
	}
347
348
	/**
349
	 * Send a error to the user.
350
	 *
351
	 * Important: phpBB (<= 3.1.2) handles non 200 status as error.
352
	 * Due to the way this is implemented, phpBB will display the browser
353
	 * generated error, instead of the user returned error.
354
	 * This method will result in a 200 OK, but the correct status is in
355
	 * the JsonResponse.status.
356
	 *
357
	 * @param string $title
358
	 * @param string $message
359
	 * @param integer $status
360
	 *
361
	 * @return \Symfony\Component\HttpFoundation\JsonResponse
362
	 */
363
	private function error($title, $message, $status)
364
	{
365
		$json = new JsonResponse(array(
366
			'title'     => $this->user->lang[$title],
0 ignored issues
show
Bug introduced by
The property lang cannot be accessed from this context as it is declared private in class phpbb\user.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
367
			'error'     => $this->user->lang[$message],
0 ignored issues
show
Bug introduced by
The property lang cannot be accessed from this context as it is declared private in class phpbb\user.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
368
			'status'    => $status,
369
		));
370
371
		return $json;
372
	}
373
374
	/**
375
	 * Add a secret token and returns it as array with creation_time and form_token.
376
	 *
377
	 * Based on phpBB's add_form_key. Compatible with check_form_key.
378
	 *
379
	 * IMPORTANT: The original event is not included, because the form is build before the event,
380
	 * while this function returns the (Possible modified) data after the event.
381
	 *
382
	 * @param string $form_name The name of the form; has to match the name used in check_form_key, otherwise no
383
	 *                          restrictions apply
384
	 *
385
	 * @return array
386
	 */
387
	function add_form_key($form_name)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
388
	{
389
		$now = time();
390
		$token_sid = ($this->user->data['user_id'] == ANONYMOUS && !empty($this->config['form_token_sid_guests'])) ? $this->user->session_id : '';
0 ignored issues
show
Bug introduced by
The property data cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
Bug introduced by
The property session_id cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
391
		$token = sha1($now . $this->user->data['user_form_salt'] . $form_name . $token_sid);
0 ignored issues
show
Bug introduced by
The property data cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
392
393
		return array(
394
			'creation_time' => $now,
395
			'form_token' => $token,
396
		);
397
	}
398
}
399