Extension:EditWarning/0.3.8

From MediaWiki.org
Jump to: navigation, search

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;
  }
}
Personal tools
Namespaces

Variants
Actions
Navigation
Support
Download
Development
Communication
Print/export
Toolbox