Modernização GLPI 11: namespace GlpiPlugin\Butterfly, Monaco, assets em public/

- Classes migradas de inc/*.class.php (PluginButterfly*) para src/ com
  namespace GlpiPlugin\Butterfly (PSR-4 registrado pelo core; KB-033).
  Referências de core qualificadas (\Config, \Html, \Session, ...).
- Editor de CSS custom agora usa o Monaco do core (GLPI.Monaco.createEditor
  + sync via formdata, mesmo padrão de custom_ui do core) com fallback
  para textarea se a lib não carregar.
- pics/ movido para public/pics: no GLPI 11 só recursos em public/ são
  servidos estaticamente em /plugins/<key>/... (RequestRouterTrait).
  URLs do select2 de temas agora usam root_doc + encodeURIComponent.
- MIN_GLPI_VERSION 11.0.0; removido bloco morto de GLPI <9.5 e
  css/login.base.css órfão.
- config_page com glpi_tab urlencoded para a classe namespaced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-07-03 18:04:13 -03:00
parent 0248febe8b
commit 39f3f3f2a2
11 changed files with 146 additions and 125 deletions

View file

@ -1,11 +0,0 @@
#logo_login {
background: none;
margin: 0;
padding: 38px 0;
text-align: center;
}
#logo_login img {
display: block;
margin: 0 auto;
}

View file

@ -10,7 +10,7 @@ if (isset($_SESSION['glpi_currentpage']) && strpos($_SESSION['glpi_currentpage']
// Redirect if is a not cached URL
if (!isset($_GET['_'])) {
$timestamp = PluginButterflyToolbox::getTimestamp();
$timestamp = \GlpiPlugin\Butterfly\Toolbox::getTimestamp();
// Disable cache and redirect to cached URL
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
@ -29,29 +29,29 @@ if (!isset($_GET['_'])) {
$name = 'internal';
$css = "";
$picture = PluginButterflyConfig::getConfig("{$name}_picture", '');
$picture = \GlpiPlugin\Butterfly\Config::getConfig("{$name}_picture", '');
if ($picture) {
$css .= ".page .glpi-logo {";
$css .= " width: " . PluginButterflyConfig::getConfig("{$name}_picture_width", '100px') . " !important;";
$css .= " height: " . PluginButterflyConfig::getConfig("{$name}_picture_height", '55px') . " !important;";
$css .= " width: " . \GlpiPlugin\Butterfly\Config::getConfig("{$name}_picture_width", '100px') . " !important;";
$css .= " height: " . \GlpiPlugin\Butterfly\Config::getConfig("{$name}_picture_height", '55px') . " !important;";
$css .= " background-size: contain !important;";
$css .= " background-repeat: no-repeat !important;";
$css .= " background-position: center !important;";
$css .= " background-image: url(\"" . PluginButterflyToolbox::getPictureUrl($picture) . "\") !important;";
$css .= " background-image: url(\"" . \GlpiPlugin\Butterfly\Toolbox::getPictureUrl($picture) . "\") !important;";
$css .= "}";
}
$css_type = PluginButterflyConfig::getConfig("{$name}_css_type", 'scss');
$css_custom = PluginButterflyConfig::getConfig("{$name}_css_custom", '');
$css_type = \GlpiPlugin\Butterfly\Config::getConfig("{$name}_css_type", 'scss');
$css_custom = \GlpiPlugin\Butterfly\Config::getConfig("{$name}_css_custom", '');
$css_custom = html_entity_decode($css_custom);
if ($css_type === 'scss' && $css_custom && PluginButterflyScss::hasScssSuport()) {
if ($css_type === 'scss' && $css_custom && \GlpiPlugin\Butterfly\Scss::hasScssSuport()) {
try {
$variables = [];
$variables['butterfly_timestamp'] = PluginButterflyToolbox::getTimestamp();
$variables['butterfly_timestamp'] = \GlpiPlugin\Butterfly\Toolbox::getTimestamp();
$css .= PluginButterflyScss::compileScss($css_custom, $variables);
$css .= \GlpiPlugin\Butterfly\Scss::compileScss($css_custom, $variables);
} catch (\Throwable $th) {
// Log error safely - check if ErrorHandler class exists
$errorHandlerClass = '\Glpi\Application\ErrorHandler';

View file

@ -10,7 +10,7 @@ if (isset($_SESSION['glpi_currentpage']) && strpos($_SESSION['glpi_currentpage']
// Redirect if is a not cached URL
if (!isset($_GET['_'])) {
$timestamp = PluginButterflyToolbox::getTimestamp();
$timestamp = \GlpiPlugin\Butterfly\Toolbox::getTimestamp();
// Disable cache and redirect to cached URL
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
@ -47,16 +47,16 @@ if (false) {
<?php echo "$(function () {"; ?>
$('link[href*="butterfly/front/internal.css.php"]').appendTo($('head'))
<?php
$favicon = PluginButterflyConfig::getConfig('favicon_picture');
$favicon = \GlpiPlugin\Butterfly\Config::getConfig('favicon_picture');
if ($favicon):
$faviconUrl = PluginButterflyToolbox::getPictureUrl($favicon);
$faviconUrl = \GlpiPlugin\Butterfly\Toolbox::getPictureUrl($favicon);
?>
var $icon = $('link[rel*=icon]');
$icon.attr('type', null);
$icon.attr('href', <?php echo json_encode($faviconUrl, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>);
<?php
endif;
$pageTitle = PluginButterflyConfig::getConfig('page_title');
$pageTitle = \GlpiPlugin\Butterfly\Config::getConfig('page_title');
if ($pageTitle):
?>
var $title = $('title');
@ -65,8 +65,8 @@ if (false) {
<?php
endif;
$footerDisplay = PluginButterflyConfig::getConfig('page_footer_display', 'original');
$footerText = PluginButterflyConfig::getConfig('page_footer_text', '');
$footerDisplay = \GlpiPlugin\Butterfly\Config::getConfig('page_footer_display', 'original');
$footerText = \GlpiPlugin\Butterfly\Config::getConfig('page_footer_text', '');
if ($footerDisplay === 'hide'):
?>
$('a[id^=show_about_modal_]').hide();

View file

@ -26,9 +26,9 @@ if ($path === '') {
}
if ($theme !== '') {
$baseDir = PluginButterflyTheme::getThemeFolder() . '/' . $theme;
$baseDir = \GlpiPlugin\Butterfly\Theme::getThemeFolder() . '/' . $theme;
} else {
$baseDir = PluginButterflyToolbox::getStorageBasePath();
$baseDir = \GlpiPlugin\Butterfly\Toolbox::getStorageBasePath();
}
$fullPath = $baseDir . '/' . ltrim($path, '/');

View file

@ -10,26 +10,20 @@ function plugin_butterfly_display_login() {
$themeInfo = null;
if ($requestedTheme) {
$themeInfo = PluginButterflyTheme::getThemeInfo($requestedTheme);
$themeInfo = \GlpiPlugin\Butterfly\Theme::getThemeInfo($requestedTheme);
}
if (!$themeInfo) {
$theme = PluginButterflyConfig::getConfig("login_theme", '');
$themeInfo = PluginButterflyTheme::getThemeInfo($theme);
$theme = \GlpiPlugin\Butterfly\Config::getConfig("login_theme", '');
$themeInfo = \GlpiPlugin\Butterfly\Theme::getThemeInfo($theme);
}
$loginPicture = PluginButterflyConfig::getConfig('login_picture');
$loginPicture = \GlpiPlugin\Butterfly\Config::getConfig('login_picture');
if (!$loginPicture && $themeInfo && !empty($themeInfo['login-logo'])) {
$loginPicture = $themeInfo['login-logo'] . '&theme=' . $themeInfo['id'];
}
if ($loginPicture && version_compare(GLPI_VERSION, '9.5.0', '<')) {
echo Html::css("/plugins/butterfly/css/login.base.css", [
'version' => PLUGIN_BUTTERFLY_VERSION,
]);
}
$loginCss = PluginButterflyScss::getLoginCSS($requestedTheme);
$loginCss = \GlpiPlugin\Butterfly\Scss::getLoginCSS($requestedTheme);
if (!empty($loginCss)) {
echo "<style id='plugin-butterfly-login-css'>\n" . $loginCss . "\n</style>";
}
@ -37,9 +31,9 @@ function plugin_butterfly_display_login() {
?>
<?php if ($loginPicture) : ?>
<?php
$pictureUrl = PluginButterflyToolbox::getPictureUrl($loginPicture);
$maxWidth = Html::cleanInputText(PluginButterflyConfig::getConfig('login_picture_max_width', '145px'));
$maxHeight = Html::cleanInputText(PluginButterflyConfig::getConfig('login_picture_max_height', '80px'));
$pictureUrl = \GlpiPlugin\Butterfly\Toolbox::getPictureUrl($loginPicture);
$maxWidth = Html::cleanInputText(\GlpiPlugin\Butterfly\Config::getConfig('login_picture_max_width', '145px'));
$maxHeight = Html::cleanInputText(\GlpiPlugin\Butterfly\Config::getConfig('login_picture_max_height', '80px'));
?>
<style>
.page-anonymous .glpi-logo {
@ -71,16 +65,16 @@ function plugin_butterfly_display_login() {
});
}
<?php
$favicon = PluginButterflyConfig::getConfig('favicon_picture');
$favicon = \GlpiPlugin\Butterfly\Config::getConfig('favicon_picture');
if ($favicon) :
$faviconUrl = PluginButterflyToolbox::getPictureUrl($favicon);
$faviconUrl = \GlpiPlugin\Butterfly\Toolbox::getPictureUrl($favicon);
?>
var $icon = $('link[rel*=icon]');
$icon.attr('type', null);
$icon.attr('href', <?php echo json_encode($faviconUrl, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>);
<?php
endif;
$pageTitle = PluginButterflyConfig::getConfig('page_title');
$pageTitle = \GlpiPlugin\Butterfly\Config::getConfig('page_title');
if ($pageTitle) :
?>
var $title = $('title');
@ -88,8 +82,8 @@ function plugin_butterfly_display_login() {
$title.text(newTitle);
<?php
endif;
$footerDisplay = PluginButterflyConfig::getConfig('page_footer_display', 'original');
$footerText = PluginButterflyConfig::getConfig('page_footer_text', '');
$footerDisplay = \GlpiPlugin\Butterfly\Config::getConfig('page_footer_display', 'original');
$footerText = \GlpiPlugin\Butterfly\Config::getConfig('page_footer_text', '');
if ($footerDisplay === 'hide') :
?>
$('#footer-login, .login-footer').hide();

View file

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 243 KiB

View file

@ -3,7 +3,7 @@
define('PLUGIN_BUTTERFLY_VERSION', '2.1.0');
// Minimal GLPI version, inclusive
define("PLUGIN_BUTTERFLY_MIN_GLPI_VERSION", "10.0.0");
define("PLUGIN_BUTTERFLY_MIN_GLPI_VERSION", "11.0.0");
// Maximum GLPI version, exclusive
define("PLUGIN_BUTTERFLY_MAX_GLPI_VERSION", "11.0.99");
@ -41,8 +41,6 @@ function plugin_init_butterfly()
);
}
// $PLUGIN_HOOKS['config_page']['butterfly'] = '../../front/config.form.php?itemtype=Config&glpi_tab=PluginButterflyConfig$1';
$plugin = new Plugin();
if ($plugin->isInstalled('butterfly') && $plugin->isActivated('butterfly')) {
@ -53,12 +51,12 @@ function plugin_init_butterfly()
}
;
Plugin::registerClass('PluginButterflyConfig', [
Plugin::registerClass('\GlpiPlugin\Butterfly\Config', [
'addtabon' => ['Config']
]);
// Register config page only when installed & activated
$PLUGIN_HOOKS['config_page']['butterfly'] = '../../front/config.form.php?itemtype=Config&glpi_tab=PluginButterflyConfig$1';
$PLUGIN_HOOKS['config_page']['butterfly'] = '../../front/config.form.php?itemtype=Config&glpi_tab=' . rawurlencode('GlpiPlugin\Butterfly\Config') . '$1';
$PLUGIN_HOOKS['display_login']['butterfly'] = "plugin_butterfly_display_login";
@ -68,6 +66,7 @@ function plugin_init_butterfly()
$PLUGIN_HOOKS["add_javascript"]['butterfly'] = 'front/internal.js.php';
$CFG_GLPI['javascript']['config']['config'][] = 'tinymce';
$CFG_GLPI['javascript']['config']['config'][] = 'monaco';
}
}

View file

@ -1,6 +1,8 @@
<?php
class PluginButterflyConfig extends CommonDBTM {
namespace GlpiPlugin\Butterfly;
class Config extends \CommonDBTM {
private static $_cache = null;
@ -9,7 +11,7 @@ class PluginButterflyConfig extends CommonDBTM {
if (self::$_cache === null) {
$config = new self();
$config->getEmpty();
$config->fields = array_merge($config->fields, Config::getConfigurationValues('butterfly'));
$config->fields = array_merge($config->fields, \Config::getConfigurationValues('butterfly'));
self::$_cache = $config->fields;
}
@ -20,7 +22,7 @@ class PluginButterflyConfig extends CommonDBTM {
return $defaultValue;
}
function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
function getTabNameForItem(\CommonGLPI $item, $withtemplate = 0) {
switch (get_class($item)) {
case 'Config':
return [1 => t_butterfly('Butterfly')];
@ -29,7 +31,7 @@ class PluginButterflyConfig extends CommonDBTM {
}
}
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
static function displayTabContentForItem(\CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
switch (get_class($item)) {
case 'Config':
$config = new self();
@ -47,7 +49,7 @@ class PluginButterflyConfig extends CommonDBTM {
if (isset($input[$blank]) && $input[$blank]) {
unset($input[$blank]);
if (isset($old[$name]) && $old[$name]) {
PluginButterflyToolbox::deletePicture($old[$name]);
Toolbox::deletePicture($old[$name]);
}
$input[$name] = '';
} else if (isset($input[$new]) && !empty($input[$new]) && !empty($input[$new][0])) {
@ -59,19 +61,19 @@ class PluginButterflyConfig extends CommonDBTM {
$picResizedPath = $tmpDir . '/resized_' . $picName;
if ($width || $height) {
if (PluginButterflyToolbox::resizePicture($picPath, $picResizedPath, $width, $height, 0, 0, 0, 0, $max_size)) {
if (Toolbox::resizePicture($picPath, $picResizedPath, $width, $height, 0, 0, 0, 0, $max_size)) {
$picPath = $picResizedPath;
}
}
if ($dest = PluginButterflyToolbox::savePicture($picPath)) {
if ($dest = Toolbox::savePicture($picPath)) {
$input[$name] = $dest;
} else {
Session::addMessageAfterRedirect(__('Unable to save picture file.'), true, ERROR);
\Session::addMessageAfterRedirect(__('Unable to save picture file.'), true, ERROR);
}
if (isset($old[$name]) && $old[$name]) {
PluginButterflyToolbox::deletePicture($old[$name]);
Toolbox::deletePicture($old[$name]);
}
}
@ -101,15 +103,15 @@ class PluginButterflyConfig extends CommonDBTM {
$input[$fullName] = preg_replace('/\\\\r\\\\n/', "\n", $input[$fullName]);
$input[$fullName] = preg_replace('/\\\\n/', "\n", $input[$fullName]);
if ($input[$type] === 'scss' && PluginButterflyScss::hasScssSuport()) {
if ($input[$type] === 'scss' && Scss::hasScssSuport()) {
try {
$variables = [];
$variables['butterfly_timestamp'] = PluginButterflyToolbox::getTimestamp();
$variables['butterfly_timestamp'] = Toolbox::getTimestamp();
PluginButterflyScss::compileScss($input[$fullName], $variables);
Scss::compileScss($input[$fullName], $variables);
} catch (\Throwable $th) {
$message = sprintf(t_butterfly('Unable to compile the SCSS (%1$s). Message: '), $label);
Session::addMessageAfterRedirect($message . $th->getMessage(), true, ERROR);
\Session::addMessageAfterRedirect($message . $th->getMessage(), true, ERROR);
}
}
}
@ -118,7 +120,7 @@ class PluginButterflyConfig extends CommonDBTM {
}
static function configUpdate($input) {
$old = Config::getConfigurationValues('butterfly');
$old = \Config::getConfigurationValues('butterfly');
unset($input['_no_history']);
@ -139,9 +141,9 @@ class PluginButterflyConfig extends CommonDBTM {
$input['timestamp'] = time();
PluginButterflyToolbox::setTimestamp($input['timestamp']);
Toolbox::setTimestamp($input['timestamp']);
Session::addMessageAfterRedirect(__('Item successfully updated'), false, INFO);
\Session::addMessageAfterRedirect(__('Item successfully updated'), false, INFO);
return $input;
}
@ -150,7 +152,7 @@ class PluginButterflyConfig extends CommonDBTM {
$defaultCss = 'css';
if (PluginButterflyScss::hasScssSuport()) {
if (Scss::hasScssSuport()) {
$defaultCss = 'scss';
}
@ -176,7 +178,7 @@ class PluginButterflyConfig extends CommonDBTM {
protected function buildPictureLine($name, $recommendedSize = null) {
if (!empty($this->fields[$name])) {
echo '<td>';
echo Html::image(PluginButterflyToolbox::getPictureUrl($this->fields[$name]), [
echo \Html::image(Toolbox::getPictureUrl($this->fields[$name]), [
'style' => '
max-width: 100px;
max-height: 100px;
@ -186,7 +188,7 @@ class PluginButterflyConfig extends CommonDBTM {
'class' => 'picture_square'
]);
echo "&nbsp;";
echo Html::getCheckbox([
echo \Html::getCheckbox([
'title' => t_butterfly('Reset'),
'name' => "_blank_$name"
]);
@ -196,7 +198,7 @@ class PluginButterflyConfig extends CommonDBTM {
} else {
echo '<td colspan="3">';
}
Html::file([
\Html::file([
'name' => $name,
'onlyimages' => true,
'min_file_size' => 1,
@ -225,28 +227,58 @@ class PluginButterflyConfig extends CommonDBTM {
'css' => 'CSS',
];
if (PluginButterflyScss::hasScssSuport()) {
if (Scss::hasScssSuport()) {
$css_type['scss'] = 'SCSS';
}
Dropdown::showFromArray($type, $css_type, ['value' => $this->fields[$type]]);
\Dropdown::showFromArray($type, $css_type, ['value' => $this->fields[$type]]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'>";
echo "<td colspan='4' style='max-width: 1000px'>";
$rand = mt_rand();
$containerId = $fullName . '_editor_' . $rand;
$value = rtrim($this->fields[$fullName]);
// Editor Monaco do core (GLPI 11) com fallback: o textarea escondido
// mantém o name/valor e é sincronizado no submit via evento formdata
echo sprintf(
'<textarea %1$s>',
Html::parseAttributes([
\Html::parseAttributes([
'id' => $fullName . '_' . $rand,
'name' => $fullName,
'class' => 'butterfly-css-editor',
'rows' => 15,
'spellcheck' => 'false',
'class' => 'butterfly-css-editor d-none',
])
);
echo rtrim($this->fields[$fullName]);
echo $value;
echo '</textarea>';
echo '<div id="' . $containerId . '" style="height: 300px"></div>';
echo \Html::scriptBlock('
$(function() {
if (window.GLPI === undefined || window.GLPI.Monaco === undefined) {
$("#' . $fullName . '_' . $rand . '").removeClass("d-none").attr({rows: 15, spellcheck: false});
$("#' . $containerId . '").remove();
return;
}
window.GLPI.Monaco.createEditor(
' . json_encode($containerId, JSON_HEX_TAG | JSON_HEX_AMP) . ',
"scss",
' . json_encode($value, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) . ',
[]
).then(() => {
$("#' . $containerId . '").closest("form").on("formdata", (e) => {
const editors = window.monaco.editor.getEditors().filter(
(editor) => editor._domElement.id === ' . json_encode($containerId, JSON_HEX_TAG | JSON_HEX_AMP) . '
);
if (editors.length) {
e.originalEvent.formData.delete(' . json_encode($fullName, JSON_HEX_TAG | JSON_HEX_AMP) . ');
e.originalEvent.formData.append(' . json_encode($fullName, JSON_HEX_TAG | JSON_HEX_AMP) . ', editors[0].getValue());
}
});
});
});
');
echo "</td>";
echo "</tr>\n";
}
@ -258,20 +290,20 @@ class PluginButterflyConfig extends CommonDBTM {
* */
function showFormDisplay() {
global $CFG_GLPI;
if (!Config::canView()) {
if (!\Config::canView()) {
return false;
}
$this->getEmpty();
$this->fields = array_merge($this->fields, Config::getConfigurationValues('butterfly'));
$this->fields = array_merge($this->fields, \Config::getConfigurationValues('butterfly'));
$canedit = Session::haveRight(Config::$rightname, UPDATE);
$canedit = \Session::haveRight(\Config::$rightname, UPDATE);
if ($canedit) {
echo "<form name='form' action=\"" . Toolbox::getItemTypeFormURL('Config') . "\" method='post'>";
echo "<form name='form' action=\"" . \Toolbox::getItemTypeFormURL('Config') . "\" method='post'>";
}
echo Html::hidden('config_context', ['value' => 'butterfly']);
echo Html::hidden('config_class', ['value' => __CLASS__]);
echo \Html::hidden('config_context', ['value' => 'butterfly']);
echo \Html::hidden('config_class', ['value' => __CLASS__]);
echo "<div class='center' id='tabsbody'>";
@ -343,7 +375,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<td colspan='3'>";
echo sprintf(
'<input type="text" %1$s />',
Html::parseAttributes([
\Html::parseAttributes([
'name' => 'page_title',
'value' => $this->fields['page_title'],
'style' => 'width: 98%',
@ -355,7 +387,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<tr class='tab_bg_1'>";
echo "<td>" . t_butterfly('Footer') . "</td>";
echo "<td colspan='3'>";
Dropdown::showFromArray('page_footer_display', [
\Dropdown::showFromArray('page_footer_display', [
'original' => __('Original'),
'hide' => t_butterfly('Hide'),
'custom' => t_butterfly('Custom'),
@ -366,7 +398,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<tr class='tab_bg_1'>";
echo "<td>" . t_butterfly('Footer text') . "</td>";
echo "<td colspan='3'>";
Html::textarea([
\Html::textarea([
'rand' => $rand,
'editor_id' => 'text' . $rand,
'name' => 'page_footer_text',
@ -403,13 +435,13 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<td colspan='2'>";
echo sprintf(
'<select %1$s>',
Html::parseAttributes([
\Html::parseAttributes([
'name' => 'login_theme',
])
);
echo '<option value="">GLPI (' . __('Original') . ')</option>';
foreach (PluginButterflyTheme::getLoginThemes() as $id => $theme) {
foreach (Theme::getLoginThemes() as $id => $theme) {
$attrs = [
'name' => 'login_theme',
'value' => $id,
@ -425,23 +457,24 @@ class PluginButterflyConfig extends CommonDBTM {
echo sprintf(
'<option %1$s>%2$s</option>',
Html::parseAttributes($attrs),
\Html::parseAttributes($attrs),
htmlentities($theme['name'])
);
}
echo '</select>';
?>
<script type="text/javascript">
var butterflyPluginBase = <?php echo json_encode($CFG_GLPI['root_doc'] . '/plugins/butterfly', JSON_HEX_TAG | JSON_HEX_AMP) ?>;
function butterflyFormatThemes(theme) {
var data = theme && theme.element && theme.element.dataset || {};
if (!theme.id || !data.preview) {
return $('<span></span>', {
html: '<img src="../plugins/butterfly/pics/login.preview.png"/>&nbsp;' + theme.text
html: '<img src="' + butterflyPluginBase + '/pics/login.preview.png"/>&nbsp;' + theme.text
});
}
return $('<span></span>', {
html: '<img src="../plugins/butterfly/front/picture.send.php?theme=' + theme.id + '&path=' + data.preview + '"/>&nbsp;' + theme.text
html: '<img src="' + butterflyPluginBase + '/front/picture.send.php?theme=' + encodeURIComponent(theme.id) + '&path=' + encodeURIComponent(data.preview) + '"/>&nbsp;' + theme.text
});
}
$("select[name=login_theme]").select2({
@ -473,7 +506,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "</td>";
echo "</tr>\n";
$themeInfo = PluginButterflyTheme::getThemeInfo($this->fields['login_theme']);
$themeInfo = Theme::getThemeInfo($this->fields['login_theme']);
if ($themeInfo && isset($themeInfo['variables'])) {
foreach ($themeInfo['variables'] as $k => $v) {
$themeId = $themeInfo['id'];
@ -485,11 +518,11 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<tr class='tab_bg_1'>";
echo "<td>" . t_butterfly($v['name']) . "</td>";
echo "<td>";
Html::showColorField($fieldName, [
\Html::showColorField($fieldName, [
'value' => $fieldValue
]);
echo "&nbsp;";
echo Html::getCheckbox([
echo \Html::getCheckbox([
'title' => t_butterfly('Reset'),
'name' => "_blank_$fieldName"
]);
@ -511,7 +544,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<td>";
echo sprintf(
'<input type="text" %1$s />',
Html::parseAttributes([
\Html::parseAttributes([
'name' => 'login_picture_max_width',
'value' => $this->fields['login_picture_max_width'],
])
@ -521,7 +554,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<td>";
echo sprintf(
'<input type="text" %1$s />',
Html::parseAttributes([
\Html::parseAttributes([
'name' => 'login_picture_max_height',
'value' => $this->fields['login_picture_max_height'],
])
@ -554,7 +587,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<td>";
echo sprintf(
'<input type="text" %1$s />',
Html::parseAttributes([
\Html::parseAttributes([
'name' => 'internal_picture_width',
'value' => $this->fields['internal_picture_width'],
])
@ -564,7 +597,7 @@ class PluginButterflyConfig extends CommonDBTM {
echo "<td>";
echo sprintf(
'<input type="text" %1$s />',
Html::parseAttributes([
\Html::parseAttributes([
'name' => 'internal_picture_height',
'value' => $this->fields['internal_picture_height'],
])
@ -588,6 +621,6 @@ class PluginButterflyConfig extends CommonDBTM {
echo "</table>";
}
Html::closeForm();
\Html::closeForm();
}
}

View file

@ -1,6 +1,8 @@
<?php
class PluginButterflyScss {
namespace GlpiPlugin\Butterfly;
class Scss {
static function hasScssSuport() {
return class_exists(\ScssPhp\ScssPhp\Compiler::class);
@ -63,14 +65,14 @@ class PluginButterflyScss {
static function getLoginCSS($theme = null, $variables = []) {
if (!$theme) {
$theme = PluginButterflyConfig::getConfig("login_theme", '');
$theme = Config::getConfig("login_theme", '');
}
$themeInfo = null;
if ($theme) {
$themeInfo = PluginButterflyTheme::getThemeInfo($theme);
$themeInfo = Theme::getThemeInfo($theme);
}
$picture = PluginButterflyConfig::getConfig("login_background_picture", '');
$picture = Config::getConfig("login_background_picture", '');
if (!$picture && $themeInfo && !empty($themeInfo['login-background'])) {
$picture = $themeInfo['login-background'] . '&theme=' . $themeInfo['id'];
@ -78,7 +80,7 @@ class PluginButterflyScss {
$css = '';
if ($picture) {
$pictureUrl = PluginButterflyToolbox::getPictureUrl($picture);
$pictureUrl = Toolbox::getPictureUrl($picture);
$css .= "#firstboxlogin, #text-login, #logo_login, .login-container, .login-card, .glpi-login__wrapper, .main-content-card {";
$css .= " background-color: transparent !important;";
@ -97,20 +99,20 @@ class PluginButterflyScss {
$css .= "}";
}
$css_type = PluginButterflyConfig::getConfig("login_css_type", 'scss');
$css_custom = PluginButterflyConfig::getConfig("login_css_custom", '');
$css_type = Config::getConfig("login_css_type", 'scss');
$css_custom = Config::getConfig("login_css_custom", '');
$themeVariables = [];
$css_custom = html_entity_decode($css_custom);
if ($css_type === 'scss' && PluginButterflyScss::hasScssSuport()) {
if ($css_type === 'scss' && Scss::hasScssSuport()) {
$variables = [];
if ($themeInfo && isset($themeInfo['variables'])) {
foreach ($themeInfo['variables'] as $k => $v) {
$themeId = $themeInfo['id'];
$fieldName = "login_theme-$themeId-$k";
$fieldValue = PluginButterflyConfig::getConfig($fieldName, $v['default']);
$fieldValue = Config::getConfig($fieldName, $v['default']);
$variables[$k] = $fieldValue;
$themeVariables[$k] = $fieldValue;
}
@ -121,10 +123,10 @@ class PluginButterflyScss {
$css_custom = "@import '" . $scssPath . "';\n" . $css_custom;
}
$variables['butterfly_timestamp'] = PluginButterflyToolbox::getTimestamp();
$variables['butterfly_timestamp'] = Toolbox::getTimestamp();
try {
$css .= PluginButterflyScss::compileScss($css_custom, $variables);
$css .= Scss::compileScss($css_custom, $variables);
} catch (\Throwable $th) {
// Log error and continue with basic CSS
error_log("SCSS compilation error: " . $th->getMessage());
@ -142,7 +144,7 @@ class PluginButterflyScss {
foreach ($themeInfo['variables'] as $k => $v) {
$themeId = $themeInfo['id'];
$fieldName = "login_theme-$themeId-$k";
$fieldValue = PluginButterflyConfig::getConfig($fieldName, $v['default']);
$fieldValue = Config::getConfig($fieldName, $v['default']);
$themeVariables[$k] = $fieldValue;
}
}
@ -154,11 +156,11 @@ class PluginButterflyScss {
$btnBg = $themeVariables['btn-background-color'] ?? null;
$btnFg = $themeVariables['btn-foreground-color'] ?? null;
if (isset($themeVariables['card-background-color']) && $themeVariables['card-background-color'] !== '') {
$cardBg = Html::cleanInputText($themeVariables['card-background-color']);
$cardBg = \Html::cleanInputText($themeVariables['card-background-color']);
}
if ($btnBg) {
$btnBg = Html::cleanInputText($btnBg);
$btnBg = \Html::cleanInputText($btnBg);
$css .= ".form-footer .btn.btn-primary, .form-footer .btn-primary.w-100, .glpi-login__wrapper .btn.btn-primary {";
$css .= " background-color: {$btnBg} !important;";
$css .= " border-color: {$btnBg} !important;";
@ -168,7 +170,7 @@ class PluginButterflyScss {
$css .= "}";
}
if ($btnFg) {
$btnFg = Html::cleanInputText($btnFg);
$btnFg = \Html::cleanInputText($btnFg);
$css .= ".form-footer .btn.btn-primary, .glpi-login__wrapper .btn.btn-primary {";
$css .= " color: {$btnFg} !important;";
$css .= "}";

View file

@ -1,6 +1,8 @@
<?php
class PluginButterflyTheme {
namespace GlpiPlugin\Butterfly;
class Theme {
public static function getThemeFolder() {
return dirname(__DIR__) . '/themes';

View file

@ -1,12 +1,14 @@
<?php
class PluginButterflyToolbox {
namespace GlpiPlugin\Butterfly;
class Toolbox {
static public function getTimestamp() {
global $GLPI_CACHE;
if (!$GLPI_CACHE) {
return PluginButterflyConfig::getConfig('timestamp', time());
return Config::getConfig('timestamp', time());
}
$timestamp = $GLPI_CACHE->get('butterfly_timestamp');
@ -25,7 +27,7 @@ class PluginButterflyToolbox {
}
if (!$GLPI_CACHE) {
Config::setConfigurationValues('butterfly', [
\Config::setConfigurationValues('butterfly', [
'timestamp' => $timestamp,
]);
return;
@ -53,7 +55,7 @@ class PluginButterflyToolbox {
if (strpos($rawPath, '.php?') !== false) {
$normalized = (strpos($rawPath, '/') === 0) ? $rawPath : '/' . $rawPath;
return Html::getPrefixedUrl($normalized);
return \Html::getPrefixedUrl($normalized);
}
$endpoint = '/plugins/butterfly/front/picture.send.php';
@ -65,13 +67,13 @@ class PluginButterflyToolbox {
$theme = trim($theme);
if ($filePath !== '' && $theme !== '') {
return Html::getPrefixedUrl(
return \Html::getPrefixedUrl(
$endpoint . '?path=' . rawurlencode($filePath) . '&theme=' . rawurlencode($theme)
);
}
}
return Html::getPrefixedUrl($endpoint . '?path=' . rawurlencode($rawPath));
return \Html::getPrefixedUrl($endpoint . '?path=' . rawurlencode($rawPath));
}
public static function getStorageBasePath() {
@ -88,7 +90,7 @@ class PluginButterflyToolbox {
static public function savePicture($src, $uniq_prefix = null) {
$basePath = static::getStorageBasePath();
if (class_exists('Document') && method_exists('Document', 'isPicture') && !Document::isPicture($src)) {
if (class_exists('Document') && method_exists('Document', 'isPicture') && !\Document::isPicture($src)) {
return false;
}