diff --git a/README.mediawiki b/README.mediawiki index b64708e..e4614a5 100644 --- a/README.mediawiki +++ b/README.mediawiki @@ -16,10 +16,23 @@ Information about previous versions can be found on: http://www.mediawiki.org/wiki/Extension:Wikilog http://groups.google.com/group/mediawiki-wikilog += Important: Original version notice = + +Original version of Wikilog was abandoned in 2012 by Juliano F. Ravasi. + +However, there is still a version of Wikilog (named 1.3.0) available in official +Wikimedia repositories (https://phabricator.wikimedia.org/r/branch/mediawiki/extensions/Wikilog, +https://github.com/wikimedia/mediawiki-extensions-Wikilog). + +We DO NOT recommend using it, because nobody develops it or adds new features, +there are only Wikimedia developers who are replacing deprecated API calls with +their newer versions. + = Requirements = -* MediaWiki 1.19-1.21 or higher, or Mediawiki4Intranet 1.18. -* A MySQL database backend. +* MediaWiki 1.19-1.27, or Mediawiki4Intranet 1.18. +* A MySQL or PostgreSQL database backend. +* ParserFunctions extension. = Installation = @@ -33,10 +46,13 @@ Information about previous versions can be found on: == Updating == -Always run php maintenance/update.php when you're updating Wikilog. Some of the updates -may not need it, bun an extra run will never harm :) +* Update code in `extensions/Wikilog` +* Run `php maintenance/update.php` to upgrade DB structure. Some updates + may not need it, but an extra run will never harm :) -If you are upgrading from one of previous versions of Wikilog, you should also run +If you are upgrading to MediaWiki4Intranet Wikilog from the original version of Wikilog +taken from the official repositories (see "Original version notice" above), or from +MediaWiki4Intranet Wikilog older than 9 Oct 2013, AND you have you should also run: php maintenance/patchSql.php extensions/Wikilog/archives/fill-wikilog-comment-meta.sql diff --git a/RELEASE-NOTES.mediawiki b/RELEASE-NOTES.mediawiki index 6ab812e..f687d3b 100644 --- a/RELEASE-NOTES.mediawiki +++ b/RELEASE-NOTES.mediawiki @@ -1,23 +1,31 @@ = Wikilog release notes = -== Mediawiki4Intranet's Wikilog as of 2013-10-10 == +== Mediawiki4Intranet's Wikilog 2.0 == + +* Support for PostgreSQL +* Support for MediaWiki up to 1.26 +* Several bug fixes + +== Mediawiki4Intranet's Wikilog as of 2015-01-21 == Our Wikilog version is heavily improved; there is a lot of new big features: * «Forum» view — i.e. sorting of entries by the date of last comment in «archives» mode, and unread comment count tracking -*: Add link to /Special:Wikilog?view=archives&show=published&sort=wlp_talk_updated&desc=1 in your MediaWiki:Sidebar with «WikiForum» title to get a forum view. -* (!) Wikilog-style hierarchical talk support for normal pages, not just for the blogs. +*: Add link to /Special:Wikilog?view=archives&show=published&sort=wlp_talk_updated&desc=1 in your MediaWiki:Sidebar with «WikiForum» title to get a forum view +* (!) Wikilog-style hierarchical talk support for normal pages, not just for the blogs * Comment email notifications -* New blog entry email notifications for main blog page watchers +* New blog entry email notifications (subscribe by watching main page of the blog) * RSS/Atom comment feeds * Subscribing/unsubscribing to all comments in a blog, or even in all blogs in a wiki (the last is a user preference) * New post creation form on Special:Wikilog (in the «blog agregator») +* Exclusion of blogs and posts in specific category from the aggregated view ($wgWikilogDefaultNotCategory) * Drop-down lists for wikilog/author/category fields on Special:Wikilog * Post calendar for MediaWiki:Sidebar *: Add «* wikilogcalendar» to MediaWiki:Sidebar to enable it * Automatic folding of non-branching comments to the linear view — this prevents too many nesting levels without any loss of hierarchy * Improved binary encoding of materialized paths to comments, allowing to store up to 250 nesting levels, versus 36 in old Wikilog * Pagination which never breaks discussion threads +* Thread/list view switching for comments * Experimental support for importing dumps from blogger.com * Various bug fixes diff --git a/SpecialWikilog.php b/SpecialWikilog.php index c30d9bb..d9873b2 100644 --- a/SpecialWikilog.php +++ b/SpecialWikilog.php @@ -53,6 +53,10 @@ function __construct( ) { parent::__construct( 'Wikilog' ); } + protected function getGroupName() { + return 'changes'; + } + /** * Execute the special page. * Called from MediaWiki. @@ -240,8 +244,7 @@ public function webOutput( FormOptions $opts ) { 'rel' => 'alternate', 'href' => $wgTitle->getLocalURL( $altquery ), 'type' => $wgMimeType, - 'title' => wfMsgExt( "wikilog-view-{$alt}", - array( 'content', 'parsemag' ) ) + 'title' => wfMessage( "wikilog-view-{$alt}" )->inContentLanguage()->text(), ) ); } } @@ -272,7 +275,7 @@ public function getMarkAllReadLink() $query = $wgRequest->getValues(); $query['markallread'] = wfTimestamp( TS_MW ); return Xml::wrapClass( - Xml::element( 'a', array( 'href' => $wgTitle->getFullUrl( $query ) ), wfMsg( 'wikilog-mark-all-read' ) ), + Xml::element( 'a', array( 'href' => $wgTitle->getFullUrl( $query ) ), wfMessage( 'wikilog-mark-all-read' )->text() ), 'markallread', 'p' ); } @@ -295,7 +298,7 @@ public function feedOutput( $format, FormOptions $opts ) { * and also the name that will be listed in Special:Specialpages. */ public function getDescription() { - return wfMsg( 'wikilog-specialwikilog-title' ); + return wfMessage( 'wikilog-specialwikilog-title' )->text(); } /** @@ -331,6 +334,8 @@ public function parseInlineParams( $parameters, FormOptions $opts ) { if ( ( $date = self::parseDateParam( $m[1] ) ) ) { list( $opts['year'], $opts['month'], $opts['day'] ) = $date; } + } elseif ( preg_match( '/^notcategory=(.*)$/', $par, $m ) ) { + $opts['notcategory'] = $m[1]; } else { if ( ( $t = Title::newFromText( $par ) ) !== null ) { $ns = $t->getNamespace(); @@ -366,7 +371,7 @@ protected function getHeader( FormOptions $opts ) { } $out = Xml::tags( 'form', array( 'action' => $wgScript ), $out ); - $out = Xml::fieldset( wfMsg( 'wikilog-form-legend' ), $out, + $out = Xml::fieldset( wfMessage( 'wikilog-form-legend' )->text(), $out, array( 'class' => 'wl-options' ) ); $out .= WikilogMainPage::formNewItem( NULL ); @@ -525,11 +530,11 @@ protected function getQueryFormFields( FormOptions $opts ) { if ( count( $values ) > 0 ) { $select = new XmlSelect( $valueid, 'wl-'.$valueid, $formvalues[$valueid] ); - $select->addOption( wfMsg('wikilog-form-all'), '' ); + $select->addOption( wfMessage( 'wikilog-form-all' )->text(), '' ); foreach( $values as $o ) $select->addOption( $o[0], count($o) > 1 ? $o[1] : false ); $fields[$valueid] = array( - Xml::label( wfMsg( 'wikilog-form-'.$valueid ), 'wl-'.$valueid ), + Xml::label( wfMessage( 'wikilog-form-'.$valueid )->text(), 'wl-'.$valueid ), $select->getHTML() ); } @@ -539,7 +544,7 @@ protected function getQueryFormFields( FormOptions $opts ) { else { $fields[$valueid] = Xml::inputLabelSep( - wfMsg( 'wikilog-form-'.$valueid ), $valueid, 'wl-'.$valueid, 40, + wfMessage( 'wikilog-form-'.$valueid )->text(), $valueid, 'wl-'.$valueid, 40, $formvalues[$valueid] ); } @@ -547,36 +552,36 @@ protected function getQueryFormFields( FormOptions $opts ) { $month_select = new XmlSelect( 'month', 'wl-month', $opts->consumeValue( 'month' ) ); $month_select->setAttribute( 'onchange', "{var wly=document.getElementById('wl-year');if(wly&&!wly.value){wly.value='".date('Y')."';}}" ); - $month_select->addOption( wfMsg('monthsall'), '' ); + $month_select->addOption( wfMessage( 'monthsall' )->text(), '' ); for ($i = 1; $i <= 12; $i++) $month_select->addOption( $wgLang->getMonthName( $i ), $i ); $year_field = Xml::input( 'year', 4, $opts->consumeValue( 'year' ), array( 'maxlength' => 4, 'id' => 'wl-year' ) ); $fields['date'] = array( - Xml::label( wfMsg( 'wikilog-form-date' ), 'wl-month' ), + Xml::label( wfMessage( 'wikilog-form-date' )->text(), 'wl-month' ), $month_select->getHTML() . " " . $year_field ); $opts->consumeValue( 'day' ); // ignore day, not really useful $viewSelect = new XmlSelect( 'view', 'wl-view', $opts->consumeValue( 'view' ) ); - $viewSelect->addOption( wfMsg( 'wikilog-view-summary' ), 'summary' ); - $viewSelect->addOption( wfMsg( 'wikilog-view-archives' ), 'archives' ); + $viewSelect->addOption( wfMessage( 'wikilog-view-summary' )->text(), 'summary' ); + $viewSelect->addOption( wfMessage( 'wikilog-view-archives' )->text(), 'archives' ); $fields['view'] = array( - Xml::label( wfMsg( 'wikilog-form-view' ), 'wl-view' ), + Xml::label( wfMessage( 'wikilog-form-view' )->text(), 'wl-view' ), $viewSelect->getHTML() ); if( $wgUser && $wgUser->getID() ) { $statusSelect = new XmlSelect( 'show', 'wl-status', $opts->consumeValue( 'show' ) ); - $statusSelect->addOption( wfMsg( 'wikilog-show-all' ), 'all' ); - $statusSelect->addOption( wfMsg( 'wikilog-show-published' ), 'published' ); - $statusSelect->addOption( wfMsg( 'wikilog-show-drafts' ), 'drafts' ); + $statusSelect->addOption( wfMessage( 'wikilog-show-all' )->text(), 'all' ); + $statusSelect->addOption( wfMessage( 'wikilog-show-published' )->text(), 'published' ); + $statusSelect->addOption( wfMessage( 'wikilog-show-drafts' )->text(), 'drafts' ); $fields['status'] = array( - Xml::label( wfMsg( 'wikilog-form-status' ), 'wl-status' ), + Xml::label( wfMessage( 'wikilog-form-status' )->text(), 'wl-status' ), $statusSelect->getHTML() ); } - $fields['submit'] = Xml::submitbutton( wfMsg( 'allpagessubmit' ) ); + $fields['submit'] = Xml::submitbutton( wfMessage( 'allpagessubmit' )->text() ); return $fields; } diff --git a/SpecialWikilogSubscriptions.php b/SpecialWikilogSubscriptions.php index 55d3228..45773a5 100644 --- a/SpecialWikilogSubscriptions.php +++ b/SpecialWikilogSubscriptions.php @@ -1,5 +1,26 @@ mTitle = SpecialPage::getTitleFor( 'wikilogsubscriptions' ); } + protected function getGroupName() { + return 'changes'; + } + public function execute( $parameters ) { global $wgUser, $wgRequest; @@ -72,7 +97,7 @@ public function execute( $parameters ) { 'LIMIT' => $opts['comments_limit'], 'OFFSET' => $opts['comments_offset'] ); - $res = $dbr->select( array( $tbl, 'page' ), 'page.*', $where, __METHOD__, $qo ); + $res = $dbr->select( array( $tbl, 'p' => 'page' ), 'p.*', $where, __METHOD__, $qo ); foreach ( $res as $row ) { $opts['comments'][] = Title::newFromRow( $row ); } @@ -87,12 +112,12 @@ public function webOutput( $opts ) { $this->webOutputPartial( $opts, 'blogs', 'boffset', 'blimit', - http_build_query( array( 'coffset' => $opts['comments_offset'], 'climit' => $opts['comments_limit'] ) ) + array( 'coffset' => $opts['comments_offset'], 'climit' => $opts['comments_limit'] ) ); $wgOut->addHtml( '

' ); $this->webOutputPartial( $opts, 'comments', 'coffset', 'climit', - http_build_query( array( 'boffset' => $opts['blogs_offset'], 'blimit' => $opts['blogs_limit'] ) ) + array( 'boffset' => $opts['blogs_offset'], 'blimit' => $opts['blogs_limit'] ) ); return $wgOut; @@ -104,28 +129,27 @@ public function errorPage( $error = 'wikilog-subscription-unauthorized' ) { } protected function webOutputPartial( $opts, $key, $offsetReplacement, $limitReplacement, $query ) { - global $wgOut; + global $wgOut, $wgLang; $html = '
'; - $html .= '

' . wfMsgNoTrans( 'wikilog-subscription-' . $key ) . '

'; + $html .= '

' . wfMessage( 'wikilog-subscription-'.$key )->plain() . '

'; if ( count( $opts[$key] ) > 0 ) { $html .= ''; - $html .= ''; + $html .= ''; foreach ( $opts[$key] as $title ) { $html .= $this->itemHTML( $title, $key == 'comments' ); } $html .= '
' . wfMsgNoTrans( 'wikilog-subscription-header-action'); - $html .= '' . wfMsgNoTrans( 'wikilog-subscription-header-' . $key ) . '
' . wfMessage( 'wikilog-subscription-header-action' )->plain(); + $html .= '' . wfMessage( 'wikilog-subscription-header-'.$key )->plain() . '
'; } else { - $html .= wfMsgNoTrans( 'wikilog-subscription-' . $key . '-empty' ); + $html .= wfMessage( 'wikilog-subscription-'.$key.'-empty' )->plain(); } $html .= '
'; $wgOut->addHtml( $html ); - - $link = wfViewPrevNext( + $link = $wgLang->viewPrevNext( + $this->mTitle, $opts[$key . '_offset'], $opts[$key . '_limit'], - $this->mTitle, $query, $opts[$key . '_offset'] + $opts[$key . '_limit'] >= $opts[$key . '_count'] ); @@ -148,7 +172,7 @@ protected function subscribe() { $id = $wgRequest->getVal( 'subscribe_to' ); $title = Title::newFromID( $id ); - if ( !$title || !$title->userCanRead() ) { + if ( !$title || !$title->userCan( 'read' ) ) { return $this->errorPage( 'wikilog-subscription-access-denied' ); } @@ -171,7 +195,7 @@ protected function subscribe() { 'ws_page' => $title->getArticleID(), 'ws_user' => $wgUser->getID(), 'ws_yes' => $subscribe, - 'ws_date' => wfTimestamp( TS_MW ), + 'ws_date' => $dbw->timestamp(), ), __METHOD__ ); @@ -189,19 +213,19 @@ protected function subscribe() { if ( $subscribe ) { $wgOut->addHtml( - '

' . wfMsgNoTrans( 'wikilog-subscription-blog-subscribed', $wgUser->getSkin()->link( $title, $title->getPrefixedText() ) ) . + '

' . wfMessage( 'wikilog-subscription-blog-subscribed', Linker::link( $title, $title->getPrefixedText() ) )->plain() . '

' . self::generateSubscriptionLink( $title, true, true ) . '

' ); } elseif ( $isComments ) { $wi = Wikilog::getWikilogInfo( $title ); $key = ( $wi->isMain() ? 'wikilog-subscription-comment-unsubscribed-blog' : 'wikilog-subscription-comment-unsubscribed-article' ); $wgOut->addHtml( - '

' . wfMsgNoTrans( $key, $title->getPrefixedText() ) . + '

' . wfMessage( $key, $title->getPrefixedText() )->plain() . '

' . $this->getCommentSubscription( $title->getTalkPage() ) . '

' ); } else { $wgOut->addHtml( - '

' . wfMsgNoTrans( 'wikilog-subscription-blog-unsubscribed', $wgUser->getSkin()->link( $title, $title->getPrefixedText() ) ) . + '

' . wfMessage( 'wikilog-subscription-blog-unsubscribed', Linker::link( $title, $title->getPrefixedText() ) )->plain() . '

' . self::generateSubscriptionLink( $title, false, true ) . '

