Rev 1 | Blame | Compare with Previous | Last modification | View Log | Download
<?php namespace ProcessWire;/*** ProcessWire InputfieldCommentsAdmin** An Inputfield for handling administration of Comments.** ProcessWire 3.x, Copyright 2022 by Ryan Cramer* https://processwire.com** @property bool|int $useManager* @method InputfieldMarkup renderItem(Comment $comment, $n)**/class InputfieldCommentsAdmin extends Inputfield implements InputfieldItemList {public static function getModuleInfo() {return array('title' => __('Comments Admin', __FILE__),'version' => 104,'summary' => __('Provides an administrative interface for working with comments', __FILE__),'permanent' => false,'requires' => 'FieldtypeComments',);}protected $commentIDsToNumbers = array();protected $commentsManagerUrl = '';protected $statuses = array();public function __construct() {$this->set('useManager', false);parent::__construct();}public function init() {parent::init();require_once(__DIR__ . '/FieldtypeComments.module');if($this->wire()->modules->isInstalled('ProcessCommentsManager')) {$this->commentsManagerUrl = $this->wire()->config->urls->admin . 'setup/comments/';}$this->statuses = array(Comment::statusFeatured => array($this->_x('Featured', 'comment-status'), 'trophy', 'featured'),Comment::statusApproved => array($this->_x('Approved', 'comment-status'), 'check-circle', 'approved'),Comment::statusPending => array($this->_x('Pending', 'comment-status'), 'commenting-o', 'pending'),Comment::statusSpam => array($this->_x('Spam', 'comment-status'), 'warning', 'spam'),);}/*** @param Comment $comment* @param int $n* @return array|mixed|null|_Module|Field|Fieldtype|Module|NullPage|Page|Permission|Role|Template|WireData|WireInputData|string**/protected function ___renderItem(Comment $comment, $n) {$name = $this->name;$names = array('status' => "{$this->name}_status_{$comment->id}",'parent' => "{$this->name}_parent_id_{$comment->id}",'cite' => "{$name}_cite_{$comment->id}",'email' => "{$name}_email_{$comment->id}",'website' => "{$name}_website_{$comment->id}",'stars' => "{$name}_stars_{$comment->id}",'text' => "{$name}_text_{$comment->id}");$sanitizer = $this->wire()->sanitizer;$statusName = '';$statusIcon = '';$statusOut = "<select id='$names[status]' name='$names[status]'>";foreach($this->statuses as $status => $statusInfo) {list($label, $icon, /*$name*/) = $statusInfo;if($comment->status == $status) {$selected = " selected='selected'";$statusName = $label;$statusIcon = $icon;} else {$selected = '';}$statusOut .= "<option value='$status'$selected>$label</option>";}$statusOut .= "<option value='delete{$comment->id}'>" . $this->_('Delete') . "</option>";$statusOut .= "</select>";$parentOut = "<select name='$names[parent]' id='$names[parent]'><option value='0'></option>";$parentID = $comment->parent_id;$_n = 0;foreach($this->value as $_comment) {$_n++;if($_comment->id == $comment->id) continue;if($_comment->created > $comment->created) continue;$selected = $parentID == $_comment->id ? " selected='selected'" : "";$parentOut .="<option$selected value='$_comment->id'>" .sprintf($this->_('Comment #%d (%s)'), $_n, $this->wire('sanitizer')->entities($_comment->cite)) ."</option>";}$parentOut .= "</select>";$notifyOut = '';if($comment->getField()->useNotify) {if($comment->flags & Comment::flagNotifyAll) $notifyOut = $this->_('ALL new comments');else if($comment->flags & Comment::flagNotifyReply) $notifyOut = $this->_('REPLIES only');else $notifyOut = $this->_('OFF');}$headLabel = $statusName;$num = $n+1;$liID = "CommentsAdminItem{$comment->id}";/** @var InputfieldMarkup $f */$f = $this->wire('modules')->get('InputfieldMarkup');$f->attr('id', $liID);$f->addClass("CommentsAdminItem$statusName");$f->icon = $statusIcon;if($comment->status == Comment::statusSpam) {$f->addClass("CommentsAdminItemSpam InputfieldIsError InputfieldStateError", 'wrapClass');$f->description = $this->_("Spam is automatically deleted after the amount of time specified in the field configuration.");$f->collapsed = Inputfield::collapsedYes;} else if($comment->status == Comment::statusApproved) {$f->collapsed = Inputfield::collapsedYes;$f->addClass('InputfieldIsSuccess');} else if($comment->status == Comment::statusPending) {$f->addClass('InputfieldIsPrimary');$f->description = $this->_("This item is awaiting approval or deletion.");}$cite = $sanitizer->entities($comment->cite);$email = $sanitizer->entities($comment->email);$website = $sanitizer->entities($comment->website);$stars = $sanitizer->entities($comment->stars);$text = $sanitizer->entities(trim($comment->text));$f->label = strtoupper($headLabel) . ': ' . sprintf($this->_('Comment #%1$d Posted %2$s by %3$s'),$num,wireRelativeTimeStr($comment->created),$cite);if($this->hasField && $this->hasField->get('useStars')) {$starsInput ="<p class='CommentsAdminItemStars'>" ."<label for='$names[stars]'>" ."<span class='detail'>" . $this->_('Stars') . "</span>" ."</label>" ."<input type='number' min='0' max='5' id='$names[stars]' name='$names[stars]' value='$stars' />" ."</p>";} else {$starsInput = '';}$notes = array();if($notifyOut) {$notes[] = $this->_('Email notifications:') . " $notifyOut";}if($this->commentsManagerUrl) {$metaQty = count($comment->getMeta());$page = $comment->getPage();$field = $comment->getField();$metaUrl = $this->commentsManagerUrl . "meta/?comment_id=$comment->id&page_id=$page->id&field_id=$field->id";// $editUrl = $this->commentsManagerUrl . "list/$field->name/all/?id=$comment->id";$notes[] ="<a href='$metaUrl' class='pw-modal' data-buttons='button'>" .sprintf($this->_n('%d meta value', '%d meta values', $metaQty), $metaQty) . "</a>";}$f->value ="<div class='ui-helper-clearfix'>" ."<p class='CommentsAdminItemStatus'>" ."<label for='$names[status]'><span class='detail'>" . $this->_('Status') . "</span></label>" .$statusOut ."</p>" ."<p class='CommentsAdminItemParent'>" ."<label for='$names[parent]'><span class='detail'>" . $this->_('Reply To') . "</span></label>" .$parentOut ."</p>" ."</div><div class='ui-helper-clearfix'>" ."<p class='CommentsAdminItemCite'>" ."<label for='$names[cite]'><span class='detail'>" . $this->_('Cite') . "</span></label>" ."<input type='text' id='$names[cite]' name='$names[cite]' value='$cite' />" ."</p>" ."<p class='CommentsAdminItemEmail'>" ."<label for='$names[email]'><span class='detail'>" . $this->_('E-Mail') . "</span></label>" ."<input type='text' id='$names[email]' name='$names[email]' value='$email' />" ."</p>" ."<p class='CommentsAdminItemWebsite'>" ."<label for='$names[website]'><span class='detail'>" . $this->_('Website') . "</span></label>" ."<input type='text' id='$names[website]' name='$names[website]' value='$website' />" ."</p>" .$starsInput ."</div>" ."<p class='CommentsAdminItemText'>" ."<label for='$names[text]'><span class='detail'>" . $this->_('Text') . "</span></label>" ."<textarea id='$names[text]' name='$names[text]' rows='5'>$text</textarea>" ."</p>" .(count($notes) ? "<p class='CommentsAdminItemNotify detail'>" . implode(' • ', $notes) . "</p>" : "") ."<input class='CommentsAdminItemSort' type='hidden' name='sort_{$this->name}_{$comment->id}' value='$n' />" ."";return $f;}public function ___render() {$value = $this->value;if($this->useManager || !count($value)) {$out = $this->renderValue();} else {$n = 0;foreach($value as $comment) {$this->commentIDsToNumbers[$comment->id] = ++$n;}$fieldset = new InputfieldWrapper(); // wired$this->wire($fieldset);$n = 0;foreach($value as $comment) {$f = $this->renderItem($comment, $n++);$f->addClass($this->wrapClass);$fieldset->add($f);}$out = $fieldset->render();}return $out;}public function ___renderValue() {$value = $this->attr('value');if(!count($value)) {return "<p>" . $this->_('There are currently no items to display.') . "</p>";}$items = array();$qtys = array();$total = 0;$field = null;$page = null;foreach($value as $comment) {/** @var Comment $comment */$total++;if(!$field) $field = $comment->getField();if(!$page) $page = $comment->getPage();$status = $comment->status;if(!isset($this->statuses[$status])) continue;if(!isset($qtys[$status])) $qtys[$status] = 0;$qtys[$status]++;}$url = $this->commentsManagerUrl . "list/$field->name/all/?pages_id=$page->id";$icon = wireIconMarkup('comments');$item = $icon . ' ' . sprintf($this->_n('%d comment', '%d comments', $total), $total);if($page->editable($field)) $item = "<a href='$url' target='_blank'>$item</a>";$items[] = $item;foreach($this->statuses as $status => $statusInfo) {if(empty($qtys[$status])) continue;$qty = $qtys[$status];list($label, $icon, /*$name*/) = $statusInfo;$icon = wireIconMarkup($icon);$items[] = "<span class='ui-priority-secondary'>$icon $qty $label</span>";}return "<p>" . implode(' ', $items) . "</p>";}public function ___processInput(WireInputData $input) {if($this->useManager) return $this;$n = 1;$names = array('cite','email','website','status','delete','parent_id','text','sort',);if($this->hasField && $this->hasField->get('useStars')) $names[] = 'stars';foreach($this->value as $comment) {/** @var Comment $comment */$data = array();foreach($names as $name) {$inputName = $this->name . "_" . $name . "_" . $comment->id;$value = isset($input[$inputName]) ? $input[$inputName] : '';$data[$name] = $value;}if($data['status'] && $data['status'] == "delete{$comment->id}") {$this->value->remove($comment);$this->message(sprintf($this->_('Removed comment #%d'), $n));$this->value->trackChange('remove');continue;}foreach($data as $key => $value) {if($key == 'text') $value = $comment->cleanCommentString($value);if(($value || $key == 'status') && $comment->$key != $value) {$comment->$key = $value;$this->message(sprintf($this->_('Updated %s for comment #%d'), $key, $n));$this->value->trackChange('update');}}$n++;}return $this;}public function ___getConfigInputfields() {$modules = $this->wire()->modules;$inputfields = parent::___getConfigInputfields();/** @var InputfieldToggle $f */$f = $modules->get('InputfieldToggle');$f->attr('name', 'useManager');$f->label = $this->_('Use comments manager rather than in-page editor?');$f->description =$this->_('When enabled user will be directed to the dedicated comments manager for editing comments.') . ' ' .$this->_('This may be preferable because the comments manager has more features and uses pagination.');$value = (int) $this->get('useManager');$f->val($value);$f->themeOffset = 1;$inputfields->prepend($f);if($value && !$this->commentsManagerUrl) {$modules->getInstall('ProcessCommentsManager');}return $inputfields;}}