Matthias Mullie has uploaded a new change for review.
https://gerrit.wikimedia.org/r/102674
Change subject: (bug 58645) Merge RecentChanges & Contributions' formatters
extend from 1 same base class
......................................................................
(bug 58645) Merge RecentChanges & Contributions' formatters extend from 1 same
base class
Bug: 58645
Change-Id: I8392302e016673f02bf495fd6ae156a9334262ab
---
M Flow.php
M container.php
M includes/Contributions/Formatter.php
A includes/Formatter.php
M includes/RecentChanges/Formatter.php
5 files changed, 483 insertions(+), 589 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow
refs/changes/74/102674/1
diff --git a/Flow.php b/Flow.php
index 7c33908..3d85ca0 100755
--- a/Flow.php
+++ b/Flow.php
@@ -121,6 +121,7 @@
$wgAutoloadClasses['Flow\Data\HeaderRecentChanges'] = $dir .
'includes/Data/RecentChanges.php';
$wgAutoloadClasses['Flow\Data\Merger'] = $dir .
'includes/Data/RevisionStorage.php';
$wgAutoloadClasses['Flow\Data\RawSql'] = $dir .
'includes/Data/ObjectManager.php';
+$wgAutoloadClasses['Flow\AbstractFormatter'] = $dir . 'includes/Formatter.php';
$wgAutoloadClasses['Flow\RecentChanges\Formatter'] = $dir .
'includes/RecentChanges/Formatter.php';
$wgAutoloadClasses['Flow\Log\Logger'] = $dir . 'includes/Log/Logger.php';
$wgAutoloadClasses['Flow\Log\Formatter'] = $dir . 'includes/Log/Formatter.php';
diff --git a/container.php b/container.php
index ed299b3..cddabdb 100644
--- a/container.php
+++ b/container.php
@@ -385,13 +385,11 @@
} );
$c['recentchanges.formatter'] = $c->share( function( $c ) {
- global $wgLang;
return new Flow\RecentChanges\Formatter(
$c['storage'],
$c['factory.loader.workflow'],
$c['flow_actions'],
- $c['templating'],
- $wgLang
+ $c['templating']
);
} );
diff --git a/includes/Contributions/Formatter.php
b/includes/Contributions/Formatter.php
index 7db6fe3..4e675f9 100644
--- a/includes/Contributions/Formatter.php
+++ b/includes/Contributions/Formatter.php
@@ -2,69 +2,11 @@
namespace Flow\Contributions;
+use Flow\AbstractFormatter;
use ContribsPager;
-use Flow\Model\AbstractRevision;
-use Flow\Model\Workflow;
-use Flow\Block\AbstractBlock;
-use Flow\Data\ManagerGroup;
-use Flow\FlowActions;
-use Flow\Model\UUID;
-use Flow\Templating;
-use Flow\UrlGenerator;
-use Flow\WorkflowLoaderFactory;
-use Language;
use Html;
-use Title;
-use User;
-use ChangesList;
-class Formatter {
- /**
- * @var ManagerGroup
- */
- protected $storage;
-
- /**
- * @var WorkflowLoaderFactory
- */
- protected $workflowLoaderFactory;
-
- /**
- * @var FlowActions
- */
- protected $actions;
-
- /**
- * @var Templating
- */
- protected $templating;
-
- /**
- * @var UrlGenerator;
- */
- protected $urlGenerator;
-
- /**
- * @var Language
- */
- protected $lang;
-
- /**
- * @param ManagerGroup $storage
- * @param WorkflowLoaderFactory $workflowLoaderFactory
- * @param FlowActions $actions
- * @param Templating $templating
- * @param Language $lang
- */
- public function __construct( ManagerGroup $storage,
WorkflowLoaderFactory $workflowLoaderFactory, FlowActions $actions, Templating
$templating ) {
- $this->actions = $actions;
- $this->storage = $storage;
- $this->workflowLoaderFactory = $workflowLoaderFactory;
- $this->templating = $templating;
-
- $this->urlGenerator = $this->templating->getUrlGenerator();
- }
-
+class Formatter extends AbstractFormatter {
/**
* @param ContribsPager $pager
* @param stdClass $row
@@ -98,12 +40,12 @@
// Format timestamp: add link
$formattedTime = $dateFormats['timeAndDate'];
if ( $links ) {
- list( $url, $message ) = $links[count( $links ) - 1];
+ list( $url, $text ) = $links[count( $links ) - 1];
$formattedTime = Html::element(
'a',
array(
'href' => $url,
- 'title' => $message->text()
+ 'title' => $text
),
$formattedTime
);
@@ -118,14 +60,14 @@
// Format links
foreach ( $links as &$link ) {
- list( $url, $message ) = $link;
+ list( $url, $text ) = $link;
$link = Html::element(
'a',
array(
'href' => $url,
- 'title' => $message->text()
+ 'title' => $text
),
- $message->text()
+ $text
);
}
$linksContent = $lang->pipeList( $links );
@@ -139,224 +81,5 @@
$linksContent . ' . . ' .
$charDiff . ' . . ' .
$description;
- }
-
- protected function buildActionLinks( Title $title, $action, UUID
$workflowId, UUID $postId = null ) {
- $links = array();
- switch( $action ) {
- case 'reply':
- $links[] = $this->topicLink( $title,
$workflowId );
- break;
-
- case 'new-post': // fall through
- case 'edit-post':
- $links[] = $this->topicLink( $title,
$workflowId );
- $links[] = $this->postLink( $title,
$workflowId, $postId );
- break;
-
- case 'suppress-post':
- case 'delete-post':
- case 'hide-post':
- case 'restore-post':
- $links[] = $this->topicLink( $title,
$workflowId );
- $links[] = $this->postHistoryLink( $title,
$workflowId, $postId );
- break;
-
- case 'suppress-topic':
- case 'delete-topic':
- case 'hide-topic':
- case 'restore-topic':
- $links[] = $this->topicLink( $title,
$workflowId );
- $links[] = $this->topicHistoryLink( $title,
$workflowId );
- break;
-
- case 'edit-title':
- $links[] = $this->topicLink( $title,
$workflowId );
- // This links to the history of the topic title
- $links[] = $this->postHistoryLink( $title,
$workflowId, $postId );
- break;
-
- case 'create-header': // fall through
- case 'edit-header':
- //$links[] = $this->workflowLink( $title,
$workflowId );
- break;
-
- case null:
- wfWarn( __METHOD__ . ': Flow change has null
change type' );
- return false;
-
- default:
- wfWarn( __METHOD__ . ': Unknown Flow action: '
. $action );
- return false;
- }
-
- return $links;
- }
-
- /**
- * @param AbstractRevision $revision
- * @param User $user
- * @param Lang $lang
- * @return array Contains [timeAndDate, date, time]
- */
- protected function getDateFormats( AbstractRevision $revision, User
$user, Language $lang ) {
- // date & time
- $timestamp =
$revision->getRevisionId()->getTimestampObj()->getTimestamp( TS_MW );
- $dateFormats = array();
- $dateFormats['timeAndDate'] = $lang->userTimeAndDate(
$timestamp, $user );
- $dateFormats['date'] = $lang->userDate( $timestamp, $user );
- $dateFormats['time'] = $lang->userTime( $timestamp, $user );
-
- return $dateFormats;
- }
-
- public function topicHistoryLink( Title $title, UUID $workflowId ) {
- return array(
- $this->urlGenerator->buildUrl(
- $title,
- 'topic-history',
- array( 'workflow' => $workflowId->getHex() )
- ),
- wfMessage( 'flow-link-history' )
- );
- }
-
- public function postHistoryLink( Title $title, UUID $workflowId, UUID
$postId ) {
- return array(
- $this->urlGenerator->buildUrl(
- $title,
- 'post-history',
- array(
- 'workflow' => $workflowId->getHex(),
- 'topic' => array( 'postId' =>
$postId->getHex() ),
- )
- ),
- wfMessage( 'flow-link-history' )
- );
- }
-
- public function topicLink( Title $title, UUID $workflowId ) {
- return array(
- $this->urlGenerator->buildUrl(
- $title,
- 'view',
- array( 'workflow' => $workflowId->getHex() )
- ),
- wfMessage( 'flow-link-topic' )
- );
- }
-
- public function postLink( Title $title, UUID $workflowId, UUID $postId
) {
- return array(
- $this->urlGenerator->buildUrl(
- $title,
- 'view',
- array(
- 'workflow' => $workflowId->getHex(),
- 'topic' => array( 'postId' =>
$postId->getHex() ),
- )
- ),
- wfMessage( 'flow-link-post' )
- );
- }
-
- protected function workflowLink( Title $title, UUID $workflowId ) {
- list( $linkTitle, $query ) = $this->urlGenerator->buildUrlData(
- $title,
- 'view'
- );
-
- return array(
- $linkTitle->getFullUrl( $query ),
- $linkTitle->getPrefixedText()
- );
- }
-
- /**
- * Build textual description for Flow's Contributions entries. These
piggy-
- * back on the i18n messages also used for Flow history, as defined in
- * FlowActions.
- *
- * @param Workflow $workflow
- * @param AbstractBlock $block
- * @param AbstractRevision $revision
- * @param User $user
- * @return string
- */
- public function getActionDescription( Workflow $workflow, AbstractBlock
$block, AbstractRevision $revision, User $user ) {
- // Build description message, piggybacking on history i18n
- $changeType = $revision->getChangeType();
- $msg = $this->actions->getValue( $changeType, 'history',
'i18n-message' );
- $params = $this->actions->getValue( $changeType, 'history',
'i18n-params' );
- $message = $this->buildMessage( $msg, (array) $params, array(
- $revision,
- $this->templating,
- $user,
- $block
- ) )->parse();
-
- return \Html::rawElement(
- 'span',
- array( 'class' => 'plainlinks' ),
- $message
- );
- }
-
- /**
- * @param AbstractRevision $revision
- * @return string|bool Chardiff or false on failure
- */
- protected function getCharDiff( AbstractRevision $revision,
AbstractRevision $previousRevision = null ) {
- $previousContent = '';
-
- if ( $previousRevision ) {
- $previousContent = $previousRevision->getContentRaw();
- }
-
- return ChangesList::showCharacterDifference( strlen(
$previousContent ), strlen( $revision->getContentRaw() ) );
- }
-
- /**
- * @param Title $title
- * @param UUID $workflowId
- * @param string $name Block name (e.g. "topic", "header")
- * @return AbstractBlock|bool Requested block or false on failure
- */
- protected function loadBlock( Title $title, UUID $workflowId, $name ) {
- $loader = $this->workflowLoaderFactory
- ->createWorkflowLoader( $title, $workflowId );
- $blocks = $loader->createBlocks();
-
- if ( !isset( $blocks[$name] ) ) {
- wfWarn( __METHOD__ . ': Could not load block ' . $name
. ' for workflow ' . $workflowId->getHex() );
- return false;
- }
-
- return $blocks[$name];
- }
-
- /**
- * Returns i18n message for $msg; piggybacking on History i18n.
- *
- * Complex parameters can be injected in the i18n messages. Anything in
- * $params will be call_user_func'ed, with these given $arguments.
- * Those results will be used as message parameters.
- *
- * Note: return array( 'raw' => $value ) or array( 'num' => $value ) for
- * raw or numeric parameter input.
- *
- * @param string $msg i18n key
- * @param array[optional] $params Callbacks for parameters
- * @param array[optional] $arguments Arguments for the callbacks
- * @return Message
- */
- protected function buildMessage( $msg, array $params = array(), array
$arguments = array() ) {
- foreach ( $params as &$param ) {
- if ( is_callable( $param ) ) {
- $param = call_user_func_array( $param,
$arguments );
- }
- }
-
- return wfMessage( $msg, $params );
}
}
diff --git a/includes/Formatter.php b/includes/Formatter.php
new file mode 100644
index 0000000..24b2694
--- /dev/null
+++ b/includes/Formatter.php
@@ -0,0 +1,411 @@
+<?php
+
+namespace Flow;
+
+use Flow\Model\AbstractRevision;
+use Flow\Model\Workflow;
+use Flow\Block\AbstractBlock;
+use Flow\Data\ManagerGroup;
+use Flow\Model\UUID;
+use Language;
+use Html;
+use Title;
+use User;
+use ChangesList;
+
+/**
+ * This is a "utility" class that might come in useful to generate 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 ManagerGroup
+ */
+ protected $storage;
+
+ /**
+ * @var WorkflowLoaderFactory
+ */
+ protected $workflowLoaderFactory;
+
+ /**
+ * @var FlowActions
+ */
+ protected $actions;
+
+ /**
+ * @var Templating
+ */
+ protected $templating;
+
+ /**
+ * @var UrlGenerator;
+ */
+ protected $urlGenerator;
+
+ /**
+ * @var Language
+ */
+ protected $lang;
+
+ /**
+ * @var array Array of Workflow objects
+ */
+ protected $workflows = array();
+
+ /**
+ * @var array Array of AbstractRevision objects
+ */
+ protected $revisions = array();
+
+ /**
+ * @param ManagerGroup $storage
+ * @param WorkflowLoaderFactory $workflowLoaderFactory
+ * @param FlowActions $actions
+ * @param Templating $templating
+ * @param Language $lang
+ */
+ public function __construct( ManagerGroup $storage,
WorkflowLoaderFactory $workflowLoaderFactory, FlowActions $actions, Templating
$templating ) {
+ $this->actions = $actions;
+ $this->storage = $storage;
+ $this->workflowLoaderFactory = $workflowLoaderFactory;
+ $this->templating = $templating;
+
+ $this->urlGenerator = $this->templating->getUrlGenerator();
+ }
+
+ protected function buildActionLinks( Title $title, $action, UUID
$workflowId, UUID $postId = null ) {
+ $links = array();
+ switch( $action ) {
+ case 'reply':
+ $links[] = $this->topicLink( $title,
$workflowId );
+ break;
+
+ case 'new-post': // fall through
+ case 'edit-post':
+ $links[] = $this->topicLink( $title,
$workflowId );
+ $links[] = $this->postLink( $title,
$workflowId, $postId );
+ break;
+
+ case 'suppress-post':
+ case 'delete-post':
+ case 'hide-post':
+ case 'restore-post':
+ $links[] = $this->topicLink( $title,
$workflowId );
+ $links[] = $this->postHistoryLink( $title,
$workflowId, $postId );
+ break;
+
+ case 'suppress-topic':
+ case 'delete-topic':
+ case 'hide-topic':
+ case 'restore-topic':
+ $links[] = $this->topicLink( $title,
$workflowId );
+ $links[] = $this->topicHistoryLink( $title,
$workflowId );
+ break;
+
+ case 'edit-title':
+ $links[] = $this->topicLink( $title,
$workflowId );
+ // This links to the history of the topic title
+ $links[] = $this->postHistoryLink( $title,
$workflowId, $postId );
+ break;
+
+ case 'create-header': // fall through
+ case 'edit-header':
+ //$links[] = $this->workflowLink( $title,
$workflowId );
+ break;
+
+ case null:
+ wfWarn( __METHOD__ . ': Flow change has null
change type' );
+ return false;
+
+ default:
+ wfWarn( __METHOD__ . ': Unknown Flow action: '
. $action );
+ return false;
+ }
+
+ return $links;
+ }
+
+ /**
+ * @param AbstractRevision $revision
+ * @param User $user
+ * @param Lang $lang
+ * @return array Contains [timeAndDate, date, time]
+ */
+ protected function getDateFormats( AbstractRevision $revision, User
$user, Language $lang ) {
+ // date & time
+ $timestamp =
$revision->getRevisionId()->getTimestampObj()->getTimestamp( TS_MW );
+ $dateFormats = array();
+ $dateFormats['timeAndDate'] = $lang->userTimeAndDate(
$timestamp, $user );
+ $dateFormats['date'] = $lang->userDate( $timestamp, $user );
+ $dateFormats['time'] = $lang->userTime( $timestamp, $user );
+
+ return $dateFormats;
+ }
+
+ public function topicHistoryLink( Title $title, UUID $workflowId ) {
+ return array(
+ $this->urlGenerator->buildUrl(
+ $title,
+ 'topic-history',
+ array( 'workflow' => $workflowId->getHex() )
+ ),
+ wfMessage( 'flow-link-history' )->text()
+ );
+ }
+
+ public function postHistoryLink( Title $title, UUID $workflowId, UUID
$postId ) {
+ return array(
+ $this->urlGenerator->buildUrl(
+ $title,
+ 'post-history',
+ array(
+ 'workflow' => $workflowId->getHex(),
+ 'topic' => array( 'postId' =>
$postId->getHex() ),
+ )
+ ),
+ wfMessage( 'flow-link-history' )->text()
+ );
+ }
+
+ public function topicLink( Title $title, UUID $workflowId ) {
+ return array(
+ $this->urlGenerator->buildUrl(
+ $title,
+ 'view',
+ array( 'workflow' => $workflowId->getHex() )
+ ),
+ wfMessage( 'flow-link-topic' )->text()
+ );
+ }
+
+ public function postLink( Title $title, UUID $workflowId, UUID $postId
) {
+ return array(
+ $this->urlGenerator->buildUrl(
+ $title,
+ 'view',
+ array(
+ 'workflow' => $workflowId->getHex(),
+ 'topic' => array( 'postId' =>
$postId->getHex() ),
+ )
+ ),
+ wfMessage( 'flow-link-post' )->text()
+ );
+ }
+
+ protected function workflowLink( Title $title, UUID $workflowId ) {
+ list( $linkTitle, $query ) = $this->urlGenerator->buildUrlData(
+ $title,
+ 'view'
+ );
+
+ return array(
+ $linkTitle->getFullUrl( $query ),
+ $linkTitle->getPrefixedText()
+ );
+ }
+
+ /**
+ * Build textual description for Flow's Contributions entries. These
piggy-
+ * back on the i18n messages also used for Flow history, as defined in
+ * FlowActions.
+ *
+ * @param Workflow $workflow
+ * @param AbstractBlock $block
+ * @param AbstractRevision $revision
+ * @param User $user
+ * @return string
+ */
+ public function getActionDescription( Workflow $workflow, AbstractBlock
$block, AbstractRevision $revision, User $user ) {
+ // Build description message, piggybacking on history i18n
+ $changeType = $revision->getChangeType();
+ $msg = $this->actions->getValue( $changeType, 'history',
'i18n-message' );
+ $params = $this->actions->getValue( $changeType, 'history',
'i18n-params' );
+ $message = $this->buildMessage( $msg, (array) $params, array(
+ $revision,
+ $this->templating,
+ $user,
+ $block
+ ) )->parse();
+
+ return \Html::rawElement(
+ 'span',
+ array( 'class' => 'plainlinks' ),
+ $message
+ );
+ }
+
+ /**
+ * @param AbstractRevision $revision
+ * @param AbstractRevision[optional] $previousRevision
+ * @return string|bool Chardiff or false on failure
+ */
+ protected function getCharDiff( AbstractRevision $revision,
AbstractRevision $previousRevision = null ) {
+ $previousContent = '';
+
+ if ( $previousRevision ) {
+ $previousContent = $previousRevision->getContentRaw();
+ }
+
+ return ChangesList::showCharacterDifference( strlen(
$previousContent ), strlen( $revision->getContentRaw() ) );
+ }
+
+ /**
+ * @param Title $title
+ * @param UUID $workflowId
+ * @param string $name Block name (e.g. "topic", "header")
+ * @return AbstractBlock|bool Requested block or false on failure
+ */
+ protected function loadBlock( Title $title, UUID $workflowId, $name ) {
+ $loader = $this->workflowLoaderFactory
+ ->createWorkflowLoader( $title, $workflowId );
+ $blocks = $loader->createBlocks();
+
+ if ( !isset( $blocks[$name] ) ) {
+ wfWarn( __METHOD__ . ': Could not load block ' . $name
. ' for workflow ' . $workflowId->getHex() );
+ return false;
+ }
+
+ return $blocks[$name];
+ }
+
+ /**
+ * Load 1 specific workflow.
+ *
+ * @param UUID $workflowId
+ * @return Workflow|bool Requested workflow or false on failure
+ */
+ protected function loadWorkflow( UUID $workflowId ) {
+ $results = $this->loadWorkflows( array( $workflowId ) );
+ if ( !isset( $results[$workflowId->getHex()] ) ) {
+ wfWarn( __METHOD__ . ': Could not load workflow ' .
$workflowId->getHex() );
+ return false;
+ }
+
+ return $results[$workflowId->getHex()];
+ }
+
+ /**
+ * Load 1 specific revision.
+ *
+ * @param UUID $revisionId
+ * @param string $revisionType Type of revision to load (e.g. Header,
PostRevision)
+ * @return AbstractRevision|bool Requested revision or false on failure
+ */
+ protected function loadRevision( UUID $revisionId, $revisionType ) {
+ $results = $this->loadRevisions( array( $revisionType => array(
$revisionId ) ) );
+ if ( !isset( $results[$revisionId->getHex()] ) ) {
+ wfWarn( __METHOD__ . ': Could not load workflow ' .
$revisionId->getHex() );
+ return false;
+ }
+
+ return $results[$revisionId->getHex()];
+ }
+
+ /**
+ * Returns i18n message for $msg; piggybacking on History i18n.
+ *
+ * Complex parameters can be injected in the i18n messages. Anything in
+ * $params will be call_user_func'ed, with these given $arguments.
+ * Those results will be used as message parameters.
+ *
+ * Note: return array( 'raw' => $value ) or array( 'num' => $value ) for
+ * raw or numeric parameter input.
+ *
+ * @param string $msg i18n key
+ * @param array[optional] $params Callbacks for parameters
+ * @param array[optional] $arguments Arguments for the callbacks
+ * @return Message
+ */
+ protected function buildMessage( $msg, array $params = array(), array
$arguments = array() ) {
+ foreach ( $params as &$param ) {
+ if ( is_callable( $param ) ) {
+ $param = call_user_func_array( $param,
$arguments );
+ }
+ }
+
+ return wfMessage( $msg, $params );
+ }
+
+ /**
+ * Batch-loads multiple workflows at once (and cached results in object)
+ *
+ * @param array $workflowIds
+ * @return array
+ */
+ public function loadWorkflows( array $workflowIds ) {
+ $results = array();
+
+ // make sure all ids are UUID objects
+ $workflowIds = array_map( array( 'Flow\Model\UUID', 'create' ),
$workflowIds );
+
+ foreach ( $workflowIds as $i => $workflowId ) {
+ // don't query for workflows already in cache
+ if ( isset( $this->workflows[$workflowId->getHex()] ) )
{
+ $results[$workflowId->getHex()] =
$this->workflows[$workflowId->getHex()];
+ unset( $workflowIds[$i] );
+ }
+ }
+
+ // fetch missing workflows
+ $workflows = (array) $this->storage->getMulti( 'Workflow',
$workflowIds );
+ foreach ( $workflows as $workflow ) {
+ $results[$workflow->getId()->getHex()] = $workflow;
+ }
+
+ // cache in object
+ $this->workflows += $results;
+
+ return $results;
+ }
+
+ /**
+ * Batch-loads multiple revisions at once (and cached results in object)
+ *
+ * @param array $revisions Multi-dimensional array of revisions to
fetch,
+ * where the revisionType (e.g. Header, PostRevision) is the key, and an
+ * array of revisionIds (UUID objects) is the value
+ * @return array
+ */
+ public function loadRevisions( array $revisions ) {
+ $results = array();
+
+ foreach ( $revisions as $revisionType => $revisionIds ) {
+ // make sure all ids are UUID objects
+ $revisionIds = array_map( array( 'Flow\Model\UUID',
'create' ), $revisionIds );
+
+ foreach ( $revisionIds as $i => $revisionId ) {
+ // don't query for revisions already in cache
+ if ( isset(
$this->revisions[$revisionId->getHex()] ) ) {
+ $results[$revisionId->getHex()] =
$this->revisions[$revisionId->getHex()];
+ unset( $revisionIds[$i] );
+ }
+ }
+
+ // fetch missing revisions
+ $revisions = (array) $this->storage->getMulti(
$revisionType, $revisionIds );
+ foreach ( $revisions as $revision ) {
+ $results[$revision->getRevisionId()->getHex()]
= $revision;
+ }
+ }
+
+ // cache in object
+ $this->revisions += $results;
+
+ return $results;
+ }
+}
diff --git a/includes/RecentChanges/Formatter.php
b/includes/RecentChanges/Formatter.php
index 274cfbd..4bb2af2 100644
--- a/includes/RecentChanges/Formatter.php
+++ b/includes/RecentChanges/Formatter.php
@@ -2,69 +2,13 @@
namespace Flow\RecentChanges;
-use Flow\Container;
-use Flow\Data\ManagerGroup;
-use Flow\FlowActions;
+use Flow\AbstractFormatter;
use Flow\Model\UUID;
use ChangesList;
-use Flow\Templating;
-use Flow\UrlGenerator;
-use Flow\WorkflowLoaderFactory;
-use Language;
-use Linker;
use Html;
use RecentChange;
-use Title;
-use User;
-class Formatter {
- /**
- * @var ManagerGroup
- */
- protected $storage;
-
- /**
- * @var WorkflowLoaderFactory
- */
- protected $workflowLoaderFactory;
-
- /**
- * @var FlowActions
- */
- protected $actions;
-
- /**
- * @var Templating
- */
- protected $templating;
-
- /**
- * @var UrlGenerator;
- */
- protected $urlGenerator;
-
- /**
- * @var Language
- */
- protected $lang;
-
- /**
- * @param ManagerGroup $storage
- * @param WorkflowLoaderFactory $workflowLoaderFactory
- * @param FlowActions $actions
- * @param Templating $templating
- * @param Language $lang
- */
- public function __construct( ManagerGroup $storage,
WorkflowLoaderFactory $workflowLoaderFactory, FlowActions $actions, Templating
$templating, Language $lang ) {
- $this->actions = $actions;
- $this->storage = $storage;
- $this->workflowLoaderFactory = $workflowLoaderFactory;
- $this->templating = $templating;
- $this->lang = $lang;
-
- $this->urlGenerator = $this->templating->getUrlGenerator();
- }
-
+class Formatter extends AbstractFormatter {
public function format( ChangesList $cl, RecentChange $rc ) {
$params = unserialize( $rc->getAttribute( 'rc_params' ) );
$changeData = $params['flow-workflow-change'];
@@ -74,264 +18,81 @@
return false;
}
- // used in $this->buildActionLinks()
- if ( !array_key_exists( 'action', $changeData ) ) {
- wfWarn( __METHOD__ . ': Flow action missing' );
+ $title = $rc->getTitle();
+ $user = $cl->getUser();
+ $lang = $cl->getLanguage();
- // Backward compatibility; get newer action name based
on old type.
- if ( array_key_exists( 'type', $changeData ) ) {
- try {
- $action = $this->actions->getValue(
$changeData['type'] );
- if ( is_string( $action ) ) {
- $changeData['action'] = $action;
- } else {
- return false;
- }
- } catch ( \MWException $e ) {
- return false;
- }
- } else {
- return false;
- }
+ /*
+ * @todo:
+ * We should some day introduce a hook in core that allows us
to hook
+ * into the full resultset, so we can first loop all entries
and pre-
+ * load workflows & revisions all at once.
+ *
+ * Since that's not yet the case, multiple queries (up to
$wgFeedLimit)
+ * may occur. Assuming revisions (yes) and workflow (less
likely) are
+ * all different, there can be $wgFeedLimit * 2 queries to DB
or cache.
+ */
+ $workflow = $this->loadWorkflow( UUID::create(
$changeData['workflow'] ) );
+ if ( !$workflow ) {
+ return false;
}
- $line = '';
- $title = $rc->getTitle();
- $links = $this->buildActionLinks( $title, $changeData );
+ $revision = $this->loadRevision( UUID::create(
$changeData['revision'] ), $changeData['revision_type'] );
+ if ( !$revision ) {
+ return false;
+ }
- if ( $links ) {
- $linksContent = $cl->getLanguage()->pipeList( $links );
- $line .= wfMessage( 'parentheses' )->rawParams(
$linksContent )->escaped()
+ $block = $this->loadBlock( $title, $workflow->getId(),
$changeData['block'] );
+ if ( !$block ) {
+ return false;
+ }
+
+ $links = (array) $this->buildActionLinks(
+ $title,
+ $revision->getChangeType(),
+ $workflow->getId(),
+ method_exists( $revision, 'getPostId' ) ?
$revision->getPostId() : null
+ );
+
+ // Format links
+ foreach ( $links as &$link ) {
+ list( $url, $text ) = $link;
+ $link = Html::element(
+ 'a',
+ array(
+ 'href' => $url,
+ 'title' => $text
+ ),
+ $text
+ );
+ }
+ $linksContent = $lang->pipeList( $links );
+ if ( $linksContent ) {
+ $linksContent = wfMessage( 'parentheses' )->rawParams(
$linksContent )->escaped()
. $this->changeSeparator();
}
- $line .= $this->workflowLink( $title, $changeData )
+ $dateFormats = $this->getDateFormats( $revision, $user, $lang );
+ $formattedTime = '<span class="mw-changeslist-date">' .
$dateFormats['time'] . '</span>';
+
+ $workflowLink = $this->workflowLink( $title, $workflow->getId()
);
+ $workflowLink = Html::element(
+ 'a',
+ array( 'href' => $workflowLink[0] ),
+ $workflowLink[1]
+ );
+
+ return $linksContent
+ . $workflowLink
. wfMessage( 'semicolon-separator' )->escaped()
- . $this->getTimestamp( $cl, $rc )
+ . $formattedTime
. ' '
. $this->changeSeparator()
. ' '
- . $this->getActionDescription( $changeData, $cl, $rc );
-
- return $line;
- }
-
- protected function buildActionLinks( Title $title, array $changeData ) {
- $links = array();
- switch( $changeData['action'] ) {
- case 'reply':
- $links[] = $this->topicLink( $title,
$changeData );
- break;
-
- case 'new-post': // fall through
- case 'edit-post':
- $links[] = $this->topicLink( $title,
$changeData );
- $links[] = $this->postLink( $title, $changeData
);
- break;
-
- case 'suppress-post':
- case 'delete-post':
- case 'hide-post':
- case 'restore-post':
- $links[] = $this->topicLink( $title,
$changeData );
- $links[] = $this->postHistoryLink( $title,
$changeData );
- break;
-
- case 'suppress-topic':
- case 'delete-topic':
- case 'hide-topic':
- case 'restore-topic':
- $links[] = $this->topicLink( $title,
$changeData );
- $links[] = $this->topicHistoryLink( $title,
$changeData );
- break;
-
- case 'edit-title':
- $links[] = $this->topicLink( $title,
$changeData );
- // This links to the history of the topic title
- $links[] = $this->postHistoryLink( $title,
$changeData );
- break;
-
- case 'create-header': // fall through
- case 'edit-header':
- //$links[] = $this->workflowLink( $title,
$changeData );
- break;
-
- case null:
- wfWarn( __METHOD__ . ': Flow change has null
change type' );
- return false;
-
- default:
- wfWarn( __METHOD__ . ': Unknown Flow action: '
. $changeData['action'] );
- return false;
- }
-
- return $links;
+ . $this->getActionDescription( $workflow, $block,
$revision, $user );
}
protected function changeSeparator() {
return ' <span class="mw-changeslist-separator">. .</span> ';
- }
-
- protected function getTimestamp( $cl, $rc ) {
- return '<span class="mw-changeslist-date">'
- . $cl->getLanguage()->userTime(
$rc->mAttribs['rc_timestamp'], $cl->getUser() )
- . '</span> ';
- }
-
- public function topicHistoryLink( Title $title, array $changeData ) {
- return Html::rawElement(
- 'a',
- array(
- 'href' => $this->urlGenerator->buildUrl(
- $title,
- 'topic-history',
- array( 'workflow' =>
$changeData['workflow'] )
- ),
- ),
- wfMessage( 'flow-link-history' )->escaped()
- );
- }
-
- public function postHistoryLink( Title $title, array $changeData ) {
- return Html::rawElement(
- 'a',
- array(
- 'href' => $this->urlGenerator->buildUrl(
- $title,
- 'post-history',
- array(
- 'workflow' =>
$changeData['workflow'],
- 'topic' => array( 'postId' =>
$changeData['post'] ),
- )
- ),
- ),
- wfMessage( 'flow-link-history' )->escaped()
- );
- }
-
- public function topicLink( Title $title, array $changeData ) {
- return Html::rawElement(
- 'a',
- array(
- 'href' => $this->urlGenerator->buildUrl(
- $title,
- 'view',
- array( 'workflow' =>
$changeData['workflow'] )
- ),
- ),
- wfMessage( 'flow-link-topic' )->escaped()
- );
- }
-
- public function postLink( Title $title, array $changeData ) {
- return Html::rawElement(
- 'a',
- array(
- 'href' => $this->urlGenerator->buildUrl(
- $title,
- 'view',
- array(
- 'workflow' =>
$changeData['workflow'],
- 'topic' => array( 'postId' =>
$changeData['post'] ),
- )
- ),
- ),
- wfMessage( 'flow-link-post' )->escaped()
- );
- }
-
- protected function workflowLink( Title $title, array $changeData ) {
- list( $linkTitle, $query ) = $this->urlGenerator->buildUrlData(
- $title,
- 'view'
- );
-
- return Html::element(
- 'a',
- array( 'href' => $linkTitle->getFullUrl( $query ) ),
- $linkTitle->getPrefixedText()
- );
- }
-
- /**
- * Build textual description for Flow's RecentChanges entries. These
piggy-
- * back on the i18n messages also used for Flow history, as defined in
- * FlowActions.
- *
- * @param array $changeData
- * @param ChangesList $cl
- * @param RecentChange $rc
- * @return string
- */
- public function getActionDescription( array $changeData, ChangesList
$cl, RecentChange $rc ) {
- // Fetch Block object
- $title = Title::newFromText( $rc->getAttribute( 'rc_title' ),
(int) $rc->getAttribute( 'rc_namespace' ) );
- $block = $this->loadBlock( $title, $changeData['workflow'],
$changeData['block'] );
- if ( !$block ) {
- wfWarn( __METHOD__ . ': Could not load block ' .
$changeData['block'] . ' for workflow ' . $changeData['workflow'] );
- return '';
- }
-
- // Fetch requested Revision
- $revision = $this->storage->get( $changeData['revision_type'],
UUID::create( $changeData['revision'] ) );
- if ( !$revision ) {
- wfWarn( __METHOD__ . ': Could not load revision ' .
$changeData['revision'] );
- return '';
- }
-
- // Build description message, piggybacking on history i18n
- $msg = $this->actions->getValue( $changeData['action'],
'history', 'i18n-message' );
- $params = $this->actions->getValue( $changeData['action'],
'history', 'i18n-params' );
- $message = $this->buildMessage( $msg, (array) $params, array(
- $revision,
- $this->templating,
- $cl->getUser(),
- $block
- ) )->parse();
-
- return \Html::rawElement(
- 'span',
- array( 'class' => 'plainlinks' ),
- $message
- );
- }
-
- /**
- * @param Title $title
- * @param string $definitionId
- * @param string $workflowId
- * @param string $name Block name
- * @return AbstractBlock|false Requested block or false on failure
- */
- protected function loadBlock( Title $title, $workflowId, $name ) {
- $loader = $this->workflowLoaderFactory
- ->createWorkflowLoader( $title, UUID::create(
$workflowId ) );
- $blocks = $loader->createBlocks();
- return isset( $blocks[$name] ) ? $blocks[$name] : false;
- }
-
- /**
- * Returns i18n message for $msg; piggybacking on History i18n.
- *
- * Complex parameters can be injected in the i18n messages. Anything in
- * $params will be call_user_func'ed, with these given $arguments.
- * Those results will be used as message parameters.
- *
- * Note: return array( 'raw' => $value ) or array( 'num' => $value ) for
- * raw or numeric parameter input.
- *
- * @param string $msg i18n key
- * @param array[optional] $params Callbacks for parameters
- * @param array[optional] $arguments Arguments for the callbacks
- * @return Message
- */
- protected function buildMessage( $msg, array $params = array(), array
$arguments = array() ) {
- foreach ( $params as &$param ) {
- if ( is_callable( $param ) ) {
- $param = call_user_func_array( $param,
$arguments );
- }
- }
-
- return wfMessage( $msg, $params );
}
}
--
To view, visit https://gerrit.wikimedia.org/r/102674
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I8392302e016673f02bf495fd6ae156a9334262ab
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits