Пример #1
0
/**
 * Display a filesize in a human-readable format.
 *
 * #### Example Usage
 *
 * <pre>
 * {filesize 123} => "123 bytes"
 * {filesize 2048} => "2 kiB"
 * </pre>
 *
 * @param array  $params  Associative (and/or indexed) array of smarty parameters passed in from the template
 * @param Smarty $smarty  Parent Smarty template object
 *
 * @return string
 * @throws SmartyException
 */
function smarty_function_filesize($params, $smarty){
	
	$size = $params[0];
	
	return \Core\Filestore\format_size($size);
}
Пример #2
0
	/**
	 * Get the breakdown of recorded events and their time into the profiler operation.
	 * 
	 * @return string
	 */
	public function getEventTimesFormatted(){
		$out = '';
		foreach ($this->getEvents() as $t) {
			$in = round($t['timetotal'], 5) * 1000;
			$dcm = I18NLoader::GetLocaleConv('decimal_point');

			if ($in == 0){
				$time = '0000' . $dcm . '00 ms';
			}
			else{
				$parts = explode($dcm, $in);
				$whole = str_pad($parts[0], 4, 0, STR_PAD_LEFT);
				$dec   = (isset($parts[1])) ? str_pad($parts[1], 2, 0, STR_PAD_RIGHT) : '00';
				$time = $whole . $dcm . $dec . ' ms';
			}

			$mem = '[mem: ' . \Core\Filestore\format_size($t['memory']) . '] ';

			$event = $t['event'];

			$out .= "[$time] $mem- $event" . "\n";
		}

		return $out;
	}
Пример #3
0
	/**
	 * Utility function to translate a filesize in bytes into a human-readable version.
	 *
	 * @deprecated 2013.05.31
	 *
	 * @param int $filesize Filesize in bytes
	 * @param int $round Precision to round to
	 *
	 * @return string
	 */
	public static function FormatSize($filesize, $round = 2) {
		return \Core\Filestore\format_size($filesize, $round);
	}
