Files

263 lines
12 KiB
PHP

<?php
/**
* Social sharing and poster runtime.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_share_platform_labels')) {
/** @return array<string,string> */
function aksrt_share_platform_labels(): array {
return [
'qzone' => __('QQ空间', 'aksrt'), 'weibo' => __('微博', 'aksrt'), 'qq' => __('QQ好友', 'aksrt'),
'facebook' => 'Facebook', 'twitter' => 'X', 'telegram' => 'Telegram', 'whatsapp' => 'WhatsApp',
'linkedin' => 'LinkedIn', 'reddit' => 'Reddit', 'line' => 'LINE', 'vk' => 'VK',
'email' => __('邮件', 'aksrt'), 'poster' => __('海报分享', 'aksrt'), 'copy' => __('复制链接', 'aksrt'),
];
}
}
if (!function_exists('aksrt_active_share_items')) {
/** @return string[] */
function aksrt_active_share_items(): array {
$config = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_share_settings() : [];
return !empty($config['enabled']) && is_array($config['items'] ?? null) ? $config['items'] : [];
}
}
if (!function_exists('aksrt_build_share_url')) {
/** @param array<string,string> $params */
function aksrt_build_share_url(string $base, array $params): string {
$query = [];
foreach ($params as $key => $value) {
if ($value !== '') {
$query[] = rawurlencode($key) . '=' . rawurlencode($value);
}
}
return $query ? $base . (str_contains($base, '?') ? '&' : '?') . implode('&', $query) : $base;
}
}
if (!function_exists('aksrt_share_context')) {
/** @return array{id:int,title:string,link_title:string,desc:string,image:string,url:string,tags:string} */
function aksrt_share_context($post = null): array {
$post = get_post($post);
if (!$post instanceof WP_Post) {
return ['id' => 0, 'title' => '', 'link_title' => '', 'desc' => '', 'image' => '', 'url' => '', 'tags' => ''];
}
$subtitle = class_exists('\\AKSRT\\Core\\PostMetaBox')
? trim((string) \AKSRT\Core\PostMetaBox::get_meta_value((int) $post->ID, 'subtitle', ''))
: '';
$title = trim(wp_strip_all_tags(get_the_title($post))) . $subtitle;
$desc = trim(wp_strip_all_tags((string) get_the_excerpt($post)));
if ($desc === '') {
$desc = wp_trim_words(wp_strip_all_tags(strip_shortcodes($post->post_content)), 70, '...');
}
$url = (string) (get_permalink($post) ?: '');
if (is_user_logged_in() && class_exists('\\AKSRT\\Settings\\Settings') && \AKSRT\Settings\Settings::affiliate_enabled()
&& class_exists('\\AKSRT\\Payment\\ReferralAttribution')) {
$link = \AKSRT\Payment\ReferralAttribution::get_instance()->create_link(get_current_user_id(), $url);
if (!empty($link['url'])) {
$url = (string) $link['url'];
}
}
$tags = '';
if ($post->post_type === 'post') {
$author = get_the_author_meta('display_name', (int) $post->post_author);
$cats = get_the_category((int) $post->ID);
$tags = sprintf(__('作者: %s', 'aksrt'), $author);
if (!empty($cats[0])) {
$tags .= sprintf(__(' · 分类: %s', 'aksrt'), $cats[0]->name);
}
}
$site = (string) get_bloginfo('name');
return [
'id' => (int) $post->ID,
'title' => $title,
'link_title' => $title . ($site !== '' ? ' - ' . $site : ''),
'desc' => $desc,
'image' => (string) (get_the_post_thumbnail_url($post, 'full') ?: ''),
'url' => $url,
'tags' => $tags,
];
}
}
if (!function_exists('aksrt_share_platform_href')) {
/** @param array<string,mixed> $ctx */
function aksrt_share_platform_href(string $key, array $ctx): string {
$url = (string) ($ctx['url'] ?? '');
$title = (string) ($ctx['link_title'] ?? '');
$desc = (string) ($ctx['desc'] ?? '');
$image = (string) ($ctx['image'] ?? '');
switch ($key) {
case 'qzone': return aksrt_build_share_url('https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey', ['url' => $url, 'title' => $title, 'pics' => $image, 'summary' => $desc]);
case 'weibo': return aksrt_build_share_url('https://service.weibo.com/share/share.php', ['url' => $url, 'title' => $title, 'pic' => $image, 'searchPic' => 'false']);
case 'qq': return aksrt_build_share_url('https://connect.qq.com/widget/shareqq/index.html', ['url' => $url, 'title' => $title, 'pics' => $image, 'desc' => $desc]);
case 'facebook': return aksrt_build_share_url('https://www.facebook.com/sharer/sharer.php', ['u' => $url]);
case 'twitter': return aksrt_build_share_url('https://twitter.com/intent/tweet', ['url' => $url, 'text' => $title]);
case 'telegram': return aksrt_build_share_url('https://t.me/share/url', ['url' => $url, 'text' => $title]);
case 'whatsapp': return aksrt_build_share_url('https://api.whatsapp.com/send', ['text' => trim($title . ' ' . $url)]);
case 'linkedin': return aksrt_build_share_url('https://www.linkedin.com/sharing/share-offsite/', ['url' => $url]);
case 'reddit': return aksrt_build_share_url('https://www.reddit.com/submit', ['url' => $url, 'title' => $title]);
case 'line': return aksrt_build_share_url('https://social-plugins.line.me/lineit/share', ['url' => $url]);
case 'vk': return aksrt_build_share_url('https://vk.com/share.php', ['url' => $url, 'title' => $title, 'image' => $image]);
case 'email': return aksrt_build_share_url('mailto:', ['subject' => $title, 'body' => trim($title . "\n" . $url . ($desc !== '' ? "\n\n" . $desc : ''))]);
default: return '#';
}
}
}
if (!function_exists('aksrt_get_share_buttons')) {
/** @param string[] $items */
function aksrt_get_share_buttons(array $items, $post = null): string {
$ctx = aksrt_share_context($post);
if ($ctx['id'] <= 0 || $ctx['url'] === '') {
return '';
}
$labels = aksrt_share_platform_labels();
$html = '';
foreach ($items as $key) {
$key = sanitize_key((string) $key);
if (!isset($labels[$key])) {
continue;
}
$icon_key = $key === 'email' ? 'd-email' : $key . '-color';
$icon = function_exists('aksrt_icon_markup') ? aksrt_icon_markup('zibsvg-' . $icon_key) : '';
$attr = '';
$target = ' target="_blank"';
$href = aksrt_share_platform_href($key, $ctx);
if ($key === 'poster') {
$target = '';
$attr = ' poster-share="' . esc_attr((string) $ctx['id']) . '"';
} elseif ($key === 'copy') {
$target = '';
$attr = ' data-clipboard-text="' . esc_attr($ctx['url']) . '" data-clipboard-tag="' . esc_attr__('链接', 'aksrt') . '"';
}
$safe_href = $href === '#' ? '#' : esc_url($href);
$html .= '<a rel="nofollow noopener" class="share-btn ' . esc_attr($key) . '"' . $target . $attr
. ' title="' . esc_attr($labels[$key]) . '" href="' . $safe_href . '"><icon>' . $icon
. '</icon><text>' . esc_html($labels[$key]) . '</text></a>';
}
return $html;
}
}
if (!function_exists('aksrt_get_share_html')) {
function aksrt_get_share_html(string $class = '', $post = null): string {
$buttons = aksrt_get_share_buttons(aksrt_active_share_items(), $post);
return $buttons === '' ? '' : '<div' . ($class !== '' ? ' class="' . esc_attr($class) . '"' : '') . '>' . $buttons . '</div>';
}
}
if (!function_exists('aksrt_render_share_buttons')) {
/** @param array<string,mixed> $args */
function aksrt_render_share_buttons(array $args = []): void {
echo aksrt_get_share_html(!empty($args['horizontal']) ? 'horizontal' : '', $args['post'] ?? null); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
if (!function_exists('aksrt_get_post_share_btn')) {
function aksrt_get_post_share_btn($post = null, string $class = '', bool $modal = false, bool $show_text = true): string {
$post = get_post($post);
if (!$post instanceof WP_Post || aksrt_active_share_items() === []) {
return '';
}
$icon = function_exists('aksrt_icon_markup') ? aksrt_icon_markup('zibsvg-share') : '<i class="fa fas fa-share-alt"></i>';
$text = $show_text ? '<text>' . esc_html__('分享', 'aksrt') . '</text>' : '';
if ($modal || wp_is_mobile()) {
$count = max(1, count(aksrt_active_share_items()));
$url = add_query_arg(['action' => 'aksrt_share_modal', 'id' => (int) $post->ID, 'nonce' => wp_create_nonce('aksrt_public_nonce')], admin_url('admin-ajax.php'));
return '<a class="' . esc_attr(trim($class . ' aksrt-modal-link')) . '" href="' . esc_url($url) . '" data-aksrt-modal="remote" data-aksrt-modal-url="' . esc_url($url)
. '" data-aksrt-modal-class="modal-mini" data-aksrt-modal-height="' . esc_attr((string) min(520, 180 + (int) ceil($count / 5) * 72))
. '" data-aksrt-modal-mobile-bottom="true" data-aksrt-modal-cache="false">' . $icon . $text . '</a>';
}
return '<span class="hover-show dropup ' . esc_attr($class) . '">' . $icon . $text
. '<div class="zib-widget hover-show-con share-button dropdown-menu">' . aksrt_get_share_html('', $post) . '</div></span>';
}
}
if (!function_exists('aksrt_share_modal_ajax')) {
function aksrt_share_modal_ajax(): void {
check_ajax_referer('aksrt_public_nonce', 'nonce');
$post = get_post(absint($_REQUEST['id'] ?? 0));
if (!$post instanceof WP_Post || get_post_status($post) !== 'publish') {
status_header(404);
echo '<div class="box-body text-center">' . esc_html__('内容不存在或参数错误', 'aksrt') . '</div>';
exit;
}
$icon = function_exists('aksrt_icon_markup') ? aksrt_icon_markup('zibsvg-share', 'em14') : '';
echo '<div class="modal-colorful-header colorful-bg jb-vip1"><button type="button" class="close" data-aksrt-modal-close aria-label="' . esc_attr__('关闭', 'aksrt') . '">'
. (function_exists('aksrt_icon_markup') ? aksrt_icon_markup('zibsvg-close', 'ic-close') : '&times;')
. '</button><div class="colorful-make"></div><div class="text-center"><div class="em2x">' . $icon
. '</div><div class="mt10 em12 padding-w10"><span class="em09">' . esc_html__('分享内容', 'aksrt') . '</span></div></div></div>'
. aksrt_get_share_html('horizontal', $post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
exit;
}
add_action('wp_ajax_aksrt_share_modal', 'aksrt_share_modal_ajax');
add_action('wp_ajax_nopriv_aksrt_share_modal', 'aksrt_share_modal_ajax');
}
if (!function_exists('aksrt_share_image_data_url')) {
function aksrt_share_image_data_url(string $url): string {
if ($url === '' || !wp_http_validate_url($url)) {
return $url;
}
$key = 'aksrt_share_img_' . md5($url);
$cached = wp_cache_get($key, 'aksrt_share');
if (is_string($cached)) {
return $cached;
}
$response = wp_safe_remote_get($url, ['timeout' => 8, 'redirection' => 3, 'limit_response_size' => 5 * MB_IN_BYTES]);
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
return $url;
}
$mime = strtolower(trim((string) wp_remote_retrieve_header($response, 'content-type')));
$mime = trim(explode(';', $mime)[0]);
if (!in_array($mime, ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], true)) {
return $url;
}
$body = wp_remote_retrieve_body($response);
if ($body === '') {
return $url;
}
$data = 'data:' . $mime . ';base64,' . base64_encode($body);
wp_cache_set($key, $data, 'aksrt_share', HOUR_IN_SECONDS);
return $data;
}
}
if (!function_exists('aksrt_poster_share_data_ajax')) {
function aksrt_poster_share_data_ajax(): void {
check_ajax_referer('aksrt_public_nonce', 'nonce');
$post = get_post(absint($_POST['id'] ?? 0));
if (!$post instanceof WP_Post || get_post_status($post) !== 'publish') {
wp_send_json_error(['message' => __('参数错误,或内容已删除', 'aksrt')], 404);
}
$config = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_share_settings() : [];
if (empty($config['poster_enabled'])) {
wp_send_json_error(['message' => __('海报分享未启用', 'aksrt')], 403);
}
$ctx = aksrt_share_context($post);
$data = [
'url' => esc_url_raw($ctx['url']), 'banner' => esc_url_raw($ctx['image']),
'banner_default' => esc_url_raw((string) ($config['poster_img'] ?? '')),
'banner_spare' => get_template_directory_uri() . '/assets/img/share_img.jpg',
'logo' => esc_url_raw((string) ($config['poster_logo'] ?? '')),
'title' => function_exists('aksrt_str_cut') ? aksrt_str_cut($ctx['title'], 0, 32) : $ctx['title'],
'content' => function_exists('aksrt_str_cut') ? aksrt_str_cut($ctx['desc'], 0, 70) : $ctx['desc'],
'tags' => $ctx['tags'], 'description' => (string) ($config['share_desc'] ?? __('扫一扫 立即查看', 'aksrt')),
];
if (!empty($config['compatible_s'])) {
foreach (['banner', 'banner_default', 'logo'] as $key) {
$data[$key] = aksrt_share_image_data_url((string) $data[$key]);
}
}
wp_send_json_success(apply_filters('aksrt_poster_share_data', $data, $post));
}
add_action('wp_ajax_aksrt_poster_share_data', 'aksrt_poster_share_data_ajax');
add_action('wp_ajax_nopriv_aksrt_poster_share_data', 'aksrt_poster_share_data_ajax');
}