revert 8cad3c2d3d
revert Merge pull request 'feat(widgets): add phase 4 validation and accessibility' (#6) from worktree/widgets-phase-4 into main Reviewed-on: #6
This commit is contained in:
@@ -28,8 +28,7 @@ final class AdminFormController {
|
||||
wp_enqueue_script('jquery-ui-sortable');
|
||||
wp_enqueue_style('aksrt-widget-admin', AKSRT_URI . '/assets/widgets/admin.css', ['wp-color-picker'], AKSRT_VERSION);
|
||||
wp_enqueue_style('aksrt-widget-preview', AKSRT_URI . '/assets/widgets/frontend.css', [], AKSRT_VERSION);
|
||||
wp_enqueue_script('aksrt-widget-admin-core', AKSRT_URI . '/assets/widgets/admin-core.js', [], AKSRT_VERSION, true);
|
||||
wp_enqueue_script('aksrt-widget-admin', AKSRT_URI . '/assets/widgets/admin.js', ['jquery', 'jquery-ui-sortable', 'wp-color-picker', 'aksrt-widget-admin-core'], AKSRT_VERSION, true);
|
||||
wp_enqueue_script('aksrt-widget-admin', AKSRT_URI . '/assets/widgets/admin.js', ['jquery', 'jquery-ui-sortable', 'wp-color-picker'], AKSRT_VERSION, true);
|
||||
wp_localize_script('aksrt-widget-admin', 'aksrtWidgetAdmin', [
|
||||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||||
'action' => self::AJAX_ACTION,
|
||||
|
||||
@@ -33,8 +33,6 @@ final class AssetManager {
|
||||
'loading' => __('正在加载…', 'aksrt'),
|
||||
'error' => __('加载失败,请重试。', 'aksrt'),
|
||||
'retry' => __('重试', 'aksrt'),
|
||||
'pause' => __('暂停自动播放', 'aksrt'),
|
||||
'resume' => __('继续自动播放', 'aksrt'),
|
||||
],
|
||||
];
|
||||
wp_add_inline_script('aksrt-widgets', 'window.aksrtWidgets=' . wp_json_encode($config) . ';', 'before');
|
||||
|
||||
@@ -9,7 +9,7 @@ defined('ABSPATH') || exit;
|
||||
*/
|
||||
final class FrontendRenderer {
|
||||
public static function render(WidgetDefinition $definition, array $args, array $instance, SchemaWidget $widget): void {
|
||||
if (!WidgetVisibility::should_render($instance)) {
|
||||
if (!self::is_visible($instance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,10 @@ final class FrontendRenderer {
|
||||
|
||||
AssetManager::enqueue_for($definition);
|
||||
$classes = ['aksrt-widget', 'aksrt-widget--' . $definition->slug(), 'aksrt-widget--' . $definition->size()];
|
||||
$device_class = WidgetVisibility::device_class($instance);
|
||||
if ($device_class !== '') {
|
||||
$classes[] = $device_class;
|
||||
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';
|
||||
@@ -48,6 +49,17 @@ final class FrontendRenderer {
|
||||
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 === '') {
|
||||
|
||||
@@ -97,10 +97,10 @@ final class ContentRenderer {
|
||||
private static function posts(string $slug, array $instance, array $context): string {
|
||||
$widget_id = (string) ($context['widget_id'] ?? '');
|
||||
if (($instance['load_mode'] ?? 'sync') === 'ajax') {
|
||||
return '<div class="aksrt-widget-items is-loading" data-widget-items data-widget="' . esc_attr($slug) . '" data-instance="' . esc_attr($widget_id) . '" data-page="1" aria-live="polite" aria-busy="true"><div class="aksrt-widget-skeleton" role="status" aria-label="' . esc_attr__('正在加载', 'aksrt') . '"></div></div>';
|
||||
return '<div class="aksrt-widget-items is-loading" data-widget-items data-widget="' . esc_attr($slug) . '" data-instance="' . esc_attr($widget_id) . '" data-page="1"><div class="aksrt-widget-skeleton" aria-label="' . esc_attr__('正在加载', 'aksrt') . '"></div></div>';
|
||||
}
|
||||
$payload = PostRenderer::payload($instance, $slug, 1);
|
||||
return '<div class="aksrt-widget-items" data-widget-items data-widget="' . esc_attr($slug) . '" data-instance="' . esc_attr($widget_id) . '" data-page="1" aria-live="polite" aria-busy="false">' . $payload['html'] . $payload['paginate_html'] . '</div>';
|
||||
return '<div class="aksrt-widget-items" data-widget-items data-widget="' . esc_attr($slug) . '" data-instance="' . esc_attr($widget_id) . '" data-page="1">' . $payload['html'] . $payload['paginate_html'] . '</div>';
|
||||
}
|
||||
|
||||
private static function tab_posts(array $instance, array $context): string {
|
||||
@@ -109,15 +109,11 @@ final class ContentRenderer {
|
||||
return RendererHelpers::empty_state(__('请配置文章栏目', 'aksrt'));
|
||||
}
|
||||
$buttons = '';
|
||||
$key = sanitize_html_class((string) ($context['widget_id'] ?? 'preview')) ?: 'preview';
|
||||
$panel_id = 'aksrt-tab-panel-' . $key;
|
||||
$first_tab_id = 'aksrt-tab-' . $key . '-0';
|
||||
foreach ($tabs as $index => $tab) {
|
||||
$tab_id = 'aksrt-tab-' . $key . '-' . $index;
|
||||
$buttons .= '<button type="button" role="tab" id="' . esc_attr($tab_id) . '" aria-controls="' . esc_attr($panel_id) . '" aria-selected="' . ($index === 0 ? 'true' : 'false') . '" tabindex="' . ($index === 0 ? '0' : '-1') . '" data-segment="' . $index . '">' . esc_html((string) ($tab['title'] ?? sprintf(__('栏目 %d', 'aksrt'), $index + 1))) . '</button>';
|
||||
$buttons .= '<button type="button" role="tab" aria-selected="' . ($index === 0 ? 'true' : 'false') . '" data-segment="' . $index . '">' . esc_html((string) ($tab['title'] ?? sprintf(__('栏目 %d', 'aksrt'), $index + 1))) . '</button>';
|
||||
}
|
||||
$payload = PostRenderer::payload($instance, 'tab_posts', 1, '0');
|
||||
return '<div class="aksrt-widget-tabs" data-widget="tab_posts" data-instance="' . esc_attr((string) ($context['widget_id'] ?? '')) . '"><div class="aksrt-widget-tabs__nav" role="tablist" aria-label="' . esc_attr__('文章栏目', 'aksrt') . '">' . $buttons . '</div><div class="aksrt-widget-tabs__panel" role="tabpanel" id="' . esc_attr($panel_id) . '" aria-labelledby="' . esc_attr($first_tab_id) . '" tabindex="0" data-widget-items data-segment="0" aria-live="polite" aria-busy="false">' . $payload['html'] . $payload['paginate_html'] . '</div></div>';
|
||||
return '<div class="aksrt-widget-tabs" data-widget="tab_posts" data-instance="' . esc_attr((string) ($context['widget_id'] ?? '')) . '"><div class="aksrt-widget-tabs__nav" role="tablist">' . $buttons . '</div><div class="aksrt-widget-tabs__panel" role="tabpanel" data-widget-items data-segment="0">' . $payload['html'] . $payload['paginate_html'] . '</div></div>';
|
||||
}
|
||||
|
||||
private static function post_pay(array $instance): string {
|
||||
|
||||
@@ -67,7 +67,7 @@ final class GeneralRenderer {
|
||||
return RendererHelpers::empty_state(__('请配置视频地址', 'aksrt'));
|
||||
}
|
||||
$ratio = (string) $i['ratio'];
|
||||
return '<div class="aksrt-widget-video aksrt-widget-video--' . esc_attr(str_replace(':', '-', $ratio)) . '" data-video-url="' . $url . '" data-video-poster="' . esc_url((string) $i['poster']) . '" data-autoplay="' . (!empty($i['autoplay']) ? '1' : '0') . '" data-muted="' . (!empty($i['muted']) ? '1' : '0') . '"><video controls playsinline preload="metadata"' . (!empty($i['autoplay']) ? ' autoplay' : '') . (!empty($i['muted']) ? ' muted' : '') . (!empty($i['poster']) ? ' poster="' . esc_url((string) $i['poster']) . '"' : '') . '><source src="' . $url . '"></video><p class="aksrt-widget-media-error" role="alert" aria-live="assertive" hidden>' . esc_html__('视频加载失败,请稍后重试。', 'aksrt') . '</p></div>';
|
||||
return '<div class="aksrt-widget-video aksrt-widget-video--' . esc_attr(str_replace(':', '-', $ratio)) . '" data-video-url="' . $url . '" data-video-poster="' . esc_url((string) $i['poster']) . '" data-autoplay="' . (!empty($i['autoplay']) ? '1' : '0') . '" data-muted="' . (!empty($i['muted']) ? '1' : '0') . '"><video controls playsinline preload="metadata"' . (!empty($i['autoplay']) ? ' autoplay' : '') . (!empty($i['muted']) ? ' muted' : '') . (!empty($i['poster']) ? ' poster="' . esc_url((string) $i['poster']) . '"' : '') . '><source src="' . $url . '"></video><p class="aksrt-widget-media-error" hidden>' . esc_html__('视频加载失败,请稍后重试。', 'aksrt') . '</p></div>';
|
||||
}
|
||||
|
||||
private static function render_embed(array $i): string {
|
||||
|
||||
@@ -9,13 +9,14 @@ defined('ABSPATH') || exit;
|
||||
/** Render the seven knowledge-product presentation widgets. */
|
||||
final class KnowledgeProductRenderer {
|
||||
public static function render(string $slug, array $instance, array $context = []): string {
|
||||
unset($context);
|
||||
switch ($slug) {
|
||||
case 'pricing_plans': return self::pricing($instance);
|
||||
case 'reviews': return self::reviews($instance);
|
||||
case 'faq': return self::faq($instance);
|
||||
case 'stats': return self::stats($instance);
|
||||
case 'highlights': return self::highlights($instance);
|
||||
case 'feature_intro': return self::feature_intro($instance, $context);
|
||||
case 'feature_intro': return self::feature_intro($instance);
|
||||
case 'tilt_cases': return self::tilt($instance);
|
||||
}
|
||||
return '';
|
||||
@@ -95,20 +96,17 @@ final class KnowledgeProductRenderer {
|
||||
return $html . '</div>';
|
||||
}
|
||||
|
||||
private static function feature_intro(array $i, array $context): string {
|
||||
private static function feature_intro(array $i): string {
|
||||
$tabs = $panels = '';
|
||||
$key = sanitize_html_class((string) ($context['widget_id'] ?? 'preview')) ?: 'preview';
|
||||
foreach ((array) $i['items'] as $index => $item) {
|
||||
$tab_id = 'aksrt-feature-' . $key . '-tab-' . $index;
|
||||
$panel_id = 'aksrt-feature-' . $key . '-panel-' . $index;
|
||||
$tabs .= '<button type="button" role="tab" id="' . esc_attr($tab_id) . '" aria-controls="' . esc_attr($panel_id) . '" data-feature-index="' . $index . '" aria-selected="' . ($index === 0 ? 'true' : 'false') . '" tabindex="' . ($index === 0 ? '0' : '-1') . '">' . esc_html((string) ($item['title'] ?? '')) . '</button>';
|
||||
$tabs .= '<button type="button" role="tab" data-feature-index="' . $index . '" aria-selected="' . ($index === 0 ? 'true' : 'false') . '">' . esc_html((string) ($item['title'] ?? '')) . '</button>';
|
||||
$features = '';
|
||||
foreach (RendererHelpers::lines((string) ($item['features'] ?? '')) as $feature) {
|
||||
$features .= '<li>' . esc_html($feature) . '</li>';
|
||||
}
|
||||
$panels .= '<article role="tabpanel" id="' . esc_attr($panel_id) . '" aria-labelledby="' . esc_attr($tab_id) . '" tabindex="0" data-feature-panel="' . $index . '"' . ($index ? ' hidden' : '') . '><div class="aksrt-feature-intro__media">' . RendererHelpers::card_media((array) $item) . '</div><div class="aksrt-feature-intro__copy"><h3>' . esc_html((string) ($item['title'] ?? '')) . '</h3><p>' . esc_html((string) ($item['description'] ?? '')) . '</p><ul>' . $features . '</ul></div></article>';
|
||||
$panels .= '<article role="tabpanel" data-feature-panel="' . $index . '"' . ($index ? ' hidden' : '') . '><div class="aksrt-feature-intro__media">' . RendererHelpers::card_media((array) $item) . '</div><div class="aksrt-feature-intro__copy"><h3>' . esc_html((string) ($item['title'] ?? '')) . '</h3><p>' . esc_html((string) ($item['description'] ?? '')) . '</p><ul>' . $features . '</ul></div></article>';
|
||||
}
|
||||
return '<div class="aksrt-feature-intro"><div class="aksrt-feature-intro__tabs" role="tablist" aria-label="' . esc_attr__('知识产品亮点', 'aksrt') . '">' . $tabs . '</div><div class="aksrt-feature-intro__panels">' . $panels . '</div></div>';
|
||||
return '<div class="aksrt-feature-intro"><div class="aksrt-feature-intro__tabs" role="tablist">' . $tabs . '</div><div class="aksrt-feature-intro__panels">' . $panels . '</div></div>';
|
||||
}
|
||||
|
||||
private static function tilt(array $i): string {
|
||||
|
||||
@@ -34,9 +34,8 @@ final class WidgetDefinition {
|
||||
$this->description = trim((string) ($definition['description'] ?? ''));
|
||||
$this->group = (string) ($definition['group'] ?? 'general');
|
||||
$this->renderer = (string) ($definition['renderer'] ?? $slug);
|
||||
$size = (string) ($definition['size'] ?? 'any');
|
||||
$this->size = in_array($size, ['any', 'wide', 'sidebar'], true)
|
||||
? $size
|
||||
$this->size = in_array(($definition['size'] ?? 'any'), ['any', 'wide', 'sidebar'], true)
|
||||
? (string) $definition['size']
|
||||
: 'any';
|
||||
$this->fields = array_values((array) ($definition['fields'] ?? []));
|
||||
$this->common = array_merge(
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace AKSRT\WidgetSystem;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/** Pure visibility rules shared by rendering and contract tests. */
|
||||
final class WidgetVisibility {
|
||||
public static function should_render(array $instance, ?int $current_id = null, ?bool $singular = null): bool {
|
||||
$type = (string) ($instance['show_id_type'] ?? '');
|
||||
$ids = RendererHelpers::ids((string) ($instance['show_ids'] ?? ''));
|
||||
if ($type === '' || !$ids) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($singular === null) {
|
||||
$singular = function_exists('is_singular') && is_singular();
|
||||
}
|
||||
if ($current_id === null) {
|
||||
$current_id = $singular && function_exists('get_queried_object_id') ? (int) get_queried_object_id() : 0;
|
||||
}
|
||||
$matched = $singular && in_array($current_id, $ids, true);
|
||||
return $type === 'show' ? $matched : !$matched;
|
||||
}
|
||||
|
||||
public static function device_class(array $instance): string {
|
||||
$type = (string) ($instance['show_type'] ?? 'all');
|
||||
if ($type === 'only_pc') {
|
||||
return 'aksrt-widget--only-pc';
|
||||
}
|
||||
return $type === 'only_sm' ? 'aksrt-widget--only-mobile' : '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user