Completed
Push — master ( d91f33...8c195c )
by Nazar
09:16 queued 03:58
created

Comments::add()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 6
eloc 14
c 3
b 1
f 0
nc 6
nop 4
dl 0
loc 19
rs 8.8571
1
<?php
2
/**
3
 * @package   Comments
4
 * @category  modules
5
 * @author    Nazar Mokrynskyi <[email protected]>
6
 * @copyright Copyright (c) 2011-2016, Nazar Mokrynskyi
7
 * @license   MIT License, see license.txt
8
 */
9
namespace cs\modules\Comments;
10
use
11
	h,
12
	cs\Cache,
13
	cs\Config,
14
	cs\Language,
15
	cs\Request,
16
	cs\User,
17
	cs\CRUD_helpers,
18
	cs\Singleton;
19
20
/**
21
 * @method static $this instance($check = false)
22
 */
23
class Comments {
24
	use
25
		CRUD_helpers,
26
		Singleton;
27
28
	/**
29
	 * @var Cache\Prefix
30
	 */
31
	protected $cache;
32
	/**
33
	 * @var int    Avatar size in px, can be redefined
34
	 */
35
	public $avatar_size = 36;
36
37
	protected $data_model = [
38
		'id'     => 'int:1',
39
		'parent' => 'int:0',
40
		'module' => 'text',
41
		'item'   => 'int:1',
42
		'user'   => 'int:1',
43
		'date'   => 'int:1',
44
		'text'   => 'html',
45
		'lang'   => 'text'
46
	];
47
48
	protected $table = '[prefix]comments';
49
50
	protected function construct () {
51
		$this->cache = Cache::prefix('Comments');
52
	}
53
	/**
54
	 * Returns database index
55
	 *
56
	 * @return int
57
	 */
58
	protected function cdb () {
59
		return Config::instance()->module('Comments')->db('comments');
60
	}
61
	/**
62
	 * Get comment data
63
	 *
64
	 * @param int|int[] $id
65
	 *
66
	 * @return array|false
67
	 */
68
	function get ($id) {
69
		return $this->read($id);
70
	}
71
	/**
72
	 * @param string $module
73
	 * @param int    $item
74
	 *
75
	 * @return int[]
1 ignored issue
show
Documentation introduced by
Should the return type not be integer|array|double|string? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
76
	 */
77
	function get_for_module_item ($module, $item) {
78
		$search_parameters = [
79
			'module' => $module,
80
			'item'   => $item
81
		];
82
		return $this->search($search_parameters, 1, PHP_INT_MAX, 'id', true) ?: [];
83
	}
84
	/**
85
	 * Add new comment
86
	 *
87
	 * @param int    $item   Item id
88
	 * @param string $module Module name
89
	 * @param string $text   Comment text
90
	 * @param int    $parent Parent comment id
91
	 *
92
	 * @return false|int
93
	 */
94
	function add ($item, $module, $text, $parent = 0) {
95
		$L    = Language::instance();
96
		$User = User::instance();
97
		$text = xap($text, true);
98
		if (!$text) {
99
			return false;
100
		}
101
		if ($parent) {
102
			$parent_comment = $this->read($parent);
103
			if ($parent_comment['item'] != $item || $parent_comment['module'] != $module) {
104
				return false;
105
			}
106
		}
107
		$id = $this->create($parent, $module, $item, $User->id, time(), $text, $L->clang);
108
		if ($id) {
109
			$this->cache->del("$module/$item");
110
		}
111
		return $id;
112
	}
113
	/**
114
	 * Set comment text
115
	 *
116
	 * @param int    $id
117
	 * @param string $text
118
	 *
119
	 * @return bool
120
	 */
121
	function set ($id, $text) {
122
		$text = xap($text, true);
123
		if (!$text) {
124
			return false;
125
		}
126
		$comment = $this->get($id);
127
		if (!$comment) {
128
			return false;
129
		}
130
		$comment['text'] = $text;
131
		$result          = $this->update($comment);
132
		if ($result) {
133
			$this->cache->del("$comment[module]/$comment[item]");
134
		}
135
		return $result;
136
	}
137
	/**
138
	 * Delete comment
139
	 *
140
	 * @param int $id
141
	 *
142
	 * @return bool
143
	 */
144
	function del ($id) {
145
		$comment = $this->read($id);
146
		if (
147
			!$comment ||
148
			$this->search(
149
				[
150
					'parent'      => $id,
151
					'total_count' => true
152
				]
153
			)
154
		) {
155
			return false;
156
		}
157
		$result = $this->delete($id);
158
		if ($result) {
159
			$this->cache->del("$comment[module]/$comment[item]");
160
		}
161
		return $result;
162
	}
163
	/**
164
	 * Delete all comments of specified item
165
	 *
166
	 * @param int    $item   Item id
167
	 * @param string $module Module name
168
	 *
169
	 * @return bool
170
	 */
171
	function del_all ($item, $module) {
172
		$item   = (int)$item;
173
		$result = $this->db_prime()->q(
174
			"DELETE FROM `[prefix]comments`
175
			WHERE
176
				`module`	= '%s' AND
177
				`item`		= '%d'",
178
			$module,
179
			$item
180
		);
181
		if ($result) {
182
			$this->cache->del("$module/$item");
183
		}
184
		return (bool)$result;
185
	}
186
	/**
187
	 * Count of comments for specified item
188
	 *
189
	 * @param int    $item   Item id
190
	 * @param string $module Module name
191
	 *
192
	 * @return int
193
	 */
194
	function count ($item, $module) {
195
		$item = (int)$item;
196
		$L    = Language::instance();
197
		return $this->cache->get(
198
			"$module/$item/count/$L->clang",
199
			function () use ($item, $module, $L) {
200
				return $this->search(
201
					[
202
						'module'      => $module,
203
						'item'        => $item,
204
						'lang'        => $L->clang,
205
						'total_count' => true
206
					]
207
				);
208
			}
209
		);
210
	}
211
	/**
212
	 * Get comments tree in html format for specified item (look at ::block() method before usage)
213
	 *
214
	 * @param int    $item   Item id
215
	 * @param string $module Module name
216
	 *
217
	 * @return string
218
	 */
219
	function tree ($item, $module) {
220
		return $this->tree_html($this->tree_data($item, $module) ?: []);
221
	}
222
	/**
223
	 * Get comments structure of specified item
224
	 *
225
	 * @param int			$item
226
	 * @param string		$module
227
	 * @param int			$parent
228
	 *
229
	 * @return false|array
230
	 */
231
	function tree_data ($item, $module, $parent = 0) {
232
		$Cache	= $this->cache;
233
		$L		= Language::instance();
234
		if (($comments = $Cache->{"$module/$item/$L->clang"}) === false) {
235
			$item		= (int)$item;
236
			$parent		= (int)$parent;
237
			$comments	= $this->db()->qfa(
238
				"SELECT
239
					`id`,
240
					`parent`,
241
					`user`,
242
					`date`,
243
					`text`,
244
					`lang`
245
				FROM `[prefix]comments`
246
				WHERE
247
					`parent`	= '%d' AND
248
					`item`		= '%d' AND
249
					`module`	= '%s' AND
250
					`lang`		= '%s'",
251
				$parent,
252
				$item,
253
				$module,
254
				$L->clang
255
			) ?: [];
256
			foreach ($comments as &$comment) {
257
				$comment['comments'] = $this->tree_data($item, $module, $comment['id']);
258
			}
259
			unset($comment);
260
			/**
261
			 * Cache only root tree data
262
			 */
263
			if ($parent == 0) {
264
				$Cache->{"$module/$item/$L->clang"}	= $comments;
265
			}
266
		}
267
		return $comments;
268
	}
269
	/**
270
	 * Get comments tree in html format for given data structure (usually uses ::tree_data() method)
271
	 *
272
	 * @param array[]	$comments
273
	 *
274
	 * @return string
275
	 */
276
	function tree_html ($comments) {
277
		$L			= Language::instance();
278
		$User		= User::instance();
279
		if (!is_array($comments) || !$comments) {
280
			return '';
281
		}
282
		$content	= '';
283
		foreach ($comments as $comment) {
284
			$uniqid		= uniqid('comment_', true);
285
			$content	.= str_replace($uniqid, $comment['text'], h::{'article.cs-comments-comment'}(
286
				h::{'img.cs-comments-comment-avatar'}([
287
					'src'	=> $User->avatar($this->avatar_size, $comment['user']),
288
					'alt'	=> $User->username($comment['user']),
289
					'title'	=> $User->username($comment['user'])
290
				]).
291
				h::span($User->username($comment['user'])).
292
				h::{'time.cs-comments-comment-date'}(
293
					date('dmY', time()) == date('dmY', $comment['date']) ?
294
						date($L->_time, $comment['date']) : $L->to_locale(date($L->_datetime, $comment['date'])),
295
					[
296
						'datetime'		=> date('c', $comment['date'])
297
					]
298
				).
299
				h::{'a.cs-comments-comment-link'}(
300
					h::icon('anchor'),
301
					[
302
						'href'	=> "#comment_$comment[id]"
303
					]
304
				).
305
				(
306
					$comment['parent'] ? h::{'a.cs-comments-comment-parent'}(
307
						h::icon('level-up'),
308
						[
309
							'href'	=> "#comment_$comment[parent]"
310
						]
311
					) : ''
312
				).
313
				(
314
					$User->id == $comment['user'] || $User->admin() ? h::{'icon.cs-comments-comment-edit.cs-cursor-pointer'}('pencil') : ''
315
				).
316
				(
317
					!$comment['comments'] &&
318
					(
319
						$User->id == $comment['user'] || $User->admin()
320
					) ? h::{'icon.cs-comments-comment-delete.cs-cursor-pointer'}('trash-o') : ''
321
				).
322
				h::{'div.cs-comments-comment-text'}($uniqid).
323
				(
324
					$comment['comments'] ? $this->tree_html($comment['comments']) : ''
325
				),
326
				[
327
					'id'	=> "comment_$comment[id]"
328
				]
329
			));
330
		}
331
		return $content;
332
	}
333
	/**
334
	 * Get comments block with comments tree and comments sending form
335
	 *
336
	 * @param int    $item   Item id
337
	 * @param string $module Module name
338
	 *
339
	 * @return string
340
	 */
341
	function block ($item, $module) {
342
		$L	= Language::prefix('comments_');
343
		return h::{'section#comments.cs-comments-comments'}(
344
			$L->comments.':'.
345
			(
346
				$this->tree($item, $module) ?: h::{'article.cs-blogs-no-comments'}($L->no_comments_yet)
347
			)
348
		).
349
		h::{'p.cs-comments-add-comment'}("$L->add_comment:").
350
		(
351
			User::instance()->user() ? h::{'section.cs-comments-comment-write'}(
352
				h::{'cs-editor-simple textarea.cs-comments-comment-write-text[is=cs-textarea][autosize]'}(
353
					'',
354
					[
355
						'data-item'		=> $item,
356
						'data-parent'	=> 0,
357
						'data-id'		=> 0,
358
						'data-module'	=> $module
359
					]
360
				).
361
				h::br().
362
				h::{'button.cs-comments-comment-write-send[is=cs-button]'}(
363
					$L->send_comment
364
				).
365
				h::{'button.cs-comments-comment-write-edit[is=cs-button]'}(
366
					$L->save,
367
					[
368
						'style'	=>	'display: none'
369
					]
370
				).
371
				h::{'button.cs-comments-comment-write-cancel[is=cs-button]'}(
372
					$L->cancel,
373
					[
374
						'style'	=>	'display: none'
375
					]
376
				)
377
			) : h::p($L->register_for_comments_sending)
378
		);
379
	}
380
}
381