Current File : /home/jvzmxxx/wiki1/extensions/Flow/includes/Exception/ExceptionHandling.php
<?php

namespace Flow\Exception;

use MWException;
use OutputPage;
use RequestContext;

/**
 * Flow base exception
 */
class FlowException extends MWException {

	/**
	 * Flow exception error code
	 * @var string
	 */
	protected $code;

	/**
	 * The output object
	 * @var OutputPage
	 */
	protected $output;

	/**
	 * @param string $message The message from exception, used for debugging error
	 * @param string $code The error code used to display error message
	 */
	public function __construct( $message, $code = 'default' ) {
		global $wgOut;
		parent::__construct( $message );
		$this->code = $code;
		// Set output object to the global $wgOut object by default
		$this->output = $wgOut;
	}

	/**
	 * Set the output object
	 */
	public function setOutput( OutputPage $output ) {
		$this->output = $output;
	}

	/**
	 * Get the message key for the localized error message
	 */
	public function getErrorCode() {
		$list = $this->getErrorCodeList();
		if ( !in_array( $this->code, $list ) ) {
			$this->code = 'default';
		}
		return 'flow-error-' . $this->code;
	}

	/**
	 * Error code list for this exception
	 */
	protected function getErrorCodeList() {
		// flow-error-default
		return array ( 'default' );
	}

	/**
	 * Override parent method: we can use wfMessage here
	 *
	 * @return bool
	 */
	public function useMessageCache() {
		return true;
	}

	/**
	 * Overrides MWException getHTML, adding a more human-friendly error message
	 *
	 * @return string
	 */
	public function getHTML() {
		/*
		 * We'll want both a proper humanized error msg & the stacktrace the
		 * parent exception handler generated.
		 * We'll create a stub OutputPage object here, to use its showErrorPage
		 * to add our own humanized error message. Then we'll append the stack-
		 * trace (parent::getHTML) and then just return the combined HTML.
		 */
		$rc = new RequestContext();
		$output = $rc->getOutput();
		$output->showErrorPage( $this->getPageTitle(), $this->getErrorCode() );
		$output->addHTML( parent::getHTML() );
		return $output->getHTML();
	}

	/**
	 * Helper function for msg function in the convenience of a default callback
	 * @param string $key
	 * @return string
	 */
	public function parsePageTitle( $key ) {
		global $wgSitename;
		return $this->msg( $key, "$1 - $wgSitename", $this->msg( 'internalerror', 'Internal error' ) );
	}

	/**
	 * Error page title
	 */
	public function getPageTitle() {
		return $this->parsePageTitle( 'errorpagetitle' );
	}

	/**
	 * Exception from API/commandline will be handled by MWException::report(),
	 * Overwrite the HTML display only
	 */
	public function reportHTML() {
		$this->output->setStatusCode( $this->getStatusCode() );

		/*
		 * Parent exception handler uses global $wgOut
		 * We want to play nice and do inheritance and all, but that means we'll
		 * have to cheat here and assign out $this->output to $wgOut in order
		 * to have parent::reportHTML use the correct OutputPage object.
		 * After that, restore original $wgOut.
		 */
		global $wgOut;
		$wgOutBkp = $wgOut;
		$wgOut = $this->output;
		parent::reportHTML(); // this will do ->output() already
		$wgOut = $wgOutBkp;
	}

	/**
	 * Default status code is 500, which is server error
	 */
	public function getStatusCode() {
		return 500;
	}
}

/**
 * Category: invalid input exception
 *
 * This is not logged, and must *only* be used when the error is caused by invalid end-user
 * input.  The same applies to the subclasses.
 *
 * If it is a logic error (including a missing or incorrect parameter not directly caused
 * by user input), or another kind of failure, another (loggable) exception must be used.
 */
class InvalidInputException extends FlowException {
	protected function getErrorCodeList() {
		// Comments are i18n messages, for grepping
		return array (
			'invalid-input', // flow-error-invalid-input
			'missing-revision', // flow-error-missing-revision
			'revision-comparison', // flow-error-revision-comparison
			'invalid-workflow', // flow-error-invalid-workflow
		);
	}

	/**
	 * Bad request
	 */
	public function getStatusCode() {
		return 400;
	}

	/**
	 * Do not log exception resulting from input error
	 */
	function isLoggable() {
		return false;
	}
}

/**
 * This is not logged, and must *only* be used for reference
 * errors caused by invalid (unprocessable) end-user input
 */
class InvalidReferenceException extends InvalidInputException {
}

