%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /www/varak.net/wiki.varak.net/extensions/MobileFrontend/includes/specials/
Upload File :
Create Path :
Current File : /www/varak.net/wiki.varak.net/extensions/MobileFrontend/includes/specials/SpecialMobileDiff.php

<?php

/**
 * Show the difference between two revisions of a page
 */
class SpecialMobileDiff extends MobileSpecialPage {
	/** @var boolean $hasDesktopVersion Does this special page has a desktop version? */
	protected $hasDesktopVersion = true;
	/** @var integer $revId Saves the actual revision ID */
	private $revId;
	/** @var Revision $rev Saves the revision Object of actual revision */
	private $rev;
	/** @var Revision $prevRev Saves the previous revision */
	private $prevRev;
	/** @var Title Saves the title of the actual revision */
	private $targetTitle;
	/**
	 * @var InlineDifferenceEngine|DifferenceEngine $mDiffEngine
	 * DifferenceEngine for this Diff-page
	 */
	protected $mDiffEngine;

	/**
	 * Construct function
	 */
	public function __construct() {
		parent::__construct( 'MobileDiff' );
	}

	/**
	 * Get the revision object from ID
	 * @param int $id ID of the wanted revision
	 * @return Revision
	 */
	public static function getRevision( $id ) {
		return Revision::newFromId( $id );
	}

	/**
	 * Generate a 404 Error message, that revisions can not be found
	 */
	public function executeBadQuery() {
		wfHttpError( 404, $this->msg( 'mobile-frontend-diffview-404-title' )->text(),
			$this->msg( 'mobile-frontend-diffview-404-desc' )->text() );
	}

	/**
	 * Takes 2 ids/keywords and validates them returning respective revisions
	 *
	 * @param int[] $revids Array of revision ids currently limited to 2 elements
	 * @return Revision[]|null[] Array of previous and next revision. The next revision is null if
	 *   a bad parameter is passed
	 */
	public function getRevisionsToCompare( $revids ) {
		$prev = null;
		$rev = null;

		// check 2 parameters are passed and are numbers
		if ( count( $revids ) === 2 && $revids[0] && $revids[1] ) {
			$id = (int)$revids[1];
			$prevId = (int)$revids[0];
			if ( $id && $prevId ) {
				$rev = static::getRevision( $id );
				// deal with identical ids
				if ( $id === $prevId ) {
					$rev = null;
				} elseif ( $rev ) {
					$prev = static::getRevision( $prevId );
					if ( !$prev ) {
						$rev = null;
					}
				} else {
					$rev = null;
				}
			}
		} elseif ( count( $revids ) === 1 ) {
			$id = (int)$revids[0];
			if ( $id ) {
				$rev = static::getRevision( $id );
				if ( $rev ) {
					$prev = $rev->getPrevious();
				}
			}
		}
		return [ $prev, $rev ];
	}

	/**
	 * Render the diff page
	 * @return bool false when revision not exist
	 * @param string $par Revision IDs separated by three points (e.g. 123...124)
	 */
	public function executeWhenAvailable( $par ) {
		$ctx = MobileContext::singleton();
		$this->setHeaders();
		$output = $this->getOutput();

		// @FIXME add full support for git-style notation (eg ...123, 123...)
		$revisions = $this->getRevisionsToCompare( explode( '...', $par ) );
		$rev = $revisions[1];
		$prev = $revisions[0];

		if ( $rev === null ) {
			$this->executeBadQuery();
			return false;
		}
		$this->revId = $rev->getId();
		$this->rev = $rev;
		$this->prevRev = $prev;
		$this->targetTitle = $this->rev->getTitle();
		$this->getSkin()->setRelevantTitle( $this->targetTitle );

		$output->setPageTitle( $this->msg(
			'mobile-frontend-diffview-title',
			$this->targetTitle->getPrefixedText()
		) );

		$output->addModuleStyles( [
			'mobile.special.user.icons',
			'mobile.pagesummary.styles',
			// @todo FIXME: Don't add these styles. This is only needed for the user
			// icon to the left of the username
			'mobile.special.pagefeed.styles'
		] );
		$output->addModules( 'mobile.special.mobilediff.scripts' );

		// Allow other extensions to load more stuff here
		Hooks::run( 'BeforeSpecialMobileDiffDisplay', [ &$output, $ctx, $revisions ] );

		$output->addHTML( '<div id="mw-mf-diffview" class="content-unstyled"><div id="mw-mf-diffarea">' );

		$this->displayDiffPage();
		$output->addHTML( '</div>' );

		$this->showFooter( $ctx, $this->getRequest()->getBool( 'unhide' ) );

		$output->addHTML( '</div>' );

		return true;
	}

