true, 'text' => __('发布', 'aksrt'), 'radius' => 20, 'class' => 'jb-blue', 'types' => []]; // Single source: header_newposts_enabled (zibll nav_newposts). // FacadeBulk maps publish_btn to the same setting. $types = is_array($cfg['types'] ?? null) ? $cfg['types'] : []; if (!$types) { $types = ['post']; } $cfg['types'] = $types; if (empty($cfg['class'])) { $cfg['class'] = 'jb-blue'; } return $cfg; } endif; if (!function_exists('aksrt_get_new_add_actions')) : /** * Build multi-type publish actions. * * @param string[] $types post|topic|product * @return list */ function aksrt_get_new_add_actions(array $types = ['post']): array { $out = []; foreach ($types as $type) { $type = sanitize_key((string) $type); if ($type === 'post') { // Front submit page may be unset → aksrt_get_new_post_url() returns ''. // Never drop the publish chip for that: fall back to WP post-new. $url = function_exists('aksrt_get_new_post_url') ? (string) aksrt_get_new_post_url() : ''; if ($url === '') { $url = admin_url('post-new.php'); } $out[] = [ 'type' => 'post', 'url' => $url, 'label' => __('写文章', 'aksrt'), 'icon' => 'fas fa-file-alt', ]; } } return $out; } endif; if (!function_exists('aksrt_normalize_header_cta_label')) : /** * Normalize CTA label HTML: map FA4 classes and keep a single leading icon. */ function aksrt_normalize_header_cta_label(string $label, string $fallback_icon = 'fas fa-pen'): string { $label = trim($label); if ($label === '') { return ' ' . esc_html__('发布', 'aksrt'); } $replacements = [ 'fa-file-text-o' => 'fa-file-alt', 'fa-file-text' => 'fa-file-alt', 'fa-pencil-square-o' => 'fa-edit', 'fa-pencil' => 'fa-pen', 'fa-comments-o' => 'fa-comments', 'fa-clock-o' => 'fa-clock', 'fa-calendar-check-o' => 'fa-calendar-check', 'fa-diamond' => 'fa-gem', ]; $label = strtr($label, $replacements); $label = preg_replace('/\bclass=(["\'])fa\s+/', 'class=$1fas ', $label) ?? $label; $label = preg_replace('/ .fa). $label = '' . esc_html(wp_strip_all_tags($label)) . ''; } else { $label = preg_replace( '/(<\/i>)\s*([^<].*)$/u', '$1$2', $label ) ?? $label; } return $label; } endif; if (!function_exists('aksrt_render_new_add_btns')) : /** * Multi-type publish button (zibll newadd-btns). * * @param string[] $types */ function aksrt_render_new_add_btns(array $types, string $class = '', string $label = ''): string { $actions = aksrt_get_new_add_actions($types); if (!$actions) { // Last resort: keep a write-post entry so the top-nav chip is never blank. $fallback = function_exists('aksrt_get_new_post_url') ? (string) aksrt_get_new_post_url() : ''; if ($fallback === '') { $fallback = admin_url('post-new.php'); } $actions = [[ 'type' => 'post', 'url' => $fallback, 'label' => __('写文章', 'aksrt'), 'icon' => 'fas fa-file-alt', ]]; } if ($label === '') { $label = __('发布', 'aksrt'); } $label_html = aksrt_normalize_header_cta_label((string) $label, 'fas fa-pen'); // Split paint classes vs wrapper tokens. $class_tokens = preg_split('/\s+/', trim($class), -1, PREG_SPLIT_NO_EMPTY) ?: []; $cta_tokens = []; $wrap_tokens = ['newadd-btns']; foreach ($class_tokens as $token) { if ($token === 'newadd-btns') { continue; } if ($token === 'btn-primary' || $token === 'but' || $token === 'navbar-cta' || $token === 'radius' || $token === 'main-radius' || $token === 'mini-radius' || str_starts_with($token, 'jb-') || str_starts_with($token, 'b-')) { $cta_tokens[] = $token; continue; } $wrap_tokens[] = $token; } if (!$cta_tokens) { $cta_tokens[] = 'jb-blue'; } if (!in_array('but', $cta_tokens, true)) { $cta_tokens[] = 'but'; } $cta_class = trim(implode(' ', array_unique($cta_tokens))); if (count($actions) === 1) { $a = $actions[0]; return '' . $label_html . ''; } // zibll: span.newadd-btns.hover-show > toggle chip + .hover-show-con.drop-newadd // Paint classes (jb-*, but, radius) MUST live on the toggle — wrapper is layout-only // (background forced transparent). Bare navbar-but has no .navbar-but-cluster shell. // data-aksrt-newadd: JS may portal menu to body so chip width cannot track menu. $html = ''; $html .= '' . $label_html . ''; $html .= ''; return $html; } endif; if (!function_exists('aksrt_render_header_menu_buttons')) : /** * Publish + optional VIP open button for header CTA. */ function aksrt_render_header_menu_buttons(): string { $cfg = aksrt_get_header_newposts_config(); $html = ''; if (!empty($cfg['enabled'])) { // zibll default: but nowave jb-blue (+ radius). $class = 'but nowave navbar-newposts'; $skin = trim((string) ($cfg['class'] ?? '')); if ($skin === '') { $skin = 'jb-blue'; } $class .= ' ' . $skin; $radius = (int) ($cfg['radius'] ?? 20); $pill = !empty($cfg['radius_pill']) || $radius >= 16; if ($pill && !str_contains($class, 'radius')) { $class .= ' radius'; } $radius_attr = $radius > 0 ? ' data-radius="' . esc_attr((string) $radius) . '" style="--navbar-cta-radius:' . $radius . 'px"' : ''; $label = (string) ($cfg['text'] ?? __('发布', 'aksrt')); $btn = aksrt_render_new_add_btns($cfg['types'] ?? ['post'], $class, $label); if ($btn !== '') { $html .= ''; } } // VIP open CTA for guests / non-VIP (zibll: .pay-vip modal). $user_id = get_current_user_id(); $show_vip = false; if (class_exists('\AKSRT\Settings\Settings')) { $vs = \AKSRT\Settings\Settings::get_payment_vip_settings(); $show_vip = !empty($vs['enabled']) && !empty(\AKSRT\Settings\Settings::get_header_nav_settings()['nav_pay_vip']); } if ($show_vip) { $is_vip = false; if ($user_id > 0 && function_exists('aksrt_get_user_vip_level')) { $is_vip = (int) aksrt_get_user_vip_level($user_id) > 0; } if (!$is_vip) { $cls = $user_id > 0 ? 'pay-vip' : 'signin-loader'; $hover = ''; if (class_exists('\AKSRT\Content\VipService')) { $svc = \AKSRT\Content\VipService::get_instance(); if (method_exists($svc, 'render_vip_card')) { $cards = $svc->render_vip_card(1, $user_id) . $svc->render_vip_card(2, $user_id); if ($cards !== '') { $hover = ''; } } } $html .= ''; } } return $html; } endif;