-ident-, 1 => -ident-] $gpLayout['Loyout_Name']['color'] = '#123456' $gpLayout['Loyout_Name']['theme'] = 'One_Point_5/Blue' */ #[\AllowDynamicProperties] class Layout extends \gp\admin\Addon\Install{ public $curr_layout; protected $layout_request = false; protected $LayoutArray; protected $scriptUrl = 'Admin_Theme_Content'; protected $versions = []; //remote install variables public $config_index = 'themes'; public $code_folder_name = '_themes'; public $path_remote = 'Admin_Theme_Content/Remote'; private $gpLayouts_before; private $config_before; public function __construct($args){ global $gpLayouts, $config; parent::__construct($args); $this->gpLayouts_before = $gpLayouts; $this->config_before = $config; if( $this->page ){ $this->page->head_js[] = '/include/js/theme_content.js'; $this->page->head_js[] = '/include/js/dragdrop.js'; $this->page->css_admin[] = '/include/css/theme_content.scss'; } \gp\tool::LoadComponents('resizable'); $this->GetPossible(); } public function RunScript(){ global $config, $gpLayouts, $langmessage; $cmd = \gp\tool::GetCommand(); //set current layout $this->curr_layout = $config['gpLayout']; if( isset($_REQUEST['layout']) ){ $this->curr_layout = $_REQUEST['layout']; } if( !array_key_exists($this->curr_layout,$gpLayouts) ){ msg($langmessage['OOPS'].' (Invalid Layout)'); $cmd = ''; } $this->SetLayoutArray(); //Installation $this->cmds['remote_install'] = 'RemoteInstall'; $this->cmds['RemoteInstall'] = ''; $this->cmds['RemoteInstallConfirmed'] = 'DefaultDisplay'; $this->cmds['UpgradeTheme'] = 'DefaultDisplay'; //Copy, Delete $this->cmds['CopyLayoutPrompt'] = ''; $this->cmds['CopyLayout'] = 'DefaultDisplay'; $this->cmds['DeleteLayout'] = 'DefaultDisplay'; //Reviews $this->cmds['SendAddonReview'] = ''; $this->cmds['ReviewAddonForm'] = ''; $this->cmds['addontext'] = 'RedirectText'; $this->LayoutCommands(); $this->RunCommands($cmd); } /** * Redirect addontext requests to correct path for TS 5.0+ * */ protected function RedirectText(){ $params = $_GET; $params['cmd'] = 'AddonTextForm'; $url = \gp\tool::GetUrl( 'Admin_Theme_Content/Text', http_build_query($params, '', '&'), false ); \gp\tool::Redirect($url); } /** * Perform various layout commands * */ public function LayoutCommands(){ $this->cmds['ShowTitles'] = ''; $this->cmds['ShowGadgets'] = ''; $this->cmds['LayoutLabel'] = ''; $this->cmds['MakeDefault'] = 'DefaultDisplay'; $this->cmds['CSSPreferences'] = ''; $this->cmds['RestoreLayout'] = 'DefaultDisplay'; $this->cmds['RmGadget'] = 'ShowGadgets'; } /** * Show all layouts and themes * */ public function DefaultDisplay(){ global $config, $langmessage, $gpLayouts; $this->page->head_js[] = '/include/js/auto_width.js'; $this->ShowHeader(); echo '
'; //all other layouts foreach($gpLayouts as $layout => $info){ $this->LayoutDiv($layout,$info); } echo '
'; echo '
'; echo '

'; echo $langmessage['see_also'] . ' '; echo \gp\tool::Link('Admin/Menu', $langmessage['file_manager']); echo '

'; $this->ColorSelector(); } /** * Display a list of all the titles using the current layout * */ public function ShowTitles(){ global $langmessage; //affected titles $titles_count = $this->TitlesCount($this->curr_layout); echo '

' . $langmessage['titles_using_layout']; echo ': ' . $titles_count; echo '

'; if( $titles_count > 0 ){ echo ''; echo '
'; } } /** * Display gadgets and their status for the current layout * */ public function ShowGadgets(){ global $langmessage, $config; $gadget_info = \gp\tool\Output::WhichGadgets($this->curr_layout); echo '

' . $langmessage['gadgets'] . '

'; echo ''; echo ''; if( !isset($config['gadgets']) || count($config['gadgets']) == 0 ){ echo ''; }else{ foreach($config['gadgets'] as $gadget => $temp){ echo ''; } } echo '
 
