Extension:Multiplicator/code/Multiplicator.page.php

From MediaWiki.org
Jump to: navigation, search

[edit] Multiplicator.page.php

<?php
 
/**
 * Special page class for the Multiplicator extension
 *
 * @addtogroup Extensions
 * @author Al Maghi <alfred.maghi@gmail.com>
 * Duplicator code from Rob Church <robchur@gmail.com>
 */
 
class SpecialMultiplicator extends SpecialPage {
 
        /**
         * Title of the page we are duplicating
         */
        private $source = '';
        private $sourceTitle = NULL;
 
        /**
         * Title of the page we are saving to
         */
        private $dest = '';
        private $destTitle = NULL;
 
        /**
         * Number of copie(s) we are saving
         */     
        private $times = 0;
 
        /**
         * Whether or not we're duplicating the talk page
         */
        private $talk = true;
 
        /**
         * Constructor
         */
        public function __construct() {
                parent::__construct( 'Multiplicator' );
        }
 
        /**
         * Main execution function
         *
         * @param $title Title passed to the page
         */
        public function execute( $title ) {
                global $wgUser, $wgOut, $wgRequest, $wgLang, $wgMultiplicatorRevisionLimit;
                wfLoadExtensionMessages( 'Multiplicator' );
                $this->setHeaders();
 
                # Check permissions
                if( !$wgUser->isAllowed( 'multiplicate' ) ) {
                        $wgOut->permissionRequired( 'multiplicate' );
                        return;
                }
 
                # Check for database lock
                if( wfReadOnly() ) {
                        $wgOut->readOnlyPage();
                        return;
                }
 
                $this->setOptions( $wgRequest, $title );
                $wgOut->addWikiMsg( 'duplicator-header' );
                $wgOut->addHTML( $this->buildForm() );
 
                # If the token doesn't match or the form wasn't POSTed, stop
                if( !$wgRequest->wasPosted() || !$wgUser->matchEditToken( $wgRequest->getVal( 'token' ), 'multiplicator' ) )
                        return;
 
                # Check we've got a valid source title
                if( !is_object( $this->sourceTitle ) ) {
                        # Invalid source title
                        $wgOut->addWikiMsg( 'duplicator-source-invalid' );
                        return;
                }
 
                # Check the source exists
                if( !$this->sourceTitle->exists() ) {
                        # Source doesn't exist
                        $wgOut->addWikiMsg( 'duplicator-source-notexist', $this->source );
                        return;
                }
 
                # Check we've got a valid destination title
                if( !is_object( $this->destTitle ) ) {
                        # Invalid destination title
                        $wgOut->addWikiMsg( 'duplicator-dest-invalid' );
                        return;
                }
 
                # Check the destination *does not* exist
                if( $this->destTitle->exists() ) {
                        # Destination exists
                        $wgOut->addWikiMsg( 'duplicator-dest-exists', $this->destTitle->getPrefixedText() );
                        return;
                }
 
                # Check there aren't a hideous number of revisions
                $dbr = wfGetDB( DB_SLAVE );
                $num = $dbr->selectField( 'revision', 'COUNT(*)',array( 'rev_page' => $this->sourceTitle->getArticleID() ), __METHOD__ );
                if( $num <= $wgMultiplicatorRevisionLimit ) {
                        # Attempt to perform the main duplicate op. first
                        if( $this->duplicate( $this->sourceTitle, $this->destTitle ) ) {
                                $success  = wfMsgNoTrans( 'duplicator-success', $this->sourceTitle->getPrefixedText(), $this->destTitle->getPrefixedText() ) . "\n\n";
                                $success .= '* ' . wfMsgNoTrans( 'duplicator-success-revisions', $wgLang->formatNum( $num ) ) . "\n";
                                //$success .= '' . wfMsgNoTrans( 'duplicator-success-subpages', $times ) . "\n";
                                # If there is a talk page and we've been asked to duplicate it, do so
                                if( $this->dealWithTalk() && $this->talk ) {
                                        if( $this->duplicate( $this->sourceTitle->getTalkPage(), $this->destTitle->getTalkPage() ) ) {
                                                $success .= '* ' . wfMsgNoTrans( 'duplicator-success-talkcopied' ) . "\n";
                                        } else {
                                                $success .= '* ' . wfMsgNoTrans( 'duplicator-success-talknotcopied' ) . "\n";
                                        }
                                }
                                # Report success to the user
                                $parsed = $wgOut->parse( $success, /*linestart*/true, /*uilang*/true );
                                $wgOut->addHTML( $parsed );
                        } else {
                                # Something went wrong, abort the entire operation
                                $wgOut->addWikiMsg( 'duplicator-failed' );
                        }
                } else {
                        # Revision count exceeds limit
                        $limit = $wgLang->formatNum( $wgMultiplicatorRevisionLimit );
                        $actual = $wgLang->formatNum( $num );
                        $stitle = $this->sourceTitle->getPrefixedText();
                        $wgOut->addWikiMsg( 'duplicator-toomanyrevisions', $stitle, $actual, $limit );
                }
 
        }
 