' ); } @@ -227,8 +251,8 @@ protected function itemHTML( $title, $comments = false ) { if ( $comments ) { $query ['comment'] = 1; } - $unsubscribeLink = $wgUser->getSkin()->link( $this->mTitle, wfMsgNoTrans( 'wikilog-subscription-item-unsubscribe' ), $params, $query ); - $titleLink = $wgUser->getSkin()->link( $title, $title->getPrefixedText() ); + $unsubscribeLink = Linker::link( $this->mTitle, wfMessage( 'wikilog-subscription-item-unsubscribe' )->plain(), $params, $query ); + $titleLink = Linker::link( $title, $title->getPrefixedText() ); $html = << {$unsubscribeLink} @@ -244,7 +268,7 @@ protected function itemHTML( $title, $comments = false ) { * @return string */ protected function getCommentSubscription( $title ) { - return wfMsgNoTrans( 'wikilog-subscription-comment-subscription', $title->getLinkUrl(), $title->getPrefixedText() ); + return wfMessage( 'wikilog-subscription-comment-subscription', $title->getLinkUrl(), $title->getPrefixedText() )->plain(); } /** @@ -255,8 +279,8 @@ protected function getCommentSubscription( $title ) { * @param boolean $subscribed Flag that current user is subscribed to article $title. If not null do not check * @return string */ - public static function generateSubscriptionLink( $title, $subscribed = null, $forEmail = false ) { - global $wgUser; + public static function generateSubscriptionLink( $title, $subscribed = null, $forEmail = false, $lang = NULL ) { + global $wgUser, $wgLang; if ( $wgUser->isAnon() ) { return ''; } @@ -276,7 +300,8 @@ public static function generateSubscriptionLink( $title, $subscribed = null, $fo $msg = ( $forEmail ? ( $subscribed ? 'wikilog-subscription-unsubscribe-email' : 'wikilog-subscription-subscribe-email' ) : ( $subscribed ? 'wikilog-subscription-unsubscribe' : 'wikilog-subscription-subscribe' ) ); - return $prefix . wfMsgNoTrans( $msg, $title->getText(), $link ); + return $prefix . wfMessage( $msg, $title->getText(), $link ) + ->inLanguage( $lang ? $lang : $wgLang )->plain(); } /** @@ -285,86 +310,82 @@ public static function generateSubscriptionLink( $title, $subscribed = null, $fo * @global User $wgUser * @return string */ - public static function subcriptionsRuleLink() { - global $wgUser; - return $wgUser->getSkin()->link( + public static function subcriptionsRuleLink( $lang = NULL ) { + global $wgLang; + return Linker::link( SpecialPage::getTitleFor( 'wikilogsubscriptions' ), - wfMsgNoTrans( 'wikilog-subscription-return-link' ) + wfMessage( 'wikilog-subscription-return-link' ) + ->inLanguage( $lang ? $lang : $wgLang )->plain() ); } - public static function sendEmails( &$article, &$user, $text, $summary, - $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId ) - { - if ( isset( $article->mExtWikilog ) && $article->mExtWikilog['signpub'] ) { - global $wgUser, $wgParser, $wgPasswordSender, $wgServer; + public static function sendEmails( &$article, $text ) { + global $wgUser, $wgPasswordSender, $wgServer, $wgContLang; - $dbr = wfGetDB( DB_SLAVE ); - - $title = $article->getTitle(); - $wi = Wikilog::getWikilogInfo( $title ); - $args = array( - $title->getSubpageText(), - $wgUser->getName(), - $title->getFullURL(), - $wi->mWikilogTitle->getText(), - $text, - $wi->mItemTalkTitle->getFullURL(), - $wi->mItemTalkTitle->getPrefixedText(), - ); + $dbr = wfGetDB( DB_SLAVE ); - // Generate body - $saveExpUrls = WikilogParser::expandLocalUrls(); - $popt = new ParserOptions( User::newFromId( $wgUser->getId() ) ); - $subject = $wgParser->parse( wfMsgNoTrans( 'wikilog-subscription-email-subject', $args ), - $title, $popt, false, false ); - $subject = strip_tags( $subject->getText() ); - $body = $wgParser->parse( wfMsgNoTrans( 'wikilog-subscription-email-body', $args), - $title, $popt, true, false ); - $body = $body->getText(); - $body .= self::generateSubscriptionLink( $wi->mWikilogTitle, true, true ) . - '
' . self::subcriptionsRuleLink(); - WikilogParser::expandLocalUrls( $saveExpUrls ); + $title = $article->getTitle(); + $wi = Wikilog::getWikilogInfo( $title ); + $args = array( + $title->getSubpageText(), + $wgUser->getName(), + $title->getFullURL(), + $wi->mWikilogTitle->getText(), + $text, + $wi->mItemTalkTitle->getFullURL(), + $wi->mItemTalkTitle->getPrefixedText(), + ); + $blogID = $wi->mWikilogTitle->getArticleID(); + $w = $dbr->tableName( 'watchlist' ); + $u = $dbr->tableName( 'user' ); + $up = $dbr->tableName( 'user_properties' ); + $res = $dbr->query( // Select subscribers - $blogID = $wi->mWikilogTitle->getArticleID(); - $res = $dbr->select( 'watchlist', 'wl_user', - 'wl_namespace = ' . NS_BLOG . ' AND wl_title = ' . $dbr->addQuotes( $wi->mWikilogTitle->getText() ), __METHOD__ ); - $emails = array(); - foreach ( $res as $row ) { - $user = User::newFromId( $row->wl_user ); - $user->mGroups = NULL; - if ( !$user || $title->getUserPermissionsErrors( 'read', $user ) ) { - continue; - } - $emails[$row->wl_user] = new MailAddress( $user->getEmail() ); - } + "SELECT $u.*, up_value user_language FROM $w". + " INNER JOIN $u ON user_id=wl_user". + " LEFT JOIN $up ON up_user=user_id AND up_property='language'". + " WHERE wl_namespace=" . NS_BLOG . + " AND wl_title=" . $dbr->addQuotes( $wi->mWikilogTitle->getDBkey() ) . // Select users who watch ALL blogs - $res = $dbr->select( 'user_properties', 'up_user', - "up_property='wl-subscribetoallblogs' AND up_value='1'", __METHOD__ ); - foreach ( $res as $row ) { - if( isset( $emails[$row->up_user] ) ) { - continue; - } - $user = User::newFromId( $row->up_user ); - $user->mGroups = NULL; - if ( !$user || $title->getUserPermissionsErrors( 'read', $user ) ) { - continue; - } - $emails[$row->up_user] = new MailAddress( $user->getEmail() ); + " UNION SELECT $u.*, l.up_value user_language FROM $up s". + " INNER JOIN $u ON user_id=s.up_user" . + " LEFT JOIN $up l ON l.up_user=user_id AND l.up_property='language'". + " WHERE s.up_property='wl-subscribetoallblogs' AND s.up_value='1'" + ); + $emails = array(); + foreach ( $res as $row ) { + if ( !$row->user_language ) { + $row->user_language = $wgContLang->getCode(); } - - // Send the message - if ( $emails ) { - $emails = array_values( $emails ); - $serverName = substr( $wgServer, strpos( $wgServer, '//' ) + 2 ); - $headers = array( - 'Message-ID' => 'getId() . '@' . $serverName . '>', - ); - $from = new MailAddress( $wgPasswordSender, 'Wikilog' ); - UserMailer::send( $emails, $from, $subject, $body, null, null, $headers ); + $user = User::newFromRow( $row ); + if ( $user && $user->getEmail() && $user->getEmailAuthenticationTimestamp() && + !$title->getUserPermissionsErrors( 'read', $user ) ) { + $emails[$row->user_language][$row->user_id] = new MailAddress( $user->getEmail() ); } } + if ( !$emails ) { + return true; + } + + // Generate body and subject in all selected languages and send it + $saveExpUrls = WikilogParser::expandLocalUrls(); + $from = new MailAddress( $wgPasswordSender, 'Wikilog' ); + $serverName = substr( $wgServer, strpos( $wgServer, '//' ) + 2 ); + $headers = array( + 'Message-ID' => 'getId() . '@' . $serverName . '>', + ); + foreach ( $emails as $lang => &$send ) { + $subject = strip_tags( wfMessage( 'wikilog-subscription-email-subject', $args ) + ->inLanguage( $lang )->parse() ); + $body = wfMessage( 'wikilog-subscription-email-body', $args ) + ->inLanguage( $lang )->parse() . + self::generateSubscriptionLink( $wi->mWikilogTitle, true, true, $lang ) . + '
' . self::subcriptionsRuleLink( $lang ); + WikilogUtils::sendHtmlMail( array_values( $send ), $from, $subject, $body, $headers ); + } + WikilogParser::expandLocalUrls( $saveExpUrls ); + return true; } } diff --git a/TODO b/TODO deleted file mode 100644 index 5f086bf..0000000 --- a/TODO +++ /dev/null @@ -1,5 +0,0 @@ -== Wikilog To-do list == - -=== Wikilog 1.3.0. === - -* Remove WikilogItemPage::preSaveTransform() (Mw 1.17 compatibility). diff --git a/Wikilog.i18n.ns.php b/Wikilog.i18n.ns.php index 0418f37..60b0188 100644 --- a/Wikilog.i18n.ns.php +++ b/Wikilog.i18n.ns.php @@ -11,11 +11,17 @@ /** English (English) */ $namespaceNames['en'] = array( NS_BLOG => 'Blog', - NS_BLOG_TALK => 'Blog talk', + NS_BLOG_TALK => 'Blog_talk', ); /** Russian (Русский) */ $namespaceNames['ru'] = array( NS_BLOG => 'Блог', - NS_BLOG_TALK => 'Обсуждение блога', + NS_BLOG_TALK => 'Обсуждение_блога', +); + +/** German (Deutsch) */ +$namespaceNames['de'] = array( + NS_BLOG => 'Blog', + NS_BLOG_TALK => 'Blog_Diskussion', ); diff --git a/Wikilog.i18n.php b/Wikilog.i18n.php index b72ebfe..50135ba 100644 --- a/Wikilog.i18n.php +++ b/Wikilog.i18n.php @@ -60,6 +60,7 @@ 'wikilog-new-item' => 'Create new wikilog article', 'wikilog-new-item-go' => 'Create', 'wikilog-new-item-subpage' => 'Invalid item name entered, it must not be a subpage!', + 'wikilog-new-item-too-long' => 'Invalid item name entered, it must be shoter!', 'wikilog-item-name' => 'Article name:', 'wikilog-import' => 'Import for Blogger.com blogs', 'wikilog-import-go' => 'Import', @@ -126,7 +127,7 @@ # Comments 'wikilog-comment-header' => '', 'wikilog-comment-footer' => '— $2 • $5 $6', - 'wikilog-comment-permalink' => '{{#if:$3|$1 at $2 ($3)|$1 at $2 ($3) [unread]}}', + 'wikilog-comment-permalink' => '{{#if:$4|$1 at $2 ($3)|$1 at $2 ($3) [unread]}}', 'wikilog-comment-note-item' => 'posted to $1', 'wikilog-comment-note-edited' => 'last edited on $1 at $2', 'wikilog-comment-anonsig' => '$3 (anonymous)', @@ -163,6 +164,7 @@ From now, you will be notified only if subscribed explicitly or if you\'re the author of post or the comment being replied.', 'wikilog-subscribed-as-author' => '

You will receive all comments to this entry by e-mail, because you are the author.


', + 'wikilog-subscribed-usertalk' => '

You will receive all comments to this page by e-mail, because it is your user talk page.


', /* These messages are parsed inside the context of item page, so {{SUBPAGENAME}} refers to the item, and is a crunch to output links instead of just bold text. */ @@ -187,9 +189,9 @@ * Read the post {{SUBPAGENAME}}. * [[$1|Reply to this comment]] and/or read discussion thread.', 'wikilog-comment-email-unsubscribe' => '

Unsubscribe from comments to $1.

', - 'wikilog-ptswitsher-to-parent' => 'answer to $1 from $2 $3 at $4', - 'wikilog-ptswitsher-to-comment' => 'To comment page', - 'wikilog-ptswitsher-comment-label' => 'comment', + 'wikilog-ptswitcher-to-parent' => 'reply to $1 from $2 $3 at $4', + 'wikilog-ptswitcher-to-comment' => 'To comment page', + 'wikilog-ptswitcher-comment-label' => 'comment', 'wikilog-ptswitcher-thread' => 'Thread view', 'wikilog-ptswitcher-list' => 'List view', @@ -272,9 +274,9 @@ 'wikilog-subscription-comments' => 'Subscriptions to comments:', 'wikilog-subscription-comments-empty' => 'You are not subscribed to any comments', 'wikilog-subscription-subscribe' => 'You are not subscribed to blog $1 via email yet. To subscribe click "watch".', - 'wikilog-subscription-unsubscribe' => 'You are already subscribed to blog $1 via email. To cancel subscribe click "unwatch".', + 'wikilog-subscription-unsubscribe' => 'You are already subscribed to blog $1 via email. Click "unwatch" on the main page of the blog to cancel the subscription.', 'wikilog-subscription-subscribe-email' => 'You are not subscribed to blog $1 via email yet. To subscribe click "watch" at main page of blog.', - 'wikilog-subscription-unsubscribe-email' => 'You are already subscribed to blog $1 via email. To cancel subscribe click "unwatch" at main page of blog.', + 'wikilog-subscription-unsubscribe-email' => 'You are already subscribed to blog $1 via email. Click "unwatch" on the main page of the blog to cancel the subscription.', 'wikilog-subscription-item-unsubscribe' => 'Cancel subscription', 'wikilog-subscription-header-action' => 'Action', 'wikilog-subscription-header-comments' => 'Article/blog title you are subscribed to comments', @@ -285,7 +287,7 @@ 'wikilog-subscription-comment-unsubscribed-article' => 'Your subscription to the comments to article $1 is canceled.', 'wikilog-subscription-comment-subscription' => 'You can subscribe to comments at discussion page: $2.', 'wikilog-subscription-return-link' => 'Subscription management page', - 'wikilog-subscription-email-subject' => '[Wikilog] $2 - New article in blog $4', + 'wikilog-subscription-email-subject' => '[Wikilog] $2 - New article in blog $4: $1', 'wikilog-subscription-email-body' => 'User [[{{ns:User}}:$2|$2]] published the article [$3 $1] in blog [[{{ns:Blog}}:$4]]:
@@ -6615,6 +6617,7 @@ 'wikilog-new-item' => 'Создать новую статью викилога', 'wikilog-new-item-go' => 'Создать', 'wikilog-new-item-subpage' => 'Название статьи викилога некорректно, оно не может содержать /!', + 'wikilog-new-item-too-long' => 'Название статьи викилога слишком длинное!', 'wikilog-item-name' => 'Название статьи:', 'wikilog-import' => 'Импорт для блогов blogger.com', 'wikilog-import-go' => 'Импортировать', @@ -6698,6 +6701,7 @@ С текущего момента вы будете получать уведомления, только если явно подписывались на запись, или вы автор этой записи, или вы автор комментария, на который оставлен ответ.', 'wikilog-subscribed-as-author' => '

Вы будете получать все комментарии к этой записи по e-mail, потому что вы её автор.


', + 'wikilog-subscribed-usertalk' => '

Вы будете получать все комментарии к этой странице по e-mail, потому что это обсуждение вашей страницы участника.


', 'wikilog-feed-description' => 'Читать последние сообщения на этом канале.', 'wikilog-comment-feed-title1' => 'Комментарии от $2 (#$1)', @@ -6727,9 +6731,9 @@ * Прочитать запись {{SUBPAGENAME}}. * [[$1|Ответить на этот комментарий]] и/или просмотреть ветвь обсуждения.', 'wikilog-comment-email-unsubscribe' => '

Отписаться от комментариев к записи $1.

', - 'wikilog-ptswitsher-to-parent' => 'ответ на $1 от $2 $3 в $4', - 'wikilog-ptswitsher-to-comment' => 'Перейти к комментарию', - 'wikilog-ptswitsher-comment-label' => 'комментарий', + 'wikilog-ptswitcher-to-parent' => 'ответ на $1 от $2 $3 в $4', + 'wikilog-ptswitcher-to-comment' => 'Перейти к комментарию', + 'wikilog-ptswitcher-comment-label' => 'комментарий', 'wikilog-ptswitcher-thread' => 'Иерархический вид', 'wikilog-ptswitcher-list' => 'Хронологический вид', @@ -6810,7 +6814,7 @@ 'wikilog-subscription-comment-unsubscribed-article' => 'Вы отменили e-mail подписку на комментарии к статье $1.', 'wikilog-subscription-comment-subscription' => 'Подписаться на комментарии можно на странице обсуждения: $2.', 'wikilog-subscription-return-link' => 'Управление e-mail подписками на блоги и комментарии', - 'wikilog-subscription-email-subject' => '[Wikilog] $2 - Новая статья в блоге $4', + 'wikilog-subscription-email-subject' => '[Wikilog] $2 - Новая статья в блоге $4: $1', 'wikilog-subscription-email-body' => 'Пользователь [[{{ns:User}}:$2|$2]] опубликовал статью [$3 $1] в блоге [[{{ns:Blog}}:$4]]:
diff --git a/Wikilog.php b/Wikilog.php index acb7cc7..ec93ba6 100644 --- a/Wikilog.php +++ b/Wikilog.php @@ -35,8 +35,8 @@ $wgExtensionCredits['specialpage'][] = array( 'path' => __FILE__, 'name' => 'Wikilog', - 'version' => '1.2.0', - 'author' => 'Juliano F. Ravasi', + 'version' => '2.0.1', + 'author' => 'Juliano F. Ravasi, Vitaliy Filippov', 'descriptionmsg' => 'wikilog-desc', 'url' => 'https://www.mediawiki.org/wiki/Extension:Wikilog', ); @@ -131,6 +131,13 @@ $wgSpecialPageGroups['Wikilog'] = 'changes'; $wgSpecialPageGroups['WikilogComments'] = 'changes'; +$wgResourceModules['ext.wikilog'] = array( + 'localBasePath' => __DIR__.'/style', + 'remoteExtPath' => 'Wikilog/style', + 'scripts' => array('wikilog.js'), + 'styles' => array('wikilog.css'), +); + /** * Hooks. */ @@ -154,8 +161,7 @@ // General Wikilog hooks $wgHooks['ArticleEditUpdates'][] = 'WikilogHooks::ArticleEditUpdates'; $wgHooks['ArticleDelete'][] = 'WikilogHooks::ArticleDelete'; -$wgHooks['ArticleSave'][] = 'WikilogHooks::ArticleSave'; -$wgHooks['ArticleSaveComplete'][] = 'SpecialWikilogSubscriptions::sendEmails'; +$wgHooks['PageContentSave'][] = 'WikilogHooks::ArticleSave'; $wgHooks['TitleMoveComplete'][] = 'WikilogHooks::TitleMoveComplete'; $wgHooks['EditPage::attemptSave'][] = 'WikilogHooks::EditPageAttemptSave'; $wgHooks['EditPage::showEditForm:fields'][] = 'WikilogHooks::EditPageEditFormFields'; @@ -253,7 +259,7 @@ static function setupNamespace( $ns, $name, $talk ) { */ static function setupBlogNamespace( $ns ) { global $wgExtensionMessagesFiles, $wgExtraNamespaces, $wgWikilogNamespaces, - $wgWikilogCommentNamespaces, $wgContentNamespaces; + $wgNamespaceAliases, $wgWikilogCommentNamespaces, $wgContentNamespaces, $wgLanguageCode; if ( $ns < 100 ) { echo "Wikilog setup: custom namespaces should start " . "at 100 to avoid conflict with standard namespaces.\n"; @@ -265,11 +271,11 @@ static function setupBlogNamespace( $ns ) { if ( $wgWikilogCommentNamespaces !== true ) { $wgWikilogCommentNamespaces[NS_BLOG_TALK] = true; } - $wgExtraNamespaces[NS_BLOG] = 'Blog'; - $wgExtraNamespaces[NS_BLOG_TALK] = 'Blog_talk'; $wgWikilogNamespaces[] = $ns; $wgContentNamespaces[] = $ns; - $wgExtensionMessagesFiles[ 'WikilogNamespace' ] = dirname( __FILE__ ).'/Wikilog.i18n.ns.php'; + require dirname( __FILE__ ).'/Wikilog.i18n.ns.php'; + $wgExtraNamespaces += $namespaceNames[isset($namespaceNames[$wgLanguageCode]) ? $wgLanguageCode : 'en']; + $wgNamespaceAliases += array_flip($namespaceNames['en']); } # ## @@ -325,15 +331,17 @@ static function getPreferences( $user, &$defaultPreferences ) { * returns an instance of WikilogInfo) and returns the proper class * instance for the article. */ - static function ArticleFromTitle( &$title, &$article ) { + static function ArticleFromTitle( $title, &$article ) { if ( $title->isTalkPage() ) { - if ( self::nsHasComments( $title ) ) { - $article = new WikilogCommentsPage( $title ); - return false; // stop processing + $page = WikilogCommentsPage::createInstance( $title ); + if ( $page ) { + $article = $page; + return false; } + return true; // continue hook processing if createInstance returned NULL } elseif ( ( $wi = self::getWikilogInfo( $title ) ) ) { if ( $wi->isItem() ) { - $item = WikilogItem::newFromInfo( $wi ); + $item = WikilogItem::newFromID( $title->getArticleID() ); $article = new WikilogItemPage( $title, $item ); } else { $article = new WikilogMainPage( $title, $wi ); @@ -350,20 +358,20 @@ static function ArticleFromTitle( &$title, &$article ) { * (msg:noarticletext), since it gives wrong instructions to visitors. * The comment form is self-explaining enough. */ - static function ArticleViewHeader( &$article, &$outputDone, &$pcache ) { + static function ArticleViewHeader( $article, &$outputDone, $pcache ) { if ( $article instanceof WikilogCommentsPage && $article->getID() == 0 ) { $outputDone = true; return false; } return true; } + /** * BeforePageDisplay hook handler function. - * Adds wikilog CSS to pages displayed. + * Adds wikilog CSS and JS to pages displayed. */ - static function BeforePageDisplay( &$output, &$skin ) { - global $wgWikilogStylePath, $wgWikilogStyleVersion; - $output->addExtensionStyle( "{$wgWikilogStylePath}/wikilog.css?{$wgWikilogStyleVersion}" ); + static function BeforePageDisplay( $output, $skin ) { + $output->addModules( 'ext.wikilog' ); return true; } @@ -372,11 +380,10 @@ static function BeforePageDisplay( &$output, &$skin ) { * Links to threaded talk pages should be always "known" and * always edited normally, without adding the sections. */ - static function LinkBegin( $skin, $target, &$text, &$attribs, &$query, - &$options, &$ret ) + static function LinkBegin( $skin, $target, $text, $attribs, $query, &$options, &$ret ) { if ( $target->isTalkPage() && - ( $i = array_search( 'broken', $options ) ) !== false ) { + ( $i = array_search( 'broken', array_keys($options) ) ) !== false ) { if ( self::nsHasComments( $target ) ) { array_splice( $options, $i, 1 ); $options[] = 'known'; @@ -389,8 +396,7 @@ static function LinkBegin( $skin, $target, &$text, &$attribs, &$query, * SkinTemplateTabAction hook handler function. * Same as Wikilog::LinkBegin, but for the tab actions. */ - static function SkinTemplateTabAction( &$skin, $title, $message, $selected, - $checkEdit, &$classes, &$query, &$text, &$result ) + static function SkinTemplateTabAction( $skin, $title, $message, $selected, $checkEdit, &$classes, &$query, &$text, &$result ) { if ( $checkEdit && $title->isTalkPage() && !$title->exists() ) { if ( self::nsHasComments( $title ) ) { @@ -431,14 +437,14 @@ static function SkinTemplateNavigation( $skin, &$links ) { * Helper function for SkinTemplateTabs and SkinTemplateNavigation hooks * to configure views links in wikilog pages. */ - private static function skinConfigViewsLinks( WikilogInfo &$wi, $skin, &$views ) { + private static function skinConfigViewsLinks( WikilogInfo $wi, $skin, &$views ) { global $wgRequest, $wgWikilogEnableComments; $action = $wgRequest->getText( 'action' ); if ( $wi->isMain() && $skin->getTitle()->quickUserCan( 'edit' ) ) { $views['wikilog'] = array( 'class' => ( $action == 'wikilog' ) ? 'selected' : false, - 'text' => wfMsg( 'wikilog-tab' ), + 'text' => wfMessage( 'wikilog-tab' )->text(), 'href' => $skin->getTitle()->getLocalUrl( 'action=wikilog' ) ); } @@ -453,16 +459,16 @@ private static function skinConfigViewsLinks( WikilogInfo &$wi, $skin, &$views ) * SkinBuildSidebar hook handler function. * Adds support for "* wikilogcalendar" on MediaWiki:Sidebar */ - static function SkinBuildSidebar($skin, &$bar) + static function SkinBuildSidebar( $skin, &$bar ) { global $wgTitle, $wgRequest, $wgWikilogNumArticles; - if (array_key_exists('wikilogcalendar', $bar)) - { + if ( array_key_exists( 'wikilogcalendar', $bar ) ) { global $wlCalPager; - if (!$wlCalPager) - unset($bar['wikilogcalendar']); - else + if ( !$wlCalPager ) { + unset( $bar['wikilogcalendar'] ); + } else { $bar['wikilogcalendar'] = WikilogCalendar::sidebarCalendar($wlCalPager); + } } return true; } @@ -482,8 +488,9 @@ static function SkinBuildSidebar($skin, &$bar) static function getWikilogInfo( $title ) { global $wgWikilogNamespaces; - if ( !$title ) + if ( !$title ) { return null; + } $ns = MWNamespace::getSubject( $title->getNamespace() ); if ( in_array( $ns, $wgWikilogNamespaces ) ) { @@ -528,28 +535,28 @@ class WikilogInfo */ function __construct( $title ) { $origns = $title->getNamespace(); - $this->mIsTalk = MWNamespace::isTalk( $origns ); - $ns = MWNamespace::getSubject( $origns ); - $tns = MWNamespace::getTalk( $origns ); - - $parts = explode( '/', $title->getText() ); - if ( count( $parts ) > 1 && ( $this->mIsTalk || count( $parts ) == 2 ) ) { - // If title contains a '/', treat as a wikilog article title. - $this->mWikilogName = array_shift( $parts ); - $this->mItemName = array_shift( $parts ); - $this->mTrailing = implode( '/', $parts ); - $rawtitle = "{$this->mWikilogName}/{$this->mItemName}"; - $this->mWikilogTitle = Title::makeTitle( $ns, $this->mWikilogName ); - $this->mItemTitle = Title::makeTitle( $ns, $rawtitle ); - $this->mItemTalkTitle = Title::makeTitle( $tns, $rawtitle ); - } elseif ( count( $parts ) == 1 ) { - // Title doesn't contain a '/', treat as a wikilog name. - $this->mWikilogName = $title->getText(); - $this->mWikilogTitle = Title::makeTitle( $ns, $this->mWikilogName ); - $this->mItemName = null; - $this->mItemTitle = null; - $this->mItemTalkTitle = null; - } + $this->mIsTalk = MWNamespace::isTalk( $origns ); + $ns = MWNamespace::getSubject( $origns ); + $tns = MWNamespace::getTalk( $origns ); + + $parts = explode( '/', $title->getText() ); + if ( count( $parts ) > 1 && (strlen($parts[1]) > 2 || count( $parts ) > 2)) { + // If title contains a '/', treat as a wikilog article title. + $this->mWikilogName = array_shift( $parts ); + $this->mItemName = array_shift( $parts ); + $this->mTrailing = implode( '/', $parts ); + $rawtitle = "{$this->mWikilogName}/{$this->mItemName}"; + $this->mWikilogTitle = Title::makeTitle( $ns, $this->mWikilogName ); + $this->mItemTitle = Title::makeTitle( $ns, $rawtitle ); + $this->mItemTalkTitle = Title::makeTitle( $tns, $rawtitle ); + } else { + // Title doesn't contain a '/', treat as a wikilog name. + $this->mWikilogName = $title->getText(); + $this->mWikilogTitle = Title::makeTitle( $ns, $this->mWikilogName ); + $this->mItemName = null; + $this->mItemTitle = null; + $this->mItemTalkTitle = null; + } } function isMain() { return $this->mItemTitle === null; } diff --git a/WikilogBloggerImport.php b/WikilogBloggerImport.php index ef33225..d634807 100644 --- a/WikilogBloggerImport.php +++ b/WikilogBloggerImport.php @@ -88,8 +88,8 @@ static function parse_blogger_xml($str, $params = array()) 'wlc_post' => $params['ns_blog'].':'.$refs[$ref]['title'], 'wlc_user_text' => $user, 'wlc_status' => 'OK', - 'wlc_timestamp' => gmdate("YmdHis", $ts), - 'wlc_updated' => gmdate("YmdHis", $ts), + 'wlc_timestamp' => $dbw->timestamp($ts), + 'wlc_updated' => $dbw->timestamp($ts), 'wlc_comment_page' => "$ns:$title", ); $comment_ai++; @@ -99,7 +99,7 @@ static function parse_blogger_xml($str, $params = array()) /* Add page row */ $out['page'][] = array( 'title' => "$ns:$title", - 'timestamp' => gmdate("YmdHis", $ts), + 'timestamp' => $dbw->timestamp($ts), 'author' => $user, 'text' => $content, ); diff --git a/WikilogCalendar.php b/WikilogCalendar.php index 6661fd9..d21db8d 100644 --- a/WikilogCalendar.php +++ b/WikilogCalendar.php @@ -71,9 +71,9 @@ static function makePagingLinks($months, $pager) $prev = array('dir' => 'next', 'offset' => ($prevmonth = $months[count($months)-1]).'01000000', 'limit' => $urlLimit ); $html = '

'; if ($prev) - $html .= $pager->makeLink(wfMsg('wikilog-calendar-prev', self::monthName(self::prevMonth($prevmonth))), $prev, 'prev'); + $html .= $pager->makeLink(wfMessage('wikilog-calendar-prev', self::monthName(self::prevMonth($prevmonth)))->text(), $prev, 'prev'); if ($next) - $html .= $pager->makeLink(wfMsg('wikilog-calendar-next', self::monthName($nextmonth)), $next, 'next'); + $html .= $pager->makeLink(wfMessage('wikilog-calendar-next', self::monthName($nextmonth))->text(), $next, 'next'); $html .= '

'; return $html; } @@ -185,10 +185,10 @@ static function sidebarCalendar($pager) 'month' => substr($date, 4, 2), 'day' => substr($date, 6, 2), )), - 'title' => wfMsgExt('wikilog-calendar-archive-link-title', 'parseinline', + 'title' => wfMessage('wikilog-calendar-archive-link-title', $sp->getPrefixedText(), date('Y-m-d', wfTimestamp(TS_UNIX, $row->wlp_pubdate)) - ), + )->parse(), ); } } diff --git a/WikilogComment.php b/WikilogComment.php index e8db1e1..450bfc6 100644 --- a/WikilogComment.php +++ b/WikilogComment.php @@ -141,7 +141,7 @@ public function getParentObj() { if ( !$this->mParentObj ) { $this->mParentObj = WikilogComment::newFromID( $this->mParent ); } - if ( !$this->mParentObj || !$this->mParentObj->mThread ) { + if ( !$this->mParentObj || $this->mParentObj->mThread === '' ) { throw new MWException( 'Invalid parent history.' ); } return $this->mParentObj; @@ -211,7 +211,7 @@ public function saveComment() { $dbw->update( 'wikilog_comments', $data, array( 'wlc_id' => $this->mID ), __METHOD__ ); } else { - $cid = $dbw->nextSequenceValue( 'wikilog_comments_wlc_id' ); + $cid = $dbw->nextSequenceValue( 'wikilog_comments_wlc_id_seq' ); $data = array( 'wlc_id' => $cid ) + $data; $dbw->insert( 'wikilog_comments', $data, __METHOD__ ); $this->mID = $dbw->insertId(); @@ -307,11 +307,7 @@ public function sendCommentEmails() { '', '', ); - // $to_ids = array( userid => TRUE|FALSE (can unsubscribe | cannot) ) - $to_ids = array(); if ( $this->mParentObj ) { - // Always notify parent comment author - $to_ids[ $this->mParentObj->mUserID ] = false; $args[4] = $this->mParentObj->mCommentTitle->getPrefixedText(); $args[5] = $this->mParentObj->mUserText; } @@ -321,55 +317,77 @@ public function sendCommentEmails() { $parent = Title::makeTitle( $this->mSubject->getNamespace(), $this->mSubject->getBaseText() ); $wlid = $parent->getArticleId(); $s = $dbr->tableName( 'wikilog_subscriptions' ); + $u = $dbr->tableName( 'user' ); $up = $dbr->tableName( 'user_properties' ); $w = $dbr->tableName( 'watchlist' ); + // $to_ids = array( => array( 'email' => , 'can_unsubscribe' => ), ... ) + $to_ids = array(); + $email_auth = "AND user_email!='' AND user_email_authenticated IS NOT NULL"; $result = $dbr->query( // Notify users subscribed to this post - "SELECT ws_user, 1 FROM $s WHERE ws_page=$id AND ws_yes=1". - " UNION ALL". + "SELECT ws_user user_id, user_email, 1 can_unsubscribe FROM $s". + " INNER JOIN $u ON user_id=ws_user $email_auth". + " WHERE ws_page=$id AND ws_yes=1". // Notify users subscribed to the blog and not unsubscribed from this post - " SELECT s1.ws_user, 1 FROM $s s1 LEFT JOIN $s s2 ON s2.ws_user=s1.ws_user". - " AND s2.ws_page=$id AND s2.ws_yes=0 WHERE s1.ws_page=$wlid AND s1.ws_yes=1 AND s2.ws_user IS NULL". " UNION ALL". + " SELECT s1.ws_user user_id, user_email, 1 can_unsubscribe FROM $s s1". + " INNER JOIN $u ON user_id=s1.ws_user $email_auth". + " LEFT JOIN $s s2 ON s2.ws_user=s1.ws_user AND s2.ws_page=$id AND s2.ws_yes=0". + " WHERE s1.ws_page=$wlid AND s1.ws_yes=1 AND s2.ws_user IS NULL". // Notify users subscribed to talk via watchlist and not unsubscribed from the post - " SELECT wl_user, 1 FROM $w LEFT JOIN $s s2 ON s2.ws_user=wl_user". - " AND s2.ws_page=$id AND s2.ws_yes=0 WHERE wl_namespace=".MWNamespace::getTalk( $this->mSubject->getNamespace() ). - " AND wl_title=".$dbr->addQuotes( $this->mSubject->getDBkey() )." AND s2.ws_user IS NULL". " UNION ALL". + " SELECT wl_user user_id, user_email, 1 can_unsubscribe FROM $w". + " INNER JOIN $u ON user_id=wl_user $email_auth". + " LEFT JOIN $s s2 ON s2.ws_user=wl_user AND s2.ws_page=$id AND s2.ws_yes=0". + " WHERE wl_namespace=".MWNamespace::getTalk( $this->mSubject->getNamespace() ). + " AND wl_title=".$dbr->addQuotes( $this->mSubject->getDBkey() )." AND s2.ws_user IS NULL". // Notify users subscribed to all blogs via user preference // and not unsubscribed from this post and not unsubscribed from this blog, // but only for comments to Wikilog posts (not to the ordinary pages) // FIXME: untie from Wikilog ( !empty( $wgWikilogNamespaces ) && in_array( $this->mSubject->getNamespace(), $wgWikilogNamespaces ) - ? " SELECT up_user, 1 FROM $up". + ? " UNION ALL". + " SELECT up_user user_id, user_email, 1 can_unsubscribe FROM $up". + " INNER JOIN $u ON user_id=up_user $email_auth". " LEFT JOIN $s ON ws_user=up_user AND ws_page IN ($id, $wlid) AND ws_yes=0". - " WHERE up_property='wl-subscribetoall' AND up_value='1' AND ws_user IS NULL". - " UNION ALL" + " WHERE up_property='wl-subscribetoall' AND up_value='1' AND ws_user IS NULL" : '' ). // Always notify post author(s), and they cannot unsubscribe (0 means that) - " SELECT wla_author, 0 FROM ".$dbr->tableName( 'wikilog_authors' )." WHERE wla_page=$id", + " UNION ALL". + " SELECT wla_author user_id, user_email, 0 can_unsubscribe FROM ".$dbr->tableName( 'wikilog_authors' ). + " INNER JOIN $u ON user_id=wla_author $email_auth". + " WHERE wla_page=$id". + // Always notify parent comment author + ( !$this->mParentObj ? "" : + " UNION ALL SELECT user_id, user_email, 0 can_unsubscribe FROM $u". + " WHERE user_id=".$this->mParentObj->mUserID." $email_auth" ). + // Always notify users about comments to their talk page + ( $this->mSubject->getNamespace() != NS_USER ? "" : + " UNION ALL SELECT user_id, user_email, 0 can_unsubscribe FROM $u". + " WHERE user_name=".$dbr->addQuotes( $this->mSubject->getText() )." $email_auth" ), __METHOD__ ); - while ( $u = $dbr->fetchRow( $result ) ) { - if ( !array_key_exists( $u[0], $to_ids ) ) { - $to_ids[ $u[0] ] = $u[1]; + foreach ( $result as $u ) { + // "Cannot unsubscribe" overrides "can unsubscribe" + if ( !isset( $to_ids[$u->user_id] ) || !$u->can_unsubscribe ) { + $to_ids[$u->user_id] = $u; } } $dbr->freeResult( $result ); // Build message subject, body and unsubscribe link $saveExpUrls = WikilogParser::expandLocalUrls(); $popt = new ParserOptions( User::newFromId( $this->mUserID ) ); - $subject = $wgParser->parse( wfMsgNoTrans( 'wikilog-comment-email-subject', $args ), + $subject = $wgParser->parse( wfMessage( 'wikilog-comment-email-subject', $args )->plain(), $this->mSubject, $popt, false, false ); $subject = 'Re: ' . strip_tags( $subject->getText() ); - $body = $wgParser->parse( wfMsgNoTrans( 'wikilog-comment-email-body', $args), + $body = $wgParser->parse( wfMessage( 'wikilog-comment-email-body', $args )->plain(), $this->mSubject, $popt, true, false ); $body = $body->getText(); WikilogParser::expandLocalUrls( $saveExpUrls ); // Unsubscribe link is appended to e-mails of users that can unsubscribe global $wgServer, $wgScript; - $unsubscribe = wfMsgNoTrans( + $unsubscribe = wfMessage( 'wikilog-comment-email-unsubscribe', $this->mSubject->getSubpageText(), $wgServer.$wgScript.'?'.http_build_query( array( @@ -378,21 +396,19 @@ public function sendCommentEmails() { 'wlActionSubscribe' => 1, 'wl-subscribe' => 0, ) ) - ); + )->plain(); // Build e-mail lists (with unsubscribe link, without unsubscribe link) + // TODO: Send e-mail to user in his own language? $to_with = array(); $to_without = array(); - foreach ( $to_ids as $id => $can_unsubcribe ) { + foreach ( $to_ids as $id => $to ) { // Do not send user his own comments if ( $id != $this->mUserID ) { - $email = User::newFromId( $id )->getEmail(); - if ( $email ) { - $email = new MailAddress( $email ); - if ( $can_unsubcribe ) { - $to_with[] = $email; - } else { - $to_without[] = $email; - } + $email = new MailAddress( $to->user_email ); + if ( $to->can_unsubscribe ) { + $to_with[] = $email; + } else { + $to_without[] = $email; } } } @@ -407,10 +423,10 @@ public function sendCommentEmails() { // Send e-mails using $wgPasswordSender as from address $from = new MailAddress( $wgPasswordSender, 'Wikilog' ); if ( $to_with ) { - UserMailer::send( $to_with, $from, $subject, $body . $unsubscribe, null, 'text/html; charset=UTF-8', $headers ); + WikilogUtils::sendHtmlMail( $to_with, $from, $subject, $body . $unsubscribe, $headers ); } if ( $to_without ) { - UserMailer::send( $to_without, $from, $subject, $body, null, 'text/html; charset=UTF-8', $headers ); + WikilogUtils::sendHtmlMail( $to_without, $from, $subject, $body, $headers ); } } @@ -500,9 +516,9 @@ public function getAutoSummary() { global $wgContLang; $user = $this->mUserID ? $this->mUserText : $this->mAnonName; $summ = $wgContLang->truncate( str_replace( "\n", ' ', $this->mText ), - max( 0, 200 - strlen( wfMsgForContent( 'wikilog-comment-autosumm' ) ) ), + max( 0, 200 - strlen( wfMessage( 'wikilog-comment-autosumm' )->inContentLanguage()->text() ) ), '...' ); - return wfMsgForContent( 'wikilog-comment-autosumm', $user, $summ ); + return wfMessage( 'wikilog-comment-autosumm', $user, $summ )->inContentLanguage()->text(); } /** @@ -793,7 +809,7 @@ class WikilogCommentFormatter */ public function __construct( $skin = false, $allowReplies = false ) { global $wgUser; - $this->mSkin = $skin ? $skin : $wgUser->getSkin(); + $this->mSkin = $skin ? $skin : RequestContext::getMain()->getSkin(); $this->mAllowReplies = $allowReplies; $this->mAllowModeration = $wgUser->isAllowed( 'wl-moderation' ); } @@ -844,7 +860,7 @@ public function formatComment( $comment, $highlight = false ) { if ( !$comment->isVisible() && !$this->mAllowModeration ) { # Placeholder. - $status = wfMsg( "wikilog-comment-{$hidden}" ); + $status = wfMessage( "wikilog-comment-{$hidden}" )->text(); $html = WikilogUtils::wrapDiv( 'wl-comment-placeholder', $status ); } else { # The comment. @@ -899,10 +915,10 @@ public function formatCommentHeader( $comment, $params ) { if ( !$comment->isVisible() ) { # If comment is not visible to non-moderators, make note of it. $hidden = WikilogComment::$statusMap[ $comment->mStatus ]; - $status = WikilogUtils::wrapDiv( 'wl-comment-status', wfMsg( "wikilog-comment-{$hidden}" ) ); + $status = WikilogUtils::wrapDiv( 'wl-comment-status', wfMessage( "wikilog-comment-{$hidden}" )->text() ); } - $header = wfMsgExt( 'wikilog-comment-header', array( 'content', 'parsemag', 'replaceafter' ), $params ); + $header = wfMessage( 'wikilog-comment-header' )->inContentLanguage()->rawParams( $params )->text(); if ( $header ) { $header = WikilogUtils::wrapDiv( 'wl-comment-header', $header ); } @@ -920,7 +936,7 @@ public function formatCommentHeader( $comment, $params ) { * @return HTML-formatted comment footer. */ public function formatCommentFooter( $comment, $params ) { - $footer = wfMsgExt( 'wikilog-comment-footer', array( 'content', 'parsemag', 'replaceafter' ), $params ); + $footer = wfMessage( 'wikilog-comment-footer' )->inContentLanguage()->rawParams( $params )->text(); if ( $footer ) { return WikilogUtils::wrapDiv( 'wl-comment-footer', $footer ); } else { @@ -939,7 +955,7 @@ public function formatCommentFooter( $comment, $params ) { * 300+ languages suported by MediaWiki. * * Parameters should be HTML-formated. They are substituded using - * 'replaceafter' parameter to wfMsgExt(). + * Message::rawParams(). * * @param $comment Comment. * @return Array with message parameters. @@ -952,11 +968,11 @@ public function getCommentMsgParams( $comment ) { $authorFmt = WikilogUtils::authorSig( $comment->mUserText, true ); } else { $authorPlain = htmlspecialchars( $comment->mAnonName ); - $authorFmt = wfMsgForContent( 'wikilog-comment-anonsig', + $authorFmt = wfMessage( 'wikilog-comment-anonsig', Xml::wrapClass( $this->mSkin->userLink( $comment->mUserID, $comment->mUserText ), 'wl-comment-author' ), $this->mSkin->userTalkLink( $comment->mUserID, $comment->mUserText ), htmlspecialchars( $comment->mAnonName ) - ); + )->inContentLanguage()->text(); } list( $date, $time, $tz ) = WikilogUtils::getLocalDateTime( $comment->mTimestamp ); @@ -965,9 +981,9 @@ public function getCommentMsgParams( $comment ) { $extra = array(); if ( $this->mShowItem ) { # Display item title. - $extra[] = wfMsgForContent( 'wikilog-comment-note-item', - $this->mSkin->link( $comment->mSubject, $comment->mSubject->getSubpageText() ) - ); + $extra[] = wfMessage( 'wikilog-comment-note-item', + Linker::link( $comment->mSubject, $comment->mSubject->getSubpageText() ) + )->inContentLanguage()->text(); } if ( $comment->mID && $comment->mCommentTitle && $comment->mCommentTitle->exists() ) @@ -975,9 +991,9 @@ public function getCommentMsgParams( $comment ) { if ( $comment->mUpdated != $comment->mTimestamp ) { # Comment was edited. list( $updDate, $updTime, $updTz ) = WikilogUtils::getLocalDateTime( $comment->mUpdated ); - $extra[] = $this->mSkin->link( $comment->mCommentTitle, - wfMsgForContent( 'wikilog-comment-note-edited', $updDate, $updTime, $updTz ), - array( 'title' => wfMsg( 'wikilog-comment-history' ) ), + $extra[] = Linker::link( $comment->mCommentTitle, + wfMessage( 'wikilog-comment-note-edited', $updDate, $updTime, $updTz )->inContentLanguage()->text(), + array( 'title' => wfMessage( 'wikilog-comment-history' )->text() ), array( 'action' => 'history' ), 'known' ); } @@ -986,17 +1002,20 @@ public function getCommentMsgParams( $comment ) { $comment->mParent && $comment->isVisible() && $comment->getParentObj()->mCommentTitle->exists() ) { - $link = $this->mSkin->link( $comment->getParentObj()->mCommentTitle, - wfMsg( 'wikilog-ptswitsher-comment-label' ), - array( 'title' => wfMsg( 'wikilog-ptswitsher-to-comment' ) ), + $parent = $comment->getParentObj(); + $link = Linker::link( $parent->mCommentTitle, + wfMessage( 'wikilog-ptswitcher-comment-label' )->text(), + array( 'title' => wfMessage( 'wikilog-ptswitcher-to-comment' )->text() ), array( 'section' => false ), 'known' ); - list( $updDate, $updTime, $updTz ) = WikilogUtils::getLocalDateTime( $comment->mUpdated ); - $extra[] = wfMsg( 'wikilog-ptswitsher-to-parent', array( - $link, $authorFmt, - $updDate, $updTime, $updTz - ) ); + list( $pd, $pt, $ptz ) = WikilogUtils::getLocalDateTime( $parent->mUpdated ); + if ( $parent->mUserID ) { + $parentSig = WikilogUtils::authorSig( $parent->mUserText, true ); + } else { + $parentSig = wfMessage( 'wikilog-comment-anonsig', '', '', htmlspecialchars( $parent->mAnonName ) )->inContentLanguage()->text(); + } + $extra[] = wfMessage( 'wikilog-ptswitcher-to-parent', array( $link, $parentSig, $pd, $pt, $ptz ) )->text(); } if ( $extra ) { @@ -1032,12 +1051,12 @@ protected function getCommentPermalink( $comment, $date, $time, $tz ) { } else { $title = $comment->mCommentTitle; } - return $this->mSkin->link( $title, - wfMsgExt( 'wikilog-comment-permalink', array( 'parseinline' ), $date, $time, $tz, $comment->mVisited ? 1 : NULL ), - array( 'title' => wfMsg( 'permalink' ) ) + return Linker::link( $title, + wfMessage( 'wikilog-comment-permalink', $date, $time, $tz, $comment->mVisited ? 1 : NULL )->parse(), + array( 'title' => wfMessage( 'permalink' )->text() ) ); } else { - return wfMsg( 'wikilog-comment-permalink', $date, $time, $tz ); + return wfMessage( 'wikilog-comment-permalink', $date, $time, $tz )->text(); } } @@ -1057,17 +1076,18 @@ protected function getCommentToolLinks( $comment ) { if ( $this->mAllowReplies && $comment->isVisible() ) { $tools['reply'] = Xml::tags( 'a', array( - 'title' => wfMsg( 'wikilog-reply-to-comment' ), - 'href' => $wgRequest->appendQueryValue( 'wlParent', $comment->mID ) + 'title' => wfMessage( 'wikilog-reply-to-comment' )->text(), + 'href' => $wgRequest->appendQueryValue( 'wlParent', $comment->mID ), + 'onclick' => 'return wlReplyTo('.$comment->mID.')', ), - wfMsg( 'wikilog-reply-lc' ) + wfMessage( 'wikilog-reply-lc' )->text() ); } if ( $this->mAllowModeration && $comment->mStatus == WikilogComment::S_PENDING ) { - $token = $wgUser->editToken(); - $tools['approve'] = $this->mSkin->link( $comment->mCommentTitle, - wfMsg( 'wikilog-approve-lc' ), - array( 'title' => wfMsg( 'wikilog-comment-approve' ) ), + $token = $wgUser->getEditToken(); + $tools['approve'] = Linker::link( $comment->mCommentTitle, + wfMessage( 'wikilog-approve-lc' )->text(), + array( 'title' => wfMessage( 'wikilog-comment-approve' )->text() ), array( 'action' => 'wikilog', 'wlActionCommentApprove' => 'approve', @@ -1075,9 +1095,9 @@ protected function getCommentToolLinks( $comment ) { ), 'known' ); - $tools['reject'] = $this->mSkin->link( $comment->mCommentTitle, - wfMsg( 'wikilog-reject-lc' ), - array( 'title' => wfMsg( 'wikilog-comment-reject' ) ), + $tools['reject'] = Linker::link( $comment->mCommentTitle, + wfMessage( 'wikilog-reject-lc' )->text(), + array( 'title' => wfMessage( 'wikilog-comment-reject' )->text() ), array( 'action' => 'wikilog', 'wlActionCommentApprove' => 'reject', @@ -1086,25 +1106,25 @@ protected function getCommentToolLinks( $comment ) { 'known' ); } - $tools['page'] = $this->mSkin->link( $comment->mCommentTitle, - wfMsg( 'wikilog-page-lc' ), - array( 'title' => wfMsg( 'wikilog-comment-page' ) ), + $tools['page'] = Linker::link( $comment->mCommentTitle, + wfMessage( 'wikilog-page-lc' )->text(), + array( 'title' => wfMessage( 'wikilog-comment-page' )->text() ), array( 'section' => false ), 'known' ); // TODO: batch checking of page restrictions if ( $comment->mCommentTitle->quickUserCan( 'edit' ) ) { - $tools['edit'] = $this->mSkin->link( $comment->mCommentTitle, - wfMsg( 'wikilog-edit-lc' ), - array( 'title' => wfMsg( 'wikilog-comment-edit' ) ), + $tools['edit'] = Linker::link( $comment->mCommentTitle, + wfMessage( 'wikilog-edit-lc' )->text(), + array( 'title' => wfMessage( 'wikilog-comment-edit' )->text() ), array( 'action' => 'edit', 'section' => false ), 'known' ); } if ( $comment->mCommentTitle->quickUserCan( 'delete' ) ) { - $tools['delete'] = $this->mSkin->link( $comment->mCommentTitle, - wfMsg( 'wikilog-delete-lc' ), - array( 'title' => wfMsg( 'wikilog-comment-delete' ) ), + $tools['delete'] = Linker::link( $comment->mCommentTitle, + wfMessage( 'wikilog-delete-lc' )->text(), + array( 'title' => wfMessage( 'wikilog-comment-delete' )->text() ), array( 'action' => 'delete' ), 'known' ); diff --git a/WikilogCommentPager.php b/WikilogCommentPager.php index 8383812..c106e26 100644 --- a/WikilogCommentPager.php +++ b/WikilogCommentPager.php @@ -131,7 +131,7 @@ function getEndBody() { } function getEmptyBody() { - return WikilogUtils::wrapDiv( 'wl-empty', wfMsgExt( 'wikilog-pager-empty', array( 'parsemag' ) ) ); + return WikilogUtils::wrapDiv( 'wl-empty', wfMessage( 'wikilog-pager-empty' )->text() ); } function getNavigationBar() { @@ -313,7 +313,7 @@ function getBody() { $doReply = $this->mReplyTrigger && $comment->mID == $this->mReplyTrigger; $html .= $this->mFormatter->formatComment( $comment, $doReply ); if ( $doReply && is_callable( $this->mReplyCallback ) ) { - if ( ( $res = call_user_func( $this->mReplyCallback, $comment ) ) ) { + if ( ( $res = call_user_func( $this->mReplyCallback, $comment, true ) ) ) { $html .= WikilogUtils::wrapDiv( 'wl-indent', $res ); } } diff --git a/WikilogCommentPagerSwitcher.php b/WikilogCommentPagerSwitcher.php index 8eb7d2e..9c28787 100644 --- a/WikilogCommentPagerSwitcher.php +++ b/WikilogCommentPagerSwitcher.php @@ -4,12 +4,12 @@ die(); class WikilogCommentPagerSwitcher { - public static function getType( Title $subject ) { + public static function getType( $subject ) { $info = static::getInfo( $subject ); return $info ? $info['type'] : 'thread'; } - public static function checkType( Title $subject ) { + public static function checkType( $subject ) { if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { $info = static::getInfo( $subject ); $msince = strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ); @@ -19,7 +19,7 @@ public static function checkType( Title $subject ) { } } - public static function setType( Title $subject, $type ) { + public static function setType( $subject, $type ) { global $wgRequest; $id = $subject ? $subject->getArticleId() : 0; $types = $wgRequest->getSessionData( 'wikilog-comments-pager-type' ); @@ -34,7 +34,7 @@ public static function setType( Title $subject, $type ) { unset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ); } - protected static function getInfo( Title $subject ) { + protected static function getInfo( $subject ) { global $wgRequest; $id = $subject ? $subject->getArticleId() : 0; $types = $wgRequest->getSessionData( 'wikilog-comments-pager-type' ); diff --git a/WikilogCommentsPage.php b/WikilogCommentsPage.php index 6933d1e..69c1977 100644 --- a/WikilogCommentsPage.php +++ b/WikilogCommentsPage.php @@ -40,9 +40,13 @@ function __construct() { parent::__construct( 'WikilogComments' ); } + protected function getGroupName() { + return 'changes'; + } + function execute( $par ) { global $wgTitle; - $page = new WikilogCommentsPage( $wgTitle ); + $page = WikilogCommentsPage::createInstance( $wgTitle ); $page->view(); } @@ -51,7 +55,7 @@ function execute( $par ) { * and also the name that will be listed in Special:Specialpages. */ public function getDescription() { - return wfMsg( 'wikilog-title-comments-all' ); + return wfMessage( 'wikilog-title-comments-all' )->text(); } } @@ -79,7 +83,7 @@ class WikilogCommentsPage public $mSingleComment; ///< Used when viewing a single comment. - var $mWikilogInfo, $mSubject; + var $mWikilogInfo, $mSubject, $mSubjectUser; var $mCommentPagerType; /** @@ -87,59 +91,81 @@ class WikilogCommentsPage * * @param $title Title of the page. */ - function __construct( Title $title ) { + static function createInstance( Title $title ) { global $wgUser, $wgRequest; - parent::__construct( $title ); + $subject = $subjectUser = $singleComment = $switchSubject = NULL; + if ( $title->getNamespace() != NS_SPECIAL ) { + if ( !Wikilog::nsHasComments( $title ) ) { + return NULL; + } + // We do not print anything from subject page, but its ID is required to correctly post comments + // So disable permission check for the time + if ( defined( 'HACL_HALOACL_VERSION' ) ) { + $hacl = haclfDisableTitlePatch(); + } + $subject = $title->getSubjectPage(); + if ( defined( 'HACL_HALOACL_VERSION' ) ) { + haclfRestoreTitlePatch( $hacl ); + } + $singleComment = WikilogComment::newFromPageID( $title->getArticleId() ); + if ( $singleComment ) { + $switchSubject = $subject; + $subject = $singleComment->mSubject; + } + // Our DB structure does not allow to post comments for non-existing subject pages, + // so we either disallow such comments or auto-create the subject page. + // We only auto-create non-existing User:* pages for registered users, + // and add them to the corresponding user's watchlist. + if ( $subject->getNamespace() == NS_USER ) { + $subjectUser = User::newFromName( $subject->getText() ); + if ( !$subjectUser || !$subjectUser->getId() ) { + return NULL; + } + } elseif ( !$subject->exists() ) { + return NULL; + } + } + + $self = new WikilogCommentsPage( $title ); if ( class_exists( 'Wikilog' ) ) { - $this->mWikilogInfo = Wikilog::getWikilogInfo( $title ); + $self->mWikilogInfo = Wikilog::getWikilogInfo( $title ); } - # Check if user can post. - $this->mUserCanPost = !$wgUser->isBlocked() && ( $wgUser->isAllowed( 'wl-postcomment' ) || + // Check if user can post. + $self->mUserCanPost = !$wgUser->isBlocked() && ( $wgUser->isAllowed( 'wl-postcomment' ) || ( $wgUser->isAllowed( 'edit' ) && $wgUser->isAllowed( 'createtalk' ) ) ); - $this->mUserCanModerate = $wgUser->isAllowed( 'wl-moderation' ); + $self->mUserCanModerate = $wgUser->isAllowed( 'wl-moderation' ); - # Prepare the skin and the comment formatter. - $this->mSkin = $wgUser->getSkin(); - $this->mFormatter = new WikilogCommentFormatter( $this->mSkin, $this->mUserCanPost ); + // Prepare the skin and the comment formatter. + $self->mSkin = RequestContext::getMain()->getSkin(); + $self->mFormatter = new WikilogCommentFormatter( $self->mSkin, $self->mUserCanPost ); - # Form options. - $this->mFormOptions = new FormOptions(); - $this->mFormOptions->add( 'wlAnonName', '' ); - $this->mFormOptions->add( 'wlComment', '' ); - $this->mFormOptions->fetchValuesFromRequest( $wgRequest, + // Form options. + $self->mFormOptions = new FormOptions(); + $self->mFormOptions->add( 'wlAnonName', '' ); + $self->mFormOptions->add( 'wlComment', '' ); + $self->mFormOptions->fetchValuesFromRequest( $wgRequest, array( 'wlAnonName', 'wlComment' ) ); - # This flags if we are viewing a single comment (subpage). - $this->mSingleComment = - WikilogComment::newFromPageID( $this->getID() ); - - # We do not print any data from subject page, but its ID is required to correctly post comments - # So disable permission check for the time - if ( defined( 'HACL_HALOACL_VERSION' ) ) { - $hacl = haclfDisableTitlePatch(); - } - $this->mSubject = $title->getNamespace() != NS_SPECIAL ? $title->getSubjectPage() : NULL; - if ( defined( 'HACL_HALOACL_VERSION' ) ) { - haclfRestoreTitlePatch( $hacl ); - } + // This flags if we are viewing a single comment (subpage). + $self->mSingleComment = $singleComment; + $self->mSubject = $subject; + $self->mSubjectUser = $subjectUser; // Set WikilogCommentPager type if ( $wgRequest->getVal( 'comment_pager_type' ) !== null ) { - WikilogCommentPagerSwitcher::setType( $this->mSubject, $wgRequest->getVal( 'comment_pager_type' ) ); + WikilogCommentPagerSwitcher::setType( $switchSubject, $wgRequest->getVal( 'comment_pager_type' ) ); } + // Refresh cache after switching - WikilogCommentPagerSwitcher::checkType( $this->mSubject ); - $this->mCommentPagerType = WikilogCommentPagerSwitcher::getType( $this->mSubject ); - if ( $this->mCommentPagerType === 'list' ) { - $this->mFormatter->mWithParent = true; + WikilogCommentPagerSwitcher::checkType( $switchSubject ); + $self->mCommentPagerType = WikilogCommentPagerSwitcher::getType( $switchSubject ); + if ( $self->mCommentPagerType === 'list' ) { + $self->mFormatter->mWithParent = true; } - // Set single comment subject AFTER selecting comment pager type! - if ( $this->mSingleComment ) { - $this->mSubject = $this->mSingleComment->mSubject; - } + return $self; } /** @@ -229,17 +255,17 @@ public function view() { if ( $this->mSubject ) { $name = $this->mSubject->getPrefixedText(); - $wgOut->setPageTitle( wfMsg( 'wikilog-title-comments', $name ) ); + $wgOut->setPageTitle( wfMessage( 'wikilog-title-comments', $name )->text() ); } else { $name = ''; - $wgOut->setPageTitle( wfMsg( 'wikilog-title-comments-all' ) ); + $wgOut->setPageTitle( wfMessage( 'wikilog-title-comments-all' )->text() ); } } # Add a backlink to the original article. if ( $name !== '' ) { - $link = $this->mSkin->link( $this->mSubject, Sanitizer::escapeHtmlAllowEntities( $name ) ); - $wgOut->setSubtitle( wfMsg( 'wikilog-backlink', $link ) ); + $link = Linker::link( $this->mSubject, Sanitizer::escapeHtmlAllowEntities( $name ) ); + $wgOut->setSubtitle( wfMessage( 'wikilog-backlink', $link )->text() ); } # Retrieve comments (or replies) from database and display them. @@ -254,7 +280,7 @@ public function view() { * them in threads. */ protected function viewComments( WikilogCommentQuery $query ) { - global $wgOut, $wgRequest, $wgUser, $wgRequest; + global $wgOut, $wgRequest, $wgUser, $wgRequest, $wgScript; # Prepare query and pager objects. $replyTo = $wgRequest->getInt( 'wlParent' ); @@ -279,12 +305,8 @@ protected function viewComments( WikilogCommentQuery $query ) { # Switch pager $type = $this->mCommentPagerType; - $msg = wfMsg( $type != 'thread' ? - 'wikilog-ptswitcher-thread' : 'wikilog-ptswitcher-list' - ); - $url = $wgRequest->appendQueryValue( 'comment_pager_type', - $type != 'thread' ? 'thread' : 'list' - ); + $msg = wfMessage( $type != 'thread' ? 'wikilog-ptswitcher-thread' : 'wikilog-ptswitcher-list' )->text(); + $url = $wgScript . '?' . http_build_query( [ 'comment_pager_type' => $type != 'thread' ? 'thread' : 'list' ] + $_GET ); $link = Xml::tags( 'a', array( 'href' => $url ), $msg ); $pagerType = Xml::tags( 'span', array( 'style' => 'float: right; font-size: 70%' ), '[ '. $link . ' ]' @@ -292,7 +314,7 @@ protected function viewComments( WikilogCommentQuery $query ) { # Comments/Replies header. $header = Xml::tags( 'h2', array( 'id' => 'wl-comments-header' ), - $pagerType . wfMsgExt( $headerMsg, array( 'parseinline' ) ) + $pagerType . wfMessage( $headerMsg )->parse() ); $wgOut->addHtml( $header ); @@ -326,8 +348,8 @@ public function wikilog() { // Subscribe/unsubscribe to new comments $id = $this->mSubject->getArticleId(); $s = $this->subscribe( $id ) ? 'yes' : 'no'; - $wgOut->setPageTitle( wfMsg( "wikilog-subscribed-title-$s" ) ); - $wgOut->addWikiText( wfMsgNoTrans( "wikilog-subscribed-text-$s", $this->mSubject->getPrefixedText() ) ); + $wgOut->setPageTitle( wfMessage( "wikilog-subscribed-title-$s" )->text() ); + $wgOut->addWikiText( wfMessage( "wikilog-subscribed-text-$s", $this->mSubject->getPrefixedText() )->plain() ); return; } @@ -414,13 +436,18 @@ public function getSubscribeLink() { $msg = $one ? 'wikilog-do-unsubscribe-all' : 'wikilog-do-subscribe-all'; } elseif ( !$this->mSingleComment ) { $dbr = wfGetDB( DB_SLAVE ); + // Is it the user talk page? If yes, he can't unsubscribe. + if ( $this->mSubject->getNamespace() == NS_USER && + $this->mSubject->getText() == $wgUser->getName() ) { + return wfMessage( 'wikilog-subscribed-usertalk' )->plain(); + } // Is the user author? If yes, he can't unsubscribe. $isa = $dbr->selectField( 'wikilog_authors', '1', array( 'wla_page' => $subjId, 'wla_author' => $wgUser->getId(), ), __METHOD__ ); if ( $isa ) { - return wfMsgNoTrans( 'wikilog-subscribed-as-author' ); + return wfMessage( 'wikilog-subscribed-as-author' )->plain(); } // Is the user subscribed globally to comments to ALL Wikilog posts? // This can be overridden by individual subscription settings (below) @@ -445,14 +472,15 @@ public function getSubscribeLink() { } else { return ''; } - return wfMsgNoTrans( $msg, + return wfMessage( $msg, // FIXME use title->getFullUrl( ??? ) $wgScript.'?'.http_build_query( array( 'title' => $this->getTitle()->getPrefixedText(), 'action' => 'wikilog', 'wlActionSubscribe' => 1, 'wl-subscribe' => $one ? 0 : 1, - ) ) ); + ) ) + )->plain(); } /** @@ -478,8 +506,8 @@ public function isSubscribed( $itemid ) { * @param $parent If provided, generates a "post reply" form to reply to * the given comment. */ - public function getPostCommentForm( $parent = null ) { - global $wgUser, $wgTitle, $wgScript, $wgRequest; + public function getPostCommentForm( $parent = null, $inline_reply = false ) { + global $wgUser, $wgTitle, $wgRequest; global $wgWikilogModerateAnonymous; if ( $this->includeSubpageComments() && !$parent || !$this->mSubject ) { @@ -494,36 +522,36 @@ public function getPostCommentForm( $parent = null ) { if ( $comment && $comment->mParent == $pid ) { $check = $this->validateComment( $comment ); if ( $check ) { - $preview = Xml::wrapClass( wfMsg( $check ), 'mw-warning', 'div' ); + $preview = Xml::wrapClass( wfMessage( $check )->text(), 'mw-warning', 'div' ); } else { $preview = $this->mFormatter->formatComment( $this->mPostedComment ); } - $header = wfMsgHtml( 'wikilog-form-preview' ); + $header = wfMessage( 'wikilog-form-preview' )->escaped(); $preview = "{$header}{$preview}
"; } + $targetTitle = $parent ? $parent->mCommentTitle : $this->getTitle(); $form = - Html::hidden( 'title', ( $parent ? $parent->mCommentTitle : $this->getTitle()->getPrefixedText() ) ) . Html::hidden( 'action', 'wikilog' ) . - Html::hidden( 'wpEditToken', $wgUser->editToken() ) . + Html::hidden( 'wpEditToken', $wgUser->getEditToken() ) . ( $parent ? Html::hidden( 'wlParent', $parent->mID ) : '' ); $fields = array(); if ( $wgUser->isLoggedIn() ) { $fields[] = array( - wfMsg( 'wikilog-form-name' ), + wfMessage( 'wikilog-form-name' )->text(), $this->mSkin->userLink( $wgUser->getId(), $wgUser->getName() ) ); } else { $loginTitle = SpecialPage::getTitleFor( 'Userlogin' ); - $loginLink = $this->mSkin->link( $loginTitle, - wfMsgHtml( 'loginreqlink' ), array(), + $loginLink = Linker::link( $loginTitle, + wfMessage( 'loginreqlink' )->escaped(), array(), array( 'returnto' => $wgTitle->getPrefixedUrl() ) ); - $message = wfMsg( 'wikilog-posting-anonymously', $loginLink ); + $message = wfMessage( 'wikilog-posting-anonymously', $loginLink )->text(); $fields[] = array( - Xml::label( wfMsg( 'wikilog-form-name' ), 'wl-name' ), + Xml::label( wfMessage( 'wikilog-form-name' )->text(), 'wl-name' ), Xml::input( 'wlAnonName', 25, $opts->consumeValue( 'wlAnonName' ), array( 'id' => 'wl-name', 'maxlength' => 255 ) ) . "

{$message}

" @@ -532,7 +560,7 @@ public function getPostCommentForm( $parent = null ) { $autofocus = $parent ? array( 'autofocus' => 'autofocus' ) : array(); $fields[] = array( - Xml::label( wfMsg( 'wikilog-form-comment' ), 'wl-comment' ), + Xml::label( wfMessage( 'wikilog-form-comment' )->text(), 'wl-comment' ), Xml::textarea( 'wlComment', $opts->consumeValue( 'wlComment' ), 40, 5, array( 'id' => 'wl-comment' ) + $autofocus ) ); @@ -542,7 +570,7 @@ public function getPostCommentForm( $parent = null ) { } if ( $wgWikilogModerateAnonymous && $wgUser->isAnon() ) { - $fields[] = array( '', wfMsg( 'wikilog-anonymous-moderated' ) ); + $fields[] = array( '', wfMessage( 'wikilog-anonymous-moderated' )->text() ); } if ( $wgUser->getID() && $this->mSubject ) { @@ -551,14 +579,14 @@ public function getPostCommentForm( $parent = null ) { if ( $subscribed === NULL ) { $subscribed = true; } - $subscribe_html = '   ' . Xml::checkLabel( wfMsg( 'wikilog-subscribe' ), 'wl-subscribe', 'wl-subscribe', $subscribed ); + $subscribe_html = '   ' . Xml::checkLabel( wfMessage( 'wikilog-subscribe' )->text(), 'wl-subscribe', 'wl-subscribe', $subscribed ); } else { $subscribe_html = ''; } $fields[] = array( '', - Xml::submitbutton( wfMsg( 'wikilog-submit' ), array( 'name' => 'wlActionCommentSubmit' ) ) . WL_NBSP . - Xml::submitbutton( wfMsg( 'wikilog-preview' ), array( 'name' => 'wlActionCommentPreview' ) ) . + Xml::submitbutton( wfMessage( 'wikilog-submit' )->text(), array( 'name' => 'wlActionCommentSubmit' ) ) . WL_NBSP . + Xml::submitbutton( wfMessage( 'wikilog-preview' )->text(), array( 'name' => 'wlActionCommentPreview' ) ) . $subscribe_html ); @@ -569,13 +597,13 @@ public function getPostCommentForm( $parent = null ) { } $form = Xml::tags( 'form', array( - 'action' => "{$wgScript}#wl-comment-form", - 'method' => 'post' + 'action' => $targetTitle->getLocalUrl()."#wl-comment-form", + 'method' => 'post', ), $form ); $msgid = ( $parent ? 'wikilog-post-reply' : 'wikilog-post-comment' ); - return Xml::fieldset( wfMsg( $msgid ), $preview . $form, - array( 'id' => 'wl-comment-form' ) ) . "\n"; + return Xml::fieldset( wfMessage( $msgid )->text(), $preview . $form, + array( 'id' => ( $inline_reply ? 'wl-comment-form-reply' : 'wl-comment-form' ) ) ) . "\n"; } protected function setCommentApproval( $comment, $approval ) { @@ -596,17 +624,14 @@ protected function setCommentApproval( $comment, $approval ) { $log->addEntry( 'c-approv', $title, '' ); $wgOut->redirect( $this->mTalkTitle->getFullUrl() ); } elseif ( $approval == 'reject' ) { - $reason = wfMsgExt( 'wikilog-log-cmt-rejdel', - array( 'content', 'parsemag' ), - $comment->mUserText - ); + $reason = wfMessage( 'wikilog-log-cmt-rejdel', $comment->mUserText )->inContentLanguage()->text(); $id = $title->getArticleID( Title::GAID_FOR_UPDATE ); if ( $this->doDeleteArticle( $reason, false, $id ) ) { $comment->deleteComment(); $log->addEntry( 'c-reject', $title, '' ); $wgOut->redirect( $this->mTalkTitle->getFullUrl() ); } else { - $wgOut->showFatalError( wfMsgExt( 'cannotdelete', array( 'parse' ) ) ); + $wgOut->showFatalError( wfMessage( 'cannotdelete' )->parse() ); $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) ); LogEventsList::showLogExtract( $wgOut, 'delete', $this->mTitle->getPrefixedText() ); } @@ -627,7 +652,7 @@ protected function subscribe( $page_id ) { 'ws_page' => $page_id, 'ws_user' => $wgUser->getID(), 'ws_yes' => $subscribe, - 'ws_date' => wfTimestamp( TS_MW ), + 'ws_date' => $dbw->timestamp(), ), __METHOD__ ); return $subscribe; } @@ -668,14 +693,30 @@ protected function postComment( WikilogComment &$comment ) { $comment->mStatus = WikilogComment::S_PENDING; } - if ( !$this->exists() ) { - # Initialize a blank talk page. - $user = User::newFromName( wfMsgForContent( 'wikilog-auto' ), false ); - $this->doEdit( - wfMsgForContent( 'wikilog-newtalk-text' ), - wfMsgForContent( 'wikilog-newtalk-summary' ), - EDIT_NEW | EDIT_SUPPRESS_RC, false, $user - ); + if ( !$this->mSubject->getArticleID() || !$this->exists() ) { + $user = User::newFromName( wfMessage( 'wikilog-auto' )->inContentLanguage()->text(), false ); + if ( !$this->exists() ) { + // Initialize a blank talk page. + $this->doEdit( + wfMessage( 'wikilog-newtalk-text' )->inContentLanguage()->text(), + wfMessage( 'wikilog-newtalk-summary' )->inContentLanguage()->text(), + EDIT_NEW | EDIT_SUPPRESS_RC, false, $user + ); + } + if ( !$this->mSubject->getArticleID() ) { + // Initialize a blank subject page. + $page = new WikiPage( $this->mSubject ); + $page->doEdit( + wfMessage( 'wikilog-newtalk-text' )->inContentLanguage()->text(), + wfMessage( 'wikilog-newtalk-summary' )->inContentLanguage()->text(), + EDIT_NEW | EDIT_SUPPRESS_RC, false, $user + ); + if ( $this->mSubjectUser ) { + // Add newly created user talk page to user's watchlist + $w = WatchedItem::fromUserTitle( $this->mSubjectUser, $this->mSubject ); + $w->addWatch(); + } + } } $comment->saveComment(); diff --git a/WikilogDefaultSettings.php b/WikilogDefaultSettings.php index ee81f7e..2cf72f8 100644 --- a/WikilogDefaultSettings.php +++ b/WikilogDefaultSettings.php @@ -52,12 +52,6 @@ */ $wgWikilogStylePath = false; -/** - * Wikilog style version, incremented when $wgWikilogStylePath/wikilog.css - * is changed. - */ -$wgWikilogStyleVersion = 6; - /* *** Presentation options *** */ /** diff --git a/WikilogFeed.php b/WikilogFeed.php index 2bdd1a2..5e402e7 100644 --- a/WikilogFeed.php +++ b/WikilogFeed.php @@ -87,7 +87,7 @@ public function __construct( Title $title, $format, WikilogQuery $query, $limit $this->mIndexField = $this->getIndexField(); # Retrieve copyright notice. - $skin = $wgUser->getSkin(); + $skin = RequestContext::getMain()->getSkin(); $saveExpUrls = WikilogParser::expandLocalUrls(); $this->mCopyright = $skin->getCopyright( 'normal' ); WikilogParser::expandLocalUrls( $saveExpUrls ); @@ -360,16 +360,16 @@ public function getFeedObject() { */ protected function getSiteFeedObject() { global $wgContLanguageCode, $wgWikilogFeedClasses, $wgFavicon, $wgLogo; - $title = wfMsgForContent( 'wikilog-specialwikilog-title' ); - $subtitle = wfMsgExt( 'wikilog-feed-description', array( 'parse', 'content' ) ); + $title = wfMessage( 'wikilog-specialwikilog-title' )->inContentLanguage()->text(); + $subtitle = wfMessage( 'wikilog-feed-description' )->inContentLanguage()->parse(); $updated = $this->mDb->selectField( 'wikilog_wikilogs', 'MAX(wlw_updated)', false, __METHOD__ ); - if ( !$updated ) $updated = wfTimestampNow(); + $updated = $updated ? wfTimestamp( TS_MW, $updated ) : wfTimestampNow(); $feed = new $wgWikilogFeedClasses[$this->mFormat]( $this->mTitle->getFullUrl(), - wfMsgForContent( 'wikilog-feed-title', $title, $wgContLanguageCode ), + wfMessage( 'wikilog-feed-title', $title, $wgContLanguageCode )->inContentLanguage()->text(), $updated, $this->mTitle->getFullUrl() ); @@ -394,8 +394,8 @@ protected function getNamespaceFeedObject( $ns ) { global $wgWikilogFeedClasses, $wgFavicon, $wgLogo; global $wgContLang, $wgContLanguageCode; - $title = wfMsgForContent( 'wikilog-feed-ns-title', $wgContLang->getFormattedNsText( $ns ) ); - $subtitle = wfMsgExt( 'wikilog-feed-description', array( 'parse', 'content' ) ); + $title = wfMessage( 'wikilog-feed-ns-title', $wgContLang->getFormattedNsText( $ns ) )->inContentLanguage()->text(); + $subtitle = wfMessage( 'wikilog-feed-description' )->inContentLanguage()->parse(); $updated = $this->mDb->selectField( array( 'wikilog_wikilogs', 'page' ), @@ -406,11 +406,11 @@ protected function getNamespaceFeedObject( $ns ) { ), __METHOD__ ); - if ( !$updated ) $updated = wfTimestampNow(); + $updated = $updated ? wfTimestamp( TS_MW, $updated ) : wfTimestampNow(); $feed = new $wgWikilogFeedClasses[$this->mFormat]( $this->mTitle->getFullUrl(), - wfMsgForContent( 'wikilog-feed-title', $title, $wgContLanguageCode ), + wfMessage( 'wikilog-feed-title', $title, $wgContLanguageCode )->inContentLanguage()->text(), $updated, $this->mTitle->getFullUrl() ); @@ -454,7 +454,7 @@ protected function getWikilogFeedObject( $wikilogTitle, $forsource = false ) { : null; $feed = new $wgWikilogFeedClasses[$this->mFormat]( $wikilogTitle->getFullUrl(), - wfMsgForContent( 'wikilog-feed-title', $title, $wgContLanguageCode ), + wfMessage( 'wikilog-feed-title', $title, $wgContLanguageCode )->inContentLanguage()->text(), $row->wlw_updated, $wikilogTitle->getFullUrl(), $self ); if ( $row->wlw_subtitle ) { @@ -593,7 +593,7 @@ public function getCacheKeys() { } else { $id = 'site'; } - $ft = 'show:' . $this->mQuery->getPubStatus() . + $ft = 'q:' . md5( serialize( $this->mQuery ) ) . ':limit:' . $this->mLimit; return array( wfMemcKey( 'wikilog', $this->mFormat, $id, 'timestamp' ), @@ -670,21 +670,19 @@ public function getIndexField() { public function getFeedObject() { global $wgContLanguageCode, $wgWikilogFeedClasses, $wgFavicon, $wgLogo; - $feedtitle = wfMsgForContent( 'wikilog-feed-title', - wfMsgForContent( + $feedtitle = wfMessage( 'wikilog-feed-title', + wfMessage( $this->mSubject ? 'wikilog-title-comments' : 'wikilog-title-comments-all', $this->mSubject ? $this->mSubject->getSubpageText() : '' - ), + )->inContentLanguage()->text(), $wgContLanguageCode - ); - $subtitle = wfMsgExt( 'wikilog-comment-feed-description', array( 'parse', 'content' ) ); + )->inContentLanguage()->text(); + $subtitle = wfMessage( 'wikilog-comment-feed-description' )->inContentLanguage()->parse(); $res = $this->mQuery->select( $this->mDb, array(), 'MAX(wlc_updated) u' ); $updated = $res->fetchObject(); $updated = $updated->u; - if ( !$updated ) { - $updated = wfTimestampNow(); - } + $updated = $updated ? wfTimestamp( TS_MW, $updated ) : wfTimestampNow(); $url = $this->mTitle->getFullUrl(); $feed = new $wgWikilogFeedClasses[$this->mFormat]( @@ -716,13 +714,13 @@ function formatFeedEntry( $row ) { if ( $comment->mUserID ) { $usertext = $comment->mUserText; } else { - $usertext = wfMsgForContent( 'wikilog-comment-anonsig', + $usertext = wfMessage( 'wikilog-comment-anonsig', $comment->mUserText, ''/*talk*/, $comment->mAnonName - ); + )->inContentLanguage()->text(); } - $title = wfMsgForContent( 'wikilog-comment-feed-title'.( $this->mSingleItem ? '1' : '2' ), + $title = wfMessage( 'wikilog-comment-feed-title'.( $this->mSingleItem ? '1' : '2' ), $comment->mID, $usertext, $comment->mSubject->getSubpageText() - ); + )->inContentLanguage()->text(); # Create new syndication entry. $entry = new WlSyndicationEntry( diff --git a/WikilogHooks.php b/WikilogHooks.php index 6b44e59..10852be 100644 --- a/WikilogHooks.php +++ b/WikilogHooks.php @@ -38,11 +38,10 @@ class WikilogHooks * ArticleEditUpdates hook handler function. * Performs post-edit updates if article is a wikilog article or a comment. */ - static function ArticleEditUpdates( &$article, &$editInfo, $changed ) { + static function ArticleEditUpdates( $article, &$editInfo, $changed ) { $title = $article->getTitle(); $wi = Wikilog::getWikilogInfo( $title ); - $title = $article->getTitle(); if ( $title->isTalkPage() ) { if ( Wikilog::nsHasComments( $title ) && !isset( WikilogComment::$saveInProgress[$title->getPrefixedText()] ) ) { @@ -63,7 +62,9 @@ static function ArticleEditUpdates( &$article, &$editInfo, $changed ) { } # Do nothing if not a wikilog article. - if ( !$wi ) return true; + if ( !$wi ) { + return true; + } if ( $wi->isItem() ) { # ::WikilogItemPage:: @@ -72,6 +73,12 @@ static function ArticleEditUpdates( &$article, &$editInfo, $changed ) { $item = new WikilogItem(); } + if ( !$wi->getTitle()->getArticleID() ) { + // If the parent (blog) page is not created yet - create it automatically + $page = new WikiPage( $wi->getTitle() ); + $page->doEdit( wfMessage( 'wikilog-newtalk-text' )->text(), wfMessage( 'wikilog-newtalk-summary' )->text(), EDIT_FORCE_BOT ); + } + $item->mName = $wi->getItemName(); $item->mTitle = $wi->getItemTitle(); $item->mParentName = $wi->getName(); @@ -106,6 +113,8 @@ static function ArticleEditUpdates( &$article, &$editInfo, $changed ) { if ( isset( $editInfo->output->mExtWikilog ) ) { $output = $editInfo->output->mExtWikilog; + $wasPublished = $item->mPublish; + # Update entry in wikilog_posts table. # Entries in wikilog_authors and wikilog_tags are updated # during LinksUpdate process. @@ -115,6 +124,15 @@ static function ArticleEditUpdates( &$article, &$editInfo, $changed ) { $item->mAuthors = $output->mAuthors; $item->mTags = $output->mTags; $item->saveData(); + + if ( !$wasPublished && $item->mPublish ) { + global $wgEnableEmail; + // Send email notifications about the new post + if ( $wgEnableEmail ) { + SpecialWikilogSubscriptions::sendEmails( $article, + !empty( $editInfo->pstContent ) ? $editInfo->pstContent->getNativeData() : $article->getText() ); + } + } } else { # Remove entry from tables. Entries in wikilog_authors and # wikilog_tags are removed during LinksUpdate process. @@ -218,27 +236,43 @@ static function ArticleDelete( $article, $user, $reason, &$error ) { /** * ArticleSave hook handler function. + * * Add article signature if user selected "sign and publish" option in - * EditPage. + * EditPage, or if there is ~~~~ in the text. */ - static function ArticleSave( &$article, &$user, &$text, &$summary, - $minor, $watch, $sectionanchor, &$flags ) - { - # $article->mExtWikilog piggybacked from WikilogHooks::EditPageAttemptSave(). - if ( isset( $article->mExtWikilog ) && $article->mExtWikilog['signpub'] ) { - $t = WikilogUtils::getPublishParameters(); - $txtDate = $t['date']; - $txtUser = $t['user']; - $text = rtrim( $text ) . "\n{{wl-publish: {$txtDate} | {$txtUser} }}\n"; - } - return true; - } + static function ArticleSave( &$wikiPage, &$user, &$content, &$summary, + $isMinor, $isWatch, $section, &$flags, &$status ) + { + $t = WikilogUtils::getPublishParameters(); + $txtDate = $t['date']; + $txtUser = $t['user']; + $text = ContentHandler::getContentText( $content ); + + // $article->mExtWikilog piggybacked from WikilogHooks::EditPageAttemptSave(). + if ( isset( $wikiPage->mExtWikilog ) && $wikiPage->mExtWikilog['signpub'] ) { + $text = rtrim( $text ) . "\n{{wl-publish: $txtDate | $txtUser }}\n"; + } elseif ( Wikilog::getWikilogInfo( $wikiPage->getTitle() ) ) { + global $wgParser; + $sigs = array( + '/\n?(--)?~~~~~\n?/m' => "\n{{wl-publish: $txtDate }}\n", + '/\n?(--)?~~~~\n?/m' => "\n{{wl-publish: $txtDate | $txtUser }}\n", + '/\n?(--)?~~~\n?/m' => "\n{{wl-author: $txtUser }}\n" + ); + $wgParser->startExternalParse( $wikiPage->getTitle(), ParserOptions::newFromUser( $user ), Parser::OT_WIKI ); + $text = $wgParser->replaceVariables( $text ); + $text = preg_replace( array_keys( $sigs ), array_values( $sigs ), $text ); + $text = $wgParser->mStripState->unstripBoth( $text ); + } + $content = new WikitextContent( $text ); + return true; + } + /** * TitleMoveComplete hook handler function. * Handles moving articles to and from wikilog namespaces. */ - static function TitleMoveComplete( &$oldtitle, &$newtitle, &$user, $pageid, $redirid ) { + static function TitleMoveComplete( $oldtitle, $newtitle, $user, $pageid, $redirid ) { global $wgWikilogNamespaces; # Check if it was or is now in a wikilog namespace. @@ -290,22 +324,22 @@ static function TitleMoveComplete( &$oldtitle, &$newtitle, &$user, $pageid, $red * EditPage::showEditForm:fields hook handler function. * Adds wikilog article options to edit pages. */ - static function EditPageEditFormFields( &$editpage, &$output ) { + static function EditPageEditFormFields( $editpage, $output ) { $wi = Wikilog::getWikilogInfo( $editpage->mTitle ); if ( $wi && $wi->isItem() && !$wi->isTalk() ) { global $wgUser, $wgWikilogSignAndPublishDefault; $fields = array(); $item = WikilogItem::newFromInfo( $wi ); - # [x] Sign and publish this wikilog article. + // [x] Sign and publish this wikilog article. if ( !$item || !$item->getIsPublished() ) { if ( isset( $editpage->wlSignpub ) ) { $checked = $editpage->wlSignpub; } else { $checked = !$item && $wgWikilogSignAndPublishDefault; } - $label = wfMsgExt( 'wikilog-edit-signpub', array( 'parseinline' ) ); - $tooltip = wfMsgExt( 'wikilog-edit-signpub-tooltip', array( 'parseinline' ) ); + $label = wfMessage( 'wikilog-edit-signpub' )->parse(); + $tooltip = wfMessage( 'wikilog-edit-signpub-tooltip' )->parse(); $fields['wlSignpub'] = Xml::check( 'wlSignpub', $checked, array( 'id' => 'wl-signpub', @@ -319,7 +353,7 @@ static function EditPageEditFormFields( &$editpage, &$output ) { $fields = implode( $fields, "\n" ); $html = Xml::fieldset( - wfMsgExt( 'wikilog-edit-fieldset-legend', array( 'parseinline' ) ), + wfMessage( 'wikilog-edit-fieldset-legend' )->parse(), $fields ); $editpage->editFormTextAfterWarn .= $html; @@ -348,9 +382,9 @@ static function EditPageAttemptSave( $editpage ) { 'signpub' => $editpage->wlSignpub ); - # Piggyback options into article object. Will be retrieved later - # in 'ArticleEditUpdates' hook. - $editpage->mArticle->mExtWikilog = $options; + // Piggyback options into article object. Will be retrieved later + // in 'ArticleEditUpdates' hook. + $editpage->mArticle->getPage()->mExtWikilog = $options; return true; } @@ -361,8 +395,7 @@ static function EditPageAttemptSave( $editpage ) { * @todo Add support for PostgreSQL and SQLite databases. */ static function ExtensionSchemaUpdates( $updater ) { - global $wikilogRegenThreads; - $wikilogRegenThreads = new WikilogRegenThreads(); + register_shutdown_function( 'WikilogRegenThreads::execute' ); $dir = dirname( __FILE__ ) . '/'; @@ -394,6 +427,9 @@ static function ExtensionSchemaUpdates( $updater ) { $updater->addExtensionUpdate( array( 'addIndex', "wikilog_comments", "wlc_timestamp", "{$dir}archives/patch-comments-indexes.sql", true ) ); $updater->addExtensionUpdate( array( 'WikilogHooks::createForeignKeys' ) ); + } elseif ( $updater->getDB()->getType() == 'postgres' ) { + $updater->addExtensionUpdate( array( 'addTable', "wikilog_wikilogs", + "{$dir}wikilog-tables.pg.sql", true ) ); } else { // TODO: PostgreSQL, SQLite, etc... print "\n" . @@ -498,10 +534,10 @@ static function EnhancedChangesListGroupBy( &$rc, &$title, &$secureName ) { } class WikilogRegenThreads { - function __destruct() { + static function execute() { $dbw = wfGetDB( DB_MASTER ); if ( !$dbw->selectField( 'wikilog_comments', 'wlc_id', - array( 'wlc_thread=LPAD(wlc_id, 6, \'0\')' ), __METHOD__ ) ) { + array( 'wlc_thread=LPAD(CONCAT(wlc_id, \'\'), 6, \'0\')' ), __METHOD__ ) ) { return; } print "Regenerating wlc_thread for Wikilog comments\n"; diff --git a/WikilogItem.php b/WikilogItem.php index 81592df..19ea00b 100644 --- a/WikilogItem.php +++ b/WikilogItem.php @@ -170,15 +170,12 @@ public function getMsgParams( $extended = false, $pout = null ) { if ( $pout !== null ) { $categories = $pout->getCategoryLinks(); if ( count( $categories ) > 0 ) { - $categoriesFmt = wfMsgExt( 'wikilog-summary-categories', - array( 'content', 'parsemag' ), + $categoriesFmt = wfMessage( 'wikilog-summary-categories', count( $categories ), WikilogUtils::categoryList( $categories ) - ); + )->inContentLanguage()->text(); } else { - $categoriesFmt = wfMsgExt( 'wikilog-summary-uncategorized', - array( 'content', 'parsemag' ) - ); + $categoriesFmt = wfMessage( 'wikilog-summary-uncategorized' )->inContentLanguage()->text(); } } if ( $wgWikilogEnableTags ) { @@ -239,6 +236,18 @@ public static function newFromRow( $row ) { if ( !is_array( $item->mTags ) ) { $item->mTags = array(); } + + $langCode = $item->mTitle->getPageLanguage()->getCode(); + if ( strlen($langCode) != 0 && strcmp($langCode, "en") !== 0 ) { + $dbr = wfGetDB( DB_SLAVE ); + $displayTitle = $dbr->selectField( + 'page_props', + 'pp_value', + array( 'pp_propname' => 'displaytitle', 'pp_page' => $item->mID ), + __METHOD__ + ); + $item->mName = $displayTitle; + } return $item; } diff --git a/WikilogItemPage.php b/WikilogItemPage.php index a20011d..3cf44a8 100644 --- a/WikilogItemPage.php +++ b/WikilogItemPage.php @@ -77,7 +77,7 @@ public function view() { global $wgOut, $wgUser, $wgContLang, $wgFeed, $wgWikilogFeedClasses, $wgWikilogCommentsOnItemPage; # Get skin - $skin = $wgUser->getSkin(); + $skin = $this->getContext()->getSkin(); if ( $this->mItem ) { $params = $this->mItem->getMsgParams( true ); @@ -88,10 +88,7 @@ public function view() { } # Item page header. - $headerTxt = wfMsgExt( 'wikilog-entry-header', - array( 'parse', 'content' ), - $params - ); + $headerTxt = wfMessage( 'wikilog-entry-header', $params )->inContentLanguage()->parse(); if ( !empty( $headerTxt ) ) { $wgOut->addHtml( WikilogUtils::wrapDiv( 'wl-entry-header', $headerTxt ) ); } @@ -100,14 +97,12 @@ public function view() { parent::view(); # Update last visit - if ( $this->mItem ) + if ( $this->mItem ) { WikilogUtils::updateLastVisit( $this->mItem->getID() ); + } # Item page footer. - $footerTxt = wfMsgExt( 'wikilog-entry-footer', - array( 'parse', 'content' ), - $params - ); + $footerTxt = wfMessage( 'wikilog-entry-footer', $params )->inContentLanguage()->parse(); if ( !empty( $footerTxt ) ) { $wgOut->addHtml( WikilogUtils::wrapDiv( 'wl-entry-footer', $footerTxt ) ); } @@ -119,11 +114,10 @@ public function view() { $wgOut->addLink( array( 'rel' => 'alternate', 'type' => "application/{$format}+xml", - 'title' => wfMsgExt( + 'title' => wfMessage( "page-{$format}-feed", - array( 'content', 'parsemag' ), $this->mItem->mParentTitle->getPrefixedText() - ), + )->inContentLanguage()->text(), 'href' => $this->mItem->mParentTitle->getLocalUrl( "feed={$format}" ) ) ); } @@ -131,25 +125,23 @@ public function view() { if ( $wgWikilogCommentsOnItemPage ) { $talk = $this->getTitle()->getTalkPage(); - $wi = Wikilog::getWikilogInfo( $talk ); - $comments = new WikilogCommentsPage( $talk, $wi ); - $comments->outputComments(); + $comments = WikilogCommentsPage::createInstance( $talk ); + if ( $comments ) { + $comments->outputComments(); + } } # Override page title. # NOTE (MW1.16+): Must come after parent::view(). - $fullPageTitle = wfMsg( 'wikilog-title-item-full', - $this->mItem->mName, - $this->mItem->mParentTitle->getPrefixedText() - ); + $fullPageTitle = wfMessage( 'wikilog-title-item-full', + $this->mItem->mName, + $this->mItem->mParentTitle->getPrefixedText() + )->text(); $wgOut->setPageTitle( Sanitizer::escapeHtmlAllowEntities( $this->mItem->mName ) ); - $wgOut->setHTMLTitle( wfMsg( 'pagetitle', $fullPageTitle ) ); + $wgOut->setHTMLTitle( wfMessage( 'pagetitle', $fullPageTitle )->text() ); # Set page subtitle - $subtitleTxt = wfMsgExt( 'wikilog-entry-sub', - array( 'parsemag', 'content' ), - $params - ); + $subtitleTxt = wfMessage( 'wikilog-entry-sub', $params )->inContentLanguage()->text(); if ( !empty( $subtitleTxt ) ) { $wgOut->setSubtitle( $wgOut->parse( $subtitleTxt ) ); } else { @@ -160,14 +152,6 @@ public function view() { parent::view(); } } - - /** - * Compatibility with MediaWiki 1.17. - * @todo Remove this in Wl1.3. - */ - public function preSaveTransform( $text ) { - return $this->newPage( $this->getTitle() )->preSaveTransform( $text ); - } } /** @@ -184,40 +168,4 @@ public static function newFromID( $id, $from = 'fromdb' ) { $t = Title::newFromID( $id ); return $t == null ? null : new self( $t ); } - - /** - * Override for preSaveTransform. Enables quick post publish by signing - * the article using the standard --~~~~ marker. This causes the signature - * marker to be replaced by a {{wl-publish:...}} parser function call, - * that is then saved to the database and causes the post to be published. - */ - public function preSaveTransform( $text, User $user = null, ParserOptions $popts = null ) { - global $wgParser, $wgUser; - $user = is_null( $user ) ? $wgUser : $user; - - if ( $popts === null ) { - $popts = ParserOptions::newFromUser( $user ); - } - - $t = WikilogUtils::getPublishParameters(); - $date_txt = $t['date']; - $user_txt = $t['user']; - - $sigs = array( - '/\n?(--)?~~~~~\n?/m' => "\n{{wl-publish: {$date_txt} }}\n", - '/\n?(--)?~~~~\n?/m' => "\n{{wl-publish: {$date_txt} | {$user_txt} }}\n", - '/\n?(--)?~~~\n?/m' => "\n{{wl-author: {$user_txt} }}\n" - ); - - if ( !StubObject::isRealObject( $wgParser ) ) { - $wgParser->_unstub(); - } - $wgParser->startExternalParse( $this->mTitle, $popts, Parser::OT_WIKI ); - - $text = $wgParser->replaceVariables( $text ); - $text = preg_replace( array_keys( $sigs ), array_values( $sigs ), $text ); - $text = $wgParser->mStripState->unstripBoth( $text ); - - return parent::preSaveTransform( $text, $user, $popts ); - } } diff --git a/WikilogItemPager.php b/WikilogItemPager.php index 5093088..db0a18b 100644 --- a/WikilogItemPager.php +++ b/WikilogItemPager.php @@ -153,7 +153,7 @@ function getEndBody() { } function getEmptyBody() { - return '
' . wfMsgExt( 'wikilog-pager-empty', array( 'parsemag' ) ) . "
"; + return '
' . wfMessage( 'wikilog-pager-empty' )->text() . "
"; } function getNavigationBar() { @@ -175,6 +175,12 @@ function formatRow( $row ) { list( $article, $parserOutput ) = WikilogUtils::parsedArticle( $item->mTitle ); list( $summary, $content ) = WikilogUtils::splitSummaryContent( $parserOutput ); + // FIXME: Do not use global output, pass it from somewhere + global $wgOut; + $wgOut->addModules( $parserOutput->getModules() ); + $wgOut->addModuleStyles( $parserOutput->getModuleStyles() ); + $wgOut->addModuleScripts( $parserOutput->getModuleScripts() ); + # Retrieve the common header and footer parameters. $params = $item->getMsgParams( $wgWikilogExtSummaries, $parserOutput ); @@ -182,27 +188,27 @@ function formatRow( $row ) { # edit link (if user can edit the article). $titleText = Sanitizer::escapeHtmlAllowEntities( $item->mName ); if ( !$item->getIsPublished() ) - $titleText .= wfMsgForContent( 'wikilog-draft-title-mark' ); - $heading = $skin->link( $item->mTitle, $titleText, array(), array(), + $titleText .= wfMessage( 'wikilog-draft-title-mark' )->inContentLanguage()->text(); + $heading = Linker::link( $item->mTitle, $titleText, array(), array(), array( 'known', 'noclasses' ) ); - if ( $this->mShowEditLink && $item->mTitle->quickUserCan( 'edit' ) ) { - $heading = $this->doEditLink( $item->mTitle, $item->mName ) . $heading; - } + //if ( $this->mShowEditLink && $item->mTitle->quickUserCan( 'edit' ) ) { + // $heading = $this->doEditLink( $item->mTitle, $item->mName ) . $heading; + //} $heading = Xml::tags( 'h2', null, $heading ); # Sumary entry header. $key = $this->mQuery->isSingleWikilog() ? 'wikilog-summary-header-single' : 'wikilog-summary-header'; - $msg = wfMsgExt( $key, array( 'content', 'parsemag' ), $params ); + $msg = wfMessage( $key, $params )->inContentLanguage()->text(); if ( !empty( $msg ) ) { $header = WikilogUtils::wrapDiv( 'wl-summary-header', $this->parse( $msg ) ); } # Summary entry text. if ( $summary ) { - $more = $this->parse( wfMsgForContentNoTrans( 'wikilog-summary-more', $params ) ); + $more = $this->parse( wfMessage( 'wikilog-summary-more', $params )->inContentLanguage()->plain() ); $summary = WikilogUtils::wrapDiv( 'wl-summary', $summary . $more ); } else { $summary = WikilogUtils::wrapDiv( 'wl-summary', $content ); @@ -215,7 +221,7 @@ function formatRow( $row ) { $key = $this->mQuery->isSingleWikilog() ? 'wikilog-summary-footer-single' : 'wikilog-summary-footer'; - $msg = wfMsgExt( $key, array( 'content', 'parsemag' ), $params ); + $msg = wfMessage( $key, $params )->inContentLanguage()->text(); if ( !empty( $msg ) ) { $footer = WikilogUtils::wrapDiv( 'wl-summary-footer', $this->parse( $msg ) ); } @@ -263,15 +269,15 @@ private function doEditLink( $title, $tooltip = null ) { $skin = $this->getSkin(); $attribs = array(); if ( !is_null( $tooltip ) ) { - $attribs['title'] = wfMsg( 'wikilog-edit-hint', $tooltip ); + $attribs['title'] = wfMessage( 'wikilog-edit-hint', $tooltip )->text(); } - $link = $skin->link( $title, wfMsg( 'wikilog-edit-lc' ), + $link = Linker::link( $title, wfMessage( 'wikilog-edit-lc' )->text(), $attribs, array( 'action' => 'edit' ), array( 'noclasses', 'known' ) ); - $result = wfMsgHtml ( 'editsection-brackets', $link ); + $result = wfMessage( 'editsection-brackets', $link )->escaped(); $result = "$result"; wfRunHooks( 'DoEditSectionLink', array( $skin, $title, "", $tooltip, &$result ) ); @@ -359,7 +365,7 @@ function formatRow( $row ) { # Some general data. $authors = WikilogUtils::authorList( array_keys( $item->mAuthors ) ); - $tags = implode( wfMsgForContent( 'comma-separator' ), array_keys( $item->mTags ) ); + $tags = implode( wfMessage( 'comma-separator' )->inContentLanguage()->text(), array_keys( $item->mTags ) ); $comments = WikilogUtils::getCommentsWikiText( $item ); $divclass = 'wl-entry' . ( $item->getIsPublished() ? '' : ' wl-draft' ); @@ -593,16 +599,16 @@ function formatValue( $name, $value ) { case 'wlw_title': $page = $this->mCurrentItem->mParentTitle; $text = Sanitizer::escapeHtmlAllowEntities( $this->mCurrentItem->mParentName ); - return $this->getSkin()->link( $page, $text, array(), array(), + return Linker::link( $page, $text, array(), array(), array( 'known', 'noclasses' ) ); case 'wlp_title': $page = $this->mCurrentItem->mTitle; $text = Sanitizer::escapeHtmlAllowEntities( $this->mCurrentItem->mName ); - $s = $this->getSkin()->link( $page, $text, array(), array(), + $s = Linker::link( $page, $text, array(), array(), array( 'known', 'noclasses' ) ); if ( !$this->mCurrentRow->wlp_publish ) { - $draft = wfMsg( 'wikilog-draft-title-mark' ); + $draft = wfMessage( 'wikilog-draft-title-mark' )->text(); $s = Xml::wrapClass( "$s $draft", 'wl-draft-inline' ); } return $s; @@ -613,7 +619,7 @@ function formatValue( $name, $value ) { if ( !empty( $this->mCurrentRow->wlp_unread_comments ) ) { $text .= ' (' . $this->mCurrentRow->wlp_unread_comments . ')'; } - return $this->getSkin()->link( $page, $text, array(), array(), + return Linker::link( $page, $text, array(), array(), array( 'known', 'noclasses' ) ); case '_wl_actions': @@ -641,22 +647,22 @@ function getFieldNames() { $fields = array(); - $fields['wlp_pubdate'] = wfMsgHtml( 'wikilog-published' ); - // $fields['wlp_updated'] = wfMsgHtml( 'wikilog-updated' ); - $fields['wlp_authors'] = wfMsgHtml( 'wikilog-authors' ); + $fields['wlp_pubdate'] = wfMessage( 'wikilog-published' )->escaped(); + // $fields['wlp_updated'] = wfMessage( 'wikilog-updated' )->escaped(); + $fields['wlp_authors'] = wfMessage( 'wikilog-authors' )->escaped(); if ( !$this->mQuery->isSingleWikilog() ) - $fields['wlw_title'] = wfMsgHtml( 'wikilog-wikilog' ); + $fields['wlw_title'] = wfMessage( 'wikilog-wikilog' )->escaped(); - $fields['wlp_title'] = wfMsgHtml( 'wikilog-title' ); + $fields['wlp_title'] = wfMessage( 'wikilog-title' )->escaped(); if ( $wgWikilogEnableComments ) - $fields['wti_num_comments'] = wfMsgHtml( 'wikilog-comments' ); + $fields['wti_num_comments'] = wfMessage( 'wikilog-comments' )->escaped(); if ( empty( $this->noActions ) ) - $fields['_wl_actions'] = wfMsgHtml( 'wikilog-actions' ); + $fields['_wl_actions'] = wfMessage( 'wikilog-actions' )->escaped(); - $fields['wti_talk_updated'] = wfMsgHtml( 'wikilog-talk-updated' ); + $fields['wti_talk_updated'] = wfMessage( 'wikilog-talk-updated' )->escaped(); return $fields; } @@ -691,7 +697,7 @@ private function authorLink( $name ) $name = $user->getRealName(); if ( !$name ) $name = $user->getName(); - return $skin->link( $user->getUserPage(), $name ); + return Linker::link( $user->getUserPage(), $name ); } /** @@ -706,15 +712,15 @@ private function doEditLink( $title, $tooltip = null ) { $skin = $this->getSkin(); $attribs = array(); if ( !is_null( $tooltip ) ) { - $attribs['title'] = wfMsg( 'wikilog-edit-hint', $tooltip ); + $attribs['title'] = wfMessage( 'wikilog-edit-hint', $tooltip )->text(); } - $link = $skin->link( $title, wfMsg( 'wikilog-edit-lc' ), + $link = Linker::link( $title, wfMessage( 'wikilog-edit-lc' )->text(), $attribs, array( 'action' => 'edit' ), array( 'noclasses', 'known' ) ); - $result = wfMsgHtml ( 'editsection-brackets', $link ); + $result = wfMessage( 'editsection-brackets', $link )->escaped(); return $result; } } diff --git a/WikilogLinksUpdate.php b/WikilogLinksUpdate.php index a417e10..632d908 100644 --- a/WikilogLinksUpdate.php +++ b/WikilogLinksUpdate.php @@ -34,15 +34,13 @@ class WikilogLinksUpdate private $mId; private $mTitle; private $mDb; - private $mOptions; private $mAuthors; private $mTags; function __construct( &$lupd, $parserOutput ) { $this->mId = $lupd->mId; $this->mTitle = $lupd->mTitle; - $this->mDb = $lupd->mDb; - $this->mOptions = $lupd->mOptions; + $this->mDb = wfGetDB( DB_MASTER ); $this->mAuthors = $parserOutput->getAuthors(); $this->mTags = $parserOutput->getTags(); } @@ -135,7 +133,7 @@ private function getTagDeletions( $existing ) { private function getExistingAuthors() { $res = $this->mDb->select( 'wikilog_authors', array( 'wla_page', 'wla_author' ), - array( 'wla_page' => $this->mId ), __METHOD__, $this->mOptions ); + array( 'wla_page' => $this->mId ), __METHOD__ ); $arr = array(); while ( $row = $this->mDb->fetchObject( $res ) ) { $arr[$row->wla_author] = 1; @@ -146,7 +144,7 @@ private function getExistingAuthors() { private function getExistingTags() { $res = $this->mDb->select( 'wikilog_tags', array( 'wlt_page', 'wlt_tag' ), - array( 'wlt_page' => $this->mId ), __METHOD__, $this->mOptions ); + array( 'wlt_page' => $this->mId ), __METHOD__ ); $arr = array(); while ( $row = $this->mDb->fetchObject( $res ) ) { $arr[$row->wlt_tag] = 1; diff --git a/WikilogMainPage.php b/WikilogMainPage.php index 3255a12..45be50c 100644 --- a/WikilogMainPage.php +++ b/WikilogMainPage.php @@ -62,9 +62,25 @@ public function __construct( &$title, &$wi ) { public function view() { global $wgRequest, $wgOut, $wgMimeType, $wgUser; - $query = new WikilogItemQuery( $this->mTitle ); + $queryTitle; + $parts = explode( '/', $this->mTitle->getText() ); + if (count( $parts ) > 1) { + $origns = $this->mTitle->getNamespace(); + $ns = MWNamespace::getSubject( $origns ); + $queryTitle = Title::makeTitle( $ns, $parts[0] ); + } else { + $queryTitle = $this->mTitle; + } + + $query = new WikilogItemQuery( $queryTitle ); $query->setPubStatus( $wgRequest->getVal( 'show' ) ); + if (count( $parts ) > 1) { + $query->setCategory('News/'.$parts[1]); + } else { + $query->setCategory('News'); + } + # RSS or Atom feed requested. Ignore all other options. if ( ( $feedFormat = $wgRequest->getVal( 'feed' ) ) ) { global $wgWikilogNumArticles; @@ -130,8 +146,7 @@ public function view() { 'rel' => 'alternate', 'href' => $this->mTitle->getLocalURL( $altquery ), 'type' => $wgMimeType, - 'title' => wfMsgExt( "wikilog-view-{$alt}", - array( 'content', 'parsemag' ) ) + 'title' => wfMessage( "wikilog-view-{$alt}" )->inContentLanguage()->text() ) ); } } @@ -143,14 +158,15 @@ public function view() { public function wikilog() { global $wgUser, $wgOut, $wgRequest; - if ( $this->mTitle->exists() && $wgRequest->getBool( 'wlActionImport' ) ) + if ( $this->mTitle->exists() && $wgRequest->getBool( 'wlActionImport' ) ) { return $this->actionImport(); + } - $wgOut->setPageTitle( wfMsg( 'wikilog-tab-title' ) ); + $wgOut->setPageTitle( wfMessage( 'wikilog-tab-title' )->text() ); $wgOut->setRobotpolicy( 'noindex,nofollow' ); if ( $this->mTitle->exists() ) { - $skin = $wgUser->getSkin(); + $skin = $this->getContext()->getSkin(); $wgOut->addHTML( $this->formatWikilogDescription( $skin ) ); $wgOut->addHTML( $this->formatWikilogInformation( $skin ) ); if ( $this->mTitle->quickUserCan( 'edit' ) ) { @@ -158,7 +174,7 @@ public function wikilog() { $wgOut->addHTML( $this->formImport() ); } } elseif ( $this->mTitle->userCan( 'create' ) ) { - $text = wfMsgExt( 'wikilog-missing-wikilog', 'parse' ); + $text = wfMessage( 'wikilog-missing-wikilog' )->parse(); $text = WikilogUtils::wrapDiv( 'noarticletext', $text ); $wgOut->addHTML( $text ); } else { @@ -182,7 +198,7 @@ protected function formatWikilogDescription( $skin ) { ); } $s .= Xml::tags( 'div', array( 'class' => 'wl-title' ), - $skin->link( $this->mTitle, null, array(), array(), array( 'known', 'noclasses' ) ) ); + Linker::link( $this->mTitle, null, array(), array(), array( 'known', 'noclasses' ) ) ); $st =& $this->mWikilogSubtitle; if ( is_array( $st ) ) { @@ -221,7 +237,7 @@ protected function formatWikilogInformation( $skin ) { $cont .= $this->formatPostCount( $skin, 'li', 'all', $n_total ); $cont .= Xml::closeElement( 'ul' ); - return Xml::fieldset( wfMsg( 'wikilog-information' ), $cont ) . "\n"; + return Xml::fieldset( wfMessage( 'wikilog-information' )->text(), $cont ) . "\n"; } /** @@ -231,8 +247,8 @@ private function formatPostCount( $skin, $elem, $type, $num ) { global $wgWikilogFeedClasses; // Uses messages 'wikilog-post-count-published', 'wikilog-post-count-drafts', 'wikilog-post-count-all' - $s = $skin->link( $this->mTitle, - wfMsgExt( "wikilog-post-count-{$type}", array( 'parsemag' ), $num ), + $s = Linker::link( $this->mTitle, + wfMessage( "wikilog-post-count-{$type}", $num )->text(), array(), array( 'view' => "archives", 'show' => $type ), array( 'knwon', 'noclasses' ) @@ -240,8 +256,8 @@ private function formatPostCount( $skin, $elem, $type, $num ) { if ( !empty( $wgWikilogFeedClasses ) ) { $f = array(); foreach ( $wgWikilogFeedClasses as $format => $class ) { - $f[] = $skin->link( $this->mTitle, - wfMsg( "feed-{$format}" ), + $f[] = Linker::link( $this->mTitle, + wfMessage( "feed-{$format}" )->text(), array( 'class' => "feedlink", 'type' => "application/{$format}+xml" ), array( 'view' => "archives", 'show' => $type, 'feed' => $format ), array( 'known', 'noclasses' ) @@ -254,15 +270,19 @@ private function formatPostCount( $skin, $elem, $type, $num ) { /** * Returns a form for new item creation. + * @param Title $title */ static function formNewItem( $title ) { - global $wgScript, $wgWikilogStylePath; + global $wgScript, $wgWikilogStylePath, $wgMaxTitleBytes; $fields = array(); - if ( $title ) - $fields[] = Xml::element( 'input', array( 'type' => 'hidden', 'value' => $title->getPrefixedText(), 'id' => 'wl-newitem-wikilog' ) ); - else - { + if ( $title ) { + $fields[] = Xml::element( 'input', array( + 'type' => 'hidden', + 'value' => $title->getPrefixedText(), + 'id' => 'wl-newitem-wikilog' + ) ); + } else { global $wgWikilogNamespaces; $dbr = wfGetDB( DB_SLAVE ); $r = $dbr->select( 'page', 'page_id', array( @@ -270,34 +290,46 @@ static function formNewItem( $title ) { 'page_title NOT LIKE \'%/%\'', ), __METHOD__ ); $opts = array(); - foreach ( $r as $obj ) - { + foreach ( $r as $obj ) { $t = Title::newFromID( $obj->page_id ); - if ( $t->userCan( 'edit' ) ) + if ( $t->userCan( 'edit' ) ) { $opts[] = $t; + } } - if ( !$opts ) + if ( !$opts ) { return ''; + } $wikilog_select = new XmlSelect( false, 'wl-newitem-wikilog' ); - foreach ( $opts as $o ) + foreach ( $opts as $o ) { $wikilog_select->addOption( $o->getText(), $o->getPrefixedText() ); - $fields[] = Xml::label( wfMsg( 'wikilog-form-wikilog' ), 'wl-newitem-wikilog' ) + } + $fields[] = Xml::label( wfMessage( 'wikilog-form-wikilog' )->text(), 'wl-newitem-wikilog' ) . ' ' . $wikilog_select->getHTML(); } $fields[] = Html::hidden( 'action', 'edit' ); $fields[] = Html::hidden( 'preload', '' ); $fields[] = Html::hidden( 'title', '' ); - $fields[] = Xml::inputLabel( wfMsg( 'wikilog-item-name' ), - false, 'wl-item-name', 70, date('Y-m-d ') ); - $fields[] = Xml::submitButton( wfMsg( 'wikilog-new-item-go' ) ); + $fields[] = Xml::inputLabel( wfMessage( 'wikilog-item-name' )->text(), + false, 'wl-item-name', 70, date( 'Y-m-d ' ) ); + $fields[] = Xml::submitButton( wfMessage( 'wikilog-new-item-go' )->text() ); $form = Xml::tags( 'form', - array( 'action' => $wgScript, 'onsubmit' => 'return checkNewItem(this, \''.wfMsg('wikilog-new-item-subpage').'\');' ), + array( + 'action' => $wgScript, + 'onsubmit' => 'return wlCheckNewItem(this, ' + . json_encode( array( + 'subpage' => wfMessage( 'wikilog-new-item-subpage' )->text(), + 'title' => array( + 'lng' => ( isset( $wgMaxTitleBytes ) ? $wgMaxTitleBytes : 255 ) - strlen( '/c' . WikilogComment::padID( 0 ) ), + 'msg' => wfMessage( 'wikilog-new-item-too-long' )->text() + ) + ) ) + . ');' + ), implode( "\n", $fields ) ); - $form = Xml::fieldset( wfMsg( 'wikilog-new-item' ), $form, array( 'id' => 'wl-new-item' ) ) . "\n"; - $form .= ''; + $form = Xml::fieldset( wfMessage( 'wikilog-new-item' )->text(), $form, array( 'id' => 'wl-new-item' ) ) . "\n"; return $form; } @@ -311,10 +343,10 @@ protected function formImport() { $fields[] = Html::hidden( 'title', $this->mTitle->getPrefixedText() ); $fields[] = Html::hidden( 'action', 'wikilog' ); $fields[] = Html::hidden( 'wikilog-import', 'blogger' ); - $fields[] = Xml::inputLabel( wfMsg('wikilog-import-file'), 'wlFile', 'wl-import-file', false, false, array('type' => 'file') ); - $fields[] = Xml::submitButton( wfMsg( 'wikilog-import-go' ), + $fields[] = Xml::inputLabel( wfMessage( 'wikilog-import-file' )->text(), 'wlFile', 'wl-import-file', false, false, array('type' => 'file') ); + $fields[] = Xml::submitButton( wfMessage( 'wikilog-import-go' )->text(), array( 'name' => 'wlActionImport' ) ); - $fields[] = '
' . Xml::label( wfMsg('wikilog-import-aliases'), 'wl-user-aliases' ) . + $fields[] = '
' . Xml::label( wfMessage( 'wikilog-import-aliases' )->text(), 'wl-user-aliases' ) . Xml::textarea( 'wlUserAliases', '', 40, 5, array( 'id' => 'wl-user-aliases' ) ); $form = Xml::tags( 'form', @@ -322,7 +354,7 @@ protected function formImport() { implode( "\n", $fields ) ); - return Xml::fieldset( wfMsg( 'wikilog-import' ), $form ) . "\n"; + return Xml::fieldset( wfMessage( 'wikilog-import' )->text(), $form ) . "\n"; } /** @@ -330,7 +362,7 @@ protected function formImport() { */ protected function actionImport() { global $wgOut, $wgRequest; - $wgOut->setPageTitle( wfMsg( 'wikilog-import' ) ); + $wgOut->setPageTitle( wfMessage( 'wikilog-import' )->text() ); if ( !$this->mTitle->quickUserCan( 'edit' ) ) { $wgOut->loginToUse(); diff --git a/WikilogParser.php b/WikilogParser.php index dfe0ddf..cd144e3 100644 --- a/WikilogParser.php +++ b/WikilogParser.php @@ -61,7 +61,7 @@ class WikilogParser /** * ParserFirstCallInit hook handler function. */ - public static function FirstCallInit( &$parser ) { + public static function FirstCallInit( $parser ) { $mwSummary =& MagicWord::get( 'wlk-summary' ); foreach ( $mwSummary->getSynonyms() as $tagname ) { $parser->setHook( $tagname, array( 'WikilogParser', 'summary' ) ); @@ -79,7 +79,7 @@ public static function FirstCallInit( &$parser ) { /** * ParserClearState hook handler function. */ - public static function ClearState( &$parser ) { + public static function ClearState( $parser ) { # These two parser attributes contain our private information. # They take a piggyback ride on the parser object. $parser->mExtWikilog = new WikilogParserOutput; @@ -95,7 +95,7 @@ public static function ClearState( &$parser ) { /** * ParserBeforeStrip hook handler function. */ - public static function BeforeStrip( &$parser, &$text, &$stripState ) { + public static function BeforeStrip( $parser, $text, $stripState ) { global $wgUser; # Do nothing if a title is not set. @@ -118,7 +118,7 @@ public static function BeforeStrip( &$parser, &$text, &$stripState ) { /** * ParserAfterTidy hook handler function. */ - public static function AfterTidy( &$parser, &$text ) { + public static function AfterTidy( $parser, $text ) { $parser->mOutput->mExtWikilog = $parser->mExtWikilog; return true; } @@ -130,7 +130,7 @@ public static function AfterTidy( &$parser, &$text ) { * article summary before it. If not found, look for the first heading * and use the text before it (intro section). */ - public static function InternalParseBeforeLinks( &$parser, &$text, &$stripState ) { + public static function InternalParseBeforeLinks( $parser, &$text, $stripState ) { if ( $parser->mExtWikilogInfo && $parser->mExtWikilogInfo->isItem() ) { static $moreRegex = false; if ( $moreRegex === false ) { @@ -140,21 +140,25 @@ public static function InternalParseBeforeLinks( &$parser, &$text, &$stripState $moreRegex = "/(?<=^|\\n)--+ *(?:$words) *--+\s*/$flags"; } - # Find and replace the --more-- marker. Extract summary. - # We do it anyway even if the summary is already set, in order - # to replace the marker with an invisible anchor. + /** + * Find and replace the --more-- marker. Extract summary. + * We do it anyway even if the summary is already set, in order + * to replace the marker with an invisible anchor. + */ $p = preg_split( $moreRegex, $text, 2 ); if ( count( $p ) > 1 ) { self::trySetSummary( $parser, trim( $p[0] ) ); $anchor = $parser->insertStripItem( self::MORE_ANCHOR ); $text = $p[0] . $anchor . $p[1]; } elseif ( !$parser->mExtWikilog->mSummary ) { - # Otherwise, make a summary from the intro section. - # Why we don't use $parser->getSection()? Because it has the - # side-effect of clearing the parser state, which is bad here - # since this hook happens during parsing. Instead, we - # anticipate the $parser->doHeadings() call and extract the - # text before the first heading. + /* + * Otherwise, make a summary from the intro section. + * Why we don't use $parser->getSection()? Because it has the + * side-effect of clearing the parser state, which is bad here + * since this hook happens during parsing. Instead, we + * anticipate the $parser->doHeadings() call and extract the + * text before the first heading. + */ $text = $parser->doHeadings( $text ); $p = preg_split( '/<(h[1-6])\\b.*?>.*?<\\/\\1\\s*>/i', $text, 2 ); if ( count( $p ) > 1 ) { @@ -169,7 +173,7 @@ public static function InternalParseBeforeLinks( &$parser, &$text, &$stripState * GetLocalURL hook handler function. * Expands local URL @a $url if self::$expandingUrls is true. */ - public static function GetLocalURL( &$title, &$url, $query ) { + public static function GetLocalURL( $title, &$url, $query ) { if ( self::$expandingUrls ) { $url = wfExpandUrl( $url ); } @@ -184,7 +188,7 @@ public static function GetLocalURL( &$title, &$url, $query ) { * from Title::getLocalURL() in situations where action != 'render'. * @todo Report this bug to MediaWiki bugzilla. */ - public static function GetFullURL( &$title, &$url, $query ) { + public static function GetFullURL( $title, &$url, $query ) { global $wgServer; if ( self::$expandingUrls ) { $l = strlen( $wgServer ); @@ -216,7 +220,7 @@ public static function summary( $text, $params, $parser ) { /** * {{wl-settings:...}} parser function handler. */ - public static function settings( &$parser /* ... */ ) { + public static function settings( $parser /* ... */ ) { global $wgOut; self::checkNamespace( $parser ); @@ -246,7 +250,7 @@ public static function settings( &$parser /* ... */ ) { $output = $parser->parse( $value, $parser->getTitle(), $popt, true, false ); $parser->mExtWikilog->mSummary = $output->getText(); } else { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-invalid-param', htmlspecialchars( $key ) ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-invalid-param', htmlspecialchars( $key ) )->text() )->text(); $parser->mOutput->addWarning( $warning ); } } @@ -257,30 +261,30 @@ public static function settings( &$parser /* ... */ ) { /** * {{wl-publish:...}} parser function handler. */ - public static function publish( &$parser, $pubdate /*, $author... */ ) { + public static function publish( $parser, $pubdate /*, $author... */ ) { self::checkNamespace( $parser ); $parser->mExtWikilog->mPublish = true; $args = array_slice( func_get_args(), 2 ); - # First argument is the publish date + // First argument is the publish date if ( !is_null( $pubdate ) ) { wfSuppressWarnings(); // Shut up E_STRICT warnings about timezone. $ts = strtotime( $pubdate ); wfRestoreWarnings(); if ( $ts > 0 ) { $parser->mExtWikilog->mPubDate = wfTimestamp( TS_MW, $ts ); - } - else { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-invalid-date', $pubdate ) ); + } else { + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-invalid-date', $pubdate )->text() )->text(); $parser->mOutput->addWarning( $warning ); } } - # Remaining arguments are author names + // Remaining arguments are author names foreach ( $args as $name ) { - if ( !self::tryAddAuthor( $parser, $name ) ) + if ( !self::tryAddAuthor( $parser, $name ) ) { break; + } } return ''; @@ -300,7 +304,7 @@ public static function comment( $parser, $parent, $anon_name = NULL ) { /** * {{wl-author:...}} parser function handler. */ - public static function author( &$parser /*, $author... */ ) { + public static function author( $parser /*, $author... */ ) { self::checkNamespace( $parser ); $args = array_slice( func_get_args(), 1 ); @@ -314,7 +318,7 @@ public static function author( &$parser /*, $author... */ ) { /** * {{wl-tags:...}} parser function handler. */ - public static function tags( &$parser /*, $tag... */ ) { + public static function tags( $parser /*, $tag... */ ) { self::checkNamespace( $parser ); $args = array_slice( func_get_args(), 1 ); @@ -329,7 +333,7 @@ public static function tags( &$parser /*, $tag... */ ) { * {{wl-info:...}} parser function handler. * Provides general information about the extension. */ - public static function info( &$parser, $id /*, $tag... */ ) { + public static function info( $parser, $id /*, $tag... */ ) { global $wgWikilogNamespaces, $wgWikilogEnableTags; global $wgWikilogEnableComments; global $wgContLang; @@ -457,7 +461,7 @@ public static function expandLocalUrls( $enable = true ) { * Set the article summary, ignore if already set. * @return True if set, false otherwise. */ - private static function trySetSummary( &$parser, $text ) { + private static function trySetSummary( $parser, $text ) { if ( !$parser->mExtWikilog->mSummary ) { $oldOpt = $parser->getOptions(); $popt = clone $oldOpt; @@ -478,11 +482,11 @@ private static function trySetSummary( &$parser, $text ) { * Adds an author to the current article. If too many authors, warns. * @return False on overflow, true otherwise. */ - private static function tryAddAuthor( &$parser, $name ) { + private static function tryAddAuthor( $parser, $name ) { global $wgWikilogMaxAuthors; if ( count( $parser->mExtWikilog->mAuthors ) >= $wgWikilogMaxAuthors ) { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-too-many-authors' ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-too-many-authors' )->text() )->text(); $parser->mOutput->addWarning( $warning ); return false; } @@ -492,7 +496,7 @@ private static function tryAddAuthor( &$parser, $name ) { $parser->mExtWikilog->mAuthors[$user->getName()] = $user->getID(); } else { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-invalid-author', $name ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-invalid-author', $name )->text() )->text(); $parser->mOutput->addWarning( $warning ); } return true; @@ -502,14 +506,14 @@ private static function tryAddAuthor( &$parser, $name ) { * Adds a tag to the current article. If too many tags, warns. * @return False on overflow, true otherwise. */ - private static function tryAddTag( &$parser, $tag ) { + private static function tryAddTag( $parser, $tag ) { global $wgWikilogMaxTags; static $tcre = false; if ( !$tcre ) { $tcre = '/[^' . Title::legalChars() . ']/'; } if ( count( $parser->mExtWikilog->mTags ) >= $wgWikilogMaxTags ) { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-too-many-tags' ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-too-many-tags' )->text() )->text(); $parser->mOutput->addWarning( $warning ); return false; } @@ -518,7 +522,7 @@ private static function tryAddTag( &$parser, $tag ) { $parser->mExtWikilog->mTags[$tag] = 1; } else { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-invalid-tag', $tag ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-invalid-tag', $tag )->text() )->text(); $parser->mOutput->addWarning( $warning ); } return true; @@ -528,14 +532,14 @@ private static function tryAddTag( &$parser, $tag ) { * Check if the calling parser function is being executed in Wikilog * context. Generates a parser warning if it isn't. */ - private static function checkNamespace( &$parser ) { + private static function checkNamespace( $parser ) { global $wgWikilogNamespaces; static $tested = false; if ( !$tested ) { $title = $parser->getTitle(); if ( !in_array( $title->getNamespace(), $wgWikilogNamespaces ) ) { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-out-of-context' ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-out-of-context' )->text() )->text(); $parser->mOutput->addWarning( $warning ); } $tested = true; @@ -550,24 +554,24 @@ private static function checkNamespace( &$parser ) { * * @return File instance, or NULL. */ - private static function parseImageLink( &$parser, $text ) { + private static function parseImageLink( $parser, $text ) { $obj = self::parseMediaLink( $parser, $text ); if ( !$obj ) { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-invalid-file', htmlspecialchars( $text ) ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-invalid-file', htmlspecialchars( $text ) )->text() )->text(); $parser->mOutput->addWarning( $warning ); return null; } list( $t1, $t2, $file ) = $obj; if ( !$file ) { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-file-not-found', htmlspecialchars( $t1 ) ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-file-not-found', htmlspecialchars( $t1 ) )->text() )->text(); $parser->mOutput->addWarning( $warning ); return null; } $type = $file->getMediaType(); if ( $type != MEDIATYPE_BITMAP && $type != MEDIATYPE_DRAWING ) { - $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-not-an-image', $file->getName() ) ); + $warning = wfMessage( 'wikilog-error-msg', wfMessage( 'wikilog-not-an-image', $file->getName() )->text() )->text(); $parser->mOutput->addWarning( $warning ); return null; } @@ -584,7 +588,7 @@ private static function parseImageLink( &$parser, $text ) { * @return Three-element array containing the matched parts of the link, * and the file object, or NULL. */ - private static function parseMediaLink( &$parser, $text ) { + private static function parseMediaLink( $parser, $text ) { $tc = Title::legalChars(); if ( !preg_match( "/\\[\\[([{$tc}]+)(?:\\|(.+?))?]]/", $text, $m ) ) return null; diff --git a/WikilogQuery.php b/WikilogQuery.php index 4acdbc8..5bf5c19 100644 --- a/WikilogQuery.php +++ b/WikilogQuery.php @@ -186,7 +186,7 @@ public function selectSQLText( $dbr, $tables, $fields, $conds = array(), if ( !$fields ) { $fields = $info['fields']; } - return $dbr->selectSQLText($tables, $fields, $conds, $function, $options, $join_conds); + return $dbr->selectSQLText( $tables, $fields, $conds, $function, $options, $join_conds ); } } @@ -750,8 +750,8 @@ public function getQueryInfo( $db, $opts = array() ) { # Filter by date. if ( $this->mDate ) { - $q_conds[] = 'wlc_timestamp >= ' . $db->addQuotes( $this->mDate->start ); - $q_conds[] = 'wlc_timestamp < ' . $db->addQuotes( $this->mDate->end ); + $q_conds[] = 'wlc_timestamp >= ' . $db->timestamp( $this->mDate->start ); + $q_conds[] = 'wlc_timestamp < ' . $db->timestamp( $this->mDate->end ); } # Sort order and limits diff --git a/WikilogUtils.php b/WikilogUtils.php index 71d1c9d..f69da0b 100644 --- a/WikilogUtils.php +++ b/WikilogUtils.php @@ -29,26 +29,28 @@ if ( !defined( 'MEDIAWIKI' ) ) die(); -class PageLastVisitUpdater { +class PageLastVisitUpdater implements DeferrableUpdate { var $visit = array(); function __construct() { - global $wgDeferredUpdateList; - $wgDeferredUpdateList[] = $this; + DeferredUpdates::addUpdate( $this ); } function add( $pageid, $userid, $timestamp ) { $this->visit[] = array( 'pv_page' => $pageid, 'pv_user' => $userid, - 'pv_date' => wfTimestamp( TS_MW, $timestamp ), + 'pv_date' => $timestamp, ); } function doUpdate() { if ( $this->visit ) { $dbw = wfGetDB( DB_MASTER ); + foreach ( $this->visit as &$v ) { + $v['pv_date'] = $dbw->timestamp( $v['pv_date'] ); + } $dbw->replace( 'page_last_visit', array( array( 'pv_page', 'pv_user' ) ), $this->visit, __METHOD__ ); $this->visit = array(); } @@ -120,7 +122,7 @@ public static function updateTalkInfo( $pageID, $isWikilogPost = false ) { $dbw->replace( 'wikilog_talkinfo', array( 'wti_page' ), array( array( 'wti_page' => $pageID, 'wti_num_comments' => $count, - 'wti_talk_updated' => $talkUpdated + 'wti_talk_updated' => $dbw->timestamp( $talkUpdated ) ) ), __METHOD__ ); return array( $count, $talkUpdated ); @@ -158,7 +160,7 @@ public static function parsedArticle( Title $title, $feed = false ) { static $parser = null; - $article = new Article( $title ); + $article = new WikiPage( $title ); # First try the parser cache. $useParserCache = $wgEnableParserCache && @@ -208,7 +210,16 @@ public static function parsedArticle( Title $title, $feed = false ) { $parser->startExternalParse( $title, $parserOpt, Parser::OT_HTML ); # Parse article. - $arttext = $article->fetchContent(); + $articleContent = $article->getContent(); + if ( !($articleContent instanceof TextContent) ){ + # Restore default behavior. + if ( $feed ) { + WikilogParser::enableFeedParsing( $saveFeedParse ); + WikilogParser::expandLocalUrls( $saveExpUrls ); + } + return array( $article, '' ); + } + $arttext = $articleContent->getNativeData(); $parserOutput = $parser->parse( $arttext, $title, $parserOpt ); # Save in parser cache. @@ -305,8 +316,8 @@ public static function authorSig( $author, $parse = false ) if ( !$n ) $n = $author; $authorSigCache[$author . ($parse ? '/1' : '/0')] = $parse - ? wfMsgExt( 'wikilog-author-signature', array( 'parseinline' ), $user->getName(), $n ) - : wfMsgForContent( 'wikilog-author-signature', $user->getName(), $n ); + ? wfMessage( 'wikilog-author-signature', $user->getName(), $n )->parse() + : wfMessage( 'wikilog-author-signature', $user->getName(), $n )->inContentLanguage()->text(); } return $authorSigCache[$author . ($parse ? '/1' : '/0')]; } @@ -419,7 +430,7 @@ public static function getCommentsWikiText( WikilogItem &$item ) { $commentsNum = $item->getNumComments(); $commentsMsg = ( $commentsNum ? 'wikilog-has-comments' : 'wikilog-no-comments' ); $commentsUrl = $item->mTitle->getTalkPage()->getPrefixedURL(); - $commentsTxt = wfMsgExt( $commentsMsg, array( 'parsemag', 'content' ), $commentsNum ); + $commentsTxt = wfMessage( $commentsMsg, $commentsNum )->inContentLanguage()->text(); return "[[{$commentsUrl}|{$commentsTxt}]]"; } @@ -519,8 +530,8 @@ public static function getLocalDateTime( $timestamp, $format = false ) { global $wgLang, $wgLocaltimezone; $ts = wfTimestamp( TS_UNIX, $timestamp ); - $ts = gmdate( 'YmdHis', $ts ); $tz = gmdate( 'T', $ts ); + $ts = gmdate( 'YmdHis', $ts ); $ts = $wgLang->userAdjust( $ts ); if ( !$format ) @@ -532,13 +543,13 @@ public static function getLocalDateTime( $timestamp, $format = false ) { # Check for translation of timezones. $key = 'timezone-' . strtolower( trim( $tz ) ); - $value = wfMsgForContent( $key ); - if ( !wfEmptyMsg( $key, $value ) ) $tz = $value; + $value = wfMessage( $key )->inContentLanguage(); + if ( !$value->isBlank() ) $tz = $value->text(); return array( $date, $time, $tz ); } - static function getOldestRevision( $articleId ) { + public static function getOldestRevision( $articleId ) { $row = NULL; $db = wfGetDB( DB_SLAVE ); $revSelectFields = Revision::selectFields(); @@ -555,12 +566,30 @@ static function getOldestRevision( $articleId ) { return $row ? Revision::newFromRow( $row ) : null; } + public static function sendHtmlMail($to, $from, $subject, $body, $headers) + { + global $wgVersion; + if (version_compare($wgVersion, '1.25', '>=')) + { + // MediaWiki 1.25+ + UserMailer::send($to, $from, $subject, $body, array( + 'headers' => $headers, + 'contentType' => 'text/html; charset=UTF-8', + )); + } + else + { + // MediaWiki 1.19+ or MediaWiki4Intranet 1.18 + UserMailer::send($to, $from, $subject, $body, NULL, 'text/html; charset=UTF-8', $headers); + } + } + // 7bit 0bbbbbbb // 14bit 10bbbbbb bbbbbbbb // 21bit 110bbbbb bbbbbbbb bbbbbbbb // 28bit 1110bbbb bbbbbbbb bbbbbbbb bbbbbbbb // 35bit 11110bbb bbbbbbbb bbbbbbbb bbbbbbbb bbbbbbbb - static function encodeVarint( $int ) { + public static function encodeVarint( $int ) { if ( $int < 0x80 ) { return chr( $int ); } elseif ( $int < 0x4000 ) { @@ -574,7 +603,7 @@ static function encodeVarint( $int ) { } } - static function encodeVarintArray( $a ) { + public static function encodeVarintArray( $a ) { $s = ''; foreach ( $a as $int ) { $s .= self::encodeVarint( $int ); @@ -582,7 +611,7 @@ static function encodeVarintArray( $a ) { return $s; } - static function decodeVarintArray( $s ) { + public static function decodeVarintArray( $s ) { $l = strlen( $s ); $array = array(); for ( $i = 0; $i < $l; ) { @@ -673,17 +702,16 @@ public function getNavigationBar( $limit ) { global $wgLang; $limit = $wgLang->formatNum( $limit ); - $opts = array( 'parsemag', 'escapenoentities' ); $linkTexts = $disabledTexts = array(); foreach ( self::$linkTextMsgs[$this->mType] as $type => $msg ) { - $label = wfMsgExt( $msg, $opts, $limit ); + $label = wfMessage( $msg, $limit )->escaped(); $linkTexts[$type] = wfMsgReplaceArgs( self::$pagingLabels[$type], array( $label ) ); $disabledTexts[$type] = Xml::wrapClass( $linkTexts[$type], 'disabled' ); } $pagingLinks = $this->mPager->getPagingLinks( $linkTexts, $disabledTexts ); // $limitLinks = $this->mPager->getLimitLinks(); // XXX: Not used yet. - $ellipsis = wfMsg( 'ellipsis' ); + $ellipsis = wfMessage( 'ellipsis' )->text(); $html = "{$pagingLinks['first']} {$pagingLinks['prev']} {$ellipsis} {$pagingLinks['next']} {$pagingLinks['last']}"; $html = WikilogUtils::wrapDiv( 'wl-pagination', $html ); diff --git a/WlCaptchaAdapter.php b/WlCaptchaAdapter.php index c095898..8e14f88 100644 --- a/WlCaptchaAdapter.php +++ b/WlCaptchaAdapter.php @@ -101,6 +101,10 @@ public function confirmEdit( $title, $newText, $oldText = null ) { private function doConfirmEdit( $title, $newText, $oldText = null ) { if ( $this->shouldCheck( $title, $newText, $oldText ) ) { + if ( method_exists( $this->mCaptcha, 'passCaptchaFromRequest' ) ) { + global $wgRequest, $wgUser; + return $this->mCaptcha->passCaptchaFromRequest( $wgRequest, $wgUser ); + } return $this->mCaptcha->passCaptcha(); } else { wfDebug( "WlCaptchaAdapter: no need to show captcha.\n" ); diff --git a/WlFeed.body.php b/WlFeed.body.php index 88e5e6f..14a1520 100644 --- a/WlFeed.body.php +++ b/WlFeed.body.php @@ -422,7 +422,7 @@ function contentType() { * declaration and stylesheet. */ function outXmlHeader() { - global $wgStylePath, $wgStyleVersion; + global $wgStylePath; $this->httpHeaders(); echo '' . "\n"; @@ -433,7 +433,7 @@ function outXmlHeader() { if ( !in_array( 'style', $this->mQuirks ) ) { echo '\n"; } } diff --git a/WlFeed.php b/WlFeed.php index 1261c92..ee3725c 100644 --- a/WlFeed.php +++ b/WlFeed.php @@ -29,18 +29,6 @@ if ( !defined( 'MEDIAWIKI' ) ) die(); -/** - * General extension information. - */ -$wgExtensionCredits['other'][] = array( - 'path' => __FILE__, - 'name' => 'WlFeed', - 'version' => '1.2.0', - 'author' => 'Juliano F. Ravasi', - 'descriptionmsg' => 'wlfeed-desc', - 'url' => 'https://www.mediawiki.org/wiki/Extension:Wikilog', -); - /** * Module autoload information. */ diff --git a/archives/patch-talkinfo.sql b/archives/patch-talkinfo.sql index 5deec13..aea4d4f 100644 --- a/archives/patch-talkinfo.sql +++ b/archives/patch-talkinfo.sql @@ -12,4 +12,7 @@ CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_talkinfo ( ) /*$wgDBTableOptions*/; INSERT INTO /*$wgDBprefix*/wikilog_talkinfo ( wti_page, wti_talk_updated, wti_num_comments ) - SELECT wlp_page, wlp_talk_updated, wlp_num_comments FROM /*$wgDBprefix*/wikilog_posts; + SELECT wlp_page, CASE WHEN MAX( wlc_updated ) > wlp_updated THEN MAX( wlc_updated ) ELSE wlp_updated END, COUNT(1) + FROM /*$wgDBprefix*/wikilog_posts + LEFT JOIN /*$wgDBprefix*/wikilog_comments ON wlc_post = wlp_page + GROUP BY wlp_page; diff --git a/maintenance/wikilogImportDocumentation.php b/maintenance/wikilogImportDocumentation.php index c2a9c59..a3f10a2 100644 --- a/maintenance/wikilogImportDocumentation.php +++ b/maintenance/wikilogImportDocumentation.php @@ -122,10 +122,10 @@ protected function doImport( $filename ) { $this->mSource = new ImportStreamSource( $this->mFileHandle ); $this->mImporter = new WikiImporter( $this->mSource ); - $this->mUser = User::newFromName( wfMsgForContent( 'wikilog-auto' ), false ); + $this->mUser = User::newFromName( wfMessage( 'wikilog-auto' )->inContentLanguage()->text(), false ); $wgUser = $this->mUser; - $this->mComment = wfMsgForContent( 'wikilog-doc-import-comment' ); + $this->mComment = wfMessage( 'wikilog-doc-import-comment' )->inContentLanguage()->text(); $this->mTimestamp = wfTimestampNow(); $this->mImporter->setRevisionCallback( array( &$this, 'handleRevision' ) ); diff --git a/style/wikilog.css b/style/wikilog.css index 862ee54..6a119b4 100644 --- a/style/wikilog.css +++ b/style/wikilog.css @@ -186,6 +186,11 @@ div.wl-comment-deleted .wl-comment-text { color: #999999; } +.wl-comment-text blockquote { + margin-left: 0; + background: #f8f8f8; +} + div.wl-comment-placeholder { background-color: #EEEEEE; border: 1px solid #CCCCCC; diff --git a/style/wikilog.js b/style/wikilog.js index bcc236d..5400a0c 100644 --- a/style/wikilog.js +++ b/style/wikilog.js @@ -1,16 +1,59 @@ /* JavaScript bits for Wikilog extension */ /* Checks new item name and sets 'title' and 'preload' arguments */ -function checkNewItem(f, msg) +window.wlCheckNewItem = function(f, msgs) { var i = document.getElementById('wl-item-name'); var w = document.getElementById('wl-newitem-wikilog'); if (i.value.indexOf('/') >= 0) { - alert(msg); + alert(msgs.subpage); return false; } + if (msgs.title) + { + if (msgs.title.lng < (w.value + '/' + i.value).length) + { + alert(msgs.title.msg); + return false; + } + } f.title.value = w.value + '/' + i.value; f.preload.value = 'Template:' + w.value; return true; -} +}; + +/* Add/move reply form to a comment */ +window.wlReplyTo = function(id) +{ + var c = document.getElementById('c'+id); + if (!c) + { + return true; + } + var f = document.getElementById('wl-comment-form-reply'); + if (!f) + { + f = document.getElementById('wl-comment-form').cloneNode(true); + f.setAttribute('id', 'wl-comment-form-reply'); + var e = document.createElement('div'); + e.setAttribute('class', 'wl-indent'); + e.appendChild(f); + f = e; + } + else + { + f = f.parentNode; //
+ } + var ff = f.getElementsByTagName('form')[0]; + if (!ff.wlParent) + { + var e = document.createElement('input'); + e.setAttribute('type', 'hidden'); + e.setAttribute('name', 'wlParent'); + ff.appendChild(e); + } + ff.wlParent.setAttribute('value', id); + c.nextSibling ? c.parentNode.insertBefore(f, c.nextSibling) : c.parentNode.appendChild(f); + return false; +}; diff --git a/wikilog-tables.pg.sql b/wikilog-tables.pg.sql new file mode 100644 index 0000000..fff97ff --- /dev/null +++ b/wikilog-tables.pg.sql @@ -0,0 +1,196 @@ +-- Tables used by the MediaWiki Wikilog extension -- PostgreSQL +-- +-- You should not have to create these tables manually unless you are doing +-- a manual installation. In normal conditions, maintenance/update.php should +-- perform any needed database setup. +-- + +-- +-- All existing wikilogs and associated metadata. +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_wikilogs ( + -- Primary key, reference to wikilog front page article. + wlw_page INT NOT NULL, + + -- Serialized PHP object representing the wikilog description or subtitle. + wlw_subtitle TEXT NOT NULL, + + -- Image that provides iconic visual identification of the feed. + wlw_icon VARCHAR(255) NOT NULL, + + -- Image that provides visual identification of the feed. + wlw_logo VARCHAR(255) NOT NULL, + + -- Serialized PHP array of authors. + wlw_authors TEXT NOT NULL, + + -- Last time the wikilog (including posts) was updated. + wlw_updated TIMESTAMPTZ NOT NULL, + + PRIMARY KEY (wlw_page) + +) /*$wgDBTableOptions*/; + +CREATE INDEX /*$wgDBprefix*/wikilog_wikilogs_wlw_updated ON /*$wgDBprefix*/wikilog_wikilogs (wlw_updated); + +-- +-- All wikilog posts and associated metadata. +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_posts ( + -- Primary key, reference to wiki article associated with this post. + wlp_page INT NOT NULL, + + -- Parent wikilog. + wlp_parent INT NOT NULL, + + -- Post title derived from page(page_title), in order to simplify indexing. + wlp_title TEXT NOT NULL, + + -- Either if the post was published or not. + wlp_publish BOOLEAN NOT NULL DEFAULT FALSE, + + -- If wlp_publish = TRUE, this is the date that the post was published, + -- otherwise, it is the date of the last draft revision (for sorting). + wlp_pubdate TIMESTAMPTZ NOT NULL, + + -- Last time the post was updated. + wlp_updated TIMESTAMPTZ NOT NULL, + + -- Serialized PHP array of authors. + wlp_authors TEXT NOT NULL, + + -- Serialized PHP array of tags. + wlp_tags TEXT NOT NULL, + + PRIMARY KEY (wlp_page) +) /*$wgDBTableOptions*/; + +CREATE INDEX /*$wgDBprefix*/wikilog_posts_wlp_parent ON /*$wgDBprefix*/wikilog_posts (wlp_parent); +CREATE INDEX /*$wgDBprefix*/wikilog_posts_wlp_title ON /*$wgDBprefix*/wikilog_posts (wlp_title); +CREATE INDEX /*$wgDBprefix*/wikilog_posts_wlp_pubdate ON /*$wgDBprefix*/wikilog_posts (wlp_pubdate); +CREATE INDEX /*$wgDBprefix*/wikilog_posts_wlp_updated ON /*$wgDBprefix*/wikilog_posts (wlp_updated); + +-- +-- Last visit dates for some Wiki pages (Wikilog posts and comments) +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/page_last_visit ( + pv_user INT NOT NULL, + pv_page INT NOT NULL, + pv_date TIMESTAMPTZ NOT NULL, + PRIMARY KEY (pv_user, pv_page) +) /*$wgDBTableOptions*/; + +-- +-- User subscriptions to posts (like to forum topics) +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_subscriptions ( + ws_user INT NOT NULL, + ws_page INT NOT NULL, + ws_yes BOOLEAN NOT NULL, + ws_date TIMESTAMPTZ NOT NULL, + PRIMARY KEY (ws_user, ws_page) +) /*$wgDBTableOptions*/; + +-- +-- Authors of each post. +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_authors ( + -- Reference to post wiki article which this author is associated to. + wla_page INT NOT NULL, + + -- ID of the author of the post. + wla_author INT NOT NULL, + + -- Name of the author of the post. + wla_author_text VARCHAR(255) NOT NULL, + + PRIMARY KEY (wla_page, wla_author_text) +) /*$wgDBTableOptions*/; + +CREATE INDEX /*$wgDBprefix*/wikilog_authors_wla_page ON /*$wgDBprefix*/wikilog_authors (wla_page); +CREATE INDEX /*$wgDBprefix*/wikilog_authors_wla_author ON /*$wgDBprefix*/wikilog_authors (wla_author); +CREATE INDEX /*$wgDBprefix*/wikilog_authors_wla_author_text ON /*$wgDBprefix*/wikilog_authors (wla_author_text); + +-- +-- Tags associated with each post. +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_tags ( + -- Reference to post wiki article which this tag is associated to. + wlt_page INT NOT NULL, + + -- Tag associated with the post. + wlt_tag VARCHAR(255) NOT NULL, + + PRIMARY KEY (wlt_page, wlt_tag) +) /*$wgDBTableOptions*/; + +CREATE INDEX /*$wgDBprefix*/wikilog_tags_wlt_tag ON /*$wgDBprefix*/wikilog_tags (wlt_tag); + +-- +-- Post comments. +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_comments ( + -- Unique comment identifier, across the whole wiki. + wlc_id SERIAL NOT NULL, + + -- Parent comment, for threaded discussion. NULL for top-level comments. + wlc_parent INT, + + -- Thread history, used for sorting. An array of wlc_id values of all parent + -- comments up to and including the current comment. Each id is padded with + -- zeros to six digits ("000000") and joined with slashes ("/"). + wlc_thread VARCHAR(255) NOT NULL DEFAULT '', + + -- Reference to post wiki article which this comment is associated to. + wlc_post INT NOT NULL, + + -- ID of the author of the comment, if a registered user. + wlc_user INT NOT NULL, + + -- Name of the author of the comment. + wlc_user_text VARCHAR(255) NOT NULL, + + -- Name used for anonymous (not logged in) posters. + wlc_anon_name VARCHAR(255), + + -- Comment status. For hidden or deleted comments, a placeholder is left + -- with some description about what happened to the comment. + -- 'OK' -- OK, comment is visible + -- 'PENDING' -- Comment is pending moderation + -- 'DELETED' -- Comment was deleted + wlc_status VARCHAR(7) NOT NULL DEFAULT 'OK', + + -- Date and time the comment was first posted. + wlc_timestamp TIMESTAMPTZ NOT NULL, + + -- Date and time the comment was edited for the last time. + wlc_updated TIMESTAMPTZ NOT NULL, + + -- Wiki article that contains this comment, to allow editing, revision + -- history and more. This should be joined with `page` and `text` to get + -- the actual comment text. + wlc_comment_page INT, + + PRIMARY KEY (wlc_id) +) /*$wgDBTableOptions*/; + +CREATE INDEX /*$wgDBprefix*/wikilog_comments_wlc_post_thread ON /*$wgDBprefix*/wikilog_comments (wlc_post, wlc_thread); +CREATE INDEX /*$wgDBprefix*/wikilog_comments_wlc_timestamp ON /*$wgDBprefix*/wikilog_comments (wlc_timestamp); +CREATE INDEX /*$wgDBprefix*/wikilog_comments_wlc_updated ON /*$wgDBprefix*/wikilog_comments (wlc_updated); +CREATE INDEX /*$wgDBprefix*/wikilog_comments_wlc_comment_page ON /*$wgDBprefix*/wikilog_comments (wlc_comment_page); + +-- +-- Page talk info, abstracted away from wikilog post concept +-- +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/wikilog_talkinfo ( + -- Primary key, reference to wiki article + wti_page INT NOT NULL, + + -- Timestamp of last comment. + wti_talk_updated TIMESTAMPTZ NOT NULL, + + -- Cached number of comments. + wti_num_comments INT NOT NULL, + + PRIMARY KEY (wti_page) +) /*$wgDBTableOptions*/;