diff --git a/inc/theme-widgets.php b/inc/theme-widgets.php index 2a87c7e..cd03f2a 100644 --- a/inc/theme-widgets.php +++ b/inc/theme-widgets.php @@ -35,6 +35,52 @@ function widgets_init() } add_action('widgets_init', 'widgets_init'); +/* ========================================================================== + * 后台「外观 → 小工具」用传统拖放面板,不用区块编辑器(3.2.53 / 工单 #23) + * + * ── 为什么要关 ────────────────────────────────────────────────────── + * WP 5.8 起把后台小工具页默认换成了区块编辑器(`wp-admin/widgets-form-blocks.php`)。 + * 它**没有"从左边拖到右边"这个动作**,只能点「+」再搜索挂件名,操作方式 + * 与传统面板差异很大。用户的实际反馈就是「找不到可以拖动的地方」。 + * + * 那挂件名字有没有问题?实测没有 —— 4 个挂件虽然写的是 + * `parent::__construct(false, false, $widget_ops)`(`$widget->name` 确实是 + * false),但名字放在 `$widget_ops['name']` 里,经 + * `wp_register_sidebar_widget()` 的 `array_merge($widget, $options)` + * 覆盖后,`$wp_registered_widgets[...]['name']` 一直是正常中文名。 + * 实测结论(老代码):`$widget->name` = false, + * `$wp_registered_widgets['ad-1']['name']` = '图片广告'。 + * **所以"找不到挂件"与名字无关,只是区块编辑器没有拖放。** + * (这一度被我误判成名字为空,记一次教训:见 tests 里的说明。) + * + * ── 为什么这个钩子名是 `use_widgets_block_editor` ─────────────────── + * WP 7.1.3 的 `wp_use_widgets_block_editor()` 只认这一个 filter: + * + * return apply_filters('use_widgets_block_editor', + * get_theme_support('widgets-block-editor')); + * + * 网上常见的 `gutenberg_use_widgets_block_editor` / `widgets_block_editor_disabled` + * 在 7.1.3 里**一处都不存在**(`grep -rn` 查过 wp-admin/ 与 wp-includes/ 全无命中), + * 写了也是白写。这里按实际源码来。 + * + * ── 顺带把主题声明也去掉 ──────────────────────────────────────────── + * 只挂 filter 也能生效,但 `get_theme_support('widgets-block-editor')` 仍返回 true, + * 语义上"主题声称支持区块小工具"却又不让用,容易误导后来人。 + * 所以在 after_setup_theme 里 `remove_theme_support` —— 必须挂在这个钩子上: + * 主题的 `add_theme_support` 与 `functions.php` 的 require 同在 after_setup_theme + * 早期跑,直接写 `remove_theme_support` 会因为"还没 add"而静默失败。 + * + * 🔴 如果哪天决定改用区块界面,把这两段一起删掉即可 —— 但**必须先确认 + * 4 个挂件的名字都补上了**,否则会退回"找不到挂件"的老问题。 + * ====================================================================== */ +add_filter('use_widgets_block_editor', '__return_false'); + +function yang_drop_widgets_block_editor_support() +{ + remove_theme_support('widgets-block-editor'); +} +add_action('after_setup_theme', 'yang_drop_widgets_block_editor_support', 20); + /* ========================================================================== * 后台挂件表单的公共样式与脚本(3.2.51) * @@ -439,12 +485,47 @@ class widget_ad extends WP_Widget { public function __construct() { + /* 名字与 id_base 都走显式实参(2026-10-27,工单 #23)。 + * + * ── 原来写法为什么"看着像 bug 但实际没坏" ──────────────────── + * 原来写的是 `parent::__construct(false, false, $widget_ops)`, + * 把名字放在 `$widget_ops['name']` 里。两条链路分开看: + * + * ① `$widget->name`:确实等于 false。 + * `WP_Widget::__construct` 只有 `$this->name = $name;`, + * 而 `wp_parse_args` 的默认值只补 classname 与 + * customize_selective_refresh,**不补 name**。 + * + * ② 但后台列表/搜索用的**不是** `$widget->name`,而是 + * `$wp_registered_widgets[]['name']`。它是这么来的: + * `_register_one()` → `wp_register_sidebar_widget($id, $this->name, ..., $this->widget_options)` + * → 里面先 `$widget = array('name' => $name, ...)` + * → 紧接着 `$widget = array_merge($widget, $options)` ← 关键 + * `$options` 就是 `$this->widget_options`,其中的 `'name'` + * **把前面的 false 覆盖掉了**。所以注册表里名字一直是好的。 + * + * 实测(老代码):`$widget->name` = false,但 + * `$wp_registered_widgets['ad-1']['name']` = '图片广告' —— 名字没丢。 + * 也就是说「用户找不到挂件」的真实原因是后台走了区块编辑器、 + * 没有拖放面板,与本构造函数的实参无关(开关见文件上方)。 + * + * ── 那为什么还是改了 ──────────────────────────────────────── + * ① 名字配在 `$widget_ops` 里是靠 array_merge **顺带**覆盖生效的, + * 属于隐式行为;显式走第 2 参是 WP 文档写法,读代码的人不用 + * 再去追 array_merge 才敢确认名字有没有生效。 + * ② `$this->name` 在整个 WP 里有多处直接读(例如区块编辑器的 + * 挂件类型接口),值是 false 时行为取决于调用方是否兜底 —— + * 这次侥幸没事,不代表以后没事。 + * + * 第 1 参显式写 'ad':$id_base 决定 option 名(widget_ad)。 + * 库里已经有用户的实例,**id_base 一旦变了配置就全丢**。 + * 原来传 false 时 WP 靠类名推导出 'ad'(不是 widget_ad,它会把 + * wp_/widget_ 前缀剥掉),效果一样 —— 写出来是为了不依赖推导。 */ $widget_ops = array( - 'name' => __('图片广告', 'kratos'), 'description' => __('显示自定义图片广告的工具', 'kratos'), ); - parent::__construct(false, false, $widget_ops); + parent::__construct('ad', __('图片广告', 'kratos'), $widget_ops); } public function widget($args, $instance) @@ -518,12 +599,16 @@ class widget_about extends WP_Widget { public function __construct() { + /* 名字走第 2 参(工单 #23,完整理由与实测见 widget_ad 的注释): + * 原来把名字塞在 `$widget_ops['name']` 里,靠 + * `wp_register_sidebar_widget()` 里 `array_merge($widget, $options)` + * 顺带覆盖才生效 —— 能用,但是隐式的。显式传更清楚。 + * 第 1 参显式写 'about',保住 option 名 widget_about —— 线上已有实例。 */ $widget_ops = array( - 'name' => __('个人简介', 'kratos'), 'description' => __('可跳转后台的个人简介展示工具', 'kratos'), ); - parent::__construct(false, false, $widget_ops); + parent::__construct('about', __('个人简介', 'kratos'), $widget_ops); } /** @@ -788,12 +873,13 @@ class widget_tags extends WP_Widget { public function __construct() { + /* 名字走第 2 参(工单 #23,完整理由与实测见 widget_ad 的注释)。 + * 第 1 参写 'tags',保住 option 名 widget_tags。 */ $widget_ops = array( - 'name' => __('标签聚合', 'kratos'), 'description' => __('文章标签的展示工具', 'kratos'), ); - parent::__construct(false, false, $widget_ops); + parent::__construct('tags', __('标签聚合', 'kratos'), $widget_ops); } public function widget($args, $instance) @@ -865,12 +951,13 @@ class widget_posts extends WP_Widget { public function __construct() { + /* 名字走第 2 参(工单 #23,完整理由与实测见 widget_ad 的注释)。 + * 第 1 参写 'posts',保住 option 名 widget_posts —— 线上已有实例。 */ $widget_ops = array( - 'name' => __('文章聚合', 'kratos'), 'description' => __('展示最热、随机、最新文章的工具', 'kratos'), ); - parent::__construct(false, false, $widget_ops); + parent::__construct('posts', __('文章聚合', 'kratos'), $widget_ops); } public function widget($args, $instance) @@ -1009,8 +1096,14 @@ class widget_recent_comments extends WP_Widget { public function __construct() { + /* 名字只走第 2 参(工单 #23,理由见 widget_ad 的注释)。 + * + * 3.2.52 这里曾同时写了两处:`$widget_ops` 里带 'name',第 2 参也传名字。 + * 两处一致时不会出问题,但配两处会让"名字到底在哪配"产生歧义。 + * 统一成第 2 参:这是 WP 文档写法,也不用依赖 + * `wp_register_sidebar_widget()` 里 `array_merge($widget, $options)` + * 那层覆盖 —— 覆盖确实管用,但读代码的人得追进去才知道。 */ $widget_ops = array( - 'name' => __('最近评论', 'kratos'), 'description' => __('带头像与摘要的最近评论,替代 Comments Widget Plus 插件', 'kratos'), ); diff --git a/style.css b/style.css index 0ccf698..1239d36 100644 --- a/style.css +++ b/style.css @@ -1,7 +1,7 @@ /* Theme Name: Kratos_Yang Text Domain: kratos_Yang -Version: 3.2.52 +Version: 3.2.53 Requires PHP: 7.0 Description: 这是一个Kratos主题的分支版本,用来增加一些定制化功能。 Tags: 博客, 双栏, 响应式, 自定义背景, 自定义颜色, 自定义图标, 自定义菜单, 特色图像, 收录优化, 邮件中心, 主题选项, 小工具, 文章置顶, 无障碍友好