263 lines
12 KiB
PHP
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') : '×')
|
|
. '</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');
|
|
}
|