MarkAHershberger has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/376161 )
Change subject: Some refactoring and re-arranging ...................................................................... Some refactoring and re-arranging Change-Id: I1cb2e4d75dc382563918726c2b1072724b5e430e --- M .gitignore D CategoryWatch.php M extension.json A src/CategoryWatch.php A src/Hook.php 5 files changed, 455 insertions(+), 457 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CategoryWatch refs/changes/61/376161/1 diff --git a/.gitignore b/.gitignore index 4a59931..d2d7c2e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *~ \#*\# .\#* +.tramp_history # misc PHPTAGS.sqlite diff --git a/CategoryWatch.php b/CategoryWatch.php deleted file mode 100644 index aca8f23..0000000 --- a/CategoryWatch.php +++ /dev/null @@ -1,453 +0,0 @@ -<?php -/** - * CategoryWatch extension - * - Extends watchlist functionality to include notification about membership - * changes of watched categories - * - * Copyright (C) 2008 Aran Dunkley - * Copyright (C) 2017 Sean Chen - * Copyright (C) 2017 Mark A. Hershberger - * - * 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. - * - * See https://www.mediawiki.org/Extension:CategoryWatch - * for installation and usage details - * See http://www.organicdesign.co.nz/Extension_talk:CategoryWatch - * for development notes and disucssion - * - * @file - * @ingroup Extensions - * @author Aran Dunkley [http://www.organicdesign.co.nz/nad User:Nad] - * @copyright © 2008 Aran Dunkley - * @licence GNU General Public Licence 2.0 or later - */ - -class CategoryWatch { - // Instance - protected static $watcher; - - /** - * The extension function. - * It has to be the static function in a class now. - */ - public static function setupCategoryWatch() { - wfDebugLog( 'CategoryWatch', 'loading extension...' ); - - # Instantiate the CategoryWatch singleton now - # that the environment is prepared - self::$watcher = new CategoryWatch(); - } - - /** - * Get a list of categories before article updated Since MediaWiki - * version 1.25.x, we have to use static function for hooks. the - * hook has different signatures. - * @param WikiPage $wikiPage the page - * @param User $user who is modifying - * @param Content $content the new article content - * @param string $summary the article summary (comment) - * @param bool $isMinor minor flag - * @param bool $isWatch watch flag (not used, aka always null) - * @param int $section section number (not used, aka always null) - * @param int $flags see WikiPage::doEditContent documentation for flags' definition - * @param Status $status Status (object) - */ - public static function onPageContentSave( - $wikiPage, $user, $content, $summary, $isMinor, - $isWatch, $section, $flags, $status - ) { - global $wgCategoryWatchUseAutoCat, $wgCategoryWatchUseAutoCatRealName, - $wgCategoryWatch; - - self::$watcher->before = []; - $dbr = wfGetDB( DB_MASTER ); - $cl = $dbr->tableName( 'categorylinks' ); - $id = $wikiPage->getID(); - wfDebugLog( 'CategoryWatch', "tablename = $cl" ); - wfDebugLog( 'CategoryWatch', "page id=$id" ); - $res = $dbr->select( - $cl, 'cl_to', "cl_from = $id", __METHOD__, - [ 'ORDER BY' => 'cl_sortkey' ] - ); - $row = $dbr->fetchRow( $res ); - while ( $row ) { - self::$watcher->before[] = $row[0]; - $row = $dbr->fetchRow( $res ); - } - $dbr->freeResult( $res ); - wfDebugLog( 'CategoryWatch', 'Categories before page saved' ); - wfDebugLog( 'CategoryWatch', join( ', ', self::$watcher->before ) ); - - # If using the automatically watched category feature, ensure - # that all users are watching it - if ( $wgCategoryWatchUseAutoCat ) { - $dbr = wfGetDB( DB_SLAVE ); - - # Find all users not watching the autocat - $like = str_replace( - ' ', '_', - trim( wfMessage( 'categorywatch-autocat', '' )->text() ) - ); - $utbl = $dbr->tableName( 'user' ); - $wtbl = $dbr->tableName( 'watchlist' ); - $sql = "SELECT user_id FROM $utbl LEFT JOIN $wtbl ON " - . "user_id=wl_user AND wl_title LIKE '%$like%' " - . "WHERE wl_user IS NULL"; - - # Insert an entry into watchlist for each - $row = $dbr->fetchRow( $res ); - while ( $row ) { - $user = User::newFromId( $row[0] ); - $name = $wgCategoryWatchUseAutoCatRealName - ? $user->getRealName() - : $user->getName(); - $wl_title = str_replace( - ' ', '_', wfMessage( 'categorywatch-autocat', $name )->text() - ); - $dbr->insert( - $wtbl, - [ - 'wl_user' => $row[0], 'wl_namespace' => NS_CATEGORY, - 'wl_title' => $wl_title - ] - ); - $row = $dbr->fetchRow( $res ); - } - $dbr->freeResult( $res ); - } - } - - /** - * the proper hook for save page request. - * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageContentSaveComplete - * @param WikiPage $article Article edited - * @param User $user who edited - * @param Content $content New article text - * @param string $summary Edit summary - * @param bool $isMinor Minor edit or not - * @param bool $isWatch Watch this article? - * @param string $section Section that was edited - * @param int $flags Edit flags - * @param Revision $revision that was created - * @param Status $status of activities - * @param int $baseRevId base revision - */ - public static function onPageContentSaveComplete( - $article, $user, $content, $summary, $isMinor, $isWatch, $section, - $flags, $revision, $status, $baseRevId - ) { - # Get cats after update - self::$watcher->after = []; - - $parseTimestamp = $revision->getTimestamp(); - $content = $revision->getContent(); - $title = $article->getTitle(); - $options = $content->getContentHandler()->makeParserOptions( 'canonical' ); - $options->setTimestamp( $parseTimestamp ); - $output = $content->getParserOutput( $title, $revision->getId(), $options ); - self::$watcher->after = array_map( - 'strval', array_keys( $output->getCategories() ) - ); - wfDebugLog( 'CategoryWatch', 'Categories after page saved' ); - wfDebugLog( 'CategoryWatch', join( ', ', self::$watcher->after ) ); - - # Get list of added and removed cats - $add = array_diff( self::$watcher->after, self::$watcher->before ); - $sub = array_diff( self::$watcher->before, self::$watcher->after ); - - # Notify watchers of each cat about the addition or removal of this article - if ( count( $add ) > 0 || count( $sub ) > 0 ) { - $page = $article->getTitle(); - $pagename = $page->getPrefixedText(); - $pageurl = $page->getFullUrl(); - $page = "$pagename ($pageurl)"; - - if ( count( $add ) == 1 && count( $sub ) == 1 ) { - $add = array_shift( $add ); - $sub = array_shift( $sub ); - - $title = Title::newFromText( $add, NS_CATEGORY ); - $message = wfMessage( - 'categorywatch-catmovein', $page, - self::$watcher->friendlyCat( $add ), - self::$watcher->friendlyCat( $sub ) - )->text(); - self::$watcher->notifyWatchers( - $title, $user, $message, $summary, $medit, $pageurl - ); - - $title = Title::newFromText( $sub, NS_CATEGORY ); - $message = wfMessage( - 'categorywatch-catmoveout', $page, - self::$watcher->friendlyCat( $sub ), - self::$watcher->friendlyCat( $add ) - )->text(); - self::$watcher->notifyWatchers( - $title, $user, $message, $summary, $medit, $pageurl - ); - } else { - - foreach ( $add as $cat ) { - $title = Title::newFromText( $cat, NS_CATEGORY ); - $message = wfMessage( - 'categorywatch-catadd', $page, - self::$watcher->friendlyCat( $cat ) - )->text(); - self::$watcher->notifyWatchers( - $title, $user, $message, $summary, $medit, $pageurl - ); - } - - foreach ( $sub as $cat ) { - $title = Title::newFromText( $cat, NS_CATEGORY ); - $message = wfMessage( - 'categorywatch-catsub', $page, - self::$watcher->friendlyCat( $cat ) - )->text(); - self::$watcher->notifyWatchers( - $title, $user, $message, $summary, $medit, $pageurl - ); - } - } - } - - global $wgCategoryWatchNotifyParentWatchers; - if ( $wgCategoryWatchNotifyParentWatchers ) { - self::notifyParentWatchers(); - } - } - - /** - * Notify the watchers of parent categories - */ - protected static function notifyParentWatchers() { - self::$watcher->allparents = []; - self::$watcher->i = 0; - self::$watcher->findCategoryParents( self::$watcher->after ); - ## For each active parent category, send the mail - if ( self::$watcher->allparents ) { - $page = $article->getTitle(); - $pageurl = $page->getFullUrl(); - foreach ( self::$watcher->allparents as $cat ) { - $title = Title::newFromText( $cat, NS_CATEGORY ); - $message = wfMessage( - 'categorywatch-catchange', $page, - self::$watcher->friendlyCat( $cat ) - ); - self::$watcher->notifyWatchers( - $title, $user, $message, $summary, $medit, $pageurl - ); - } - } - } - - /** - * Recursively find all parents of the given categories - * - * @param array $catarray the categories - */ - protected function findCategoryParents( array $catarray ) { - $this->i++; - if ( $this->i == 200 ) { - return; - } - - if ( $catarray ) { - foreach ( $catarray as $catname ) { - self::$watcher->allparents[] = $catname; - $id = self::$watcher->getCategoryArticleId( $catname ); - if ( is_numeric( $id ) ) { - $parentCat = self::$watcher->getParentCategories( $id ); - if ( $parentCat ) { - self::$watcher->allparents[] = $parentCat; - self::$watcher->findCategoryParents( [ $parentCat ] ); - } - } - } - self::$watcher->allparents = array_unique( self::$watcher->allparents ); - } - } - - /** - * Return the parent categories - * @param int $id Category Article id - * @return parents - */ - protected function getParentCategories( $id ) { - $dbr = wfGetDB( DB_SLAVE ); - $cl = $dbr->tableName( 'categorylinks' ); - $res = $dbr->select( - $cl, 'cl_to', "cl_from = $id", __METHOD__, - [ 'ORDER BY' => 'cl_sortkey' ] - ); - $row = $dbr->fetchRow( $res ); - $dbr->freeResult( $res ); - if ( empty( $row[0] ) ) { - return false; - } - return $row[0]; - } - - /** - * Load page ID of one category - * - * @param string $catname name of category - * @return int - */ - protected function getCategoryArticleId( $catname ) { - $dbr = wfGetDB( DB_SLAVE ); - $cl = $dbr->tableName( 'page' ); - $res = $dbr->select( $cl, 'page_id', "page_title = '$catname'", __METHOD__ ); - $row = $dbr->fetchRow( $res ); - $dbr->freeResult( $res ); - return $row[0]; - } - - /** - * Return "Category:Cat (URL)" from "Cat" - * @param string $cat name of category - * @return string - */ - protected function friendlyCat( $cat ) { - $cat = Title::newFromText( $cat, NS_CATEGORY ); - $catname = $cat->getPrefixedText(); - $caturl = $cat->getFullUrl(); - return "$catname ($caturl)"; - } - - /** - * Notify any watchers - * @param Title $title of article - * @param User $editor of article - * @param string $message for user - * @param string $summary editor gave - * @param bool $medit true if minor - * @param string $pageurl of page - */ - function notifyWatchers( $title, $editor, $message, $summary, $medit, $pageurl ) { - global $wgLang, $wgNoReplyAddress, $wgCategoryWatchNotifyEditor, - $wgEnotifRevealEditorAddress, $wgEnotifUseRealName, $wgPasswordSender, - $wgEnotifFromEditor, $wgPasswordSenderName; - - # Get list of users watching this category - $dbr = wfGetDB( DB_SLAVE ); - $conds = [ - 'wl_title' => $title->getDBkey(), 'wl_namespace' => $title->getNamespace() - ]; - if ( !$wgCategoryWatchNotifyEditor ) { - $conds[] = 'wl_user <> ' . intval( $editor->getId() ); - } - $res = $dbr->select( 'watchlist', [ 'wl_user' ], $conds, __METHOD__ ); - - # Wrap message with common body and send to each watcher - $page = $title->getPrefixedText(); - $adminAddress = new MailAddress( - $wgPasswordSender, - isset( $wgPasswordSenderName ) - ? $wgPasswordSenderName - : 'WikiAdmin' - ); - $editorAddress = new MailAddress( $editor ); - $summary = $summary - ? $summary - : ' - '; - $medit = $medit - ? wfMessage( 'minoredit' )->text() - : ''; - $row = $dbr->fetchRow( $res ); - while ( $row ) { - $watchingUser = User::newFromId( $row[0] ); - $timecorrection = $watchingUser->getOption( 'timecorrection' ); - $editdate = $wgLang->timeanddate( - wfTimestampNow(), true, false, $timecorrection - ); - - if ( - $watchingUser->getOption( 'enotifwatchlistpages' ) - && $watchingUser->isEmailConfirmed() - ) { - $to = new MailAddress( $watchingUser ); - $subject = wfMessage( 'categorywatch-emailsubject', $page )->text(); - $body = wfMessage( 'enotif_body' )->inContentLanguage()->text(); - - # Reveal the page editor's address as REPLY-TO address only if - # the user has not opted-out and the option is enabled at the - # global configuration level. - if ( $wgCategoryWatchNoRealName ) { - $name = $watchingUser->getName(); - } - $name = $wgEnotifUseRealName - ? $watchingUser->getRealName() - : $watchingUser->getName(); - if ( $wgEnotifRevealEditorAddress - && ( $editor->getEmail() != '' ) - && $editor->getOption( 'enotifrevealaddr' ) - ) { - if ( $wgEnotifFromEditor ) { - $from = $editorAddress; - } else { - $from = $adminAddress; - $replyto = $editorAddress; - } - } else { - $from = $adminAddress; - $replyto = new MailAddress( $wgNoReplyAddress ); - } - - # Define keys for body message - $userPage = $editor->getUserPage(); - $keys = [ - '$WATCHINGUSERNAME' => $name, - '$NEWPAGE' => $message, - '$PAGETITLE' => $page, - '$PAGEEDITDATE' => $editdate, - '$CHANGEDORCREATED' => wfMessage( 'changed' ) - ->inContentLanguage()->text(), - '$PAGETITLE_URL' => $title->getFullUrl(), - '$PAGEEDITOR_WIKI' => $userPage->getFullUrl(), - '$PAGESUMMARY' => $summary, - '$PAGEMINOREDIT' => $medit, - '$OLDID' => '' - ]; - if ( $editor->isIP( $name ) ) { - $utext = wfMessage( - 'enotif_anon_editor', $name - )->inContentLanguage()->text(); - $subject = str_replace( '$PAGEEDITOR', $utext, $subject ); - $keys['$PAGEEDITOR'] = $utext; - $keys['$PAGEEDITOR_EMAIL'] = wfMmessage( - 'noemailtitle' - )->inContentLanguage()->text(); - } else { - $subject = str_replace( '$PAGEEDITOR', $name, $subject ); - $keys['$PAGEEDITOR'] = $name; - $emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $name ); - $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getFullUrl(); - } - $keys['$PAGESUMMARY'] = $summary; - - # Replace keys, wrap text and send - $body = strtr( $body, $keys ); - $body = wordwrap( $body, 72 ); - $options = []; - $options['replyTo'] = $replyto; - UserMailer::send( $to, $from, $subject, $body, $options ); - } - } - - $dbr->freeResult( $res ); - } -} diff --git a/extension.json b/extension.json index 2d06c58..343fa1e 100644 --- a/extension.json +++ b/extension.json @@ -11,20 +11,21 @@ "license-name": "GPL-2.0+", "type": "other", "AutoloadClasses": { - "CategoryWatch": "CategoryWatch.php" + "CategoryWatch\\CategoryWatch": "src/CategoryWatch.php", + "CategoryWatch\\Hook": "src/Hook.php" }, "ExtensionFunctions": [ - "CategoryWatch::setupCategoryWatch" + "CategoryWatch\\Hook::setupCategoryWatch" ], "MessagesDirs": { "CategoryWatch": "i18n" }, "Hooks": { "PageContentSave": [ - "CategoryWatch::onPageContentSave" + "CategoryWatch\\Hook::onPageContentSave" ], "PageContentSaveComplete": [ - "CategoryWatch::onPageContentSaveComplete" + "CategoryWatch\\Hook::onPageContentSaveComplete" ] }, "config": { diff --git a/src/CategoryWatch.php b/src/CategoryWatch.php new file mode 100644 index 0000000..09469c9 --- /dev/null +++ b/src/CategoryWatch.php @@ -0,0 +1,357 @@ +<?php + +/** + * Misc functions for category watches + * + * Copyright (C) 2017 Mark A. Hershberger + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +namespace CategoryWatch; + +class CategoryWatch { + public $before = []; + public $after = []; + + protected $count = 0; + protected $allParents = []; + + protected $wikiPage; + protected $editor; + protected $content; + protected $summary; + protected $minorEdit; + protected $flags; + + /** + * Construction + * @param WikiPage $wikiPage the page + * @param User $user who is modifying + * @param Content $content the new article content + * @param string $summary the article summary (comment) + * @param bool $isMinor minor flag + * @param int $flags see WikiPage::doEditContent documentation for flags' definition + */ + public function __construct( + WikiPage $wikiPage, User $user, Content $content, $summary, $isMinor, $flags + ) { + $this->wikiPage; + $this->editor; + $this->content; + $this->summary; + $this->minorEdit; + $this->flags; + + $this->before = $this->wikiPage->getTitle()->getParentCategories(); + $this->doAutoCat(); + } + + /** + * Notify all category watchers + * + * @param Revision $revision that was created + * @param int $baseRevId base revision + */ + public function notifyCategoryWatchers( + Revision $revision, $baseRevId + ) { + # Get cats after update + $this->after = $this->wikiPage->getTitle()->getParentCategories(); + + # Get list of added and removed cats + $add = array_diff( $this->after, $this->before ); + $sub = array_diff( $this->before, $this->after ); + wfDebugLog( 'CategoryWatch', 'Categories after page saved' ); + wfDebugLog( 'CategoryWatch', join( ', ', $this->after ) ); + wfDebugLog( 'CategoryWatch', 'Categories added' ); + wfDebugLog( 'CategoryWatch', join( ', ', $add ) ); + wfDebugLog( 'CategoryWatch', 'Categories removed' ); + wfDebugLog( 'CategoryWatch', join( ', ', $sub ) ); + + # Notify watchers of each cat about the addition or removal of this article + if ( count( $add ) > 0 || count( $sub ) > 0 ) { + $page = $article->getTitle(); + $pagename = $page->getPrefixedText(); + $pageurl = $page->getFullUrl(); + $page = "$pagename ($pageurl)"; + + if ( count( $add ) == 1 && count( $sub ) == 1 ) { + $this->notifyMove( $sub[0], $add[0] ); + } else { + $this->notifyAdd( $add ); + + foreach ( $sub as $cat ) { + $title = Title::newFromText( $cat, NS_CATEGORY ); + $message = wfMessage( + 'categorywatch-catsub', $page, + $this->friendlyCat( $cat ) + )->text(); + $this->notifyWatchers( + $title, $user, $message, $summary, $medit, $pageurl + ); + } + } + } + + if ( $this->shouldNotifyParentWatchers() ) { + $this->notifyParentWatchers(); + } + } + + protected function shouldNotifyParentWatchers() { + global $wgCategoryWatchNotifyParentWatchers; + return $wgCategoryWatchNotifyParentWatchers; + } + + protected function shouldNotifyEditor() { + global $wgCategoryWatchNotifyEditor; + return $wgCategoryWatchNotifyEditor; + } + + protected function useRealName() { + global $wgCategoryWatchNoRealName; + return !$wgCategoryWatchNoRealName; + } + + /** + * Return "Category:Cat (URL)" from "Cat" + * @param string $cat name of category + * @return string + */ + protected function friendlyCat( $cat ) { + $cat = Title::newFromText( $cat, NS_CATEGORY ); + $catname = $cat->getPrefixedText(); + $caturl = $cat->getFullUrl(); + return "$catname ($caturl)"; + } + + /** + * Notify any watchers + * @param Title $title of article + * @param User $editor of article + * @param string $message for user + * @param string $summary editor gave + * @param bool $medit true if minor + * @param string $pageurl of page + */ + protected function notifyWatchers( + $title, $editor, $message, $summary, $medit, $pageurl + ) { + global $wgLang, $wgNoReplyAddress, + $wgEnotifRevealEditorAddress, $wgEnotifUseRealName, $wgPasswordSender, + $wgEnotifFromEditor, $wgPasswordSenderName; + + # Get list of users watching this category + $dbr = wfGetDB( DB_SLAVE ); + $conds = [ + 'wl_title' => $title->getDBkey(), 'wl_namespace' => $title->getNamespace() + ]; + if ( !$this->shouldNotifyEditor() ) { + $conds[] = 'wl_user <> ' . intval( $editor->getId() ); + } + $res = $dbr->select( 'watchlist', [ 'wl_user' ], $conds, __METHOD__ ); + + # Wrap message with common body and send to each watcher + $page = $title->getPrefixedText(); + $adminAddress = new MailAddress( + $wgPasswordSender, + isset( $wgPasswordSenderName ) + ? $wgPasswordSenderName + : 'WikiAdmin' + ); + $editorAddress = new MailAddress( $editor ); + $summary = $summary + ? $summary + : ' - '; + $medit = $medit + ? wfMessage( 'minoredit' )->text() + : ''; + $row = $dbr->fetchRow( $res ); + while ( $row ) { + $watchingUser = User::newFromId( $row[0] ); + $timecorrection = $watchingUser->getOption( 'timecorrection' ); + $editdate = $wgLang->timeanddate( + wfTimestampNow(), true, false, $timecorrection + ); + + if ( + $watchingUser->getOption( 'enotifwatchlistpages' ) + && $watchingUser->isEmailConfirmed() + ) { + $to = new MailAddress( $watchingUser ); + $subject = wfMessage( 'categorywatch-emailsubject', $page )->text(); + $body = wfMessage( 'enotif_body' )->inContentLanguage()->text(); + + # Reveal the page editor's address as REPLY-TO address only if + # the user has not opted-out and the option is enabled at the + # global configuration level. + $name = $wgEnotifUseRealName + ? $watchingUser->getRealName() + : $watchingUser->getName(); + if ( $wgEnotifRevealEditorAddress + && ( $editor->getEmail() != '' ) + && $editor->getOption( 'enotifrevealaddr' ) + ) { + if ( $wgEnotifFromEditor ) { + $from = $editorAddress; + } else { + $from = $adminAddress; + $replyto = $editorAddress; + } + } else { + $from = $adminAddress; + $replyto = new MailAddress( $wgNoReplyAddress ); + } + + # Define keys for body message + $userPage = $editor->getUserPage(); + $keys = [ + '$WATCHINGUSERNAME' => $name, + '$NEWPAGE' => $message, + '$PAGETITLE' => $page, + '$PAGEEDITDATE' => $editdate, + '$CHANGEDORCREATED' => wfMessage( 'changed' ) + ->inContentLanguage()->text(), + '$PAGETITLE_URL' => $title->getFullUrl(), + '$PAGEEDITOR_WIKI' => $userPage->getFullUrl(), + '$PAGESUMMARY' => $summary, + '$PAGEMINOREDIT' => $medit, + '$OLDID' => '' + ]; + if ( $editor->isIP( $name ) ) { + $utext = wfMessage( + 'enotif_anon_editor', $name + )->inContentLanguage()->text(); + $subject = str_replace( '$PAGEEDITOR', $utext, $subject ); + $keys['$PAGEEDITOR'] = $utext; + $keys['$PAGEEDITOR_EMAIL'] = wfMmessage( + 'noemailtitle' + )->inContentLanguage()->text(); + } else { + $subject = str_replace( '$PAGEEDITOR', $name, $subject ); + $keys['$PAGEEDITOR'] = $name; + $emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $name ); + $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getFullUrl(); + } + $keys['$PAGESUMMARY'] = $summary; + + # Replace keys, wrap text and send + $body = strtr( $body, $keys ); + $body = wordwrap( $body, 72 ); + $options = []; + $options['replyTo'] = $replyto; + UserMailer::send( $to, $from, $subject, $body, $options ); + } + } + + $dbr->freeResult( $res ); + } + + /** + * Notify the watchers of parent categories + */ + protected function notifyParentWatchers() { + $this->allparents = $this->wikiPage->getTitle()->getParentCategoryTree(); + $page = $this->wikiPage->getTitle(); + $pageUrl = $page->getFullUrl(); + foreach ( (array)$this->allparents as $cat ) { + $title = Title::newFromText( $cat, NS_CATEGORY ); + $message = wfMessage( + 'categorywatch-catchange', $page, + $this->friendlyCat( $cat ) + ); + $this->notifyWatchers( + $title, $user, $message, $summary, $medit, $pageurl + ); + } + } + + /** + * Handle autocat option + */ + protected function doAutoCat() { + global $wgCategoryWatchUseAutoCat; + if ( $wgCategoryWatchUseAutoCat ) { + $dbr = wfGetDB( DB_SLAVE ); + + # Find all users not watching the autocat + $like = '%' . str_replace( + ' ', '_', trim( wfMessage( 'categorywatch-autocat', '' )->text() ) + ) . '%'; + $res = $dbr->select( [ 'user', 'watchlist' ], 'user_id', + 'wl_user IS NULL', __METHOD__, [], + [ 'watchlist' => [ 'LEFT JOIN', + [ + 'user_id=wl_user', + 'wl_tile', $dbr->buildLike( $like ) + ] ] ] ); + + + # Insert an entry into watchlist for each + $row = $dbr->fetchRow( $res ); + while ( $row ) { + $user = User::newFromId( $row[0] ); + $name = $user->getName(); + $wl_title = str_replace( + ' ', '_', wfMessage( 'categorywatch-autocat', $name )->text() + ); + $dbr->insert( + 'watchlist', + [ + 'wl_user' => $row[0], 'wl_namespace' => NS_CATEGORY, + 'wl_title' => $wl_title + ] + ); + $row = $dbr->fetchRow( $res ); + } + $dbr->freeResult( $res ); + } + } + + protected function notifyMove( $from, $to ) { + $title = Title::newFromText( $add, NS_CATEGORY ); + $message = wfMessage( + 'categorywatch-catmovein', $page, + $this->friendlyCat( $add ), + $this->friendlyCat( $sub ) + )->text(); + $this->notifyWatchers( + $title, $user, $message, $summary, $medit, $pageurl + ); + + $title = Title::newFromText( $sub, NS_CATEGORY ); + $message = wfMessage( + 'categorywatch-catmoveout', $page, + $this->friendlyCat( $sub ), + $this->friendlyCat( $add ) + )->text(); + $this->notifyWatchers( + $title, $user, $message, $summary, $medit, $pageurl + ); + } + + protected function notifyAdd( $add ) { + foreach ( $add as $cat ) { + $title = Title::newFromText( $cat, NS_CATEGORY ); + $message = wfMessage( + 'categorywatch-catadd', $page, + $this->friendlyCat( $cat ) + )->text(); + $this->notifyWatchers( + $title, $user, $message, $summary, $medit, $pageurl + ); + } + } +} \ No newline at end of file diff --git a/src/Hook.php b/src/Hook.php new file mode 100644 index 0000000..15072bc --- /dev/null +++ b/src/Hook.php @@ -0,0 +1,92 @@ +<?php +/** + * CategoryWatch extension + * - Extends watchlist functionality to include notification about membership + * changes of watched categories + * + * Copyright (C) 2008 Aran Dunkley + * Copyright (C) 2017 Sean Chen + * Copyright (C) 2017 Mark A. Hershberger + * + * 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. + * + * See https://www.mediawiki.org/Extension:CategoryWatch + * for installation and usage details + * See http://www.organicdesign.co.nz/Extension_talk:CategoryWatch + * for development notes and disucssion + * + * @file + * @ingroup Extensions + * @author Aran Dunkley [http://www.organicdesign.co.nz/nad User:Nad] + * @copyright © 2008 Aran Dunkley + * @licence GNU General Public Licence 2.0 or later + */ + +namespace CategoryWatch; + +use SpecialPage; +use Title; +use User; +use UserMailer; + +class Hook { + // Instance + protected static $watcher; + + /** + * Instantiate CategoryWatch object and get categories + * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageContentSave + * @param WikiPage $wikiPage the page + * @param User $user who is modifying + * @param Content $content the new article content + * @param string $summary the article summary (comment) + * @param bool $isMinor minor flag + * @param bool $isWatch watch flag (not used, aka always null) + * @param int $section section number (not used, aka always null) + * @param int $flags see WikiPage::doEditContent documentation for flags' definition + * @param Status $status Status (object) + */ + public static function onPageContentSave( + $wikiPage, $user, $content, $summary, $isMinor, + $isWatch, $section, $flags, $status + ) { + self::$watcher = new CategoryWatch( + $wikiPage, $user, $content, $summary, $isMinor, $flags + ); + } + + /** + * the proper hook for save page request. + * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageContentSaveComplete + * @param WikiPage $article Article edited + * @param User $user who edited + * @param Content $content New article text + * @param string $summary Edit summary + * @param bool $isMinor Minor edit or not + * @param bool $isWatch Watch this article? + * @param string $section Section that was edited + * @param int $flags Edit flags + * @param Revision $revision that was created + * @param Status $status of activities + * @param int $baseRevId base revision + */ + public static function onPageContentSaveComplete( + $article, $user, $content, $summary, $isMinor, $isWatch, $section, + $flags, $revision, $status, $baseRevId + ) { + self::$watcher->notifyCategoryWatchers( $revision, $baseRevId ); + } +} -- To view, visit https://gerrit.wikimedia.org/r/376161 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I1cb2e4d75dc382563918726c2b1072724b5e430e Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/CategoryWatch Gerrit-Branch: master Gerrit-Owner: MarkAHershberger <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
