fix(frontend): 修复前台页面编辑弹窗并 1:1 复刻参考主题
远端加载的弹窗在 admin-ajax 上下文里拿不到查询对象,enabled() 恒为假,直接返回 success:false;而 AksrtRequest.responseError 只读 message/data.message,读不到 msg,遂报「请求失败(HTTP 200)」。 改为参考主题原生架构:wp_footer 直出 #modal_admin_set,提交走 vendored main.js 的 aksrt_ajax 契约,不再有 AJAX 取 HTML。 对齐参考主题 zib-frontend-set.php: - 弹窗补齐 aria-hidden=false、win-ajax-replace、role=document - 隐藏字段改用 taxonomy + post_type - 字段顺序与 is_page 分支(标题样式、widgets_register、容器位置) - 多选 checkbox 改 name="id[]",描述允许富文本 - 模块布局指向定制器小工具面板 - term 保存使用 POST 的 taxonomy 字段 清理不再使用的 assets/js/page-admin-set.js。 新增 frontend-page-edit-harness.php 覆盖门禁、渲染与各保存分支。
This commit is contained in:
@@ -150,11 +150,11 @@ test('split upload ships a full chunk protocol: routes, merge pipeline, and clie
|
||||
assert.doesNotMatch(read('src/Core/ScriptsPart1c.php'), /is_split_upload|split_minimum_size/);
|
||||
});
|
||||
|
||||
test('frontend page edit ships gate, float button, modal, and whitelisted save', () => {
|
||||
test('frontend page edit ships gate, footer modal, and legacy ajax-save contract', () => {
|
||||
const pageAdminSet = read('src/Frontend/PageAdminSet.php');
|
||||
const pageAdminJs = read('assets/js/page-admin-set.js');
|
||||
const floatButtons = read('inc/helpers/aksrt-float-buttons.php');
|
||||
const bootstrap = read('functions.php');
|
||||
const mainJs = read('assets/js/runtime/main.js');
|
||||
|
||||
assert.match(bootstrap, /\\AKSRT\\Frontend\\PageAdminSet::get_instance\(\)->init\(\)/);
|
||||
assert.match(pageAdminSet, /public static function enabled\(\): bool/);
|
||||
@@ -163,27 +163,59 @@ test('frontend page edit ships gate, float button, modal, and whitelisted save',
|
||||
assert.match(pageAdminSet, /is_page_template\('templates\/pages\/page-submit\.php'\)/);
|
||||
assert.match(pageAdminSet, /is_page_template\('templates\/pages\/page-posts-navs\.php'\)/);
|
||||
|
||||
// Float bar gains the same extension point the reference theme hooks into.
|
||||
// Reference parity: the gear float button opens the footer-rendered bootstrap modal.
|
||||
assert.match(floatButtons, /apply_filters\('aksrt_float_right_buttons', \$btn, \$is_mobile\)/);
|
||||
assert.match(pageAdminSet, /add_filter\('aksrt_float_right_buttons', \[\$this, 'float_button'\], 10, 2\)/);
|
||||
assert.match(pageAdminSet, /data-aksrt-modal="remote"/);
|
||||
assert.match(pageAdminSet, /check_ajax_referer\('aksrt_frontend_set', '_wpnonce'\)/);
|
||||
assert.match(pageAdminSet, /add_action\('wp_footer', \[\$this, 'render_modal'\], 10\)/);
|
||||
assert.match(pageAdminSet, /data-toggle="modal" data-target="#modal_admin_set"/);
|
||||
assert.match(pageAdminSet, /class="modal fade" id="modal_admin_set" tabindex="-1" role="dialog" aria-hidden="false" win-ajax-replace="modal_admin_set"/);
|
||||
assert.match(pageAdminSet, /class="modal-content page-set-modal"/);
|
||||
assert.match(pageAdminSet, /wp_nonce_field\('aksrt_frontend_set', '_wpnonce', true, false\)/);
|
||||
// Reference hidden inputs: type + taxonomy + post_type + id travel with the submit.
|
||||
assert.match(pageAdminSet, /name="action" value="aksrt_frontend_set_save"/);
|
||||
assert.match(pageAdminSet, /name="type" value="' . esc_attr\(\$type\)/);
|
||||
assert.match(pageAdminSet, /name="taxonomy" value="' . esc_attr\(\$taxonomy\)/);
|
||||
assert.match(pageAdminSet, /name="post_type" value="' . esc_attr\(\$post_type\)/);
|
||||
// 模块布局 opens the customizer widgets panel and returns to the current URL.
|
||||
assert.match(pageAdminSet, /admin_url\('customize\.php'\)/);
|
||||
assert.match(pageAdminSet, /'autofocus' => \['panel' => 'widgets'\]/);
|
||||
|
||||
// Modal + save endpoints; save is whitelisted and preserves other meta keys.
|
||||
assert.match(pageAdminSet, /add_action\('wp_ajax_aksrt_frontend_set_modal', \[\$this, 'ajax_modal'\]\)/);
|
||||
assert.match(pageAdminSet, /add_action\('wp_ajax_aksrt_frontend_set_save', \[\$this, 'ajax_save'\]\)/);
|
||||
// Modal footer mirrors the reference: 模块布局 / 后台编辑 / 确认修改 (wp-ajax-submit).
|
||||
assert.match(pageAdminSet, /esc_html__\('模块布局', 'aksrt'\)/);
|
||||
assert.match(pageAdminSet, /esc_html__\('后台编辑', 'aksrt'\)/);
|
||||
assert.match(pageAdminSet, /esc_html__\('确认修改', 'aksrt'\)/);
|
||||
assert.match(pageAdminSet, /class="but c-yellow-2 padding-lg"/);
|
||||
assert.match(pageAdminSet, /class="but c-yellow padding-lg"/);
|
||||
assert.match(pageAdminSet, /class="but jb-blue padding-lg wp-ajax-submit"/);
|
||||
|
||||
// Fields replicate the reference input construct and map to AKSRT's post meta.
|
||||
assert.match(pageAdminSet, /private function render_inputs\(array \$inputs\): string/);
|
||||
assert.match(pageAdminSet, /class="heading col-xs-3 text-right"/);
|
||||
assert.match(pageAdminSet, /class="option col-xs-8"/);
|
||||
assert.match(pageAdminSet, /\\AKSRT\\Core\\PostMetaBox::META_KEY/);
|
||||
assert.match(pageAdminSet, /\\AKSRT\\Core\\DomainModel::POST_VIEW_COUNT_KEY/);
|
||||
assert.match(pageAdminSet, /update_post_meta\(\$post_id, '_aksrt_like_count', max\(0, \(int\) \$_POST\['like'\]\)\)/);
|
||||
assert.match(pageAdminSet, /wp_update_term\(\$term_id, \(string\) \$term->taxonomy, \$data\)/);
|
||||
assert.match(pageAdminSet, /set_post_format\(\$post_id, \$format === 'standard' \? '' : \$format\)/);
|
||||
// Page branch: 标题样式 + 模块布局(widgets_register) + 容器位置.
|
||||
assert.match(pageAdminSet, /esc_attr\(\(string\) \(\$meta\['id'\] \?\? ''\)\) \. '\[\]" id="'/);
|
||||
assert.match(pageAdminSet, /'page_header_style'/);
|
||||
assert.match(pageAdminSet, /update_post_meta\(\$post_id, 'widgets_register', \$register \? '1' : ''\)/);
|
||||
assert.match(pageAdminSet, /update_post_meta\(\$post_id, 'widgets_register_container', \$containers\)/);
|
||||
// Reference checkbox semantics: unchecked boxes never submit, so both are written unconditionally.
|
||||
assert.match(pageAdminSet, /\$meta\['no_article-navs'\] = !empty\(\$_POST\['no_article-navs'\]\)/);
|
||||
assert.match(pageAdminSet, /\$meta\['article_maxheight_xz'\] = !empty\(\$_POST\['article_maxheight_xz'\]\)/);
|
||||
// The geometry mirrors the reference construct (row + heading + option, \n separators).
|
||||
assert.match(pageAdminSet, /'<div class="mb10 row' \. esc_attr\(\$class\) \. '">' \. "\\n"/);
|
||||
|
||||
// Client submits through the shared modal runtime contract; the ajax action
|
||||
// comes from the form's hidden field that the modal endpoint embeds.
|
||||
assert.match(pageAdminJs, /form\.aksrt-admin-set-form/);
|
||||
assert.match(pageAdminJs, /input\[name="action"\]/);
|
||||
assert.match(pageAdminJs, /window\.location\.reload/);
|
||||
assert.match(pageAdminSet, /'html' => \$html/);
|
||||
// Save runs under the vendored main.js aksrt_ajax contract ({msg,reload}).
|
||||
assert.match(pageAdminSet, /add_action\('wp_ajax_aksrt_frontend_set_save', \[\$this, 'ajax_save'\]\)/);
|
||||
assert.match(pageAdminSet, /check_ajax_referer\('aksrt_frontend_set', '_wpnonce'\)/);
|
||||
assert.match(pageAdminSet, /wp_send_json\(\['msg' => __\('保存成功,正在刷新页面', 'aksrt'\), 'reload' => true\]\)/);
|
||||
assert.match(mainJs, /jQuery\.fn\.serializeObject = function/);
|
||||
assert.match(mainJs, /if \(n\.reload\) \{/);
|
||||
// The dedicated fetch-submit client is gone: vendored main.js owns the flow.
|
||||
assert.equal(fs.existsSync(path.join(root, 'assets/js/page-admin-set.js')), false);
|
||||
});
|
||||
|
||||
test('float toolbar config reaches the tinymce plugin with reference-context buttons', () => {
|
||||
@@ -227,3 +259,9 @@ test('split upload runtime contract harness passes', () => {
|
||||
const output = execFileSync('php', [harness], { encoding: 'utf8' });
|
||||
assert.match(output, /Split upload harness passed/);
|
||||
});
|
||||
|
||||
test('frontend page edit runtime contract harness passes', () => {
|
||||
const harness = path.join(root, 'tests', 'widget-system', 'frontend-page-edit-harness.php');
|
||||
const output = execFileSync('php', [harness], { encoding: 'utf8' });
|
||||
assert.match(output, /Frontend page edit harness passed/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user