PageRenderTime 24ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/phase3/includes/logging/LogFormatter.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 342 lines | 172 code | 44 blank | 126 comment | 19 complexity | aa5cf0a86caa8c0aec408862cc6c152d MD5 | raw file
  1. <?php
  2. /**
  3. * Contains classes for formatting log entries
  4. *
  5. * @file
  6. * @author Niklas Laxström
  7. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
  8. * @since 1.19
  9. */
  10. /**
  11. * Implements the default log formatting.
  12. * Can be overridden by subclassing and setting
  13. * $wgLogActionsHandlers['type/subtype'] = 'class'; or
  14. * $wgLogActionsHandlers['type/*'] = 'class';
  15. * @since 1.19
  16. */
  17. class LogFormatter {
  18. // Static->
  19. /**
  20. * Constructs a new formatter suitable for given entry.
  21. * @param $entry LogEntry
  22. * @return LogFormatter
  23. */
  24. public static function newFromEntry( LogEntry $entry ) {
  25. global $wgLogActionsHandlers;
  26. $fulltype = $entry->getFullType();
  27. $wildcard = $entry->getType() . '/*';
  28. $handler = '';
  29. if ( isset( $wgLogActionsHandlers[$fulltype] ) ) {
  30. $handler = $wgLogActionsHandlers[$fulltype];
  31. } elseif ( isset( $wgLogActionsHandlers[$wildcard] ) ) {
  32. $handler = $wgLogActionsHandlers[$wildcard];
  33. }
  34. if ( $handler !== '' && class_exists( $handler ) ) {
  35. return new $handler( $entry );
  36. }
  37. return new LegacyLogFormatter( $entry );
  38. }
  39. /**
  40. * Handy shortcut for constructing a formatter directly from
  41. * database row.
  42. * @param $row
  43. * @see DatabaseLogEntry::getSelectQueryData
  44. * @return LogFormatter
  45. */
  46. public static function newFromRow( $row ) {
  47. return self::newFromEntry( DatabaseLogEntry::newFromRow( $row ) );
  48. }
  49. // Nonstatic->
  50. /// @var LogEntry
  51. protected $entry;
  52. /// Whether to output user tool links
  53. protected $linkFlood = false;
  54. /**
  55. * Set to true if we are constructing a message text that is going to
  56. * be included in page history or send to IRC feed. Links are replaced
  57. * with plaintext or with [[pagename]] kind of syntax, that is parsed
  58. * by page histories and IRC feeds.
  59. * @var boolean
  60. */
  61. protected $plaintext = false;
  62. protected function __construct( LogEntry $entry ) {
  63. $this->entry = $entry;
  64. $this->context = RequestContext::getMain();
  65. }
  66. /**
  67. * Replace the default context
  68. * @param $context RequestContext
  69. */
  70. public function setContext( RequestContext $context ) {
  71. $this->context = $context;
  72. }
  73. /**
  74. * If set to true, will produce user tool links after
  75. * the user name. This should be replaced with generic
  76. * CSS/JS solution.
  77. * @param $value boolean
  78. */
  79. public function setShowUserToolLinks( $value ) {
  80. $this->linkFlood = $value;
  81. }
  82. /**
  83. * Ugly hack to produce plaintext version of the message.
  84. * Usually you also want to set extraneous request context
  85. * to avoid formatting for any particular user.
  86. * @see getActionText()
  87. * @return string text
  88. */
  89. public function getPlainActionText() {
  90. $this->plaintext = true;
  91. $text = $this->getActionText();
  92. $this->plaintext = false;
  93. return $text;
  94. }
  95. /**
  96. * Gets the log action, including username.
  97. * @return string HTML
  98. */
  99. public function getActionText() {
  100. $element = $this->getActionMessage();
  101. if ( $element instanceof Message ) {
  102. $element = $this->plaintext ? $element->text() : $element->escaped();
  103. }
  104. if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) {
  105. $performer = $this->getPerformerElement() . $this->msg( 'word-separator' )->text();
  106. $element = $performer . self::getRestrictedElement( 'rev-deleted-event' );
  107. }
  108. return $element;
  109. }
  110. /**
  111. * Returns a sentence describing the log action. Usually
  112. * a Message object is returned, but old style log types
  113. * and entries might return pre-escaped html string.
  114. * @return Message|pre-escaped html
  115. */
  116. protected function getActionMessage() {
  117. $message = $this->msg( $this->getMessageKey() );
  118. $message->params( $this->getMessageParameters() );
  119. return $message;
  120. }
  121. /**
  122. * Returns a key to be used for formatting the action sentence.
  123. * Default is logentry-TYPE-SUBTYPE for modern logs. Legacy log
  124. * types will use custom keys, and subclasses can also alter the
  125. * key depending on the entry itself.
  126. * @return string message key
  127. */
  128. protected function getMessageKey() {
  129. $type = $this->entry->getType();
  130. $subtype = $this->entry->getSubtype();
  131. $key = "logentry-$type-$subtype";
  132. return $key;
  133. }
  134. /**
  135. * Extract parameters intented for action message from
  136. * array of all parameters. The are three hardcoded
  137. * parameters (array zero-indexed, this list not):
  138. * - 1: user name with premade link
  139. * - 2: usable for gender magic function
  140. * - 3: target page with premade link
  141. * @return array
  142. */
  143. protected function getMessageParameters() {
  144. $entry = $this->entry;
  145. $params = array();
  146. $params[0] = Message::rawParam( $this->getPerformerElement() );
  147. $params[1] = $entry->getPerformer()->getName();
  148. $params[2] = Message::rawParam( $this->makePageLink( $entry->getTarget() ) );
  149. if ( $entry->isLegacy() ) {
  150. foreach ( $entry->getParameters() as $index => $value ) {
  151. $params[$index + 3] = $value;
  152. }
  153. }
  154. // Filter out parameters which are not in format #:foo
  155. foreach ( $entry->getParameters() as $key => $value ) {
  156. if ( strpos( $key, ':' ) === false ) continue;
  157. list( $index, $type, $name ) = explode( ':', $key, 3 );
  158. $params[$index - 1] = $value;
  159. }
  160. /* Message class doesn't like non consecutive numbering.
  161. * Fill in missing indexes with empty strings to avoid
  162. * incorrect renumbering.
  163. */
  164. $max = max( array_keys( $params ) );
  165. for ( $i = 4; $i < $max; $i++ ) {
  166. if ( !isset( $params[$i] ) ) {
  167. $params[$i] = '';
  168. }
  169. }
  170. return $params;
  171. }
  172. /**
  173. * Helper to make a link to the page, taking the plaintext
  174. * value in consideration.
  175. * @param $title Title the page
  176. * @param $parameters array query parameters
  177. * @return String
  178. */
  179. protected function makePageLink( Title $title, $parameters = array() ) {
  180. if ( !$this->plaintext ) {
  181. $link = Linker::link( $title, null, array(), $parameters );
  182. } else {
  183. $link = '[[' . $title->getPrefixedText() . ']]';
  184. }
  185. return $link;
  186. }
  187. /**
  188. * Provides the name of the user who performed the log action.
  189. * Used as part of log action message or standalone, depending
  190. * which parts of the log entry has been hidden.
  191. */
  192. public function getPerformerElement() {
  193. $performer = $this->entry->getPerformer();
  194. if ( $this->plaintext ) {
  195. $element = $performer->getName();
  196. } else {
  197. $element = Linker::userLink(
  198. $performer->getId(),
  199. $performer->getName()
  200. );
  201. if ( $this->linkFlood ) {
  202. $element .= Linker::userToolLinks(
  203. $performer->getId(),
  204. $performer->getName(),
  205. true, // Red if no edits
  206. 0, // Flags
  207. $performer->getEditCount()
  208. );
  209. }
  210. }
  211. if ( $this->entry->isDeleted( LogPage::DELETED_USER ) ) {
  212. $element = self::getRestrictedElement( 'rev-deleted-user' );
  213. }
  214. return $element;
  215. }
  216. /**
  217. * Gets the luser provided comment
  218. * @return string HTML
  219. */
  220. public function getComment() {
  221. $lang = $this->context->getLang();
  222. $element = $lang->getDirMark() . Linker::commentBlock( $this->entry->getComment() );
  223. if ( $this->entry->isDeleted( LogPage::DELETED_COMMENT ) ) {
  224. $element = self::getRestrictedElement( 'rev-deleted-comment' );
  225. }
  226. return $element;
  227. }
  228. /**
  229. * Helper method for displaying restricted element.
  230. * @param $message string
  231. * @return string HTML
  232. */
  233. protected function getRestrictedElement( $message ) {
  234. if ( $this->plaintext ) {
  235. return $this->msg( $message )->text();
  236. }
  237. $content = $this->msg( $message )->escaped();
  238. $attribs = array( 'class' => 'history-deleted' );
  239. return Html::rawElement( 'span', $attribs, $content );
  240. }
  241. /**
  242. * Shortcut for wfMessage which honors local context.
  243. * @todo Would it be better to require replacing the global context instead?
  244. * @param $key string
  245. * @return Message
  246. */
  247. protected function msg( $key ) {
  248. return wfMessage( $key )
  249. ->inLanguage( $this->context->getLang() )
  250. ->title( $this->context->getTitle() );
  251. }
  252. }
  253. /**
  254. * This class formats all log entries for log types
  255. * which have not been converted to the new system.
  256. * This is not about old log entries which store
  257. * parameters in a different format - the new
  258. * LogFormatter classes have code to support formatting
  259. * those too.
  260. * @since 1.19
  261. */
  262. class LegacyLogFormatter extends LogFormatter {
  263. protected function getActionMessage() {
  264. $entry = $this->entry;
  265. $action = LogPage::actionText(
  266. $entry->getType(),
  267. $entry->getSubtype(),
  268. $entry->getTarget(),
  269. $this->context->getSkin(),
  270. (array)$entry->getParameters(),
  271. true
  272. );
  273. $performer = $this->getPerformerElement();
  274. return $performer . $this->msg( 'word-separator' )->text() . $action;
  275. }
  276. }
  277. /**
  278. * This class formats move log entries.
  279. * @since 1.19
  280. */
  281. class MoveLogFormatter extends LogFormatter {
  282. protected function getMessageKey() {
  283. $key = parent::getMessageKey();
  284. $params = $this->getMessageParameters();
  285. if ( isset( $params[4] ) && $params[4] === '1' ) {
  286. $key .= '-noredirect';
  287. }
  288. return $key;
  289. }
  290. protected function getMessageParameters() {
  291. $params = parent::getMessageParameters();
  292. $oldname = $this->makePageLink( $this->entry->getTarget(), array( 'redirect' => 'no' ) );
  293. $newname = $this->makePageLink( Title::newFromText( $params[3] ) );
  294. $params[2] = Message::rawParam( $oldname );
  295. $params[3] = Message::rawParam( $newname );
  296. return $params;
  297. }
  298. }