Add automated theme generator (#14293)

Google Summer of Code 2018 project

Signed-off-by: Saksham Gupta <shucon01@gmail.com>
Signed-off-by: Maurício Meneghini Fauth <mauriciofauth@gmail.com>
This commit is contained in:
Saksham Gupta 2019-01-29 19:58:19 +05:30 committed by Maurício Meneghini Fauth
parent 2fc8bb133a
commit 27b8fbe71c
28 changed files with 7602 additions and 2 deletions

View File

@ -149,6 +149,13 @@ $cfg['SaveDir'] = '';
*/
//$cfg['SendErrorReports'] = 'always';
/**
* Enabling or disabling Theme Generator
*
* default = 'false'
*/
//$cfg['ThemeGenerator'] = 'false';
/**
* You can find more configuration options in the documentation
* in the doc/ folder or at <https://docs.phpmyadmin.net/>.

View File

@ -217,8 +217,8 @@ Basic settings
Setting this to ``true`` allows phpMyAdmin to be included inside a frame,
and is a potential security hole allowing cross-frame scripting attacks or
clickjacking. Setting this to 'sameorigin' prevents phpMyAdmin to be
included from another document in a frame, unless that document belongs
clickjacking. Setting this to 'sameorigin' prevents phpMyAdmin to be
included from another document in a frame, unless that document belongs
to the same domain.
Server connection settings
@ -3265,6 +3265,13 @@ Theme manager settings
Whether to allow different theme for each server.
.. config:option:: $cfg['ThemeGenerator']
:type: boolean
:default: false
Whether to enable theme generator.
.. config:option:: $cfg['FontSize']
:type: string

43
doc/theme_generator.rst Normal file
View File

@ -0,0 +1,43 @@
Create Own Custom Themes
========================
You can create your own themes using Theme Generator tool present on page index.php.
Choose a Base Colour using the colour picker tool.
Colour schemes
--------------
The colour schemes are:
* Triadic
* Complementary
* Adjacent
* Monochrome
You can choose any one of the four schemes using the dropdown menu.
Each element's colour can be customised by clicking on a particular colour box.
Upon hovering the colour box it would display the element the colour corresponds to.
On clicking Go button the program would create the necessary theme files.
Now you can choose the theme you created from the Theme drop-down on page index.php.
Automatic text colours for better visibility
++++++++++++++++++++++++++++++++++++++++++++
A checkbox can be found stating Automatically set text colours for best visibility.
On using this option the text colour would be chosen for best visibility.
You would not be able to change the text colours manually, when using this option.
Preview panels
++++++++++++++
On clicking Preview button the view would change to how the theme would look after
being saved. This is a temporary view and would not generate any files, and upon going on any
other page the view would return back to the original view. For better visualisation,
some elements such as tables and group would popup.
Saving the theme
++++++++++++++++
To save the theme, you need to specify a theme name. All other parameters are optional.
Note that if another theme already exists, it would be overwritten to save the new theme.
After the theme saved you can change the theme from the index.php page.

View File

@ -13,4 +13,5 @@ User Guide
charts
import_export
themes
theme_generator
other

View File

@ -293,6 +293,19 @@ if ($GLOBALS['cfg']['ThemeManager']) {
echo Util::getImage('s_theme') , " "
, ThemeManager::getInstance()->getHtmlSelectBox();
echo '</li>';
if ($GLOBALS['cfg']['ThemeGenerator']) {
Core::printListItem(
Util::getImage('s_theme') . "&nbsp;" . __(
'Theme Generator'
),
'li_theme_generator',
'theme_generator.php' . $common_url_query,
null,
null,
null,
"no_bullets"
);
}
}
echo '</ul>';

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,103 @@
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Used for generating previews
*/
AJAX.registerTeardown('theme_generator/preview.js',function () {
document.getElementById('pma_navigation').style.background = '';
document.getElementById('serverinfo').style.background = '';
document.getElementById('lock_page_icon').style.background = '';
document.getElementById('page_settings_icon').style.background = '';
document.getElementById('goto_pagetop').style.background = '';
document.getElementsByTagName('body')[0].style.background = '';
document.getElementsByTagName('body')[0].style.color = '';
$(document).on(
'mouseover',
'#pma_navigation_tree.highlight li:not(.fast_filter)',
function () {
if ($('li:visible', this).length === 0) {
$(this).css('background-color','');
}
}
);
var head = document.getElementsByTagName('head')[0];
head.removeChild(head.lastChild);
});
$(document).on('click', '#preview' ,function () {
var id = document.getElementById('theme').options.selectedIndex;
tablePreview(id);
navigationPreview(id);
bodyPreview(id);
headerPreview(id);
groupPreview(id);
});
var tablePreview = function (id) {
var tableRow = document.querySelectorAll('[title="Table Row Background"]')[id].style.backgroundColor;
var tableAlternateRow = document.querySelectorAll('[title="Table Row Alternate Background"]')[id].style.backgroundColor;
var hoverRow = document.querySelectorAll('[title="Table Row Hover and Selected"]')[id].style.backgroundColor;
var tableHeader = document.querySelectorAll('[title="Table Header and Footer Background"]')[id].style.backgroundColor;
$('.row_preview').css('background',tableRow);
$('.row_alternate_preview').css('background',tableAlternateRow);
document.getElementById('table_preview').style.display = 'block';
var head = document.getElementsByTagName('head')[0];
var style = document.createElement('style');
var cssText = 'tr.row_preview:not(.nopointer):hover, tr.row_alternate_preview:not(.nopointer):hover , tr.marked:not(.nomarker) td { background:' + hoverRow + '!important }';
var hoverDeclarations = document.createTextNode(cssText);
var cssText = 'th { background: ' + tableHeader + ' !important}';
var headerDeclarations = document.createTextNode(cssText);
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = hoverDeclarations.nodeValue;
style.styleSheet.cssText += headerDeclarations.nodeValue;
} else {
style.appendChild(hoverDeclarations);
style.appendChild(headerDeclarations);
}
head.appendChild(style);
};
var navigationPreview = function (id) {
var navColor = document.querySelectorAll('[title="Navigation Panel"]')[id].style.backgroundColor;
var navHover = document.querySelectorAll('[title="Navigation Hover"]')[id].style.backgroundColor;
var backgroundColor = document.querySelectorAll('[title="Background Colour"]')[id].style.backgroundColor;
document.getElementById('pma_navigation').style.background = 'linear-gradient(to right, ' + navColor + ',' + backgroundColor + ')';
$(document).on(
'mouseover',
'#pma_navigation_tree.highlight li:not(.fast_filter)',
function () {
if ($('li:visible', this).length === 0) {
$(this).css('background-color',navHover);
}
}
);
$(document).on(
'mouseout',
'#pma_navigation_tree.highlight li:not(.fast_filter)',
function () {
$(this).css('background-color','transparent');
}
);
};
var bodyPreview = function (id) {
var backgroundColor = document.querySelectorAll('[title="Background Colour"]')[id].style.backgroundColor;
var textColor = document.querySelectorAll('[title="Text Colour"]')[id].style.backgroundColor;
document.getElementsByTagName('body')[0].style.background = backgroundColor;
document.getElementsByTagName('body')[0].style.color = textColor;
};
var headerPreview = function (id) {
var headerColor = document.querySelectorAll('[title="Header"]')[id].style.backgroundColor;
document.getElementById('serverinfo').style.background = headerColor;
document.getElementById('lock_page_icon').style.background = headerColor;
document.getElementById('page_settings_icon').style.background = headerColor;
document.getElementById('goto_pagetop').style.background = headerColor;
};
var groupPreview = function (id) {
var groupColor = document.querySelectorAll('[title="Group Background"]')[id].style.backgroundColor;
document.getElementById('group_preview').style.display = 'block';
document.getElementById('group_preview').style.background = groupColor;
};

View File

