*/
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' => 'fa fas fa-file-alt',
];
}
}
return $out;
}
endif;
if (!function_exists('aksrt_normalize_header_cta_label')) :
/**
* Normalize CTA label HTML: map FA5 classes and keep a single leading icon.
*/
function aksrt_normalize_header_cta_label(string $label, string $fallback_icon = 'fa fas fa-pen'): string {
$label = trim($label);
if ($label === '') {
return ' ' . esc_html__('发布', 'aksrt');
}
if (stripos($label, ' .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' => 'fa fas fa-file-alt',
]];
}
if ($label === '') {
$label = __('发布', 'aksrt');
}
$label_html = aksrt_normalize_header_cta_label((string) $label, 'fa 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 {
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::read_domain('page_display', 'header-nav') : [];
$types = is_array($settings['nav_newposts_btns'] ?? null)
? array_values(array_intersect(array_map('sanitize_key', $settings['nav_newposts_btns']), ['post']))
: ['post'];
if (!$types) {
$types = ['post'];
}
$cfg = [
'enabled' => !isset($settings['nav_newposts']) || !empty($settings['nav_newposts']),
'text' => trim((string) ($settings['nav_newposts_text'] ?? __('发布', 'aksrt'))),
'radius_pill' => !isset($settings['nav_newposts_radius']) || !empty($settings['nav_newposts_radius']),
'class' => sanitize_html_class((string) (($settings['nav_newposts_class'] ?? '') ?: 'jb-blue')),
'types' => $types,
];
$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;
$pill = !empty($cfg['radius_pill']);
if ($pill && !str_contains($class, 'radius')) {
$class .= ' radius';
}
$label = (string) ($cfg['text'] ?? __('发布', 'aksrt'));
$btn = aksrt_render_new_add_btns($cfg['types'] ?? ['post'], $class, $label);
if ($btn !== '') {
$html .= $btn;
}
}
// 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']);
}
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 = '';
}
}
}
// zibll: span.hover-show wraps button + .hover-show-con.sub-vip-card
$html .= '';
$html .= ' 0 ? ' vip-level="1"' : '') . '>';
$html .= ''
. '' . esc_html__('开通会员', 'aksrt') . '';
$html .= '' . $hover . '';
}
}
return $html;
}
endif;