| Current File : /home/jvzmxxx/wiki1/extensions/Flow/includes/Formatter/AbstractFormatter.php |
<?php
namespace Flow\Formatter;
use Flow\Container;
use Flow\FlowActions;
use Flow\Model\Anchor;
use Flow\Model\PostRevision;
use Flow\RevisionActionPermissions;
use Html;
use IContextSource;
use Linker;
use Message;
/**
* This is a "utility" class that might come in useful to generate
* some output per Flow entry, e.g. for RecentChanges, Contributions, ...
* These share a lot of common characteristics (like displaying a date, links to
* the posts, some description of the action, ...)
*
* Just extend from this class to use these common util methods, and make sure
* to pass the correct parameters to these methods. Basically, you'll need to
* create a new method that'll accept the objects for your specific
* implementation (like ChangesList & RecentChange objects for RecentChanges, or
* ContribsPager and a DB row for Contributions). From those rows, you should be
* able to derive the objects needed to pass to these utility functions (mainly
* Workflow, AbstractRevision, Title, User and Language objects) and return the
* output.
*
* For implementation examples, check Flow\RecentChanges\Formatter or
* Flow\Contributions\Formatter.
*/
abstract class AbstractFormatter {
/**
* @var RevisionActionPermissions
*/
protected $permissions;
/**
* @var RevisionFormatter
*/
protected $serializer;
public function __construct( RevisionActionPermissions $permissions, RevisionFormatter $serializer ) {
$this->permissions = $permissions;
$this->serializer = $serializer;
}
abstract protected function getHistoryType();
/**
* @see RevisionFormatter::buildLinks
* @see RevisionFormatter::getDateFormats
*
* @param array $data Expects an array with keys 'dateFormats', 'isModeratedNotLocked'
* and 'links'. The former should be an array having the key $key being
* tossed in here; the latter an array of links in the [key => [href, msg]]
* format, where 'key' corresponds with a $linksKeys value. The central is
* a boolean.
* @param string $key Date format to use - any of the keys in the array
* returned by RevisionFormatter::getDateFormats
* @param string[] $linkKeys Link key(s) to use as link for the timestamp;
* the first available key will be used (but accepts an array of multiple
* keys for when different kinds of data are tossed in, which may not all
* have the same kind of links available)
* @return string HTML
*/
protected function formatTimestamp( array $data, $key = 'timeAndDate', $linkKeys = array( 'header-revision', 'topic-revision', 'post-revision', 'summary-revision' ) ) {
// Format timestamp: add link
$formattedTime = $data['dateFormats'][$key];
// Find the first available link to attach to the timestamp
$anchor = null;
foreach ( $linkKeys as $linkKey ) {
if ( isset( $data['links'][$linkKey] ) ) {
$anchor = $data['links'][$linkKey];
break;
}
}
$class = array( 'mw-changeslist-date' );
if ( $data['isModeratedNotLocked'] ) {
$class[] = 'history-deleted';
}
if ( $anchor instanceof Anchor ) {
return Html::rawElement(
'span',
array( 'class' => $class ),
$anchor->toHtml( $formattedTime )
);
} else {
return Html::element( 'span', array( 'class' => $class ), $formattedTime );
}
}
/**
* Generate HTML for "(foo | bar | baz)" based on the links provided by
* RevisionFormatter.
*
* @param array $links Contains any combination of Anchor|Message|string
* @param IContextSource $ctx
* @param string[] $request List of link names to be allowed in result output
* @return string Html valid for user output
*/
protected function formatAnchorsAsPipeList( array $links, IContextSource $ctx, array $request = null ) {
if ( $request === null ) {
$request = array_keys( $links );
} elseif ( !$request ) {
// empty array was passed
return '';
}
$have = array_combine( $request, $request );
$formatted = array();
foreach ( $links as $key => $link ) {
if ( isset( $have[$key] ) ) {
if ( $link instanceof Anchor ) {
$formatted[] = $link->toHtml();
} elseif( $link instanceof Message ) {
$formatted[] = $link->escaped();
} else {
// plain text
$formatted[] = htmlspecialchars( $key );
}
}
}
if ( $formatted ) {
$content = $ctx->getLanguage()->pipeList( $formatted );
if ( $content ) {
return $ctx->msg( 'parentheses' )->rawParams( $content )->escaped();
}
}
return '';
}
/**
* Gets the "diff" link; linking to the diff against the previous revision,
* in a format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
* @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
protected function getDiffAnchor( array $input, IContextSource $ctx ) {
if ( !isset( $input['diff'] ) ) {
// plain text with no link
return $ctx->msg( 'diff' );
}
return $input['diff'];
}
/**
* Gets the "prev" link; linking to the diff against the previous revision,
* in a format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
* @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
protected function getDiffPrevAnchor( array $input, IContextSource $ctx ) {
if ( !isset( $input['diff-prev'] ) ) {
// plain text with no link
return $ctx->msg( 'last' );
}
return $input['diff-prev'];
}
/**
* Gets the "cur" link; linking to the diff against the current revision,
* in a format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
* @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
protected function getDiffCurAnchor( array $input, IContextSource $ctx ) {
if ( !isset( $input['diff-cur'] ) ) {
// plain text with no link
return $ctx->msg( 'cur' );
}
return $input['diff-cur'];
}
/**
* Gets the "hist" link; linking to the history of a certain element, in a
* format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
* @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
protected function getHistAnchor( array $input, IContextSource $ctx ) {
if ( isset( $input['post-history'] ) ) {
$anchor = $input['post-history'];
} elseif ( isset( $input['topic-history'] ) ) {
$anchor = $input['topic-history'];
} elseif ( isset( $input['board-history'] ) ) {
$anchor = $input['board-history'];
} else {
$anchor = null;
}
if ( $anchor instanceof Anchor ) {
$anchor->setMessage( wfMessage( 'hist' ) );
return $anchor;
} else {
// plain text with no link
return $ctx->msg( 'hist' );
}
}
/**
* @return string Html valid for user output
*/
protected function changeSeparator() {
return ' <span class="mw-changeslist-separator">. .</span> ';
}
/**
* @param array $data
* @param IContextSource $ctx
* @return Message
*/
protected function getDescription( array $data, IContextSource $ctx ) {
// Build description message, piggybacking on history i18n
$changeType = $data['changeType'];
$actions = $this->permissions->getActions();
$key = $actions->getValue( $changeType, 'history', 'i18n-message' );
// find specialized message for this particular formatter type
// E.g. the -irc messages.
$msg = $ctx->msg( $key . '-' . $this->getHistoryType() );
if ( !$msg->exists() ) {
// fallback to default msg
$msg = $ctx->msg( $key );
}
return $msg->params( $this->getDescriptionParams( $data, $actions, $changeType ) );
}
/**
* @param array $data
* @param FlowActions $actions
* @param string $changeType
* @return array
*/
protected function getDescriptionParams( array $data, FlowActions $actions, $changeType ) {
$source = $actions->getValue( $changeType, 'history', 'i18n-params' );
$params = array();
foreach ( $source as $param ) {
if ( isset( $data['properties'][$param] ) ) {
$params[] = $data['properties'][$param];
} else {
wfDebugLog( 'Flow', __METHOD__ . ": Missing expected parameter $param for change type $changeType" );
$params[] = '';
}
}
return $params;
}
/**
* Generate an HTML revision description.
*
* @param array $data
* @param IContextSource $ctx
* @return string Html valid for user output
*/
protected function formatDescription( array $data, IContextSource $ctx ) {
$msg = $this->getDescription( $data, $ctx );
return '<span class="plainlinks">' . $msg->parse() . '</span>';
}
/**
* Returns HTML links to the page title and (if the action is topic-related)
* the topic.
*
* @param array $data
* @param FormatterRow $row
* @param IContextSource $ctx
* @return string HTML linking to topic & board
*/
protected function getTitleLink( array $data, FormatterRow $row, IContextSource $ctx ) {
$ownerLink = Linker::link(
$row->workflow->getOwnerTitle(),
null,
array( 'class' => 'mw-title' )
);
if ( !isset( $data['links']['topic'] ) || !$row->revision instanceof PostRevision ) {
return $ownerLink;
}
/** @var Anchor $topic */
$topic = $data['links']['topic'];
// generated link has generic link text, should be actual topic title
$root = $row->revision->getRootPost();
if ( $root && $this->permissions->isAllowed( $root, 'view' ) ) {
$topicDisplayText = Container::get( 'templating' )->getContent( $root, 'topic-title-plaintext' );
$topic->setMessage( $topicDisplayText );
}
return $ctx->msg( 'flow-rc-topic-of-board' )->rawParams(
$topic->toHtml(),
$ownerLink
)->escaped();
}
}