	/**
	 * Returns the ID of the previous Revision, if it is set, otherwise 0.
	 *
	 * @return int|null
	 */
	protected function getPrevId() {
		return $this->prevRev ? $this->prevRev->getId() : 0;
	}

	/**
	 * Setups the mobile DifferenceEngine and displays a mobile optimised diff.
	 */
	protected function displayDiffPage() {
		$unhide = $this->getRequest()->getBool( 'unhide' );
		$contentHandler = $this->rev->getContentHandler();
		$this->mDiffEngine = $contentHandler->createDifferenceEngine( $this->getContext(),
		$this->getPrevId(), $this->revId, 0, false, $unhide );
		$this->showHeader( $unhide );
		$this->mDiffEngine->showDiffPage();
	}

	/**
	 * Render the header of a diff page including:
	 * Navigation links
	 * Name with url to page
	 * Bytes added/removed
	 * Day and time of edit
	 * Edit Comment
	 */
	private function showHeader( $unhide = false ) {
		if ( $this->rev->isMinor() ) {
			$minor = ChangesList::flag( 'minor' );
		} else {
			$minor = '';
		}
		$this->getOutput()->addHTML(
			$this->getRevisionNavigationLinksHTML() .
			$this->getIntroHTML() .
			$minor .
			$this->getCommentHTML( $unhide )
		);
	}

	/**
	 * Get the edit comment
	 * @return string Build HTML for edit comment section
	 */
	private function getCommentHTML( $unhide = false ) {
		$audience = $unhide ? Revision::FOR_THIS_USER : Revision::FOR_PUBLIC;
		$comment = $this->rev->getComment( $audience );

		if ( $this->rev->isDeleted( Revision::DELETED_COMMENT ) && !$unhide ) {
			$commentHtml = $this->msg( 'rev-deleted-comment' )->escaped();
		} elseif ( $comment !== '' && $comment !== null ) {
			$commentHtml = Linker::formatComment( $comment, $this->targetTitle );
		} else {
			$commentHtml = $this->msg( 'mobile-frontend-changeslist-nocomment' )->escaped();
		}

		return Html::rawElement(
			'div',
			[ 'id' => 'mw-mf-diff-comment' ],
			$commentHtml
		);
	}

	/**
	 * Get the intro HTML
	 * @return string Built HTML for intro section
	 */
	private function getIntroHTML() {
		if ( $this->prevRev ) {
			$bytesChanged = $this->rev->getSize() - $this->prevRev->getSize();
		} else {
			$bytesChanged = $this->rev->getSize();
		}
		if ( $bytesChanged > 0 ) {
			$changeMsg = 'mobile-frontend-diffview-bytesadded';
			$sizeClass = MobileUI::iconClass( 'bytesadded', 'before',
				'meta mw-mf-bytesadded mw-ui-icon-small' );
		} elseif ( $bytesChanged === 0 ) {
			$changeMsg = 'mobile-frontend-diffview-bytesnochange';
			$sizeClass = MobileUI::iconClass( 'bytesneutral', 'before',
				'meta mw-mf-bytesneutral mw-ui-icon-small' );
		} else {
			$changeMsg = 'mobile-frontend-diffview-bytesremoved';
			$sizeClass = MobileUI::iconClass( 'bytesremoved', 'before',
				'meta mw-mf-bytesremoved mw-ui-icon-small' );
			$bytesChanged = abs( $bytesChanged );
		}
		$ts = new MWTimestamp( $this->rev->getTimestamp() );

		return Html::openElement( 'div', [ 'id' => 'mw-mf-diff-info', 'class' => 'page-summary' ] )
			. Html::openElement( 'h2' )
				. Html::element( 'a',
					[
						'href' => $this->targetTitle->getLocalURL( [
							'oldid' => $this->revId,
						] )
					],
					$this->targetTitle->getPrefixedText()
				)
			. Html::closeElement( 'h2' )
			. $this->msg( 'mobile-frontend-diffview-comma' )->rawParams(
				Html::element( 'span', [ 'class' => $sizeClass ],
					$this->msg( $changeMsg )->numParams( $bytesChanged )->text()
				),
				Html::element(
					'span', [ 'class' => 'mw-mf-diff-date meta' ],
					$this->getLanguage()->getHumanTimestamp( $ts )
				)
			)->parse()
		. Html::closeElement( 'div' );
	}

