Files
wordpress-theme-aksrt/inc/helpers/aksrt-header-menu-buttons.php
T

246 lines
8.5 KiB
PHP

<?php
/**
* Header multi-function cluster (zibll zib_menu_button publish/VIP subset).
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_get_header_newposts_config')) :
/**
* @return array{enabled:bool,text:string,radius:int,class:string,types:string[]}
*/
function aksrt_get_header_newposts_config(): array {
$cfg = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_header_newposts_config()
: ['enabled' => true, 'text' => __('发布', 'aksrt'), 'radius' => 20, 'class' => ''];
$all = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
// Prefer publish_btn from header nav when newposts not explicitly set.
$nav = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_header_nav_settings()
: ['publish_btn' => true];
if (empty($cfg['enabled']) && !empty($nav['publish_btn'])) {
$cfg['enabled'] = true;
}
$types = [];
if (!empty($all['header_newposts_types']) && is_array($all['header_newposts_types'])) {
$types = array_values(array_filter(array_map('sanitize_key', $all['header_newposts_types'])));
}
if (!$types) {
$types = ['post'];
if (class_exists('\AKSRT\Settings\Settings')) {
$forum = \AKSRT\Settings\Settings::get_forum_settings();
$shop = \AKSRT\Settings\Settings::get_shop_settings();
if (!empty($forum['enabled'])) {
$types[] = 'topic';
}
if (!empty($shop['enabled'])) {
$types[] = 'product';
}
}
}
$cfg['types'] = $types;
return $cfg;
}
endif;
if (!function_exists('aksrt_get_new_add_actions')) :
/**
* Build multi-type publish actions.
*
* @param string[] $types post|topic|product
* @return list<array{type:string,url:string,label:string,icon:string}>
*/
function aksrt_get_new_add_actions(array $types = ['post']): array {
$out = [];
foreach ($types as $type) {
$type = sanitize_key((string) $type);
if ($type === 'post') {
$url = function_exists('aksrt_get_new_post_url') ? aksrt_get_new_post_url() : admin_url('post-new.php');
if ($url === '') {
continue;
}
$out[] = [
'type' => 'post',
'url' => $url,
'label' => __('写文章', 'aksrt'),
// FA5 free solid names (avoid FA4 aliases like file-text-o).
'icon' => 'fas fa-file-alt',
];
} elseif ($type === 'topic') {
$url = function_exists('aksrt_get_forum_compose_url') ? aksrt_get_forum_compose_url() : '';
if ($url === '') {
continue;
}
$out[] = [
'type' => 'topic',
'url' => $url,
'label' => __('发帖', 'aksrt'),
'icon' => 'fas fa-comments',
];
} elseif ($type === 'product') {
$url = '';
if (function_exists('aksrt_get_product_edit_url')) {
$url = (string) aksrt_get_product_edit_url();
}
if ($url === '') {
$url = admin_url('post-new.php?post_type=aksrt_product');
}
$out[] = [
'type' => 'product',
'url' => $url,
'label' => __('发布商品', 'aksrt'),
'icon' => 'fas fa-shopping-bag',
];
}
}
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 '<i class="' . esc_attr($fallback_icon) . '" aria-hidden="true"></i> ' . esc_html__('发布', 'aksrt');
}
// Common FA4 → FA5 renames used in admin defaults.
$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);
// Ensure icon uses fas (FA5 solid) when only bare "fa " is present.
$label = preg_replace('/\bclass=(["\'])fa\s+/', 'class=$1fas ', $label) ?? $label;
$label = preg_replace('/<i\s+class=(["\'])(?!fas\b|far\b|fab\b)/', '<i class=$1fas ', $label) ?? $label;
// If label is plain text without icon markup, prefix default icon.
if (stripos($label, '<i') === false) {
$label = '<i class="' . esc_attr($fallback_icon) . '" aria-hidden="true"></i> <span class="navbar-cta-text">' . esc_html(wp_strip_all_tags($label)) . '</span>';
} else {
// Wrap remaining text nodes for flex alignment without raw text siblings.
$label = preg_replace(
'/(<\/i>)\s*([^<].*)$/u',
'$1 <span class="navbar-cta-text">$2</span>',
$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) {
return '';
}
if ($label === '') {
$label = __('发布', 'aksrt');
}
$label_html = aksrt_normalize_header_cta_label((string) $label, 'fas fa-pen');
$class = trim('newadd-btns ' . $class);
if (count($actions) === 1) {
$a = $actions[0];
// Prefer configured label; icon already embedded after normalize.
return '<a rel="nofollow" class="' . esc_attr(trim($class . ' but navbar-cta')) . '" href="' . esc_url($a['url']) . '">'
. $label_html
. '</a>';
}
$html = '<span class="' . esc_attr($class . ' hover-show') . '">';
$html .= '<a href="javascript:;" class="but newadd-btns__toggle navbar-cta" rel="nofollow">'
. $label_html
. ' <i class="fas fa-caret-down" aria-hidden="true"></i></a>';
$html .= '<div class="hover-show-con dropdown-menu drop-newadd">';
foreach ($actions as $a) {
$html .= '<a rel="nofollow" class="newadd-btns__item" href="' . esc_url($a['url']) . '">';
$html .= '<i class="' . esc_attr($a['icon']) . '" aria-hidden="true"></i> '
. '<span>' . esc_html($a['label']) . '</span>';
$html .= '</a>';
}
$html .= '</div></span>';
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'])) {
$class = 'btn-primary navbar-newposts';
if (!empty($cfg['class'])) {
$class .= ' ' . $cfg['class'];
}
$radius = (int) ($cfg['radius'] ?? 20);
// Radius applied via CSS class variable to avoid style attribute overriding flex.
$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 .= '<div class="navbar-form navbar-right navbar-but"' . $radius_attr . '>' . $btn . '</div>';
}
}
// 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 = '<div class="hover-show-con sub-menu sub-vip-card">' . $cards . '</div>';
}
}
}
$html .= '<div class="navbar-form navbar-right navbar-vip">';
// zibll: span.hover-show wraps button + .hover-show-con.sub-vip-card
$html .= '<span class="hover-show inline-block navbar-vip-hover">';
$html .= '<a class="but jb-red radius payvip-icon navbar-cta ' . esc_attr($cls) . '" href="javascript:;"'
. ($user_id > 0 ? ' vip-level="1"' : '') . '>';
$html .= '<i class="fas fa-gem" aria-hidden="true"></i>'
. '<span class="navbar-cta-text">' . esc_html__('开通会员', 'aksrt') . '</span>';
$html .= '</a>' . $hover . '</span></div>';
}
}
return $html;
}
endif;