2353 lines
		
	
	
	
		
			58 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			2353 lines
		
	
	
	
		
			58 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace gp\tool{
 | 
						|
 | 
						|
	defined('is_running') or die('Not an entry point...');
 | 
						|
 | 
						|
	global $GP_ARRANGE, $gpOutConf;
 | 
						|
 | 
						|
	$GP_ARRANGE	= true;
 | 
						|
	$gpOutConf	= [];
 | 
						|
 | 
						|
 | 
						|
	//named menus should just be shortcuts to the numbers in custom menu
 | 
						|
	//	custom menu format: $top_level,$bottom_level,$expand_level
 | 
						|
 | 
						|
	//custom menu: 0,0,0,0
 | 
						|
	$gpOutConf['FullMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetFullMenu',
 | 
						|
		'link'		=> 'all_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: 0,0,1,1
 | 
						|
	$gpOutConf['ExpandMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetExpandMenu',
 | 
						|
		'link'		=> 'expanding_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: 0,0,2,1
 | 
						|
	$gpOutConf['ExpandLastMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetExpandLastMenu',
 | 
						|
		'link'		=> 'expanding_bottom_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: 0,1,0,0
 | 
						|
	$gpOutConf['Menu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetMenu',
 | 
						|
		'link'		=> 'top_level_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: 1,0,0,0
 | 
						|
	$gpOutConf['SubMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetSubMenu',
 | 
						|
		'link'		=> 'subgroup_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: 0,2,0,0
 | 
						|
	$gpOutConf['TopTwoMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetTopTwoMenu',
 | 
						|
		'link'		=> 'top_two_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: does not translate, this pays no attention to grouping
 | 
						|
	$gpOutConf['BottomTwoMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetBottomTwoMenu',
 | 
						|
		'link'		=> 'bottom_two_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: 1,2,0,0
 | 
						|
	$gpOutConf['MiddleSubMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetSecondSubMenu',
 | 
						|
		'link'		=> 'second_sub_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu: 2,3,0,0
 | 
						|
	$gpOutConf['BottomSubMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'GetThirdSubMenu',
 | 
						|
		'link'		=> 'third_sub_links',
 | 
						|
	];
 | 
						|
 | 
						|
	//custom menu
 | 
						|
	$gpOutConf['CustomMenu'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'CustomMenu',
 | 
						|
	];
 | 
						|
 | 
						|
	//breadcrumb nav
 | 
						|
	$gpOutConf['Breadcrumbs'] = [
 | 
						|
		'class'		=> '\\gp\\tool\\Output\\Menu',
 | 
						|
		'method'	=> 'BreadcrumbNav',
 | 
						|
		'link'		=> 'Breadcrumb Links',
 | 
						|
	];
 | 
						|
	//$gpOutConf['Breadcrumbs']['method']	= ['\\gp\\tool\\Output', 'BreadcrumbNav'];
 | 
						|
	//$gpOutConf['Breadcrumbs']['link']		= 'Breadcrumb Links';
 | 
						|
 | 
						|
 | 
						|
	$gpOutConf['Extra']['method']			= ['\\gp\\tool\\Output', 'GetExtra'];
 | 
						|
 | 
						|
	//$gpOutConf['Text']['method']			= ['\\gp\\tool\\Output','GetText']; //use Area() and GetArea() instead
 | 
						|
 | 
						|
	//$gpOutConf['Image']['method']			= ['\\gp\\tool\\Output','GetImage'];
 | 
						|
 | 
						|
	/* The following methods should be used with \gp\tool\Output'::Fetch() */
 | 
						|
	$gpOutConf['Gadget']['method']			= ['\\gp\\tool\\Output', 'GetGadget'];
 | 
						|
 | 
						|
 | 
						|
	class Output{
 | 
						|
 | 
						|
		public static $components			= '';
 | 
						|
		public static $editlinks			= '';
 | 
						|
		public static $template_included	= false;
 | 
						|
 | 
						|
		private static $out_started			= false;
 | 
						|
		private static $gadget_cache		= [];
 | 
						|
 | 
						|
		public static $edit_area_id			= '';
 | 
						|
 | 
						|
		private static $catchable			= [];
 | 
						|
 | 
						|
		public static $lang_values			= [];
 | 
						|
		public static $inline_vars			= [];
 | 
						|
		public static $nested_edit			= false;
 | 
						|
 | 
						|
		private static $edit_index			= 0;
 | 
						|
 | 
						|
		private static $head_css			= '';
 | 
						|
		private static $head_content		= '';
 | 
						|
		private static $head_js				= '';
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Backwards compat for functions moved to \gp\tool\Output\Menu
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function __callStatic($name, $args){
 | 
						|
 | 
						|
			if( method_exists('\\gp\\tool\\Output\\Menu', $name) ){
 | 
						|
				$menu = new \gp\tool\Output\Menu();
 | 
						|
				return call_user_func_array([$menu, $name], $args);
 | 
						|
			}
 | 
						|
 | 
						|
			throw new \Exception('Call to undefined method gp\\tool\\Output::' . $name);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/*
 | 
						|
		 *
 | 
						|
		 * Request Type Functions
 | 
						|
		 * functions used in conjuction with $_REQUEST['gpreq']
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
 | 
						|
 | 
						|
		 public static function Prep(){
 | 
						|
			global $page;
 | 
						|
			if( !isset($page->rewrite_urls) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			ini_set('arg_separator.output', '&');
 | 
						|
			foreach($page->rewrite_urls as $key => $value){
 | 
						|
				output_add_rewrite_var($key, $value);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Send only messages and the content buffer to the client
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function Flush(){
 | 
						|
			global $page;
 | 
						|
			self::StandardHeaders();
 | 
						|
			echo GetMessages();
 | 
						|
			echo $page->contentBuffer;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function Content(){
 | 
						|
			global $page;
 | 
						|
			self::StandardHeaders();
 | 
						|
			echo GetMessages();
 | 
						|
			$page->GetGpxContent();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function StandardHeaders(){
 | 
						|
			header('Content-Type: text/html; charset=utf-8');
 | 
						|
			Header('Vary: Accept,Accept-Encoding'); // for proxies
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Send only the messages and content as a simple html document
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function BodyAsHTML(){
 | 
						|
			global $page;
 | 
						|
 | 
						|
			self::$inline_vars['gp_bodyashtml']	= true;
 | 
						|
 | 
						|
			self::TemplateSettings();
 | 
						|
 | 
						|
			self::StandardHeaders();
 | 
						|
 | 
						|
			echo '<!DOCTYPE html>';
 | 
						|
			echo '<html lang="' . $page->lang . '"><head><meta charset="UTF-8" />';
 | 
						|
			self::getHead();
 | 
						|
			echo '</head>';
 | 
						|
 | 
						|
			echo '<body class="gpbody">';
 | 
						|
			echo GetMessages();
 | 
						|
 | 
						|
			$page->GetGpxContent();
 | 
						|
 | 
						|
			echo '</body>';
 | 
						|
			echo '</html>';
 | 
						|
 | 
						|
			self::HeadContent();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function AdminHtml(){
 | 
						|
			global $page;
 | 
						|
 | 
						|
			//\gp\tool\Output::$inline_vars['gp_bodyashtml']	= true;
 | 
						|
 | 
						|
			self::StandardHeaders();
 | 
						|
 | 
						|
			echo '<!DOCTYPE html>';
 | 
						|
			echo '<html class="admin_body" lang="' . $page->lang . '"><head><meta charset="UTF-8" />';
 | 
						|
			self::getHead();
 | 
						|
			echo '</head>';
 | 
						|
 | 
						|
			echo '<body class="gpbody">';
 | 
						|
			echo GetMessages();
 | 
						|
 | 
						|
			$page->GetGpxContent();
 | 
						|
 | 
						|
			echo '</body>';
 | 
						|
			echo '</html>';
 | 
						|
 | 
						|
			self::HeadContent();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get default values from customizer if it exists
 | 
						|
		 * return empty array otherwise
 | 
						|
		 *
 | 
						|
		 * Layout installer will pass a customizer file path
 | 
						|
		 *
 | 
						|
		 * @static
 | 
						|
		 * @since 5.2
 | 
						|
		 * @param string $used_in
 | 
						|
		 * @param string $customizer_file
 | 
						|
		 * @return array
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetCustomizerDefaults($used_in='', $customizer_file=''){
 | 
						|
			global $page;
 | 
						|
 | 
						|
			if( empty($customizer_file) ){
 | 
						|
				$layout_dir			= $page->theme_dir . '/' . $page->theme_color;
 | 
						|
				$customizer_file	= $layout_dir . '/customizer.php';
 | 
						|
			}
 | 
						|
 | 
						|
			if( !file_exists($customizer_file) ){
 | 
						|
				// msg('customizer file ' . htmlspecialchars($customizer_file) . ' does not exist'); // TODO remove
 | 
						|
				return [];
 | 
						|
			};
 | 
						|
 | 
						|
			$customizer = \gp\tool\Files::Get($customizer_file, 'customizer');
 | 
						|
			// debug('$customizer = ' . pre($customizer));
 | 
						|
			$defaults		= [];
 | 
						|
 | 
						|
			foreach($customizer as $section => $section_data){
 | 
						|
 | 
						|
				foreach($section_data['items'] as $item_name => $item_data){
 | 
						|
					if( !empty($used_in) &&
 | 
						|
						isset($item_data['control']['used_in']) &&
 | 
						|
						is_array($item_data['control']['used_in']) &&
 | 
						|
						!in_array($used_in, $item_data['control']['used_in'])
 | 
						|
					){
 | 
						|
						continue;
 | 
						|
					}
 | 
						|
 | 
						|
					$defaults[$item_name]['value'] = $item_data['default_value'];
 | 
						|
					if( !empty($item_data['default_units']) ){
 | 
						|
						$defaults[$item_name]['units'] = $item_data['default_units'];
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			return $defaults;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get javascript values from the layout
 | 
						|
		 * if the layout has no stored js_vals, try to get customizer defaults
 | 
						|
		 * otherwise return empty string
 | 
						|
		 *
 | 
						|
		 * @static
 | 
						|
		 * @since 5.2
 | 
						|
		 * @return string js expression like 'var layout_config = JSON;'
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetLayoutJsVars(){
 | 
						|
			global $page, $gpLayouts;
 | 
						|
 | 
						|
			if( $page->gpLayout ){
 | 
						|
				$layout_info = $gpLayouts[$page->gpLayout];
 | 
						|
				if( isset($layout_info['js_vars']) ){
 | 
						|
					return $layout_info['js_vars'];
 | 
						|
				}
 | 
						|
			}
 | 
						|
			
 | 
						|
			$js_vars = self::GetCustomizerDefaults('js');
 | 
						|
			return "\n" . 'var layout_config = ' . json_encode($js_vars) . ';' . "\n";
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get configuration array from the layout
 | 
						|
		 * if the layout has no stored config, try to get customizer defaults
 | 
						|
		 * otherwise return empty array
 | 
						|
		 *
 | 
						|
		 * @static
 | 
						|
		 * @since 5.2
 | 
						|
		 * @return array layout configuration
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetLayoutConfig(){
 | 
						|
			global $page, $gpLayouts;
 | 
						|
 | 
						|
			if( $page->gpLayout ){
 | 
						|
				$layout_info = $gpLayouts[$page->gpLayout];
 | 
						|
				if( isset($layout_info['config']) ){
 | 
						|
					return $layout_info['config'];
 | 
						|
				}
 | 
						|
			}
 | 
						|
			
 | 
						|
			return self::GetCustomizerDefaults('php');
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Send all content according to the current layout
 | 
						|
		 * @static
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Template(){
 | 
						|
			global $page, $gpLayouts, $layout_config;
 | 
						|
			global $GP_ARRANGE, $GP_STYLES, $get_all_gadgets_called;
 | 
						|
			global $addon_current_id, $GP_MENU_LINKS, $GP_MENU_CLASS;
 | 
						|
			global $GP_MENU_CLASSES, $GP_MENU_ELEMENTS;
 | 
						|
 | 
						|
			$get_all_gadgets_called		= false;
 | 
						|
			self::$template_included	= true;
 | 
						|
 | 
						|
			if( isset($page->theme_addon_id) ){
 | 
						|
				$addon_current_id = $page->theme_addon_id;
 | 
						|
			}
 | 
						|
			self::TemplateSettings();
 | 
						|
 | 
						|
			self::StandardHeaders();
 | 
						|
 | 
						|
			if( !empty($page->preview_layout_config) ){
 | 
						|
				// only exists in Layout Editor preview mode
 | 
						|
				$layout_config = $page->preview_layout_config;
 | 
						|
			}elseif( empty($layout_config) ){
 | 
						|
				$layout_config = self::GetLayoutConfig();
 | 
						|
			}
 | 
						|
			// debug('$layout_config = ' . pre($layout_config));
 | 
						|
 | 
						|
			$path = $page->theme_dir . '/template.php';
 | 
						|
 | 
						|
			$return = IncludeScript(
 | 
						|
				$path,
 | 
						|
				'require',
 | 
						|
				[
 | 
						|
					'page', 'layout_config',
 | 
						|
					'GP_ARRANGE',
 | 
						|
					'GP_MENU_LINKS', 'GP_MENU_CLASS',
 | 
						|
					'GP_MENU_CLASSES', 'GP_MENU_ELEMENTS'
 | 
						|
				]
 | 
						|
			);
 | 
						|
 | 
						|
			//return will be false if there's a fatal error with the template.php file
 | 
						|
			if( $return === false ){
 | 
						|
				self::BodyAsHtml();
 | 
						|
			}
 | 
						|
			\gp\tool\Plugins::ClearDataFolder();
 | 
						|
 | 
						|
			self::HeadContent();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the settings for the current theme if settings.php exists
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function TemplateSettings(){
 | 
						|
			global $page;
 | 
						|
 | 
						|
			$path = $page->theme_dir . '/settings.php';
 | 
						|
			IncludeScript($path, 'require_if', ['page', 'GP_GETALLGADGETS']);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add a Header to the response
 | 
						|
		 * The header will be discarded if it's an ajax request or similar
 | 
						|
		 *
 | 
						|
		 * @param string $header
 | 
						|
		 * @param bool $replace
 | 
						|
		 * @param int $code
 | 
						|
		 * @return bool
 | 
						|
		 */
 | 
						|
		public static function AddHeader($header, $replace=true, $code=null){
 | 
						|
			if( !empty($_REQUEST['gpreq']) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
			if( !is_null($code) ){
 | 
						|
				\gp\tool::status_header($code, $header);
 | 
						|
			}else{
 | 
						|
				header($header, $replace);
 | 
						|
			}
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/*
 | 
						|
		 *
 | 
						|
		 * Content Area Functions
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
 | 
						|
		 public static function GetContainerID($name, $arg=false){
 | 
						|
			static $indices;
 | 
						|
 | 
						|
			$name = str_replace(
 | 
						|
				['+', '/', '='],
 | 
						|
				['', '', ''],
 | 
						|
				base64_encode($name)
 | 
						|
			);
 | 
						|
			if( !isset($indices[$name]) ){
 | 
						|
				$indices[$name] = 0;
 | 
						|
			}else{
 | 
						|
				$indices[$name]++;
 | 
						|
			}
 | 
						|
			return $name . '_' . $indices[$name];
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Fetch the output and return as a string
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Fetch($default, $arg=''){
 | 
						|
			ob_start();
 | 
						|
			self::Get($default, $arg);
 | 
						|
			return ob_get_clean();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function Get($default='', $arg=''){
 | 
						|
			global $page, $gpLayouts, $gpOutConf;
 | 
						|
 | 
						|
			$outSet = false;
 | 
						|
			$outKeys = false;
 | 
						|
 | 
						|
			$layout_info =& $gpLayouts[$page->gpLayout];
 | 
						|
 | 
						|
			//container id
 | 
						|
			$container_id	= $default . ':' . substr($arg, 0, 10);
 | 
						|
			$container_id	= self::GetContainerID($container_id);
 | 
						|
 | 
						|
			if( isset($layout_info) && isset($layout_info['handlers']) ){
 | 
						|
				$handlers =& $layout_info['handlers'];
 | 
						|
				if( isset($handlers[$container_id]) ){
 | 
						|
					$outKeys	= $handlers[$container_id];
 | 
						|
					$outSet		= true;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//default values
 | 
						|
			if( !$outSet && isset($gpOutConf[$default]) ){
 | 
						|
				$outKeys[] = trim($default . ':' . $arg, ':');
 | 
						|
			}
 | 
						|
 | 
						|
			self::ForEachOutput($outKeys, $container_id);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function ForEachOutput($outKeys, $container_id){
 | 
						|
 | 
						|
			if( !is_array($outKeys) || (count($outKeys) == 0) ){
 | 
						|
				$info				= [];
 | 
						|
				$info['gpOutCmd']	= '';
 | 
						|
				self::CallOutput($info, $container_id);
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			foreach($outKeys as $gpOutCmd){
 | 
						|
				$info = self::GetgpOutInfo($gpOutCmd);
 | 
						|
				if( $info === false ){
 | 
						|
					trigger_error('gpOutCmd <i>' . $gpOutCmd . '</i> not set');
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				$info['gpOutCmd'] = $gpOutCmd;
 | 
						|
				self::CallOutput($info, $container_id);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/* static */
 | 
						|
		public static function GetgpOutInfo($gpOutCmd){
 | 
						|
			global $gpOutConf, $config;
 | 
						|
 | 
						|
			$key	= $gpOutCmd = trim($gpOutCmd, ':');
 | 
						|
			$info	= false;
 | 
						|
			$arg	= '';
 | 
						|
			$pos	= mb_strpos($key, ':');
 | 
						|
 | 
						|
			if( $pos > 0 ){
 | 
						|
				$arg = mb_substr($key, $pos + 1);
 | 
						|
				$key = mb_substr($key, 0, $pos);
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($gpOutConf[$key]) ){
 | 
						|
				$info = $gpOutConf[$key];
 | 
						|
			}elseif( isset($config['gadgets'][$key]) ){
 | 
						|
				$info = $config['gadgets'][$key];
 | 
						|
				$info['is_gadget'] = true;
 | 
						|
			}else{
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			$info['key']		= $key;
 | 
						|
			$info['arg']		= $arg;
 | 
						|
			$info['gpOutCmd']	= $gpOutCmd;
 | 
						|
 | 
						|
			return $info;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		public static function GpOutLabel($info){
 | 
						|
			global $langmessage;
 | 
						|
 | 
						|
			$info += ['arg' => '']; // suppress warning with older themes TODO: check the cause
 | 
						|
			$label = $info['arg'];
 | 
						|
			if( empty($label) ){
 | 
						|
				$label = $info['gpOutCmd'];
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($info['link']) && isset($langmessage[$info['link']]) ){
 | 
						|
				$label = $langmessage[$info['link']];
 | 
						|
			}
 | 
						|
 | 
						|
			return str_replace([' ', '_', ':'], [' ', ' ', ': '], $label);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function CallOutput($info,$container_id){
 | 
						|
			global $GP_ARRANGE, $page, $langmessage, $GP_MENU_LINKS;
 | 
						|
			global $GP_MENU_CLASS, $GP_MENU_CLASSES, $gp_current_container;
 | 
						|
 | 
						|
			$gp_current_container	= $container_id;
 | 
						|
			self::$out_started		= true;
 | 
						|
			self::$edit_area_id		= '';
 | 
						|
 | 
						|
			if( isset($info['disabled']) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//gpOutCmd identifies the output function used, there can only be one
 | 
						|
			if( !isset($info['gpOutCmd']) ){
 | 
						|
				trigger_error('gpOutCmd not set for $info in CallOutput()');
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//generate a class based on the area $info
 | 
						|
			if( isset($info['html']) ){
 | 
						|
				$class = $info['key'];
 | 
						|
				$class = preg_replace('#\[.*\]#', '', $class);
 | 
						|
			}else{
 | 
						|
				$class = $info['gpOutCmd'];
 | 
						|
			}
 | 
						|
 | 
						|
			//add gpMenu class to all menu areas for better styling
 | 
						|
			$add_menu_class = '';
 | 
						|
			if( isset($info['class']) && $info['class'] == '\gp\tool\Output\Menu' ){
 | 
						|
				$add_menu_class = 'gpMenu ';
 | 
						|
			}
 | 
						|
			$class			= $add_menu_class . 'gpArea_' . str_replace([':', ','], ['_', ''], trim($class, ':'));
 | 
						|
			$param			= $container_id . '|' . $info['gpOutCmd'];
 | 
						|
			$permission		= self::ShowEditLink('Admin_Theme_Content');
 | 
						|
 | 
						|
 | 
						|
			ob_start();
 | 
						|
 | 
						|
			//for theme content arrangement
 | 
						|
			if( $GP_ARRANGE && $permission && isset($GLOBALS['GP_ARRANGE_CONTENT']) ){
 | 
						|
				$empty_container = empty($info['gpOutCmd']); //empty containers can't be removed and don't have labels
 | 
						|
				$class .= ' gp_output_area';
 | 
						|
 | 
						|
				echo '<div class="gp_inner_links nodisplay"><div>';
 | 
						|
				echo \gp\tool::Link(
 | 
						|
					'Admin_Theme_Content/Edit/' . $page->gpLayout,
 | 
						|
					$param,
 | 
						|
					'cmd=DragArea&dragging=' . urlencode($param) . '&to=%s',
 | 
						|
					['data-cmd' => 'creq', 'class' => 'dragdroplink nodisplay']
 | 
						|
				); //drag-drop link
 | 
						|
 | 
						|
				echo '<div class="output_area_label">';
 | 
						|
				if( $empty_container ){
 | 
						|
					echo $langmessage['Empty Container'];
 | 
						|
				}else{
 | 
						|
					echo self::GpOutLabel($info);
 | 
						|
				}
 | 
						|
				echo '</div>';
 | 
						|
 | 
						|
				echo '<div class="output_area_link">';
 | 
						|
				echo ' ' . \gp\tool::Link(
 | 
						|
					'Admin_Theme_Content/Edit/' . $page->gpLayout,
 | 
						|
					'<i class="fa fa-plus"></i> ' . $langmessage['insert'],
 | 
						|
					'cmd=SelectContent¶m=' . $param,
 | 
						|
					['data-cmd' => 'gpabox']
 | 
						|
				);
 | 
						|
				if( !$empty_container ){
 | 
						|
					echo ' ' . \gp\tool::Link(
 | 
						|
						'Admin_Theme_Content/Edit/' . $page->gpLayout,
 | 
						|
						'<i class="fa fa-times"></i> ' . $langmessage['remove'],
 | 
						|
						'cmd=RemoveArea¶m=' . $param,
 | 
						|
						['data-cmd' => 'creq']
 | 
						|
					);
 | 
						|
				}
 | 
						|
				echo '</div>';
 | 
						|
 | 
						|
				echo '</div></div>';
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
			//editable links only .. other editable_areas are handled by their output functions
 | 
						|
			if( $permission ){
 | 
						|
				if( isset($info['link']) ){
 | 
						|
					$label = $langmessage[$info['link']];
 | 
						|
 | 
						|
					$edit_link = self::EditAreaLink(
 | 
						|
						$edit_index,
 | 
						|
						'Admin_Theme_Content/Edit/' . urlencode($page->gpLayout),
 | 
						|
						$langmessage['edit'],
 | 
						|
						'cmd=LayoutMenu&handle=' . $param,
 | 
						|
						['data-cmd' => 'gpabox', 'title' => $label ]
 | 
						|
					);
 | 
						|
					echo '<span class="nodisplay" id="ExtraEditLnks' . $edit_index . '">';
 | 
						|
					echo $edit_link;
 | 
						|
					echo \gp\tool::Link(
 | 
						|
						'Admin/Menu',
 | 
						|
						$langmessage['file_manager'],
 | 
						|
						'',
 | 
						|
						['class' => 'nodisplay']
 | 
						|
					);
 | 
						|
					//call to current also not needed, there will only be 1 entry);
 | 
						|
					echo '</span>';
 | 
						|
 | 
						|
					self::$edit_area_id = 'ExtraEditArea'.$edit_index;
 | 
						|
 | 
						|
				}elseif( isset($info['key']) && ($info['key'] == 'CustomMenu') ){
 | 
						|
 | 
						|
					$edit_link = self::EditAreaLink(
 | 
						|
						$edit_index,
 | 
						|
						'Admin_Theme_Content/Edit/' . urlencode($page->gpLayout),
 | 
						|
						$langmessage['edit'],
 | 
						|
						'cmd=LayoutMenu&handle=' . $param,
 | 
						|
						['data-cmd' => 'gpabox', 'title' => $langmessage['Links']]
 | 
						|
					);
 | 
						|
 | 
						|
					echo '<span class="nodisplay" id="ExtraEditLnks' . $edit_index . '">';
 | 
						|
 | 
						|
					echo $edit_link;
 | 
						|
 | 
						|
					echo \gp\tool::Link(
 | 
						|
						'Admin/Menu',
 | 
						|
						$langmessage['file_manager'],
 | 
						|
						'',
 | 
						|
						['class' => 'nodisplay']
 | 
						|
					);
 | 
						|
 | 
						|
					echo '</span>';
 | 
						|
 | 
						|
					self::$edit_area_id = 'ExtraEditArea' . $edit_index;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			self::$editlinks .= ob_get_clean();
 | 
						|
 | 
						|
			echo '<div class="' . $class . ' GPAREA">';
 | 
						|
			self::ExecArea($info);
 | 
						|
			echo '</div>';
 | 
						|
 | 
						|
			$GP_ARRANGE				= true;
 | 
						|
			$gp_current_container	= false;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function ExecArea($info){
 | 
						|
			//retreive from gadget cache if set
 | 
						|
			if( isset($info['gpOutCmd']) ){
 | 
						|
				$gadget = $info['gpOutCmd'];
 | 
						|
				if( substr($gadget, 0, 7) == 'Gadget:' ){
 | 
						|
					$gadget = substr($gadget, 7);
 | 
						|
				}
 | 
						|
				if( isset(self::$gadget_cache[$gadget]) ){
 | 
						|
					echo self::$gadget_cache[$gadget];
 | 
						|
					return;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			$info += ['arg' => ''];
 | 
						|
			$args = [$info['arg'], $info];
 | 
						|
 | 
						|
			$info = \gp\tool\Plugins::Filter('ExecArea', [$info, $args]);
 | 
						|
			if( !$info ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			self::ExecInfo($info, $args);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Execute a set of directives for theme areas, hooks and special pages
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function ExecInfo($info, $args=[]){
 | 
						|
			global $addonFolderName, $installed_addon, $page;
 | 
						|
 | 
						|
			$args += ['page' => $page];
 | 
						|
 | 
						|
			//addonDir is deprecated as of 2.0b3
 | 
						|
			$addon = false;
 | 
						|
			if( isset($info['addonDir']) ){
 | 
						|
				$addon = $info['addonDir'];
 | 
						|
			}elseif( isset($info['addon']) ){
 | 
						|
				$addon = $info['addon'];
 | 
						|
			}
 | 
						|
 | 
						|
			if( $addon !== false ){
 | 
						|
				if( gp_safe_mode ){
 | 
						|
					return $args;
 | 
						|
				}
 | 
						|
				\gp\tool\Plugins::SetDataFolder($addon);
 | 
						|
			}
 | 
						|
 | 
						|
			//if addon was just installed
 | 
						|
			if( $installed_addon && $installed_addon === $addonFolderName){
 | 
						|
				\gp\tool\Plugins::ClearDataFolder();
 | 
						|
				return $args;
 | 
						|
			}
 | 
						|
 | 
						|
			// check for fatal errors
 | 
						|
			if( self::FatalNotice('exec', $info) ){
 | 
						|
				return $args;
 | 
						|
			}
 | 
						|
 | 
						|
			try{
 | 
						|
				$args = self::_ExecInfo($info, $args);
 | 
						|
			}catch(\Throwable $e){
 | 
						|
				\showError(E_ERROR,
 | 
						|
					'ExecInfo() Fatal Error: ' . $e->getMessage(),
 | 
						|
					$e->GetFile(),
 | 
						|
					$e->GetLine(),
 | 
						|
					[],
 | 
						|
					$e->getTrace()
 | 
						|
				);
 | 
						|
			}
 | 
						|
 | 
						|
			if( $addon !== false ){
 | 
						|
				\gp\tool\Plugins::ClearDataFolder();
 | 
						|
			}
 | 
						|
 | 
						|
			self::PopCatchable();
 | 
						|
 | 
						|
			return $args;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function _ExecInfo($info, $args=[]){
 | 
						|
			global $dataDir, $gp_overwrite_scripts;
 | 
						|
 | 
						|
			// get data
 | 
						|
			if( !empty($info['data']) ){
 | 
						|
				IncludeScript($dataDir . $info['data'], 'include_if', ['page', 'dataDir', 'langmessage']);
 | 
						|
			}
 | 
						|
 | 
						|
			// get script
 | 
						|
			$has_script = false;
 | 
						|
			if( !empty($info['script']) ){
 | 
						|
 | 
						|
				if( is_array($gp_overwrite_scripts) && isset($gp_overwrite_scripts[$info['script']]) ){
 | 
						|
					$full_path = $gp_overwrite_scripts[$info['script']];
 | 
						|
				}else{
 | 
						|
					$full_path = $dataDir . $info['script'];
 | 
						|
				}
 | 
						|
 | 
						|
				if( !file_exists($full_path) ){
 | 
						|
					self::ExecError(\CMS_NAME . ' Error: Addon hook script doesn\'t exist.', $info, 'script');
 | 
						|
					return $args;
 | 
						|
				}
 | 
						|
 | 
						|
				if( IncludeScript($full_path, 'include_once', ['page', 'dataDir', 'langmessage']) ){
 | 
						|
					$has_script = true;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//class & method execution
 | 
						|
			if( !empty($info['class_admin']) && \gp\tool::LoggedIn() ){
 | 
						|
				return self::ExecClass($has_script, $info['class_admin'], $info, $args);
 | 
						|
			}elseif( !empty($info['class']) ){
 | 
						|
				return self::ExecClass($has_script, $info['class'], $info, $args);
 | 
						|
			}
 | 
						|
 | 
						|
			//method execution
 | 
						|
			if( !empty($info['method']) ){
 | 
						|
				return self::ExecMethod($has_script, $info, $args);
 | 
						|
			}
 | 
						|
 | 
						|
			return $args;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Execute hooks that have a ['class'] defined
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		private static function ExecClass($has_script, $exec_class, $info, $args){
 | 
						|
 | 
						|
			if( !class_exists($exec_class) ){
 | 
						|
				self::ExecError(\CMS_NAME . ' Error: Addon class doesn\'t exist.', $info, 'class');
 | 
						|
				return $args;
 | 
						|
			}
 | 
						|
 | 
						|
			$object = new $exec_class($args);
 | 
						|
 | 
						|
			if( !empty($info['method']) ){
 | 
						|
				if( method_exists($object, $info['method']) ){
 | 
						|
					$args[0] = call_user_func_array([$object, $info['method']], $args);
 | 
						|
				}elseif( $has_script ){
 | 
						|
					self::ExecError(\CMS_NAME . ' Error: Addon hook method doesn\'t exist (1).', $info, 'method');
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return $args;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Execute hooks that have a ['method'] defined
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		private static function ExecMethod($has_script, $info, $args){
 | 
						|
 | 
						|
			$callback = $info['method'];
 | 
						|
 | 
						|
			//object callbacks since 3.0
 | 
						|
			if( is_string($callback) && strpos($callback, '->') !== false ){
 | 
						|
				$has_script = true;
 | 
						|
				list($object, $method) = explode('->', $callback);
 | 
						|
				if( isset($GLOBALS[$object]) &&
 | 
						|
					is_object($GLOBALS[$object]) &&
 | 
						|
					method_exists($GLOBALS[$object], $method)
 | 
						|
				){
 | 
						|
					$callback = [$GLOBALS[$object], $method];
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if( is_callable($callback) ){
 | 
						|
				$args[0] = call_user_func_array($callback, $args);
 | 
						|
			}elseif( $has_script ){
 | 
						|
				self::ExecError(\CMS_NAME.' Error: Addon hook method doesn\'t exist (2).', $info, 'method');
 | 
						|
			}
 | 
						|
 | 
						|
			return $args;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Trigger an error
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function ExecError($msg, $exec_info, $error_info){
 | 
						|
			global $config, $addonFolderName;
 | 
						|
 | 
						|
			// append addon name
 | 
						|
			if( !empty($addonFolderName) && isset($config['addons'][$addonFolderName]) ){
 | 
						|
				$msg	.= ' Addon: ' . $config['addons'][$addonFolderName]['name'] . '. ';
 | 
						|
			}
 | 
						|
 | 
						|
			// which piece of $exec_info is the problem
 | 
						|
			if( !isset($exec_info[$error_info]) ){
 | 
						|
				$msg	.= $error_info;
 | 
						|
			}elseif( is_array($exec_info[$error_info]) ){
 | 
						|
				$msg	.= $error_info . ': ' . implode('::', $exec_info[$error_info]);
 | 
						|
			}else{
 | 
						|
				$msg	.= $error_info . ': ' . $exec_info[$error_info];
 | 
						|
			}
 | 
						|
 | 
						|
			trigger_error($msg);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Check for fatal errors corresponing to $hash
 | 
						|
		 * Notify administrators of disabled components
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function FatalNotice($type, $info){
 | 
						|
			global $dataDir, $page;
 | 
						|
			static $notified = false;
 | 
						|
 | 
						|
			$info					= (array)$info;
 | 
						|
			$info['catchable_type']	= $type;
 | 
						|
 | 
						|
			$hash_dir				= $dataDir . '/data/_site/fatal_' . $type . '_' . \gp\tool::ArrayHash($info);
 | 
						|
			$hash_request			= $hash_dir . '/' . \gp\tool::ArrayHash($_REQUEST);
 | 
						|
 | 
						|
			self::$catchable[$hash_request]	= $info;
 | 
						|
 | 
						|
			if( !self::FatalLimit($hash_dir) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			if( !$notified ){
 | 
						|
				error_log( 'Warning: A component of this page has been disabled because it caused fatal errors' );
 | 
						|
				$notified = true;
 | 
						|
			}
 | 
						|
 | 
						|
			self::PopCatchable();
 | 
						|
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return true if the limit of fatal errors has been reached
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function FatalLimit($hash_dir){
 | 
						|
 | 
						|
			//no folder = no fatal error
 | 
						|
			if( !file_exists($hash_dir) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			// if the error didn't occur for the exact request and it hasn't happend a lot, allow the code to keep working
 | 
						|
			$fatal_hashes = scandir($hash_dir);
 | 
						|
			if( $fatal_hashes !== false && count($fatal_hashes) < (gp_allowed_fatal_errors + 3) ){
 | 
						|
				// add 3 for ".", ".." and "index.html" entries
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function PopCatchable(){
 | 
						|
			array_pop(self::$catchable);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Determine if an inline edit link should be shown for the current user
 | 
						|
		 *
 | 
						|
		 * @param string $permission
 | 
						|
		 * @return bool
 | 
						|
		 */
 | 
						|
		public static function ShowEditLink($permission=null){
 | 
						|
 | 
						|
			if( !is_null($permission) ){
 | 
						|
				return !self::$nested_edit && \gp\tool::LoggedIn() && \gp\admin\Tools::HasPermission($permission);
 | 
						|
			}
 | 
						|
			return !self::$nested_edit && \gp\tool::LoggedIn();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * @param int $index
 | 
						|
		 * @param string $href
 | 
						|
		 * @param string $label
 | 
						|
		 * @param string $query
 | 
						|
		 * @param string|array $attr
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function EditAreaLink(&$index, $href, $label, $query='', $attr=''){
 | 
						|
			self::$edit_index++;
 | 
						|
			$index = self::$edit_index; //since &$index is passed by reference
 | 
						|
 | 
						|
			if( is_array($attr) ){
 | 
						|
				$attr += [
 | 
						|
					'class'				=> 'ExtraEditLink nodisplay',
 | 
						|
					'id'				=> 'ExtraEditLink' . $index,
 | 
						|
					'data-gp-area-id'	=> $index,
 | 
						|
				];
 | 
						|
			}else{
 | 
						|
				$attr .= ' class="ExtraEditLink nodisplay" ' .
 | 
						|
					'id="ExtraEditLink' . $index . '" ' .
 | 
						|
					'data-gp-area-id="' . $index . '"';
 | 
						|
			}
 | 
						|
			return \gp\tool::Link($href, $label, $query, $attr);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Unless the gadget area is customized by the user, this function will output all active gadgets
 | 
						|
		 * If the area has been reorganized, it will output the customized areas
 | 
						|
		 * This function is not called from \gp\tool\Output::Get('GetAllGadgets')
 | 
						|
		 * so that each individual gadget area can be used as a drag area
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetAllGadgets(){
 | 
						|
			global $config, $page, $gpLayouts, $get_all_gadgets_called;
 | 
						|
			$get_all_gadgets_called = true;
 | 
						|
 | 
						|
			//if we have handler info
 | 
						|
			if( isset($gpLayouts[$page->gpLayout]['handlers']['GetAllGadgets']) ){
 | 
						|
				self::ForEachOutput($gpLayouts[$page->gpLayout]['handlers']['GetAllGadgets'], 'GetAllGadgets');
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//show all gadgets if no changes have been made
 | 
						|
			if( !empty($config['gadgets']) ){
 | 
						|
				$count = 0;
 | 
						|
				foreach($config['gadgets'] as $gadget => $info){
 | 
						|
					if( isset($info['addon']) ){
 | 
						|
						$info['gpOutCmd'] = $info['key'] = $gadget;
 | 
						|
						self::CallOutput($info, 'GetAllGadgets');
 | 
						|
						$count++;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if( $count ){
 | 
						|
					return;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//Show the area as editable if there isn't anything to show
 | 
						|
			$info				= [];
 | 
						|
			$info['gpOutCmd']	= '';
 | 
						|
			self::CallOutput($info, 'GetAllGadgets');
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Simply determine if a Gadget exists
 | 
						|
		 * allows us to check whether a plugin gadget exists before loading it in template.php
 | 
						|
		 * @since 5.2-rc
 | 
						|
		 * @param string Gadget id
 | 
						|
		 * @return boolean
 | 
						|
		 */
 | 
						|
		public static function GadgetExists($id){
 | 
						|
			global $config;
 | 
						|
			return isset($config['gadgets'][$id]);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get a Single Gadget
 | 
						|
		 * This method should be called using \gp\tool\Output::Fetch('Gadget',$gadget_name)
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetGadget($id){
 | 
						|
			global $config;
 | 
						|
 | 
						|
			if( !isset($config['gadgets'][$id]) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			self::ExecArea($config['gadgets'][$id]);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Prepare the gadget content before getting template.php
 | 
						|
		 * so that gadget functions can add css and js to the head
 | 
						|
		 * @return null
 | 
						|
		 */
 | 
						|
		public static function PrepGadgetContent(){
 | 
						|
			global $page;
 | 
						|
 | 
						|
			//not needed for admin pages
 | 
						|
			if( $page->pagetype == 'admin_display' ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			$gadget_info = self::WhichGadgets($page->gpLayout);
 | 
						|
 | 
						|
			foreach($gadget_info as $gpOutCmd => $info){
 | 
						|
				if( !isset(self::$gadget_cache[$gpOutCmd]) ){
 | 
						|
					ob_start();
 | 
						|
					self::ExecArea($info);
 | 
						|
					self::$gadget_cache[$gpOutCmd] = ob_get_clean();
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return information about the gadgets being used in the current layout
 | 
						|
		 * @return array
 | 
						|
		 */
 | 
						|
		public static function WhichGadgets($layout){
 | 
						|
			global $config, $gpLayouts;
 | 
						|
 | 
						|
			$gadget_info = $temp_info = [];
 | 
						|
			if( !isset($config['gadgets']) ){
 | 
						|
				return $gadget_info;
 | 
						|
			}
 | 
						|
 | 
						|
			$layout_info = & $gpLayouts[$layout];
 | 
						|
 | 
						|
			$GetAllGadgets = true;
 | 
						|
			if( isset($layout_info['all_gadgets']) && !$layout_info['all_gadgets'] ){
 | 
						|
				$GetAllGadgets = false;
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($layout_info['handlers']) ){
 | 
						|
				foreach($layout_info['handlers'] as $handler => $out_cmds){
 | 
						|
					//don't prep even if GetAllGadgets is set in the layout's config
 | 
						|
					if( $handler == 'GetAllGadgets' && !$GetAllGadgets ){
 | 
						|
						continue;
 | 
						|
					}
 | 
						|
					foreach($out_cmds as $gpOutCmd){
 | 
						|
						$temp_info[$gpOutCmd] = self::GetgpOutInfo($gpOutCmd);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//add all gadgets if $GetAllGadgets is true and the GetAllGadgets handler isn't overwritten
 | 
						|
			if( $GetAllGadgets && !isset($layout_info['handlers']['GetAllGadgets']) ){
 | 
						|
				foreach($config['gadgets'] as $gadget => $temp){
 | 
						|
					if( isset($temp['addon']) ){
 | 
						|
						$temp_info[$gadget] = self::GetgpOutInfo($gadget);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			foreach($temp_info as $gpOutCmd => $info){
 | 
						|
				if( isset($info['is_gadget']) &&
 | 
						|
					$info['is_gadget'] &&
 | 
						|
					!isset($info['disabled'])
 | 
						|
				){
 | 
						|
					$gadget_info[$gpOutCmd] = $info;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			return $gadget_info;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function GetExtra($name='Side_Menu', $info=[]){
 | 
						|
			echo \gp\tool\Output\Extra::GetExtra($name);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function GetImage($src, $attributes=[]){
 | 
						|
			global $page, $dataDir, $langmessage, $gpLayouts;
 | 
						|
 | 
						|
			//$width,$height,$attributes = ''
 | 
						|
			$attributes				= (array)$attributes;
 | 
						|
			$attributes				+= ['class' => ''];
 | 
						|
			$attributes['class'] 	.= 'GPAREA filetype-image';
 | 
						|
			unset($attributes['id']);
 | 
						|
 | 
						|
			//default image information
 | 
						|
			$img_rel = dirname($page->theme_rel) . '/' . ltrim($src, '/');
 | 
						|
 | 
						|
			//container id
 | 
						|
			$container_id = 'Image:' . $src;
 | 
						|
			$container_id = self::GetContainerID($container_id);
 | 
						|
 | 
						|
			//select custom image
 | 
						|
			if( isset($gpLayouts[$page->gpLayout]) &&
 | 
						|
				isset($gpLayouts[$page->gpLayout]['images']) &&
 | 
						|
				isset($gpLayouts[$page->gpLayout]['images'][$container_id]) &&
 | 
						|
				is_array($gpLayouts[$page->gpLayout]['images'][$container_id])
 | 
						|
			){
 | 
						|
				//shuffle($gpLayouts[$page->gpLayout]['images'][$container_id]);
 | 
						|
				//Does not make sense ? There will always be only 1 entry in 
 | 
						|
				//for this container as it is per img element
 | 
						|
				//call to current also not needed, there will only be 1 entry
 | 
						|
				$image = $gpLayouts[$page->gpLayout]['images'][$container_id][0];
 | 
						|
 | 
						|
				$img_full = $dataDir.$image['img_rel'];
 | 
						|
				if( file_exists($img_full) ){
 | 
						|
					$img_rel				= $image['img_rel'];
 | 
						|
					$attributes['width']	= $image['width'];
 | 
						|
					$attributes['height']	= $image['height'];
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//attributes
 | 
						|
			if( !isset($attributes['alt']) ){
 | 
						|
				$attributes['alt'] = '';
 | 
						|
			}
 | 
						|
 | 
						|
			//edit options
 | 
						|
			$editable = self::ShowEditLink('Admin_Theme_Content');
 | 
						|
			if( $editable ){
 | 
						|
				$edit_link = self::EditAreaLink(
 | 
						|
					$edit_index,
 | 
						|
					'Admin_Theme_Content/Image/' . $page->gpLayout,
 | 
						|
					$langmessage['edit'],
 | 
						|
					'file=' . rawurlencode($img_rel) . '&container=' . $container_id . '&time=' . time(),
 | 
						|
					['title' => 'Edit Image', 'data-cmd' => 'inline_edit_generic' ]
 | 
						|
				);
 | 
						|
				self::$editlinks 		.= '<span class="nodisplay" id="ExtraEditLnks' .
 | 
						|
												$edit_index . '">' .
 | 
						|
												$edit_link .
 | 
						|
											'</span>';
 | 
						|
				$attributes['class']	.= ' editable_area';
 | 
						|
				$attributes['id']		= 'ExtraEditArea' . $edit_index;
 | 
						|
			}
 | 
						|
 | 
						|
			//remove class if empty, commented because class will never be empty anymore because of filetype-image
 | 
						|
			// $attributes['class'] = trim($attributes['class']);
 | 
						|
			// if( empty($attributes['class']) ){
 | 
						|
			//	unset($attributes['class']);
 | 
						|
			//}
 | 
						|
 | 
						|
			//convert attributes to string
 | 
						|
			$str = '';
 | 
						|
			foreach($attributes as $key => $value){
 | 
						|
				$str .= ' ' . $key . '="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8', false) . '"';
 | 
						|
			}
 | 
						|
			echo '<img src="' . \gp\tool::GetDir($img_rel, true) . '"' . $str . '/>';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/*
 | 
						|
		 *
 | 
						|
		 * Output Additional Areas
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
 | 
						|
		/* draggable html and editable text */
 | 
						|
		public static function Area($name,$html){
 | 
						|
			global $gpOutConf;
 | 
						|
			if( self::$out_started ){
 | 
						|
				trigger_error('\gp\tool\Output::Area() must be called before all other output functions');
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			$name 						= '[text]' . $name;
 | 
						|
			$gpOutConf[$name]			= [];
 | 
						|
			$gpOutConf[$name]['method']	= ['\\gp\\tool\\Output', 'GetAreaOut'];
 | 
						|
			$gpOutConf[$name]['html']	= $html;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function GetArea($name, $text){
 | 
						|
			$name = '[text]' . $name;
 | 
						|
			self::Get($name, $text);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function GetAreaOut($text,$info){
 | 
						|
			global $config, $langmessage, $page;
 | 
						|
 | 
						|
			$html =& $info['html'];
 | 
						|
 | 
						|
			$wrap = self::ShowEditLink('Admin_Theme_Content');
 | 
						|
			if( $wrap ){
 | 
						|
				self::$editlinks .= self::EditAreaLink(
 | 
						|
					$edit_index,
 | 
						|
					'Admin_Theme_Content/Text',
 | 
						|
					$langmessage['edit'],
 | 
						|
					'cmd=EditText&key=' . urlencode($text) . '&return=' . urlencode($page->title),
 | 
						|
					['title' => htmlspecialchars($text), 'data-cmd'	=> 'gpabox']
 | 
						|
				);
 | 
						|
				echo '<div class="editable_area inner_size" id="ExtraEditArea' . $edit_index . '">';
 | 
						|
				// class="edit_area" added by javascript
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($config['customlang'][$text]) ){
 | 
						|
				$text = $config['customlang'][$text];
 | 
						|
 | 
						|
			}elseif( isset($langmessage[$text]) ){
 | 
						|
				$text = $langmessage[$text];
 | 
						|
			}
 | 
						|
 | 
						|
			echo str_replace('%s', $text, $html); //in case there's more than one %s
 | 
						|
 | 
						|
			if( $wrap ){
 | 
						|
				echo '</div>';
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get additional CSS classes that can be added to the
 | 
						|
		 * html or body elements' class atrribute
 | 
						|
		 * e.g. to display an larger header only on the homepage
 | 
						|
		 * Use in template.php: <html class="<?php gpOutput::GetPageInfoClasses(); ?>">
 | 
						|
		 * @since 5.2-rc
 | 
						|
		 * @param boolean $echo_classes (defaults to true), output the class names as space-separated string
 | 
						|
		 * @return array of css class names that apply
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetPageInfoClasses($echo_classes=true){
 | 
						|
			global $page;
 | 
						|
 | 
						|
			$classes = [];
 | 
						|
		
 | 
						|
			if( self::is_front_page() ){
 | 
						|
				$classes[] = 'is-homepage';
 | 
						|
			}
 | 
						|
 | 
						|
			if( $page->pagetype == 'special_display' ){
 | 
						|
				$classes[] = 'is-special-page';
 | 
						|
			}
 | 
						|
 | 
						|
			switch( $page->gp_index ){
 | 
						|
				case 'special_contact':
 | 
						|
					$classes[] = 'is-contactform-page';
 | 
						|
					break;
 | 
						|
 | 
						|
				case 'special_galleries':
 | 
						|
					$classes[] = 'is-galleries-page';
 | 
						|
					break;
 | 
						|
 | 
						|
				case 'special_gpsearch':
 | 
						|
					$classes[] = 'is-search-page';
 | 
						|
					break;
 | 
						|
 | 
						|
				case 'special_missing':
 | 
						|
					$classes[] = 'is-missing-page';
 | 
						|
					break;
 | 
						|
 | 
						|
				case 'special_blog':
 | 
						|
					$classes[] = 'is-blog-page';
 | 
						|
					if( isset($_GET['id']) ){
 | 
						|
						$classes[] = 'is-single-post-page';
 | 
						|
					}
 | 
						|
					break;
 | 
						|
 | 
						|
				case 'special_blog_categories':
 | 
						|
					$classes[] = 'is-blog-page';
 | 
						|
					$classes[] = 'is-blog-categories-page';
 | 
						|
					if( isset($_GET['cat']) ){
 | 
						|
						$classes[] = 'is-single-category-page';
 | 
						|
					}
 | 
						|
					break;
 | 
						|
			}
 | 
						|
 | 
						|
			if( $echo_classes && !empty($classes) ){
 | 
						|
				echo ' ' . implode(' ', $classes) . ' ';
 | 
						|
			}
 | 
						|
 | 
						|
			return $classes;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/*
 | 
						|
		 *
 | 
						|
		 * editable text, not draggable
 | 
						|
		 *
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
 | 
						|
		/**
 | 
						|
		 * similar to ReturnText() but links to script for editing all addon texts
 | 
						|
		 * the $html parameter should primarily be used when the text is to be placed
 | 
						|
		 * inside of a link or other element that cannot have a link and/or span as a child node
 | 
						|
		 */
 | 
						|
		public static function GetAddonText($key, $html='%s', $wrapper_class=''){
 | 
						|
			global $addonFolderName;
 | 
						|
 | 
						|
			if( !$addonFolderName ){
 | 
						|
				return self::ReturnText($key, $html, $wrapper_class);
 | 
						|
			}
 | 
						|
 | 
						|
			$query = 'cmd=AddonTextForm&addon=' . urlencode($addonFolderName) . '&key=' . urlencode($key);
 | 
						|
			return self::ReturnTextWorker($key, $html, $query, $wrapper_class);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function ReturnText($key,$html='%s', $wrapper_class=''){
 | 
						|
			$query = 'cmd=EditText&key='.urlencode($key);
 | 
						|
			return self::ReturnTextWorker($key, $html, $query, $wrapper_class);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function ReturnTextWorker($key, $html, $query, $wrapper_class=''){
 | 
						|
			global $langmessage;
 | 
						|
 | 
						|
			$text		= self::SelectText($key);
 | 
						|
			$result		= str_replace('%s', $text, $html); //in case there's more than one %s
 | 
						|
 | 
						|
			$editable	= self::ShowEditLink('Admin_Theme_Content');
 | 
						|
			if( $editable ){
 | 
						|
 | 
						|
				$title = htmlspecialchars(strip_tags($key));
 | 
						|
				if( strlen($title) > 20 ){
 | 
						|
					$title = substr($title, 0, 20) . '...'; //javscript may shorten it as well
 | 
						|
				}
 | 
						|
 | 
						|
				self::$editlinks .= self::EditAreaLink(
 | 
						|
					$edit_index,
 | 
						|
					'Admin_Theme_Content/Text',
 | 
						|
					$langmessage['edit'],
 | 
						|
					$query,
 | 
						|
					['title' => $title, 'data-cmd' => 'gpabox']
 | 
						|
				);
 | 
						|
				return '<span class="editable_area ' . $wrapper_class .'" '
 | 
						|
				 . 'id="ExtraEditArea' . $edit_index . '">' . $result . '</span>';
 | 
						|
			}
 | 
						|
 | 
						|
			if( $wrapper_class ){
 | 
						|
				return '<span class="' . $wrapper_class . '">' . $result . '</span>';
 | 
						|
			}
 | 
						|
 | 
						|
			return $result;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Returns the user translated string if it exists or
 | 
						|
		 * $key (the untranslated string) if a translation doesn't exist
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function SelectText($key){
 | 
						|
			global $config,$langmessage;
 | 
						|
 | 
						|
			$text = $key;
 | 
						|
			if( isset($config['customlang'][$key]) ){
 | 
						|
				$text = $config['customlang'][$key];
 | 
						|
 | 
						|
			}elseif( isset($langmessage[$key]) ){
 | 
						|
				$text = $langmessage[$key];
 | 
						|
			}
 | 
						|
			return $text;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/*
 | 
						|
		 *
 | 
						|
		 * Generate and output the <head> portion of the html document
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
 | 
						|
		 public static function GetHead(){
 | 
						|
			\gp\tool\Plugins::Action('GetHead');
 | 
						|
			self::PrepGadgetContent();
 | 
						|
			echo '<!-- get_head_placeholder ' . \gp_random . ' -->';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function HeadContent(){
 | 
						|
			global $config, $page, $wbMessageBuffer;
 | 
						|
 | 
						|
			//before ob_start() so plugins can get buffer content
 | 
						|
			\gp\tool\Plugins::Action('HeadContent');
 | 
						|
 | 
						|
 | 
						|
			if( \gp\tool::LoggedIn() ){
 | 
						|
				\gp\tool::AddColorBox();
 | 
						|
			}
 | 
						|
 | 
						|
			//always include javascript when there are messages
 | 
						|
			if( $page->admin_js || !empty($page->jQueryCode) || !empty($wbMessageBuffer) || isset($_COOKIE['cookie_cmd']) ){
 | 
						|
				\gp\tool::LoadComponents('gp-main');
 | 
						|
			}
 | 
						|
			//defaults
 | 
						|
			\gp\tool::LoadComponents('jquery,gp-additional');
 | 
						|
 | 
						|
			//get css and js info
 | 
						|
			$scripts = \gp\tool\Output\Combine::ScriptInfo( self::$components );
 | 
						|
 | 
						|
			ob_start();
 | 
						|
			self::GetHead_TKD();
 | 
						|
			self::$head_content = ob_get_clean();
 | 
						|
 | 
						|
			ob_start();
 | 
						|
			self::GetHead_CSS($scripts['css']); //css before js so it's available to scripts
 | 
						|
			self::$head_css = ob_get_clean();
 | 
						|
 | 
						|
			//javascript
 | 
						|
			ob_start();
 | 
						|
			self::GetHead_Lang();
 | 
						|
			self::GetHead_JS($scripts['js']);
 | 
						|
			self::GetHead_InlineJS();
 | 
						|
			self::$head_js = ob_get_clean();
 | 
						|
 | 
						|
			//gadget info
 | 
						|
			if( isset($config['addons']) ){
 | 
						|
				foreach($config['addons'] as $addon_info){
 | 
						|
					if( !empty($addon_info['html_head']) ){
 | 
						|
						self::MoveScript($addon_info['html_head']);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if( !empty($page->head) ){
 | 
						|
				self::MoveScript($page->head);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Move <script>..</script> to self::$head_js
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function MoveScript($string){
 | 
						|
 | 
						|
			//conditional comments with script tags
 | 
						|
			$patt = '#' . preg_quote('<!--[if', '#') . '.*?' . preg_quote('<![endif]-->', '#') . '#s';
 | 
						|
			if( preg_match_all($patt,$string, $matches) ){
 | 
						|
				foreach($matches[0] as $match){
 | 
						|
					if( strpos($match,'<script') !== false ){
 | 
						|
						$string = str_replace($match, '', $string);
 | 
						|
						self::$head_js .= "\n" . $match;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//script tags
 | 
						|
			if( preg_match_all('#<script.*?</script>#i',$string,$matches) ){
 | 
						|
				foreach($matches[0] as $match){
 | 
						|
					$string = str_replace($match, '', $string);
 | 
						|
					self::$head_js .= "\n" . $match;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//add the rest to the head_content
 | 
						|
			self::$head_content .= "\n" . $string;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Output the title, keywords, description and other meta for the current html document
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetHead_TKD(){
 | 
						|
			global $config, $page, $gpLayouts;
 | 
						|
 | 
						|
			//charset
 | 
						|
			if( $page->gpLayout &&
 | 
						|
				isset($gpLayouts[$page->gpLayout]) &&
 | 
						|
				isset($gpLayouts[$page->gpLayout]['doctype'])
 | 
						|
			){
 | 
						|
				echo $gpLayouts[$page->gpLayout]['doctype'];
 | 
						|
			}
 | 
						|
 | 
						|
			//title, keyords & description
 | 
						|
			$page_title = self::MetaTitle();
 | 
						|
			self::MetaKeywords($page_title);
 | 
						|
			self::MetaDescription($page_title);
 | 
						|
 | 
						|
			if( !empty($page->TitleInfo['rel']) ){
 | 
						|
				echo "\n" . '<meta name="robots" content="' . $page->TitleInfo['rel'] . '" />';
 | 
						|
			}
 | 
						|
 | 
						|
			echo "\n" . '<meta name="generator" content="' . \CMS_NAME_FULL . '" />';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add the <title> tag to the page
 | 
						|
		 * return the value
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function MetaTitle(){
 | 
						|
			global $page, $config;
 | 
						|
 | 
						|
			$meta_title = '';
 | 
						|
			$page_title = '';
 | 
						|
			if( !empty($page->TitleInfo['browser_title']) ){
 | 
						|
				$page_title = $page->TitleInfo['browser_title'];
 | 
						|
			}elseif( !empty($page->label) ){
 | 
						|
				$page_title = strip_tags($page->label);
 | 
						|
			}elseif( isset($page->title) ){
 | 
						|
				$page_title = \gp\tool::GetBrowserTitle($page->title);
 | 
						|
			}
 | 
						|
			$meta_title .= $page_title;
 | 
						|
			if( !empty($page_title) && !empty($config['title']) ){
 | 
						|
				$meta_title .=  ' - ';
 | 
						|
			}
 | 
						|
			$meta_title .= $config['title'];
 | 
						|
 | 
						|
			$meta_title = \gp\tool\Plugins::Filter(
 | 
						|
				'MetaTitle',
 | 
						|
				[$meta_title, $page_title, $config['title']]
 | 
						|
			);
 | 
						|
 | 
						|
			echo "\n" . '<title>' . strip_tags($meta_title) . '</title>';
 | 
						|
			return $page_title;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add the <meta name="keywords"> tag to the page
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function MetaKeywords($page_title){
 | 
						|
			global $page, $config;
 | 
						|
 | 
						|
			if( count($page->meta_keywords) ){
 | 
						|
				$keywords = $page->meta_keywords;
 | 
						|
			}elseif( !empty($page->TitleInfo['keywords']) ){
 | 
						|
				$keywords = explode(',', $page->TitleInfo['keywords']);
 | 
						|
			}
 | 
						|
 | 
						|
			$keywords[]		= strip_tags($page_title);
 | 
						|
			$keywords[]		= strip_tags($page->label);
 | 
						|
 | 
						|
			$site_keywords	= explode(',', $config['keywords']);
 | 
						|
			$keywords		= array_merge($keywords, $site_keywords);
 | 
						|
			$keywords		= array_unique($keywords);
 | 
						|
			$keywords		= array_filter($keywords);
 | 
						|
 | 
						|
			echo "\n<meta name=\"keywords\" content=\"" . implode(', ', $keywords) . "\" />";
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add the <meta name="dscription"> tag to the page
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function MetaDescription($page_title){
 | 
						|
			global $page, $config;
 | 
						|
 | 
						|
			$description = '';
 | 
						|
			if( !empty($page->meta_description) ){
 | 
						|
				$description .= $page->meta_description;
 | 
						|
			}elseif( !empty($page->TitleInfo['description']) ){
 | 
						|
				$description .= $page->TitleInfo['description'];
 | 
						|
			}else{
 | 
						|
				$description .= $page_title;
 | 
						|
			}
 | 
						|
			$description = self::EndPhrase($description);
 | 
						|
 | 
						|
			if( !empty($config['desc']) ){
 | 
						|
				$description .= htmlspecialchars($config['desc']);
 | 
						|
			}
 | 
						|
			$description = trim($description);
 | 
						|
 | 
						|
			if( !empty($description) ){
 | 
						|
				echo "\n" . '<meta name="description" content="' . $description . '" />';
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Prepare and output any inline Javascript for the current page
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetHead_InlineJS(){
 | 
						|
			global $page, $gp_titles;
 | 
						|
 | 
						|
			if( isset($page->gp_index) &&
 | 
						|
				isset($gp_titles[$page->gp_index]['vis']) &&
 | 
						|
				$gp_titles[$page->gp_index]['vis'] == 'private'
 | 
						|
			){
 | 
						|
				$page->jQueryCode .= '$("html").addClass("isPrivate");' . "\n";
 | 
						|
			}
 | 
						|
 | 
						|
			if( \gp\tool::LoggedIn() && $page->pagetype !== 'admin_display' ){
 | 
						|
				$page->jQueryCode .= '$gp.HideAdminUI.init();' . "\n";
 | 
						|
				// get available classes
 | 
						|
				$avail_classes		= \gp\admin\Settings\Classes::GetClasses();
 | 
						|
				$avail_classes		= \gp\tool\Plugins::Filter('AvailableClasses', [$avail_classes]);
 | 
						|
				$page->head_script .= "\n" . 'var gp_avail_classes = ' . json_encode($avail_classes) . ';';
 | 
						|
			}
 | 
						|
 | 
						|
			// get customizer js vars
 | 
						|
			$layout_js_vars = self::GetLayoutJsVars();
 | 
						|
			// debug('$layout_js_vars = <em>' . $layout_js_vars . '</em>');
 | 
						|
 | 
						|
			ob_start();
 | 
						|
 | 
						|
			echo $layout_js_vars;
 | 
						|
 | 
						|
			echo $page->head_script . "\n";
 | 
						|
 | 
						|
			if( !empty($page->jQueryCode) ){
 | 
						|
				echo '$(function(){' . "\n";
 | 
						|
				echo $page->jQueryCode . "\n";
 | 
						|
				echo '});';
 | 
						|
			}
 | 
						|
 | 
						|
			$inline = ob_get_clean();
 | 
						|
			$inline = ltrim($inline);
 | 
						|
 | 
						|
			echo "\n" . '<script type="text/javascript">' . "\n" . $inline . "\n" . '</script>' . "\n";
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add language values to the current page
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetHead_Lang(){
 | 
						|
			global $langmessage;
 | 
						|
 | 
						|
			if( !count(self::$lang_values) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			echo "\n" . '<script type="text/javascript">';
 | 
						|
			echo 'var gplang = {';
 | 
						|
			$comma = '';
 | 
						|
			foreach(self::$lang_values as $from_key => $to_key){
 | 
						|
				echo $comma;
 | 
						|
				echo $to_key . ':"'	. str_replace(['\\', '"'], ['\\\\', '\"'], $langmessage[$from_key]) . '"';
 | 
						|
				$comma = ',';
 | 
						|
			}
 | 
						|
			echo "}; </script>";
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Prepare and output the Javascript for the current page
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetHead_JS($scripts){
 | 
						|
			global $page, $config;
 | 
						|
 | 
						|
			$combine	= $config['combinejs'] && !\gp\tool::loggedIn() && ($page->pagetype !== 'admin_display');
 | 
						|
			$scripts	= self::GetHead_CDN('js', $scripts);
 | 
						|
 | 
						|
			//just local jquery
 | 
						|
			if( !count($page->head_js) && count($scripts) === 1 && isset($scripts['jquery']) ){
 | 
						|
				echo '<!-- jquery_placeholder ' . \gp_random . ' -->';
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			if( !$combine || $page->head_force_inline ){
 | 
						|
				echo "\n<script type=\"text/javascript\">\n";
 | 
						|
				\gp\tool::jsStart();
 | 
						|
				echo "\n</script>";
 | 
						|
			}
 | 
						|
 | 
						|
			if( is_array($page->head_js) ){
 | 
						|
				$scripts += $page->head_js; //other js files
 | 
						|
			}else{
 | 
						|
				trigger_error('$page->head_js is not an array');
 | 
						|
			}
 | 
						|
 | 
						|
			Output\Assets::CombineFiles($scripts, 'js', $combine);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Prepare and output the css for the current page
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetHead_CSS($to_add){
 | 
						|
			global $page, $config, $dataDir;
 | 
						|
 | 
						|
			$scripts	= [];
 | 
						|
			$to_add		= self::GetHead_CDN('css', $to_add);
 | 
						|
			$scripts	= Output\Assets::MergeScripts($scripts, $to_add);
 | 
						|
 | 
						|
 | 
						|
			if( isset($page->css_user) ){
 | 
						|
				$scripts	= Output\Assets::MergeScripts($scripts, $page->css_user);
 | 
						|
			}
 | 
						|
 | 
						|
			// add theme css
 | 
						|
			if( !empty($page->theme_name) && $page->get_theme_css === true ){
 | 
						|
				$scripts	= Output\Assets::MergeScripts($scripts, Output\Assets::LayoutStyleFiles());
 | 
						|
			}
 | 
						|
 | 
						|
			//styles that need to override admin.css should be added to $page->css_admin;
 | 
						|
			if( isset($page->css_admin)  ){
 | 
						|
				$scripts	= Output\Assets::MergeScripts($scripts, $page->css_admin);
 | 
						|
			}
 | 
						|
 | 
						|
			// disable 'combine css' if 'create_css_sourcemaps' is set to true in /gpconfig.php
 | 
						|
			$combinecss = \create_css_sourcemaps ? false : $config['combinecss'];
 | 
						|
 | 
						|
			Output\Assets::CombineFiles($scripts, 'css', $combinecss);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add CDN hosted resources to the page
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetHead_CDN($type, $scripts){
 | 
						|
			global $config;
 | 
						|
 | 
						|
			if( empty($config['cdn']) ){
 | 
						|
				return $scripts;
 | 
						|
			}
 | 
						|
 | 
						|
			$cdn		= $config['cdn'];
 | 
						|
 | 
						|
			foreach($scripts as $key => $script_info){
 | 
						|
 | 
						|
				if( !isset($script_info['cdn']) || !isset($script_info['cdn'][$cdn]) ){
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
 | 
						|
				$cdn_url = $script_info['cdn'][$cdn];
 | 
						|
 | 
						|
				//remove packages
 | 
						|
				if( isset($script_info['package']) ){
 | 
						|
					foreach($scripts as $_key => $_info){
 | 
						|
						if( isset($_info['package']) && $_info['package'] == $script_info['package'] ){
 | 
						|
							unset($scripts[$_key]);
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				unset($scripts[$key]);
 | 
						|
 | 
						|
				echo Output\Assets::FormatAsset($type,$cdn_url);
 | 
						|
			}
 | 
						|
 | 
						|
			return $scripts;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the path for the custom css/scss/less file
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function CustomStyleFile($layout, $style_type){
 | 
						|
			global $dataDir;
 | 
						|
 | 
						|
			if( $style_type == 'scss' ){
 | 
						|
				return $dataDir . '/data/_layouts/' . $layout . '/custom.scss';
 | 
						|
			}
 | 
						|
 | 
						|
			return $dataDir . '/data/_layouts/' . $layout . '/custom.css';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the path for the customizer css/scss/less file
 | 
						|
		 *
 | 
						|
		 * @since 5.2
 | 
						|
		 */
 | 
						|
		public static function CustomizerStyleFile($layout, $style_type){
 | 
						|
			global $dataDir;
 | 
						|
 | 
						|
			if( $style_type == 'scss' ){
 | 
						|
				return $dataDir . '/data/_layouts/' . $layout . '/customizer.scss';
 | 
						|
			}
 | 
						|
 | 
						|
			return $dataDir . '/data/_layouts/' . $layout . '/customizer.css';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the path for the custom layout config file
 | 
						|
		 *
 | 
						|
		 * @since 5.2
 | 
						|
		 */
 | 
						|
		public static function LayoutConfigFile($layout){
 | 
						|
			global $dataDir;
 | 
						|
 | 
						|
			return $dataDir . '/data/_layouts/' . $layout . '/config.php';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the filetype of the style.* file
 | 
						|
		 *
 | 
						|
		 * @return string
 | 
						|
		 */
 | 
						|
		public static function StyleType($dir){
 | 
						|
 | 
						|
			$types = ['less','scss'];
 | 
						|
 | 
						|
			foreach($types as $type){
 | 
						|
				$path = $dir . '/style.'.$type;
 | 
						|
				if( file_exists($path) ){
 | 
						|
					return $type;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return 'css';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Determines whether the passed directory qualifies as layout
 | 
						|
		 * by checking whether a style.css, style.less or style.css file exists
 | 
						|
		 * @return boolean
 | 
						|
		 */
 | 
						|
		public static function IsLayoutDir($dir){
 | 
						|
 | 
						|
			$types = ['less','scss','css'];
 | 
						|
 | 
						|
			foreach($types as $type){
 | 
						|
				$path = $dir . '/style.' . $type;
 | 
						|
				if( file_exists($path) ){
 | 
						|
					return true;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Complete the response by adding final content to the <head> of the document
 | 
						|
		 * @static
 | 
						|
		 * @since 2.4.1
 | 
						|
		 * @param string $buffer html content
 | 
						|
		 * @return string finalized response
 | 
						|
		 */
 | 
						|
		public static function BufferOut($buffer){
 | 
						|
			global $config;
 | 
						|
 | 
						|
			//add error notice if there was a fatal error
 | 
						|
			if( !ini_get('display_errors') ){
 | 
						|
				$last_error	= self::LastFatal();
 | 
						|
				if( !empty($last_error) ){
 | 
						|
					self::RecordFatal($last_error);
 | 
						|
					$buffer .= self::FatalMessage($last_error);
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//remove lock
 | 
						|
			if( defined('gp_has_lock') && \gp_has_lock ){
 | 
						|
				\gp\tool\Files::Unlock('write', \gp_random);
 | 
						|
			}
 | 
						|
 | 
						|
			//make sure whe have a complete html request
 | 
						|
			$placeholder = '<!-- get_head_placeholder ' . \gp_random . ' -->';
 | 
						|
			if( strpos($buffer,$placeholder) === false ){
 | 
						|
				return $buffer;
 | 
						|
			}
 | 
						|
 | 
						|
			$replacements		= [];
 | 
						|
 | 
						|
			//performace stats
 | 
						|
			if( class_exists('admin_tools') ){
 | 
						|
				$replacements	= self::PerformanceStats();
 | 
						|
			}
 | 
						|
 | 
						|
			//head content
 | 
						|
			//add css to bottom of <body>
 | 
						|
			if( \load_css_in_body ){
 | 
						|
				$buffer = self::AddToBody($buffer, self::$head_css);
 | 
						|
				$replacements[$placeholder]	= self::$head_content;
 | 
						|
			}else{
 | 
						|
				$replacements[$placeholder]	= self::$head_css . self::$head_content;
 | 
						|
			}
 | 
						|
 | 
						|
			//add js to bottom of <body>
 | 
						|
			$buffer = self::AddToBody($buffer, self::$head_js);
 | 
						|
 | 
						|
			//add jquery if needed
 | 
						|
			$placeholder = '<!-- jquery_placeholder ' . \gp_random . ' -->';
 | 
						|
			$replacement = '';
 | 
						|
			if( !empty(self::$head_js) || stripos($buffer, '<script') !== false ){
 | 
						|
				$replacement = Output\Assets::FormatAsset('js',\gp\tool::GetDir('/include/thirdparty/js/jquery.js')); // TODO: restore this line
 | 
						|
			}
 | 
						|
 | 
						|
			$replacements[$placeholder]	= $replacement;
 | 
						|
 | 
						|
			//messages
 | 
						|
			$pos = strpos($buffer, '<!-- message_start ' . \gp_random . ' -->');
 | 
						|
			$len = strpos($buffer, '<!-- message_end -->') - $pos;
 | 
						|
			if( $pos && $len ){
 | 
						|
				$replacement = GetMessages(false);
 | 
						|
				$buffer = substr_replace($buffer, $replacement, $pos, $len + 20);
 | 
						|
			}
 | 
						|
 | 
						|
			return str_replace( array_keys($replacements), array_values($replacements), $buffer);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add content to the html document before the </body> tag
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function AddToBody($buffer, $add_string){
 | 
						|
 | 
						|
			if( empty($add_string) ){
 | 
						|
				return $buffer;
 | 
						|
			}
 | 
						|
 | 
						|
			$pos_body = stripos($buffer, '</body');
 | 
						|
			if( $pos_body !== false ){
 | 
						|
				return substr_replace($buffer, "\n" . $add_string . "\n", $pos_body, 0);
 | 
						|
			}
 | 
						|
 | 
						|
			return $buffer;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the message displayed when a fatal error has been caught
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function FatalMessage($error_details){
 | 
						|
 | 
						|
			$message = '<p>Oops, an error occurred while generating this page.<p>';
 | 
						|
 | 
						|
			if( !\gp\tool::LoggedIn() ){
 | 
						|
 | 
						|
				//reload non-logged in users automatically if there were catchable errors
 | 
						|
				if( !empty(self::$catchable) ){
 | 
						|
					$message .= 'Reloading... <script type="text/javascript">'
 | 
						|
						. 'window.setTimeout(function(){window.location.href = '
 | 
						|
						. 'window.location.href},1000);</script>';
 | 
						|
				}else{
 | 
						|
					$message .= '<p>If you are the site administrator, you can troubleshoot '
 | 
						|
						. 'the problem by changing php\'s display_errors setting to 1 in '
 | 
						|
						. 'the gpconfig.php file.</p><p>If the problem is being caused by an addon, '
 | 
						|
						. 'you may also be able to bypass the error by enabling ' . \CMS_NAME . '\'s '
 | 
						|
						. 'safe mode in the gpconfig.php file.</p><p>More information is available '
 | 
						|
						. 'in the <a href="' . \CMS_DOMAIN . '/Docs/Main/Troubleshooting">Documentation</a>.'
 | 
						|
						. '</p><p><a href="?">Reload this page to continue</a>.</p>';
 | 
						|
				}
 | 
						|
 | 
						|
				return $message;
 | 
						|
			}
 | 
						|
 | 
						|
			$message .= '<h3>Error Details</h3>'
 | 
						|
					.pre($error_details)
 | 
						|
					. '<p><a href="?">Reload this page</a></p>'
 | 
						|
					. '<p style="font-size:90%">Note: Error details are only '
 | 
						|
					. 'displayed for logged in administrators</p>'
 | 
						|
					. \gp\tool::ErrorBuffer(true, false);
 | 
						|
 | 
						|
			return $message;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Determine if a fatal error has been fired
 | 
						|
		 * @return array
 | 
						|
		 */
 | 
						|
		public static function LastFatal(){
 | 
						|
			$fatal_errors	= [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR];
 | 
						|
			$last_error		= error_get_last();
 | 
						|
			if( is_array($last_error) && in_array($last_error['type'], $fatal_errors) ){
 | 
						|
				return $last_error;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Record fatal errors in /data/_site/ so we can prevent subsequent requests from having the same issue
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function RecordFatal($last_error){
 | 
						|
			global $config, $addon_current_id, $addonFolderName;
 | 
						|
 | 
						|
			$last_error['request'] = $_SERVER['REQUEST_URI'];
 | 
						|
			if( $addon_current_id ){
 | 
						|
				$last_error['addon_name'] = $config['addons'][$addonFolderName]['name'];
 | 
						|
				$last_error['addon_id'] = $addon_current_id;
 | 
						|
			}
 | 
						|
 | 
						|
			$last_error['file'] = realpath($last_error['file']);//may be redundant
 | 
						|
			showError(
 | 
						|
				$last_error['type'],
 | 
						|
				$last_error['message'],
 | 
						|
				$last_error['file'],
 | 
						|
				$last_error['line'],
 | 
						|
				false
 | 
						|
			); //send error to logger
 | 
						|
 | 
						|
			if( empty(self::$catchable) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			$last_error['time'] = time();
 | 
						|
			$last_error['request_method'] = $_SERVER['REQUEST_METHOD'];
 | 
						|
			if( !empty($last_error['file']) ){
 | 
						|
				$last_error['file_modified'] = filemtime($last_error['file']);
 | 
						|
				$last_error['file_size'] = filesize($last_error['file']);
 | 
						|
			}
 | 
						|
 | 
						|
			$content	= json_encode($last_error);
 | 
						|
			$temp		= array_reverse(self::$catchable);
 | 
						|
 | 
						|
			foreach($temp as $filepath => $info){
 | 
						|
 | 
						|
				\gp\tool\Files::Save($filepath,$content);
 | 
						|
 | 
						|
				if( $info['catchable_type'] == 'exec' ){
 | 
						|
					break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return Performance Stats about the current request
 | 
						|
		 *
 | 
						|
		 * @return array
 | 
						|
		 */
 | 
						|
		public static function PerformanceStats(){
 | 
						|
 | 
						|
			$stats = [];
 | 
						|
 | 
						|
			if( function_exists('memory_get_peak_usage') ){
 | 
						|
				$stats['<span cms-memory-usage>?</span>']	= \gp\admin\Tools::FormatBytes(memory_get_usage());
 | 
						|
				$stats['<span cms-memory-max>?</span>']		= \gp\admin\Tools::FormatBytes(memory_get_peak_usage());
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($_SERVER['REQUEST_TIME_FLOAT']) ){
 | 
						|
				$time	= microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
 | 
						|
			}else{
 | 
						|
				$time	= microtime(true) - gp_start_time;
 | 
						|
			}
 | 
						|
 | 
						|
			$stats['<span cms-seconds>?</span>']	= round($time, 3);
 | 
						|
			$stats['<span cms-ms>?</span>']			= round($time * 1000);
 | 
						|
 | 
						|
			return $stats;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return true if the user agent is a search engine bot
 | 
						|
		 * Detection is rudimentary and shouldn't be relied on
 | 
						|
		 * @return bool
 | 
						|
		 */
 | 
						|
		public static function DetectBot(){
 | 
						|
			$user_agent =& $_SERVER['HTTP_USER_AGENT'];
 | 
						|
			return (bool)preg_match('#bot|yahoo\! slurp|ask jeeves|ia_archiver|spider|crawler#i', $user_agent);
 | 
						|
		}
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return true if the current page is the home page
 | 
						|
		 */
 | 
						|
		public static function is_front_page(){
 | 
						|
			global $config, $page;
 | 
						|
			return $page->gp_index == $config['homepath_key'];
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Outputs the sitemap link, admin login/logout link, powered by link and messages
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetAdminLink($messages=true){
 | 
						|
			self::GetSitemapLink(); // as of 5.2-rc
 | 
						|
			echo ' ';
 | 
						|
			self::GetLoginLink(); // as of 5.2-rc
 | 
						|
			echo ' ';
 | 
						|
			self::GetPoweredByLink(); // as of 5.2-rc
 | 
						|
 | 
						|
			\gp\tool\Plugins::Action('GetAdminLink');
 | 
						|
 | 
						|
			if( $messages ){
 | 
						|
				echo GetMessages();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Outputs only the sitemap link
 | 
						|
		 * as of 5.2-rc
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetSitemapLink(){
 | 
						|
			global $config, $langmessage, $page;
 | 
						|
 | 
						|
			if( !isset($config['showsitemap']) || $config['showsitemap'] ){
 | 
						|
				echo ' <span class="sitemap_link">';
 | 
						|
				echo \gp\tool::Link(
 | 
						|
					'Special_Site_Map',
 | 
						|
					$langmessage['site_map']
 | 
						|
				);
 | 
						|
				\gp\tool\Plugins::Action('GetSitemapLink');
 | 
						|
				echo '</span>';
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Outputs only the login/logout link
 | 
						|
		 * as of 5.2-rc
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetLoginLink($force_show=false){
 | 
						|
			global $config, $langmessage, $page;
 | 
						|
 | 
						|
			if( $force_show || !isset($config['showlogin']) || $config['showlogin'] ){
 | 
						|
				echo '<span class="login_link">';
 | 
						|
					if( \gp\tool::LoggedIn() ){
 | 
						|
						echo \gp\tool::Link(
 | 
						|
							$page->title,
 | 
						|
							$langmessage['logout'],
 | 
						|
							'cmd=logout',
 | 
						|
							['data-cmd' => 'cnreq', 'rel' => 'nofollow']
 | 
						|
						);
 | 
						|
					}else{
 | 
						|
						echo \gp\tool::Link(
 | 
						|
							'Admin',
 | 
						|
							$langmessage['login'],
 | 
						|
							'file=' . rawurlencode($page->title),
 | 
						|
							['data-cmd' => 'login', 'rel' => 'nofollow']
 | 
						|
						);
 | 
						|
					}
 | 
						|
				\gp\tool\Plugins::Action('GetLoginLink');
 | 
						|
				echo '</span>';
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function AdminLinkGadget(){
 | 
						|
			self::GetAdminLink(false);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function LoginLinkGadget(){
 | 
						|
			self::GetLoginLink(true);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Outputs only the powered_by link
 | 
						|
		 * as of 5.2-rc
 | 
						|
		 * @static
 | 
						|
		 */
 | 
						|
		public static function GetPoweredByLink($always_show=false){
 | 
						|
			global $config;
 | 
						|
 | 
						|
			if( !isset($config['showgplink']) || $config['showgplink'] ){
 | 
						|
				if( self::is_front_page() || $always_show ){
 | 
						|
					echo '<span id="powered_by_link">';
 | 
						|
					echo 'Powered by <a href="' . \CMS_DOMAIN . '" target="_blank">' . \CMS_NAME . '</a>';
 | 
						|
					\gp\tool\Plugins::Action('GetPoweredByLink');
 | 
						|
					echo '</span>';
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add punctuation to the end of a string if it isn't already punctuated.
 | 
						|
		 * Looks for !?.,;: characters
 | 
						|
		 *
 | 
						|
		 * @static
 | 
						|
		 * @since 2.4RC1
 | 
						|
		 */
 | 
						|
		public static function EndPhrase($string){
 | 
						|
			$string = trim($string);
 | 
						|
			if( empty($string) ){
 | 
						|
				return $string;
 | 
						|
			}
 | 
						|
			$len = strspn($string, '!?.,;:', -1);
 | 
						|
			if( $len == 0 ){
 | 
						|
				$string .= '.';
 | 
						|
			}
 | 
						|
			return $string . ' ';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function RunOut(){
 | 
						|
			global $langmessage, $page;
 | 
						|
 | 
						|
			$page->RunScript();
 | 
						|
 | 
						|
			//prepare the admin content
 | 
						|
			if( \gp\tool::LoggedIn() ){
 | 
						|
				\gp\admin\Tools::AdminHtml();
 | 
						|
			}
 | 
						|
 | 
						|
			//decide how to send the content
 | 
						|
			self::Prep();
 | 
						|
			switch(\gp\tool::RequestType()){
 | 
						|
 | 
						|
				// <a data-cmd="admin_box">
 | 
						|
				case 'flush':
 | 
						|
					self::Flush();
 | 
						|
					break;
 | 
						|
 | 
						|
				// remote request
 | 
						|
				// file browser
 | 
						|
				case 'body':
 | 
						|
					\gp\tool::CheckTheme();
 | 
						|
					self::BodyAsHTML();
 | 
						|
					break;
 | 
						|
 | 
						|
				case 'admin':
 | 
						|
					self::AdminHtml();
 | 
						|
					break;
 | 
						|
 | 
						|
				// <a data-cmd="gpajax">
 | 
						|
				// <a data-cmd="gpabox">
 | 
						|
				// <input data-cmd="gpabox">
 | 
						|
				case 'json':
 | 
						|
					\gp\tool::CheckTheme();
 | 
						|
					\gp\tool\Output\Ajax::Response();
 | 
						|
					break;
 | 
						|
 | 
						|
				case 'content':
 | 
						|
					self::Content();
 | 
						|
					break;
 | 
						|
 | 
						|
				default:
 | 
						|
					\gp\tool::CheckTheme();
 | 
						|
					self::Template();
 | 
						|
					break;
 | 
						|
			}
 | 
						|
 | 
						|
			// if logged in, don't send 304 response
 | 
						|
			if( \gp\tool::LoggedIn() ){
 | 
						|
				//empty edit links if there isn't a layout
 | 
						|
				if( !$page->gpLayout ){
 | 
						|
					self::$editlinks = '';
 | 
						|
				}
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			// attempt to send 304 response
 | 
						|
			if( $page->fileModTime > 0 ){
 | 
						|
				global $wbMessageBuffer;
 | 
						|
				$len	= ob_get_length();
 | 
						|
				$etag	= \gp\tool::GenEtag(
 | 
						|
					$page->fileModTime,
 | 
						|
					$len,
 | 
						|
					json_encode($wbMessageBuffer),
 | 
						|
					self::$head_content,
 | 
						|
					self::$head_js
 | 
						|
				);
 | 
						|
				\gp\tool::Send304($etag);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add one or more components to the page. Output the <script> and/or <style> immediately
 | 
						|
		 * @param string $names comma separated list of components
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetComponents($names=''){
 | 
						|
			$scripts = \gp\tool\Output\Combine::ScriptInfo($names);
 | 
						|
 | 
						|
			$scripts['css'] = self::GetHead_CDN('css', $scripts['css']);
 | 
						|
			Output\Assets::CombineFiles($scripts['css'], 'css', false);
 | 
						|
 | 
						|
			$scripts['js'] = self::GetHead_CDN('js', $scripts['js']);
 | 
						|
			Output\Assets::CombineFiles($scripts['js'], 'js', false);
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
namespace{
 | 
						|
	class gpOutput extends gp\tool\Output{}
 | 
						|
}
 |