From ada83c629afb339813c8a26324302810f0491b02 Mon Sep 17 00:00:00 2001 From: Dmitriy Simushev Date: Tue, 21 Oct 2014 11:22:44 +0000 Subject: [PATCH] Encapsulate work with bans in Ban class --- src/mibew/libs/chat.php | 21 -- src/mibew/libs/classes/Mibew/Ban.php | 238 ++++++++++++++++++ .../Mibew/Controller/BanController.php | 94 +++---- .../Mibew/RequestProcessor/UsersProcessor.php | 17 +- 4 files changed, 286 insertions(+), 84 deletions(-) create mode 100644 src/mibew/libs/classes/Mibew/Ban.php diff --git a/src/mibew/libs/chat.php b/src/mibew/libs/chat.php index 702d373b..c9190a36 100644 --- a/src/mibew/libs/chat.php +++ b/src/mibew/libs/chat.php @@ -615,27 +615,6 @@ function setup_chatview_for_operator( return $data; } -/** - * Check if the address is banned - * - * @param string $addr IP address which most be checked - * - * @return null|array It is banned address structure. contains (banid string, - * comment string) - */ -function ban_for_addr($addr) -{ - $db = Database::getInstance(); - return $db->query( - "SELECT banid,comment FROM {ban} WHERE dtmtill > :now AND address = :addr", - array( - ':addr' => $addr, - ':now' => time(), - ), - array('return_rows' => Database::RETURN_ONE_ROW) - ); -} - /** * @return array Return visitor info from active request. contains * (user_id string, user_name string) diff --git a/src/mibew/libs/classes/Mibew/Ban.php b/src/mibew/libs/classes/Mibew/Ban.php new file mode 100644 index 00000000..3d7dfe52 --- /dev/null +++ b/src/mibew/libs/classes/Mibew/Ban.php @@ -0,0 +1,238 @@ +query( + "SELECT * FROM {ban} WHERE banid = :id", + array(':id' => $id), + array('return_rows' => Database::RETURN_ONE_ROW) + ); + + // There is no ban with such id in database + if (!$ban_info) { + return false; + } + + // Store ban properties + $ban = new self(); + $ban->id = $ban_info['banid']; + $ban->created = $ban_info['dtmcreated']; + $ban->till = $ban_info['dtmtill']; + $ban->address = $ban_info['address']; + $ban->comment = $ban_info['comment']; + + return $ban; + } + + /** + * Loads ban by IP address. + * + * @param int $address Address of the ban to load + * @return boolean|Ban Returns a Ban instance or boolean false on failure. + */ + public static function loadByAddress($address) + { + // Check $id + if (empty($address)) { + return false; + } + + // Load thread + $ban_info = Database::getInstance()->query( + "SELECT * FROM {ban} WHERE address = :address", + array(':address' => $address), + array('return_rows' => Database::RETURN_ONE_ROW) + ); + + // There is no ban with such id in database + if (!$ban_info) { + return false; + } + + // Store ban properties + $ban = new self(); + $ban->id = $ban_info['banid']; + $ban->created = $ban_info['dtmcreated']; + $ban->till = $ban_info['dtmtill']; + $ban->address = $ban_info['address']; + $ban->comment = $ban_info['comment']; + + return $ban; + } + + /** + * Loads all bans. + * + * @return array List of Ban instances. + * + * @throws \RuntimeException If something went wrong and the list could not + * be loaded. + */ + public static function all() + { + $rows = Database::getInstance()->query( + "SELECT banid, dtmtill AS till, address, comment FROM {ban}", + null, + array('return_rows' => Database::RETURN_ALL_ROWS) + ); + + if ($rows === false) { + throw new \RuntimeException('Bans list cannot be retrieved.'); + } + + $bans = array(); + foreach ($rows as $item) { + $ban = new self(); + $ban->id = $item['banid']; + $ban->till = $item['till']; + $ban->address = $item['address']; + $ban->comment = $item['comment']; + $bans[] = $ban; + } + + return $bans; + } + + /** + * Class constructor. + */ + public function __construct() + { + // Set default values + $this->id = false; + $this->created = time(); + $this->till = $this->created + 24 * 60 * 60; + } + + /** + * Remove ban from the database. + */ + public function delete() + { + if (!$this->id) { + throw new \RuntimeException('You cannot delete a ban without id'); + } + + $db = Database::getInstance(); + $db->query( + "DELETE FROM {ban} WHERE banid = :id LIMIT 1", + array(':id' => $this->id) + ); + } + + /** + * Save the ban to the database. + */ + public function save() + { + $db = Database::getInstance(); + + if (!$this->id) { + // This ban is new. + $db->query( + ("INSERT INTO {ban} (dtmcreated, dtmtill, address, comment) " + . "VALUES (:created, :till, :address, :comment)"), + array( + ':created' => (int)$this->created, + ':till' => (int)$this->till, + ':address' => $this->address, + ':comment' => $this->comment, + ) + ); + $this->id = $db->insertedId(); + } else { + // Update existing ban + $db->query( + ("UPDATE {ban} SET dtmtill = :till, address = :address, " + . "comment = :comment WHERE banid = :id"), + array( + ':id' => $this->id, + ':till' => (int)$this->till, + ':address' => $this->address, + ':comment' => $this->comment, + ) + ); + } + } + + /** + * Checks if the ban is expired or not. + * + * @return boolean + */ + public function isExpired() + { + return ($this->till < time()); + } +} diff --git a/src/mibew/libs/classes/Mibew/Controller/BanController.php b/src/mibew/libs/classes/Mibew/Controller/BanController.php index f5fa405a..f7b33391 100644 --- a/src/mibew/libs/classes/Mibew/Controller/BanController.php +++ b/src/mibew/libs/classes/Mibew/Controller/BanController.php @@ -19,7 +19,7 @@ namespace Mibew\Controller; -use Mibew\Database; +use Mibew\Ban; use Mibew\Http\Exception\BadRequestException; use Mibew\Http\Exception\NotFoundException; use Mibew\Thread; @@ -46,17 +46,15 @@ class BanController extends AbstractController ); // Prepare list of all banned visitors - $db = Database::getInstance(); - $blocked_list = $db->query( - "SELECT banid, dtmtill AS till, address, comment FROM {ban}", - null, - array('return_rows' => Database::RETURN_ALL_ROWS) - ); - - foreach ($blocked_list as &$item) { - $item['comment'] = $item['comment']; + foreach (Ban::all() as $ban) { + $blocked_list[] = array( + 'banid' => $ban->id, + 'created' => $ban->created, + 'till' => $ban->till, + 'address' => $ban->address, + 'comment' => $ban->comment, + ); } - unset($item); $page['title'] = getlocal('Ban List'); $page['menuid'] = 'bans'; @@ -75,6 +73,8 @@ class BanController extends AbstractController * * @param Request $request Incoming request. * @return string Rendered page content. + * @throws NotFoundException If the ban with specified ID is not found in + * the system. */ public function deleteAction(Request $request) { @@ -82,9 +82,14 @@ class BanController extends AbstractController $ban_id = $request->attributes->getInt('ban_id'); - // Remove ban from database - $db = Database::getInstance(); - $db->query("DELETE FROM {ban} WHERE banid = ?", array($ban_id)); + // Check if the ban exists + $ban = Ban::load($ban_id); + if (!$ban) { + throw new NotFoundException('The ban is not found.'); + } + + // Remove the ban + $ban->delete(); // Redirect the current operator to page with bans list return $this->redirect($this->generateUrl('bans')); @@ -120,25 +125,15 @@ class BanController extends AbstractController $ban_id = $request->attributes->getInt('ban_id'); // Retrieve ban information from the database - $db = Database::getInstance(); - $ban = $db->query( - ("SELECT banid, (dtmtill - :now) AS days, address, comment " - . "FROM {ban} WHERE banid = :banid"), - array( - ':banid' => $ban_id, - ':now' => time(), - ), - array('return_rows' => Database::RETURN_ONE_ROW) - ); - + $ban = Ban::load($ban_id); if (!$ban) { throw new NotFoundException('The ban is not found.'); } - $page['banId'] = $ban['banid']; - $page['formaddress'] = $ban['address']; - $page['formdays'] = round($ban['days'] / 86400); - $page['formcomment'] = $ban['comment']; + $page['banId'] = $ban->id; + $page['formaddress'] = $ban->address; + $page['formdays'] = round(($ban->till - time()) / 86400); + $page['formcomment'] = $ban->comment; } elseif ($request->query->has('thread')) { // Prepopulate form using thread data $thread_id = $request->query->has('thread'); @@ -176,6 +171,8 @@ class BanController extends AbstractController * * @param Request $request Incoming request. * @return string Rendered page content. + * @throws NotFoundException If the ban with specified ID is not found in + * the system. */ public function submitEditFormAction(Request $request) { @@ -208,14 +205,14 @@ class BanController extends AbstractController } // Check if the ban already exists in the database - $existing_ban = ban_for_addr($address); + $existing_ban = Ban::loadByAddress($address); $ban_duplicate = (!$ban_id && $existing_ban) - || ($ban_id && $existing_ban && $ban_id != $existing_ban['banid']); + || ($ban_id && $existing_ban && $ban_id != $existing_ban->id); if ($ban_duplicate) { $ban_url = $this->generateUrl( 'ban_edit', - array('ban_id' => $existing_ban['banid']) + array('ban_id' => $existing_ban->id) ); $errors[] = getlocal('The specified address is already in use. Click here if you want to edit it.', array($address, $ban_url)); } @@ -228,32 +225,19 @@ class BanController extends AbstractController } // Save ban into the database - $db = Database::getInstance(); - $now = time(); - $till_time = $now + $days * 24 * 60 * 60; if (!$ban_id) { - $db->query( - ("INSERT INTO {ban} (dtmcreated, dtmtill, address, comment) " - . "VALUES (:now,:till,:address,:comment)"), - array( - ':now' => $now, - ':till' => $till_time, - ':address' => $address, - ':comment' => $comment, - ) - ); + $ban = new Ban(); + $ban->created = time(); } else { - $db->query( - ("UPDATE {ban} SET dtmtill = :till, address = :address, " - . "comment = :comment WHERE banid = :banid"), - array( - ':till' => $till_time, - ':address' => $address, - ':comment' => $comment, - ':banid' => $ban_id, - ) - ); + $ban = Ban::load($ban_id); + if (!$ban) { + throw new NotFoundException('The ban is not found.'); + } } + $ban->till = time() + $days * 24 * 60 * 60; + $ban->address = $address; + $ban->comment = $comment; + $ban->save(); // Rerender the form page $page['saved'] = true; diff --git a/src/mibew/libs/classes/Mibew/RequestProcessor/UsersProcessor.php b/src/mibew/libs/classes/Mibew/RequestProcessor/UsersProcessor.php index 11a0b31b..099900c4 100644 --- a/src/mibew/libs/classes/Mibew/RequestProcessor/UsersProcessor.php +++ b/src/mibew/libs/classes/Mibew/RequestProcessor/UsersProcessor.php @@ -22,6 +22,7 @@ namespace Mibew\RequestProcessor; // Import namespaces and classes of the core use Mibew\Authentication\AuthenticationManagerAwareInterface; use Mibew\Authentication\AuthenticationManagerInterface; +use Mibew\Ban; use Mibew\Database; use Mibew\EventDispatcher\EventDispatcher; use Mibew\EventDispatcher\Events; @@ -245,16 +246,16 @@ class UsersProcessor extends ClientSideProcessor implements AuthenticationManage // Get ban info - $ban_info = (Settings::get('enableban') == "1") - ? ban_for_addr($thread->remote) + $ban = (Settings::get('enableban') == "1") + ? Ban::loadByAddress($thread->remote) : false; - if ($ban_info !== false) { - $ban = array( - 'id' => $ban_info['banid'], - 'reason' => $ban_info['comment'], + if ($ban !== false && !$ban->isExpired()) { + $ban_info = array( + 'id' => $ban->id, + 'reason' => $ban->comment, ); } else { - $ban = false; + $ban_info = false; } // Get user name @@ -322,7 +323,7 @@ class UsersProcessor extends ClientSideProcessor implements AuthenticationManage 'canOpen' => $can_open, 'canView' => $can_view, 'canBan' => $can_ban, - 'ban' => $ban, + 'ban' => $ban_info, 'state' => $thread->state, 'totalTime' => $thread->created, 'waitingTime' => $thread->modified,