        /**
         * Determine various options and attempt initialisation of objects
         *
         * @param $request WebRequest we're running off
         * @param $title Title passed to the page
         */
        private function setOptions( &$request, $title ) {
                $source = $request->getText( 'source' );
                $this->source = $source ? $source : ( $title ? $title : '' );
                $this->sourceTitle = Title::newFromUrl( $this->source );
                $this->dest = $request->getText( 'dest', '' );
                $this->destTitle = Title::newFromUrl( $this->dest );
                $this->talk = $request->getCheck( 'talk' );
                $times = $request->getText( 'times', '' );
 
        }
 
        /**
         * Should we allow the user to see the talk page option?
         * Don't bother if there is no talk page, or we're duplicating one
         *
         * @return bool
         */
        private function dealWithTalk() {
                if( is_object( $this->sourceTitle ) ) {
                        if( $this->sourceTitle->isTalkPage() )
                                return false;
                        $talk = $this->sourceTitle->getTalkPage();
                        return $talk->exists();
                } else {
                        # We can't determine, but it doesn't matter; either the user
                        # hasn't hit the submit button, or we'll be throwing up a bad title error
                        return true;
                }
        }
 
        /**
         * Build a form for entering the source and destination titles
         *
         * @return string
         */
        private function buildForm() {
                global $wgUser;
                $self = SpecialPage::getTitleFor( 'multiplicator' );
                $source = is_object( $this->sourceTitle ) ? $this->sourceTitle->getPrefixedText() : $this->source;
                $dest = is_object( $this->destTitle ) ? $this->destTitle->getPrefixedText() : $this->dest;
                $form  = '<form method="post" action="' . $self->getLocalUrl() . '">';
                $form .= '<fieldset><legend>' . wfMsgHtml( 'duplicator-options' ) . '</legend>';
                $form .= '<table>';
                $form .= '<tr>';
                $form .= '<td><label for="source">' . wfMsgHtml( 'duplicator-source' ) . '</label></td>';
                $form .= '<td>' . Xml::input( 'source', 40, $source, array( 'id' => 'source' ) ) . '</td>';
                $form .= '</tr><tr>';
                $form .= '<td><label for="dest">' . wfMsgHtml( 'duplicator-dest' ) . '</label></td>';
                $form .= '<td>' . Xml::input( 'dest', 40, $dest, array( 'id' => 'dest' ) ) . '</td>';
                $form .= '</tr><tr>';
                $form .= '<td><label for="times">' . wfMsgHtml( 'multiplicator-times' ) . '</label></td>';
                $form .= '<td>' . Xml::openElement( 'select', array( 'name' => 'times' ) ) 
                                                . Xml::option( wfMsg( "multiplicator-select1" ), 1 ) 
                                                . Xml::option( wfMsg( "multiplicator-select2" ), 2 )
                                                . Xml::option( wfMsg( "multiplicator-select3" ), 3 )
                                                . Xml::option( wfMsg( "multiplicator-select4" ), 4 )
                                                . Xml::option( wfMsg( "multiplicator-select5" ), 5 )
                                                . Xml::option( wfMsg( "multiplicator-select6" ), 6 )
                                                . Xml::option( wfMsg( "multiplicator-select7" ), 7 )
                                                . Xml::option( wfMsg( "multiplicator-select8" ), 8 )
                                                . Xml::option( wfMsg( "multiplicator-select9" ), 9 )
                                                . Xml::option( wfMsg( "multiplicator-select10" ), 10 )
                                                . Xml::closeElement( 'select' ) . '</td>';
                $form .= '</tr><tr>';
                $form .= '<td>&nbsp;</td>';
                $form .= '<td>' . Xml::checkLabel( wfMsg( 'duplicator-dotalk' ), 'talk', 'talk', $this->talk ) . '</td>';
                $form .= '</tr><tr>';
                $form .= '<td>&nbsp;</td>';
                $form .= '<td>' . Xml::submitButton( wfMsg( 'duplicator-submit' ) ) . '</td>';
                $form .= '</tr>';
                $form .= '</table>';
                $form .= Xml::hidden( 'token', $wgUser->editToken( 'multiplicator' ) );
                $form .= '</fieldset></form>';
                return $form;
        }
 