	/**
	 * Render the revision navigation links
	 * @return string built HTML for Revision navigation links
	 */
	private function getRevisionNavigationLinksHTML() {
		$prev = $this->rev->getPrevious();
		$next = $this->rev->getNext();
		$history = '';

		if ( $prev || $next ) {
			$history = Html::openElement( 'ul', [ 'class' => 'hlist revision-history-links' ] );
			if ( $prev ) {
				$history .= Html::openElement( 'li', [ 'class' => 'revision-history-prev' ] )
					. Html::element( 'a', [
						'href' => SpecialPage::getTitleFor( 'MobileDiff', $prev->getId() )
							->getLocalURL()
					], $this->msg( 'previousdiff' )->text() ) . Html::closeElement( 'li' );
			}
			if ( $next ) {
				$history .= Html::openElement( 'li', [ 'class' => 'revision-history-next' ] )
					. Html::element( 'a', [
						'href' => SpecialPage::getTitleFor( 'MobileDiff', $next->getId() )
							->getLocalURL()
					], $this->msg( 'nextdiff' )->text() ) . Html::closeElement( 'li' );
			}
			$history .= Html::closeElement( 'ul' );
		}
		return $history;
	}

	/**
	 * Render the footer including userinfos (Name, Role, Editcount)
	 *
	 * @param IContextSource $context
	 * @param bool $unhide whether hidden content should be shown
	 */
	private function showFooter( IContextSource $context, $unhide ) {
		$output = $this->getOutput();

		$output->addHTML(
			Html::openElement( 'div', [ 'id' => 'mw-mf-userinfo',
				'class' => 'position-fixed' ] ) .
			Html::openElement( 'div', [ 'class' => 'post-content' ] )
		);

		$audience = $unhide ? Revision::FOR_THIS_USER : Revision::FOR_PUBLIC;
		$userId = $this->rev->getUser( $audience );
		$ipAddr = $this->rev->getUserText( $audience );

		// Note $userId will be 0 and $ipAddr an empty string if the current audience cannot see it.
		if ( $userId ) {
			$user = User::newFromId( $userId );
			$edits = $user->getEditCount();
			$attrs = [
				'class' => MobileUI::iconClass( 'user', 'before', 'mw-mf-user' ),
				'data-revision-id' => $this->revId,
				'data-user-name' => $user->getName(),
				'data-user-gender' => $user->getOption( 'gender' ),
			];
			// Note we do not use LinkRenderer here as this will render
			// a broken link if the user page does not exist
			$output->addHTML(
				Html::openElement( 'div', $attrs ) .
				$this->getLinkRenderer()->makeLink(
					$user->getUserPage(),
					$user->getName(),
					[ 'class' => 'mw-mf-user-link' ],
					// T197581: Override red linking so that the user page is always accessible
					// for user pages that do not exist. We want to allow access to contributions
					[ 'action' => 'view' ]
				) .
				'</div>' .
				'<div class="mw-mf-roles meta">' .
					$this->listGroups( $user, $context ) .
				'</div>' .
				'<div class="mw-mf-edit-count meta">' .
					$this->msg(
						'mobile-frontend-diffview-editcount',
						$this->getLanguage()->formatNum( $edits )
					)->parse() .
				'</div>'
			);
		} elseif ( $ipAddr ) {
			$userPage = SpecialPage::getTitleFor( 'Contributions', $ipAddr );
			$output->addHTML(
				Html::element( 'div', [
					'class' => MobileUI::iconClass( 'anonymous', 'before', 'mw-mf-user mw-mf-anon' ),
				], $this->msg( 'mobile-frontend-diffview-anonymous' )->text() ) .
				'<div>' .
					$this->getLinkRenderer()->makeLink( $userPage, $ipAddr ) .
				'</div>'
			);
		} else {
			// Case where the user cannot see who made the edit
			$output->addHTML(
				$this->msg( 'rev-deleted-user' )->escaped()
			);
		}

		$output->addHTML(
			Html::closeElement( 'div' ) .
			Html::closeElement( 'div' )
		);
	}