Пример #4
0
	/**
	 * Fetch this view as an HTML string.
	 * @return mixed|null|string
	 */
	public function fetch() {

		if($this->_fetchCache !== null){
			// w00t ;)
			return $this->_fetchCache;
		}

		try{
			$body = $this->fetchBody();
			\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record(
				'Fetched application content from within View->fetch() for ' . $this->templatename
			);
		}
		catch(Exception $e){
			$this->error = View::ERROR_SERVERERROR;
			\Core\ErrorManagement\exception_handler($e, ($this->mode == View::MODE_PAGE));
			$body = '';
		}


		// If there's no template, I have nothing to even do!
		if ($this->mastertemplate === false) {
			return $body;
		}
		// Else if it's null, it's just not set yet :p
		// @deprecated here!
		elseif ($this->mastertemplate === null) {
			$this->mastertemplate = ConfigHandler::Get('/theme/default_template');
		}

		// Whee!
		//var_dump($this->templatename, Core\Templates\Template::ResolveFile($this->templatename));
		// Content types take priority on controlling the master template.
		if ($this->contenttype == View::CTYPE_JSON) {
			$mastertpl = false;
		}
		else {
			// Master template depends on the render mode.
			switch ($this->mode) {
				case View::MODE_PAGEORAJAX:
					if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){
						$mastertpl = false;
						$this->mode = View::MODE_AJAX;
					}
					else{
						$mastertpl = ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/skins/' . $this->mastertemplate;
						$this->mode = View::MODE_PAGE;
					}
					break;
				case View::MODE_NOOUTPUT:
				case View::MODE_AJAX:
					$mastertpl = false;
					break;
				case View::MODE_PAGE:
				case View::MODE_EMAILORPRINT:
					$mastertpl = Core\Templates\Template::ResolveFile('skins/' . $this->mastertemplate);
					//$mastertpl = ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/skins/' . $this->mastertemplate;
					break;
				case View::MODE_WIDGET:
					$mastertpl = Core\Templates\Template::ResolveFile('widgetcontainers/' . $this->mastertemplate);
					break;
			}
		}

		// If there's *still* no template, I still have nothing to do.
		if (!$mastertpl) return $body;


		$template = \Core\Templates\Template::Factory($mastertpl);
		// Ensure that the template is linked to this View correctly.
		$template->setView($this);
		//$template = new Core\Templates\Template();
		//$template->setBaseURL('/');
		// Page-level views have some special variables.
		if ($this->mode == View::MODE_PAGE) {
			$template->assign('breadcrumbs', $this->getBreadcrumbs());
			$template->assign('controls', $this->controls);
			$template->assign('messages', Core::GetMessages());

			// Tack on the pre and post body variables from the current page.
			//$body = CurrentPage::GetBodyPre() . $body . CurrentPage::GetBodyPost();
		}
		// Widgets need some special variables too.
		//if($this->mode == View::MODE_WIDGET){
		//	//var_dump($this->getVariable('widget')); die();
		//	$template->assign('widget', $this->getVariable('widget'));
		//}


		// This logic is needed for the SEO title, since that's usually completely human unfriendly.
		if(isset($this->meta['title']) && $this->meta['title']){
			$template->assign('seotitle', $this->meta['title']);
		}
		else{
			$template->assign('seotitle', $this->getTitle());
		}
		$template->assign('title', $this->getTitle());
		$template->assign('body', $body);

		// The body needs some custom classes for assisting the designers.
		// These are mainly pulled from the UA.
		$ua = \Core\UserAgent::Construct();

		$this->bodyclasses = array_merge($this->bodyclasses, $ua->getPseudoIdentifier(true));

		// Provide a way for stylesheets to target this page specifically.
		switch ($this->error) {
			case View::ERROR_BADREQUEST:
			case View::ERROR_PAYMENTREQUIRED:
			case View::ERROR_ACCESSDENIED:
			case View::ERROR_NOTFOUND:
			case View::ERROR_METHODNOTALLOWED:
			case View::ERROR_NOTACCEPTABLE:
			case View::ERROR_PROXYAUTHENTICATIONREQUIRED:
			case View::ERROR_REQUESTTIMEOUT:
			case View::ERROR_CONFLICT:
			case View::ERROR_GONE:
			case View::ERROR_LENGTHREQUIRED:
			case View::ERROR_PRECONDITIONFAILED:
			case View::ERROR_ENTITYTOOLARGE:
			case View::ERROR_URITOOLARGE:
			case View::ERROR_UNSUPPORTEDMEDIATYPE:
			case View::ERROR_RANGENOTSATISFIABLE:
			case View::ERROR_EXPECTATIONFAILED:
			case View::ERROR_UNAUTHORIZED:
				$url = 'error-' . $this->error;
				break;
			case 403:
				$url = "error-403 page-user-login";
				break;
			default:
				$url  = strtolower(trim(preg_replace('/[^a-z0-9\-]*/i', '', str_replace('/', '-', $this->baseurl)), '-'));
		}

		while($url != ''){
			$this->bodyclasses[] = 'page-' . $url;
			$url = substr($url, 0, strrpos($url, '-'));
		}


		$bodyclasses = strtolower(implode(' ', $this->bodyclasses));
		$template->assign('body_classes', $bodyclasses);

		try{
			$data = $template->fetch();
		}
		catch(SmartyException $e){
			$this->error = View::ERROR_SERVERERROR;
			error_log('[view error]');
			error_log('Template name: [' . $mastertpl . ']');
			\Core\ErrorManagement\exception_handler($e);
			require(ROOT_PDIR . 'core/templates/halt_pages/fatal_error.inc.html');
			die();
		}
		catch(TemplateException $e){
			$this->error = View::ERROR_SERVERERROR;
			error_log('[view error]');
			error_log('Template name: [' . $mastertpl . ']');
			\Core\ErrorManagement\exception_handler($e);
			require(ROOT_PDIR . 'core/templates/halt_pages/fatal_error.inc.html');
			die();
		}

		if($this->mode == View::MODE_EMAILORPRINT && $this->contenttype == View::CTYPE_HTML){
			// Inform other elements that the page is just about to be rendered.
			HookHandler::DispatchHook('/core/page/rendering', $this);

			// Replace the </head> tag with the head data from the current page
			// and the </body> with the foot data from the current page.
			// This is needed to be done at this stage because some element in
			// the template after rendering may add additional script to the head.
			// Also tack on any attributes for the <html> tag.
			if(preg_match('#</head>#i', $data)){
				// I need to do preg_replace because I only want to replace the FIRST instance of </head>
				$data = preg_replace('#</head>#i', $this->getHeadContent() . "\n" . '</head>', $data, 1);
			}
		}
		elseif ($this->mode == View::MODE_PAGE && $this->contenttype == View::CTYPE_HTML) {
			// Inform other elements that the page is just about to be rendered.
			HookHandler::DispatchHook('/core/page/rendering', $this);

			// Metadata!  w00t

			// Replace the </head> tag with the head data from the current page
			// and the </body> with the foot data from the current page.
			// This is needed to be done at this stage because some element in
			// the template after rendering may add additional script to the head.
			// Also tack on any attributes for the <html> tag.
			if(preg_match('#</head>#i', $data)){
				// I need to do preg_replace because I only want to replace the FIRST instance of </head>
				$data = preg_replace('#</head>#i', $this->getHeadContent() . "\n" . '</head>', $data, 1);
			}
			if(preg_match('#</body>#i', $data)){
				// I need to use strrpos because I only want the LAST instance of </body>
				$match = strrpos($data, '</body>');

				$foot = $this->getFootContent();

				if(defined('ENABLE_XHPROF') && function_exists('xhprof_disable')){
					require_once('xhprof_lib/utils/xhprof_lib.php'); #SKIPCOMPILER
					require_once('xhprof_lib/utils/xhprof_runs.php'); #SKIPCOMPILER
					$xhprof_data = xhprof_disable();
					$namespace = trim(str_replace(['.', '/'], '-', HOST . REL_REQUEST_PATH), '-');
					$xhprof_runs = new XHProfRuns_Default();
					$run_id = $xhprof_runs->save_run($xhprof_data, $namespace);

					define('XHPROF_RUN', $run_id);
					define('XHPROF_SOURCE', $namespace);

					$xhprof_link = sprintf(
						'<a href="' . SERVERNAME . '/xhprof/index.php?run=%s&source=%s" target="_blank">View XHprof Profiler Report</a>' . "\n",
						$run_id,
						$namespace
					);
				}
				else{
					$xhprof_link = '';
				}

				// If the viewmode is regular and DEVELOPMENT_MODE is enabled, show some possibly useful information now that everything's said and done.
				if (DEVELOPMENT_MODE) {
					$legend = '<div class="fieldset-title">%s<i class="icon-chevron-down expandable-hint"></i><i class="icon-chevron-up collapsible-hint"></i></div>' . "\n";

					$debug = '';
					$debug .= '<pre class="xdebug-var-dump screen">';
					$debug .= '<fieldset class="debug-section collapsible" id="debug-section-template-information">';
					$debug .= sprintf($legend, 'Template Information');
					$debug .= "<span>";
					$debug .= 'Base URL: ' . $this->baseurl . "\n";
					$debug .= 'Template Requested: ' . $this->templatename . "\n";
					$debug .= 'Template Actually Used: ' . \Core\Templates\Template::ResolveFile($this->templatename) . "\n";
					$debug .= 'Master Skin: ' . $this->mastertemplate . "\n";
					$debug .= "</span>";
					$debug .= '</fieldset>';

					$debug .= '<fieldset class="debug-section collapsible" id="debug-section-performance-information">';
					$debug .= sprintf($legend, 'Performance Information');
					$debug .= "<span>";
					$debug .= $xhprof_link;
					$debug .= "Database Reads: " . \Core\Utilities\Profiler\DatamodelProfiler::GetDefaultProfiler()->readCount() . "\n";
					$debug .= "Database Writes: " . \Core\Utilities\Profiler\DatamodelProfiler::GetDefaultProfiler()->writeCount() . "\n";
					//$debug .= "Number of queries: " . DB::Singleton()->counter . "\n";
					//$debug .= "Amount of memory used by PHP: " . \Core\Filestore\format_size(memory_get_usage()) . "\n";
					$debug .= "Amount of memory used by PHP: " . \Core\Filestore\format_size(memory_get_peak_usage(true)) . "\n";
					$profiler = Core\Utilities\Profiler\Profiler::GetDefaultProfiler();
					$debug .= "Total processing time: " . $profiler->getTimeFormatted() . "\n";
					$debug .= "</span>";
					$debug .= '</fieldset>';

					$debug .= '<fieldset class="debug-section collapsible" id="debug-section-profiler-information">';
					$debug .= sprintf($legend, 'Core Profiler');
					$debug .= "<span>";
					$debug .= $profiler->getEventTimesFormatted();
					$debug .= "</span>";
					$debug .= '</fieldset>';

					$debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-components-information">';
					// Tack on what components are currently installed.
					$debug .= sprintf($legend, 'Available Components');
					$debugcomponents = array_merge(Core::GetComponents(), Core::GetDisabledComponents());
					$debug .= "<span>";
					// Give me sorting!
					ksort($debugcomponents);
					foreach ($debugcomponents as $l => $v) {
						if($v->isEnabled() && $v->isReady()){
							$debug .= '[<span style="color:green;">Enabled</span>]';
						}
						elseif($v->isEnabled() && !$v->isReady()){
							$debug .= '[<span style="color:red;">!ERROR!</span>]';
						}
						else{
							$debug .= '[<span style="color:red;">Disabled</span>]';
						}


						$debug .= $v->getName() . ' ' . $v->getVersion() . "<br/>";
					}
					$debug .= "</span>";
					$debug .= '</fieldset>';

					$debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-hooks-information">';
					// I wanna see what hooks are registered too!
					$debug .= sprintf($legend, 'Registered Hooks');
					foreach(HookHandler::GetAllHooks() as $hook){
						$debug .= "<span>";
						/** @var $hook Hook */
						$debug .= $hook->name;
						if($hook->description) $debug .= ' <em> - ' . $hook->description . '</em>';
						$debug .= "\n" . '<span style="color:#999;">Return expected: ' . $hook->returnType . '</span>';
						$debug .= "\n" . '<span style="color:#999;">Attached by ' . $hook->getBindingCount() . ' binding(s).</span>';
						foreach($hook->getBindings() as $b){
							$debug .= "\n" . ' * ' . $b['call'];
						}
						$debug .= "\n\n";
						$debug .= "</span>";
					}
					$debug .= '</fieldset>';

					// Display the licensed content on this application
					$debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-licenser-information">';
					$debug .= sprintf($legend, 'Licensed Information');
					$lic = \Core\Licenser::GetRaw();
					$debug .= '<div>';
					foreach($lic as $dat){
						$debug .= $dat['url'] . '::' . $dat['feature'] . ' => ' . $dat['value'] . "\n";
					}
					$debug .= '</div></fieldset>';

					$debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-includes-information">';
					// I want to see how many files were included.
					$debug .= sprintf($legend, 'Included Files');
					$debug .= '<span>Number: ' . sizeof(get_included_files()) . "</span>";
					$debug .= '<span>'. implode("<br/>", get_included_files()) . "</span>";
					$debug .= '</fieldset>';

					$debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-query-information">';
					$debug .= sprintf($legend, 'Query Log');
					$profiler = \Core\Utilities\Profiler\DatamodelProfiler::GetDefaultProfiler();
					$debug .= '<div>' . $profiler->getEventTimesFormatted() . '</div>';
					$debug .= '</fieldset>';

					// Display all the i18n strings available on the system.
					$debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-i18nstrings-information">';
					$debug .= sprintf($legend, 'I18N Strings Available');
					$strings = \Core\i18n\I18NLoader::GetAllStrings();
					$debug .= '<ul>';
					foreach($strings as &$s){
						$debug .= '<li>' . $s['key'] . '</li>';
					}
					$debug .= '</ul>';
					$debug .= '</fieldset>';
					$debug .= '</pre>';

					// And append!
					$foot .= "\n" . $debug;
				}
				$data = substr_replace($data, $foot . "\n" . '</body>', $match, 7);
			}
			$data = preg_replace('#<html#', '<html ' . $this->getHTMLAttributes(), $data, 1);


			// This logic has been migrated to the {$body_classes} variable.
			/*
			if(preg_match('/<body[^>]*>/', $data, $matches)){
				// body is $matches[0].
				$fullbody = $matches[0];
				if($fullbody == '<body>'){
					$body = '<body class="' . $bodyclass . '">';
				}
				elseif(strpos($fullbody, 'class=') === false){
					// Almost as easy, other elements but no class.
					$body = substr($fullbody, 0, -1) . ' class="' . $bodyclass . '">';
				}
				else{
					// parsing HTML is far easier with XML objects.
					$node = new SimpleXMLElement($fullbody . '</body>');
					$body = '<body';
					foreach($node->attributes() as $k => $v){
						if($k == 'class'){
							$body .= ' ' . $k . '="' . $bodyclass . ' ' . $v . '"';
						}
						else{
							$body .= ' ' . $k . '="' . $v . '"';
						}
					}
					$body .= '>';
				}

				// And replace!
				$data = preg_replace('#<body[^>]*>#', $body, $data, 1);
			}
			*/
		}

		$this->_fetchCache = $data;

		return $data;
	}