diff --git a/src/Install.php b/src/Install.php index bd52aa6..a408a1e 100644 --- a/src/Install.php +++ b/src/Install.php @@ -14,18 +14,15 @@ declare(strict_types=1); namespace Dotclear\Plugin\whiteListCom; -/* dotclear ns */ use dcCore; use dcNamespace; use dcNsProcess; - -/* php ns */ use Exception; class Install extends dcNsProcess { // Module specs - private static $mod_conf = [ + private static array $mod_conf = [ [ 'unmoderated', '[]', @@ -49,7 +46,11 @@ class Install extends dcNsProcess public static function process(): bool { - if (!sestaticlf::$init) { + if (!static::$init) { + return false; + } + + if (is_null(dcCore::app()->blog)) { return false; } @@ -89,15 +90,15 @@ class Install extends dcNsProcess ); while ($record->fetch()) { - if (preg_match('/^whiteListCom(.*?)$/', $record->setting_id, $match)) { - $value = @unserialize(@base64_decode($record->setting_value)); - $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME); - $cur->setting_id = $match[1]; - $cur->setting_ns = My::id(); - $cur->setting_value = is_array($value) ? json_encode($value) : '[]'; + if (preg_match('/^whiteListCom(.*?)$/', $record->f('setting_id'), $match)) { + $value = @unserialize(@base64_decode($record->f('setting_value'))); + $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME); + $cur->setField('setting_id', $match[1]); + $cur->setField('setting_ns', My::id()); + $cur->setField('setting_value', is_array($value) ? json_encode($value) : '[]'); $cur->update( - "WHERE setting_id = '" . $record->setting_id . "' and setting_ns = 'whiteListCom' " . - 'AND blog_id ' . (null === $record->blog_id ? 'IS NULL ' : ("= '" . dcCore::app()->con->escape($record->blog_id) . "' ")) + "WHERE setting_id = '" . $record->f('setting_id') . "' and setting_ns = 'whiteListCom' " . + 'AND blog_id ' . (null === $record->f('blog_id') ? 'IS NULL ' : ("= '" . dcCore::app()->con->escapeStr((string) $record->f('blog_id')) . "' ")) ); } } diff --git a/src/ReservedWhiteList.php b/src/ReservedWhiteList.php index d0da001..9ce891a 100644 --- a/src/ReservedWhiteList.php +++ b/src/ReservedWhiteList.php @@ -16,13 +16,13 @@ namespace Dotclear\Plugin\whiteListCom; use dcCore; use dcPage; -use dcSpamFilter; use Dotclear\Helper\Html\Form\{ Checkbox, Hidden }; use Dotclear\Helper\Html\Html; use Dotclear\Helper\Network\Http; +use Dotclear\Plugin\antispam\SpamFilter; use Exception; /** @@ -30,17 +30,23 @@ use Exception; * @brief Filter for reserved names. * @since 2.6 */ -class ReservedWhiteList extends dcSpamFilter +class ReservedWhiteList extends SpamFilter { public $name = 'Reserved names'; public $has_gui = true; + /** + * @return void + */ protected function setInfo() { $this->name = __('Reserved names'); $this->description = __('Whitelist of reserved names of users'); } + /** + * @return void|null|bool + */ public function isSpam($type, $author, $email, $site, $ip, $content, $post_id, &$status) { if ($type != 'comment') { @@ -50,9 +56,7 @@ class ReservedWhiteList extends dcSpamFilter $throw = false; try { - $wlc = new Utils(); - - if (true === $wlc->isReserved($author, $email)) { + if (true === Utils::isReserved($author, $email)) { $status = 'reserved name'; //return true; $throw = true; @@ -68,6 +72,9 @@ class ReservedWhiteList extends dcSpamFilter } } + /** + * @return string + */ public function getStatusMessage($status, $comment_id) { return __('This name is reserved to an other user.'); @@ -75,40 +82,41 @@ class ReservedWhiteList extends dcSpamFilter public function gui(string $url): string { - $wlc = new Utils(); $comments = []; try { if (!empty($_POST['update_reserved'])) { - $wlc->emptyReserved(); + Utils::emptyReserved(); foreach ($_POST['reserved'] as $i => $name) { - $wlc->addReserved($name, $_POST['reserved_email'][$i]); + Utils::addReserved($name, $_POST['reserved_email'][$i]); } - $wlc->commit(); + Utils::commit(); dcPage::addSuccessNotice(__('Reserved names have been successfully updated.')); Http::redirect($url); } - $comments = $wlc->getCommentsUsers(); + $comments = Utils::getCommentsUsers(); } catch (Exception $e) { dcCore::app()->error->add($e->getMessage()); } $res = '
' . '

' . __('Check the users who can make comments without being moderated.') . '

' . - '

' . __('Comments authors list') . '

' . + '
' . '' . + '' . '' . ''; $i = 0; foreach ($comments as $user) { - $res .= '' . + $checked = null === Utils::isReserved($user['name'], $user['email']); + $res .= '' . '' . - '' . + '' . ''; $i++; } diff --git a/src/UnmoderatedWhiteList.php b/src/UnmoderatedWhiteList.php index 6eca617..666032d 100644 --- a/src/UnmoderatedWhiteList.php +++ b/src/UnmoderatedWhiteList.php @@ -16,10 +16,10 @@ namespace Dotclear\Plugin\whiteListCom; use dcCore; use dcPage; -use dcSpamFilter; use Dotclear\Helper\Html\Form\Checkbox; use Dotclear\Helper\Html\Html; use Dotclear\Helper\Network\Http; +use Dotclear\Plugin\antispam\SpamFilter; use Exception; /** @@ -29,17 +29,23 @@ use Exception; * * This filter is used only if comments are moderates */ -class UnmoderatedWhiteList extends dcSpamFilter +class UnmoderatedWhiteList extends SpamFilter { public $name = 'Unmoderated authors'; public $has_gui = true; + /** + * @return void + */ protected function setInfo() { $this->name = __('Unmoderated authors'); $this->description = __('Whitelist of unmoderated authors'); } + /** + * @return void|null|bool + */ public function isSpam($type, $author, $email, $site, $ip, $content, $post_id, &$status) { if ($type != 'comment' @@ -49,8 +55,7 @@ class UnmoderatedWhiteList extends dcSpamFilter } try { - $wlc = new Utils(); - if ($wlc->isUnmoderated($email)) { + if (Utils::isUnmoderated($email)) { $status = 'unmoderated'; # return true in order to change comment_status after @@ -69,23 +74,23 @@ class UnmoderatedWhiteList extends dcSpamFilter try { if (!empty($_POST['update_unmoderated'])) { - $wlc->emptyUnmoderated(); + Utils::emptyUnmoderated(); foreach ($_POST['unmoderated'] as $email) { - $wlc->addUnmoderated($email); + Utils::addUnmoderated($email); } - $wlc->commit(); + Utils::commit(); dcPage::addSuccessNotice(__('Unmoderated names have been successfully updated.')); Http::redirect($url); } - $posts = $wlc->getPostsUsers(); - $comments = $wlc->getCommentsUsers(); + $posts = Utils::getPostsUsers(); + $comments = Utils::getCommentsUsers(); } catch (Exception $e) { dcCore::app()->error->add($e->getMessage()); } $res = ''; - if (dcCore::app()->blog->settings->get('system')->get('comments_pub')) { + if (!is_null(dcCore::app()->blog) && dcCore::app()->blog->settings->get('system')->get('comments_pub')) { $res .= '

' . __('This filter is used only if comments are moderates') . '

'; @@ -93,42 +98,46 @@ class UnmoderatedWhiteList extends dcSpamFilter $res .= '' . '

' . __('Check the users who can make comments without being moderated.') . '

' . - '
' . - '
' . - '

' . __('Posts authors list') . '

' . + '
' . + '
' . + '
' . '
' . __('Comments authors list') . '
' . __('Author') . '' . __('Email') . '
' . - (new Checkbox(['reserved[' . $i . ']'], (null === $wlc->isReserved($user['name'], $user['email']))))->value($user['name'])->render() . + (new Checkbox(['reserved[' . $i . ']'], $checked))->value($user['name'])->render() . (new Hidden(['reserved_email[' . $i . ']'], $user['email']))->render() . ' ' . $user['name'] . '' . $user['email'] . '' . $user['email'] . '
' . + '' . '' . ''; foreach ($posts as $user) { - $res .= '' . + $checked = Utils::isUnmoderated($user['email']); + $res .= '' . '' . '' . ''; } $res .= '' . - '
' . __('Posts authors list') . '
' . __('Name') . '' . __('Email') . '
' . - (new Checkbox(['unmoderated[]'], $wlc->isUnmoderated($user['email'])))->value($user['email'])->render() . + (new Checkbox(['unmoderated[]'], $checked))->value($user['email'])->render() . ' ' . $user['name'] . '' . $user['email'] . '
' . + '
' . '' . - '
' . - '

' . __('Comments authors list') . '

' . + '
' . + '
' . '' . + '' . '' . ''; foreach ($comments as $user) { - $res .= '' . + $checked = Utils::isUnmoderated($user['email']); + $res .= '' . '' . '' . ''; } $res .= '' . - '
' . __('Comments authors list') . '
' . __('Author') . '' . __('Email') . '
' . - (new Checkbox(['unmoderated[]'], $wlc->isUnmoderated($user['email'])))->value($user['email'])->render() . + (new Checkbox(['unmoderated[]'], $checked))->value($user['email'])->render() . ' ' . $user['name'] . '' . $user['email'] . '
' . + '
' . '
' . '
' . '

' . diff --git a/src/Utils.php b/src/Utils.php index b84c328..88a7724 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -14,10 +14,13 @@ declare(strict_types=1); namespace Dotclear\Plugin\whiteListCom; -/* dotclear ns */ use dcBlog; use dcCore; use dcUtils; +use Dotclear\Database\Statement\{ + JoinStatement, + SelectStatement, +}; /** * @ingroup DC_PLUGIN_WHITELISTCOM @@ -26,36 +29,61 @@ use dcUtils; */ class Utils { - public $con; - public $blog; - public $settings; + /** @var bool $init preload check */ + private static bool $init = false; - private $unmoderated = []; - private $reserved = []; + /** @var array $unmoderated List of unmoderated users */ + private static array $unmoderated = []; - public function __construct() + /** @var array $unmoderated List of reserved name */ + private static array $reserved = []; + + /** + * Initialize properties. + */ + private static function init(): void { - $this->con = dcCore::app()->con; - $this->blog = dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id); - $this->settings = dcCore::app()->blog->settings->get(My::id()); - $this->unmoderated = self::decode($this->settings->get('unmoderated')); - $this->reserved = self::decode($this->settings->get('reserved')); + if (self::$init) { + return; + } + + if (is_null(dcCore::app()->blog)) { + return; + } + + $s = dcCore::app()->blog->settings->get(My::id()); + + self::$unmoderated = self::decode($s->get('unmoderated')); + self::$reserved = self::decode($s->get('reserved')); + + self::$init = true; } - public function commit(): void + /** + * Save changes. + */ + public static function commit(): void { - $this->settings->put( + if (is_null(dcCore::app()->blog)) { + return; + } + + self::init(); + + $s = dcCore::app()->blog->settings->get(My::id()); + + $s->put( 'unmoderated', - self::encode($this->unmoderated), + self::encode(self::$unmoderated), 'string', 'Whitelist of unmoderated users on comments', true, false ); - $this->settings->put( + $s->put( 'reserved', - self::encode($this->reserved), + self::encode(self::$reserved), 'string', 'Whitelist of reserved names on comments', true, @@ -63,64 +91,122 @@ class Utils ); } - # Return - # true if it is a reserved name with wrong email - # false if it is not a reserved name - # null if it is a reserved name with right email - public function isReserved($author, $email): ?bool + /** + * Check if a name is reserved. + * + * Return: + * - true if it is a reserved name with wrong email + * - false if it is not a reserved name + * - null if it is a reserved name with right email + * + * @param string $author The author + * @param string $email The email + * + * @return null|bool The reserved state + */ + public static function isReserved(string $author, string $email): ?bool { - if (!isset($this->reserved[$author])) { + self::init(); + + if (!isset(self::$reserved[$author])) { return false; - } elseif ($this->reserved[$author] != $email) { + } elseif (self::$reserved[$author] != $email) { return true; } return null; } - # You must do a commit to save this change - public function addReserved($author, $email): bool + /** + * Add a reserved user. + * + * You must do a Utils::commit() to save this change + * + * @param string $author The author + * @param string $email The email + */ + public static function addReserved(string $author, string $email): void { - $this->reserved[$author] = $email; + self::init(); - return true; + self::$reserved[$author] = $email; } - # You must do a commit to save this change - public function emptyReserved(): void + /** + * Clean reserved names list. + * + * You must do a Utils::commit() to save this change + */ + public static function emptyReserved(): void { - $this->reserved = []; + self::init(); + + self::$reserved = []; } - # Return - # true if it is known as an unmoderated email else false - public function isUnmoderated($email): bool + /** + * Check if an email is unmoderated. + * + * Return: + * - true if it is known as an unmoderated email + * - false else + * + * @param string $email The email + * + * @return bool The reserved state + */ + public static function isUnmoderated(string $email): bool { - return in_array($email, $this->unmoderated); + self::init(); + + return in_array($email, self::$unmoderated); } - # You must do a commit to save this change - public function addUnmoderated($email): ?bool + /** + * Add a unmoderated user. + * + * You must do a Utils::commit() to save this change + * + * @param string $email The email + */ + public static function addUnmoderated(string $email): void { - if (!in_array($email, $this->unmoderated)) { - $this->unmoderated[] = $email; + self::init(); - return true; + if (!in_array($email, self::$unmoderated)) { + self::$unmoderated[] = $email; + } + } + + /** + * Clean unmoderated users list. + * + * You must do a Utils::commit() to save this change + */ + public static function emptyUnmoderated(): void + { + self::init(); + + self::$unmoderated = []; + } + + /** + * Get posts users. + * + * @return array The users name/email pairs + */ + public static function getPostsUsers(): array + { + if (is_null(dcCore::app()->blog)) { + return []; } - return null; - } + $rs = dcCore::app()->blog->getPostsUsers(); + if ($rs->isEmpty()) { + return []; + } - # You must do a commit to save this change - public function emptyUnmoderated(): void - { - $this->unmoderated = []; - } - - public function getPostsUsers(): array - { $users = []; - $rs = dcCore::app()->blog->getPostsUsers(); while ($rs->fetch()) { $name = dcUtils::getUserCN( $rs->f('user_id'), @@ -137,16 +223,41 @@ class Utils return $users; } - public function getCommentsUsers(): array + /** + * Get comments users. + * + * @return array The users name/email pairs + */ + public static function getCommentsUsers(): array { + if (is_null(dcCore::app()->blog)) { + return []; + } + + $sql = new SelectStatement(); + $rs = $sql->from($sql->as(dcCore::app()->prefix . dcBlog::COMMENT_TABLE_NAME, 'C')) + ->columns([ + 'comment_author', + 'comment_email', + ]) + ->join( + (new JoinStatement()) + ->left() + ->from($sql->as(dcCore::app()->prefix . dcBlog::POST_TABLE_NAME, 'P')) + ->on('C.post_id = P.post_id') + ->statement() + ) + ->where('blog_id = ' . $sql->quote(dcCore::app()->blog->id)) + ->and('comment_trackback = 0') + ->and("comment_email != ''") + ->group('comment_email, comment_author') // Added author to fix postgreSql + ->select(); + + if (is_null($rs) || $rs->isEmpty()) { + return []; + } + $users = []; - $rs = $this->con->select( - 'SELECT comment_author, comment_email ' . - 'FROM ' . dcCore::app()->prefix . dcBlog::COMMENT_TABLE_NAME . ' C ' . - 'LEFT JOIN ' . dcCore::app()->prefix . 'post P ON C.post_id=P.post_id ' . - "WHERE blog_id='" . $this->blog . "' AND comment_trackback=0 " . - 'GROUP BY comment_email, comment_author ' // Added author to fix postgreSql - ); while ($rs->fetch()) { $users[] = [ 'name' => $rs->f('comment_author'), @@ -157,13 +268,27 @@ class Utils return $users; } + /** + * Encode settings. + * + * @param array|string $x The value to encode + * + * @return string The encoded value + */ public static function encode($x): string { $y = is_array($x) ? $x : []; - return json_encode($y); + return (string) json_encode($y); } + /** + * Decode settings. + * + * @param string $x The value to decode + * + * @return array The decoded value + */ public static function decode($x): array { $y = json_decode($x, true);