@ -83,6 +83,7 @@ class Theme
'jqplot',
'resizable-menu',
'icons',
'theme_generator',
];
/**

View File

@ -0,0 +1,170 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Holds the PhpMyAdmin\ThemeGenerator class
*
* @package PhpMyAdmin
*/
declare(strict_types=1);
namespace PhpMyAdmin;
use PhpMyAdmin\Message;
use PhpMyAdmin\Sanitize;
use PhpMyAdmin\Template;
use PhpMyAdmin\ThemeGenerator\Common;
use PhpMyAdmin\ThemeGenerator\Layout;
use PhpMyAdmin\ThemeGenerator\Navigation;
/**
* Set of functions for Automated Theme Generator in phpMyAdmin
*
* @package PhpMyAdmin
*/
class ThemeGenerator
{
protected $template;
/**
* Constructor
*/
public function __construct()
{
$this->template = new Template();
}
/**
* Colour Picker HTML file
*
* @return string HTML for the color picker tool
*/
public function colorPicker()
{
$output = $this->template->render('theme_generator/color_picker');
return $output;
}
/**
* File creation form
*
* @return string HTML for the form submission
*/
public function form()
{
$output = $this->template->render('theme_generator/form');
return $output;
}
/**
* Preview panel for Table
*
* @return string HTML for the preview panels
*/
public function tablePreview()
{
$output = $this->template->render('theme_generator/table_preview');
return $output;
}
/**
* Preview panel for Groups
*
* @return string HTML for the preview panels
*/
public function groupPreview()
{
$output = $this->template->render('theme_generator/group_preview');
return $output;
}
/**
* Creates file structure
*
* @param array $post POST form data
*
* @return array $out generated file data
*/
public function createFileStructure(array $post)
{
$out = array();
$nav = new Navigation();
$layout = new Layout();
$common = new Common();
$post['theme_name'] = Sanitize::sanitizeFilename($post['theme_name'], true);
$name = $post['theme_name'];
if (!is_dir("themes/" . $name)) {
@mkdir("themes/" . $name);
@mkdir("themes/" . $name . "/css");
}
if (is_dir("themes/" . $name)) {
$out['json'] = $this->createJsonFile($post);
$common->createCommonFile($name);
$out['layout'] = $layout->createLayoutFile($post);
$nav->createNavigationFile($name);
}
return $out;
}
/**
* Checks whether the theme directory is writable
*
* @return null
*/
public function testWritableThemeDirectory()
{
clearstatcache();
if (! is_writable('themes')) {
trigger_error(__("The 'themes' directory is not writable by the webserver process. You must change permissions for the theme generator to be able to write the generated theme."), E_USER_WARNING);
}
return;
}
/**
* Creates theme.json
*
* @param array $post POST data
*
* @return string $txt JSON file data
*/
public function createJsonFile($post)
{
$name = $post['theme_name'];
$file = fopen("themes/" . $name . "/theme.json", "w");
$txt = '{';
$txt .= '"name": "' . $name . '",';
if ($post['version'] != "") {
$txt .= '"version": "' . $post['version'] . '",';
} else {
$txt .= '"version": "5.0",';
}
if ($post['description'] != "") {
$txt .= '"description": "' . $post['description'] . '",';
} else {
$txt .= '"description": "Theme Generated by Automated Theme Generator",';
}
if ($post['author'] != "") {
$txt .= '"author": "' . $post['author'] . '",';
} else {
$txt .= '"author": "",';
}
if ($post['url'] != "") {
$txt .= '"url": "' . $post['url'] . '",';
} else {
$txt .= '"url": "https://www.phpmyadmin.net/",';
}
$version = str_split(PMA_VERSION);
$trimmed_version = array_slice($version, 0, 3);
$txt .= '"supports": ["' . implode($trimmed_version) . '"]';
$txt .= '}';
// Check if the file is writable as this condition would only occur if files are overwritten.
if ($file) {
fwrite($file, $txt);
fclose($file);
return $txt;
} else {
trigger_error(__("The theme.json file is not writable by the webserver process. You must change permissions for the theme generator to be able to write the generated theme."), E_USER_ERROR);
return;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Creates Layout.inc.php file
*
* @package PhpMyAdmin
*/
declare(strict_types=1);
namespace PhpMyAdmin\ThemeGenerator;
/**
* Function to create Layout.inc.php in phpMyAdmin
*
* @package PhpMyAdmin
*/
class Layout
{
/**
* Creates layout.inc.php
*
* @param array $post POST form data
*
* @return string $txt layout.inc.php file data
*/
public function createLayoutFile(array $post)
{
$name = $post['theme_name'];
$file = fopen("themes/" . $name . "/layout.inc.php", "w");
$txt = "<?php\n";
/**
* configures general layout
* for detailed layout configuration please refer to the css files
*/
$txt .= 'declare(strict_types=1);';
/**
* navi frame
*/
// navi frame width
$txt .= '$GLOBALS[\'cfg\'][\'NaviWidth\'] = 240;';
// foreground (text) color for the navi frame
$txt .= '$GLOBALS[\'cfg\'][\'NaviColor\'] = \'#000\';';
// background for the navi frame
$txt .= '$GLOBALS[\'cfg\'][\'NaviBackground\'] = \'' . $post['Navigation_Panel'] . '\';';
// foreground (text) color of the pointer in navi frame
$txt .= '$GLOBALS[\'cfg\'][\'NaviPointerColor\'] = \'#000\';';
// background of the pointer in navi frame
$txt .= '$GLOBALS[\'cfg\'][\'NaviPointerBackground\'] = \'' . $post['Navigation_Hover'] . '\';';
/**
* main frame
*/
// foreground (text) color for the main frame
$txt .= '$GLOBALS[\'cfg\'][\'MainColor\'] = \'' . $post['Text_Colour'] . '\';';
// background for the main frame
$txt .= '$GLOBALS[\'cfg\'][\'MainBackground\'] = \'' . $post['Background_Colour'] . '\';';
// foreground (text) color of the pointer in browse mode
$txt .= '$GLOBALS[\'cfg\'][\'BrowsePointerColor\'] = \'#000\';';
// background of the pointer in browse mode
$txt .= '$GLOBALS[\'cfg\'][\'BrowsePointerBackground\'] = \'#cfc\';';
// foreground (text) color of the marker (visually marks row by clicking on it)
// in browse mode
$txt .= '$GLOBALS[\'cfg\'][\'BrowseMarkerColor\'] = \'#000\';';
// background of the marker (visually marks row by clicking on it) in browse mode
$txt .= '$GLOBALS[\'cfg\'][\'BrowseMarkerBackground\'] = \'#fc9\';';
//server info header
$txt .= '$GLOBALS[\'cfg\'][\'Header\'] = \'' . $post['Header'] . '\';';
/**
* fonts
*/
/**
* the font family as a valid css font family value,
* if not set the browser default will be used
* (depending on browser, DTD and system settings)
*/
$txt .= '$GLOBALS[\'cfg\'][\'FontFamily\'] = \'' . $post['font'] . '\';';
/**
* fixed width font family, used in textarea
*/
$txt .= '$GLOBALS[\'cfg\'][\'FontFamilyFixed\'] = \'monospace\';';
/**
* tables
*/
// border
$txt .= '$GLOBALS[\'cfg\'][\'Border\'] = 0;';
// table header and footer color
// Dialogue Footer color
$txt .= '$GLOBALS[\'cfg\'][\'ThBackground\'] = \'' . $post['Table_Header_and_Footer_Background'] . '\';';
// table header and footer background
//text color footer and dialogue
$txt .= '$GLOBALS[\'cfg\'][\'ThColor\'] = \'' . $post['Table_Header_and_Footer_Text_Colour'] . '\';';
// table data row background
// Dialougue result background
$txt .= '$GLOBALS[\'cfg\'][\'BgOne\'] = \'' . $post['Table_Row_Background'] . '\';';
// table data row background, alternate
$txt .= '$GLOBALS[\'cfg\'][\'BgTwo\'] = \'' . $post['Table_Row_Alternate_Background'] . '\';';
//table hover and selected
$txt .= '$GLOBALS[\'cfg\'][\'BgThree\'] = \'' . $post['Table_Row_Hover_and_Selected'] . '\';';
// Hyperlink Text
$txt .= '$GLOBALS[\'cfg\'][\'Hyperlink\'] = \'' . $post['Hyperlink_Text'] . '\';';
// Group Background
$txt .= '$GLOBALS[\'cfg\'][\'GroupBg\'] = \'' . $post['Group_Background'] . '\';';
// Check if the file is writable as this condition would only occur if files are overwritten.
if ($file) {
fwrite($file, $txt);
fclose($file);
return $txt;
} else {
trigger_error("The layout.inc.php file is not writable by the webserver process. You must change permissions for the theme generator to be able to write the generated theme.", E_USER_ERROR);
return;
}
}
}

View File

@ -0,0 +1,432 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Creates Navigation.css.php file
*
* @package PhpMyAdmin
*/
declare(strict_types=1);
namespace PhpMyAdmin\ThemeGenerator;
/**
* Function to create Navigation.css.php in phpMyAdmin
*
* @package PhpMyAdmin
*/
class Navigation
{
/**
* Creates navigation.css.php
*
* @param string $name name of new theme
*
* @return null
*/
public function createNavigationFile($name)
{
$file = fopen("themes/" . $name . "/css/navigation.css.php", "w");
$txt = "<?php\n";
$txt .= 'declare(strict_types=1);';
$txt .= 'if (! defined(\'PHPMYADMIN\') && ! defined(\'TESTSUITE\')) {';
$txt .= ' exit();';
$txt .= '}';
$txt .= "?>\n";
$txt .= '#pma_navigation {';
$txt .= ' width: <?php echo $GLOBALS[\'cfg\'][\'NaviWidth\']; ?>px;';
$txt .= ' position: fixed;';
$txt .= ' top: 0;';
$txt .= ' <?php echo $left; ?>: 0;';
$txt .= ' height: 100vh;';
$txt .= ' background: linear-gradient(to right, <?php echo $GLOBALS[\'cfg\'][\'NaviBackground\']; ?> , <?php echo $GLOBALS[\'cfg\'][\'MainBackground\']; ?>);';
$txt .= ' color: <?php echo $GLOBALS[\'cfg\'][\'NaviColor\']; ?>;';
$txt .= ' z-index: 800;';
$txt .= '}';
$txt .= '#pma_navigation_header {';
$txt .= ' overflow: hidden;';
$txt .= '}';
$txt .= '#pma_navigation_content {';
$txt .= ' width: 100%;';
$txt .= ' height: 100%;';
$txt .= ' position: absolute;';
$txt .= ' top: 0;';
$txt .= ' <?php echo $left; ?>: 0;';
$txt .= ' z-index: 0;';
$txt .= '}';
$txt .= '#pma_navigation ul {';
$txt .= ' margin: 0;';
$txt .= '}';
$txt .= '#pma_navigation form {';
$txt .= ' margin: 0;';
$txt .= ' padding: 0;';
$txt .= ' display: inline;';
$txt .= '}';
$txt .= '#pma_navigation select#select_server,';
$txt .= '#pma_navigation select#lightm_db {';
$txt .= ' width: 100%;';
$txt .= '}';
$txt .= '#pma_navigation div.pageselector {';
$txt .= ' text-align: center;';
$txt .= ' margin: 0;';
$txt .= ' margin-<?php echo $left; ?>: 0.75em;';
$txt .= ' border-<?php echo $left; ?>: 1px solid #666;';
$txt .= '}';
$txt .= '#pma_navigation div#pmalogo {';
$txt .= ' <?php //better echo $GLOBALS[\'cfg\'][\'logoBGC\']; ?>';
$txt .= '}';
$txt .= '#pma_navigation #pmalogo,';
$txt .= '#pma_navigation #serverChoice,';
$txt .= '#pma_navigation #navipanellinks,';
$txt .= '#pma_navigation #recentTableList,';
$txt .= '#pma_navigation #favoriteTableList,';
$txt .= '#pma_navigation #databaseList,';
$txt .= '#pma_navigation div.pageselector.dbselector {';
$txt .= ' text-align: center;';
$txt .= ' padding: 5px 10px 0;';
$txt .= ' border: 0;';
$txt .= '}';
$txt .= '#pma_navigation #recentTable,';
$txt .= '#pma_navigation #favoriteTable {';
$txt .= ' width: 200px;';
$txt .= '}';
$txt .= '#pma_navigation #favoriteTableList select,';
$txt .= '#pma_navigation #serverChoice select';
$txt .= ' {';
$txt .= ' width: 80%;';
$txt .= '}';
$txt .= '#pma_navigation_content > img.throbber {';
$txt .= ' display: none;';
$txt .= ' margin: .3em auto 0;';
$txt .= '}';
$txt .= '#pma_navigation_tree {';
$txt .= ' margin: 0;';
$txt .= ' margin-<?php echo $left; ?>: 5px;';
$txt .= ' overflow: hidden;';
$txt .= ' color: #444;';
$txt .= ' height: 74%;';
$txt .= ' position: relative;';
$txt .= '}';
$txt .= '#pma_navigation_select_database {';
$txt .= ' text-align: left;';
$txt .= ' padding: 0 0 0;';
$txt .= ' border: 0;';
$txt .= ' margin: 0;';
$txt .= '}';
$txt .= '#pma_navigation_db_select {';
$txt .= ' margin-top: 0.5em;';
$txt .= ' margin-<?php echo $left; ?>: 0.75em;';
$txt .= '}';
$txt .= '#pma_navigation_db_select select {';
$txt .= ' background: url("./themes/pmahomme/img/select_bg.png") repeat scroll 0 0;';
$txt .= ' -webkit-border-radius: 2px;';
$txt .= ' border-radius: 2px;';
$txt .= ' border: 1px solid #bbb;';
$txt .= ' border-top: 1px solid #bbb;';
$txt .= ' color: #333;';
$txt .= ' padding: 4px 6px;';
$txt .= ' margin: 0 0 0;';
$txt .= ' width: 92%;';
$txt .= ' font-size: 1.11em;';
$txt .= '}';
$txt .= '#pma_navigation_tree_content {';
$txt .= ' width: 100%;';
$txt .= ' overflow: hidden;';
$txt .= ' overflow-y: auto;';
$txt .= ' position: absolute;';
$txt .= ' height: 100%;';
$txt .= '}';
$txt .= '#pma_navigation_tree_content a.hover_show_full {';
$txt .= ' position: relative;';
$txt .= ' z-index: 100;';
$txt .= ' vertical-align: sub;';
$txt .= '}';
$txt .= '#pma_navigation_tree a {';
$txt .= ' color: <?php echo $GLOBALS[\'cfg\'][\'NaviColor\']; ?>;';
$txt .= '}';
$txt .= '#pma_navigation_tree a:hover {';
$txt .= ' text-decoration: underline;';
$txt .= '}';
$txt .= '#pma_navigation_tree li.activePointer {';
$txt .= ' color: <?php echo $GLOBALS[\'cfg\'][\'NaviPointerColor\']; ?>;';
$txt .= ' background-color: <?php echo $GLOBALS[\'cfg\'][\'NaviPointerBackground\']; ?>;';
$txt .= '}';
$txt .= '#pma_navigation_tree li.selected {';
$txt .= ' color: <?php echo $GLOBALS[\'cfg\'][\'NaviPointerColor\']; ?>;';
$txt .= ' background-color: <?php echo $GLOBALS[\'cfg\'][\'NaviPointerBackground\']; ?>;';
$txt .= '}';
$txt .= '#pma_navigation_tree li .dbItemControls {';
$txt .= ' padding-left: 4px;';
$txt .= '}';
$txt .= '#pma_navigation_tree li .navItemControls {';
$txt .= ' display: none;';
$txt .= ' padding-left: 4px;';
$txt .= '}';
$txt .= '#pma_navigation_tree li.activePointer .navItemControls {';
$txt .= ' display: inline;';
$txt .= ' opacity: 0.5;';
$txt .= '}';
$txt .= '#pma_navigation_tree li.activePointer .navItemControls:hover {';
$txt .= ' display: inline;';
$txt .= ' opacity: 1.0;';
$txt .= '}';
$txt .= '#pma_navigation_tree ul {';
$txt .= ' clear: both;';
$txt .= ' padding: 0;';
$txt .= ' list-style-type: none;';
$txt .= ' margin: 0;';
$txt .= '}';
$txt .= '#pma_navigation_tree ul ul {';
$txt .= ' position: relative;';
$txt .= '}';
$txt .= '#pma_navigation_tree li,';
$txt .= '#pma_navigation_tree li.fast_filter {';
$txt .= ' white-space: nowrap;';
$txt .= ' clear: both;';
$txt .= ' min-height: 16px;';
$txt .= '}';
$txt .= '#pma_navigation_tree img {';
$txt .= ' margin: 0;';
$txt .= '}';
$txt .= '#pma_navigation_tree i {';
$txt .= ' display: block;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block {';
$txt .= ' position: relative;';
$txt .= ' width: 1.5em;';
$txt .= ' height: 1.5em;';
$txt .= ' min-width: 16px;';
$txt .= ' min-height: 16px;';
$txt .= ' float: <?php echo $left; ?>;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block.double {';
$txt .= ' width: 2.5em;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block i,';
$txt .= '#pma_navigation_tree div.block b {';
$txt .= ' width: 1.5em;';
$txt .= ' height: 1.7em;';
$txt .= ' min-width: 16px;';
$txt .= ' min-height: 8px;';
$txt .= ' position: absolute;';
$txt .= ' bottom: 0.7em;';
$txt .= ' <?php echo $left; ?>: 0.75em;';
$txt .= ' z-index: 0;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block i { /* Top and right segments for the tree element connections */';
$txt .= ' display: block;';
$txt .= ' border-<?php echo $left; ?>: 1px solid #666;';
$txt .= ' border-bottom: 1px solid #666;';
$txt .= ' position: relative;';
$txt .= ' z-index: 0;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block i.first { /* Removes top segment */';
$txt .= ' border-<?php echo $left; ?>: 0;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block b { /* Bottom segment for the tree element connections */';
$txt .= ' display: block;';
$txt .= ' height: 0.75em;';
$txt .= ' bottom: 0;';
$txt .= ' <?php echo $left; ?>: 0.75em;';
$txt .= ' border-<?php echo $left; ?>: 1px solid #666;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block a,';
$txt .= '#pma_navigation_tree div.block u {';
$txt .= ' position: absolute;';
$txt .= ' <?php echo $left; ?>: 50%;';
$txt .= ' top: 50%;';
$txt .= ' z-index: 10;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block a + a {';
$txt .= ' <?php echo $left; ?>: 100%;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block.double a,';
$txt .= '#pma_navigation_tree div.block.double u {';
$txt .= ' <?php echo $left; ?>: 33%;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block.double a + a {';
$txt .= ' <?php echo $left; ?>: 85%;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.block img {';
$txt .= ' position: relative;';
$txt .= ' top: -0.6em;';
$txt .= ' <?php echo $left; ?>: 0;';
$txt .= ' margin-<?php echo $left; ?>: -7px;';
$txt .= '}';
$txt .= '#pma_navigation_tree div.throbber img {';
$txt .= ' top: 2px;';
$txt .= ' <?php echo $left; ?>: 2px;';
$txt .= '}';
$txt .= '#pma_navigation_tree li.last > ul {';
$txt .= ' background: none;';
$txt .= '}';
$txt .= '#pma_navigation_tree li > a, #pma_navigation_tree li > i {';
$txt .= ' line-height: 1.5em;';
$txt .= ' height: 1.5em;';
$txt .= ' padding-<?php echo $left; ?>: 0.3em;';
$txt .= '}';
$txt .= '#pma_navigation_tree .list_container {';
$txt .= ' border-<?php echo $left; ?>: 1px solid #666;';
$txt .= ' margin-<?php echo $left; ?>: 0.75em;';
$txt .= ' padding-<?php echo $left; ?>: 0.75em;';
$txt .= '}';
$txt .= '#pma_navigation_tree .last > .list_container {';
$txt .= ' border-<?php echo $left; ?>: 0 solid #666;';
$txt .= '}';
$txt .= '';
$txt .= 'li.fast_filter {';
$txt .= ' padding-<?php echo $left; ?>: 0.75em;';
$txt .= ' margin-<?php echo $left; ?>: 0.75em;';
$txt .= ' padding-<?php echo $right; ?>: 35px;';
$txt .= ' border-<?php echo $left; ?>: 1px solid #666;';
$txt .= ' list-style: none;';
$txt .= '}';
$txt .= 'li.fast_filter input {';
$txt .= ' margin: 3px 0 0 0;';
$txt .= ' font-size: 0.7em;';
$txt .= ' padding-top: 2px;';
$txt .= ' padding-bottom: 2px;';
$txt .= ' padding-<?php echo $left; ?>: 4px;';
$txt .= ' padding-<?php echo $right; ?>: 1.7em;';
$txt .= ' width: 100%;';
$txt .= '}';
$txt .= 'li.fast_filter span {';
$txt .= ' position: relative;';
$txt .= ' <?php echo $right; ?>: 1.5em;';
$txt .= ' padding: 0.2em;';
$txt .= ' cursor: pointer;';
$txt .= ' font-weight: bold;';
$txt .= ' color: #800;';
$txt .= ' font-size: 0.7em;';
$txt .= '}';
/* IE10+ has its own reset X */
$txt .= 'html.ie li.fast_filter span {';
$txt .= ' display: none;';
$txt .= '}';
$txt .= 'html.ie.ie9 li.fast_filter span,';
$txt .= 'html.ie.ie8 li.fast_filter span {';
$txt .= ' display: auto;';
$txt .= '}';
$txt .= 'html.ie li.fast_filter input {';
$txt .= ' padding-<?php echo $right; ?>: .2em;';
$txt .= '}';
$txt .= 'html.ie.ie9 li.fast_filter input,';
$txt .= 'html.ie.ie8 li.fast_filter input {';
$txt .= ' padding-<?php echo $right; ?>: 1.7em;';
$txt .= '}';
$txt .= 'li.fast_filter.db_fast_filter {';
$txt .= ' border: 0;';
$txt .= ' margin-left: 0;';
$txt .= ' margin-right: 10px;';
$txt .= '}';
$txt .= '#navigation_controls_outer {';
$txt .= ' min-height: 21px !important;';
$txt .= '}';
$txt .= '#navigation_controls_outer.activePointer {';
$txt .= ' background-color: transparent !important;';
$txt .= '}';
$txt .= '#navigation_controls {';
$txt .= ' float: right;';
$txt .= ' padding-right: 23px;';
$txt .= '}';
$txt .= '#pma_navigation_resizer {';
$txt .= ' width: 3px;';
$txt .= ' height: 100%;';
$txt .= ' background-color: #aaa;';
$txt .= ' cursor: col-resize;';
$txt .= ' position: fixed;';
$txt .= ' top: 0;';
$txt .= ' <?php echo $left; ?>: 240px;';
$txt .= ' z-index: 801;';
$txt .= '}';
$txt .= '#pma_navigation_collapser {';
$txt .= ' width: 20px;';
$txt .= ' height: 22px;';
$txt .= ' line-height: 22px;';
$txt .= ' background: #eee;';
$txt .= ' color: #555;';
$txt .= ' font-weight: bold;';
$txt .= ' position: fixed;';
$txt .= ' top: 0;';
$txt .= ' <?php echo $left; ?>: <?php echo $GLOBALS[\'cfg\'][\'NaviWidth\']; ?>px;';
$txt .= ' text-align: center;';
$txt .= ' cursor: pointer;';
$txt .= ' z-index: 800;';
$txt .= ' text-shadow: 0 1px 0 #fff;';
$txt .= ' filter: dropshadow(color=#fff, offx=0, offy=1);';
$txt .= ' border: 1px solid #888;';
$txt .= '}';
$txt .= '.pma_quick_warp {';
$txt .= ' margin-top: 5px;';
$txt .= ' margin-<?php echo $left; ?>: 2px;';
$txt .= ' position: relative;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list {';
$txt .= ' float: <?php echo $left; ?>;';
$txt .= ' margin-<?php echo $left; ?>: 3px;';
$txt .= ' padding: 2px 0;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_button {';
$txt .= ' padding: 0 .3em;';
$txt .= ' border: 1px solid #ddd;';
$txt .= ' border-radius: .3em;';
$txt .= ' background: #f2f2f2;';
$txt .= ' cursor: pointer;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list:hover .drop_button {';
$txt .= ' background: #fff;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list ul {';
$txt .= ' position: absolute;';
$txt .= ' margin: 0;';
$txt .= ' padding: 0;';
$txt .= ' overflow: hidden;';
$txt .= ' overflow-y: auto;';
$txt .= ' list-style: none;';
$txt .= ' background: #fff;';
$txt .= ' border: 1px solid #ddd;';
$txt .= ' border-radius: .3em;';
$txt .= ' border-top-<?php echo $right; ?>-radius: 0;';
$txt .= ' border-bottom-<?php echo $right; ?>-radius: 0;';
$txt .= ' box-shadow: 0 0 5px #ccc;';
$txt .= ' top: 100%;';
$txt .= ' <?php echo $left; ?>: 3px;';
$txt .= ' <?php echo $right; ?>: 0;';
$txt .= ' display: none;';
$txt .= ' z-index: 802;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list:hover ul {';
$txt .= ' display: block;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list li {';
$txt .= ' white-space: nowrap;';
$txt .= ' padding: 0;';
$txt .= ' border-radius: 0;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list li img {';
$txt .= ' vertical-align: sub;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list li:hover {';
$txt .= ' background: #f2f2f2;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list a {';
$txt .= ' display: block;';
$txt .= ' padding: .2em .3em;';
$txt .= '}';
$txt .= '.pma_quick_warp .drop_list a.favorite_table_anchor {';
$txt .= ' clear: left;';
$txt .= ' float: left;';
$txt .= ' padding: .1em .3em 0;';
$txt .= '}';
// Check if the file is writable as this condition would only occur if files are overwritten.
if ($file) {
fwrite($file, $txt);
fclose($file);
} else {
trigger_error("The navigation.css.php file is not writable by the webserver process. You must change permissions for the theme generator to be able to write the generated theme.", E_USER_ERROR);
}
return null;
}
}

View File

@ -2894,6 +2894,13 @@ $cfg['ThemeDefault'] = 'pmahomme';
*/
$cfg['ThemePerServer'] = false;
/**
* Enabling theme generator
*
* @global boolean $cfg['ThemeGenerator']
*/
$cfg['ThemeGenerator'] = false;
/*******************************************************************************
*
*/

View File

@ -0,0 +1,9 @@
<div id="container">
<div id="palette" class="block">
<div id="color-palette"></div>
</div>
<div id="picker" class="block">
<div class="ui-color-picker" data-topic="picker" data-mode="HSB"></div>
<div id="picker-samples" sample-id="master"></div>
</div>
</div>

View File

@ -0,0 +1,40 @@
<form action="theme_generator.php" method="post" id="save">
<select name="type" id="theme">
<option value="0">{% trans 'Triadic' %}</option>
<option value="1">{% trans 'Complementary' %}</option>
<option value="2">{% trans 'Adjacent' %}</option>
<option value="3">{% trans 'Monochrome' %}</option>
</select>
<br>
&nbsp; Font :<br>
<select name="font" id="font">
<option value="sans-serif">sans-serif</option>
<option value="Georgia">Georgia</option>
<option value="Palatino Linotype">Palatino Linotype</option>
<option value="Book Antiqua">Book Antiqua</option>
<option value="Arial">Arial</option>
<option value="Helvetica">Helvetica</option>
<option value="Arial Black">Arial Black</option>
<option value="Courier New">Courier New</option>
<option value="Verdana">Verdana</option>
</select>
<br>
&nbsp; {% trans 'Theme Name' %} :<br>
<input type="text" name="theme_name" required></input> <br>
<br>
&nbsp; {% trans 'Version' %} :<br>
<input type="text" name="version"></input> <br>
<br>
&nbsp; {% trans 'Description' %} :<br>
<input type="text" name="description"></input> <br>
<br>
&nbsp; {% trans 'Author' %} :<br>
<input type="text" name="author"></input> <br>
<br>
&nbsp; {% trans 'URL' %} :<br>
<input type="text" name="url"></input> <br>
<input type="checkbox" name="text_contrast">{% trans 'Automatically set text colours for best visibility' %}<br>
<br><br>
<input type="button" value="{% trans 'Preview' %}" id="preview">
<input type="submit" value="{% trans 'Save theme' %}">
</form>

View File

@ -0,0 +1,20 @@
<div class="group" id="group_preview">
<h2>Preview Panel</h2>
<ul>
<li id="li_change_password" class="no_bullets">
<a href="#">
<img src="themes/dot.gif" title="" alt="" class="icon ic_s_passwd">&nbsp;Change password
</a>
</li>
<li id="li_select_mysql_collation" class="no_bullets">
<label for="select_collation_connection">
<img src="themes/dot.gif" title="" alt="" class="icon ic_s_asci">&nbsp;Server connection collation
<a href="" target="mysql_doc"><img src="themes/dot.gif" title="Documentation" alt="Documentation" class="icon ic_b_help"></a>:
</label>
<select lang="en" dir="ltr" name="collation_connection" id="select_collation_connection" class="autosubmit">
<option value="">Collation</option>
</select>
</li>
</ul>
</div>

View File

@ -0,0 +1,75 @@
<div id="table_preview">
<div style="position: relative;" class="data">
<div class="cRsz" style="height: 102px;">
<div class="colborder" style="left: 294.716px;"></div>
<div class="colborder" style="left: 369.713px;"></div>
<div class="colborder" style="left: 441.716px;"></div>
<div class="colborder" style="left: 552.716px;"></div>
</div>
<table class="sticky_columns" style="position: fixed; z-index: 99; width: 554px; margin-left: 6.56px; top: 57.5625px; display: none;">
<thead>
<tr>
<th class="column_action print_ignore" colspan="4" style="width: 194.156px;"><span><a href="#" ><img class="fulltext" src="./themes/pmahomme/img/s_fulltext.png" alt="Full texts" title="Full texts"></a></span></th>
<th class="draggable column_heading pointer marker" data-column="Dname" style="width: 87.1562px;"><span><a href="#" class="sortlink">Dname <img src="themes/dot.gif" title="" alt="Ascending" class="icon ic_s_asc soimg"> <img src="themes/dot.gif" title="" alt="Descending" class="icon ic_s_desc soimg hide"> <small>1</small><input type="hidden" ></a></span></th>
</tr>
</thead>
</table>
<table class="table_results ajax pma_table" data-uniqueid="510480552">
<thead>
<tr>
<th class="column_action print_ignore" colspan="4"><span><a href="#" ><img class="fulltext" src="./themes/pmahomme/img/s_fulltext.png" alt="Full texts" title="Full texts"></a></span></th>
<th class="draggable column_heading pointer marker" data-column="Dname" style="cursor: move;"><span><a href="#" class="sortlink">Dname <img src="themes/dot.gif" title="" alt="Ascending" class="icon ic_s_asc soimg" style=""> <img src="themes/dot.gif" title="" alt="Descending" class="icon ic_s_desc soimg hide" style="display: none;"> <small>1</small><input type="hidden" ></a></span></th>
</tr>
</thead>
<tbody>
<tr class="row_preview">
<td class="center print_ignore"><span><input type="checkbox" id="id_rows_to_delete0_left" name="rows_to_delete[0]" class="multi_checkbox checkall" ><input type="hidden" class="condition_array" > </span></td>
<td class="edit_row_anchor center print_ignore"><span class="nowrap"><a href="#" ><span class="nowrap"><img src="themes/dot.gif" title="Edit" alt="Edit" class="icon ic_b_edit">&nbsp;Edit</span></a><input type="hidden" class="where_clause" ></span>
</td>
<td class="center print_ignore"><span class="nowrap"><a href="#" ><span class="nowrap"><img src="themes/dot.gif" title="Copy" alt="Copy" class="icon ic_b_insrow">&nbsp;Copy</span></a><input type="hidden" class="where_clause" ></span>
</td>
<td class="center print_ignore"><a href="#" class="delete_row requireConfirm ajax"><span class="nowrap"><img src="themes/dot.gif" title="Delete" alt="Delete" class="icon ic_b_drop">&nbsp;Delete</span></a>
</td>
<td data-decimals="0" data-type="string" data-originallength="14" class="data grid_edit click2 not_null text"><span>Row 1</span></td>
</tr>
<tr class="row_alternate_preview">
<td class="center print_ignore"><span><input type="checkbox" id="id_rows_to_delete1_left" name="rows_to_delete[1]" class="multi_checkbox checkall" ><input type="hidden" class="condition_array" > </span></td>
<td class="edit_row_anchor center print_ignore"><span class="nowrap"><a href="#" ><span class="nowrap"><img src="themes/dot.gif" title="Edit" alt="Edit" class="icon ic_b_edit">&nbsp;Edit</span></a><input type="hidden" class="where_clause" ></span>
</td>
<td class="center print_ignore"><span class="nowrap"><a href="#" ><span class="nowrap"><img src="themes/dot.gif" title="Copy" alt="Copy" class="icon ic_b_insrow">&nbsp;Copy</span></a><input type="hidden" class="where_clause" ></span>
</td>
<td class="center print_ignore"><a href="#" class="delete_row requireConfirm ajax"><span class="nowrap"><img src="themes/dot.gif" title="Delete" alt="Delete" class="icon ic_b_drop">&nbsp;Delete</span></a>
</td>
<td data-decimals="0" data-type="string" data-originallength="11" class="data grid_edit click2 not_null text"><span>Row 2</span></td>
</tr>
<tr class="row_preview">
<td class="center print_ignore"><span><input type="checkbox" id="id_rows_to_delete2_left" name="rows_to_delete[2]" class="multi_checkbox checkall" ><input type="hidden" class="condition_array" > </span></td>
<td class="edit_row_anchor center print_ignore"><span class="nowrap"><a href="#" ><span class="nowrap"><img src="themes/dot.gif" title="Edit" alt="Edit" class="icon ic_b_edit">&nbsp;Edit</span></a><input type="hidden" class="where_clause" ></span>
</td>
<td class="center print_ignore"><span class="nowrap"><a href="#" ><span class="nowrap"><img src="themes/dot.gif" title="Copy" alt="Copy" class="icon ic_b_insrow">&nbsp;Copy</span></a><input type="hidden" class="where_clause" ></span>
</td>
<td class="center print_ignore"><a href="#" class="delete_row requireConfirm ajax"><span class="nowrap"><img src="themes/dot.gif" title="Delete" alt="Delete" class="icon ic_b_drop">&nbsp;Delete</span></a>
</td>
<td data-decimals="0" data-type="string" data-originallength="8" class="data grid_edit click2 not_null text"><span>Row 3</span></td>
</tr>
</tbody>
</table>
<div class="cPointer" style="visibility: hidden;"></div>
<div class="cCpy" style="display: none;"></div>
<div class="cDrop">
<div class="coldrop" style="left: 175.844px; top: -1.312px;"></div>
</div>
<div class="cList" style="display: none;">
<div class="lDiv">
<div><input type="checkbox" checked="checked">Dname 1</div>
</div>
<div class="showAllColBtn">Show all</div>
</div>
<div class="cEdit" style="display: none;"><input class="edit_box" rows="1">
<div class="edit_area"></div>
</div>
<div class="cEdit" style="display: none;"><textarea class="edit_box" rows="1"></textarea>
<div class="edit_area"></div>
</div>
</div>
</div>

View File

@ -0,0 +1,35 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* tests for Layout class in theme folder
*
* @package PhpMyAdmin-test
*/
declare(strict_types=1);
namespace PhpMyAdmin\Tests\ThemeGenerator;
use PhpMyAdmin\Tests\ThemeGeneratorTest;
use PhpMyAdmin\Tests\PmaTestCase;
/**
* Tests for PMA_Layout class
*
* @package PhpMyAdmin-test
*/
class LayoutTest extends PmaTestCase
{
/**
* Test for Layout::createLayoutFile
*
* @return void
*/
public function testCreateLayoutFile()
{
$theme = new ThemeGeneratorTest();
$post = $theme->setUp();
$output = $theme->getLayoutData();
$this->assertFileIsReadable('themes/' . $post['theme_name'] . '/layout.inc.php');
$this->assertContains('$GLOBALS[\'cfg\'][\'NaviBackground\'] = \'' . $post['Navigation_Panel'] . '\';' , $output);
}
}

View File

@ -0,0 +1,133 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* tests for ThemeGenerator class
*
* @package PhpMyAdmin-test
*/
declare(strict_types=1);
namespace PhpMyAdmin\Tests;
use PhpMyAdmin\ThemeGenerator;
use PhpMyAdmin\Tests\PmaTestCase;
/**
* Tests for PMA_ThemeGenerator class
*
* @package PhpMyAdmin-test
*/
class ThemeGeneratorTest extends PmaTestCase
{
var $output;
protected $theme;
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*
* @return array $_POST POST data for LayoutTest assertion
*/
protected function setUp()
{
$_POST['theme_name'] = 'phpunit';
$_POST['version'] = 'test1';
$_POST['description'] = 'Test theme';
$_POST['author'] = 'test';
$_POST['url'] = 'http://www.123test.com';
$_POST['Navigation_Panel'] = '#ffffff';
$_POST['Navigation_Hover'] = '#ffffff';
$_POST['Text_Colour'] = '#ffffff';
$_POST['Background_Colour'] = '#ffffff';
$_POST['Header'] = '#ffffff';
$_POST['Table_Header_and_Footer'] = '#ffffff';
$_POST['Table_Header_and_Footer_Background'] = '#ffffff';
$_POST['Table_Header_and_Footer_Text_Colour'] = '#ffffff';
$_POST['Table_Row_Background'] = '#ffffff';
$_POST['Table_Row_Alternate_Background'] = '#ffffff';
$_POST['Table_Row_Hover_and_Selected'] = '#ffffff';
$_POST['Hyperlink_Text'] = '#ffffff';
$_POST['Group_Background'] = '#ffffff';
$_POST['font'] = 'Arial';
$GLOBALS['cfg']['ThemeGenerator'] = true;
$this->theme = new ThemeGenerator();
$this->output = $this->theme->createFileStructure($_POST);
return $_POST;
}
/**
* Test for ThemeGenerator::colorPicker
*
* @return void
*/
public function testColorPicker()
{
if ($GLOBALS['cfg']['ThemeGenerator']) {
$output = $this->theme->colorPicker();
$this->assertContains('<div id="container">' , $output);
$this->assertContains('<div id="palette" class="block">' , $output);
$this->assertContains('<div id="color-palette"></div>' , $output);
$this->assertContains('<div id="picker" class="block">' , $output);
$this->assertContains('<div class="ui-color-picker" data-topic="picker" data-mode="HSB"></div>' , $output);
$this->assertContains('<div id="picker-samples" sample-id="master">' , $output);
}
}
/**
* Test for ThemeGenerator::form
*
* @return void
*/
public function testForm()
{
if ($GLOBALS['cfg']['ThemeGenerator']) {
$output = $this->theme->form();
$this->assertContains('<form action="theme_generator.php" method="post" id="save">' , $output);
$this->assertContains('<select name="type" id="theme">' , $output);
$this->assertContains('<input type="text" name="theme_name" required></input>' , $output);
}
}
/**
* Test for ThemeGenerator::createJsonFile
*
* @return void
*/
public function testCreateJsonFile()
{
$name = $_POST['theme_name'];
$this->assertFileIsReadable('themes/' . $name . '/theme.json');
$this->assertContains('"name": "' . $name . '",' , $this->output['json']);
$this->assertContains('"version": "' . $_POST['version'] . '",' , $this->output['json']);
$this->assertContains('"description": "' . $_POST['description'] . '",' , $this->output['json']);
$this->assertContains('"author": "' . $_POST['author'] . '",' , $this->output['json']);
$this->assertContains('"url": "' . $_POST['url'] . '",' , $this->output['json']);
}
/**
* Return Layout file data
*
* @return string $this->output['layout'] layout.inc.php data string
*/
public function getLayoutData()
{
return $this->output['layout'];
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*
* @return void
*/
protected function tearDown()
{
$name = $_POST['theme_name'];
unlink('themes/' . $name . '/theme.json');
unlink('themes/' . $name . '/layout.inc.php');
unlink('themes/' . $name . '/css/common.css.php');
unlink('themes/' . $name . '/css/navigation.css.php');
rmdir('themes/' . $name . '/css');
rmdir('themes/' . $name);
}
}

42
theme_generator.php Normal file
View File

@ -0,0 +1,42 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Theme generator tool
*
* @package PhpMyAdmin
*/
use PhpMyAdmin\Message;
use PhpMyAdmin\Response;
use PhpMyAdmin\ThemeGenerator;
require_once 'libraries/common.inc.php';
$response = Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
if ($GLOBALS['cfg']['ThemeGenerator']) {
$scripts->addFile('theme_generator/color_picker.js');
$scripts->addFile('theme_generator/preview.js');
$theme = new ThemeGenerator();
$response->addHTML($theme->testWritableThemeDirectory());
$response->addHTML($theme->colorPicker());
$response->addHTML($theme->form());
$response->addHTML($theme->tablePreview());
$response->addHTML($theme->groupPreview());
if (isset($_POST['Base_Colour'])) {
$output = $theme->createFileStructure($_POST);
if ($output['json'] && $output['layout']) {
$response->addHTML(
Message::success(
sprintf(
__('Theme saved, go to the %smain page%s to try it'),
'<a href="index.php">',
'</a>'
)
)
);
}
}
}

View File

@ -0,0 +1,725 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Theme Generator styles for the pmahomme theme
*
* @package PhpMyAdmin-theme
* @subpackage PMAHomme
*/
// unplanned execution path
if (! defined('PHPMYADMIN') && ! defined('TESTSUITE')) {
exit();
}
$pickerMask = $theme->getImgPath('theme_generator/picker_mask_200.png');
$arrow = $theme->getImgPath('theme_generator/arrow.png');
$arrows = $theme->getImgPath('theme_generator/arrows.png');
$hue = $theme->getImgPath('theme_generator/hue.png');
$alpha = $theme->getImgPath('theme_generator/alpha.png');
$alphaMask = $theme->getImgPath('theme_generator/alpha_mask.png');
$grain = $theme->getImgPath('theme_generator/grain.png');
?>
.ui-color-picker {
width: 420px;
margin: 0;
border: 1px solid #DDD;
background-color: #FFF;
display: table;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ui-color-picker .picking-area {
width: 198px;
height: 198px;
margin: 5px;
border: 1px solid #DDD;
position: relative;
float: left;
display: table;
}
.ui-color-picker .picking-area:hover {
cursor: default;
}
/* HSB format - Hue-Saturation-Value(Brightness) */
.ui-color-picker .picking-area {
background: url(<?php echo $pickerMask; ?>) center center;
background: -moz-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
-moz-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
background: -webkit-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
-webkit-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
-ms-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
-o-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
background-color: #F00;
}
/* HSL format - Hue-Saturation-Lightness */
.ui-color-picker[data-mode='HSL'] .picking-area {
background: -moz-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
-moz-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
background: -webkit-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
-webkit-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
background: -ms-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
-ms-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
background: -o-linear-gradient(top, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%,
hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%),
-o-linear-gradient(left, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%);
background-color: #F00;
}
.ui-color-picker .picker {
width: 10px;
height: 10px;
border-radius: 50%;
border: 1px solid #FFF;
position: absolute;
top: 45%;
left: 45%;
}
.ui-color-picker .picker:before {
width: 8px;
height: 8px;
content: "";
position: absolute;
border: 1px solid #999;
border-radius: 50%;
}
.ui-color-picker .hue,
.ui-color-picker .alpha {
width: 198px;
height: 28px;
margin: 5px;
border: 1px solid #FFF;
float: left;
}
.ui-color-picker .hue {
background: url(<?php echo $hue; ?>) center;
background: -moz-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
#00F 66.66%, #F0F 83.33%, #F00 100%);
background: -webkit-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
#00F 66.66%, #F0F 83.33%, #F00 100%);
background: -ms-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
#00F 66.66%, #F0F 83.33%, #F00 100%);
background: -o-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
#00F 66.66%, #F0F 83.33%, #F00 100%);
}
.ui-color-picker .alpha {
border: 1px solid #CCC;
background: url(<?php echo $alpha; ?>);
}
.ui-color-picker .alpha-mask {
width: 100%;
height: 100%;
background: url(<?php echo $alphaMask; ?>);
}
.ui-color-picker .slider-picker {
width: 2px;
height: 100%;
border: 1px solid #777;
background-color: #FFF;
position: relative;
top: -1px;
}
/* input HSB and RGB */
.ui-color-picker .info {
width: 200px;
margin: 5px;
float: left;
}
.ui-color-picker .info * {
float: left;
}
.ui-color-picker .input {
width: 64px;
margin: 5px 2px;
float: left;
}
.ui-color-picker .input .name {
height: 20px;
width: 30px;
text-align: center;
font-size: 14px;
line-height: 18px;
float: left;
}
.ui-color-picker .input input {
width: 30px;
height: 18px;
margin: 0;
padding: 0;
border: 1px solid #DDD;
text-align: center;
float: right;
-moz-user-select: text;
-webkit-user-select: text;
-ms-user-select: text;
}
.ui-color-picker .input[data-topic="lightness"] {
display: none;
}
.ui-color-picker[data-mode='HSL'] .input[data-topic="value"] {
display: none;
}
.ui-color-picker[data-mode='HSL'] .input[data-topic="lightness"] {
display: block;
}
.ui-color-picker .input[data-topic="alpha"] {
margin-top: 10px;
width: 93px;
}
.ui-color-picker .input[data-topic="alpha"] > .name {
width: 60px;
}
.ui-color-picker .input[data-topic="alpha"] > input {
float: right;
}
.ui-color-picker .input[data-topic="hexa"] {
width: auto;
float: right;
margin: 6px 8px 0 0;
}
.ui-color-picker .input[data-topic="hexa"] > .name {
display: none;
}
.ui-color-picker .input[data-topic="hexa"] > input {
width: 90px;
height: 24px;
padding: 2px 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
/* Preview color */
.ui-color-picker .preview {
width: 95px;
height: 53px;
margin: 5px;
margin-top: 10px;
border: 1px solid #DDD;
background-image: url(<?php echo $alpha; ?>);
float: left;
position: relative;
}
.ui-color-picker .preview:before {
height: 100%;
width: 50%;
left: 50%;
top: 0;
content: "";
background: #FFF;
position: absolute;
z-index: 1;
}
.ui-color-picker .preview-color {
width: 100%;
height: 100%;
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
z-index: 1;
}
.ui-color-picker .switch_mode {
width: 10px;
height: 20px;
position: relative;
border-radius: 5px 0 0 5px;
border: 1px solid #DDD;
background-color: #EEE;
left: -12px;
top: -1px;
z-index: 1;
transition: all 0.5s;
}
.ui-color-picker .switch_mode:hover {
background-color: #CCC;
cursor: pointer;
}
/*
* UI Component
*/
.ui-input-slider {
height: 20px;
font-family: "Segoe UI", Arial, Helvetica, sans-serif;
-moz-user-select: none;
user-select: none;
}
.ui-input-slider * {
float: left;
height: 100%;
line-height: 100%;
}
/* Input Slider */
.ui-input-slider > input {
margin: 0;
padding: 0;
width: 50px;
text-align: center;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.ui-input-slider-info {
width: 90px;
padding: 0px 10px 0px 0px;
text-align: right;
text-transform: lowercase;
}
.ui-input-slider-left, .ui-input-slider-right {
width: 16px;
cursor: pointer;
background: url(<?php echo $arrows; ?>) center left no-repeat;
}
.ui-input-slider-right {
background: url(<?php echo $arrows; ?>) center right no-repeat;
}
.ui-input-slider-name {
width: 90px;
padding: 0 10px 0 0;
text-align: right;
text-transform: lowercase;
}
.ui-input-slider-btn-set {
width: 25px;
background-color: #2C9FC9;
border-radius: 5px;
color: #FFF;
font-weight: bold;
line-height: 14px;
text-align: center;
}
.ui-input-slider-btn-set:hover {
background-color: #379B4A;
cursor: pointer;
}
/**
* Container
*/
#container {
width: 100%;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: table;
}
/**
* Picker Zone
*/
#picker {
padding: 10px;
width: 980px;
}
.ui-color-picker {
padding: 3px 5px;
float: left;
border-color: #FFF;
}
.ui-color-picker .switch_mode {
display: none;
}
.ui-color-picker .preview-color:hover {
cursor: move;
}
/**
* Picker Container
*/
#picker-samples {
width: 375px;
height: 114px;
max-height: 218px;
margin: 0 10px 0 30px;
overflow: hidden;
position: relative;
float: left;
transition: all 0.2s;
}
#picker-samples .sample {
width: 40px;
height: 40px;
margin: 5px;
border: 1px solid #DDD;
position: absolute;
float: left;
transition: all 0.2s;
}
#picker-samples .sample:hover {
cursor: pointer;
border-color: #BBB;
transform: scale(1.15);
border-radius: 3px;
}
#picker-samples .sample[data-active='true'] {
border-color: #999;
}
#picker-samples .sample[data-active='true']:after {
content: "";
position: absolute;
background: url(<?php echo $arrow; ?>) center no-repeat;
width: 100%;
height: 12px;
top: -12px;
z-index: 2;
}
#picker-samples #add-icon {
width: 100%;
height: 100%;
position: relative;
box-shadow: inset 0px 0px 2px 0px #DDD;
}
#picker-samples #add-icon:hover {
cursor: pointer;
border-color: #DDD;
box-shadow: inset 0px 0px 5px 0px #CCC;
}
#picker-samples #add-icon:before,
#picker-samples #add-icon:after {
content: "";
position: absolute;
background-color: #EEE;
box-shadow: 0 0 1px 0 #EEE;
}
#picker-samples #add-icon:before {
width: 70%;
height: 16%;
top: 42%;
left: 15%;
}
#picker-samples #add-icon:after {
width: 16%;
height: 70%;
top: 15%;
left: 42%;
}
#picker-samples #add-icon:hover:before,
#picker-samples #add-icon:hover:after {
background-color: #DDD;
box-shadow: 0 0 1px 0 #DDD;
}
/**
* Controls
*/
#controls {
width: 110px;
padding: 10px;
float: right;
}
#controls #picker-switch {
text-align: center;
float: left;
}
#controls .icon {
width: 48px;
height: 48px;
margin: 10px 0;
background-repeat: no-repeat;
background-position: center;
border: 1px solid #DDD;
display: table;
float: left;
}
#controls .icon:hover {
cursor: pointer;
}
#controls .switch {
width: 106px;
padding: 1px;
border: 1px solid #CCC;
font-size: 14px;
text-align: center;
line-height: 24px;
overflow: hidden;
float: left;
}
#controls .switch:hover {
cursor: pointer;
}
#controls .switch > * {
width: 50%;
padding: 2px 0;
background-color: #EEE;
float: left;
}
#controls .switch [data-active='true'] {
color: #FFF;
background-image: url(<?php echo $grain; ?>);
background-color: #777;
}
/**
* Color Theme
*/
#color-theme {
margin: 0 8px 0 0;
border: 1px solid #EEE;
display: inline-block;
float: right;
}
#color-theme .box {
width: 80px;
height: 92px;
float: left;
}
/**
* Color info box
*/
#color-info {
width: 360px;
float: left;
}
#color-info .title {
width: 100%;
padding: 15px;
font-size: 18px;
text-align: center;
}
#color-info .copy-container {
position: absolute;
top: -100%;
}
#color-info .property {
min-width: 280px;
height: 30px;
margin: 10px 0;
text-align: center;
line-height: 30px;
}
#color-info .property > * {
float: left;
}
#color-info .property .type {
width: 60px;
height: 100%;
padding: 0 16px 0 0;
text-align: right;
}
#color-info .property .value {
width: 200px;
height: 100%;
padding: 0 10px;
font-family: "Segoe UI", Arial, Helvetica, sans-serif;
font-size: 16px;
color: #777;
text-align: center;
background-color: #FFF;
border: none;
}
#color-info .property .value:hover {
color: #37994A;
}
#color-info .property .value:hover + .copy {
background-position: center right;
}
/**
* Color Palette
*/
#palette {
width: 675px;
height: 220px;
padding: 10px 0;
background-image: url(<?php echo $grain; ?>);
background-repeat: repeat;
background-color: #EEE;
color: #777;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#color-palette {
width: 1000px;
font-family: Arial, Helvetica, sans-serif;
color: #777;
float: left;
}
#color-palette .container {
width: 100%;
height: 50px;
line-height: 50px;
overflow: hidden;
float: left;
transition: all 0.5s;
}
#color-palette .container > * {
float: left;
}
#color-palette .title {
width: 100px;
padding: 0 10px;
text-align: right;
line-height: inherit;
}
#color-palette .palette {
width: 494px;
height: 38px;
margin: 3px;
padding: 3px;
display: table;
background-color: #FFF;
}
#color-palette .palette .sample {
width: 30px;
height: 30px;
margin: 3px;
position: relative;
border: 1px solid #DDD;
float: left;
transition: all 0.2s;
}
#color-palette .palette .sample:hover {
cursor: pointer;
border-color: #BBB;
transform: scale(1.15);
border-radius: 3px;
}
#zindex {
height: 20px;
margin: 5px;
font-size: 16px;
position: absolute;
opacity: 0;
top: -10000px;
left: 0;
color: #777;
float: left;
transition: opacity 1s;
}
#zindex input {
border: 1px solid #DDD;
font-size: 16px;
color: #777;
}
#zindex .ui-input-slider-info {
width: 60px;
}
#zindex[data-active='true'] {
top: 0;
opacity: 1;
}
.title:hover {
text-decoration: underline;
color: #235a81;
}
#group_preview {
display: none;
position: relative;
left: 523px;
bottom: 700px;
}
#group_preview.group {
width: 294px;
}
#table_preview {
display: none;
position: relative;
left: 523px;
bottom: 718px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB