Typesetter-Original-gtbu/include/admin/Layout.php
2021-09-08 19:52:21 +02:00

2291 lines
56 KiB
PHP

<?php
namespace gp\admin;
defined('is_running') or die('Not an entry point...');
/*
what can be moved?
* .editable_area
How do we position elements?
* above, below in relation to another editable_area
How do we do locate them programatically
* We need to know the calling functions that output the areas
then be able to organize a list of output functions within each of the calling functions
!each area is represented by a list, either a default value if an override hasn't been defined, or the custom list created by the user
How To Identify the Output Functions for the Output Lists?
* Gadgets have:
$info['script']
$info['data']
$info['class']
$gpOutConf = [] of output functions/classes.. to use with the theme content
==potential values==
$gpOutConf[-ident-]['script'] = -path relative to datadir or rootdir?
$gpOutConf[-ident-]['data'] = -path relative to datadir-
$gpOutConf[-ident-]['class'] = -path relative to datadir or rootdir?
$gpOutConf[-ident-]['method'] = string or array: string=name of function, [class, method]
$gpLayout['Loyout_Name']['handlers'][-ident-] = [0 => -ident-, 1 => -ident-]
$gpLayout['Loyout_Name']['color'] = '#123456'
$gpLayout['Loyout_Name']['theme'] = 'One_Point_5/Blue'
*/
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 '<div id="adminlinks2">';
//all other layouts
foreach($gpLayouts as $layout => $info){
$this->LayoutDiv($layout,$info);
}
echo '</div>';
echo '<hr/>';
echo '<p class="admin_note">';
echo $langmessage['see_also'] . ' ';
echo \gp\tool::Link('Admin/Menu', $langmessage['file_manager']);
echo '</p>';
$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 '<h2>' . $langmessage['titles_using_layout'];
echo ': ' . $titles_count;
echo '</h2>';
if( $titles_count > 0 ){
echo '<ul class="titles_using">';
foreach( $this->LayoutArray as $index => $layout_comparison ){
if( $this->curr_layout == $layout_comparison ){
$title = \gp\tool::IndexToTitle($index);
if( empty($title) ){
continue; //may be external link
}
echo "\n" . '<li>';
$label = \gp\tool::GetLabel($title);
$label = \gp\tool::LabelSpecialChars($label);
echo \gp\tool::Link($title, $label);
echo '</li>';
}
}
echo '</ul>';
echo '<div class="clear"></div>';
}
}
/**
* 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 '<h2>' . $langmessage['gadgets'] . '</h2>';
echo '<table class="bordered full_width">';
echo '<tr><th colspan="2">&nbsp;</th></tr>';
if( !isset($config['gadgets']) || count($config['gadgets']) == 0 ){
echo '<tr><td colspan="2">';
echo $langmessage['Empty'];
echo '</td></tr>';
}else{
foreach($config['gadgets'] as $gadget => $temp){
echo '<tr><td>';
echo str_replace('_', ' ', $gadget);
echo '</td><td>';
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 '</td></tr>';
}
}
echo '</table>';
}
/**
* Create a drop-down menu for the layout options
*
*/
public function LayoutOptions($layout,$info){
global $langmessage, $config;
//theme name
echo '<li>';
echo '<span>' . $langmessage['theme'] . ': ';
echo $this->ThemeLabel($info['theme_name']);
echo '</span>';
echo '</li>';
//default
echo '<li>';
if( $config['gpLayout'] == $layout ){
echo '<span><b>' . $langmessage['default'] . '</b></span>';
}else{
echo \gp\tool::Link(
'Admin_Theme_Content',
$langmessage['make_default'],
'cmd=MakeDefault&layout=' . rawurlencode($layout),
[
'data-cmd' => 'creq',
'title' => $langmessage['make_default'],
]
);
}
echo '</li>';
//gadgets
echo '<li>';
echo $this->LayoutLink(
$layout,
$langmessage['gadgets'],
'cmd=ShowGadgets',
['data-cmd' => 'gpabox']
);
echo '</li>';
//titles using layout
echo '<li>';
$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 '<span>' . $label . '</span>';
}
echo '</li>';
//content arrangement
$handlers_count = $this->HandlersCount($info);
echo '<li>';
if( $handlers_count ){
echo $this->LayoutLink(
$layout,
$langmessage['restore_defaults'],
'cmd=RestoreLayout',
['data-cmd' => 'creq']
);
}else{
echo '<span>';
echo $langmessage['content_arrangement'] . ': ' . $langmessage['default'];
echo '</span>';
}
echo '</li>';
//copy
echo '<li>';
$query = 'cmd=CopyLayoutPrompt&layout=' . $layout;
echo \gp\tool::Link(
'Admin_Theme_Content',
$langmessage['Copy'],
$query,
['data-cmd' => 'gpabox']
);
echo '</li>';
//delete
if( $config['gpLayout'] != $layout ){
echo '<li>';
$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 '</li>';
}
}
/**
* 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 '<h2>' . $langmessage['new_layout'] . '</h2>';
echo '<form action="' . \gp\tool::GetUrl('Admin_Theme_Content') . '" method="post">';
echo '<table class="bordered full_width">';
echo '<tr><th colspan="2">';
echo $langmessage['options'];
echo '</th></tr>';
echo '<tr><td>';
echo $langmessage['label'];
echo '</td><td>';
echo '<input type="text" name="label" ';
echo 'value="' . htmlspecialchars($label) . '" class="gpinput" />';
echo '</td></tr>';
echo '<tr><td>';
echo $langmessage['make_default'];
echo '</td><td>';
echo '<input type="checkbox" name="default" value="default" />';
echo '</td></tr>';
echo '</table>';
echo '<p>';
echo ' <input type="hidden" name="layout"';
echo ' value="' . htmlspecialchars($layout) . '" />';
echo ' <button type="submit" name="cmd" value="CopyLayout" class="gpsubmit">';
echo $langmessage['save'];
echo '</button>';
echo ' <input type="button" name="" value="' . $langmessage['cancel'] . '"';
echo ' class="admin_box_close gpcancel" />';
echo '</p>';
echo '</form>';
}
/**
* 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;
}
$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>H1 Lorem Ipsum Heading</h1>';
echo '<p style="font-size:larger;">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. </p>';
echo '<h2>H2 Lorem Ipsum Heading</h2>';
echo '<p>Paragraph: Excepteur sint <em>emphasize</em> cupidatat non <strong>strong</strong> proident, sunt in ';
echo '<em><strong>emphasized strong</strong></em> culpa qui officia <a href="#">anchor</a> ';
echo 'deserunt <u>underline</u> 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 title="abbreviation">abbr</abbr> officia deserunt mollit <mark>mark</mark> anim id est <code>code</code> laborum. </p>';
echo '<blockquote>Blockquote: Lorem ipsum dolor sit amet, consectetur adipisicing elit.</blockquote>';
echo '<div class="gpRow">';
echo '<div class="gpCol-4">';
echo '<h4>Unordered list</h4>';
echo '<ul>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '</ul>';
echo '</div>'; // /.gpCol-4
echo '<div class="gpCol-4">';
echo '<h4>Ordered list</h4>';
echo '<ol>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '</ol>';
echo '</div>'; // /.gpCol-4
echo '<div class="gpCol-4">';
echo '<h4>Description list</h4>';
echo '<dl>';
echo '<dt>Lorem Ipsum term</dt><dd>Lorem Ipsum description</dd>';
echo '<dt>Lorem Ipsum term</dt><dd>Lorem Ipsum description</dd>';
echo '</dl>';
echo '</div>'; // /.gpCol-4
echo '</div>'; // /.gpRow
echo '<hr/>';
echo '<div class="gpRow">';
echo '<div class="gpCol-6">';
echo '<h3>H3 Lorem Ipsum Heading</h3>';
echo '<h4>H4 Lorem Ipsum Heading</h4>';
echo '<h5>H5 Lorem Ipsum Heading</h5>';
echo '<h6>H6 Lorem Ipsum Heading</h6>';
echo '<p style="font-size:smaller;">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. </p>';
echo '</div>'; // /.gpCol-6
echo '<div class="gpCol-6">';
echo '<table>';
echo '<thead>';
echo '<tr>';
echo '<th colspan="3">Unstyled Table - Heading</th>';
echo '</tr>';
echo '</thead>';
echo '<tbody>';
echo '<tr><td>Row&nbsp;1, Cell&nbsp;1</td><td>Row&nbsp;1, Cell&nbsp;2</td><td>Row&nbsp;1, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;2, Cell&nbsp;1</td><td>Row&nbsp;2, Cell&nbsp;2</td><td>Row&nbsp;2, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;3, Cell&nbsp;1</td><td>Row&nbsp;3, Cell&nbsp;2</td><td>Row&nbsp;3, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;4, Cell&nbsp;1</td><td>Row&nbsp;4, Cell&nbsp;2</td><td>Row&nbsp;4, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;5, Cell&nbsp;1</td><td>Row&nbsp;5, Cell&nbsp;2</td><td>Row&nbsp;5, Cell&nbsp;3</td></tr>';
echo '</tbody>';
echo '</table>';
echo '</div>'; // /.gpCol-6
echo '</div>'; // /.gpRow
echo '<div class="gpclear"></div>';
$this->page->non_admin_content = ob_get_clean();
// boostrap content
ob_start();
echo '<h1>H1 Lorem Ipsum Heading <small>+ small</small></h1>';
echo '<p class="lead">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. </p>';
echo '<h2>H2 Lorem Ipsum Heading <small>+ small</small></h2>';
echo '<p>Default paragraph: Excepteur sint <em>emphasize</em> cupidatat non <strong>strong</strong> proident, sunt in ';
echo '<em><strong>emphasized strong</strong></em> culpa qui officia <a href="#">anchor</a> ';
echo 'deserunt <u>underline</u> 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>kbd</kbd> occaecat cupidatat non proident, sunt in culpa qui ';
echo '<abbr title="abbreviation">abbr</abbr> officia deserunt mollit <mark>mark</mark> anim id est <code>code</code> laborum. </p>';
echo '<p>';
echo '<span class="text-muted">text-muted</span>&nbsp; &nbsp;';
echo '<span class="text-primary">text-primary</span>&nbsp; &nbsp;';
echo '<span class="text-secondary">text-secondary</span>&nbsp; &nbsp;';
echo '<span class="text-success">text-success</span>&nbsp; &nbsp;';
echo '<span class="text-info">text-info</span>&nbsp; &nbsp;';
echo '<span class="text-warning">text-warning</span>&nbsp; &nbsp;';
echo '<span class="text-danger">text-danger</span>&nbsp; &nbsp;';
echo '<span class="badge badge-secondary">badge</span></a>';
// echo '&nbsp; &nbsp; <span class="label label-default">label label-default</span></a>';
echo '</p>';
echo '<blockquote>Blockquote: Lorem ipsum dolor sit amet, consectetur adipisicing elit.</blockquote>';
echo '<div class="row">';
echo '<div class="col-md-4">';
echo '<h4>Unordered list</h4>';
echo '<ul>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '<li>Lorem Ipsum unordered list item</li>';
echo '</ul>';
echo '</div>'; // /.col-md-4
echo '<div class="col-md-4">';
echo '<h4>Ordered list</h4>';
echo '<ol>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '<li>Lorem Ipsum ordered list item</li>';
echo '</ol>';
echo '</div>'; // /.col-md-4
echo '<div class="col-md-4">';
echo '<h4>Description list</h4>';
echo '<dl>';
echo '<dt>Lorem Ipsum term</dt><dd>Lorem Ipsum description</dd>';
echo '<dt>Lorem Ipsum term</dt><dd>Lorem Ipsum description</dd>';
echo '</dl>';
echo '</div>'; // /.col-md-4
echo '</div>'; // /.row
echo '<div class="row">';
echo '<div class="col-md-6">';
echo '<h3>H3 Lorem Ipsum Heading <small>+ small</small></h3>';
echo '<h4>H4 Lorem Ipsum Heading <small>+ small</small></h4>';
echo '<h5>H5 Lorem Ipsum Heading <small>+ small</small></h5>';
echo '<h6>H6 Lorem Ipsum Heading <small>+ small</small></h6>';
echo '<p class="small">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 '</p>';
echo '<hr/>';
echo '<p>';
echo '<a href="#" class="btn btn-primary">btn-primary</a> &nbsp; ';
echo '<a href="#" class="btn btn-secondary">btn-secondary</a> &nbsp; ';
echo '<a href="#" class="btn btn-success">btn-success</a>';
echo '</p>';
echo '<div></div>';
echo '<p>';
echo '<a href="#" class="btn btn-info">btn-info</a> &nbsp; ';
echo '<a href="#" class="btn btn-warning">btn-warning</a> &nbsp; ';
echo '<a href="#" class="btn btn-danger">btn-danger</a>';
echo '</p>';
echo '<div></div>';
echo '<p>';
echo '<a href="#" class="btn btn-default">btn-default</a> &nbsp; ';
echo '<a href="#" class="btn btn-link">btn-link</a>';
echo '</p>';
echo '<hr/>';
echo '</div>'; // /.col-md-6
echo '<div class="col-md-6">';
echo '<table class="table table-bordered table-striped table-hover" style="table-layout:fixed;">';
echo '<thead>';
echo '<tr>';
echo '<th>Table Heading</th>';
echo '<th colspan="2">';
echo '<span class="text-muted" style="font-weight:normal;">';
echo '&lt;table class=&quot;table table-bordered table-striped table-hover&quot;&gt;';
echo '</span>';
echo '</th>';
echo '</tr>';
echo '</thead>';
echo '<tbody>';
echo '<tr><td>Row&nbsp;1, Cell&nbsp;1</td><td>Row&nbsp;1, Cell&nbsp;2</td><td>Row&nbsp;1, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;2, Cell&nbsp;1</td><td>Row&nbsp;2, Cell&nbsp;2</td><td>Row&nbsp;2, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;3, Cell&nbsp;1</td><td>Row&nbsp;3, Cell&nbsp;2</td><td>Row&nbsp;3, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;4, Cell&nbsp;1</td><td>Row&nbsp;4, Cell&nbsp;2</td><td>Row&nbsp;4, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;5, Cell&nbsp;1</td><td>Row&nbsp;5, Cell&nbsp;2</td><td>Row&nbsp;5, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;6, Cell&nbsp;1</td><td>Row&nbsp;6, Cell&nbsp;2</td><td>Row&nbsp;6, Cell&nbsp;3</td></tr>';
echo '<tr><td>Row&nbsp;7, Cell&nbsp;1</td><td>Row&nbsp;7, Cell&nbsp;2</td><td>Row&nbsp;7, Cell&nbsp;3</td></tr>';
echo '</tbody>';
echo '</table>';
echo '</div>'; // /.col-md-6
echo '</div>'; // /.row
echo '<div class="gpclear"></div>';
$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 '<div id="layout_ident" class="gp_floating_area">';
echo '<div>';
$form_action = ($layout === false) ?
\gp\tool::GetUrl('Admin_Theme_Content') :
\gp\tool::GetUrl('Admin_Theme_Content/Edit/' . $layout);
echo '<form action="' . $form_action . '" method="post">';
echo '<input type="hidden" name="layout" value="" />';
echo '<input type="hidden" name="color" value="" />';
echo '<input type="hidden" name="cmd" value="LayoutLabel" />';
echo '<table>';
echo '<tr><td>';
echo ' <a class="layout_color_id" id="current_color"></a> ';
echo '<input type="text" name="layout_label" value="" maxlength="25" />';
echo '</td></tr>';
echo '<tr><td>';
echo '<div class="colors">';
foreach($colors as $color){
echo '<a class="color" style="background-color:' . $color . '"';
echo ' title="' . $color . '" data-arg="' . $color . '">';
echo '</a>';
}
echo '</div>';
echo '</td></tr>';
echo '<tr><td>';
echo ' <input type="submit" name="" value="Ok" class="gpajax close_color_dialog gpsubmit" />';
echo ' <input type="button" class="close_color_dialog gpcancel"';
echo ' name="" value="' . $langmessage['cancel'] . '" />';
echo '</td></tr>';
echo '</table>';
echo '</form>';
echo '</div>';
echo '</div>';
}
/**
* Display layout label and options
*
*/
public function LayoutDiv($layout, $info){
global $langmessage;
$layout_info = \gp\tool::LayoutInfo($layout, false);
echo '<div class="panelgroup" id="panelgroup_' . md5($layout) . '">';
echo $this->GetLayoutLabel($layout, $info);
echo '<div class="panelgroup2">';
echo '<ul class="submenu">';
echo '<li>';
echo \gp\tool::Link(
'Admin_Theme_Content/Edit/' . rawurlencode($layout),
$langmessage['edit_this_layout'],
'',
['title' => htmlspecialchars($langmessage['Arrange Content']) ]
);
echo '</li>';
//layout options
echo '<li class="expand_child_click">';
echo '<a>' . $langmessage['Layout Options'] . '</a>';
echo '<ul>';
$this->LayoutOptions($layout, $layout_info);
echo '</ul>';
//css options
echo '<li class="expand_child_click">';
echo '<a>CSS</a>';
echo $this->CSSPreferenceForm($layout, $layout_info);
echo '</li>';
$this->LayoutDivAddon($layout_info);
//new versions
if( isset($layout_info['addon_id']) ){
$addon_id = $layout_info['addon_id'];
$version =& $layout_info['version'];
//local or already downloaded
if( isset($this->versions[$addon_id]) &&
version_compare($this->versions[$addon_id]['version'], $version, '>')
){
$version_info = $this->versions[$addon_id];
$label = $langmessage['upgrade'] . ' &nbsp; ' . $version_info['version'];
$source = $version_info['index'] . '/' . $layout_info['theme_color']; //could be different folder
echo '<div class="gp_notice">';
echo \gp\tool::Link(
'Admin_Theme_Content',
$label,
'cmd=UpgradeTheme&source=' . $source,
['data-cmd' => 'creq']
);
echo '</div>';
//remote version
}elseif( gp_remote_themes &&
isset(\gp\admin\Tools::$new_versions[$addon_id]) &&
version_compare(\gp\admin\Tools::$new_versions[$addon_id]['version'], $version, '>')
){
$version_info = \gp\admin\Tools::$new_versions[$addon_id];
$label = $langmessage['new_version'] .
' &nbsp; ' . $version_info['version'] .
' &nbsp; (' . \CMS_READABLE_DOMAIN . ')';
echo '<div class="gp_notice">';
$remote_install_id = $addon_id;
$remote_install_id .= '&name=' . rawurlencode($version_info['name']);
$remote_install_id .= '&layout=' . $layout;
echo \gp\tool::Link(
'Admin_Theme_Content',
$label,
'cmd=RemoteInstall&id=' . $remote_install_id
);
echo '</div>';
}
}
echo '</ul>';
echo '</div>';
echo '</div>';
}
/**
* 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 '<li>';
echo \gp\tool::Link(
'Admin/Addons/'.\gp\admin\Tools::encode64($addon_key),
'<i class="fa fa-plug"></i> ' . $addon_config['name']
);
echo '</li>';
//hooks
$this->AddonPanelGroup($addon_key, false);
}
//version
if( !empty($layout_info['version']) ){
echo '<li><a>' . $langmessage['Your_version'] . ' ' . $layout_info['version'] . '</a></li>';
}elseif( $addon_config && !empty($addon_config['version']) ){
echo '<li><a>' . $langmessage['Your_version'] . ' ' . $addon_config['version'] . '</a></li>';
}
//upgrade
if( $addon_config !== false ){
echo '<li>';
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 '</li>';
}
$options = ob_get_clean();
if( !empty($options) ){
echo '<li class="expand_child_click">';
echo '<a>' . $langmessage['options'] . '</a>';
echo '<ul>';
echo $options;
echo '</ul></li>';
}
}
/**
* Return the layout name and id color
*
*/
public function GetLayoutLabel($layout, $layout_info){
global $config, $langmessage, $config;
ob_start();
echo '<span class="layout_label_' . $layout . ' layout_label">';
echo '<a data-cmd="layout_id" data-arg="' . $layout_info['color'] . '">';
echo '<input type="hidden" name="layout" value="' . htmlspecialchars($layout) . '" /> ';
echo '<input type="hidden" name="layout_label" value="' . $layout_info['label'] . '" /> ';
echo '<span class="layout_color_id" title="' . $layout_info['color'] . '"';
echo ' style="background-color:' . $layout_info['color'] . ';"></span> ';
if( $config['gpLayout'] == $layout ){
echo ' <span class="layout_default"> (' . $langmessage['default'] . ')</span>';
echo '&nbsp;';
}
echo '<span title="' . $layout_info['label'] . '">' . $layout_info['label'] . '</span>';
echo '</a>';
echo '</span>';
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 '<ul id="layout_css_ul_' . $layout . '">';
// name based menu classes
echo '<li>';
echo '<form action="' . \gp\tool::GetUrl('Admin_Theme_Content') . '" method="post">';
echo '<input type="hidden" name="layout" value="' . $layout . '" />';
echo '<input type="hidden" name="cmd" value="CSSPreferences" />';
$checked = '';
$value = 'on';
if( !isset($layout_info['menu_css_ordered']) ){
$checked = ' checked="checked"';
$value = 'off';
}
echo '<input type="hidden" name="menu_css_ordered" value="' . $value . '" />';
echo '<label>';
echo '<input type="checkbox" name="none" value="" class="gpajax"' . $checked . ' /> ';
echo $langmessage['Name Based Menu Classes'];
echo '</label>';
echo '</form>';
echo '</li>';
//ordered menu classes
echo '<li>';
echo '<form action="' . \gp\tool::GetUrl('Admin_Theme_Content') . '" method="post">';
echo '<input type="hidden" name="layout" value="' . $layout . '" />';
echo '<input type="hidden" name="cmd" value="CSSPreferences" />';
$checked = '';
$value = 'on';
if( !isset($layout_info['menu_css_indexed']) ){
$checked = ' checked="checked"';
$value = 'off';
}
echo '<input type="hidden" name="menu_css_indexed" value="' . $value . '" />';
echo '<label>';
echo '<input type="checkbox" name="none" value="" class="gpajax"' . $checked . ' /> ';
echo $langmessage['Ordered Menu Classes'];
echo '</label>';
echo '</form>';
echo '</li>';
echo '</ul>';
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'];
}
}