Joomla4.x对模板系统做了一些调整,这些调整是不兼容J3的。在做J3升级到J4的过程中,经常会出现页面样式完全错乱的问题。
1,chrome风格实现的调整
Chrome是joomla对模块的一个包装器,通过在定义模块的style属性时候可以指定该模块位置所有模块使用的默认包装器。
在J3.x(包括J2.x)之前,所有的Chrome样式定义是在当前模板的html/modules.php文件中的。每一个样式都是一个以modxxx开头的函数。代码如下:
<?php
/**
* @package Joomla.Site
* @subpackage Templates.protostar
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* This is a file to add template specific chrome to module rendering. To use it you would
* set the style attribute for the given module(s) include in your template to use the style
* for each given modChrome function.
*
* eg. To render a module mod_test in the submenu style, you would use the following include:
* <jdoc:include type="module" name="test" style="submenu" />
*
* This gives template designers ultimate control over how modules are rendered.
*
* NOTICE: All chrome wrapping methods should be named: modChrome_{STYLE} and take the same
* two arguments.
*/
/*
* Module chrome for rendering the module in a submenu
*/
function modChrome_no($module, &$params, &$attribs)
{
if ($module->content)
{
echo $module->content;
}
}
function modChrome_well($module, &$params, &$attribs)
{
$moduleTag = htmlspecialchars($params->get('module_tag', 'div'), ENT_QUOTES, 'UTF-8');
$bootstrapSize = (int) $params->get('bootstrap_size', 0);
$moduleClass = $bootstrapSize !== 0 ? ' span' . $bootstrapSize : '';
$headerTag = htmlspecialchars($params->get('header_tag', 'h3'), ENT_QUOTES, 'UTF-8');
$headerClass = htmlspecialchars($params->get('header_class', 'page-header'), ENT_COMPAT, 'UTF-8');
if ($module->content)
{
echo '<' . $moduleTag . ' class="well ' . htmlspecialchars($params->get('moduleclass_sfx'), ENT_COMPAT, 'UTF-8') . $moduleClass . '">';
if ($module->showtitle)
{
echo '<' . $headerTag . ' class="' . $headerClass . '">' . $module->title . '</' . $headerTag . '>';
}
echo $module->content;
echo '</' . $moduleTag . '>';
}
}
在J4.x以后,就不采用这种方案来实现了。在J4.x(包括J5.x),所有的Chrome样式定义是在当前模板的html/layouts/chromes目录下面,一个风格,对应一个同名的php文件。结构如下:
其中,每一个风格的实现也不是用函数,而是用layout来代替。典型的代码如下:
<?php
/**
* @package Joomla.Site
* @subpackage Templates.cassiopeia
*
* @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Utilities\ArrayHelper;
$module = $displayData['module'];
$params = $displayData['params'];
$attribs = $displayData['attribs'];
if ($module->content === null || $module->content === '') {
return;
}
$moduleTag = $params->get('module_tag', 'div');
$moduleAttribs = [];
$moduleAttribs['class'] = $module->position . ' card ' . htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_QUOTES, 'UTF-8');
$headerTag = htmlspecialchars($params->get('header_tag', 'h3'), ENT_QUOTES, 'UTF-8');
$headerClass = htmlspecialchars($params->get('header_class', ''), ENT_QUOTES, 'UTF-8');
$headerAttribs = [];
$headerAttribs['class'] = $headerClass;
// Only output a header class if it is not card-title
if ($headerClass !== 'card-title') :
$headerAttribs['class'] = 'card-header ' . $headerClass;
endif;
// Only add aria if the moduleTag is not a div
if ($moduleTag !== 'div') {
if ($module->showtitle) :
$moduleAttribs['aria-labelledby'] = 'mod-' . $module->id;
$headerAttribs['id'] = 'mod-' . $module->id;
else :
$moduleAttribs['aria-label'] = $module->title;
endif;
}
$header = '<' . $headerTag . ' ' . ArrayHelper::toString($headerAttribs) . '>' . $module->title . '</' . $headerTag . '>';
?>
<<?php echo $moduleTag; ?> <?php echo ArrayHelper::toString($moduleAttribs); ?>>
<?php if ($module->showtitle && $headerClass !== 'card-title') : ?>
<?php echo $header; ?>
<?php endif; ?>
<div class="card-body">
<?php if ($module->showtitle && $headerClass === 'card-title') : ?>
<?php echo $header; ?>
<?php endif; ?>
<?php echo $module->content; ?>
</div>
</<?php echo $moduleTag; ?>>
如何来做兼容转换
通过上面的代码分析,joomla实际上并没有做大的改变,只是将之前的方法传参该为使用layout的$displayData注入。其它的代码保持不变。因此,我们只需要将函数的主体内容拿出来直接输出。将参数改为从$displayData中拿到就可以解决。典型转换代码如下:
之前的J3.x代码:
/*
* Default Module Chrome that has sematic markup and has best SEO support
*/
function modChrome_T3Xhtml($module, &$params, &$attribs)
{
$badge = preg_match ('/badge/', $params->get('moduleclass_sfx'))? '<span class="badge"> </span>' : '';
$moduleTag = htmlspecialchars($params->get('module_tag', 'div'));
$headerTag = htmlspecialchars($params->get('header_tag', 'h3'));
$headerClass = $params->get('header_class');
$bootstrapSize = $params->get('bootstrap_size');
$moduleClass = !empty($bootstrapSize) ? ' col-sm-' . (int) $bootstrapSize . '' : '';
$moduleClassSfx = htmlspecialchars($params->get('moduleclass_sfx'));
if (!empty ($module->content)) {
$html = "<{$moduleTag} class=\"t3-module module{$moduleClassSfx} {$moduleClass}\" id=\"Mod{$module->id}\">" .
"<div class=\"module-inner\">" . $badge;
if ($module->showtitle != 0) {
$html .= "<{$headerTag} class=\"module-title {$headerClass}\"><span>{$module->title}</span></{$headerTag}>";
}
$html .= "<div class=\"module-ct\">{$module->content}</div></div></{$moduleTag}>";
echo $html;
}
}
转换后J4.x代码:
<?php
/**
* @package Joomla.Site
* @subpackage Templates.cassiopeia
*
* @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Utilities\ArrayHelper;
$module = $displayData['module'];
$params = $displayData['params'];
$attribs = $displayData['attribs'];
$badge = preg_match ('/badge/', $params->get('moduleclass_sfx'))? '<span class="badge"> </span>' : '';
$moduleTag = htmlspecialchars($params->get('module_tag', 'div'));
$headerTag = htmlspecialchars($params->get('header_tag', 'h3'));
$headerClass = $params->get('header_class');
$bootstrapSize = $params->get('bootstrap_size');
$moduleClass = !empty($bootstrapSize) ? ' col-sm-' . (int) $bootstrapSize . '' : '';
$moduleClassSfx = htmlspecialchars($params->get('moduleclass_sfx'));
if (!empty ($module->content)) {
$html = "<{$moduleTag} class=\"t3-module module{$moduleClassSfx} {$moduleClass}\" id=\"Mod{$module->id}\">" .
"<div class=\"module-inner\">" . $badge;
if ($module->showtitle != 0) {
$html .= "<{$headerTag} class=\"module-title {$headerClass}\"><span>{$module->title}</span></{$headerTag}>";
}
$html .= "<div class=\"module-ct\">{$module->content}</div></div></{$moduleTag}>";
echo $html;
}
如此操作,即可保证样式正常工作。

评论 (0)