'; echo $langmessage['Empty']; echo '
'; echo str_replace('_', ' ', $gadget); echo ''; if( isset($gadget_info[$gadget]) ){ echo $this->LayoutLink( $this->curr_layout, $langmessage['remove'], 'cmd=RmGadget&gadget=' . urlencode($gadget), ['data-cmd' => 'gpabox'] ); }else{ echo $langmessage['disabled']; } echo '
'; } /** * Create a drop-down menu for the layout options * */ public function LayoutOptions($layout,$info){ global $langmessage, $config; //theme name echo '
  • '; echo '' . $langmessage['theme'] . ': '; echo $this->ThemeLabel($info['theme_name']); echo ''; echo '
  • '; //default echo '
  • '; if( $config['gpLayout'] == $layout ){ echo '' . $langmessage['default'] . ''; }else{ echo \gp\tool::Link( 'Admin_Theme_Content', $langmessage['make_default'], 'cmd=MakeDefault&layout=' . rawurlencode($layout), [ 'data-cmd' => 'creq', 'title' => $langmessage['make_default'], ] ); } echo '
  • '; //gadgets echo '
  • '; echo $this->LayoutLink( $layout, $langmessage['gadgets'], 'cmd=ShowGadgets', ['data-cmd' => 'gpabox'] ); echo '
  • '; //titles using layout echo '
  • '; $titles_count = $this->TitlesCount($layout); $label = sprintf($langmessage['%s Pages'], $titles_count); if( $titles_count ){ echo $this->LayoutLink( $layout, $label, 'cmd=ShowTitles', ['data-cmd' => 'gpabox'] ); }else{ echo '' . $label . ''; } echo '
  • '; //content arrangement $handlers_count = $this->HandlersCount($info); echo '
  • '; if( $handlers_count ){ echo $this->LayoutLink( $layout, $langmessage['restore_defaults'], 'cmd=RestoreLayout', ['data-cmd' => 'creq'] ); }else{ echo ''; echo $langmessage['content_arrangement'] . ': ' . $langmessage['default']; echo ''; } echo '
  • '; //copy echo '
  • '; $query = 'cmd=CopyLayoutPrompt&layout=' . $layout; echo \gp\tool::Link( 'Admin_Theme_Content', $langmessage['Copy'], $query, ['data-cmd' => 'gpabox'] ); echo '
  • '; //delete if( $config['gpLayout'] != $layout ){ echo '
  • '; $attr = [ 'data-cmd' => 'creq', 'class' => 'gpconfirm', 'title' => sprintf($langmessage['generic_delete_confirm'], $info['label']), ]; echo \gp\tool::Link( 'Admin_Theme_Content', $langmessage['delete'], 'cmd=deletelayout&layout=' . $layout, $attr ); echo '
  • '; } } /** * Get number of handlers * */ public function HandlersCount($layout_info){ $handlers_count = 0; if( isset($layout_info['handlers']) && is_array($layout_info['handlers']) ){ foreach($layout_info['handlers'] as $val){ $int = count($val); if( $int === 0){ $handlers_count++; } $handlers_count += $int; } } return $handlers_count; } /** * Get the layout customizer array if customizer.php exists * @since 5.2 * @param string the layout id * @return array layout customizer */ public function GetLayoutCustomizer($layout){ $layout_info = \gp\tool::LayoutInfo($layout, false); $dir = $layout_info['dir'] . '/' . $layout_info['theme_color']; $customizer_file = $dir . '/customizer.php'; if( file_exists($customizer_file) ){ return \gp\tool\Files::Get($customizer_file, 'customizer'); } return []; } /** * Get the custom config for a layout if it exists * @since 5.2 * @param string the layout id * @return array layout configuration * */ public function GetLayoutConfig($layout){ $config_file = \gp\tool\Output::LayoutConfigFile($layout); if( file_exists($config_file) ){ $config = \gp\tool\Files::Get($config_file, 'config'); if( !empty($config) ){ return $config; } } // not yet saved? - get the defaults from customizer return $this->GetLayoutDefaultConfig($layout); } /** * Extract default config values from customizer definition file * @since 5.2 * @param string the layout id * @return array default config * */ public function GetLayoutDefaultConfig($layout){ $customizer_data = $this->GetLayoutCustomizer($layout); if( empty($customizer_data) ){ return []; } $default_config = []; foreach( $customizer_data as $area => $area_info ){ foreach( $area_info['items'] as $var_name => $var_data ){ $default_config[$var_name] = []; $default_config[$var_name]['value'] = $var_data['default_value']; if( !empty($var_data['default_units']) ){ $default_config[$var_name]['units'] = $var_data['default_units']; } } } return $default_config; } /** * Get the path of the customizer css file * @since 5.2 * @param string the layout id * @return string * */ public function GetCustomizerCSSFile($layout){ $layout_info = \gp\tool::LayoutInfo($layout, false); $dir = $layout_info['dir'] . '/' . $layout_info['theme_color']; $style_type = \gp\tool\Output::StyleType($dir); return \gp\tool\Output::CustomizerStyleFile($layout, $style_type); } /** * @deprecated 5.2 * use GetLayoutCSS instead */ public function LayoutCSS($layout){ return $this->GetLayoutCSS($layout); } /** * Get the custom css for a layout if it exists * @since 5.2 * @param string the layout id * @return string CSS, SCSS or LESS */ public function GetLayoutCSS($layout){ $custom_css_file = $this->GetLayoutCSSFile($layout); if( file_exists($custom_css_file) ){ return file_get_contents($custom_css_file); } return ''; } /** * @deprecated 5.2 * use SaveCustomCSS instead */ public function SaveCustom($layout, $css){ $this->SaveCustomCSS($layout, $css); } /** * Save the custom.css / .less / .scss file * @since 5.2 * @param string the layout id * @param string CSS, SCSS or LESS * @return bool success * */ public function SaveCustomCSS($layout, $css){ global $langmessage; $custom_file = $this->GetLayoutCSSFile($layout); //delete css file if empty if( empty($css) ){ return $this->RemoveCSS($layout, $custom_file); } //save if not empty if( !\gp\tool\Files::Save($custom_file, $css) ){ msg($langmessage['OOPS'] . ' (CSS not saved)'); return false; } return true; } /** * Save the data posted by customizer * @since 5.2 * @param string the layout id * @param array customizer results * @return bool success * */ public function SaveCustomizerResults($layout, $customizer_results){ $success = true; // customizer css $customizer_css = ''; if( !empty($customizer_results['scssless_vars']) ){ $customizer_css .= $customizer_results['scssless_vars']; } if( !empty($customizer_results['css_vars']) ){ $customizer_css .= $customizer_results['css_vars']; } $success = $success && $this->SaveCustomizerCSS($layout, $customizer_css); // layout config $layout_config = !empty($customizer_results['layout_config']) ? $customizer_results['layout_config'] : []; $success = $success && $this->SaveLayoutConfig($layout, $layout_config); return $success; } /** * Save the layout config from customizer * @since 5.2 * @param string the layout id * @param array layout config * @return bool success * */ public function SaveLayoutConfig($layout, $layout_config){ global $langmessage; $success = true; $layout_config_file = \gp\tool\Output::LayoutConfigFile($layout); if( empty($layout_config) ){ // delete layout config file if empty $success = $success && $this->RemoveLayoutConfig($layout); // save it otherwise }elseif( !\gp\tool\Files::SaveData($layout_config_file, 'config', $layout_config) ){ msg($langmessage['OOPS'] . ' (Layout config not saved)'); $success = false; } return $success; } /** * Get the customizer css for a layout if it exists * @since 5.2 * @param string the layout id * @return string CSS, SCSS or LESS */ public function GetCustomizerCSS($layout){ $customizer_css_file = $this->GetCustomizerCSSFile($layout); if( file_exists($customizer_css_file) ){ return file_get_contents($customizer_css_file); } return ''; } /** * Save the customizer css * @since 5.2 * @param string the layout id * @param array customizer results * @return bool success * */ public function SaveCustomizerCSS($layout, $customizer_css){ global $langmessage; $success = true; $customizer_css_file = $this->GetCustomizerCSSFile($layout); if( empty($customizer_css) ){ // delete css file if empty $success = $success && $this->RemoveCustomizerCSS($layout, $customizer_css_file); // save it otherwise }elseif( !\gp\tool\Files::Save($customizer_css_file, $customizer_css) ){ msg($langmessage['OOPS'] . ' (Customizer stylesheet not saved)'); $success = false; } return $success; } /** * @deprecated 5.2 * use GetLayoutCSSFile instead */ public function LayoutCSSFile($layout){ return $this->GetLayoutCSSFile(); } /** * Get the path of the custom css file * @since 5.2 * @param string the layout id * @return string * */ public function GetLayoutCSSFile($layout){ $layout_info = \gp\tool::LayoutInfo($layout, false); $dir = $layout_info['dir'] . '/' . $layout_info['theme_color']; $style_type = \gp\tool\Output::StyleType($dir); return \gp\tool\Output::CustomStyleFile($layout, $style_type); } /** * Remove the custom css file and unset the 'css' key from a layout * @param string the layout id * @param string custom file abspath * @return bool success */ public function RemoveCSS($layout, $custom_file){ global $gpLayouts; if( file_exists($custom_file) ){ unlink($custom_file); } if( isset($gpLayouts[$layout]['css']) ){ unset($gpLayouts[$layout]['css']); } return true; } /** * Remove the customizer.scss/less/css file for a layout * @since 5.2 * @param string the layout id * @return bool success * */ public function RemoveCustomizerCSS($layout){ global $gpLayouts; $customizer_css_file = $this->GetCustomizerCSSFile($layout); if( file_exists($customizer_css_file) ){ unlink($customizer_css_file); } if( isset($gpLayouts[$layout]['customizer_css']) ){ unset($gpLayouts[$layout]['customizer_css']); } return true; } /** * Remove the custom config.php file for a layout * @since 5.2 * @param string the layout id * @return bool success * */ public function RemoveLayoutConfig($layout){ global $gpLayouts; $config_file = \gp\tool\Output::LayoutConfigFile($layout); if( file_exists($config_file) ){ unlink($config_file); } if( isset($gpLayouts[$layout]['config']) ){ unset($gpLayouts[$layout]['config']); } return true; } /** * Entirely remove the custom layout data direcory and its content * @since 5.2 * @param string the layout directory * @return bool success * */ public function RemoveCustomDir($layout){ global $langmessage, $dataDir; $dir = $dataDir . '/data/_layouts/' . $layout; if( !file_exists($dir) ){ return false; } $remove_files = [ $dir . '/custom.css', $dir . '/custom.less', $dir . '/custom.scss', $dir . '/customizer.css', $dir . '/customizer.less', $dir . '/customizer.scss', $dir . '/config.php', $dir . '/index.html', ]; foreach($remove_files as $path){ if( file_exists($path) ){ @unlink($path); } } if( !\gp\tool\Files::RmDir($dir) ){ msg( $langmessage['OOPS'] . ' Cannot remove /data/_layouts/' . htmlspecialchars($layout) . '. Directory is not empty.' ); return false; }; return true; } /** * Save changes to the css settings for a layout * */ public function CSSPreferences(){ global $langmessage, $gpLayouts; $new_info = $gpLayouts[$this->curr_layout]; if( isset($_POST['menu_css_ordered']) ){ if( $_POST['menu_css_ordered'] === 'off' ){ $new_info['menu_css_ordered'] = false; }else{ unset($new_info['menu_css_ordered']); } } if( isset($_POST['menu_css_indexed']) ){ if( $_POST['menu_css_indexed'] === 'off' ){ $new_info['menu_css_indexed'] = false; }else{ unset($new_info['menu_css_indexed']); } } $gpLayouts[$this->curr_layout] = $new_info; if( !$this->SaveLayouts(false) ){ return; } if( $this->layout_request || $this->page->gpLayout == $this->curr_layout ){ $this->page->SetTheme($this->curr_layout); } $content = $this->CSSPreferenceForm($this->curr_layout,$new_info); $this->page->ajaxReplace = []; $this->page->ajaxReplace[] = [ 'replace', '#layout_css_ul_' . $this->curr_layout, $content ]; } /** * Remove a gadget from a layout * @return null * */ public function RmGadget(){ global $langmessage; //$this->page->ajaxReplace = []; $gadget =& $_REQUEST['gadget']; $handlers = $this->GetAllHandlers($this->curr_layout); //make sure GetAllGadgets is set $this->PrepContainerHandlers( $handlers, 'GetAllGadgets', 'GetAllGadgets' ); $changed = false; foreach($handlers as $container => $container_info){ foreach($container_info as $key => $gpOutCmd){ if( $gpOutCmd == $gadget ){ $changed = true; unset($handlers[$container][$key]); } } } if( !$changed ){ msg($langmessage['OOPS'] . ' (Not Changed)'); return; } $this->SaveHandlersNew($handlers, $this->curr_layout); } public static function GetRandColor(){ $colors = self::GetColors(); $color_key = array_rand($colors); return $colors[$color_key]; } public static function GetColors(){ return [ '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#9900ff', '#ff00ff', '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#cfe2f3', '#d9d2e9', '#ead1dc', '#ea9999', '#f9cb9c', '#ffe599', '#b6d7a8', '#a2c4c9', '#9fc5e8', '#b4a7d6', '#d5a6bd', '#e06666', '#f6b26b', '#ffd966', '#93c47d', '#76a5af', '#6fa8dc', '#8e7cc3', '#c27ba0', '#cc0000', '#e69138', '#f1c232', '#6aa84f', '#45818e', '#3d85c6', '#674ea7', '#a64d79', '#990000', '#b45f06', '#bf9000', '#38761d', '#134f5c', '#0b5394', '#351c75', '#741b47', ]; } /** * Update theme hooks and references in any related layouts * * */ public function UpgradeTheme(){ global $langmessage, $gpLayouts; $theme =& $_REQUEST['source']; $theme_info = $this->ThemeInfo($theme); if( !$theme_info ){ msg($langmessage['OOPS'] . ' (Invalid Source)'); return false; } //install addon $installer = new \gp\admin\Addon\Installer(); $installer->addon_folder_rel = dirname($theme_info['rel']); $installer->code_folder_name = '_themes'; $installer->source = $theme_info['full_dir']; $success = $installer->Install(); $installer->OutputMessages(); if( !$success ){ return; } $this->UpdateLayouts($installer); } /** * Update related layouts with new $theme_info * */ public function UpdateLayouts($installer){ global $gpLayouts, $langmessage; $theme_folder = basename($installer->dest); if( strpos($installer->dest, '/data/_themes') !== false ){ $new_layout_info = $this->AvailableTheme('/data/_themes', true, $theme_folder); }else{ $new_layout_info = $this->AvailableTheme('/themes', false, $theme_folder); } if( $new_layout_info === false ){ return; } if( $installer->has_hooks ){ $new_layout_info['addon_key'] = $installer->config_key; } // update each layout foreach($gpLayouts as $layout => $layout_info){ if( !$this->SameTheme($layout_info, $new_layout_info) ){ continue; } unset( $layout_info['is_addon'], $layout_info['addon_id'], $layout_info['version'], $layout_info['name'], $layout_info['addon_key'] ); $layout_info += $new_layout_info; $layout_info['theme'] = $theme_folder . '/' . basename($layout_info['theme']); $gpLayouts[$layout] = $layout_info; } $this->SaveLayouts(); } /** * Return true if two layouts use the same theme * */ public function SameTheme($layout_info, $new_layout_info ){ //if we have addon ids if( isset($new_layout_info['addon_id']) && isset($layout_info['addon_id']) && $layout_info['addon_id'] == $new_layout_info['addon_id'] ){ return true; } if( isset($layout_info['is_addon']) && $layout_info['is_addon'] ){ $layout_info['rel'] = '/data/_themes/' . dirname($layout_info['theme']); }else{ $layout_info['rel'] = '/themes/' . dirname($layout_info['theme']); } $keys = ['is_addon' => '', 'rel' => '']; $testa = array_intersect_key($layout_info, $keys); $testb = array_intersect_key($new_layout_info, $keys); if( $testa === $testb ){ return true; } return false; } /** * */ public function RemoteInstallConfirmed($type='themes'){ $installer = parent::RemoteInstallConfirmed($type); $this->GetPossible(); $this->UpdateLayouts($installer); } /** * Display some options before copying a layout * */ public function CopyLayoutPrompt(){ global $langmessage, $gpLayouts; $layout = $this->ReqLayout(); if( $layout === false ){ return; } $label = self::NewLabel($gpLayouts[$layout]['label']); echo '

    ' . $langmessage['new_layout'] . '

    '; echo '
    '; echo ''; echo ''; echo ''; echo ''; echo '
    '; echo $langmessage['options']; echo '
    '; echo $langmessage['label']; echo ''; echo ''; echo '
    '; echo $langmessage['make_default']; echo ''; echo ''; echo '
    '; echo '

    '; echo ' '; echo ' '; echo ' '; echo '

    '; echo '
    '; } /** * Copy a layout * */ public function CopyLayout(){ global $gpLayouts, $langmessage; $copy_id = $this->ReqLayout(); if( $copy_id === false ){ return; } if( empty($_POST['label']) ){ msg($langmessage['OOPS'] . '(Empty Label)'); return; } $newLayout = $gpLayouts[$copy_id]; $newLayout['color'] = self::GetRandColor(); $newLayout['label'] = htmlspecialchars($_POST['label']); //get new unique layout id do{ $layout_id = rand(1000, 9999); }while(isset($gpLayouts[$layout_id])); $gpLayouts[$layout_id] = $newLayout; if( !\gp\tool\Files::ArrayInsert($copy_id, $layout_id, $newLayout, $gpLayouts, 1) ){ msg($langmessage['OOPS'] . '(Not Inserted)'); return; } $success = true; //copy any css $css = $this->GetLayoutCSS($copy_id); if( !$this->SaveCustom($layout_id, $css) ){ $success = false; } //copy possible customizer css $customizer_css = $this->GetCustomizerCSS($copy_id); if( !empty($customizer_css) && !$this->SaveCustomizerCSS($layout_id, $customizer_css) ){ $success = false; } //copy possible layout config $layout_config = $this->GetLayoutConfig($copy_id); if( !empty($layout_config) && !$this->SaveLayoutConfig($layout_id, $layout_config) ){ $success = false; } if (!empty($_POST['default'])){ $this->SaveLayouts(false); $this->curr_layout = $layout_id; $this->MakeDefault(); }else{ $this->SaveLayouts(); } } /** * Save the gpLayouts data * */ protected function SaveLayouts($notify_user=true){ global $gpLayouts; if( \gp\admin\Tools::SavePagesPHP($notify_user, $notify_user) ){ return true; } if( is_array($this->gpLayouts_before) ){ $gpLayouts = $this->gpLayouts_before; } return false; } /** * Save the config setting * NOTE: This is not layout config but global system config! */ protected function SaveConfig(){ global $config; if( \gp\admin\Tools::SaveConfig(true, true) ){ return true; } if( is_array($this->config_before) ){ $config = $this->config_before; } return false; } /** * Create a new unique layout label * @static */ public function NewLabel($label){ global $gpLayouts; $labels = []; foreach($gpLayouts as $info){ $labels[$info['label']] = true; } $len = strlen($label); if( $len > 25 ){ $label = substr($label,0,$len-2); } if( substr($label, $len - 2, 1) === '_' && is_numeric(substr($label, $len - 1, 1)) ){ $label = substr($label, 0, $len - 2); } $int = 1; do{ $new_label = $label . '_' . $int; $int++; }while(isset($labels[$new_label])); return $new_label; } public function LoremIpsum(){ global $langmessage, $gp_titles, $gp_menu; ob_start(); echo '

    H1 Lorem Ipsum Heading

    '; echo '

    Paragraph (larger): Lorem ipsum dolor sit amet, consectetur adipisicing elit, '; echo 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. '; echo 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

    '; echo '

    H2 Lorem Ipsum Heading

    '; echo '

    Paragraph: Excepteur sint emphasize cupidatat non strong proident, sunt in '; echo 'emphasized strong culpa qui officia anchor '; echo 'deserunt underline mollit anim id est laborum. Duis aute irure dolor in reprehenderit in voluptate '; echo 'velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui '; echo 'abbr officia deserunt mollit mark anim id est code laborum.

    '; echo '
    Blockquote: Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    '; echo '
    '; echo '
    '; echo '

    Unordered list

    '; echo ''; echo '
    '; // /.gpCol-4 echo '
    '; echo '

    Ordered list

    '; echo '
      '; echo '
    1. Lorem Ipsum ordered list item
    2. '; echo '
    3. Lorem Ipsum ordered list item
    4. '; echo '
    5. Lorem Ipsum ordered list item
    6. '; echo '
    7. Lorem Ipsum ordered list item
    8. '; echo '
    '; echo '
    '; // /.gpCol-4 echo '
    '; echo '

    Description list

    '; echo '
    '; echo '
    Lorem Ipsum term
    Lorem Ipsum description
    '; echo '
    Lorem Ipsum term
    Lorem Ipsum description
    '; echo '
    '; echo '
    '; // /.gpCol-4 echo '
    '; // /.gpRow echo '
    '; echo '
    '; echo '
    '; echo '

    H3 Lorem Ipsum Heading

    '; echo '

    H4 Lorem Ipsum Heading

    '; echo '
    H5 Lorem Ipsum Heading
    '; echo '
    H6 Lorem Ipsum Heading
    '; echo '

    Paragraph (smaller): Excepteur sint cupidatat non proident, sunt in '; echo 'culpa qui officia deserunt mollit anim id est laborum. Duis aute irure dolor in reprehenderit '; echo 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat '; echo 'non proident.

    '; echo '
    '; // /.gpCol-6 echo '
    '; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
    Unstyled Table - Heading
    Row 1, Cell 1Row 1, Cell 2Row 1, Cell 3
    Row 2, Cell 1Row 2, Cell 2Row 2, Cell 3
    Row 3, Cell 1Row 3, Cell 2Row 3, Cell 3
    Row 4, Cell 1Row 4, Cell 2Row 4, Cell 3
    Row 5, Cell 1Row 5, Cell 2Row 5, Cell 3
    '; echo '
    '; // /.gpCol-6 echo '
    '; // /.gpRow echo '
    '; $this->page->non_admin_content = ob_get_clean(); // boostrap content ob_start(); echo '

    H1 Lorem Ipsum Heading + small

    '; echo '

    Lead: Lorem ipsum dolor sit amet, consectetur adipisicing elit, '; echo 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. '; echo 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

    '; echo '

    H2 Lorem Ipsum Heading + small

    '; echo '

    Default paragraph: Excepteur sint emphasize cupidatat non strong proident, sunt in '; echo 'emphasized strong culpa qui officia anchor '; echo 'deserunt underline mollit anim id est laborum. Duis aute irure dolor in reprehenderit in voluptate '; echo 'velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint kbd occaecat cupidatat non proident, sunt in culpa qui '; echo 'abbr officia deserunt mollit mark anim id est code laborum.

    '; echo '

    '; echo 'text-muted   '; echo 'text-primary   '; echo 'text-secondary   '; echo 'text-success   '; echo 'text-info   '; echo 'text-warning   '; echo 'text-danger   '; echo 'badge'; // echo '    label label-default'; echo '

    '; echo '
    Blockquote: Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    '; echo '
    '; echo '
    '; echo '

    Unordered list

    '; echo ''; echo '
    '; // /.col-md-4 echo '
    '; echo '

    Ordered list

    '; echo '
      '; echo '
    1. Lorem Ipsum ordered list item
    2. '; echo '
    3. Lorem Ipsum ordered list item
    4. '; echo '
    5. Lorem Ipsum ordered list item
    6. '; echo '
    7. Lorem Ipsum ordered list item
    8. '; echo '
    '; echo '
    '; // /.col-md-4 echo '
    '; echo '

    Description list

    '; echo '
    '; echo '
    Lorem Ipsum term
    Lorem Ipsum description
    '; echo '
    Lorem Ipsum term
    Lorem Ipsum description
    '; echo '
    '; echo '
    '; // /.col-md-4 echo '
    '; // /.row echo '
    '; echo '
    '; echo '

    H3 Lorem Ipsum Heading + small

    '; echo '

    H4 Lorem Ipsum Heading + small

    '; echo '
    H5 Lorem Ipsum Heading + small
    '; echo '
    H6 Lorem Ipsum Heading + small
    '; echo '

    Small text paragraph: Excepteur sint cupidatat non proident, sunt in '; echo 'culpa qui officia deserunt mollit anim id est laborum. Duis aute irure dolor in reprehenderit '; echo 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat '; echo 'non proident. '; echo '

    '; echo '
    '; echo '

    '; echo 'btn-primary   '; echo 'btn-secondary   '; echo 'btn-success'; echo '

    '; echo '
    '; echo '

    '; echo 'btn-info   '; echo 'btn-warning   '; echo 'btn-danger'; echo '

    '; echo '
    '; echo '

    '; echo 'btn-default   '; echo 'btn-link'; echo '

    '; echo '
    '; echo '
    '; // /.col-md-6 echo '
    '; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
    Table Heading'; echo ''; echo '<table class="table table-bordered table-striped table-hover">'; echo ''; echo '
    Row 1, Cell 1Row 1, Cell 2Row 1, Cell 3
    Row 2, Cell 1Row 2, Cell 2Row 2, Cell 3
    Row 3, Cell 1Row 3, Cell 2Row 3, Cell 3
    Row 4, Cell 1Row 4, Cell 2Row 4, Cell 3
    Row 5, Cell 1Row 5, Cell 2Row 5, Cell 3
    Row 6, Cell 1Row 6, Cell 2Row 6, Cell 3
    Row 7, Cell 1Row 7, Cell 2Row 7, Cell 3
    '; echo '
    '; // /.col-md-6 echo '
    '; // /.row echo '
    '; $this->page->non_admin_content_bootstrap = ob_get_clean(); } public function ThemeInfo($theme){ $template = dirname($theme); $color = basename($theme); if( !isset($this->avail_addons[$template]) || !isset($this->avail_addons[$template]['colors'][$color]) ){ return false; } $theme_info = $this->avail_addons[$template]; $theme_info['color'] = $color; return $theme_info; } /** * Return an array of available themes * @return array * */ public function GetPossible(){ $this->avail_addons = []; $this->versions = []; $this->AvailableThemes('/themes', false); //local themes $this->AvailableThemes('/data/_themes', true); //downloaded themes //remove older versions if( gp_unique_addons ){ $themes = $this->avail_addons; $this->avail_addons = []; foreach($themes as $index => $info){ if( !isset($info['id']) || !isset($info['version']) ){ $this->avail_addons[$index] = $info; continue; } if( version_compare($this->versions[$info['id']]['version'], $info['version'], '>') ){ continue; } $this->avail_addons[$index] = $info; } uksort($this->avail_addons, 'strnatcasecmp'); } } /** * Scan the directory for available themes * */ private function AvailableThemes($dir_rel, $is_addon){ global $dataDir; $dir = $dataDir . $dir_rel; $folders = \gp\tool\Files::readDir($dir, 1); foreach($folders as $folder){ $addon = $this->AvailableTheme($dir_rel, $is_addon, $folder); if( $addon === false ){ continue; } $index = $addon['index']; $this->avail_addons[$index] = $addon; } } /** * Get info about one theme * */ private function AvailableTheme($dir_rel, $is_addon, $folder){ global $dataDir; $full_dir = $dataDir . '/' . $dir_rel . '/' . $folder; $ini_info = $this->GetAvailInstall($full_dir); if( $ini_info === false ){ return false; } if( $is_addon ){ $index = $ini_info['Addon_Name'] . '(remote)'; }else{ $index = $folder . '(local)'; } $this->AddVersionInfo($ini_info, $index); $addon = $this->IniExtract($ini_info); if( empty($addon['name']) ){ $addon['name'] = $folder; } $addon['folder'] = $folder; $addon['colors'] = $this->GetThemeColors($full_dir); $addon['is_addon'] = $is_addon; $addon['full_dir'] = $full_dir; $addon['rel'] = $dir_rel.'/'.$folder; $addon['index'] = $index; return $addon; } /** * Extract addon information from ini content * */ public function IniExtract($ini_info){ $extracted = []; if( isset($ini_info['Addon_Unique_ID']) ){ $extracted['addon_id'] = $ini_info['Addon_Unique_ID']; } if( isset($ini_info['Addon_Version']) ){ $extracted['version'] = $ini_info['Addon_Version']; } if( isset($ini_info['Addon_Name']) ){ $extracted['name'] = $ini_info['Addon_Name']; } if( isset($ini_info['About']) ){ $extracted['name'] = $ini_info['About']; } return $extracted; } /** * Keep track of theme versions * */ private function AddVersionInfo($ini_info,$index){ if( isset($ini_info['Addon_Version']) && isset($ini_info['Addon_Unique_ID']) ){ $addon_id = $ini_info['Addon_Unique_ID']; $version = $ini_info['Addon_Version']; if( !isset($this->versions[$addon_id]) ){ $this->versions[$addon_id] = ['version' => $version, 'index' => $index]; }elseif( version_compare($this->versions[$addon_id]['version'], $version, '<') ){ $this->versions[$addon_id] = ['version' => $version, 'index' => $index]; } } } /** * Return ini info if the addon is installable * @return false|array * */ public function GetAvailInstall($dir){ global $langmessage; $iniFile = $dir . '/Addon.ini'; $template_file = $dir . '/template.php'; $dirname = basename($dir); if( !is_readable($dir) ){ $this->invalid_folders[$dirname] = 'Directory is not readable'; return false; } if( !file_exists($template_file) ){ $this->invalid_folders[$dirname] = 'template.php is not readable or does not exist'; return false; } if( !file_exists($iniFile) ){ return []; } $array = \gp\tool\Ini::ParseFile($iniFile); if( $array === false ){ return []; } $array += ['Addon_Version' => '']; return $array; } /** * Get a list of theme subfolders that have style.css files * */ public function GetThemeColors($dir){ $subdirs = \gp\tool\Files::readDir($dir, 1); $colors = []; asort($subdirs); foreach($subdirs as $subdir){ if( \gp\tool\Output::IsLayoutDir($dir . '/' . $subdir) !== false ){ $colors[$subdir] = $subdir; } } return $colors; } /** * Save $layout as the default layout for the site * */ public function MakeDefault(){ global $config; $config['gpLayout'] = $this->curr_layout; if( $this->SaveConfig() ){ $this->page->SetTheme(); $this->SetLayoutArray(); } } /** * Save the color and label of a layout * */ public function LayoutLabel(){ global $gpLayouts, $langmessage; $this->page->ajaxReplace = []; $layout = $this->ReqLayout(); if( $layout === false ){ return; } if( !empty($_POST['color']) && (strlen($_POST['color']) == 7) && $_POST['color'][0] == '#' ){ $gpLayouts[$layout]['color'] = htmlspecialchars($_POST['color']); } $gpLayouts[$layout]['label'] = htmlspecialchars($_POST['layout_label']); if( !$this->SaveLayouts(false) ){ return; } //send new label $layout_info = \gp\tool::LayoutInfo($layout, false); $replace = $this->GetLayoutLabel($layout, $layout_info); $this->page->ajaxReplace[] = ['replace', '.layout_label_' . $layout, $replace]; } /** * Display the color selector for * @param string $layout The layout being edited * */ public function ColorSelector($layout=false){ global $langmessage; $colors = self::GetColors(); echo '
    '; echo '
    '; $form_action = ($layout === false) ? \gp\tool::GetUrl('Admin_Theme_Content') : \gp\tool::GetUrl('Admin_Theme_Content/Edit/' . $layout); echo '
    '; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
    '; echo ' '; echo ''; echo '
    '; echo '
    '; foreach($colors as $color){ echo ''; echo ''; } echo '
    '; echo '
    '; echo ' '; echo ' '; echo '
    '; echo '
    '; echo '
    '; echo '
    '; } /** * Display layout label and options * */ public function LayoutDiv($layout, $info){ global $langmessage; $layout_info = \gp\tool::LayoutInfo($layout, false); echo '
    '; echo $this->GetLayoutLabel($layout, $info); echo '
    '; echo ''; echo '
    '; echo '
    '; } /** * Output addon information about a layout * */ public function LayoutDivAddon($layout_info){ global $langmessage; // layouts with hooks ob_start(); $addon_config = false; if( isset($layout_info['addon_key']) ){ $addon_key = $layout_info['addon_key']; $addon_config = \gp\tool\Plugins::GetAddonConfig($addon_key); echo '
  • '; echo \gp\tool::Link( 'Admin/Addons/'.\gp\admin\Tools::encode64($addon_key), ' ' . $addon_config['name'] ); echo '
  • '; //hooks $this->AddonPanelGroup($addon_key, false); } //version if( !empty($layout_info['version']) ){ echo '
  • ' . $langmessage['Your_version'] . ' ' . $layout_info['version'] . '
  • '; }elseif( $addon_config && !empty($addon_config['version']) ){ echo '
  • ' . $langmessage['Your_version'] . ' ' . $addon_config['version'] . '
  • '; } //upgrade if( $addon_config !== false ){ echo '
  • '; if( $layout_info['is_addon'] ){ $source = $layout_info['name'] . '(remote)/' . $layout_info['theme_color']; }else{ $source = $layout_info['theme_name'] . '(local)/' . $layout_info['theme_color']; } echo \gp\tool::Link( 'Admin_Theme_Content', $langmessage['upgrade'], 'cmd=UpgradeTheme&source=' . rawurlencode($source), ['data-cmd' => 'creq'] ); echo '
  • '; } $options = ob_get_clean(); if( !empty($options) ){ echo '
  • '; echo '' . $langmessage['options'] . ''; echo '
  • '; } } /** * Return the layout name and id color * */ public function GetLayoutLabel($layout, $layout_info){ global $config, $langmessage, $config; ob_start(); echo ''; echo ''; echo ' '; echo ' '; echo ' '; if( $config['gpLayout'] == $layout ){ echo ' (' . $langmessage['default'] . ')'; echo ' '; } echo '' . $layout_info['label'] . ''; echo ''; echo ''; return ob_get_clean(); } /** * Return form for name based menu classes and ordered menu classes * */ public function CSSPreferenceForm($layout, $layout_info){ global $langmessage; ob_start(); echo ''; return ob_get_clean(); } public function ThemeLabel($theme_color){ $theme = $theme_color; $color = false; if( strpos($theme_color, '/') ){ list($theme,$color) = explode('/', $theme_color); } foreach($this->avail_addons as $info){ if( $info['folder'] == $theme ){ $theme = $info['name']; break; } } if( $color ){ return $theme . '/' . $color; } return $theme; } public function TitlesCount($layout){ $titles_count = 0; foreach($this->LayoutArray as $layout_comparison){ if( $layout == $layout_comparison ){ $titles_count++; } } return $titles_count; } /** * Restore a layout to it's default content arrangement */ public function RestoreLayout(){ $this->SaveHandlersNew([], $this->curr_layout); } public function SaveHandlersNew($handlers, $layout=false){ global $config, $langmessage, $gpLayouts; //make sure the keys are sequential foreach($handlers as $container => $container_info){ if( is_array($container_info) ){ $handlers[$container] = array_values($container_info); } } if( $layout === false ){ $layout = $this->curr_layout; } if( !isset($gpLayouts[$layout]) ){ msg($langmessage['OOPS']); return false; } if( count($handlers) === 0 ){ unset($gpLayouts[$layout]['handlers']); }else{ $gpLayouts[$layout]['handlers'] = $handlers; } $this->SaveLayouts(); } public function GetAllHandlers($layout=false){ global $gpLayouts, $config; if( $layout === false ){ $layout = $this->curr_layout; } $handlers =& $gpLayouts[$layout]['handlers']; if( !is_array($handlers) || count($handlers) < 1 ){ $gpLayouts[$layout]['hander_v'] = '2'; $handlers = []; } //clean : characters for backwards compat foreach($handlers as $container => $container_info){ if( is_string($container_info) ){ $handlers[$container] = trim($container_info, ':'); continue; } if( !is_array($container_info) ){ continue; } foreach($container_info as $key => $gpOutCmd){ $handlers[$container][$key] = trim($gpOutCmd, ':'); } } return $handlers; } //set default values if not set public function PrepContainerHandlers(&$handlers, $container, $gpOutCmd){ if( isset($handlers[$container]) && is_array($handlers[$container]) ){ return; } $handlers[$container] = $this->GetDefaultList($container, $gpOutCmd); } public function GetDefaultList($container, $gpOutCmd){ global $config; if( $container !== 'GetAllGadgets' ){ //Just a container that doesn't have content by default // ex: \gp\tool\Output::Get('AfterContent'); if( empty($gpOutCmd) ){ return []; } return [$gpOutCmd]; } $result = []; if( isset($config['gadgets']) && is_array($config['gadgets']) ){ foreach($config['gadgets'] as $gadget => $info){ if( isset($info['addon']) ){ $result[] = $gadget; } } } return $result; } public function ReturnHeader(){ global $page; $page->ajaxReplace = []; $page->ajaxReplace[] = ['reload']; } public function SetLayoutArray(){ global $gp_menu, $gp_titles, $gp_index, $config; $titleThemes = []; $customThemes = []; $max_level = 5; foreach($gp_menu as $id => $info){ $level = $info['level']; //reset theme inheritance $max_level = max($max_level, $level); for( $i = $level; $i <= $max_level; $i++){ if( isset($customThemes[$i]) ){ $customThemes[$i] = false; } } if( !empty($gp_titles[$id]['gpLayout']) ){ $titleThemes[$id] = $gp_titles[$id]['gpLayout']; }else{ $parent_layout = false; $temp_level = $level; while( $temp_level >= 0 ){ if( isset($customThemes[$temp_level]) && ($customThemes[$temp_level] !== false) ){ $titleThemes[$id] = $parent_layout = $customThemes[$temp_level]; break; } $temp_level--; } if( $parent_layout === false ){ $titleThemes[$id] = $config['gpLayout']; } } $customThemes[$level] = $titleThemes[$id]; } foreach($gp_index as $title => $id){ $titleInfo = $gp_titles[$id]; if( isset($titleThemes[$id]) ){ continue; } if( !empty($titleInfo['gpLayout']) ){ $titleThemes[$id] = $titleInfo['gpLayout']; }else{ $titleThemes[$id] = $config['gpLayout']; } } $this->LayoutArray = $titleThemes; } /** * Remove a layout * */ public function DeleteLayout(){ global $gpLayouts, $langmessage, $gp_titles; $layout =& $_POST['layout']; if( !isset($gpLayouts[$layout]) ){ msg($langmessage['OOPS'] . ' (Layout not set)'); return false; } //remove from $gp_titles $this->RmLayout($layout); } /** * Remove a layout from $gp_titles and $gpLayouts * */ public function RmLayout($layout){ global $gp_titles, $gpLayouts, $langmessage; $this->RmLayoutPrep($layout); //determine if code in /data/_themes/$layout/ should be removed $rm_addon = $this->RemoveAddonCode($layout); unset($gpLayouts[$layout]); //delete and save if( $rm_addon ){ $installer = new \gp\admin\Addon\Installer(); $installer->rm_folders = false; if( !$installer->Uninstall($rm_addon) ){ $gpLayouts = $this->gpLayouts_before; } $installer->OutputMessages(); } if( !$this->SaveLayouts() ){ return false; } //remove custom layout files and its directory $this->RemoveCustomDir($layout); } /** * Determine if the code in /data/_themes/$layout/ should be removed * */ public function RemoveAddonCode($layout){ global $gpLayouts; if( !isset($gpLayouts[$layout]['addon_key']) ){ return false; } $rm_addon = $gpLayouts[$layout]['addon_key']; //don't remove if there are other layouts using the same code foreach($gpLayouts as $layout_id => $info){ if( $layout_id == $layout ){ continue; } if( !array_key_exists('addon_key', $info) ){ continue; } if( $info['addon_key'] == $rm_addon ){ $rm_addon = false; } } return $rm_addon; } public function RmLayoutPrep($layout){ global $gp_titles; //remove from $gp_titles foreach($gp_titles as $title => $titleInfo){ if( empty($titleInfo['gpLayout']) ){ continue; } if( $titleInfo['gpLayout'] == $layout ){ unset($gp_titles[$title]['gpLayout']); } } } public function LayoutUrl($layout, &$query=''){ $url = 'Admin_Theme_Content'; if( $this->layout_request ){ $url = 'Admin_Theme_Content/Edit/' . rawurlencode($layout); }else{ $query .= '&layout=' . rawurlencode($layout); } return $url; } public function LayoutLink($layout, $label, $query, $attr){ $url = $this->LayoutUrl($layout, $query); return \gp\tool::Link($url, $label, $query, $attr); } /** * Get the requested layout * */ public function ReqLayout(){ global $langmessage, $gpLayouts; if( !isset($_REQUEST['layout']) || !isset($gpLayouts[$_REQUEST['layout']]) ){ msg($langmessage['OOPS'] . '(Invalid layout)'); return; } return $_REQUEST['layout']; } }