Page MenuHomePhabricator

Allow augmented $wgHostStatsCommands entries for better readable SpecialPage
Open, Needs TriagePublic

Description

Hey

First of all: Great Extension, really proving quite useful for my team. Backgroud: we have some workflows in which edits in the wiki trigger scripts on the host. I'm showing the current state of these scripts to my team via this extensions. Unfortunately, these people find it sometimes difficult to navigate the SpecialPage because all this "techy stuff in the toc" (to paraphrase the feedback).

I'm suggesting a change in handling of $wgHostStatsCommands to allow for the entries to either be a string (and render the command output like it is rendered currently) or an array in the form of

[
	'title' => 'title of the section',
	'command' => 'command as before',
	'description' => 'an optional description text'
],

Code to accomplish this (including removal of some deprecations) could look like this:

<?php

use MediaWiki\MediaWikiServices;
use MediaWiki\Shell\Shell;

/**
 * The file that implements Special:HostStats.
 *
 * @file
 * @ingroup Extensions
 */

class SpecialHostStats extends SpecialPage {
	public function __construct() {
		parent::__construct( 'HostStats' );
	}

	/**
	 * @param string|null $par
	 */
	public function execute( $par ) {
		global $wgHostStatsCommands;

		if ( !MediaWikiServices::getInstance()->getPermissionManager()->userHasRight( $this->getUser(), 'hoststats' ) ) {
			throw new PermissionsError( 'hoststats' );
		}

		$this->setHeaders();
		$this->getOutput()->setPageTitle( wfMessage( 'hoststats-title' )->escaped() );
		$outpage = wfMessage( 'hoststats-intro' )->escaped();
		$outpage .= "\n";
		if ( Shell::isDisabled() ) {
			$outpage .= '<p />' . wfMessage( 'hoststats-shell-disabled-error' )->parse();
		} else {
			foreach ($wgHostStatsCommands as $entry) {
				list($title, $description, $command) = $this->processEntry($entry);
				$outpage .= '<h3>' . $title . '</h3>';
				if ($description) {
					$outpage .= "\n<p />\n" . $description;
				}
				$outpage .= "\n<pre>\n" . $this->query($command) . "</pre>";
			}
		}
		$this->getOutput()->addWikiTextAsInterface( $outpage );
	}

	/**
	 * @inheritDoc
	 */
	protected function query( $query ) {
		$result = Shell::command( [] )
			->unsafeParams( (array)$query )
			->includeStderr( true )
			->restrict( Shell::RESTRICT_DEFAULT )
			->execute();
		return $result->getStdout();
	}

	/**
	 * @return string
	 */
	protected function getGroupName() {
		return 'wiki';
	}

	/**
	 * @param string|string[] $entry
	 * @return string[]
	 */
	private function processEntry( $entry ): array {
		if ( is_string( $entry ) ) {
			return [ $entry, null, $entry ];
			#return [ $entry, null, explode( ' ', $entry ) ];
		}
		$cmd = $entry['command'] ?? ( $entry[2] ?? 'undefined' );
		if ( !empty( $entry['args'] ) || !empty( $entry['arguments'] ) ) {
			$cmd = [ $cmd, $entry['args'] ?? $entry['arguments'] ];
		}
		return [
			$entry['title'] ?? ( $entry[1] ?? ( $entry['command'] ?? ( $entry[2] ?? 'undefined' ) ) ),
			$entry['description'] ?? ( $entry[1] ?? null ),
			$cmd,
		];
	}
}

Event Timeline

Oetterer updated the task description. (Show Details)

@Hydriz Sorry to bother you, but can you give me a pointer on what to do next? Does this need to be approved? Or do I submit the patch directly?

@Oetterer: Thanks for taking a look at the code! You are very welcome to use developer access to submit the proposed code changes as a Git branch directly into Gerrit which makes it easier to review and provide feedback. If you don't want to set up Git/Gerrit, you can also use the Gerrit Patch Uploader. Thanks again!