<commit_before><?php
/*
 * Copyright (C) 2011-2015 Solver Ltd. All rights reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
namespace Solver\Lab;

/**
 * Base class for page handlers (i.e. controllers, in a typical web MVC framework).
 * 
 * You don't need to use this particular class, the dispatcher and router will accept any callable format. This class
 * is one possible base class for a page controller, and provides shortcuts and functionality typically needed for it.
 */
abstract class Page {
	/**
	 * A dict of inputs as passed by the router (for details, see \Solver\Lab\Router::dispatch()), wrapped in a 
	 * DataBox instance for convenient data access.
	 *
	 * @var \Solver\Lab\DataBox
	 */
	protected $input;

	/**
	 * A dict of parameters, which the page accumulates, and passes to the template(s).
	 *
	 * This is part of the "viewmodel" in the framework. The other part is property $log.
	 *
	 * @var array
	 */
	protected $data = [];

	/**
	 * A log of success/info/warning/error events, which the page accumulates, and passes to the template(s).
	 *
	 * This is part of the "viewmodel" in the framework. The other part is property $data.
	 *
	 * @var \Solver\Lab\PageLog
	 */
	protected $log = [];

	final public function __invoke(array $input) {
		try {
			$this->input = new DataBox($input);
			$this->log = new PageLog();
			$this->main(); 
		} catch (\Exception $e) {
			if ($e instanceof PageException) {
				// TODO: Eating the exception when the code is 0 is a feature we should reconsider (needed for the time
				// being as a flow control clutch when a super method wants to display an error and make sure the sub
				// method doesn't execute /say, after redirecting to a login page/). 
				if ($e->getCode() != 0) throw $e;
			} else {
				// Any other exception type is a sign of unexpected application failure.
				
				// For development setups, let it bubble up.
				if (\DEBUG) throw $e;

				// For production setups, log it and continue to a status 500 page.
				\error_log(sprintf("%s: %s\n%s",
					get_class($e),
					$e->getMessage(),
					$e->getTraceAsString()
				));
				
				throw new PageException(null, 500, $e);
			}
		}
	}

	/**
	 * This method will get called when the dispatcher invokes a page. Define this method in your subclass.
	 */
	abstract public function main();

	/**
	 * Renders a view template.
	 *
	 * @param string $templateId
	 * Optional (default = null).
	 *
	 * Special symbols:
	 * 
	 * - You can use "@" to refer to the page class name, so "@\ExampleTemplate", when executed for class "Foo\BarPage"
	 * will resolve to template id "Foo\BarPage\ExampleTemplate".
	 * - You can use '.' to refer to the page class namespace, so ".\ExampleTemplate", when when executed for class
	 * "Foo\BarPage" will resolve to template id "Foo\ExampleTemplate".
	 * 
	 * Without a dot "." or at "@", names are considered absolute.
	 * 
	 * The default value if you pass null (or nothing) for template id is "@\Template".
	 * 
	 * LEGACY: Page class names ending in Controller will be resolved by default (if templateId is null or not passed)
	 * to names ending in View. For example, for controller "Foo\BarController", the assumed template identifier will be
	 * "Foo\BarView". This will be removed in the future.
	 *
	 * For a detailed description of what a "template id" is, see AbstractTemplate::__construct().
	 */
	final protected function renderTemplate($templateId = null) {
		$class = get_class($this);
		$namespace = preg_replace('/^(.*)\\\\[\w\.\@]$/', '', $class);
			
		if ($templateId === null) {
			// Legacy resolution.
			if (preg_match('/^(.*)Controller$/', $class, $matches)) {
				$templateId = $matches[1] . 'View';
			} else {
				$templateId = '@\Template';
			}
		}
		
		$templateId = str_replace(['@', '.'], [$class, $namespace], $templateId);
		
		$template = new Template($templateId);
		$template($this->data, $this->log);
	}
	
	/**
	 * Legacy alias. See renderTemplate().
	 * 
	 * @deprecated
	 * 
	 * @param string $templateId
	 */
	final protected function renderView($templateId = null) {
		$this->renderTemplate($templateId);
	}
	
