feat: rewrite schema-driven widget system
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace AKSRT\WidgetSystem;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Applies the common widget contract before dispatching business markup.
|
||||
*/
|
||||
final class FrontendRenderer {
|
||||
public static function render(WidgetDefinition $definition, array $args, array $instance, SchemaWidget $widget): void {
|
||||
if (!self::is_visible($instance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context = [
|
||||
'widget_id' => (string) $widget->id,
|
||||
'id_base' => $definition->id_base(),
|
||||
];
|
||||
$content = RendererRegistry::render($definition->renderer(), $instance, $context);
|
||||
if ($content === '' && $definition->slug() !== 'layout_gap') {
|
||||
return;
|
||||
}
|
||||
|
||||
AssetManager::enqueue_for($definition);
|
||||
$classes = ['aksrt-widget', 'aksrt-widget--' . $definition->slug(), 'aksrt-widget--' . $definition->size()];
|
||||
if (($instance['show_type'] ?? 'all') === 'only_pc') {
|
||||
$classes[] = 'aksrt-widget--only-pc';
|
||||
} elseif (($instance['show_type'] ?? 'all') === 'only_sm') {
|
||||
$classes[] = 'aksrt-widget--only-mobile';
|
||||
}
|
||||
if (!empty($instance['sidebar_affix'])) {
|
||||
$classes[] = 'aksrt-widget--affix';
|
||||
}
|
||||
if (!empty($instance['animation_in'])) {
|
||||
$classes[] = 'aksrt-widget--animate';
|
||||
$classes[] = 'aksrt-widget--animate-' . sanitize_html_class((string) $instance['animation_in']);
|
||||
}
|
||||
if (!empty($instance['animation_repeat'])) {
|
||||
$classes[] = 'aksrt-widget--animate-repeat';
|
||||
}
|
||||
|
||||
$style = self::style($instance);
|
||||
echo (string) ($args['before_widget'] ?? '<section>'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<div class="' . esc_attr(implode(' ', $classes)) . '" data-aksrt-widget="' . esc_attr($definition->slug()) . '" data-widget-id="' . esc_attr((string) $widget->id) . '"' . ($style !== '' ? ' style="' . esc_attr($style) . '"' : '') . '>';
|
||||
echo self::title($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<div class="aksrt-widget__content">' . $content . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '</div>';
|
||||
echo (string) ($args['after_widget'] ?? '</section>'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
private static function is_visible(array $instance): bool {
|
||||
$type = (string) ($instance['show_id_type'] ?? '');
|
||||
$ids = RendererHelpers::ids((string) ($instance['show_ids'] ?? ''));
|
||||
if ($type === '' || !$ids) {
|
||||
return true;
|
||||
}
|
||||
$current = function_exists('is_singular') && is_singular() && function_exists('get_queried_object_id') ? (int) get_queried_object_id() : 0;
|
||||
$matched = in_array($current, $ids, true);
|
||||
return $type === 'show' ? $matched : !$matched;
|
||||
}
|
||||
|
||||
private static function title(array $instance): string {
|
||||
$title = trim((string) ($instance['title'] ?? ''));
|
||||
if ($title === '') {
|
||||
return '';
|
||||
}
|
||||
$safe_title = esc_html($title);
|
||||
$highlight = trim((string) ($instance['title_highlight'] ?? ''));
|
||||
if ($highlight !== '') {
|
||||
$safe_highlight = esc_html($highlight);
|
||||
$safe_title = str_replace($safe_highlight, '<mark class="' . esc_attr((string) ($instance['title_highlight_color'] ?? 'focus-color')) . '">' . $safe_highlight . '</mark>', $safe_title);
|
||||
}
|
||||
$html = '<header class="aksrt-widget__header' . (($instance['title_style'] ?? '') === 'big' ? ' aksrt-widget__header--big' : '') . '"><div><h2 class="aksrt-widget__title">' . nl2br($safe_title) . '</h2>';
|
||||
if (!empty($instance['subtitle'])) {
|
||||
$html .= '<p class="aksrt-widget__subtitle">' . nl2br(esc_html((string) $instance['subtitle'])) . '</p>';
|
||||
}
|
||||
$html .= '</div><nav class="aksrt-widget__title-links" aria-label="' . esc_attr__('模块链接', 'aksrt') . '">';
|
||||
foreach (['title_link', 'title_link2', 'title_link3'] as $index => $key) {
|
||||
$link = RendererHelpers::link((array) ($instance[$key] ?? []));
|
||||
if ($link['url'] !== '' && $link['text'] !== '') {
|
||||
$color = (string) ($instance['title_link_style']['color_' . ($index + 1)] ?? '');
|
||||
$html .= '<a class="' . esc_attr($color) . '" href="' . $link['url'] . '"' . RendererHelpers::link_attrs($link) . '>' . esc_html($link['text']) . '</a>';
|
||||
}
|
||||
}
|
||||
return $html . '</nav></header>';
|
||||
}
|
||||
|
||||
private static function style(array $instance): string {
|
||||
$properties = [];
|
||||
foreach (['layout_pin_pc' => 'space', 'layout_pin_m' => 'space-m'] as $key => $prefix) {
|
||||
foreach (['top', 'right', 'bottom', 'left'] as $edge) {
|
||||
$value = $instance[$key][$edge] ?? '';
|
||||
if ($value !== '' && is_numeric($value)) {
|
||||
$properties[] = '--aksrt-widget-' . $prefix . '-' . $edge . ':' . (float) $value . 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (['light', 'dark'] as $mode) {
|
||||
$background = (array) ($instance['layout_bg'][$mode] ?? []);
|
||||
if (!empty($background['color'])) {
|
||||
$properties[] = '--aksrt-widget-bg-' . $mode . ':' . (string) $background['color'];
|
||||
}
|
||||
if (!empty($background['image'])) {
|
||||
$properties[] = '--aksrt-widget-bg-image-' . $mode . ':url(' . esc_url_raw((string) $background['image']) . ')';
|
||||
}
|
||||
}
|
||||
return implode(';', $properties);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user