Extension:EditWarning/0.3.8
From MediaWiki.org
In development of Extension:EditWarning you can use this version to
- check pages with are opened to edit but not jet saved and
- to use relative path for file-inclusion. --Jostar 17:17, 20 September 2011 (UTC)
Contents |
[edit] Rename file EditWarning.i18n.php
Please rename Message.i18n.php to standard format as EditWarning.i18n.php
[edit] Change database mySQL
An additional row is used to save the page name.
CREATE TABLE current_edits ( id int(10) unsigned NOT NULL auto_increment, page_id int(10) unsigned NOT NULL, page_name varchar(255) character set latin1 collate latin1_bin NOT NULL, user_id int(10) unsigned NOT NULL, user_name varchar(255) character set latin1 collate latin1_bin NOT NULL, timestamp int(10) unsigned NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
[edit] Update EditWarning.php
<?php /** * MediaWiki extension: EditWarning * * Warns user editing a page that's currently being edited. * * @author Thomas David <ThomasDavid@gmx.de> * @addtogroup Extensions * @version 0.3.5 * @copyright 2010 by Thomas David * @license GNU GPL 2.0 or later * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * @version 0.3.8 <Jostar> check pages with are opened to edit but not jet saved, relative path for file-inclusion is used */ if(defined('MEDIAWIKI')) { define('EWDEBUG', false); require_once dirname( __FILE__ )."/EditWarning.class.php"; $wgExtensionFunctions[] = 'fnEditwarning_init'; $wgExtensionCredits['other'][] = array( 'name' => 'EditWarning', 'version' => '0.3.8', 'author' => 'Thomas David', 'url' => 'http://www.mediawiki.org/wiki/Extension:EditWarning', 'description' => 'Warns user editing a page that\'s currently being edited.', ); // Assign hooks to functions $wgHooks['AlternateEdit'][] = 'fnEditWarning_edit'; $wgHooks['ArticleSave'][] = 'fnEditWarning_save'; $wgHooks['UserLogout'][] = 'fnEditWarning_logout'; $wgHooks['ArticleViewHeader'][] = 'fnEditWarning_cancel'; /** * Inititalize EditWarning class * * @return: true */ function fnEditWarning_init() { if (EWDEBUG) error_log('----- fnEditWarning_init()'); global $wgRequest, $wgOut, $EditWarning_OnlyEditor; // Add CSS styles to header if ( ( $wgRequest->getVal('action') == 'edit' || $wgRequest->getVal('action') == 'submit' ) && $EditWarning_OnlyEditor ) { $wgOut->addHeadItem('edit_css', ' <link href="extensions/EditWarning/article_edit.css" rel="stylesheet" type="text/css" />'); } $wgOut->addHeadItem('EditWarning', ' <link href="extensions/EditWarning/EditWarning.css" rel="stylesheet" type="text/css" />'); return true; } /** * Action on editing page * * @hook: AlternateEdit * @param: &$editpage * Editpage object * @return true */ function fnEditWarning_edit(&$editpage) { global $PHP_SELF; if (EWDEBUG) error_log('----- fnEditWarning_edit()'); if ($editpage->mArticle->mTitle->getNamespace() == 'NS_MAIN') { $article_title = $editpage->mArticle->mTitle->getPartialURL(); } else { $article_title = $editpage->mArticle->mTitle->getNsText() . ":" . $editpage->mArticle->mTitle->getPartialURL(); } $page_name = $editpage->mTitle->getText(); $p = EditWarning::getInstance($editpage->mArticle->getID()); $p->getEditor($page_name); $p->setReplacementVar('URL', $PHP_SELF . "?title=" . $article_title); if ($p->userActive() || $p->onlyUser() || !$p->activeEditing()) { // // The current user is editing the page - show notice // $timestamp = mktime(date("H"), date("i") + $p->getTimeout(), date("s"), date("m"), date("d"), date("Y")); $p->setReplacementVar('DATE', date("Y-m-d", $timestamp)); $p->setReplacementVar('TIME', date("H:i", $timestamp)); $p->editorUpdate($page_name); $html = $p->processTemplate('notice'); } else { // // The user opened the page after the active user - show warning // $active_user = $p->getActiveUser(); $time_user = $active_user['timestamp']; $timestamp = mktime(date("H", $time_user), date("i", $time_user) - $p->getTimeout(), date("s", $time_user), date("m", $time_user), date("d", $time_user), date("Y", $time_user)); // Calculate time to wait. $difference = floatval(abs(time() - $time_user)); $time_to_wait = bcdiv($difference, 60, 0); // Debug if (EWDEBUG) { error_log(sprintf(' difference: %s seconds', $difference)); error_log(sprintf(' time_to_wait: %s minutes', $time_to_wait)); } $p->setReplacementVar('DATE', date('Y-m-d', $timestamp)); $p->setReplacementVar('TIME', date('H:i', $timestamp)); $p->setReplacementVar('USERNAME', $active_user['name']); if ($time_to_wait > 1 || $difference > 60) { $p->setReplacementVar('MINSEC', $p->getReplacementMsg('MINUTES')); } else { $p->setReplacementVar('MINSEC', $p->getReplacementMsg('SECONDS')); $time_to_wait = $difference; } $p->setReplacementVar('TIMEOUT', $time_to_wait); $html = $p->processTemplate('warning'); } $editpage->editFormPageTop .= $html; return true; } /** * Action on article save * * @hook: ArticleSave * @param: &$article * Article object * @return: boolean * Returns true if the page lock could be removed from DB. * Default return: false */ function fnEditWarning_save(&$article, &$user, &$text, &$summary, $minor, $watch, $sectionanchor, &$flags) { if (EWDEBUG) error_log('----- fnEditWarning_save()'); $p = EditWarning::getInstance(); $p->setArticleID($article->getID()); if ($p->deleteUser($p->getUserID())) { return true; } return false; } /** * Action if user cancels editing * * @hook: ArticleViewHeader * @param: &$article * Article object * @return: boolean * Returns false if the page lock couldn't be removed from DB. * Default return: true */ function fnEditWarning_cancel(&$article) { if (EWDEBUG) error_log('----- fnEditWarning_cancel()'); global $wgRequest, $wgOut; if ($wgRequest->getVal('cancel') == 'true') { $p = EditWarning::getInstance(); $p->setArticleID($article->getID()); if(!$p->deleteUser($p->getUserID())) { return false; } $wgOut->addHtml($p->processTemplate('canceled')); } return true; } /** * Remove all page locks on logout * * @hook: UserLogout * @param: &$user * User object * @return: boolean * Returns true if all page locks could be removed from DB. * Default return: false */ function fnEditWarning_logout(&$user) { if (EWDEBUG) error_log('----- fnEditWarning_logout()'); $p = EditWarning::getInstance(); if ($p->deleteUserAll($p->getUserID())) { return true; } return false; } }
[edit] Update EditWarning.class.php
<?php /** * EditWarning base class * * This file is part of the MediaWiki extension EditWarning * * @author Thomas David <ThomasDavid@gmx.de> * @addtogroup Extensions * @version 0.3.5 * @copyright 2010 by Thomas David * @license GNU GPL 2.0 or later * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * @version 0.3.8 <Jostar> check pages with are opened to edit but not jet saved, relative path for file-inclusion is used */ class EditWarning { private static $_instance = null; private $_article_id; private $_page_name; private $_user_id; private $_user_name; private $_editors; private $_timeout; private $_tpl_replacements = array("var" => array(), "msg" => array()); private function __clone() {} public static function getInstance($article_id = null) { if (EWDEBUG) error_log(sprintf('getInstance(%s)', $article_id)); if (self::$_instance == null) { if (EWDEBUG) error_log('Create new EditWarning instance.'); self::$_instance = new EditWarning($article_id); } else { self::$_instance->setArticleID($article_id); } return self::$_instance; } protected function __construct(&$article_id = null) { if (EWDEBUG) error_log(sprintf('Construct EditWarning. article_id: %s', $article_id)); global $wgUser, $wgRequest, $EditWarning_Timeout; if ($article_id != null) { $this->_article_id = $article_id; } $this->_user_id = $wgUser->getID(); $this->_user_name = $wgUser->getName(); $timeout = intval($EditWarning_Timeout); if ($timeout == '' || $timeout == null || $timeout <= 0) { // Set default timeout to 10 minutes. $this->_timeout = 10; } else { $this->_timeout = $timeout; } // Load extension message strings require_once dirname( __FILE__ ) . "/EditWarning.i18n.php"; isset($messages[strtolower($wgUser->getOption("language"))]) ? $lang = strtolower($wgUser->getOption("language")) : $lang = "en"; foreach($messages[$lang] as $key => $msg) { $this->_tpl_replacements['msg'][strtoupper($key)] = $msg; } // Debug if (EWDEBUG) { error_log('EditWarning vars:'); error_log(sprintf(' _article_id: %s', $this->_article_id)); error_log(sprintf(' _page_name: %s', $this->_page_name)); error_log(sprintf(' _user_id: %s', $this->_user_id)); error_log(sprintf(' _user_name: %s', $this->_user_name)); error_log(sprintf(' _editors: %s', $this->_editors)); error_log(sprintf(' _timeout: %s', $this->_timeout)); } return true; } /** * Returns article id. * * @access public * @return int */ public function getArticleID() { return $this->_article_id; } /** * Returns user id. * * @access public * @return int */ public function getUserID() { return $this->_user_id; } /** * Returns user name. * * @access public * @return string */ public function getUserName() { return $this->_user_name; } /** * Returns timeout. * * @access public * @return int */ public function getTimeout() { return $this->_timeout; } /** * Returns active user * * @access public * @return array */ public function getActiveUser() { return $this->_editors['active']; } public function getEditor($page_name) { // Load article editors //if($this->_article_id != null) { if($this->_getArticleEditor($this->_article_id, $page_name)) { return true; } //} return false; } /** * Returns a i18n message * * @access public * @return string */ public function getReplacementMsg($name) { return $this->_tpl_replacements['msg'][$name]; } /** * Returns article editors * * @access private * @return array */ private function _getEditors() { return $this->_editors; } /** * Returns template contents * * @access private * @return string */ private function _getTemplate($tpl_name) { $filename = dirname( __FILE__ ) . "/tpl_" . $tpl_name . ".html"; $file = @fopen($filename, "r"); $tpl_content = @fread($file, filesize($filename)); @fclose($file); // Debug if (EWDEBUG) { error_log(sprintf('_getTemplate(%s): %s', $tpl_name, $filename)); if (!file) error_log('ERROR! Couldn\'t open template file!'); if (!tpl_content) error_log('ERROR! Couldn\'t read template file!'); } return $tpl_content; } /** * Sets article id * * @access public * @param int article_id * @return true */ public function setArticleID($article_id) { if (EWDEBUG) error_log(sprintf('Set _article_id to %s', $article_id)); $this->_article_id = $article_id; return true; } /** * Sets user values * * @access public * @param array user * @return true */ public function setUser($user) { $this->_user_id = $user['id']; $this->_user_name = $user['name']; } /** * Set variable for replacement * * @access public * @return true */ public function setReplacementVar($name, $content) { if (EWDEBUG) error_log(sprintf('Set _tpl_replacements[\'var\'][%s] to %s', $name, $content)); $this->_tpl_replacements['var'][$name] = $content; return true; } /** * Loads template, replaces variables with i18n strings * * @access public * @return string */ public function processTemplate($tpl_name) { if (EWDEBUG) error_log(sprintf('processTempate(%s)', $tpl_name)); $tpl_data = $this->_getTemplate($tpl_name); // Messages foreach ($this->_tpl_replacements['msg'] as $msg => $replacement) { $tpl_data = preg_replace("/{{{" . $msg . "}}}/", $replacement, $tpl_data); } // Variables foreach ($this->_tpl_replacements['var'] as $var => $replacement) { $tpl_data = preg_replace("/{{{" . $var . "}}}/", $replacement, $tpl_data); } return $tpl_data; } /** * Gets article editor from DB and sets array _editors * * @access private * @return true */ private function _getArticleEditor($article_id, $page_name) { if (EWDEBUG) error_log(sprintf('_getArticleEditor(%s, %s)', $article_id, $page_name)); global $wgDBprefix; $editors = array(); $dbr =& wfGetDB(DB_SLAVE); $page_id = $this->getArticleID(); $timestamp = mktime(date("H"), date("i"), date("s"), date("m"), date("d"), date("Y")); // Debug if (EWDEBUG) { error_log(sprintf(' page_id: %s', $page_id)); error_log(sprintf(' timestamp: %s (%s)', $timestamp, date('Y-m-d H:i:s', $timestamp))); } $conditions = ($page_id == 0 ? "(`page_id` = '0' AND `page_name` = '$page_name')" : "`page_id` = '$page_id'"); $conditions .= sprintf( " AND timestamp >= '%s'", $timestamp ); $conditions .= sprintf( " ORDER BY timestamp DESC" ); $result = $dbr->select( "current_edits", "*", $conditions ); while ($row = $dbr->fetchObject($result)) { if (EWDEBUG) error_log(sprintf(' %s [id: %s, timestamp: %s]', $row->user_name, $row->user_id, $row->timestamp)); $editors[$row->user_name] = array($row->user_id, $row->timestamp); // Save active user $editors['active'] = array( "name" => $row->user_name, "id" => $row->user_id, "timestamp" => $row->timestamp ); } $dbr->freeResult($result); $this->_editors = $editors; return true; } /** * Checks if the user is the only editor * * @access private * @return boolean * Returns true if the user is the only editor. * Default return: false */ public function onlyUser() { $editors = $this->_getEditors(); $user_id = $this->getUserID(); $user_name = $this->getUserName(); // Debug if (EWDEBUG) { error_log('onlyUser()'); error_log(sprintf(' editors count: %s', count($editors))); error_log(sprintf(' first editor: %s', $editors[$user_name][0])); error_log(sprintf(' user_id: %s', $user_id)); error_log(sprintf(' user_name: %s', $user_name)); } if ((count($editors) == 1 && $editors[$user_name][0] == $user_id) || count($editors) == 0) { if (EWDEBUG) error_log('RETURN true.'); return true; } if (EWDEBUG) error_log('RETURN false'); return false; } /** * Checks if the user is the active user * * @access public * @return boolean * Returns true if the user is editing the page. * Default return: false */ public function userActive() { $editors = $this->_getEditors(); $user_id = $this->getUserID(); // Debug if (EWDEBUG) { error_log('userActive()'); error_log(sprintf(' active id: %s', $editors['active']['id'])); error_log(sprintf(' user_id: %s', $user_id)); } if ($editors['active']['id'] == $user_id) { if (EWDEBUG) error_log('RETURN true'); return true; } if (EWDEBUG) error_log('RETURN false'); return false; } /** * Checks if someone is editing the page * * @access public * @return boolean * Returns true if someone is editing the page. * Default return: false */ public function activeEditing() { if (DEBUG) error_log('activeEditing()'); $editors = $this->_getEditors(); if (count($editors) == 0) { if (EWDEBUG) error_log('RETURN false'); return false; } if (EWDEBUG) error_log('RETURN true'); return true; } /** * Checks if the user is editing the page. * * @access public * @return boolean * Returns true if user has an entry. * Default return: false */ public function userExists($editors) { $editors = $this->_getEditors(); $user_id = $this->getUserID(); $user_name = $this->getUserName(); if ($editors[$user_name][0] == $user_id) { return true; } return false; } /** * Update the editors for the page * * @access public * @return boolean * Returns false if the user is anonymous * Default return: true */ public function editorUpdate($page_name) { if (EWDEBUG) error_log('editorUpdate()'); global $wgDBprefix; $dbw =& wfGetDB( DB_MASTER ); $timestamp = mktime(date("H"), date("i") + $this->getTimeout(), date("s"), date("m"), date("d"), date("Y")); $page_id = $this->getArticleID(); $user_id = $this->getUserID(); $user_name = $this->getUserName(); // Debug if (EWDEBUG) { error_log(sprintf(' timestamp: %s (%s)', $timestamp, date('Y-m-d H:i:s', $timestamp))); error_log(sprintf(' page_id: %s', $page_id)); error_log(sprintf(' user_id: %s', $user_id)); error_log(sprintf(' user_name: %s', $user_name)); } // Mark new pages which have not jet an ID if (!$page_id ) $page_id = 0; // Don't save anonymous users or pages without a name if ($page_name == "" || $user_id == 0) { if (EWDEBUG) error_log('Anonymous user. Break.'); return false; } if ($this->userExists($this->_getEditors())) { $value = array( "timestamp" => $timestamp ); $conditions = array( 'user_id' => $user_id, 'page_id' => $page_id, 'page_name' => $page_name, ); $dbw->update( "current_edits", $value, $conditions ); } else { $values = array( 'page_id' => $page_id, 'page_name' => $page_name, 'user_id' => $user_id, 'user_name' => $user_name, 'timestamp' => $timestamp ); $dbw->insert( "current_edits", $values ); } return true; } /** * Remove the page lock of a user * * @param int user_id * @return boolean * Return true if the removal was successfull. * Default return: false */ public function deleteUser($user_id) { if (EWDEBUG) error_log(sprintf('deleteUser(%s)', $user_id)); global $wgDBprefix; $dbw =& wfGetDB( DB_MASTER ); $page_id = $this->getArticleID(); $conditions = array ( 'user_id' => $user_id, 'page_id' => $page_id ); $dbw->delete( "current_edits", $conditions ); return true; } /** * Remove all page locks of a user * * @param int user_id * @return boolean * Return true if the removal was successfull. * Default return: false */ public function deleteUserAll($user_id) { if (EWDEBUG) error_log(sprintf('deleteUserAll(%s)', $user_id)); global $wgDBprefix; $dbw =& wfGetDB( DB_MASTER ); $conditions = array( 'user_id' => $user_id ); $dbw->delete( "current_edits", $conditions ); return true; } }