	/**
	 * Identical to renderTemplate(), however instead of allowing the template to render to the output stream, it
	 * captures the output and returns it as a string.
	 * 
	 * Certain special actions, like the template setting HTTP headers can't be captured.
	 * 
	 * @param string $templateId
	 * Optional (default = null). Template id, see renderTemplate() for details.
	 */
	final protected function captureTemplate($templateId = null) {
		ob_start();<commit_msg>Class Page: Default resolution for templates changed from @\Template to @\DefaultTemplate (BC break).<commit_after><?php
/*
 * Copyright (C) 2011-2015 Solver Ltd. All rights reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
namespace Solver\Lab;

/**
 * Base class for page handlers (i.e. controllers, in a typical web MVC framework).
 * 
 * You don't need to use this particular class, the dispatcher and router will accept any callable format. This class
 * is one possible base class for a page controller, and provides shortcuts and functionality typically needed for it.
 */
abstract class Page {
	/**
	 * A dict of inputs as passed by the router (for details, see \Solver\Lab\Router::dispatch()), wrapped in a 
	 * DataBox instance for convenient data access.
	 *
	 * @var \Solver\Lab\DataBox
	 */
	protected $input;

	/**
	 * A dict of parameters, which the page accumulates, and passes to the template(s).
	 *
	 * This is part of the "viewmodel" in the framework. The other part is property $log.
	 *
	 * @var array
	 */
	protected $data = [];

	/**
	 * A log of success/info/warning/error events, which the page accumulates, and passes to the template(s).
	 *
	 * This is part of the "viewmodel" in the framework. The other part is property $data.
	 *
	 * @var \Solver\Lab\PageLog
	 */
	protected $log = [];

	final public function __invoke(array $input) {
		try {
			$this->input = new DataBox($input);
			$this->log = new PageLog();
			$this->main(); 
		} catch (\Exception $e) {
			if ($e instanceof PageException) {
				// TODO: Eating the exception when the code is 0 is a feature we should reconsider (needed for the time
				// being as a flow control clutch when a super method wants to display an error and make sure the sub
				// method doesn't execute /say, after redirecting to a login page/). 
				if ($e->getCode() != 0) throw $e;
			} else {
				// Any other exception type is a sign of unexpected application failure.
				
				// For development setups, let it bubble up.
				if (\DEBUG) throw $e;

				// For production setups, log it and continue to a status 500 page.
				\error_log(sprintf("%s: %s\n%s",
					get_class($e),
					$e->getMessage(),
					$e->getTraceAsString()
				));
				
				throw new PageException(null, 500, $e);
			}
		}
	}

	/**
	 * This method will get called when the dispatcher invokes a page. Define this method in your subclass.
	 */
	abstract public function main();

	/**
	 * Renders a view template.
	 *
	 * @param string $templateId
	 * Optional (default = null).
	 *
	 * Special symbols:
	 * 
	 * - You can use "@" to refer to the page class name, so "@\ExampleTemplate", when executed for class "Foo\BarPage"
	 * will resolve to template id "Foo\BarPage\ExampleTemplate".
	 * - You can use '.' to refer to the page class namespace, so ".\ExampleTemplate", when when executed for class
	 * "Foo\BarPage" will resolve to template id "Foo\ExampleTemplate".
	 * 
	 * Without a dot "." or at "@", names are considered absolute.
	 * 
	 * The default value if you pass null (or nothing) for template id is "@\DefaultTemplate".
	 * 
	 * LEGACY: Page class names ending in Controller will be resolved by default (if templateId is null or not passed)
	 * to names ending in View. For example, for controller "Foo\BarController", the assumed template identifier will be
	 * "Foo\BarView". This will be removed in the future.
	 *
	 * For a detailed description of what a "template id" is, see AbstractTemplate::__construct().
	 */
	final protected function renderTemplate($templateId = null) {
		$class = get_class($this);
		$namespace = preg_replace('/^(.*)\\\\[\w\.\@]$/', '', $class);
			
		if ($templateId === null) {
			if (preg_match('/^(.*)Controller$/', $class, $matches)) { // Legacy resolution.
				$templateId = $matches[1] . 'View';
			} else { // New resolution.
				$templateId = '@\DefaultTemplate';
			}
		}
		
		$templateId = str_replace(['@', '.'], [$class, $namespace], $templateId);
		
		$template = new Template($templateId);
		$template($this->data, $this->log);
	}
	
	/**
	 * Legacy alias. See renderTemplate().
	 * 
	 * @deprecated
	 * 
	 * @param string $templateId
	 */
	final protected function renderView($templateId = null) {
		$this->renderTemplate($templateId);
	}
	
	/**
	 * Identical to renderTemplate(), however instead of allowing the template to render to the output stream, it
	 * captures the output and returns it as a string.
	 * 
	 * Certain special actions, like the template setting HTTP headers can't be captured.
	 * 
	 * @param string $templateId
	 * Optional (default = null). Template id, see renderTemplate() for details.
	 */
	final protected function captureTemplate($templateId = null) {
		ob_start();
{'fraction_non_alphanumeric': 0.1154741128563118, 'fraction_numerical': 0.004072134962187318, 'mean_word_length': 3.250103007828595, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6879112', 'n_tokens_mistral': 3237, 'n_tokens_neox': 2794, 'n_words': 1241}