        /**
         * Duplicate one page to another, including full histories
         * Does some basic error-catching, but not as much as the code above [should]
         *
         * @param $source Title to duplicate
         * @param $dest Title to save to
         * @return bool
         */
                private function duplicate( &$source, &$dest ) {
                        global $wgUser, $wgBot;
                        if( !$source->exists() || $dest->exists() )
                                return false; # Source doesn't exist, or destination does
                        $dbw = wfGetDB( DB_MASTER );
                        $dbw->begin();
                        $sid = $source->getArticleID();
                        # Create an article representing the destination page and save it
                        $destArticle = new Article( $dest );
                        $aid = $destArticle->insertOn( $dbw );
 
 
                        # Perform the revision duplication
                        # An INSERT...SELECT here seems to fuck things up
                        $res = $dbw->select( 'revision', '*', array( 'rev_page' => $sid ), __METHOD__ );
                        if( $res && $dbw->numRows( $res ) > 0 ) {
                                while( $row = $dbw->fetchObject( $res ) ) {
                                        $values['rev_page'] = $aid;
                                        $values['rev_text_id'] = $row->rev_text_id;
                                        $values['rev_comment'] = $row->rev_comment;
                                        $values['rev_user'] = $row->rev_user;
                                        $values['rev_user_text'] = $row->rev_user_text;
                                        $values['rev_timestamp'] = $row->rev_timestamp;
                                        $values['rev_minor_edit'] = $row->rev_minor_edit;
                                        $values['rev_deleted'] = $row->rev_deleted;
                                        $dbw->insert( 'revision', $values, __METHOD__ );
                                }
                                $dbw->freeResult( $res );
                        }
                        # Update page record
                        $latest = $dbw->selectField( 'revision', 'MAX(rev_id)', array( 'rev_page' => $aid ), __METHOD__ );
                        $rev = Revision::newFromId( $latest );
                        $destArticle->updateRevisionOn( $dbw, $rev );
                        # Commit transaction
                        $dbw->commit();
                        # Create a null revision with an explanation; do cache clearances, etc.
                        $dbw->begin();
                        $comment = wfMsgForContent( 'duplicator-summary', $source->getPrefixedText() );
                        $nr = Revision::newNullRevision( $dbw, $aid, $comment, true );
                        $nid = $nr->insertOn( $dbw );
                        $destArticle->updateRevisionOn( $dbw, $nr );
                        $destArticle->createUpdates( $nr );
                        Article::onArticleCreate( $dest );
                        $bot = $wgUser->isAllowed( 'bot' );
                        RecentChange::notifyNew( $nr->getTimestamp(), $dest, true, $wgUser, $comment, $bot );
                        $dest->invalidateCache();
                        $dbw->commit();
                        return true;
 
                }
        }
Personal tools
Namespaces

Variants
Actions
Navigation
Support
Download
Development
Communication
Print/export
Toolbox