/**
 * Category: invalid action exception
 */
class InvalidActionException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-invalid-action
		return array ( 'invalid-action' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function getPageTitle() {
		return $this->parsePageTitle( 'nosuchaction' );
	}

	/**
	 * Bad request
	 */
	public function getStatusCode() {
		return 400;
	}

	/**
	 * {@inheritDoc}
	 */
	public function getHTML() {
		// we only want a nice error message here, no stack trace
		$rc = new RequestContext();
		$output = $rc->getOutput();
		$output->showErrorPage( $this->getPageTitle(), $this->getErrorCode() );
		return $output->getHTML();
	}

	/**
	 * Do not log exception resulting from input error
	 */
	function isLoggable() {
		return false;
	}
}

/**
 * Category: commit failure exception
 */
class FailCommitException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-fail-commit
		return array ( 'fail-commit' );
	}
}

/**
 * Category: permission related exception
 */
class PermissionException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-insufficient-permission
		return array ( 'insufficient-permission' );
	}

	/**
	 * Do not log exception resulting from user requesting
	 * disallowed content.
	 */
	function isLoggable() {
		return false;
	}
}

/**
 * Category: invalid data exception
 */
class InvalidDataException extends FlowException {
	protected function getErrorCodeList() {
		return array (
			'invalid-title', // flow-error-invalid-title
			'fail-load-data', // flow-error-fail-load-data
			'fail-load-history', // flow-error-fail-load-history
			'fail-search', // flow-error-fail-search
			'missing-topic-title', // flow-error-missing-topic-title
			'missing-metadata', // flow-error-missing-metadata
			'different-page', // flow-error-different-page
		);
	}
}

/**
 * Category: data model processing exception
 */
class DataModelException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-process-data
		return array ( 'process-data' );
	}
}

/**
 * Category: data persistency exception
 */
class DataPersistenceException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-process-data
		return array ( 'process-data' );
	}
}

/**
 * Category: Parsoid
 */
class NoParserException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-process-wikitext
		return array ( 'process-wikitext' );
	}
}

/**
 * Category: wikitext/html conversion exception
 */
class WikitextException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-process-wikitext
		return array ( 'process-wikitext' );
	}
}

/**
 * Category: Data Index
 */
class NoIndexException extends FlowException {
	protected function getErrorCodeList() {
		// flow-error-no-index
		return array ( 'no-index' );
	}
}

/**
 * Category: Cross Wiki
 */
class CrossWikiException extends FlowException {}

/**
 * Category: Template helper
 */
class WrongNumberArgumentsException extends FlowException {
	/**
	 * @param array $args
	 * @param string $minExpected
	 * @param string|null $maxExpected
	 */
	public function __construct( array $args, $minExpected, $maxExpected = null ) {
		$count = count( $args );
		if ( $maxExpected === null ) {
			parent::__construct( "Expected $minExpected arguments but received $count" );
		} else {
			parent::__construct( "Expected between $minExpected and $maxExpected arguments but received $count" );
		}
	}
}

/**
 * Specific exception thrown when a workflow is requested by id through
 * WorkflowLoaderFactory and it does not exist.
 */
class UnknownWorkflowIdException extends InvalidInputException {
	protected function getErrorCodeList() {
		// flow-error-invalid-input
		return array( 'invalid-input' );
	}

	public function getHTML() {
		return wfMessage( 'flow-error-unknown-workflow-id' )->escaped();
	}

	public function getPageTitle() {
		return wfMessage( 'flow-error-unknown-workflow-id-title' )->escaped();
	}
}

/**
 * Specific exception thrown when a page within NS_TOPIC is requested
 * through WorkflowLoaderFactory and it is an invalid uuid
 */
class InvalidTopicUuidException extends InvalidInputException {
	protected function getErrorCodeList() {
		// flow-error-invalid-input
		return array( 'invalid-input' );
	}

	public function getHTML() {
		return wfMessage( 'flow-error-invalid-topic-uuid' )->escaped();
	}

	public function getPageTitle() {
		return wfMessage( 'flow-error-invalid-topic-uuid-title' )->escaped();
	}
}

/**
 * Exception for missing or invalid parameters to method calls, when not traced directly to
 * user input.
 *
 * This deliberately does not extend InvalidInputException, and must be loggable
 */
class InvalidParameterException extends FlowException {
	public function __construct( $message ) {
		parent::__construct( $message, 'invalid-parameter' );
	}

	protected function getErrorCodeList() {
		// flow-error-invalid-parameter
		return array( 'invalid-parameter' );
	}
}