feat(phase2): shared common-form layer + CommonWidgetFields trait for all widgets

- Extract Zibll CSF_Widget::params() common-field parity into
  inc/modules/widget-common.php (required by widgets-register.php to keep
  both files <1000 lines): subtitle, title_style(simple/big), title_highlight
  +color, title_link x3, title_link_style colors, sidebar_affix, show_type
  (all/only_pc/only_sm), show_id_type(show/hide), show_ids, animation_in,
  animation_repeat, layout_pin_pc/m, layout_bg(white/dark). Adds
  normalize_link/normalize_bg helpers, affix_attrs, common_wrapper_attr,
  render_title, animation_class. Back-compat normalizes legacy tokens
  (in_affix->sidebar_affix, pc/only_pc, include/exclude->show/hide).
- Add src/AKSRT/Widgets/Traits/CommonWidgetFields.php trait
  (render_common_form_section + update_common_fields).
- Wire all 57 widgets to use the trait; migrate the 16 hand-rolled in_affix
  implementations to shared sidebar_affix (fixes 6 latent bugs where
  in_affix was never persisted). SearchWidget intentionally skips the shared
  form section (its business show_type collides) but adopts the affix helper.
- widget_display_callback parity verified via tmp assertion script.

Refs .specs/plans/zibll-widgets-1to1.md Phase 2 (US1/US5)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-07-30 20:42:46 +08:00
parent 98aeee3cc1
commit d975ff4ce6
60 changed files with 1227 additions and 489 deletions
+12 -12
View File
@@ -30,12 +30,12 @@
### Done when
- [ ] `inc/helpers/aksrt-template-tags.php` 存在 `function aksrt_render_pagination(?WP_Query $query = null, array $args = []): void`,含 `numbered`(`.pagenav.ajax-pag.aksrt-pagination` + `paginate_links` + 跳转)与 `load_more`/`infinite`(`.aksrt-pagination-ajax` + `data-mode`/`data-query-vars`/`data-render-config`)两分支。
- [ ] `grep -n "display: block !important" assets/css/frontend/post-card.css` 不再出现在基础 `.posts-item` 规则块(行 28-46);`.posts-item.card` 的 `display: inline-block` 生效,可用浏览器/截图确认 3 列卡片网格(验证命令:`grep -A3 '.posts-item.card {' assets/css/frontend/post-card.css` 见 `display: inline-block`)。
- [ ] `archive-resources.php` 不再含 `posts-row ajaxpager` 手写容器与 `get_template_part('templates/parts/content', 'post-card')`,改为调用 `aksrt_render_post_list()` + `aksrt_render_pagination()`(`grep -n "aksrt_render_post_list\|get_template_part.*post-card" archive-resources.php` 确认)。
- [ ] `index.php:40`、`search.php:281`、`archive-resources.php` 的 `aksrt_render_pagination()` 调用所在文件在 `php -l` 下无未定义函数风险(函数已在 `aksrt-template-tags.php` 定义且通过 `inc/bootstrap.php` 加载链可达)。
- [ ] `php tools/audit-admin-contracts.php` 退出码 0(无新增 schema/REST 硬不一致)。
- [ ] 全部改动文件 ≤1000 行;超限已拆。
- [x] `inc/helpers/aksrt-template-tags.php` 存在 `function aksrt_render_pagination(?WP_Query $query = null, array $args = []): void`,含 `numbered`(`.pagenav.ajax-pag.aksrt-pagination` + `paginate_links` + 跳转)与 `load_more`/`infinite`(`.aksrt-pagination-ajax` + `data-mode`/`data-query-vars`/`data-render-config`)两分支。
- [x] `grep -n "display: block !important" assets/css/frontend/post-card.css` 不再出现在基础 `.posts-item` 规则块(行 28-46);`.posts-item.card` 的 `display: inline-block` 生效,可用浏览器/截图确认 3 列卡片网格(验证命令:`grep -A3 '.posts-item.card {' assets/css/frontend/post-card.css` 见 `display: inline-block`)。
- [x] `archive-resources.php` 不再含 `posts-row ajaxpager` 手写容器与 `get_template_part('templates/parts/content', 'post-card')`,改为调用 `aksrt_render_post_list()` + `aksrt_render_pagination()`(`grep -n "aksrt_render_post_list\|get_template_part.*post-card" archive-resources.php` 确认)。
- [x] `index.php:40`、`search.php:281`、`archive-resources.php` 的 `aksrt_render_pagination()` 调用所在文件在 `php -l` 下无未定义函数风险(函数已在 `aksrt-template-tags.php` 定义且通过 `inc/bootstrap.php` 加载链可达)。
- [x] `php tools/audit-admin-contracts.php` 退出码 0(无新增 schema/REST 硬不一致)。
- [x] 全部改动文件 ≤1000 行;超限已拆。
---
@@ -49,12 +49,12 @@
### Done when
- [ ] `inc/modules/widgets-register.php` 的 `aksrt_widget_common_defaults()` / `normalize_common()` / `render_common_form()` 覆盖上述全部字段(`grep -c "subtitle\|title_style\|title_highlight\|title_link\|show_type\|show_id_type\|sidebar_affix\|animation_in\|animation_repeat\|layout_bg" inc/modules/widgets-register.php` ≥ 预期命中)。
- [ ] 新增 `src/AKSRT/Widgets/Traits/CommonWidgetFields.php`(trait),封装 `render_common_form_section()` + `update_common_fields()`,`php -l` 通过。
- [ ] `grep -rL "CommonWidgetFields\|aksrt_widget_render_common_form" src/AKSRT/Widgets/*.php` 在所有**非纯展示/无表单**小工具上为空(即全部接入)。
- [ ] `grep -rln "in_affix" src/AKSRT/Widgets/*.php` 返回的文件数 = 0(局部重复实现已删除,逻辑全部经共享层 `sidebar_affix`)。
- [ ] `aksrt_filter_widget_display_by_area()`(`widget_display_callback`)读取的 `show_type`/`show_id_type`/`show_ids` 字段与共享层 `normalize_common()` 输出一致;任意小工具设置「仅 PC」在移动端 `widget_display_callback` 返回 `false`(可写一次性 PHP 断言脚本置于 `$CLAUDE_JOB_DIR/tmp` 验证,不入库)。
- [ ] `php tools/audit-admin-contracts.php` 退出码 0;改动文件 ≤1000 行。
- [x] `inc/modules/widgets-register.php` 的 `aksrt_widget_common_defaults()` / `normalize_common()` / `render_common_form()` 覆盖上述全部字段(`grep -c "subtitle\|title_style\|title_highlight\|title_link\|show_type\|show_id_type\|sidebar_affix\|animation_in\|animation_repeat\|layout_bg" inc/modules/widgets-register.php` ≥ 预期命中)。—— 实现已抽至 `inc/modules/widget-common.php`(由 widgets-register.php require),token 命中 115。
- [x] 新增 `src/AKSRT/Widgets/Traits/CommonWidgetFields.php`(trait),封装 `render_common_form_section()` + `update_common_fields()`,`php -l` 通过。
- [x] `grep -rL "CommonWidgetFields\|aksrt_widget_render_common_form" src/AKSRT/Widgets/*.php` 在所有**非纯展示/无表单**小工具上为空(即全部接入)。—— 全部 57 个小工具接入(WidgetProductOneline 经继承);SearchWidget 因业务 `show_type` 与共享 `show_type` 同名冲突,刻意不渲染共享表单段(已在代码注释说明),但已 `use` trait 并接入 `update_common_fields` + `aksrt_widget_affix_attrs`。
- [x] `grep -rln "in_affix" src/AKSRT/Widgets/*.php` 返回的文件数 = 0(局部重复实现已删除,逻辑全部经共享层 `sidebar_affix`)。
- [x] `aksrt_filter_widget_display_by_area()`(`widget_display_callback`)读取的 `show_type`/`show_id_type`/`show_ids` 字段与共享层 `normalize_common()` 输出一致;任意小工具设置「仅 PC」在移动端 `widget_display_callback` 返回 `false`(可写一次性 PHP 断言脚本置于 `$CLAUDE_JOB_DIR/tmp` 验证,不入库)。—— 断言脚本 `$CLAUDE_JOB_DIR/tmp/assert-display-parity.php` 全部通过(含 only_pc/only_sm/show/hide/legacy pc·include·exclude·in_affix 迁移)。
- [x] `php tools/audit-admin-contracts.php` 退出码 0;改动文件 ≤1000 行。
---
+638
View File
@@ -0,0 +1,638 @@
<?php
/**
* Shared widget common-form layer — Zibll CSF_Widget::params() parity.
*
* Extracted from widgets-register.php to keep each file under the 1000-line
* hard limit. Provides:
* - common field defaults / normalization (subtitle, title_style, highlight,
* 3 title links, sidebar_affix, show_type, show_id_type, animation, layout)
* - shared admin form renderer + update processor
* - wrapper class/attr builders (affix, animation, show-type, layout bg)
* - Zibll-aligned title block renderer (simple / big styles)
* - display-by-id gate consumed by widget_display_callback
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
// ============================================================
// Shared Widget Form Helper — 公共表单字段与显示规则
// ============================================================
if (!function_exists('aksrt_widget_common_defaults')) {
/**
* Default values for shared widget instance fields.
*
* Zibll CSF_Widget::params() common-field parity:
* subtitle, title_style, title_highlight, title_highlight_color,
* title_link (×3), title_link_style colors, sidebar_affix,
* show_type (all/only_pc/only_sm), show_id_type (show/hide), show_ids,
* animation_in, animation_repeat, layout_pin_pc/m, layout_bg (white/dark).
*
* @return array<string, mixed>
*/
function aksrt_widget_common_defaults(): array {
return [
'subtitle' => '',
'title_style' => '',
'title_highlight' => '',
'title_highlight_color'=> 'focus-color',
'title_link' => ['url' => '', 'text' => '', 'target' => ''],
'title_link2' => ['url' => '', 'text' => '', 'target' => ''],
'title_link3' => ['url' => '', 'text' => '', 'target' => ''],
'title_link_style' => ['color_1' => 'jb-blue', 'color_2' => 'jb-yellow', 'color_3' => 'jb-green'],
'sidebar_affix' => false,
'show_type' => 'all',
'show_id_type' => '',
'show_ids' => '',
'animation_in' => '',
'animation_repeat' => false,
'layout_pin_pc' => ['top' => '', 'bottom' => ''],
'layout_pin_m' => ['top' => '', 'bottom' => ''],
'layout_bg' => ['img_white' => [], 'img_dark' => []],
];
}
}
if (!function_exists('aksrt_widget_normalize_link')) {
/**
* Normalize a title_linkN array {url,text,target}.
*
* @param mixed $raw
* @return array{url:string,text:string,target:string}
*/
function aksrt_widget_normalize_link($raw): array {
$raw = is_array($raw) ? $raw : [];
return [
'url' => esc_url_raw(trim((string) ($raw['url'] ?? ''))),
'text' => sanitize_text_field((string) ($raw['text'] ?? '')),
'target' => ($raw['target'] ?? '') === '_blank' ? '_blank' : '',
];
}
}
if (!function_exists('aksrt_widget_normalize_common')) {
/**
* Normalize common widget instance fields, filling defaults for legacy instances.
*
* Accepts both the new structured shape (title_link as array) and legacy
* flat shapes (title_link as URL string, in_affix bool) emitted by older
* widget versions, normalizing them onto the canonical shared schema.
*
* @param array<string, mixed> $instance
* @return array<string, mixed>
*/
function aksrt_widget_normalize_common(array $instance): array {
$defaults = aksrt_widget_common_defaults();
$result = array_merge($defaults, $instance);
$result['subtitle'] = sanitize_text_field($result['subtitle'] ?? '');
$result['title_style'] = in_array($result['title_style'] ?? '', ['', 'big'], true) ? $result['title_style'] : '';
$result['title_highlight'] = sanitize_text_field($result['title_highlight'] ?? '');
$result['title_highlight_color'] = sanitize_html_class((string) ($result['title_highlight_color'] ?? 'focus-color'));
if ($result['title_highlight_color'] === '') {
$result['title_highlight_color'] = 'focus-color';
}
// Legacy flat title_link (URL string) → structured first link.
if (is_string($result['title_link'] ?? null)) {
$result['title_link'] = ['url' => esc_url_raw(trim($result['title_link'])), 'text' => '', 'target' => ''];
}
$result['title_link'] = aksrt_widget_normalize_link($result['title_link'] ?? []);
$result['title_link2'] = aksrt_widget_normalize_link($result['title_link2'] ?? []);
$result['title_link3'] = aksrt_widget_normalize_link($result['title_link3'] ?? []);
$tl_style = is_array($result['title_link_style'] ?? null) ? $result['title_link_style'] : [];
$result['title_link_style'] = [
'color_1' => sanitize_html_class((string) ($tl_style['color_1'] ?? 'jb-blue')) ?: 'jb-blue',
'color_2' => sanitize_html_class((string) ($tl_style['color_2'] ?? 'jb-yellow')) ?: 'jb-yellow',
'color_3' => sanitize_html_class((string) ($tl_style['color_3'] ?? 'jb-green')) ?: 'jb-green',
];
// show_type: accept both AKSRT legacy (pc/mobile) and Zibll (only_pc/only_sm) tokens.
$show_type = (string) ($result['show_type'] ?? 'all');
if ($show_type === 'only_pc' || $show_type === 'pc') {
$show_type = 'only_pc';
} elseif ($show_type === 'only_sm' || $show_type === 'mobile') {
$show_type = 'only_sm';
} else {
$show_type = 'all';
}
$result['show_type'] = $show_type;
// show_id_type: Zibll (show/hide) ↔ AKSRT legacy (include/exclude).
$id_type = (string) ($result['show_id_type'] ?? '');
if ($id_type === 'include') {
$id_type = 'show';
} elseif ($id_type === 'exclude') {
$id_type = 'hide';
} elseif (!in_array($id_type, ['', 'show', 'hide'], true)) {
$id_type = '';
}
$result['show_id_type'] = $id_type;
$result['show_ids'] = sanitize_text_field($result['show_ids'] ?? '');
$result['sidebar_affix'] = !empty($result['sidebar_affix']) || !empty($result['in_affix'] ?? false);
$result['animation_in'] = sanitize_key($result['animation_in'] ?? '');
$result['animation_repeat'] = !empty($result['animation_repeat']);
foreach (['layout_pin_pc', 'layout_pin_m'] as $pin_key) {
$pin = is_array($result[$pin_key] ?? null) ? $result[$pin_key] : [];
$result[$pin_key] = [
'top' => preg_match('/^-?\d+$/', (string) ($pin['top'] ?? '')) ? (string) (int) $pin['top'] : '',
'bottom' => preg_match('/^-?\d+$/', (string) ($pin['bottom'] ?? '')) ? (string) (int) $pin['bottom'] : '',
];
}
$bg = is_array($result['layout_bg'] ?? null) ? $result['layout_bg'] : [];
$result['layout_bg'] = [
'img_white' => aksrt_widget_normalize_bg($bg['img_white'] ?? []),
'img_dark' => aksrt_widget_normalize_bg($bg['img_dark'] ?? []),
];
return $result;
}
}
if (!function_exists('aksrt_widget_normalize_bg')) {
/**
* Normalize a layout_bg sub-block (background CSS props).
*
* @param mixed $raw
* @return array<string,string>
*/
function aksrt_widget_normalize_bg($raw): array {
$raw = is_array($raw) ? $raw : [];
$out = [];
foreach (['background-color', 'background-image', 'background-position', 'background-repeat', 'background-attachment', 'background-size', 'background-origin'] as $k) {
$v = trim((string) ($raw[$k] ?? ''));
if ($k === 'background-image' && $v !== '') {
$v = esc_url_raw($v);
} elseif ($k === 'background-color' && $v !== '') {
// Allow hex / rgb / rgba / named; strip tags defensively.
$v = sanitize_text_field($v);
} else {
$v = sanitize_text_field($v);
}
if ($v !== '') {
$out[$k] = $v;
}
}
return $out;
}
}
if (!function_exists('aksrt_widget_animation_options')) {
/**
* Zibll-aligned module entrance animation options.
*
* @return array<string,string>
*/
function aksrt_widget_animation_options(): array {
return [
'' => __('无动画', 'aksrt'),
'fade' => __('淡入', 'aksrt'),
'slideup' => __('从下往上滑出', 'aksrt'),
'slidedown' => __('从上往下滑出', 'aksrt'),
'slideright' => __('从左往右滑出', 'aksrt'),
'slideleft' => __('从右往左滑出', 'aksrt'),
'zoomin' => __('由小变大', 'aksrt'),
'zoomout' => __('由大变小', 'aksrt'),
];
}
}
if (!function_exists('aksrt_widget_highlight_color_options')) {
/**
* Highlight color palette (Zibll zib_palette parity, theme classes).
*
* @return array<string,string>
*/
function aksrt_widget_highlight_color_options(): array {
return [
'focus-color' => __('主题色', 'aksrt'),
'jb-blue' => __('渐变蓝', 'aksrt'),
'jb-green' => __('渐变绿', 'aksrt'),
'jb-yellow' => __('渐变黄', 'aksrt'),
'jb-orange' => __('渐变橙', 'aksrt'),
'jb-red' => __('渐变红', 'aksrt'),
'jb-purple' => __('渐变紫', 'aksrt'),
'jb-pink' => __('渐变粉', 'aksrt'),
'jb-cyan' => __('渐变青', 'aksrt'),
'c-blue' => __('蓝色', 'aksrt'),
'c-green' => __('绿色', 'aksrt'),
'c-red' => __('红色', 'aksrt'),
'c-yellow' => __('黄色', 'aksrt'),
'c-purple' => __('紫色', 'aksrt'),
];
}
}
if (!function_exists('aksrt_widget_render_link_field')) {
/**
* Render a single title-link sub-field (url/text/target) for the admin form.
*
* @param string $base Field base name, e.g. 'title_link'.
* @param array $link Normalized link {url,text,target}.
* @param string $label Field label.
*/
function aksrt_widget_render_link_field(string $base, array $link, string $label): void {
?>
<p>
<label><?php echo esc_html($label); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($base); ?>[text]" value="<?php echo esc_attr($link['text']); ?>" placeholder="<?php esc_attr_e('按钮文字', 'aksrt'); ?>">
</label>
<input class="widefat" type="url" name="<?php echo esc_attr($base); ?>[url]" value="<?php echo esc_attr($link['url']); ?>" placeholder="<?php esc_attr_e('链接地址', 'aksrt'); ?>">
<label><input type="checkbox" name="<?php echo esc_attr($base); ?>[target]" value="_blank" <?php checked($link['target'] === '_blank'); ?>> <?php esc_html_e('新窗口打开', 'aksrt'); ?></label>
</p>
<?php
}
}
if (!function_exists('aksrt_widget_render_common_form')) {
/**
* Render shared widget admin form fields.
*
* Call this from your widget's form() method. Renders the full Zibll
* common-field set: title block (subtitle / style / highlight / 3 links),
* sidebar affix, display rules, entrance animation, layout padding + bg.
*
* @param array<string, mixed> $instance Current widget instance.
*/
function aksrt_widget_render_common_form(array $instance): void {
$instance = aksrt_widget_normalize_common($instance);
$pin_pc = $instance['layout_pin_pc'];
$pin_m = $instance['layout_pin_m'];
$bg_w = $instance['layout_bg']['img_white'];
$bg_d = $instance['layout_bg']['img_dark'];
?>
<hr style="margin:16px 0 12px;border-color:#e0e0e0;">
<p style="font-size:12px;color:#666;margin-bottom:8px;font-weight:600;"><?php esc_html_e('标题与链接', 'aksrt'); ?></p>
<p>
<label><?php esc_html_e('副标题', 'aksrt'); ?>
<input class="widefat" type="text" name="subtitle" value="<?php echo esc_attr($instance['subtitle']); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('标题样式', 'aksrt'); ?></label>
<label><input type="radio" name="title_style" value="" <?php checked($instance['title_style'], ''); ?>> <?php esc_html_e('简约', 'aksrt'); ?></label>
<label><input type="radio" name="title_style" value="big" <?php checked($instance['title_style'], 'big'); ?>> <?php esc_html_e('居中大标题', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('标题选字高亮(标题中要被高亮的部分)', 'aksrt'); ?>
<input class="widefat" type="text" name="title_highlight" value="<?php echo esc_attr($instance['title_highlight']); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('高亮颜色', 'aksrt'); ?>
<select class="widefat" name="title_highlight_color">
<?php foreach (aksrt_widget_highlight_color_options() as $val => $lbl) : ?>
<option value="<?php echo esc_attr($val); ?>" <?php selected($instance['title_highlight_color'], $val); ?>><?php echo esc_html($lbl); ?></option>
<?php endforeach; ?>
</select>
</label>
</p>
<?php aksrt_widget_render_link_field('title_link', $instance['title_link'], __('标题链接', 'aksrt')); ?>
<?php if ($instance['title_style'] !== 'big') : ?>
<?php aksrt_widget_render_link_field('title_link2', $instance['title_link2'], __('标题链接 2', 'aksrt')); ?>
<?php aksrt_widget_render_link_field('title_link3', $instance['title_link3'], __('标题链接 3', 'aksrt')); ?>
<?php endif; ?>
<?php if ($instance['title_style'] === 'big') : ?>
<p>
<label><?php esc_html_e('链接样式(颜色1/2/3)', 'aksrt'); ?></label>
<select name="title_link_style[color_1]">
<?php foreach (aksrt_widget_highlight_color_options() as $val => $lbl) : ?>
<option value="<?php echo esc_attr($val); ?>" <?php selected($instance['title_link_style']['color_1'], $val); ?>><?php echo esc_html($lbl); ?></option>
<?php endforeach; ?>
</select>
<select name="title_link_style[color_2]">
<?php foreach (aksrt_widget_highlight_color_options() as $val => $lbl) : ?>
<option value="<?php echo esc_attr($val); ?>" <?php selected($instance['title_link_style']['color_2'], $val); ?>><?php echo esc_html($lbl); ?></option>
<?php endforeach; ?>
</select>
<select name="title_link_style[color_3]">
<?php foreach (aksrt_widget_highlight_color_options() as $val => $lbl) : ?>
<option value="<?php echo esc_attr($val); ?>" <?php selected($instance['title_link_style']['color_3'], $val); ?>><?php echo esc_html($lbl); ?></option>
<?php endforeach; ?>
</select>
</p>
<?php endif; ?>
<p style="font-size:12px;color:#666;margin:10px 0 8px;font-weight:600;"><?php esc_html_e('显示规则', 'aksrt'); ?></p>
<p>
<label><?php esc_html_e('显示设备', 'aksrt'); ?></label>
<label><input type="radio" name="show_type" value="all" <?php checked($instance['show_type'], 'all'); ?>> <?php esc_html_e('全部', 'aksrt'); ?></label>
<label><input type="radio" name="show_type" value="only_pc" <?php checked($instance['show_type'], 'only_pc'); ?>> <?php esc_html_e('仅 PC', 'aksrt'); ?></label>
<label><input type="radio" name="show_type" value="only_sm" <?php checked($instance['show_type'], 'only_sm'); ?>> <?php esc_html_e('仅移动端', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('按 ID 显示或隐藏', 'aksrt'); ?></label>
<label><input type="radio" name="show_id_type" value="" <?php checked($instance['show_id_type'], ''); ?>> <?php esc_html_e('不限制', 'aksrt'); ?></label>
<label><input type="radio" name="show_id_type" value="show" <?php checked($instance['show_id_type'], 'show'); ?>> <?php esc_html_e('指定 ID 显示', 'aksrt'); ?></label>
<label><input type="radio" name="show_id_type" value="hide" <?php checked($instance['show_id_type'], 'hide'); ?>> <?php esc_html_e('指定 ID 隐藏', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('文章/页面 ID(逗号分隔)', 'aksrt'); ?>
<input class="widefat" type="text" name="show_ids" value="<?php echo esc_attr($instance['show_ids']); ?>" placeholder="1,2,3">
</label>
</p>
<p>
<label><input type="checkbox" name="sidebar_affix" value="1" <?php checked($instance['sidebar_affix']); ?>> <?php esc_html_e('侧栏吸顶(仅侧栏有效)', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('入场动画', 'aksrt'); ?>
<select class="widefat" name="animation_in">
<?php foreach (aksrt_widget_animation_options() as $val => $lbl) : ?>
<option value="<?php echo esc_attr($val); ?>" <?php selected($instance['animation_in'], $val); ?>><?php echo esc_html($lbl); ?></option>
<?php endforeach; ?>
</select>
</label>
</p>
<p>
<label><input type="checkbox" name="animation_repeat" value="1" <?php checked($instance['animation_repeat']); ?>> <?php esc_html_e('动画重复播放', 'aksrt'); ?></label>
</p>
<p style="font-size:12px;color:#666;margin:10px 0 8px;font-weight:600;"><?php esc_html_e('布局:间距与背景', 'aksrt'); ?></p>
<p>
<label><?php esc_html_e('PC 端额外上/下间距 (px)', 'aksrt'); ?>
<input class="tiny-text" type="number" name="layout_pin_pc[top]" value="<?php echo esc_attr($pin_pc['top']); ?>" placeholder="0">
<input class="tiny-text" type="number" name="layout_pin_pc[bottom]" value="<?php echo esc_attr($pin_pc['bottom']); ?>" placeholder="0">
</label>
</p>
<p>
<label><?php esc_html_e('移动端额外上/下间距 (px)', 'aksrt'); ?>
<input class="tiny-text" type="number" name="layout_pin_m[top]" value="<?php echo esc_attr($pin_m['top']); ?>" placeholder="0">
<input class="tiny-text" type="number" name="layout_pin_m[bottom]" value="<?php echo esc_attr($pin_m['bottom']); ?>" placeholder="0">
</label>
</p>
<p>
<label><?php esc_html_e('日间背景色', 'aksrt'); ?>
<input class="widefat" type="text" name="layout_bg[img_white][background-color]" value="<?php echo esc_attr($bg_w['background-color'] ?? ''); ?>">
</label>
<label><?php esc_html_e('日间背景图', 'aksrt'); ?>
<input class="widefat" type="url" name="layout_bg[img_white][background-image]" value="<?php echo esc_attr($bg_w['background-image'] ?? ''); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('夜间背景色', 'aksrt'); ?>
<input class="widefat" type="text" name="layout_bg[img_dark][background-color]" value="<?php echo esc_attr($bg_d['background-color'] ?? ''); ?>">
</label>
<label><?php esc_html_e('夜间背景图', 'aksrt'); ?>
<input class="widefat" type="url" name="layout_bg[img_dark][background-image]" value="<?php echo esc_attr($bg_d['background-image'] ?? ''); ?>">
</label>
</p>
<?php
}
}
if (!function_exists('aksrt_widget_update_common')) {
/**
* Process shared widget form fields in update().
*
* @param array<string, mixed> $new_instance
* @param array<string, mixed> $old_instance
* @return array<string, mixed>
*/
function aksrt_widget_update_common(array $new_instance, array $old_instance): array {
$merged = array_merge($old_instance, $new_instance);
return aksrt_widget_normalize_common($merged);
}
}
if (!function_exists('aksrt_widget_render_common_before')) {
/**
* Build common wrapper classes/attrs for a widget instance.
*
* Zibll CSF_Widget::wrap_attributes() parity: show-type class, sidebar
* affix data-affix, entrance animation class, layout padding/bg CSS vars.
* Call this at the start of widget() before rendering content.
*
* @param array $args Sidebar args.
* @param array $instance Widget instance.
* @return array<int,string> CSS class names (Zibll show_class style).
*/
function aksrt_widget_get_common_wrapper_classes(array $args, array $instance): array {
$instance = aksrt_widget_normalize_common($instance);
$classes = [];
// Show type: PC or mobile (Zibll hidden-xs / visible-xs-block).
if ($instance['show_type'] === 'only_pc') {
$classes[] = 'hidden-xs';
} elseif ($instance['show_type'] === 'only_sm') {
$classes[] = 'visible-xs-block';
}
// Sidebar affix
if ($instance['sidebar_affix']) {
$classes[] = 'is-affix';
}
// Animation (Zibll obs-animate ani-*).
if ($instance['animation_in'] !== '') {
$classes[] = 'obs-animate';
$classes[] = 'ani-' . $instance['animation_in'];
if ($instance['animation_repeat']) {
$classes[] = 'obs-animate-repeat';
}
}
return $classes;
}
}
if (!function_exists('aksrt_widget_common_wrapper_attr')) {
/**
* Build the full wrapper attribute string (class + style + data-affix) for
* the Zibll .zib-widget-wrap parity layer.
*
* Combine with a widget-specific class via a leading space, or use as-is.
*
* @param array<string,mixed> $instance Widget instance.
* @param string $extra_class Additional class (widget-specific).
* @return string Escaped attribute string beginning with a leading space, e.g. ' class="…" style="…" data-affix="true"'.
*/
function aksrt_widget_common_wrapper_attr(array $instance, string $extra_class = ''): string {
$instance = aksrt_widget_normalize_common($instance);
$classes = ['zib-widget-wrap'];
foreach (aksrt_widget_get_common_wrapper_classes([], $instance) as $c) {
$classes[] = $c;
}
$extra_class = trim($extra_class);
if ($extra_class !== '') {
$classes[] = $extra_class;
}
$styles = [];
if ($instance['layout_pin_pc']['top'] !== '') {
$styles[] = '--pt-pc:' . (int) $instance['layout_pin_pc']['top'] . 'px;';
}
if ($instance['layout_pin_pc']['bottom'] !== '') {
$styles[] = '--pb-pc:' . (int) $instance['layout_pin_pc']['bottom'] . 'px;';
}
if ($instance['layout_pin_m']['top'] !== '') {
$styles[] = '--pt-m:' . (int) $instance['layout_pin_m']['top'] . 'px;';
}
if ($instance['layout_pin_m']['bottom'] !== '') {
$styles[] = '--pb-m:' . (int) $instance['layout_pin_m']['bottom'] . 'px;';
}
foreach (['white' => 'img_white', 'dark' => 'img_dark'] as $mode => $bg_key) {
$bg = $instance['layout_bg'][$bg_key] ?? [];
if (!empty($bg['background-color'])) {
$styles[] = '--bg-color-' . $mode . ':' . $bg['background-color'] . ';';
}
if (!empty($bg['background-image'])) {
$styles[] = '--bg-img-' . $mode . ':url("' . $bg['background-image'] . '");';
}
}
$attr = ' class="' . esc_attr(implode(' ', $classes)) . '"';
if ($styles) {
$attr .= ' style="' . esc_attr(implode('', $styles)) . '"';
}
if ($instance['sidebar_affix']) {
$attr .= ' data-affix="true"';
}
return $attr;
}
}
if (!function_exists('aksrt_widget_affix_attrs')) {
/**
* Compact affix class+attribute helper for widgets that apply affix onto an
* inner wrapper (the two-family pattern from the legacy in_affix widgets).
*
* @param array<string,mixed> $instance Widget instance.
* @return array{class:string,attr:string} class includes leading space when active; attr includes leading space.
*/
function aksrt_widget_affix_attrs(array $instance): array {
$instance = aksrt_widget_normalize_common($instance);
if (empty($instance['sidebar_affix'])) {
return ['class' => '', 'attr' => ''];
}
return ['class' => ' is-affix', 'attr' => ' data-affix="true"'];
}
}
if (!function_exists('aksrt_widget_render_title')) {
/**
* Render the Zibll-aligned widget title block (CSF_Widget::show_title parity).
*
* Two styles:
* - '' (简约): .box-body notop > .title-theme with optional subtitle + more link
* - 'big' (居中大标题): .big-title-wrap with up to 3 button links
*
* Highlight wraps the matched substring in a colored span.
*
* @param array<string,mixed> $instance Widget instance.
* @return string Title HTML (empty when no title).
*/
function aksrt_widget_render_title(array $instance): string {
$instance = aksrt_widget_normalize_common($instance);
$title = trim((string) ($instance['title'] ?? ''));
if ($title === '') {
return '';
}
$highlight = trim((string) $instance['title_highlight']);
$subtitle = (string) $instance['subtitle'];
$anim = function_exists('aksrt_widget_animation_class')
? aksrt_widget_animation_class($instance)
: '';
$title = esc_html($title);
if ($highlight !== '' && $highlight !== $title) {
$color = $instance['title_highlight_color'];
$hl_esc = esc_html($highlight);
$title = str_replace($hl_esc, '<span class="title-highlight ' . esc_attr($color) . '">' . $hl_esc . '</span>', $title);
}
if ($instance['title_style'] === 'big') {
$style = $instance['title_link_style'];
$links = '';
foreach (['title_link' => 'color_1', 'title_link2' => 'color_2', 'title_link3' => 'color_3'] as $key => $color_key) {
$link = $instance[$key];
if ($link['url'] !== '' && $link['text'] !== '') {
$blank = $link['target'] === '_blank' ? ' target="_blank"' : '';
$links .= '<a' . $blank . ' href="' . esc_url($link['url']) . '" class="but ' . esc_attr($style[$color_key]) . '">' . esc_html($link['text']) . '</a>';
}
}
$links = $links !== '' ? '<div class="flex jc big-title-buts' . $anim . '">' . $links . '</div>' : '';
$sub = $subtitle !== '' ? '<p class="big-title-sub muted-2-color' . $anim . '">' . esc_html($subtitle) . '</p>' : '';
return '<div class="big-title-wrap"><h2 class="big-title' . $anim . '">' . $title . '</h2>' . $sub . $links . '</div>';
}
// Simple style.
$link = $instance['title_link'];
$sub = $subtitle !== '' ? '<small class="ml10">' . esc_html($subtitle) . '</small>' : '';
$more = '';
if ($link['url'] !== '') {
$text = $link['text'] !== '' ? $link['text'] : '<i class="fa fa-angle-right fa-fw"></i>' . __('更多', 'aksrt');
$blank = $link['target'] === '_blank' ? ' target="_blank"' : '';
$more = '<div class="pull-right em09 mt3"><a' . $blank . ' href="' . esc_url($link['url']) . '" class="muted-2-color">' . wp_kses_post($text) . '</a></div>';
}
return '<div class="box-body notop' . $anim . '"><div class="title-theme">' . $title . $sub . $more . '</div></div>';
}
}
if (!function_exists('aksrt_widget_animation_class')) {
/**
* Zibll CSF_Widget::animation_class parity: obs-animate ani-* [+repeat].
*
* @param array<string,mixed> $instance Normalized widget instance.
* @param bool $is_title Reserved for title-specific animation.
* @return string
*/
function aksrt_widget_animation_class(array $instance, bool $is_title = false): string {
$animation = (string) ($instance['animation_in'] ?? '');
if ($animation === '') {
return '';
}
$class = ' obs-animate ani-' . $animation;
if (!empty($instance['animation_repeat'])) {
$class .= ' obs-animate-repeat';
}
return $class;
}
}
if (!function_exists('aksrt_widget_should_display_by_ids')) {
/**
* Check if the current post/page should display the widget based on show_id_type and show_ids.
*
* show_id_type tokens: '' (no limit) | 'show' (whitelist) | 'hide' (blacklist).
* Accepts legacy 'include'/'exclude' via normalize_common.
*
* @param array $instance Widget instance.
* @return bool
*/
function aksrt_widget_should_display_by_ids(array $instance): bool {
$instance = aksrt_widget_normalize_common($instance);
if ($instance['show_id_type'] === '' || $instance['show_ids'] === '') {
return true;
}
$current_id = get_the_ID();
if (!$current_id) {
return true; // Not on a singular page, allow display
}
// Zibll splits on comma/Chinese-comma/whitespace/newline.
$ids = array_filter(array_map('absint', preg_split('/[,,\s]+/', $instance['show_ids']) ?: []));
if ($instance['show_id_type'] === 'show') {
return in_array($current_id, $ids, true);
}
if ($instance['show_id_type'] === 'hide') {
return !in_array($current_id, $ids, true);
}
return true;
}
}
+5 -205
View File
@@ -7,6 +7,8 @@
defined('ABSPATH') || exit;
require_once AKSRT_DIR . '/inc/modules/widget-common.php';
/**
* Register custom widgets.
*/
@@ -307,208 +309,6 @@ if (!function_exists('aksrt_widget_get_area_context')) {
}
}
// ============================================================
// Shared Widget Form Helper — 公共表单字段与显示规则
// ============================================================
if (!function_exists('aksrt_widget_common_defaults')) {
/**
* Default values for shared widget instance fields.
*
* @return array<string, mixed>
*/
function aksrt_widget_common_defaults(): array {
return [
'subtitle' => '',
'title_link' => '',
'show_type' => 'all',
'show_id_type' => '',
'show_ids' => '',
'sidebar_affix' => false,
'animation_in' => '',
'animation_repeat'=> false,
];
}
}
if (!function_exists('aksrt_widget_normalize_common')) {
/**
* Normalize common widget instance fields, filling defaults for legacy instances.
*
* @param array<string, mixed> $instance
* @return array<string, mixed>
*/
function aksrt_widget_normalize_common(array $instance): array {
$defaults = aksrt_widget_common_defaults();
$result = array_merge($defaults, $instance);
$result['subtitle'] = sanitize_text_field($result['subtitle'] ?? '');
$result['title_link'] = esc_url_raw($result['title_link'] ?? '');
$result['show_type'] = in_array($result['show_type'] ?? '', ['all', 'pc', 'mobile'], true) ? $result['show_type'] : 'all';
$result['show_id_type'] = in_array($result['show_id_type'] ?? '', ['', 'include', 'exclude'], true) ? $result['show_id_type'] : '';
$result['show_ids'] = sanitize_text_field($result['show_ids'] ?? '');
$result['sidebar_affix'] = !empty($result['sidebar_affix']);
$result['animation_in'] = sanitize_key($result['animation_in'] ?? '');
$result['animation_repeat']= !empty($result['animation_repeat']);
return $result;
}
}
if (!function_exists('aksrt_widget_render_common_form')) {
/**
* Render shared widget admin form fields.
*
* Call this from your widget's form() method after rendering custom fields.
*
* @param array<string, mixed> $instance Current widget instance.
*/
function aksrt_widget_render_common_form(array $instance): void {
$instance = aksrt_widget_normalize_common($instance);
?>
<hr style="margin:16px 0 12px;border-color:#e0e0e0;">
<p style="font-size:12px;color:#666;margin-bottom:8px;font-weight:600;"><?php esc_html_e('显示规则', 'aksrt'); ?></p>
<p>
<label for="<?php echo esc_attr($instance['show_type_id'] ?? ''); ?>"><?php esc_html_e('显示设备', 'aksrt'); ?></label><br>
<select name="<?php echo esc_attr($instance['show_type_name'] ?? 'show_type'); ?>" id="<?php echo esc_attr($instance['show_type_id'] ?? ''); ?>" class="widefat">
<option value="all" <?php selected($instance['show_type'], 'all'); ?>><?php esc_html_e('全部', 'aksrt'); ?></option>
<option value="pc" <?php selected($instance['show_type'], 'pc'); ?>><?php esc_html_e('仅 PC', 'aksrt'); ?></option>
<option value="mobile" <?php selected($instance['show_type'], 'mobile'); ?>><?php esc_html_e('仅移动端', 'aksrt'); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr($instance['show_id_type_id'] ?? ''); ?>"><?php esc_html_e('ID 显示规则', 'aksrt'); ?></label><br>
<select name="<?php echo esc_attr($instance['show_id_type_name'] ?? 'show_id_type'); ?>" id="<?php echo esc_attr($instance['show_id_type_id'] ?? ''); ?>" class="widefat">
<option value="" <?php selected($instance['show_id_type'], ''); ?>><?php esc_html_e('不限制', 'aksrt'); ?></option>
<option value="include" <?php selected($instance['show_id_type'], 'include'); ?>><?php esc_html_e('仅指定 ID 显示', 'aksrt'); ?></option>
<option value="exclude" <?php selected($instance['show_id_type'], 'exclude'); ?>><?php esc_html_e('指定 ID 隐藏', 'aksrt'); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr($instance['show_ids_id'] ?? ''); ?>"><?php esc_html_e('文章/页面 ID', 'aksrt'); ?></label><br>
<input type="text" name="<?php echo esc_attr($instance['show_ids_name'] ?? 'show_ids'); ?>" id="<?php echo esc_attr($instance['show_ids_id'] ?? ''); ?>" class="widefat" value="<?php echo esc_attr($instance['show_ids']); ?>" placeholder="<?php esc_attr_e('逗号分隔,如: 1,2,3', 'aksrt'); ?>">
</p>
<p>
<label>
<input type="checkbox" name="<?php echo esc_attr($instance['sidebar_affix_name'] ?? 'sidebar_affix'); ?>" value="1" <?php checked($instance['sidebar_affix']); ?>>
<?php esc_html_e('侧栏吸顶', 'aksrt'); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr($instance['animation_in_id'] ?? ''); ?>"><?php esc_html_e('入场动画', 'aksrt'); ?></label><br>
<select name="<?php echo esc_attr($instance['animation_in_name'] ?? 'animation_in'); ?>" id="<?php echo esc_attr($instance['animation_in_id'] ?? ''); ?>" class="widefat">
<option value="" <?php selected($instance['animation_in'], ''); ?>><?php esc_html_e('无', 'aksrt'); ?></option>
<option value="fadeIn" <?php selected($instance['animation_in'], 'fadeIn'); ?>><?php esc_html_e('淡入', 'aksrt'); ?></option>
<option value="fadeInUp" <?php selected($instance['animation_in'], 'fadeInUp'); ?>><?php esc_html_e('上移淡入', 'aksrt'); ?></option>
<option value="fadeInDown" <?php selected($instance['animation_in'], 'fadeInDown'); ?>><?php esc_html_e('下移淡入', 'aksrt'); ?></option>
<option value="fadeInLeft" <?php selected($instance['animation_in'], 'fadeInLeft'); ?>><?php esc_html_e('左移淡入', 'aksrt'); ?></option>
<option value="fadeInRight" <?php selected($instance['animation_in'], 'fadeInRight'); ?>><?php esc_html_e('右移淡入', 'aksrt'); ?></option>
<option value="zoomIn" <?php selected($instance['animation_in'], 'zoomIn'); ?>><?php esc_html_e('缩放进入', 'aksrt'); ?></option>
</select>
</p>
<p>
<label>
<input type="checkbox" name="<?php echo esc_attr($instance['animation_repeat_name'] ?? 'animation_repeat'); ?>" value="1" <?php checked($instance['animation_repeat']); ?>>
<?php esc_html_e('动画重复播放', 'aksrt'); ?>
</label>
</p>
<?php
}
}
if (!function_exists('aksrt_widget_update_common')) {
/**
* Process shared widget form fields in update().
*
* @param array<string, mixed> $new_instance
* @param array<string, mixed> $old_instance
* @return array<string, mixed>
*/
function aksrt_widget_update_common(array $new_instance, array $old_instance): array {
$merged = array_merge($old_instance, $new_instance);
return aksrt_widget_normalize_common($merged);
}
}
if (!function_exists('aksrt_widget_render_common_before')) {
/**
* Render common wrapper attributes and classes before widget content.
*
* Outputs CSS classes for animation, affix, show_type, etc.
* Call this at the start of widget() before rendering content.
*
* @param array $args Sidebar args.
* @param array $instance Widget instance.
* @return array Modified args with extra classes.
*/
function aksrt_widget_get_common_wrapper_classes(array $args, array $instance): array {
$instance = aksrt_widget_normalize_common($instance);
$classes = [];
// Show type: PC or mobile
if ($instance['show_type'] === 'pc') {
$classes[] = 'aksrt-widget--pc-only';
} elseif ($instance['show_type'] === 'mobile') {
$classes[] = 'aksrt-widget--mobile-only';
}
// Sidebar affix
if ($instance['sidebar_affix']) {
$classes[] = 'aksrt-widget--affix';
}
// Animation
if ($instance['animation_in'] !== '') {
$classes[] = 'aksrt-widget--animated';
$classes[] = 'aksrt-anim-' . $instance['animation_in'];
if ($instance['animation_repeat']) {
$classes[] = 'aksrt-anim-repeat';
}
}
return $classes;
}
}
if (!function_exists('aksrt_widget_should_display_by_ids')) {
/**
* Check if the current post/page should display the widget based on show_id_type and show_ids.
*
* @param array $instance Widget instance.
* @return bool
*/
function aksrt_widget_should_display_by_ids(array $instance): bool {
$instance = aksrt_widget_normalize_common($instance);
if ($instance['show_id_type'] === '' || $instance['show_ids'] === '') {
return true;
}
$current_id = get_the_ID();
if (!$current_id) {
return true; // Not on a singular page, allow display
}
$ids = array_filter(array_map('absint', explode(',', $instance['show_ids'])));
if ($instance['show_id_type'] === 'include') {
return in_array($current_id, $ids, true);
}
if ($instance['show_id_type'] === 'exclude') {
return !in_array($current_id, $ids, true);
}
return true;
}
}
if (!function_exists('aksrt_widget_render_location_help')) {
/**
* Render placement hint inside widget admin forms.
@@ -559,11 +359,11 @@ if (!function_exists('aksrt_filter_widget_display_by_area')) {
if (is_array($instance) && function_exists('aksrt_widget_normalize_common')) {
$normalized = aksrt_widget_normalize_common($instance);
// Show type: PC / mobile filter
if ($normalized['show_type'] === 'pc' && wp_is_mobile()) {
// Show type: PC / mobile filter (Zibll only_pc / only_sm).
if ($normalized['show_type'] === 'only_pc' && wp_is_mobile()) {
return false;
}
if ($normalized['show_type'] === 'mobile' && !wp_is_mobile()) {
if ($normalized['show_type'] === 'only_sm' && !wp_is_mobile()) {
return false;
}
+8 -3
View File
@@ -5,9 +5,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class AboutWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -367,12 +371,13 @@ class AboutWidget extends \WP_Widget {
<?php esc_html_e('留空则使用默认背景图。已登录用户可使用个人封面图。', 'aksrt'); ?>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'cover' => esc_url_raw($new_instance['cover'] ?? ''),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class ButtonsWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct('aksrt_buttons', esc_html__('AKSRT 按钮组', 'aksrt'), [
@@ -213,7 +217,8 @@ class ButtonsWidget extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name("buttons[{$i}][new_window]")); ?>" value="1" <?php checked(!empty($btn['new_window'])); ?>> <?php esc_html_e('新窗口', 'aksrt'); ?></label>
</div>
<?php endforeach;
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -244,7 +249,7 @@ class ButtonsWidget extends \WP_Widget {
}
}
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'align' => in_array(($new_instance['align'] ?? ''), ['left', 'center', 'right'], true) ? $new_instance['align'] : 'center',
'radius' => !empty($new_instance['radius']) ? 1 : 0,
@@ -256,6 +261,6 @@ class ButtonsWidget extends \WP_Widget {
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
'animation_repeat'=> !empty($new_instance['animation_repeat']) ? 1 : 0,
'buttons' => $buttons,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+10 -10
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class CategoriesWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -176,12 +179,12 @@ class CategoriesWidget extends \WP_Widget {
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$in_affix = !empty($instance['in_affix']);
if ($in_affix) {
echo '<div class="is-affix" data-affix="true">';
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
if ($affix['class'] !== '') {
echo '<div class="is-affix"' . $affix['attr'] . '>';
}
echo self::render_html($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ($in_affix) {
if ($affix['class'] !== '') {
echo '</div>';
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -238,9 +241,7 @@ class CategoriesWidget extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_empty')); ?>" value="1" <?php checked(!isset($instance['hide_empty']) || !empty($instance['hide_empty'])); ?>> <?php esc_html_e('隐藏空分类', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hierarchical')); ?>" value="1" <?php checked(!empty($instance['hierarchical'])); ?>> <?php esc_html_e('层级树', 'aksrt'); ?></label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -254,7 +255,7 @@ class CategoriesWidget extends \WP_Widget {
if (!in_array($orderby, ['count', 'name', 'id', 'slug'], true)) {
$orderby = 'count';
}
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(50, (int) ($new_instance['count'] ?? 8))),
'orderby' => $orderby,
@@ -267,7 +268,6 @@ class CategoriesWidget extends \WP_Widget {
'show_thumb' => !empty($new_instance['show_thumb']) ? 1 : 0,
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
'hierarchical' => !empty($new_instance['hierarchical']) ? 1 : 0,
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
];
]);
}
}
+8 -3
View File
@@ -5,6 +5,8 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
/**
@@ -311,6 +313,8 @@ if (!function_exists('aksrt_home_widget_get_lazyload_args')) {
* Homepage category block widget.
*/
class CategoryBlockWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -486,10 +490,11 @@ class CategoryBlockWidget extends \WP_Widget {
</p>
<?php if (function_exists('aksrt_widget_render_location_help')) { aksrt_widget_render_location_help('hybrid'); } ?>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'category_id' => absint($new_instance['category_id'] ?? 0),
'count' => max(1, min(12, absint($new_instance['count'] ?? 6))),
@@ -497,7 +502,7 @@ class CategoryBlockWidget extends \WP_Widget {
'layout' => aksrt_home_widget_resolve_layout($new_instance['layout'] ?? 'card', 'card'),
'show_more' => ! empty($new_instance['show_more']) ? 1 : 0,
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'none')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'none')) : 'none',
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
public static function resolve_category_id_static(array $instance): int {
@@ -5,12 +5,16 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
/**
* Homepage category recommend cards widget.
*/
class CategoryRecommendWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -194,10 +198,11 @@ class CategoryRecommendWidget extends \WP_Widget {
</p>
<?php if (function_exists('aksrt_widget_render_location_help')) { aksrt_widget_render_location_help('homepage'); } ?>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'category_ids' => aksrt_home_widget_normalize_category_ids($new_instance['category_ids'] ?? [], 4),
'posts_per_category' => max(1, min(8, absint($new_instance['posts_per_category'] ?? 5))),
@@ -206,7 +211,7 @@ class CategoryRecommendWidget extends \WP_Widget {
'show_description' => ! empty($new_instance['show_description']) ? 1 : 0,
'show_dates' => ! empty($new_instance['show_dates']) ? 1 : 0,
'show_more' => ! empty($new_instance['show_more']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
/**
+8 -3
View File
@@ -5,12 +5,16 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
/**
* Homepage category tabs widget.
*/
class CategoryTabsWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -157,17 +161,18 @@ public function form($instance): void {
</p>
<?php if (function_exists('aksrt_widget_render_location_help')) { aksrt_widget_render_location_help('hybrid'); } ?>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'category_ids' => aksrt_home_widget_normalize_category_ids($new_instance['category_ids'] ?? [], 6),
'count' => max(1, min(12, absint($new_instance['count'] ?? 6))),
'columns' => max(1, min(4, absint($new_instance['columns'] ?? 3))),
'layout' => aksrt_home_widget_resolve_layout($new_instance['layout'] ?? 'card', 'card'),
'show_more' => ! empty($new_instance['show_more']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
/**
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class CustomHtmlGapWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct('aksrt_custom_html_gap', esc_html__('AKSRT 自定义HTML/间距', 'aksrt'), [
@@ -90,7 +94,8 @@ class CustomHtmlGapWidget extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('full_width')); ?>" value="1" <?php checked(!empty($instance['full_width'])); ?>> <?php esc_html_e('HTML 通栏', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -98,13 +103,13 @@ class CustomHtmlGapWidget extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
$business = [
'mode' => in_array(($new_instance['mode'] ?? ''), ['html', 'gap'], true) ? $new_instance['mode'] : 'html',
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'content' => wp_kses_post((string) ($new_instance['content'] ?? '')),
'gap_height' => max(0, min(500, (int) ($new_instance['gap_height'] ?? 20))),
'gap_height_m' => max(0, min(500, (int) ($new_instance['gap_height_m'] ?? $new_instance['gap_height'] ?? 20))),
'full_width' => !empty($new_instance['full_width']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -2
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class FriendLinksWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct('aksrt_friend_links', esc_html__('AKSRT 友情链接', 'aksrt'), [
@@ -155,7 +159,8 @@ class FriendLinksWidget extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_box')); ?>" value="1" <?php checked(!isset($instance['show_box']) || !empty($instance['show_box'])); ?>> <?php esc_html_e('外框盒子', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -167,7 +172,7 @@ class FriendLinksWidget extends \WP_Widget {
if (!in_array($type, ['card', 'bigcard', 'image', 'simple'], true)) {
$type = 'card';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'source' => ($new_instance['source'] ?? '') === 'bookmarks' ? 'bookmarks' : 'settings',
'type' => $type,
@@ -183,5 +188,6 @@ class FriendLinksWidget extends \WP_Widget {
'columns' => max(1, min(4, (int) ($new_instance['columns'] ?? 2))),
'show_icon' => !empty($new_instance['show_icon']) ? 1 : 0,
];
return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+10 -8
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class HotPostsWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -204,12 +207,12 @@ class HotPostsWidget extends \WP_Widget {
if ($title) {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$instance['paginate'] = sanitize_key((string) ($instance['paginate'] ?? 'ajax'));
$payload = self::query_payload($instance, 1);
$rest = rest_url('aksrt/v1/widgets/hot-posts');
$wrap = 'ajaxpager' . ($in_affix ? ' is-affix' : '');
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . ($in_affix ? ' data-affix="true"' : '') . '>';
$wrap = 'ajaxpager' . $affix['class'];
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . $affix['attr'] . '>';
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="post_ajax_loader" data-aksrt-ajax-loader data-aksrt-ajax-loader-hide hidden></div>';
@@ -246,8 +249,7 @@ class HotPostsWidget extends \WP_Widget {
<input class="tiny-text" id="<?php echo esc_attr($this->get_field_id('days')); ?>" name="<?php echo esc_attr($this->get_field_name('days')); ?>" type="number" min="0" max="365" value="<?php echo (int) $days; ?>">
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_thumb')); ?>" value="1" <?php checked(!empty($instance['show_thumb'])); ?>> <?php esc_html_e('显示缩略图', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_thumb')); ?>" value="1" <?php checked(!empty($instance['show_thumb'])); ?>> <?php esc_html_e('显示缩略图', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('分页', 'aksrt'); ?>
@@ -258,18 +260,18 @@ class HotPostsWidget extends \WP_Widget {
</select>
</label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'count' => absint($new_instance['count'] ?? 5),
'order_by' => in_array($new_instance['order_by'] ?? '', ['views', 'comments', 'likes', 'favorites', 'downloads'], true) ? $new_instance['order_by'] : 'views',
'days' => absint($new_instance['days'] ?? 30),
'show_thumb' => !empty($new_instance['show_thumb']) ? 1 : 0,
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class IconCardsWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct('aksrt_icon_cards', esc_html__('AKSRT 图标卡片', 'aksrt'), [
@@ -193,7 +197,8 @@ class IconCardsWidget extends \WP_Widget {
<input class="widefat" type="url" name="<?php echo esc_attr($this->get_field_name("cards[{$i}][url]")); ?>" value="<?php echo esc_attr((string) ($card['url'] ?? '')); ?>" placeholder="<?php esc_attr_e('链接', 'aksrt'); ?>">
</div>
<?php endforeach;
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -201,7 +206,7 @@ class IconCardsWidget extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'columns' => max(1, min(6, (int) ($new_instance['columns'] ?? 2))),
'm_row' => max(1, min(4, (int) ($new_instance['m_row'] ?? 2))),
@@ -210,6 +215,6 @@ class IconCardsWidget extends \WP_Widget {
'icon_radius' => !empty($new_instance['icon_radius']) ? 1 : 0,
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
'cards' => $this->normalize($new_instance['cards'] ?? []),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+10 -11
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class NoticeWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct('aksrt_notice', esc_html__('AKSRT 滚动公告', 'aksrt'), [
@@ -36,7 +39,7 @@ if (!$items) {
$radius = !empty($instance['radius']);
$interval = max(2, min(15, (int) ($instance['interval'] ?? 4)));
$align = sanitize_html_class((string) ($instance['alignment'] ?? ''));
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
@@ -51,12 +54,9 @@ if (!$items) {
if ($align !== '') {
$wrap_cls .= ' ' . $align;
}
if ($in_affix) {
$wrap_cls .= ' is-affix';
}
$wrap_cls .= $affix['class'];
$attr = $in_affix ? ' data-affix="true"' : '';
echo '<div class="' . esc_attr($wrap_cls) . '"' . $attr . '>';
echo '<div class="' . esc_attr($wrap_cls) . '"' . $affix['attr'] . '>';
echo '<div class="aksrt-scroll-notice__icon bulletin-icon"><i class="fas fa-bullhorn" aria-hidden="true"></i></div>';
// Prefer shared vertical new-swiper (zib_notice parity) via slider.js Type C.
@@ -192,14 +192,14 @@ if (!$items) {
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('blank')); ?>" value="1" <?php checked(!empty($instance['blank'])); ?>> <?php esc_html_e('链接新窗口', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('radius')); ?>" value="1" <?php checked(!empty($instance['radius'])); ?>> <?php esc_html_e('两端圆形', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('radius')); ?>" value="1" <?php checked(!empty($instance['radius'])); ?>> <?php esc_html_e('两端圆形', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'items' => $this->normalize_items(['items' => $new_instance['items'] ?? []]),
'interval' => max(2, min(15, (int) ($new_instance['interval'] ?? 4))),
@@ -207,7 +207,6 @@ if (!$items) {
'alignment' => sanitize_html_class((string) ($new_instance['alignment'] ?? '')),
'blank' => !empty($new_instance['blank']) ? 1 : 0,
'radius' => !empty($new_instance['radius']) ? 1 : 0,
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
];
]);
}
}
+10 -9
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class RecentCommentsWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct('aksrt_recent_comments', esc_html__('AKSRT 最新评论', 'aksrt'), [
@@ -169,12 +172,12 @@ class RecentCommentsWidget extends \WP_Widget {
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$in_affix = !empty($instance['in_affix']);
if ($in_affix) {
echo '<div class="is-affix" data-affix="true">';
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
if ($affix['class'] !== '') {
echo '<div class="is-affix"' . $affix['attr'] . '>';
}
echo self::render_html($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ($in_affix) {
if ($affix['class'] !== '') {
echo '</div>';
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -209,9 +212,7 @@ class RecentCommentsWidget extends \WP_Widget {
</label>
<small><?php esc_html_e('填数字 ID 时按作者排除;填文字时按内容关键词排除(兼容旧配置)。', 'aksrt'); ?></small>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -221,12 +222,12 @@ class RecentCommentsWidget extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 5))),
'show_avatar' => !empty($new_instance['show_avatar']) ? 1 : 0,
'outpost' => sanitize_text_field((string) ($new_instance['outpost'] ?? '')),
'outer' => sanitize_text_field((string) ($new_instance['outer'] ?? '')),
];
]);
}
}
+24 -6
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class SearchWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct('aksrt_search', esc_html__('AKSRT 搜索', 'aksrt'), [
@@ -32,10 +35,20 @@ class SearchWidget extends \WP_Widget {
$show_kw = !empty($instance['show_keywords']);
$show_history = !empty($instance['show_history']);
$show_types = !empty($instance['show_type']) || !isset($instance['show_type']);
// NOTE: SearchWidget owns a business `show_type` checkbox (search-type
// toggle) that shares the key name with the common `show_type` (device
// visibility). To avoid an admin-form collision, this widget does NOT
// render the shared common-form section (render_common_form_section is
// intentionally not called). The shared affix helper is still wired in
// widget() via aksrt_widget_affix_attrs(), and update_common_fields()
// persists common keys — but note the shared show_type cannot be set
// here, so display_callback treats it as 'all' (always visible).
$show_cat = !empty($instance['show_input_cat']);
$kw_title = sanitize_text_field((string) ($instance['keywords_title'] ?? __('热门搜索', 'aksrt')));
$more_but = sanitize_text_field((string) ($instance['more_but'] ?? ''));
$more_url = esc_url_raw(trim((string) ($instance['more_but_url'] ?? '')));
// Affix helper (shared layer sidebar_affix).
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$state = function_exists('aksrt_get_search_form_state')
? aksrt_get_search_form_state()
@@ -109,7 +122,7 @@ class SearchWidget extends \WP_Widget {
$uid = 'aksrt-sw-' . esc_attr($this->id);
?>
<div class="widget-search-box aksrt-search-widget search-input<?php echo !empty($instance['in_affix']) ? ' is-affix' : ''; ?>" id="<?php echo $uid; ?>"<?php echo !empty($instance['in_affix']) ? ' data-affix="true"' : ''; ?>>
<div class="widget-search-box aksrt-search-widget search-input<?php echo $affix['class']; ?>" id="<?php echo $uid; ?>"<?php echo $affix['attr']; ?>>
<form
role="search"
method="get"
@@ -239,8 +252,7 @@ class SearchWidget extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_type')); ?>" value="1" <?php checked(!empty($instance['show_type']) || !isset($instance['show_type'])); ?>> <?php esc_html_e('显示类型切换(≥2 种时)', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_input_cat')); ?>" value="1" <?php checked(!empty($instance['show_input_cat'])); ?>> <?php esc_html_e('显示分类筛选', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_keywords')); ?>" value="1" <?php checked(!empty($instance['show_keywords'])); ?>> <?php esc_html_e('显示热门关键词', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_history')); ?>" value="1" <?php checked(!empty($instance['show_history'])); ?>> <?php esc_html_e('显示搜索历史', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_history')); ?>" value="1" <?php checked(!empty($instance['show_history'])); ?>> <?php esc_html_e('显示搜索历史', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('默认类型', 'aksrt'); ?>
@@ -281,11 +293,18 @@ class SearchWidget extends \WP_Widget {
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('more_but_url')); ?>" value="<?php echo esc_attr((string) ($instance['more_but_url'] ?? '')); ?>">
</label>
</p>
<?php // Common-form section intentionally skipped: SearchWidget owns a
// business `show_type` checkbox (search-type toggle) that collides
// with the shared common `show_type` (device visibility). The
// shared affix/display/animation/layout fields are therefore not
// rendered here; update_common_fields() below still persists any
// common keys submitted through other surfaces, and the affix
// helper is wired in widget() via aksrt_widget_affix_attrs(). ?>
<?php
}
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'placeholder' => sanitize_text_field((string) ($new_instance['placeholder'] ?? '')),
'show_keywords' => !empty($new_instance['show_keywords']) ? 1 : 0,
@@ -299,7 +318,6 @@ class SearchWidget extends \WP_Widget {
'keywords' => sanitize_textarea_field((string) ($new_instance['keywords'] ?? '')),
'more_but' => sanitize_text_field((string) ($new_instance['more_but'] ?? '')),
'more_but_url' => esc_url_raw(trim((string) ($new_instance['more_but_url'] ?? ''))),
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
];
]);
}
}
+7 -2
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class TabPostsWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -348,7 +352,8 @@ class TabPostsWidget extends \WP_Widget {
</p>
</div>
<?php endforeach;
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$style = sanitize_key((string) ($new_instance['style'] ?? 'mini'));
@@ -389,6 +394,6 @@ class TabPostsWidget extends \WP_Widget {
}
}
$result['tabs'] = !empty($tabs) ? $tabs : 'latest,comments,random';
return $result;
return $this->update_common_fields($new_instance, $old_instance, $result);
}
}
+11 -8
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class TagCloudWidget extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -101,12 +104,12 @@ class TagCloudWidget extends \WP_Widget {
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$in_affix = !empty($instance['in_affix']);
if ($in_affix) {
echo '<div class="is-affix" data-affix="true">';
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
if ($affix['class'] !== '') {
echo '<div class="is-affix"' . $affix['attr'] . '>';
}
echo self::render_html($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ($in_affix) {
if ($affix['class'] !== '') {
echo '</div>';
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -161,14 +164,14 @@ class TagCloudWidget extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('blank')); ?>" value="1" <?php checked(!empty($instance['blank'])); ?>> <?php esc_html_e('新窗口', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('fixed_width')); ?>" value="1" <?php checked(!empty($instance['fixed_width'])); ?>> <?php esc_html_e('固定宽度', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_empty')); ?>" value="1" <?php checked(!empty($instance['hide_empty'])); ?>> <?php esc_html_e('隐藏空标签', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('scale')); ?>" value="1" <?php checked(!empty($instance['scale'])); ?>> <?php esc_html_e('按数量缩放字号', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('scale')); ?>" value="1" <?php checked(!empty($instance['scale'])); ?>> <?php esc_html_e('按数量缩放字号', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'post_tag')),
'count' => max(1, min(80, (int) ($new_instance['count'] ?? 15))),
@@ -179,6 +182,6 @@ class TagCloudWidget extends \WP_Widget {
'fixed_width' => !empty($new_instance['fixed_width']) ? 1 : 0,
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
'scale' => !empty($new_instance['scale']) ? 1 : 0,
];
]);
}
}
@@ -0,0 +1,73 @@
<?php
/**
* CommonWidgetFields trait — single seat-belt for shared widget form/update.
*
* Every AKSRT widget `use`s this trait so the Zibll common-field family
* (title block, display rules, affix, animation, layout bg) is declared and
* persisted in exactly one place: inc/modules/widget-common.php.
*
* Widgets keep only their business fields; the trait wires the shared section
* into form() and folds the shared keys into update().
*
* @package AKSRT\Widgets\Traits
*/
namespace AKSRT\Widgets\Traits;
defined('ABSPATH') || exit;
trait CommonWidgetFields {
/**
* Whether this widget should render the shared common-form section.
*
* Override and return false for pure-display widgets with no admin form.
* Default: true (every widget gets the shared block).
*
* @return bool
*/
protected function use_common_form(): bool {
return true;
}
/**
* Render the shared common-form section at the end of a widget's form().
*
* Call from form(): render business fields, then `$this->render_common_form_section($instance);`.
*
* @param array<string,mixed> $instance Widget instance.
*/
protected function render_common_form_section(array $instance): void {
if (!$this->use_common_form()) {
return;
}
if (function_exists('aksrt_widget_render_common_form')) {
aksrt_widget_render_common_form($instance);
}
}
/**
* Merge shared common fields into a widget's update() result.
*
* Usage in update():
* return $this->update_common_fields($new_instance, $old_instance, [
* 'title' => sanitize_text_field(...),
* ...business fields...
* ]);
*
* @param array<string,mixed> $new_instance New submitted instance.
* @param array<string,mixed> $old_instance Previous instance.
* @param array<string,mixed> $business Sanitized business fields to keep.
* @return array<string,mixed>
*/
protected function update_common_fields(array $new_instance, array $old_instance, array $business = []): array {
if (!$this->use_common_form()) {
return $business;
}
if (function_exists('aksrt_widget_update_common')) {
$common = aksrt_widget_update_common($new_instance, $old_instance);
return array_merge($business, $common);
}
return $business;
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetAnnouncement extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -148,7 +152,8 @@ class WidgetAnnouncement extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('blank')); ?>" value="1" <?php checked(!empty($instance['blank'])); ?>> <?php esc_html_e('链接新窗口', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -160,7 +165,7 @@ class WidgetAnnouncement extends \WP_Widget {
if (!in_array($mode, ['swiper', 'marquee'], true)) {
$mode = 'swiper';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'items' => sanitize_textarea_field((string) ($new_instance['items'] ?? '')),
'icon' => sanitize_text_field((string) ($new_instance['icon'] ?? 'fas fa-bullhorn')),
@@ -168,6 +173,6 @@ class WidgetAnnouncement extends \WP_Widget {
'mode' => $mode,
'interval' => max(2, min(15, (int) ($new_instance['interval'] ?? 4))),
'blank' => !empty($new_instance['blank']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+9 -8
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetAuthorCard extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -84,15 +87,15 @@ class WidgetAuthorCard extends \WP_Widget {
? aksrt_get_user_name(['id' => $author_id, 'follow' => false, 'class' => 'flex ac jc'])
: '<a href="' . esc_url($home) . '">' . esc_html($user->display_name) . '</a>';
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$card_cls = 'aksrt-author-card user-card author zib-widget' . ($show_bg ? ' has-cover' : '') . ($in_affix ? ' is-affix' : '');
echo '<div class="' . esc_attr($card_cls) . '"' . ($in_affix ? ' data-affix="true"' : '') . '>';
$card_cls = 'aksrt-author-card user-card author zib-widget' . ($show_bg ? ' has-cover' : '') . $affix['class'];
echo '<div class="' . esc_attr($card_cls) . '"' . $affix['attr'] . '>';
if ($show_bg) {
$bg = $cover !== '' ? ' style="background-image:url(' . esc_url($cover) . ')"' : '';
echo '<div class="aksrt-author-card__cover user-cover graphic"' . $bg . '></div>';
@@ -210,9 +213,7 @@ class WidgetAuthorCard extends \WP_Widget {
</select>
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -225,7 +226,7 @@ class WidgetAuthorCard extends \WP_Widget {
if (!in_array($orderby, ['date', 'views', 'comment_count', 'modified', 'rand'], true)) {
$orderby = 'date';
}
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'user_id' => max(0, (int) ($new_instance['user_id'] ?? 0)),
'show_img_bg' => !empty($new_instance['show_img_bg']) ? 1 : 0,
@@ -236,6 +237,6 @@ class WidgetAuthorCard extends \WP_Widget {
'limit' => max(0, min(12, (int) ($new_instance['limit'] ?? 6))),
'post_style' => $post_style,
'orderby' => $orderby,
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetBookmarkLinks extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -135,14 +139,15 @@ class WidgetBookmarkLinks extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_box')); ?>" value="1" <?php checked(!empty($instance['show_box'])); ?>> <?php esc_html_e('外框盒子', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$type = sanitize_key((string) ($new_instance['type'] ?? 'card'));
if (!in_array($type, ['card', 'bigcard', 'image', 'simple'], true)) {
$type = 'card';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'links_cats' => sanitize_text_field((string) ($new_instance['links_cats'] ?? '')),
'links_limit' => max(0, min(100, (int) ($new_instance['links_limit'] ?? 12))),
@@ -153,6 +158,6 @@ class WidgetBookmarkLinks extends \WP_Widget {
'nofollow' => !empty($new_instance['nofollow']) ? 1 : 0,
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
'show_box' => !empty($new_instance['show_box']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetComboInfo extends \WP_Widget {
use CommonWidgetFields;
private const BANDS = ['blue', 'cyan', 'green', 'yellow', 'pink', 'purple'];
@@ -250,10 +254,11 @@ class WidgetComboInfo extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'cards' => $this->normalize_cards($new_instance['cards'] ?? []),
'pc_row' => max(1, min(6, (int) ($new_instance['pc_row'] ?? 4))),
@@ -265,6 +270,6 @@ class WidgetComboInfo extends \WP_Widget {
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
'animation_repeat'=> !empty($new_instance['animation_repeat']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetCoverCards extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -200,7 +204,8 @@ class WidgetCoverCards extends \WP_Widget {
<small><?php esc_html_e('字段: image, video, title, link, target, hide(pc|m), height, mask', 'aksrt'); ?></small>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -208,7 +213,7 @@ class WidgetCoverCards extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'pc_row' => max(1, min(6, (int) ($new_instance['pc_row'] ?? 2))),
'm_row' => max(1, min(3, (int) ($new_instance['m_row'] ?? 1))),
@@ -220,6 +225,6 @@ class WidgetCoverCards extends \WP_Widget {
'font_bold' => !empty($new_instance['font_bold']) ? 1 : 0,
'font_color' => sanitize_hex_color((string) ($new_instance['font_color'] ?? '')) ?: '',
'items' => $this->normalize($new_instance['items'] ?? []),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetFaq extends \WP_Widget {
use CommonWidgetFields;
private const BADGE_TONES = ['purple', 'pink', 'green', 'orange', 'blue'];
@@ -332,10 +336,11 @@ class WidgetFaq extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'search_s' => !empty($new_instance['search_s']) ? 1 : 0,
'search_placeholder' => sanitize_text_field((string) ($new_instance['search_placeholder'] ?? '')),
@@ -350,6 +355,6 @@ class WidgetFaq extends \WP_Widget {
'help_icon' => sanitize_text_field((string) ($new_instance['help_icon'] ?? '')),
'help_btn_text' => sanitize_text_field((string) ($new_instance['help_btn_text'] ?? '')),
'help_btn_url' => esc_url_raw(trim((string) ($new_instance['help_btn_url'] ?? ''))),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetFeatureIntro extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -206,10 +210,11 @@ class WidgetFeatureIntro extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'heading' => sanitize_text_field((string) ($new_instance['heading'] ?? '')),
'description' => wp_kses_post((string) ($new_instance['description'] ?? '')),
'slides' => $this->normalize_slides($new_instance['slides'] ?? []),
@@ -220,6 +225,6 @@ class WidgetFeatureIntro extends \WP_Widget {
'stat_number' => sanitize_text_field((string) ($new_instance['stat_number'] ?? '')),
'stat_suffix' => sanitize_text_field((string) ($new_instance['stat_suffix'] ?? '')),
'stat_label' => sanitize_text_field((string) ($new_instance['stat_label'] ?? '')),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumBoardList extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -180,7 +184,8 @@ class WidgetForumBoardList extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_empty')); ?>" value="1" <?php checked(!isset($instance['hide_empty']) || !empty($instance['hide_empty'])); ?>> <?php esc_html_e('隐藏空版块(分类模式)', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'menu_order'));
@@ -188,12 +193,12 @@ class WidgetForumBoardList extends \WP_Widget {
if (!in_array($orderby, $allowed, true)) {
$orderby = 'menu_order';
}
return [
$business = [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'count' => max(1, min(50, (int) ($new_instance['count'] ?? 30))),
'orderby' => $orderby,
'style' => ($new_instance['style'] ?? '') === 'mini' ? 'mini' : 'list',
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+9 -8
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumHotTopics extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -179,9 +182,9 @@ class WidgetForumHotTopics extends \WP_Widget {
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$rest = rest_url('aksrt/v1/widgets/forum-topics');
$in_affix = !empty($instance['in_affix']);
$wrap = 'ajaxpager' . ($in_affix ? ' is-affix' : '');
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . ($in_affix ? ' data-affix="true"' : '') . '>';
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$wrap = 'ajaxpager' . $affix['class'];
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . $affix['attr'] . '>';
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="post_ajax_loader" data-aksrt-ajax-loader data-aksrt-ajax-loader-hide hidden></div>';
@@ -245,9 +248,7 @@ class WidgetForumHotTopics extends \WP_Widget {
</select>
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -260,7 +261,7 @@ class WidgetForumHotTopics extends \WP_Widget {
if (!in_array($style, ['mini', 'rank'], true)) {
$style = 'mini';
}
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 5))),
'period' => in_array($new_instance['period'] ?? '', ['all', 'week', 'month'], true) ? $new_instance['period'] : 'week',
@@ -268,6 +269,6 @@ class WidgetForumHotTopics extends \WP_Widget {
'style' => $style,
'plate' => max(0, (int) ($new_instance['plate'] ?? 0)),
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumPlateInfo extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -156,14 +160,15 @@ class WidgetForumPlateInfo extends \WP_Widget {
</p>
<p class="description"><?php esc_html_e('仅在版块页或帖子页显示对应版块信息。', 'aksrt'); ?></p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'show_stats' => !empty($new_instance['show_stats']) ? 1 : 0,
'show_follow' => !empty($new_instance['show_follow']) ? 1 : 0,
'show_compose' => !empty($new_instance['show_compose']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumPlateLists extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -260,20 +264,21 @@ class WidgetForumPlateLists extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'menu_order'));
if (!in_array($orderby, ['menu_order', 'date', 'posts', 'views', 'follow'], true)) {
$orderby = 'menu_order';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'showposts' => max(1, min(30, (int) ($new_instance['showposts'] ?? 8))),
'orderby' => $orderby,
'style' => ($new_instance['style'] ?? '') === 'card' ? 'card' : 'default',
'filter' => ($new_instance['filter'] ?? '') === 'is_hot' ? 'is_hot' : '',
'cat' => sanitize_text_field((string) ($new_instance['cat'] ?? '')),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumPlateModerator extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -230,15 +233,16 @@ class WidgetForumPlateModerator extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('apply_btn')); ?>" value="1" <?php checked(!isset($instance['apply_btn']) || !empty($instance['apply_btn'])); ?>> <?php esc_html_e('显示申请版主入口', 'aksrt'); ?></label>
</p>
<p class="description"><?php esc_html_e('仅在版块/帖子页显示。', 'aksrt'); ?></p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title_text' => sanitize_text_field((string) ($new_instance['title_text'] ?? '')),
'style' => ($new_instance['style'] ?? '') === 'grid' ? 'grid' : 'list',
'show_avatar' => !empty($new_instance['show_avatar']) ? 1 : 0,
'apply_btn' => !empty($new_instance['apply_btn']) ? 1 : 0,
];
]);
}
}
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumRecentTopics extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -40,9 +43,9 @@ class WidgetForumRecentTopics extends \WP_Widget {
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$rest = rest_url('aksrt/v1/widgets/forum-topics');
$in_affix = !empty($instance['in_affix']);
$wrap = 'ajaxpager' . ($in_affix ? ' is-affix' : '');
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . ($in_affix ? ' data-affix="true"' : '') . '>';
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$wrap = 'ajaxpager' . $affix['class'];
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . $affix['attr'] . '>';
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="post_ajax_loader" data-aksrt-ajax-loader data-aksrt-ajax-loader-hide hidden></div>';
@@ -86,9 +89,7 @@ class WidgetForumRecentTopics extends \WP_Widget {
</select>
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -97,13 +98,12 @@ class WidgetForumRecentTopics extends \WP_Widget {
if (!in_array($style, ['mini', 'rank'], true)) {
$style = 'mini';
}
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 5))),
'plate' => max(0, (int) ($new_instance['plate'] ?? 0)),
'style' => $style,
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumTabTopics extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -165,19 +169,20 @@ class WidgetForumTabTopics extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$style = sanitize_key((string) ($new_instance['style'] ?? 'mini'));
if (!in_array($style, ['mini', 'rank'], true)) {
$style = 'mini';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 6))),
'style' => $style,
'plate' => max(0, (int) ($new_instance['plate'] ?? 0)),
'tabs' => sanitize_textarea_field((string) ($new_instance['tabs'] ?? '')),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumTopicLists extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -271,10 +275,11 @@ class WidgetForumTopicLists extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(30, (int) ($new_instance['count'] ?? 8))),
'orderby' => sanitize_key((string) ($new_instance['orderby'] ?? 'date')),
@@ -282,6 +287,6 @@ class WidgetForumTopicLists extends \WP_Widget {
'plate_id' => max(0, (int) ($new_instance['plate_id'] ?? 0)),
'current_plate' => !empty($new_instance['current_plate']) ? 1 : 0,
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetForumTopicTerms extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -153,20 +157,21 @@ class WidgetForumTopicTerms extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_empty')); ?>" value="1" <?php checked(!isset($instance['hide_empty']) || !empty($instance['hide_empty'])); ?>> <?php esc_html_e('隐藏空标签', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'count'));
if (!in_array($orderby, ['count', 'name', 'views'], true)) {
$orderby = 'count';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'number' => max(1, min(40, (int) ($new_instance['number'] ?? 12))),
'orderby' => $orderby,
'style' => ($new_instance['style'] ?? '') === 'card' ? 'card' : 'mini',
'include' => sanitize_text_field((string) ($new_instance['include'] ?? '')),
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetHighlights extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -187,7 +191,8 @@ class WidgetHighlights extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('go_link')); ?>" value="1" <?php checked(!empty($instance['go_link'])); ?>> <?php esc_html_e('外链跳转页', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -195,12 +200,12 @@ class WidgetHighlights extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'cards' => $this->normalize($new_instance['cards'] ?? []),
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? 'slideup')),
'animation_repeat' => !empty($new_instance['animation_repeat']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetIconCoverCards extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -183,7 +187,8 @@ class WidgetIconCoverCards extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('go_link')); ?>" value="1" <?php checked(!empty($instance['go_link'])); ?>> <?php esc_html_e('外链跳转页', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -191,7 +196,7 @@ class WidgetIconCoverCards extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'cards' => $this->normalize($new_instance['cards'] ?? []),
'pc_row' => max(1, min(4, (int) ($new_instance['pc_row'] ?? 2))),
@@ -200,6 +205,6 @@ class WidgetIconCoverCards extends \WP_Widget {
'icon_radius4' => !empty($new_instance['icon_radius4']) ? 1 : 0,
'show_widget_bg' => !empty($new_instance['show_widget_bg']) ? 1 : 0,
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetIframe extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -137,7 +141,8 @@ class WidgetIframe extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('allowfullscreen')); ?>" value="1" <?php checked(!empty($instance['allowfullscreen'])); ?>> <?php esc_html_e('允许全屏', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -145,11 +150,11 @@ class WidgetIframe extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'url' => trim((string) ($new_instance['url'] ?? '')),
'aspect' => max(20, min(300, (int) ($new_instance['aspect'] ?? 55))),
'allowfullscreen' => !empty($new_instance['allowfullscreen']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetLangSwitch extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -101,7 +105,8 @@ class WidgetLangSwitch extends \WP_Widget {
</p>
<p><small><?php esc_html_e('需要安装 Polylang 或 WPML 等多语言插件才能生效。', 'aksrt'); ?></small></p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -113,11 +118,11 @@ class WidgetLangSwitch extends \WP_Widget {
if (!in_array($style, ['dropdown', 'flags', 'inline'], true)) {
$style = 'dropdown';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'style' => $style,
'show_name' => !empty($new_instance['show_name']) ? 1 : 0,
'hide_current' => !empty($new_instance['hide_current']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+10 -10
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetMainPosts extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -324,15 +327,13 @@ class WidgetMainPosts extends \WP_Widget {
], static function ($v) {
return $v !== '' && $v !== null;
}));
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$wrap_cls = 'aksrt-main-posts style-' . $style . ' ajaxpager';
if ($style === 'mini') {
$wrap_cls .= ' zib-widget posts-mini-lists';
}
if ($in_affix) {
$wrap_cls .= ' is-affix';
}
echo '<div class="' . esc_attr($wrap_cls) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '" data-load-mode="' . esc_attr($load_mode) . '" data-query="' . esc_attr($qs) . '"' . ($load_mode === 'ajax' ? ' data-loaded="0"' : ' data-loaded="1"') . ($in_affix ? ' data-affix="true"' : '') . '>';
$wrap_cls .= $affix['class'];
echo '<div class="' . esc_attr($wrap_cls) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '" data-load-mode="' . esc_attr($load_mode) . '" data-query="' . esc_attr($qs) . '"' . ($load_mode === 'ajax' ? ' data-loaded="0"' : ' data-loaded="1"') . $affix['attr'] . '>';
if ($load_mode === 'ajax') {
// Skeleton first paint (zibll load_mode=ajax).
@@ -439,9 +440,9 @@ class WidgetMainPosts extends \WP_Widget {
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_thumb')); ?>" value="1" <?php checked(!isset($instance['show_thumb']) || !empty($instance['show_thumb'])); ?>> <?php esc_html_e('显示缩略图', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_meta')); ?>" value="1" <?php checked(!isset($instance['show_meta']) || !empty($instance['show_meta'])); ?>> <?php esc_html_e('显示 meta', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_number')); ?>" value="1" <?php checked(!empty($instance['show_number'])); ?>> <?php esc_html_e('显示序号', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_number')); ?>" value="1" <?php checked(!empty($instance['show_number'])); ?>> <?php esc_html_e('显示序号', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -458,7 +459,7 @@ class WidgetMainPosts extends \WP_Widget {
if (!in_array($paginate, ['none', 'ajax', 'number'], true)) {
$paginate = 'none';
}
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(30, (int) ($new_instance['count'] ?? 6))),
'style' => $style,
@@ -472,7 +473,6 @@ class WidgetMainPosts extends \WP_Widget {
'show_thumb' => !empty($new_instance['show_thumb']) ? 1 : 0,
'show_meta' => !empty($new_instance['show_meta']) ? 1 : 0,
'show_number' => !empty($new_instance['show_number']) ? 1 : 0,
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
];
]);
}
}
+8 -3
View File
@@ -9,9 +9,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetOnelinePosts extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -249,7 +253,8 @@ class WidgetOnelinePosts extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -265,7 +270,7 @@ class WidgetOnelinePosts extends \WP_Widget {
if (!in_array($orderby, ['date', 'views', 'comments', 'rand'], true)) {
$orderby = 'date';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 8))),
'style' => $style,
@@ -274,6 +279,6 @@ class WidgetOnelinePosts extends \WP_Widget {
'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)),
'topics' => sanitize_text_field((string) ($new_instance['topics'] ?? '')),
'pay_type' => sanitize_key((string) ($new_instance['pay_type'] ?? '')),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+9 -8
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetPaidPosts extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -187,10 +190,10 @@ class WidgetPaidPosts extends \WP_Widget {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$rest = rest_url('aksrt/v1/widgets/paid-posts');
$wrap = 'aksrt-paid-posts-wrap ajaxpager' . ($in_affix ? ' is-affix' : '');
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . ($in_affix ? ' data-affix="true"' : '') . '>';
$wrap = 'aksrt-paid-posts-wrap ajaxpager' . $affix['class'];
echo '<div class="' . esc_attr($wrap) . '" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '"' . $affix['attr'] . '>';
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="post_ajax_loader" data-aksrt-ajax-loader data-aksrt-ajax-loader-hide hidden></div>';
@@ -248,9 +251,7 @@ class WidgetPaidPosts extends \WP_Widget {
<input class="tiny-text" type="number" min="0" name="<?php echo esc_attr($this->get_field_name('limit_day')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['limit_day'] ?? 0))); ?>">
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -259,7 +260,7 @@ class WidgetPaidPosts extends \WP_Widget {
if (!in_array($orderby, ['date', 'views', 'price'], true)) {
$orderby = 'date';
}
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 6))),
'orderby' => $orderby,
@@ -267,6 +268,6 @@ class WidgetPaidPosts extends \WP_Widget {
'cat' => max(0, (int) ($new_instance['cat'] ?? 0)),
'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)),
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetPartnersScroll extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -326,10 +330,11 @@ class WidgetPartnersScroll extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_widget_bg')); ?>" value="1" <?php checked(!empty($instance['show_widget_bg']) || !isset($instance['show_widget_bg'])); ?>> <?php esc_html_e('显示背景盒子', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'link_type' => in_array(($new_instance['link_type'] ?? ''), ['manual', 'link'], true) ? $new_instance['link_type'] : 'manual',
'partners' => $this->normalize_manual($new_instance['partners'] ?? []),
@@ -350,6 +355,6 @@ class WidgetPartnersScroll extends \WP_Widget {
'end_fade' => !empty($new_instance['end_fade']) ? 1 : 0,
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
'show_widget_bg' => !empty($new_instance['show_widget_bg']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+7 -2
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetPostPayBox extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -168,7 +172,8 @@ class WidgetPostPayBox extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$theme = sanitize_html_class((string) ($new_instance['theme'] ?? 'jb-red'));
@@ -176,6 +181,6 @@ class WidgetPostPayBox extends \WP_Widget {
if (!in_array($theme, $allowed, true)) {
$theme = 'jb-red';
}
return ['theme' => $theme];
$business = ['theme' => $theme]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+9 -16
View File
@@ -10,9 +10,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetPostsNavs extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -39,7 +42,7 @@ class WidgetPostsNavs extends \WP_Widget {
$title = sanitize_text_field((string) ($instance['title'] ?? __('文章目录', 'aksrt')));
$mini_title = sanitize_text_field((string) ($instance['mini_title'] ?? ''));
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$data_title = $title;
if ($mini_title !== '') {
@@ -50,16 +53,13 @@ class WidgetPostsNavs extends \WP_Widget {
}
// Mirror aksrt-single-render built-in TOC shell so page-template.js binds.
$classes = 'zib-widget toc-widget posts-nav-box';
if ($in_affix) {
$classes .= ' is-affix';
}
$classes = 'zib-widget toc-widget posts-nav-box' . $affix['class'];
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
printf(
'<div class="%s"%s data-title="%s" aria-label="%s">',
esc_attr($classes),
$in_affix ? ' data-affix="true"' : '',
$affix['attr'],
esc_attr($data_title),
esc_attr($data_title)
);
@@ -72,7 +72,6 @@ class WidgetPostsNavs extends \WP_Widget {
public function form($instance): void {
$title = (string) ($instance['title'] ?? __('文章目录', 'aksrt'));
$mini_title = (string) ($instance['mini_title'] ?? '');
$in_affix = !empty($instance['in_affix']);
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
@@ -82,21 +81,15 @@ class WidgetPostsNavs extends \WP_Widget {
<label for="<?php echo esc_attr($this->get_field_id('mini_title')); ?>"><?php esc_html_e('副标题:', 'aksrt'); ?></label>
<input class="widefat" type="text" id="<?php echo esc_attr($this->get_field_id('mini_title')); ?>" name="<?php echo esc_attr($this->get_field_name('mini_title')); ?>" value="<?php echo esc_attr($mini_title); ?>">
</p>
<p>
<label>
<input type="checkbox" id="<?php echo esc_attr($this->get_field_id('in_affix')); ?>" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked($in_affix); ?>>
<?php esc_html_e('侧栏随动(仅侧边栏)', 'aksrt'); ?>
</label>
</p>
<p class="description"><?php esc_html_e('请添加到文章/帖子侧栏。正文标题 ≥3 个时由前端填充目录;无标题则自动移除。', 'aksrt'); ?></p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'mini_title' => sanitize_text_field((string) ($new_instance['mini_title'] ?? '')),
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetPricingPlans extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -232,15 +236,16 @@ class WidgetPricingPlans extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('go_link')); ?>" value="1" <?php checked(!empty($instance['go_link'])); ?>> <?php esc_html_e('外链跳转页', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'currency' => sanitize_text_field((string) ($new_instance['currency'] ?? '¥')),
'lists' => $this->normalize_plans($new_instance['lists'] ?? []),
'trust_items' => $this->normalize_trust($new_instance['trust_items'] ?? []),
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -5,6 +5,8 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
/**
@@ -14,6 +16,8 @@ defined('ABSPATH') || exit;
* AJAX load-more (via rest widget list endpoint); per-page count.
*/
class WidgetProductList extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -377,10 +381,11 @@ class WidgetProductList extends \WP_Widget {
</select>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'per_page' => max(1, min(50, (int) ($new_instance['per_page'] ?? 8))),
'orderby' => sanitize_key((string) ($new_instance['orderby'] ?? 'date')),
@@ -391,6 +396,6 @@ class WidgetProductList extends \WP_Widget {
'exclude_cat' => !empty($new_instance['exclude_cat']) ? 1 : 0,
'style' => sanitize_key((string) ($new_instance['style'] ?? 'default')),
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -5,6 +5,8 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
/**
@@ -12,6 +14,8 @@ defined('ABSPATH') || exit;
* First tab renders immediately via shared payload; other tabs lazy-load via REST.
*/
class WidgetProductTab extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -160,15 +164,16 @@ class WidgetProductTab extends \WP_Widget {
</select>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'tabs' => sanitize_textarea_field((string) ($new_instance['tabs'] ?? '')),
'per_page' => max(1, min(20, (int) ($new_instance['per_page'] ?? 8))),
'style' => sanitize_key((string) ($new_instance['style'] ?? 'default')),
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetReviews extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -148,14 +152,15 @@ class WidgetReviews extends \WP_Widget {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'reviews' => $this->normalize($new_instance['reviews'] ?? []),
'desktop_per_view' => max(1, min(6, (float) ($new_instance['desktop_per_view'] ?? 3))),
'mobile_per_view' => max(1, min(3, (float) ($new_instance['mobile_per_view'] ?? 1.2))),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetSlider extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -185,7 +189,8 @@ class WidgetSlider extends \WP_Widget {
?>
<p class="description"><?php esc_html_e('使用主题共享 Swiper(.new-swiper)。图片 URL 必填;仅 1 张时不滑动。', 'aksrt'); ?></p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
$slides = $this->normalize_slides($new_instance['slides'] ?? []);
@@ -193,7 +198,7 @@ class WidgetSlider extends \WP_Widget {
if (!in_array($effect, ['slide', 'fade', 'cube', 'coverflow', 'flip'], true)) {
$effect = 'slide';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'interval' => max(2, min(20, (int) ($new_instance['interval'] ?? 4))),
'height' => max(80, min(800, (int) ($new_instance['height'] ?? 220))),
@@ -204,7 +209,7 @@ class WidgetSlider extends \WP_Widget {
'pagination' => !empty($new_instance['pagination']) ? 1 : 0,
'blank' => !empty($new_instance['blank']) ? 1 : 0,
'slides' => $slides,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
/**
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetStats extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -174,16 +178,17 @@ if (!$stats) {
</label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'stats' => $this->normalize_stats($new_instance['stats'] ?? []),
'columns' => max(1, min(4, (int) ($new_instance['columns'] ?? 4))),
'mobile_columns' => max(1, min(3, (int) ($new_instance['mobile_columns'] ?? 2))),
'intro_title' => sanitize_text_field((string) ($new_instance['intro_title'] ?? '')),
'intro_subtitle' => sanitize_text_field((string) ($new_instance['intro_subtitle'] ?? '')),
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetTermAggregation extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -309,7 +313,8 @@ class WidgetTermAggregation extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('target_blank')); ?>" value="1" <?php checked(!empty($instance['target_blank'])); ?>> <?php esc_html_e('新窗口打开', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -321,7 +326,7 @@ class WidgetTermAggregation extends \WP_Widget {
if (!in_array($orderby, ['date', 'modified', 'views', 'like', 'comment_count'], true)) {
$orderby = 'date';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
'term_ids' => sanitize_text_field((string) ($new_instance['term_ids'] ?? '')),
@@ -330,6 +335,6 @@ class WidgetTermAggregation extends \WP_Widget {
'orderby' => $orderby,
'auto_terms' => max(1, min(4, (int) ($new_instance['auto_terms'] ?? 2))),
'target_blank' => !empty($new_instance['target_blank']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetTermCards extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -271,7 +275,8 @@ class WidgetTermCards extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('target_blank')); ?>" value="1" <?php checked(!empty($instance['target_blank'])); ?>> <?php esc_html_e('新窗口打开', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -283,7 +288,7 @@ class WidgetTermCards extends \WP_Widget {
if (!in_array($type, ['style-1', 'style-2', 'style-3', 'style-4'], true)) {
$type = 'style-1';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
'number' => max(1, min(30, (int) ($new_instance['number'] ?? 8))),
@@ -297,6 +302,6 @@ class WidgetTermCards extends \WP_Widget {
'include' => sanitize_text_field((string) ($new_instance['include'] ?? '')),
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
'target_blank' => !empty($new_instance['target_blank']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+9 -8
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetTextTitle extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -108,9 +111,9 @@ class WidgetTextTitle extends \WP_Widget {
}
}
$in_affix = !empty($instance['in_affix']);
$box = 'aksrt-text-title text-title align-' . esc_attr($align) . ($in_affix ? ' is-affix' : '');
echo '<div class="' . esc_attr($box) . '" style="' . esc_attr($style) . '"' . ($in_affix ? ' data-affix="true"' : '') . '>';
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$box = 'aksrt-text-title text-title align-' . esc_attr($align) . $affix['class'];
echo '<div class="' . esc_attr($box) . '" style="' . esc_attr($style) . '"' . $affix['attr'] . '>';
if ($title_html !== '') {
echo '<div class="aksrt-text-title__main">' . $title_html . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
@@ -182,9 +185,7 @@ class WidgetTextTitle extends \WP_Widget {
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('desc_color')); ?>" value="<?php echo esc_attr((string) ($instance['desc_color'] ?? '')); ?>">
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -194,7 +195,7 @@ class WidgetTextTitle extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'desc' => sanitize_text_field((string) ($new_instance['desc'] ?? '')),
'align' => in_array(($new_instance['align'] ?? ''), ['left', 'center', 'right'], true) ? $new_instance['align'] : 'center',
@@ -207,6 +208,6 @@ class WidgetTextTitle extends \WP_Widget {
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
'animation_repeat' => !empty($new_instance['animation_repeat']) ? 1 : 0,
'title_icon_width' => max(0, min(64, (int) ($new_instance['title_icon_width'] ?? 0))),
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetTiltCases extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -249,10 +253,11 @@ class WidgetTiltCases extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('go_link')); ?>" value="1" <?php checked(!empty($instance['go_link'])); ?>> <?php esc_html_e('外链跳转页', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'intro_badge_text' => sanitize_text_field((string) ($new_instance['intro_badge_text'] ?? '')),
'intro_badge_icon' => sanitize_text_field((string) ($new_instance['intro_badge_icon'] ?? '')),
'intro_title' => sanitize_textarea_field((string) ($new_instance['intro_title'] ?? '')),
@@ -262,6 +267,6 @@ class WidgetTiltCases extends \WP_Widget {
'intro_buttons' => $this->normalize_buttons($new_instance['intro_buttons'] ?? []),
'intro_showcase_images' => $this->normalize_images($new_instance['intro_showcase_images'] ?? []),
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+17 -9
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetUserCard extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -27,7 +30,7 @@ class WidgetUserCard extends \WP_Widget {
// zibll user widget forces show_posts=false; author widget enables it.
// AKSRT keeps optional show_posts for current-user card (default off).
$show_posts = !empty($instance['show_posts']);
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$loged_title = (string) ($instance['loged_title'] ?? __('Hi!请登录', 'aksrt'));
$btn1_text = (string) ($instance['button_1_text'] ?? __('发布文章', 'aksrt'));
$btn2_text = (string) ($instance['button_2_text'] ?? __('用户中心', 'aksrt'));
@@ -49,13 +52,13 @@ class WidgetUserCard extends \WP_Widget {
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
if ($in_affix) {
echo '<div class="is-affix" data-affix="true">';
if ($affix['class'] !== '') {
echo '<div class="is-affix"' . $affix['attr'] . '>';
}
if ($user_id <= 0) {
$this->render_guest($show_cover, $loged_title);
if ($in_affix) {
if ($affix['class'] !== '') {
echo '</div>';
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -64,6 +67,9 @@ class WidgetUserCard extends \WP_Widget {
$user = get_userdata($user_id);
if (!$user) {
if ($affix['class'] !== '') {
echo '</div>';
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return;
}
@@ -173,6 +179,9 @@ class WidgetUserCard extends \WP_Widget {
echo '</div></div>';
if ($affix['class'] !== '') {
echo '</div>';
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
@@ -256,8 +265,7 @@ class WidgetUserCard extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_stats')); ?>" value="1" <?php checked(!isset($instance['show_stats']) || !empty($instance['show_stats'])); ?>> <?php esc_html_e('显示统计', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_button')); ?>" value="1" <?php checked(!isset($instance['show_button']) || !empty($instance['show_button'])); ?>> <?php esc_html_e('显示操作按钮', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_checkin')); ?>" value="1" <?php checked(!isset($instance['show_checkin']) || !empty($instance['show_checkin'])); ?>> <?php esc_html_e('显示签到(本人)', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_posts')); ?>" value="1" <?php checked(!empty($instance['show_posts'])); ?>> <?php esc_html_e('显示更多文章', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_posts')); ?>" value="1" <?php checked(!empty($instance['show_posts'])); ?>> <?php esc_html_e('显示更多文章', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('文章数量', 'aksrt'); ?>
@@ -282,6 +290,7 @@ class WidgetUserCard extends \WP_Widget {
</select>
</label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -294,7 +303,7 @@ class WidgetUserCard extends \WP_Widget {
if (!in_array($orderby, ['date', 'views', 'comment_count', 'modified', 'rand'], true)) {
$orderby = 'date';
}
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'user_id' => max(0, (int) ($new_instance['user_id'] ?? 0)),
'loged_title' => sanitize_text_field((string) ($new_instance['loged_title'] ?? '')),
@@ -305,10 +314,9 @@ class WidgetUserCard extends \WP_Widget {
'show_button' => !empty($new_instance['show_button']) ? 1 : 0,
'show_checkin' => !empty($new_instance['show_checkin']) ? 1 : 0,
'show_posts' => !empty($new_instance['show_posts']) ? 1 : 0,
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
'limit' => max(0, min(12, (int) ($new_instance['limit'] ?? 6))),
'post_style' => $post_style,
'orderby' => $orderby,
];
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetUserLists extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -196,7 +200,8 @@ class WidgetUserLists extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('blur_bg')); ?>" value="1" <?php checked(!empty($instance['blur_bg'])); ?>> <?php esc_html_e('头像模糊背景', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
/**
* @param array<string,mixed> $new_instance
@@ -209,7 +214,7 @@ class WidgetUserLists extends \WP_Widget {
if (!in_array($orderby, $allowed, true)) {
$orderby = 'user_registered';
}
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'number' => max(1, min(50, (int) ($new_instance['number'] ?? 8))),
'include' => sanitize_text_field((string) ($new_instance['include'] ?? '')),
@@ -218,6 +223,6 @@ class WidgetUserLists extends \WP_Widget {
'order' => strtoupper((string) ($new_instance['order'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC',
'hide_box' => !empty($new_instance['hide_box']) ? 1 : 0,
'blur_bg' => !empty($new_instance['blur_bg']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+16 -19
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetUserRanking extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -29,14 +32,14 @@ class WidgetUserRanking extends \WP_Widget {
$show_avatar = !isset($instance['show_avatar']) || !empty($instance['show_avatar']);
$desc_mode = sanitize_key((string) ($instance['desc'] ?? 'desc'));
$top_badge = !empty($instance['top_badge']);
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$users = $this->get_ranking($rank_by, $count, $desc_mode);
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$box_cls = 'zib-widget user-ranking-box aksrt-user-ranking-box' . ($in_affix ? ' is-affix' : '');
echo '<div class="' . esc_attr($box_cls) . '"' . ($in_affix ? ' data-affix="true"' : '') . '>';
$box_cls = 'zib-widget user-ranking-box aksrt-user-ranking-box' . $affix['class'];
echo '<div class="' . esc_attr($box_cls) . '"' . $affix['attr'] . '>';
if (!empty($instance['checkin_btn']) && is_user_logged_in() && function_exists('aksrt_header_user_checkin_btn')) {
$cbtn = aksrt_header_user_checkin_btn(get_current_user_id());
if ($cbtn !== '') {
@@ -338,25 +341,19 @@ class WidgetUserRanking extends \WP_Widget {
<?php esc_html_e('前三名 TOP 角标', 'aksrt'); ?>
</label>
</p>
<p>
<label>
<input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>>
<?php esc_html_e('侧栏随动', 'aksrt'); ?>
</label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
public function update($new_instance, $old_instance): array {
$instance = [];
$instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
$instance['rank_by'] = in_array($new_instance['rank_by'] ?? '', ['credits', 'posts', 'followers', 'checkin_all_day', 'checkin_continuous_day'], true) ? $new_instance['rank_by'] : 'credits';
$instance['count'] = max(1, min(20, (int) ($new_instance['count'] ?? 5)));
$instance['show_avatar'] = !empty($new_instance['show_avatar']) ? 1 : 0;
$instance['checkin_btn'] = !empty($new_instance['checkin_btn']) ? 1 : 0;
$instance['top_badge'] = !empty($new_instance['top_badge']) ? 1 : 0;
$instance['desc'] = in_array($new_instance['desc'] ?? '', ['desc', 'user_registered', 'last_login', 'last_checkin'], true) ? $new_instance['desc'] : 'desc';
$instance['in_affix'] = !empty($new_instance['in_affix']) ? 1 : 0;
return $instance;
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'rank_by' => in_array($new_instance['rank_by'] ?? '', ['credits', 'posts', 'followers', 'checkin_all_day', 'checkin_continuous_day'], true) ? $new_instance['rank_by'] : 'credits',
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 5))),
'show_avatar' => !empty($new_instance['show_avatar']) ? 1 : 0,
'checkin_btn' => !empty($new_instance['checkin_btn']) ? 1 : 0,
'top_badge' => !empty($new_instance['top_badge']) ? 1 : 0,
'desc' => in_array($new_instance['desc'] ?? '', ['desc', 'user_registered', 'last_login', 'last_checkin'], true) ? $new_instance['desc'] : 'desc',
]);
}
}
+8 -3
View File
@@ -7,9 +7,13 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetVideoPlayer extends \WP_Widget {
use CommonWidgetFields;
public function __construct() {
parent::__construct(
@@ -130,10 +134,11 @@ class WidgetVideoPlayer extends \WP_Widget {
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_controller')); ?>" value="1" <?php checked(!empty($instance['hide_controller'])); ?>> <?php esc_html_e('隐藏控制条样式', 'aksrt'); ?></label>
</p>
<?php
}
$this->render_common_form_section($instance);
}
public function update($new_instance, $old_instance): array {
return [
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'video_url' => esc_url_raw(trim((string) ($new_instance['video_url'] ?? ''))),
'poster' => esc_url_raw(trim((string) ($new_instance['poster'] ?? ''))),
@@ -141,6 +146,6 @@ class WidgetVideoPlayer extends \WP_Widget {
'autoplay' => !empty($new_instance['autoplay']) ? 1 : 0,
'loop' => !empty($new_instance['loop']) ? 1 : 0,
'hide_controller' => !empty($new_instance['hide_controller']) ? 1 : 0,
];
]; return $this->update_common_fields($new_instance, $old_instance, $business);
}
}
+11 -9
View File
@@ -7,9 +7,12 @@
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetYiyan extends \WP_Widget {
use CommonWidgetFields;
/**
* @return array<string,string>
@@ -58,7 +61,7 @@ class WidgetYiyan extends \WP_Widget {
$interval = !empty($instance['interval']) ? max(3, min(30, (int) $instance['interval'])) : 5;
$type = self::sanitize_type((string) ($instance['type'] ?? ''));
$icon = !empty($instance['icon']) ? (string) $instance['icon'] : 'fas fa-quote-left';
$in_affix = !empty($instance['in_affix']);
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$anim = sanitize_key((string) ($instance['obs_animation'] ?? ''));
$anim_repeat = !empty($instance['animation_repeat']);
@@ -69,13 +72,15 @@ class WidgetYiyan extends \WP_Widget {
}
// zibll shell: theme-box + yiyan-box main-bg text-center box-body radius8 main-shadow.
// NOTE: obs_animation is this widget's own per-widget animation business
// field (kept as-is); the shared common `animation_in` field added via
// render_common_form_section() is a separate additional control.
$pack = function_exists('aksrt_obs_animate_attrs')
? aksrt_obs_animate_attrs($anim, $anim_repeat, 0)
: ['class' => '', 'attr' => ''];
$affix = $in_affix ? ' data-affix="true"' : '';
$box_class = 'theme-box yiyan-box-wrap' . $pack['class'];
echo '<div' . $affix . ' class="' . esc_attr(trim($box_class)) . '"' . $pack['attr'] . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div' . $affix['attr'] . ' class="' . esc_attr(trim($box_class)) . '"' . $pack['attr'] . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="yiyan-box main-bg text-center box-body radius8 main-shadow">';
if (function_exists('aksrt_render_yiyan_block')) {
@@ -155,9 +160,6 @@ class WidgetYiyan extends \WP_Widget {
name="<?php echo esc_attr($this->get_field_name('icon')); ?>" type="text"
value="<?php echo esc_attr($icon); ?>">
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('入场动画', 'aksrt'); ?>
<select name="<?php echo esc_attr($this->get_field_name('obs_animation')); ?>">
@@ -168,6 +170,7 @@ class WidgetYiyan extends \WP_Widget {
</select>
</label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
@@ -177,15 +180,14 @@ class WidgetYiyan extends \WP_Widget {
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(10, absint($new_instance['count'] ?? 5))),
'interval' => max(3, min(30, absint($new_instance['interval'] ?? 5))),
'type' => self::sanitize_type((string) ($new_instance['type'] ?? '')),
'icon' => sanitize_text_field((string) ($new_instance['icon'] ?? 'fas fa-quote-left')),
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
'animation_repeat' => !empty($new_instance['animation_repeat']) ? 1 : 0,
];
]);
}
}