	/**
	 * Get the list of groups of user
	 * @param User $user The user object to get the list from
	 * @param IContextSource $context
	 * @return string comma separated list of user groups
	 */

	private function listGroups( User $user, IContextSource $context ) {
		// Get groups to which the user belongs
		$userGroups = $user->getGroups();
		$userMembers = [];
		foreach ( $userGroups as $group ) {
			$userMembers[] = UserGroupMembership::getLink( $group, $context, 'html' );
		}

		return $this->getLanguage()->commaList( $userMembers );
	}

	/**
	 * Get the url for the mobile diff special page to use in Desktop footer
	 * @return bool|string Return URL or false when revision id's not set
	 */
	public static function getMobileUrlFromDesktop() {
		$req = MobileContext::singleton()->getRequest();
		$rev2 = $req->getText( 'diff' );
		$rev1 = $req->getText( 'oldid' );
		// Actually, both do the same, WTF
		if ( $rev1 == 'prev' || $rev1 == 'next' ) {
			$rev1 = '';
		}
		// redirect requests to the diff page to mobile view
		if ( !$rev2 ) {
			if ( $rev1 ) {
				$rev2 = $rev1;
				$rev1 = '';
			} else {
				return false;
			}
		}

		if ( $rev1 ) {
			$rev = static::getRevision( $rev1 );
			if ( $rev ) {
				// the diff parameter could be the string prev or next - deal with these cases
				if ( $rev2 === 'prev' ) {
					$prev = $rev->getPrevious();
					// yes this is confusing - this is how it works arrgghh
					$rev2 = $rev1;
					$rev1 = $prev ? $prev->getId() : '';
				} elseif ( $rev2 === 'next' ) {
					$next = $rev->getNext();
					$rev2 = $next ? $next->getId() : '';
				} else {
					$rev2 = static::getRevision( $rev2 );
					$rev2 = $rev2 ? $rev2->getId() : '';
				}
			} else {
				$rev2 = '';
			}
		}

		if ( $rev2 ) {
			$subpage = $rev1 ? $rev1 . '...' . $rev2 : $rev2;
			$title = SpecialPage::getTitleFor( 'MobileDiff', $subpage );
			return $title->getLocalURL();
		}
		return false;
	}

	/**
	 * Get the URL for Desktop version of difference view
	 * @param string $subPage URL of mobile diff page
	 * @return string Url to mobile diff page
	 */
	public function getDesktopUrl( $subPage ) {
		$parts = explode( '...', $subPage );
		if ( count( $parts ) > 1 ) {
			$params = [ 'diff' => $parts[1], 'oldid' => $parts[0] ];
		} else {
			$params = [ 'diff' => $parts[0] ];
		}
		if ( $this->getRequest()->getVal( 'unhide' ) ) {
			$params['unhide'] = 1;
		}
		return wfAppendQuery( wfScript(), $params );
	}
}

Zerion Mini Shell 1.0