1 <?php
2
3 4 5 6 7 8 9 10
11
12 namespace Icybee\Modules\Comments;
13
14 use ICanBoogie\Debug;
15 use ICanBoogie\Event;
16 use ICanBoogie\Exception;
17 use ICanBoogie\I18n;
18 use ICanBoogie\Operation;
19
20 use Brickrouge\Element;
21 use Brickrouge\Form;
22 use Brickrouge\Text;
23
24 use Icybee\Modules\Nodes\Node;
25
26 class Hooks
27 {
28 29 30
31
32 static public function before_node_save(Operation\BeforeProcessEvent $event, \Icybee\Modules\Nodes\SaveOperation $sender)
33 {
34 $request = $event->request;
35
36 if (isset($request['metas']['comments/reply']))
37 {
38 $metas = &$request->params['metas']['comments/reply'];
39
40 $metas += array
41 (
42 'is_notify' => null
43 );
44
45 $metas['is_notify'] = filter_var($metas['is_notify'], FILTER_VALIDATE_BOOLEAN);
46 }
47 }
48
49 50 51 52 53 54
55 static public function on_node_delete(Operation\ProcessEvent $event, \Icybee\Modules\Nodes\DeleteOperation $operation)
56 {
57 global $core;
58
59 try
60 {
61 $model = $core->models['comments'];
62 }
63 catch (\Exception $e)
64 {
65 return;
66 }
67
68 $ids = $model->select('{primary}')->filter_by_nid($operation->key)->all(\PDO::FETCH_COLUMN);
69
70 foreach ($ids as $commentid)
71 {
72 $model->delete($commentid);
73 }
74 }
75
76 77 78 79 80 81
82 static public function on_node_collect_dependencies(\ICanBoogie\ActiveRecord\CollectDependenciesEvent $event, \Icybee\Modules\Nodes\Node $target)
83 {
84 global $core;
85
86 $records = $core->models['comments']->filter_by_nid($target->nid)->order('created_at DESC')->all;
87
88 foreach ($records as $record)
89 {
90 $event->add('comments', $record->commentid, \ICanBoogie\shorten($record->contents, 48, 1), true, $record->url);
91 }
92 }
93
94 static public function alter_block_edit(Event $event)
95 {
96 global $core;
97
98 if (!isset($core->modules['comments']))
99 {
100 return;
101 }
102
103 $values = null;
104 $key = 'comments/reply';
105 $metas_prefix = 'metas[' . $key . ']';
106
107 if ($event->entry)
108 {
109 $entry = $event->entry;
110
111 $values = array
112 (
113 $metas_prefix => unserialize($entry->metas[$key])
114 );
115 }
116
117 $ns = \ICanBoogie\escape($metas_prefix);
118
119 $event->tags = \ICanBoogie\array_merge_recursive
120 (
121 $event->tags, array
122 (
123 Form::VALUES => $values ? $values : array(),
124
125 Element::CHILDREN => array
126 (
127 $key => new Element\Templated
128 (
129 'div', array
130 (
131 Element::GROUP => 'notify',
132 Element::CHILDREN => array
133 (
134 $metas_prefix . '[is_notify]' => new Element
135 (
136 Element::TYPE_CHECKBOX, array
137 (
138 Element::LABEL => 'Activer la notification aux réponses',
139 Element::DESCRIPTION => "Cette option déclanche l'envoi
140 d'un email à l'auteur ayant choisi d'être informé d'une
141 réponse à son commentaire."
142 )
143 ),
144
145 $metas_prefix . '[from]' => new Text
146 (
147 array
148 (
149 Form::LABEL => 'Adresse d\'expédition'
150 )
151 ),
152
153 $metas_prefix . '[bcc]' => new Text
154 (
155 array
156 (
157 Form::LABEL => 'Copie cachée'
158 )
159 ),
160
161 $metas_prefix . '[subject]' => new Text
162 (
163 array
164 (
165 Form::LABEL => 'Sujet du message'
166 )
167 ),
168
169 $metas_prefix . '[template]' => new Element
170 (
171 'textarea', array
172 (
173 Form::LABEL => 'Patron du message',
174 Element::DESCRIPTION => "Le sujet du message et le corps du message
175 sont formatés par <a href=\"http://github.com/Weirdog/WdPatron\" target=\"_blank\">WdPatron</a>,
176 utilisez ses fonctionnalités avancées pour les personnaliser."
177 )
178 )
179 )
180 ),
181
182 <<<EOT
183 <div class="panel">
184 <div class="form-element is_notify">{\${$metas_prefix}[is_notify]}</div>
185 <table>
186 <tr><td class="label">{\${$metas_prefix}[from].label:}</td><td>{\${$metas_prefix}[from]}</td>
187 <td class="label">{\${$metas_prefix}[bcc].label:}</td><td>{\${$metas_prefix}[bcc]}</td></tr>
188 <tr><td class="label">{\${$metas_prefix}[subject].label:}</td><td colspan="3">{\${$metas_prefix}[subject]}</td></tr>
189 <tr><td colspan="4">{\${$metas_prefix}[template]}<button type="button" class="reset small warn" value="/api/forms/feedback.comments/defaults?type=notify" data-ns="$ns">Valeurs par défaut</button></td></tr>
190 </table>
191 </div>
192 EOT
193 )
194 )
195 )
196 );
197 }
198
199 static public function on_view_render(Event $event, \Icybee\Modules\Views\View $view)
200 {
201 global $core;
202
203 if ($event->id != 'articles/view')
204 {
205 return;
206 }
207
208 $editor = $core->editors['view'];
209 $list = $editor->render('comments/list');
210 $submit = $editor->render('comments/submit');
211
212 $event->rc .= PHP_EOL . $list . PHP_EOL . $submit;
213 }
214
215 /*
216 * Prototype
217 */
218
219 /**
220 * Returns the approved comments associated with a node.
221 *
222 * @param Node $ar
223 *
224 * @return array[]Node
225 */
226 static public function get_comments(Node $ar)
227 {
228 global $core;
229
230 return $core->models['comments']->where('nid = ? AND status = "approved"', $ar->nid)->order('created_at')->all;
231 }
232
233 /**
234 * Returns the number of approved comments associated with a node.
235 *
236 * @param Node $ar
237 *
238 * @return int
239 */
240 static public function get_comments_count(Node $ar)
241 {
242 global $core;
243
244 return $core->models['comments']->where('nid = ? AND status = "approved"', $ar->nid)->count;
245 }
246
247 /**
248 * Returns the rendered number of comment associated with a node.
249 *
250 * The string is formated using the `comments.count` locale string.
251 *
252 * @param Node $ar
253 *
254 * @return string
255 */
256 static public function get_rendered_comments_count(Node $ar)
257 {
258 return I18n\t('comments.count', array(':count' => $ar->comments_count));
259 }
260
261 static public function including_comments_count(\Icybee\Modules\Nodes\Model $target, array $records)
262 {
263 global $core;
264
265 $keys = array();
266
267 foreach ($records as $record)
268 {
269 $keys[$record->nid] = $record;
270 }
271
272 $counts = $core->models['comments']->approved->filter_by_nid(array_keys($keys))->count('nid');
273 $counts = $counts + array_combine(array_keys($keys), array_fill(0, count($keys), 0));
274
275 foreach ($counts as $nid => $count)
276 {
277 $keys[$nid]->comments_count = $count;
278 }
279
280 return $records;
281 }
282
283 /*
284 * Markups
285 */
286
287 static public function markup_comments(array $args, \Patron\Engine $patron, $template)
288 {
289 global $core;
290
291 extract($args);
292
293 #
294 # build sql query
295 #
296
297 $model = $core->models['comments'];
298 $arr = $model->filter_by_status(Comment::STATUS_APPROVED);
299
300 if ($node)
301 {
302 $arr->filter_by_nid($node);
303 }
304
305 if ($noauthor)
306 {
307 $arr->where('(SELECT uid FROM {prefix}nodes WHERE nid = comment.nid) != IFNULL(uid, 0)');
308 }
309
310 if ($order)
311 {
312 $arr->order($order);
313 }
314
315 if ($limit)
316 {
317 $arr->limit($limit * $page, $limit);
318 }
319
320 $records = $arr->all;
321
322 if (!$records && !$parseempty)
323 {
324 return;
325 }
326
327 $model->including_node($records);
328
329 return $patron($template, $records);
330 }
331
332 static public function markup_form(array $args, \Patron\Engine $patron, $template)
333 {
334 global $core;
335
336 #
337 # Obtain the form to use to add a comment from the 'forms' module.
338 #
339
340 $module = $core->modules['comments'];
341 $form_id = $core->site->metas['comments.form_id'];
342
343 if (!$form_id)
344 {
345 throw new Exception\Config($module);
346 }
347
348 if (!$core->user->has_permission(\ICanBoogie\Module::PERMISSION_CREATE, 'comments'))
349 {
350 if (Debug::$mode != Debug::MODE_DEV)
351 {
352 return;
353 }
354
355 return new \Brickrouge\Alert
356 (
357 <<<EOT
358 You don't have permission the create comments,
359 <a href="{$core->site->path}/admin/users.roles">the <q>Visitor</q> role should be modified.</a>
360 EOT
361 , array(), 'error'
362 );
363 }
364
365 $form = $core->models['forms'][$form_id];
366
367 if (!$form)
368 {
369 throw new Exception
370 (
371 'Uknown form with Id %nid', array
372 (
373 '%nid' => $form_id
374 )
375 );
376 }
377
378 new \BlueTihi\Context\LoadedNodesEvent($patron->context, array($form));
379
380 #
381 # Traget Id for the comment
382 #
383
384 $page = $core->request->context->page;
385
386 $form->form->hiddens[Comment::NID] = $page->node ? $page->node->nid : $page->nid;
387 $form->form->add_class('wd-feedback-comments');
388
389 return $template ? $patron($template, $form) : $form;
390 }
391
392 /*
393 * Other
394 */
395
396 static public function dashboard_last()
397 {
398 global $core;
399
400 if (empty($core->modules['comments']))
401 {
402 return;
403 }
404
405 $document = $core->document;
406 $document->css->add('../public/admin.css');
407
408 $model = $core->models['comments'];
409 $entries = $model
410 ->where('(SELECT 1 FROM {prefix}nodes WHERE nid = comment.nid AND (siteid = 0 OR siteid = ?)) IS NOT NULL', $core->site_id)
411 ->order('created_at DESC')->limit(5)->all;
412
413 if (!$entries)
414 {
415 return '<p class="nothing">' . I18n\t('No record yet') . '</p>';
416 }
417
418 $model->including_node($entries);
419
420 $rc = '';
421 $context = $core->site->path;
422
423 foreach ($entries as $entry)
424 {
425 $url = $entry->url;
426 $author = \ICanBoogie\escape($entry->author);
427
428 if ($entry->author_url)
429 {
430 $author = '<a class="author" href="' . \ICanBoogie\escape($entry->author_url) . '">' . $author . '</a>';
431 }
432 else
433 {
434 $author = '<strong class="author">' . $author . '</strong>';
435 }
436
437 $excerpt = \ICanBoogie\shorten(strip_tags((string) html_entity_decode($entry, ENT_COMPAT, \ICanBoogie\CHARSET)), 140);
438 $target_url = $entry->node->url;
439 $target_title = \ICanBoogie\escape(\ICanBoogie\shorten($entry->node->title));
440
441 $image = \ICanBoogie\escape($entry->author_icon);
442
443 $entry_class = $entry->status == 'spam' ? 'spam' : '';
444 $url_edit = "$context/admin/comments/$entry->commentid/edit";
445 $url_delete = "$context/admin/comments/$entry->commentid/delete";
446
447 $date = \ICanBoogie\I18n\format_date($entry->created_at, 'dd MMM');
448
449 $txt_delete = I18n\t('Delete');
450 $txt_edit = I18n\t('Edit');
451 $txt_display_associated_node = I18n\t('Display associated node');
452
453 $rc .= <<<EOT
454 <div class="record $entry_class">
455 <div class="options">
456 <img src="$image&s=48" alt="" />
457 </div>
458
459 <div class="contents">
460 <div class="head">
461 $author
462 <span class="date light">$date</span>
463 </div>
464
465 <div class="body"><a href="$url">$excerpt</a></div>
466
467 <div class="actions light">
468 <a href="$url_edit">$txt_edit</a>, <a href="$url_delete" class="danger">$txt_delete</a> − <a href="$target_url" class="target" title="$txt_display_associated_node">$target_title</a>
469 </div>
470 </div>
471 </div>
472 EOT;
473 }
474
475 $count = $model->joins(':nodes')->where('siteid = 0 OR siteid = ?', $core->site_id)->count;
476 $txt_all_comments = I18n\t('comments.count', array(':count' => $count));
477
478 $rc .= <<<EOT
479 <div class="panel-footer"><a href="$context/admin/comments">$txt_all_comments</a></div>
480 EOT;
481
482 return $rc;
483 }
484 }