1850 lines
80 KiB
PHP
1850 lines
80 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: Ansico SoMe Plugin
|
|
* Plugin URI: https://ansico.dk/Ansico/Ansico-SoMe-plugin
|
|
* Description: Turn WordPress into your own microblog with comments and likes. Lots of blocks.
|
|
* Version: 1.2.0
|
|
* Author: Andreas Andersen (Ansico)
|
|
* Author URI: https://ansico.dk
|
|
* License: GPL-3.0-or-later
|
|
* License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
|
* Text Domain: ansico-some-plugin
|
|
* Requires at least: 6.4
|
|
* Requires PHP: 7.4
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
if ( ! defined( 'ANSICO_SOME_PLUGIN_VERSION' ) ) {
|
|
define( 'ANSICO_SOME_PLUGIN_VERSION', '1.2.0' );
|
|
}
|
|
|
|
add_filter( 'block_categories_all', 'ansico_register_block_category', 10, 2 );
|
|
function ansico_register_block_category( $categories, $post ) {
|
|
foreach ( $categories as $category ) {
|
|
if ( isset( $category['slug'] ) && 'ansico' === $category['slug'] ) {
|
|
return $categories;
|
|
}
|
|
}
|
|
|
|
array_unshift(
|
|
$categories,
|
|
array(
|
|
'slug' => 'ansico',
|
|
'title' => __( 'Ansico Blocks', 'ansico-some-plugin' ),
|
|
'icon' => null,
|
|
)
|
|
);
|
|
|
|
return $categories;
|
|
}
|
|
|
|
|
|
function ansico_get_micropost_max_chars() {
|
|
$value = get_option( 'ansico_micropost_max_chars', 500 );
|
|
$value = intval( $value );
|
|
return $value > 0 ? $value : 500;
|
|
}
|
|
|
|
add_action( 'admin_menu', 'ansico_register_settings_page' );
|
|
function ansico_register_settings_page() {
|
|
add_options_page(
|
|
'Ansico SoMe Plugin',
|
|
'Ansico SoMe Plugin',
|
|
'manage_options',
|
|
'ansico-some-plugin-settings',
|
|
'ansico_render_settings_page'
|
|
);
|
|
}
|
|
|
|
add_action( 'admin_init', 'ansico_register_settings' );
|
|
function ansico_register_settings() {
|
|
register_setting(
|
|
'ansico_some_plugin_settings',
|
|
'ansico_micropost_max_chars',
|
|
array(
|
|
'type' => 'integer',
|
|
'sanitize_callback' => 'ansico_sanitize_micropost_max_chars',
|
|
'default' => 500,
|
|
)
|
|
);
|
|
|
|
register_setting(
|
|
'ansico_some_plugin_settings',
|
|
'ansico_clean_up_profile_settings',
|
|
array(
|
|
'type' => 'boolean',
|
|
'sanitize_callback' => 'ansico_sanitize_checkbox_setting',
|
|
'default' => false,
|
|
)
|
|
);
|
|
|
|
add_settings_section(
|
|
'ansico_some_plugin_main',
|
|
__( 'Micropost settings', 'ansico-some-plugin' ),
|
|
function() {
|
|
echo '<p>' . esc_html__( 'Settings for Ansico SoMe Plugin.', 'ansico-some-plugin' ) . '</p>';
|
|
},
|
|
'ansico-some-plugin-settings'
|
|
);
|
|
|
|
add_settings_field(
|
|
'ansico_micropost_max_chars',
|
|
__( 'Maximum characters in Micropost Form', 'ansico-some-plugin' ),
|
|
'ansico_render_micropost_max_chars_field',
|
|
'ansico-some-plugin-settings',
|
|
'ansico_some_plugin_main'
|
|
);
|
|
|
|
add_settings_field(
|
|
'ansico_clean_up_profile_settings',
|
|
__( 'Clean up profile settings', 'ansico-some-plugin' ),
|
|
'ansico_render_clean_up_profile_settings_field',
|
|
'ansico-some-plugin-settings',
|
|
'ansico_some_plugin_main'
|
|
);
|
|
}
|
|
|
|
function ansico_sanitize_checkbox_setting( $value ) {
|
|
return ! empty( $value ) ? '1' : '';
|
|
}
|
|
|
|
function ansico_sanitize_micropost_max_chars( $value ) {
|
|
$value = intval( $value );
|
|
if ( $value < 1 ) {
|
|
$value = 500;
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
function ansico_render_micropost_max_chars_field() {
|
|
$value = ansico_get_micropost_max_chars();
|
|
echo '<input type="number" min="1" step="1" name="ansico_micropost_max_chars" value="' . esc_attr( $value ) . '" class="small-text" />';
|
|
echo '<p class="description">' . esc_html__( 'Default is 500 characters.', 'ansico-some-plugin' ) . '</p>';
|
|
}
|
|
|
|
function ansico_render_clean_up_profile_settings_field() {
|
|
$enabled = ! empty( get_option( 'ansico_clean_up_profile_settings', '' ) );
|
|
echo '<label for="ansico-clean-up-profile-settings">';
|
|
echo '<input type="checkbox" id="ansico-clean-up-profile-settings" name="ansico_clean_up_profile_settings" value="1" ' . checked( $enabled, true, false ) . ' /> ';
|
|
echo esc_html__( 'Organize the WordPress profile page into tabs: Profile, Federation, and Other settings.', 'ansico-some-plugin' );
|
|
echo '</label>';
|
|
}
|
|
|
|
function ansico_render_settings_page() {
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return;
|
|
}
|
|
?>
|
|
<div class="wrap">
|
|
<h1><?php echo esc_html__( 'Ansico SoMe Plugin', 'ansico-some-plugin' ); ?></h1>
|
|
<form method="post" action="options.php">
|
|
<?php
|
|
settings_fields( 'ansico_some_plugin_settings' );
|
|
do_settings_sections( 'ansico-some-plugin-settings' );
|
|
submit_button();
|
|
?>
|
|
</form>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/* ==========================================================================
|
|
1. MICROPOST POST TYPE & TAXONOMY
|
|
========================================================================== */
|
|
|
|
/* ==========================================================================
|
|
1.5. INKLUDER MICROPOSTS I FORFATTER ARKIV (TIL QUERY LOOP)
|
|
========================================================================== */
|
|
add_action( 'pre_get_posts', 'ansico_include_microposts_in_author_archive' );
|
|
function ansico_include_microposts_in_author_archive( $query ) {
|
|
if ( ! is_admin() && $query->is_main_query() && $query->is_author() ) {
|
|
$types = $query->get('post_type');
|
|
if (empty($types) || $types === 'post') {
|
|
$query->set( 'post_type', array( 'post', 'micropost' ) );
|
|
} elseif (is_array($types) && !in_array('micropost', $types)) {
|
|
$types[] = 'micropost';
|
|
$query->set('post_type', $types);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* ==========================================================================
|
|
1.6. FORCE COMMENTS OPEN FOR MICROPOSTS
|
|
========================================================================== */
|
|
add_filter( 'comments_open', 'ansico_force_micropost_comments_open', 10, 2 );
|
|
function ansico_force_micropost_comments_open( $open, $post_id ) {
|
|
if ( get_post_type( $post_id ) === 'micropost' ) {
|
|
return true;
|
|
}
|
|
return $open;
|
|
}
|
|
|
|
|
|
/* ==========================================================================
|
|
1.7. FORMAT MICROPOST COMMENTS (Mastodon & Embeds)
|
|
========================================================================== */
|
|
add_filter( 'comment_text', 'ansico_format_comment_text', 10, 2 );
|
|
function ansico_format_comment_text( $text, $comment = null ) {
|
|
if ( ! is_object( $comment ) || get_post_type( $comment->comment_post_ID ) !== 'micropost' ) {
|
|
return $text;
|
|
}
|
|
|
|
return ansico_get_formatted_comment_html( $comment, true );
|
|
}
|
|
|
|
function ansico_apply_micropost_text_formatting( $text ) {
|
|
$text = (string) $text;
|
|
|
|
$text = preg_replace('/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/i', '<a href="$2" target="_blank" rel="nofollow ugc noopener">$1</a>', $text);
|
|
$text = preg_replace('/(?<!["\w@])@([a-zA-Z0-9_]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})(?!\S)/u', '<a href="https://$2/@$1" target="_blank" rel="nofollow ugc noopener">@$1@$2</a>', $text);
|
|
$text = preg_replace_callback('/(?<=^|\s|>|>)#([\p{L}\p{N}_]+)/u', function($m) {
|
|
$link = get_term_link($m[1], 'micropost_tag');
|
|
if ( is_wp_error($link) ) {
|
|
$link = home_url('/micropost-tag/' . sanitize_title($m[1]) . '/');
|
|
}
|
|
return '<a href="' . esc_url( $link ) . '" class="ansico-hashtag">#' . esc_html($m[1]) . '</a>';
|
|
}, $text);
|
|
$text = make_clickable($text);
|
|
$text = preg_replace('/\*\*(.+?)\*\*/s', '<strong>$1</strong>', $text);
|
|
$text = preg_replace('/\*([^\*]+)\*/s', '<em>$1</em>', $text);
|
|
$text = preg_replace('/`([^`]+)`/s', '<code>$1</code>', $text);
|
|
$text = preg_replace('/^>\s+(.*)/m', '<blockquote>$1</blockquote>', $text);
|
|
|
|
return $text;
|
|
}
|
|
|
|
function ansico_get_formatted_comment_html( $comment, $already_filtered = false ) {
|
|
if ( ! is_object( $comment ) ) {
|
|
return '';
|
|
}
|
|
|
|
$raw_text = isset( $comment->comment_content ) ? (string) $comment->comment_content : '';
|
|
if ( $raw_text === '' ) {
|
|
return '';
|
|
}
|
|
|
|
preg_match( '/(https?:\/\/[^\s()<>{}\[\]]+)/i', $raw_text, $url_matches );
|
|
$first_url = ! empty( $url_matches[1] ) ? $url_matches[1] : '';
|
|
|
|
$text = esc_html( $raw_text );
|
|
|
|
$text = ansico_apply_micropost_text_formatting( $text );
|
|
$text = wpautop( $text );
|
|
|
|
if ( $first_url ) {
|
|
$embed_data = ansico_fetch_metadata_internal( $first_url );
|
|
if ( $embed_data && ! empty( $embed_data['title'] ) ) {
|
|
$img_html = ! empty( $embed_data['image'] ) ? '<img src="' . esc_url( $embed_data['image'] ) . '" class="ansico-tweet-embed-image" />' : '';
|
|
$text .= '<div class="ansico-tweet-embed"><a href="' . esc_url( $first_url ) . '" target="_blank" rel="nofollow noreferrer noopener" style="text-decoration:none; color:inherit; display:block;">' . $img_html . '<div class="ansico-tweet-embed-content"><span class="ansico-tweet-embed-domain">' . esc_html( $embed_data['domain'] ) . '</span><h3 class="ansico-tweet-embed-title">' . esc_html( $embed_data['title'] ) . '</h3></div></a></div>';
|
|
}
|
|
}
|
|
|
|
return ansico_prepare_comment_display_html( $text );
|
|
}
|
|
|
|
function ansico_prepare_comment_display_html( $html ) {
|
|
$html = (string) $html;
|
|
if ( $html === '' ) {
|
|
return '';
|
|
}
|
|
|
|
// Normaliser WordPress-kommentar HTML uden at skabe ekstra luft omkring embeds.
|
|
$html = shortcode_unautop( $html );
|
|
|
|
// Fjern tomme afsnit og linjeskift rundt om embed-kort.
|
|
$patterns = array(
|
|
'#<p>\s*(<div class="ansico-tweet-embed"[^>]*>)#i',
|
|
'#(</div>)\s*</p>#i',
|
|
'#<p>\s*(<a [^>]*>\s*<img[^>]*class="ansico-tweet-embed-image"[^>]*>\s*</a>)\s*</p>#i',
|
|
'#<p>\s*(<img[^>]*class="ansico-tweet-embed-image"[^>]*>)\s*</p>#i',
|
|
'#<p>\s*(<blockquote[^>]*>.*?</blockquote>)\s*</p>#is',
|
|
'#<p>\s*</p>#i',
|
|
);
|
|
$replacements = array('$1', '$1', '$1', '$1', '$1', '');
|
|
$html = preg_replace( $patterns, $replacements, $html );
|
|
|
|
return trim( $html );
|
|
}
|
|
|
|
/* ==========================================================================
|
|
1.8. CUSTOM COMMENT MARKUP (Design uden "siger" og med ny opstilling)
|
|
========================================================================== */
|
|
|
|
function ansico_custom_comment_markup($comment, $args, $depth) {
|
|
$GLOBALS['comment'] = $comment;
|
|
$avatar = get_avatar($comment, 40, '', '', array('class' => 'ansico-tweet-avatar'));
|
|
$author_link = get_comment_author_link($comment);
|
|
$author_url = '';
|
|
if ( is_object( $comment ) && ! empty( $comment->user_id ) ) {
|
|
$author_url = get_author_posts_url( (int) $comment->user_id );
|
|
} elseif ( is_object( $comment ) && ! empty( $comment->comment_author_url ) ) {
|
|
$author_url = $comment->comment_author_url;
|
|
}
|
|
$avatar_html = $author_url ? '<a class="ansico-comment-avatar-link" href="' . esc_url( $author_url ) . '">' . $avatar . '</a>' : $avatar;
|
|
$time_display = get_comment_date( get_option('date_format'), $comment ) . ' · ' . get_comment_time( get_option('time_format'), false, false, $comment );
|
|
$like_button = ansico_render_like_button( 'comment', $comment->comment_ID );
|
|
?>
|
|
<li <?php comment_class('ansico-isolated-comment'); ?> id="comment-<?php comment_ID(); ?>" style="position: relative; display: block !important; list-style: none; margin-bottom: 20px;">
|
|
<button class="ansico-copy-btn-comment" onclick="navigator.clipboard.writeText('<?php echo esc_js(get_comment_link($comment)); ?>'); var el=this; el.classList.add('copied'); setTimeout(function(){el.classList.remove('copied');}, 2000);" title="<?php echo esc_attr__( 'Copy link', 'ansico-some-plugin' ); ?>">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
|
</button>
|
|
<div class="ansico-comment-inner-wrap" style="display: flex; gap: 12px; width: 100%;">
|
|
<div class="ansico-comment-avatar-wrap"><?php echo $avatar_html; ?></div>
|
|
<div class="ansico-comment-content-wrap" style="flex: 1; min-width: 0;">
|
|
<div class="ansico-comment-header-row" style="display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px;">
|
|
<div class="ansico-tweet-name" style="font-weight: 700; font-size: 15px; color: #0f1419;"><?php echo $author_link; ?></div>
|
|
<div class="ansico-tweet-time" style="font-size: 13px; color: #536471;"><?php echo $time_display; ?></div>
|
|
</div>
|
|
<div class="ansico-comment-text-body" style="font-size: 15px; color: #0f1419; line-height: 1.4; word-wrap: break-word;">
|
|
<?php echo wp_kses_post( ansico_get_formatted_comment_html( $comment ) ); ?>
|
|
</div>
|
|
<div class="reply-action-wrap ansico-tweet-actions-bottom" style="margin-top: 6px;">
|
|
<?php if ( $like_button ) echo $like_button; ?>
|
|
<?php
|
|
$reply_icon = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle;"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>';
|
|
comment_reply_link(array_merge($args, array(
|
|
'depth' => $depth,
|
|
'max_depth' => $args['max_depth'],
|
|
'reply_text' => $reply_icon
|
|
)));
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
|
|
add_action( 'init', 'ansico_register_micropost_type' );
|
|
function ansico_register_micropost_type() {
|
|
register_post_type( 'micropost', array(
|
|
'labels' => array(
|
|
'name' => 'Microposts',
|
|
'singular_name' => 'Micropost',
|
|
),
|
|
'public' => true,
|
|
'has_archive' => true,
|
|
'supports' => array( 'editor', 'author', 'custom-fields', 'comments' ),
|
|
'menu_icon' => 'dashicons-edit-page',
|
|
'show_in_rest' => true,
|
|
'rewrite' => array('slug' => 'micropost'),
|
|
));
|
|
|
|
register_taxonomy( 'micropost_tag', 'micropost', array(
|
|
'labels' => array(
|
|
'name' => 'Tags',
|
|
'singular_name' => 'Tag',
|
|
),
|
|
'public' => true,
|
|
'rewrite' => array( 'slug' => 'micropost-tag' ),
|
|
'hierarchical' => false,
|
|
'show_in_rest' => true,
|
|
'show_admin_column' => true,
|
|
));
|
|
}
|
|
|
|
add_filter( 'wp_insert_post_data', function( $data, $postarr ) {
|
|
if ( $data['post_type'] === 'micropost' && $data['post_status'] !== 'trash' ) {
|
|
if ( empty( $postarr['post_title'] ) || $postarr['post_title'] === 'Auto Draft' || $postarr['post_title'] === '' ) {
|
|
$clean_content = strip_tags( $data['post_content'] );
|
|
$data['post_title'] = mb_substr( $clean_content, 0, 50 );
|
|
}
|
|
if ( empty( $data['post_name'] ) ) {
|
|
$data['post_name'] = date('YmdHis') . rand(100, 999);
|
|
}
|
|
}
|
|
return $data;
|
|
}, 10, 2 );
|
|
|
|
add_action('save_post_micropost', function($post_id, $post, $update) {
|
|
if ( wp_is_post_revision( $post_id ) ) return;
|
|
preg_match_all('/#([\p{L}\p{N}_]+)/u', $post->post_content, $matches);
|
|
if (!empty($matches[1])) {
|
|
wp_set_object_terms( $post_id, $matches[1], 'micropost_tag', false );
|
|
}
|
|
}, 10, 3);
|
|
|
|
/* ==========================================================================
|
|
2. TEMPLATE STYRING
|
|
========================================================================== */
|
|
|
|
|
|
function ansico_get_micropost_ids_matching_search( $search_query ) {
|
|
global $wpdb;
|
|
|
|
$search_query = trim( (string) $search_query );
|
|
if ( $search_query === '' ) {
|
|
return array();
|
|
}
|
|
|
|
$like = '%' . $wpdb->esc_like( $search_query ) . '%';
|
|
|
|
$post_ids = $wpdb->get_col( $wpdb->prepare(
|
|
"SELECT ID FROM {$wpdb->posts}
|
|
WHERE post_type = %s
|
|
AND post_status = 'publish'
|
|
AND (post_title LIKE %s OR post_content LIKE %s)",
|
|
'micropost',
|
|
$like,
|
|
$like
|
|
) );
|
|
|
|
$comment_post_ids = $wpdb->get_col( $wpdb->prepare(
|
|
"SELECT DISTINCT c.comment_post_ID
|
|
FROM {$wpdb->comments} c
|
|
INNER JOIN {$wpdb->posts} p ON p.ID = c.comment_post_ID
|
|
WHERE p.post_type = %s
|
|
AND p.post_status = 'publish'
|
|
AND c.comment_approved = '1'
|
|
AND (c.comment_type = '' OR c.comment_type = 'comment')
|
|
AND c.comment_content LIKE %s",
|
|
'micropost',
|
|
$like
|
|
) );
|
|
|
|
$all_ids = array_unique( array_map( 'intval', array_merge( $post_ids, $comment_post_ids ) ) );
|
|
rsort( $all_ids );
|
|
|
|
return $all_ids;
|
|
}
|
|
|
|
add_action( 'pre_get_posts', 'ansico_apply_micropost_archive_search' );
|
|
function ansico_apply_micropost_archive_search( $query ) {
|
|
if ( is_admin() || ! $query->is_main_query() ) {
|
|
return;
|
|
}
|
|
|
|
if ( $query->is_post_type_archive( 'micropost' ) ) {
|
|
$search_query = '';
|
|
|
|
if ( isset( $_GET['ms'] ) ) {
|
|
$search_query = sanitize_text_field( wp_unslash( $_GET['ms'] ) );
|
|
} elseif ( isset( $_GET['s'] ) ) {
|
|
$search_query = sanitize_text_field( wp_unslash( $_GET['s'] ) );
|
|
}
|
|
|
|
if ( $search_query !== '' ) {
|
|
$matching_ids = ansico_get_micropost_ids_matching_search( $search_query );
|
|
$query->set( 'post_type', 'micropost' );
|
|
$query->set( 's', '' );
|
|
$query->set( 'post__in', ! empty( $matching_ids ) ? $matching_ids : array( 0 ) );
|
|
$query->set( 'orderby', 'date' );
|
|
$query->set( 'order', 'DESC' );
|
|
}
|
|
}
|
|
}
|
|
|
|
add_filter('template_include', 'ansico_micropost_templates');
|
|
function ansico_micropost_templates( $template ) {
|
|
// Deaktiveret for enkelte microposts, så din Site Editor skabelon kan bruges.
|
|
/* if ( is_singular('micropost') ) {
|
|
$plugin_template = plugin_dir_path(__FILE__) . 'templates/single-micropost.php';
|
|
if ( file_exists($plugin_template) ) return $plugin_template;
|
|
} */
|
|
|
|
// Brug kun pluginets simple archive-template på det normale micropost-arkiv.
|
|
// Ved søgning skal temaets eget layout bruges, så sidebar og globalt site-design bevares.
|
|
if ( is_post_type_archive('micropost') ) {
|
|
$has_search = false;
|
|
|
|
if ( isset( $_GET['ms'] ) ) {
|
|
$has_search = trim( (string) wp_unslash( $_GET['ms'] ) ) !== '';
|
|
} elseif ( isset( $_GET['s'] ) ) {
|
|
$has_search = trim( (string) wp_unslash( $_GET['s'] ) ) !== '';
|
|
}
|
|
|
|
if ( ! $has_search ) {
|
|
$plugin_template = plugin_dir_path(__FILE__) . 'templates/archive-micropost.php';
|
|
if ( file_exists($plugin_template) ) return $plugin_template;
|
|
}
|
|
}
|
|
// Deaktiveret for tags, så din egen Site Editor skabelon kan træde i kraft.
|
|
/* if ( is_tax('micropost_tag') ) {
|
|
$plugin_template = plugin_dir_path(__FILE__) . 'templates/taxonomy-micropost_tag.php';
|
|
if ( file_exists($plugin_template) ) return $plugin_template;
|
|
} */
|
|
|
|
/* if ( is_author() ) {
|
|
$plugin_template = plugin_dir_path(__FILE__) . 'templates/author-micropost.php';
|
|
if ( file_exists($plugin_template) ) return $plugin_template;
|
|
} */
|
|
return $template;
|
|
}
|
|
|
|
add_action( 'add_meta_boxes', function() {
|
|
add_meta_box( 'ansico_micropost_meta', 'Micropost Details', 'ansico_micropost_meta_html', 'micropost', 'normal', 'high' );
|
|
});
|
|
|
|
function ansico_micropost_meta_html( $post ) {
|
|
$url = get_post_meta( $post->ID, 'ansico_micropost_url', true );
|
|
$time = get_post_meta( $post->ID, 'ansico_micropost_time', true );
|
|
$is_federated = ansico_is_micropost_federated( $post->ID );
|
|
wp_nonce_field( 'ansico_micropost_save', 'ansico_micropost_nonce' );
|
|
?>
|
|
<p><label><strong>Permalink/URL:</strong></label><br><input type="text" name="ansico_micropost_url" value="<?php echo esc_attr($url); ?>" style="width:100%;" /></p>
|
|
<p><label><strong>Time:</strong></label><br><input type="text" name="ansico_micropost_time" value="<?php echo esc_attr($time); ?>" style="width:100%;" /></p>
|
|
<p>
|
|
<label style="display:flex; align-items:center; gap:8px;">
|
|
<input type="checkbox" <?php checked( $is_federated ); ?> disabled="disabled" />
|
|
<strong><?php echo esc_html__( 'Has been federated', 'ansico-some-plugin' ); ?></strong>
|
|
</label>
|
|
</p>
|
|
<?php
|
|
}
|
|
|
|
|
|
add_action( 'save_post', function( $post_id ) {
|
|
if ( !isset($_POST['ansico_micropost_nonce']) || !wp_verify_nonce($_POST['ansico_micropost_nonce'], 'ansico_micropost_save') ) return;
|
|
if ( isset($_POST['ansico_micropost_url']) ) update_post_meta( $post_id, 'ansico_micropost_url', sanitize_text_field( $_POST['ansico_micropost_url'] ) );
|
|
if ( isset($_POST['ansico_micropost_time']) ) update_post_meta( $post_id, 'ansico_micropost_time', sanitize_text_field( $_POST['ansico_micropost_time'] ) );
|
|
});
|
|
|
|
function ansico_get_activitypub_visibility_meta_key() {
|
|
return 'activitypub_content_visibility';
|
|
}
|
|
|
|
function ansico_get_activitypub_status_meta_key() {
|
|
return 'activitypub_status';
|
|
}
|
|
|
|
function ansico_is_micropost_federated( $post_id ) {
|
|
$post_id = intval( $post_id );
|
|
if ( $post_id < 1 || get_post_type( $post_id ) !== 'micropost' ) {
|
|
return false;
|
|
}
|
|
|
|
if ( '1' === (string) get_post_meta( $post_id, '_ansico_has_been_federated', true ) ) {
|
|
return true;
|
|
}
|
|
|
|
$visibility = strtolower( (string) get_post_meta( $post_id, ansico_get_activitypub_visibility_meta_key(), true ) );
|
|
$status = strtolower( (string) get_post_meta( $post_id, ansico_get_activitypub_status_meta_key(), true ) );
|
|
|
|
if ( $visibility === 'public' && in_array( $status, array( 'federated', 'scheduled', 'processing', 'sent', 'success', 'done' ), true ) ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ansico_sync_micropost_federation_meta( $post_id ) {
|
|
$post_id = intval( $post_id );
|
|
if ( $post_id < 1 || get_post_type( $post_id ) !== 'micropost' ) {
|
|
return;
|
|
}
|
|
|
|
if ( ansico_is_micropost_federated( $post_id ) ) {
|
|
update_post_meta( $post_id, '_ansico_has_been_federated', '1' );
|
|
}
|
|
}
|
|
|
|
add_action( 'save_post_micropost', 'ansico_sync_micropost_federation_meta', 20 );
|
|
|
|
function ansico_mark_micropost_as_federated( $wp_object ) {
|
|
if ( is_object( $wp_object ) && isset( $wp_object->ID ) && get_post_type( $wp_object->ID ) === 'micropost' ) {
|
|
update_post_meta( intval( $wp_object->ID ), '_ansico_has_been_federated', '1' );
|
|
}
|
|
}
|
|
add_action( 'activitypub_mark_wp_object_as_federated', 'ansico_mark_micropost_as_federated' );
|
|
|
|
/* ==========================================================================
|
|
3. RENDERING ENGINE
|
|
========================================================================== */
|
|
|
|
function ansico_get_like_count( $object_type, $object_id ) {
|
|
$object_id = intval( $object_id );
|
|
if ( $object_id < 1 ) {
|
|
return 0;
|
|
}
|
|
|
|
if ( $object_type === 'comment' ) {
|
|
return max( 0, intval( get_comment_meta( $object_id, '_ansico_like_count', true ) ) );
|
|
}
|
|
|
|
return max( 0, intval( get_post_meta( $object_id, '_ansico_like_count', true ) ) );
|
|
}
|
|
|
|
function ansico_get_user_liked_items( $user_id, $object_type ) {
|
|
$meta_key = $object_type === 'comment' ? '_ansico_liked_comments' : '_ansico_liked_posts';
|
|
$liked = get_user_meta( intval( $user_id ), $meta_key, true );
|
|
return is_array( $liked ) ? array_values( array_unique( array_map( 'intval', $liked ) ) ) : array();
|
|
}
|
|
|
|
function ansico_user_has_liked( $object_type, $object_id, $user_id = 0 ) {
|
|
$user_id = $user_id ? intval( $user_id ) : get_current_user_id();
|
|
$object_id = intval( $object_id );
|
|
|
|
if ( $user_id < 1 || $object_id < 1 ) {
|
|
return false;
|
|
}
|
|
|
|
return in_array( $object_id, ansico_get_user_liked_items( $user_id, $object_type ), true );
|
|
}
|
|
|
|
function ansico_toggle_like( $object_type, $object_id, $user_id = 0 ) {
|
|
$user_id = $user_id ? intval( $user_id ) : get_current_user_id();
|
|
$object_id = intval( $object_id );
|
|
|
|
if ( $user_id < 1 || $object_id < 1 ) {
|
|
return new WP_Error( 'ansico_like_forbidden', 'Kun loggede brugere kan like.', array( 'status' => 403 ) );
|
|
}
|
|
|
|
if ( $object_type === 'comment' ) {
|
|
$comment = get_comment( $object_id );
|
|
if ( ! $comment || intval( $comment->comment_approved ) !== 1 ) {
|
|
return new WP_Error( 'ansico_like_invalid_comment', 'Kommentaren findes ikke.', array( 'status' => 404 ) );
|
|
}
|
|
$liked = ansico_get_user_liked_items( $user_id, 'comment' );
|
|
$has_liked = in_array( $object_id, $liked, true );
|
|
if ( $has_liked ) {
|
|
$liked = array_values( array_diff( $liked, array( $object_id ) ) );
|
|
update_user_meta( $user_id, '_ansico_liked_comments', $liked );
|
|
$count = max( 0, ansico_get_like_count( 'comment', $object_id ) - 1 );
|
|
update_comment_meta( $object_id, '_ansico_like_count', $count );
|
|
return array( 'liked' => false, 'count' => $count );
|
|
}
|
|
$liked[] = $object_id;
|
|
update_user_meta( $user_id, '_ansico_liked_comments', array_values( array_unique( array_map( 'intval', $liked ) ) ) );
|
|
$count = ansico_get_like_count( 'comment', $object_id ) + 1;
|
|
update_comment_meta( $object_id, '_ansico_like_count', $count );
|
|
return array( 'liked' => true, 'count' => $count );
|
|
}
|
|
|
|
$post = get_post( $object_id );
|
|
if ( ! $post || $post->post_status !== 'publish' || $post->post_type !== 'micropost' ) {
|
|
return new WP_Error( 'ansico_like_invalid_post', 'Microposten findes ikke.', array( 'status' => 404 ) );
|
|
}
|
|
|
|
$liked = ansico_get_user_liked_items( $user_id, 'post' );
|
|
$has_liked = in_array( $object_id, $liked, true );
|
|
if ( $has_liked ) {
|
|
$liked = array_values( array_diff( $liked, array( $object_id ) ) );
|
|
update_user_meta( $user_id, '_ansico_liked_posts', $liked );
|
|
$count = max( 0, ansico_get_like_count( 'post', $object_id ) - 1 );
|
|
update_post_meta( $object_id, '_ansico_like_count', $count );
|
|
return array( 'liked' => false, 'count' => $count );
|
|
}
|
|
$liked[] = $object_id;
|
|
update_user_meta( $user_id, '_ansico_liked_posts', array_values( array_unique( array_map( 'intval', $liked ) ) ) );
|
|
$count = ansico_get_like_count( 'post', $object_id ) + 1;
|
|
update_post_meta( $object_id, '_ansico_like_count', $count );
|
|
return array( 'liked' => true, 'count' => $count );
|
|
}
|
|
|
|
function ansico_render_like_button( $object_type, $object_id, $extra_classes = '' ) {
|
|
$object_id = intval( $object_id );
|
|
if ( $object_id < 1 ) {
|
|
return '';
|
|
}
|
|
|
|
$count = ansico_get_like_count( $object_type, $object_id );
|
|
$is_logged_in = is_user_logged_in();
|
|
$has_liked = $is_logged_in ? ansico_user_has_liked( $object_type, $object_id ) : false;
|
|
$classes = trim( 'ansico-action-btn ansico-like-btn ' . $extra_classes . ( $has_liked ? ' is-liked' : '' ) );
|
|
$disabled_attr = $is_logged_in ? '' : ' disabled aria-disabled="true" tabindex="-1"';
|
|
$title = $is_logged_in ? ( $has_liked ? 'Fjern like' : 'Like' ) : 'Log ind for at like';
|
|
|
|
return '<button class="' . esc_attr( $classes ) . '" type="button" data-ansico-like data-object-type="' . esc_attr( $object_type ) . '" data-object-id="' . intval( $object_id ) . '" title="' . esc_attr( $title ) . '" aria-label="' . esc_attr( $title ) . '"' . $disabled_attr . '><svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 21s-6.7-4.35-9.33-8.28C.9 10.13 1.29 6.5 4.35 4.77c2.03-1.15 4.53-.73 6.15.96 1.62-1.69 4.12-2.11 6.15-.96 3.06 1.73 3.45 5.36 1.68 7.95C18.7 16.65 12 21 12 21z"></path></svg><span class="ansico-like-count">' . intval( $count ) . '</span></button>';
|
|
}
|
|
|
|
function ansico_get_tweet_html($author_id, $text, $time_str, $source_url, $embed_data = null, $post_id = 0) {
|
|
$name = get_the_author_meta( 'display_name', $author_id );
|
|
$avatar = get_avatar_url( $author_id, array( 'size' => 50 ) );
|
|
|
|
if (!$embed_data) {
|
|
preg_match('/(?<!href=")(?<!src=")((https?:\/\/[^\s()<>{}\[\]]+))/i', $text, $matches);
|
|
if ($matches) { $embed_data = ansico_fetch_metadata_internal($matches[0]); }
|
|
}
|
|
|
|
$time_display = $time_str;
|
|
if ( strtotime($time_str) ) {
|
|
$ts = strtotime($time_str);
|
|
$time_display = wp_date(get_option('date_format'), $ts) . ' · ' . wp_date(get_option('time_format'), $ts);
|
|
}
|
|
|
|
$text = ansico_apply_micropost_text_formatting( $text );
|
|
|
|
$comment_count = $post_id ? get_comments_number($post_id) : 0;
|
|
$permalink = $post_id ? get_permalink($post_id) : $source_url;
|
|
$like_button = $post_id ? ansico_render_like_button( 'post', $post_id ) : '';
|
|
$is_federated = $post_id ? ansico_is_micropost_federated( $post_id ) : false;
|
|
|
|
ob_start(); ?>
|
|
<div class="ansico-micropost-wrapper">
|
|
<div class="ansico-some-tweet" id="micropost-<?php echo $post_id; ?>">
|
|
<?php if ( $is_federated || $permalink ) : ?>
|
|
<div class="ansico-top-right-icons" style="position:absolute; top:12px; right:12px; display:flex; align-items:center; gap:8px; z-index:10;">
|
|
<?php if ( $is_federated ) : ?>
|
|
<span class="ansico-federated-icon-top" title="<?php echo esc_attr__( 'Federated', 'ansico-some-plugin' ); ?>" aria-label="<?php echo esc_attr__( 'Federated', 'ansico-some-plugin' ); ?>" style="display:flex; align-items:center; justify-content:center; width:32px; height:32px; color:#536471;">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"></circle><path d="M3 12h18"></path><path d="M12 3a14.5 14.5 0 0 1 4 9 14.5 14.5 0 0 1-4 9 14.5 14.5 0 0 1-4-9 14.5 14.5 0 0 1 4-9Z"></path></svg>
|
|
</span>
|
|
<?php endif; ?>
|
|
<?php if ($permalink) : ?>
|
|
<button class="ansico-copy-btn-top" style="position:static !important; top:auto !important; right:auto !important; margin:0 !important;" onclick="navigator.clipboard.writeText('<?php echo esc_js($permalink); ?>'); var el=this; el.classList.add('copied'); setTimeout(function(){el.classList.remove('copied');}, 2000);" title="<?php echo esc_attr__( 'Copy link', 'ansico-some-plugin' ); ?>">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<a href="<?php echo esc_url(get_author_posts_url($author_id)); ?>" class="ansico-tweet-avatar-link">
|
|
<img src="<?php echo esc_url($avatar); ?>" class="ansico-tweet-avatar" alt="" />
|
|
</a>
|
|
<div class="ansico-tweet-content">
|
|
<div class="ansico-tweet-header">
|
|
<a href="<?php echo esc_url(get_author_posts_url($author_id)); ?>" class="ansico-tweet-name-link">
|
|
<span class="ansico-tweet-name"><?php echo esc_html($name); ?></span>
|
|
</a>
|
|
<span class="ansico-tweet-time"><?php echo wp_kses_post($time_display); ?></span>
|
|
</div>
|
|
<div class="ansico-tweet-text"><?php echo wp_kses_post(wpautop($text)); ?></div>
|
|
<?php if ($embed_data && !empty($embed_data['title'])) : ?>
|
|
<div class="ansico-tweet-embed">
|
|
<a href="<?php echo esc_url($matches[0] ?? $source_url); ?>" target="_blank" rel="nofollow noreferrer" style="text-decoration:none; color:inherit; display:block;">
|
|
<?php if (!empty($embed_data['image'])) : ?><img src="<?php echo esc_url($embed_data['image']); ?>" class="ansico-tweet-embed-image" /><?php endif; ?>
|
|
<div class="ansico-tweet-embed-content">
|
|
<span class="ansico-tweet-embed-domain"><?php echo esc_html($embed_data['domain']); ?></span>
|
|
<h3 class="ansico-tweet-embed-title"><?php echo esc_html($embed_data['title']); ?></h3>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="ansico-tweet-actions-bottom">
|
|
<?php if ( $like_button ) echo $like_button; ?>
|
|
<a href="<?php echo esc_url($permalink); ?>#respond" class="ansico-action-btn ansico-comment-btn" title="<?php echo esc_attr__( 'Reply', 'ansico-some-plugin' ); ?>">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
|
|
<span class="ansico-comment-count"><?php echo intval($comment_count); ?></span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php
|
|
// Inkluder kommentarspor på enkelt-visning
|
|
if ( is_singular('micropost') && get_queried_object_id() == $post_id ) : ?>
|
|
<div class="ansico-comments-area">
|
|
<?php
|
|
$comments = get_comments(array('post_id' => $post_id, 'status' => 'approve', 'order' => 'ASC'));
|
|
if ($comments) {
|
|
echo '<h3 class="ansico-comments-title">' . esc_html__( 'Replies', 'ansico-some-plugin' ) . '</h3>';
|
|
echo '<ul class="ansico-comment-list">';
|
|
wp_list_comments(array(
|
|
'style' => 'ul',
|
|
'short_ping' => true,
|
|
'callback' => 'ansico_custom_comment_markup',
|
|
), $comments);
|
|
echo '</ul>';
|
|
}
|
|
|
|
if ( is_user_logged_in() ) {
|
|
comment_form(array(
|
|
'title_reply' => '',
|
|
'title_reply_to' => '',
|
|
'comment_notes_before' => '',
|
|
'class_submit' => 'ansico-twitter-reply-btn',
|
|
'label_submit' => __( 'Reply', 'ansico-some-plugin' ),
|
|
'class_form' => 'ansico-twitter-reply-form',
|
|
'logged_in_as' => '',
|
|
'must_log_in' => '',
|
|
'comment_field' => '<div class="ansico-reply-field-container"><img class="ansico-reply-user-avatar" src="' . get_avatar_url(get_current_user_id(), array('size' => 48)) . '" alt="" /><textarea id="comment" name="comment" placeholder="' . esc_attr__( 'Write your reply...', 'ansico-some-plugin' ) . '" required></textarea></div>',
|
|
), $post_id);
|
|
}
|
|
?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
|
|
add_filter( 'preprocess_comment', 'ansico_set_logged_in_comment_author_url' );
|
|
function ansico_set_logged_in_comment_author_url( $commentdata ) {
|
|
if ( empty( $commentdata['comment_post_ID'] ) ) {
|
|
return $commentdata;
|
|
}
|
|
|
|
$post_id = intval( $commentdata['comment_post_ID'] );
|
|
if ( $post_id < 1 || get_post_type( $post_id ) !== 'micropost' || ! is_user_logged_in() ) {
|
|
return $commentdata;
|
|
}
|
|
|
|
$user_id = get_current_user_id();
|
|
if ( $user_id > 0 ) {
|
|
$commentdata['comment_author_url'] = get_author_posts_url( $user_id );
|
|
}
|
|
|
|
return $commentdata;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
4. BLOCKS & API
|
|
========================================================================== */
|
|
add_action( 'init', 'ansico_some_register_all' );
|
|
function ansico_some_register_all() {
|
|
wp_register_script(
|
|
'ansico-blocks-js',
|
|
plugins_url( 'block.js', __FILE__ ),
|
|
array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-data', 'wp-components', 'wp-core-data' ),
|
|
ANSICO_SOME_PLUGIN_VERSION
|
|
);
|
|
wp_register_style( 'ansico-style', plugins_url( 'style.css', __FILE__ ), array(), ANSICO_SOME_PLUGIN_VERSION );
|
|
|
|
register_block_type( 'ansico/some-author', array( 'editor_script' => 'ansico-blocks-js', 'style' => 'ansico-style', 'render_callback' => 'ansico_render_author' ) );
|
|
register_block_type( 'ansico/some-comment', array( 'editor_script' => 'ansico-blocks-js', 'style' => 'ansico-style', 'render_callback' => 'ansico_render_comment' ) );
|
|
register_block_type( 'ansico/embed-url', array( 'editor_script' => 'ansico-blocks-js', 'style' => 'ansico-style' ) );
|
|
|
|
register_block_type( 'ansico/micropost-form', array(
|
|
'editor_script' => 'ansico-blocks-js',
|
|
'style' => 'ansico-style',
|
|
'render_callback' => 'ansico_render_micropost_form'
|
|
) );
|
|
|
|
register_block_type( 'ansico/micropost-search', array( 'editor_script' => 'ansico-blocks-js', 'style' => 'ansico-style', 'render_callback' => 'ansico_render_micropost_search' ) );
|
|
register_block_type( 'ansico/micropost-list', array(
|
|
'editor_script' => 'ansico-blocks-js',
|
|
'style' => 'ansico-style',
|
|
'render_callback' => 'ansico_render_micropost_list',
|
|
'attributes' => array(
|
|
'postsPerPage' => array(
|
|
'type' => 'number',
|
|
'default' => 20,
|
|
),
|
|
'tagFilter' => array(
|
|
'type' => 'string',
|
|
'default' => '',
|
|
),
|
|
),
|
|
) );
|
|
|
|
register_block_type( 'ansico/micropost-comments', array(
|
|
'editor_script' => 'ansico-blocks-js',
|
|
'style' => 'ansico-style',
|
|
'render_callback' => 'ansico_render_micropost_comments',
|
|
'attributes' => array(
|
|
'commentsToShow' => array(
|
|
'type' => 'number',
|
|
'default' => 5,
|
|
),
|
|
),
|
|
) );
|
|
|
|
register_block_type( 'ansico/micropost-top-tags', array(
|
|
'editor_script' => 'ansico-blocks-js',
|
|
'style' => 'ansico-style',
|
|
'render_callback' => 'ansico_render_micropost_top_tags',
|
|
'attributes' => array(
|
|
'tagsToShow' => array(
|
|
'type' => 'number',
|
|
'default' => 10,
|
|
),
|
|
),
|
|
) );
|
|
|
|
register_block_type( 'ansico/micropost-activity', array(
|
|
'editor_script' => 'ansico-blocks-js',
|
|
'style' => 'ansico-style',
|
|
'render_callback' => 'ansico_render_micropost_activity',
|
|
'attributes' => array(
|
|
'itemsPerPage' => array(
|
|
'type' => 'number',
|
|
'default' => 10,
|
|
),
|
|
),
|
|
) );
|
|
}
|
|
|
|
function ansico_get_author_micropost_comment_count( $author_id ) {
|
|
$author_id = intval( $author_id );
|
|
if ( $author_id < 1 ) {
|
|
return 0;
|
|
}
|
|
|
|
return (int) get_comments( array(
|
|
'user_id' => $author_id,
|
|
'status' => 'approve',
|
|
'post_type' => 'micropost',
|
|
'type' => 'comment',
|
|
'count' => true,
|
|
) );
|
|
}
|
|
|
|
|
|
|
|
function ansico_get_social_profile_fields() {
|
|
return array(
|
|
'facebook' => array( 'label' => 'Facebook', 'abbr' => 'f' ),
|
|
'twitter' => array( 'label' => 'Twitter/X', 'abbr' => 'X' ),
|
|
'bluesky' => array( 'label' => 'Bluesky', 'abbr' => 'B' ),
|
|
'threads' => array( 'label' => 'Threads', 'abbr' => '@' ),
|
|
'mastodon' => array( 'label' => 'Mastodon', 'abbr' => 'M' ),
|
|
'instagram' => array( 'label' => 'Instagram', 'abbr' => 'I' ),
|
|
'linkedin' => array( 'label' => 'LinkedIn', 'abbr' => 'in' ),
|
|
'friendica' => array( 'label' => 'Friendica', 'abbr' => 'F' ),
|
|
'pixelfed' => array( 'label' => 'Pixelfed', 'abbr' => 'P' ),
|
|
);
|
|
}
|
|
|
|
function ansico_get_visible_social_profiles( $user_id ) {
|
|
$profiles = array();
|
|
foreach ( ansico_get_social_profile_fields() as $key => $field ) {
|
|
$url = trim( (string) get_user_meta( $user_id, 'ansico_social_' . $key . '_url', true ) );
|
|
$show = ! empty( get_user_meta( $user_id, 'ansico_social_' . $key . '_show', true ) );
|
|
if ( $show && ! empty( $url ) ) {
|
|
$profiles[ $key ] = array(
|
|
'label' => $field['label'],
|
|
'abbr' => $field['abbr'],
|
|
'url' => esc_url( $url ),
|
|
);
|
|
}
|
|
}
|
|
return $profiles;
|
|
}
|
|
|
|
function ansico_render_social_profile_links( $user_id ) {
|
|
$profiles = ansico_get_visible_social_profiles( $user_id );
|
|
if ( empty( $profiles ) ) {
|
|
return '';
|
|
}
|
|
|
|
$html = '<div class="ansico-author-social-links" aria-label="' . esc_attr__( 'Social profiles', 'ansico-some-plugin' ) . '">';
|
|
foreach ( $profiles as $key => $profile ) {
|
|
$html .= '<a class="ansico-social-link ansico-social-link-' . esc_attr( $key ) . '" href="' . esc_url( $profile['url'] ) . '" target="_blank" rel="nofollow noopener" title="' . esc_attr( $profile['label'] ) . '" aria-label="' . esc_attr( $profile['label'] ) . '"><span class="ansico-social-link-abbr">' . esc_html( $profile['abbr'] ) . '</span></a>';
|
|
}
|
|
$html .= '</div>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
function ansico_render_author_intro_html( $author_id ) {
|
|
$author_name = get_the_author_meta('display_name', $author_id);
|
|
$author_avatar = get_avatar_url($author_id, array('size' => 120));
|
|
$post_count = count_user_posts($author_id, 'micropost');
|
|
$comment_count = ansico_get_author_micropost_comment_count( $author_id );
|
|
$author_bio = get_the_author_meta('description', $author_id);
|
|
$author_website = get_the_author_meta('user_url', $author_id);
|
|
$social_links = ansico_render_social_profile_links( $author_id );
|
|
|
|
if ($author_bio) {
|
|
$author_bio = esc_html($author_bio);
|
|
$author_bio = preg_replace('/(?<=^|\s|>|>)@([a-zA-Z0-9_]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i', '<a href="https://$2/@$1" target="_blank" rel="nofollow">@$1@$2</a>', $author_bio);
|
|
$author_bio = make_clickable($author_bio);
|
|
$author_bio = preg_replace('/>https?:\/\/(www\.)?([^<]+)<\/a>/i', '>$2</a>', $author_bio);
|
|
$author_bio = wpautop($author_bio);
|
|
}
|
|
|
|
ob_start(); ?>
|
|
<div class="ansico-author-intro" style="margin-bottom: 30px;">
|
|
<img src="<?php echo esc_url($author_avatar); ?>" class="ansico-author-intro-avatar" />
|
|
<div class="ansico-author-intro-content">
|
|
<h2 class="ansico-author-intro-name"><?php echo esc_html($author_name); ?></h2>
|
|
<?php if ($author_bio) : ?><div class="ansico-author-intro-bio"><?php echo wp_kses_post($author_bio); ?></div><?php endif; ?>
|
|
<?php if (!empty($author_website)) : ?>
|
|
<div class="ansico-author-intro-website">
|
|
<a href="<?php echo esc_url($author_website); ?>" target="_blank" rel="nofollow noopener">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#536471" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: text-bottom; margin-right: 4px;"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
|
<?php echo esc_html(preg_replace('#^https?://(www\.)?#', '', $author_website)); ?>
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php if ( ! empty( $social_links ) ) : ?>
|
|
<?php echo $social_links; ?>
|
|
<?php endif; ?>
|
|
<div class="ansico-author-intro-stats" style="display:flex; gap:16px; flex-wrap:wrap; align-items:center;">
|
|
<span><strong><?php echo intval($post_count); ?></strong> <?php echo esc_html__( 'Microposts', 'ansico-some-plugin' ); ?></span>
|
|
<span><strong><?php echo intval($comment_count); ?></strong> <?php echo esc_html__( 'Comments', 'ansico-some-plugin' ); ?></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
function ansico_render_author() {
|
|
if ( is_author() ) {
|
|
$author_id = get_queried_object_id();
|
|
} else {
|
|
$author_id = get_post_field( 'post_author', get_the_ID() ) ?: get_current_user_id();
|
|
}
|
|
|
|
return ansico_render_author_intro_html( $author_id );
|
|
}
|
|
|
|
function ansico_render_comment($attributes) {
|
|
$author_id = get_post_field( 'post_author', get_the_ID() ) ?: get_current_user_id();
|
|
return ansico_get_tweet_html($author_id, $attributes['text'] ?? '', $attributes['time'] ?? '', $attributes['url'] ?? '', null, get_the_ID());
|
|
}
|
|
|
|
function ansico_render_micropost_form() {
|
|
if ( !is_user_logged_in() ) return '';
|
|
$max_chars = ansico_get_micropost_max_chars();
|
|
ob_start(); ?>
|
|
<div class="ansico-micropost-form-wrap">
|
|
<textarea id="ansico-micropost-text" placeholder="<?php echo esc_attr__( "What's happening?", 'ansico-some-plugin' ); ?>" maxlength="<?php echo esc_attr( $max_chars ); ?>"></textarea>
|
|
<div class="ansico-form-bottom">
|
|
<span id="ansico-char-counter">0 / <?php echo esc_html( $max_chars ); ?></span>
|
|
<button id="ansico-post-btn" class="wp-element-button"><?php echo esc_html__( 'Post', 'ansico-some-plugin' ); ?></button>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const area = document.getElementById('ansico-micropost-text');
|
|
const count = document.getElementById('ansico-char-counter');
|
|
const btn = document.getElementById('ansico-post-btn');
|
|
const maxChars = <?php echo (int) $max_chars; ?>;
|
|
if(!area) return;
|
|
area.addEventListener('input', () => {
|
|
let len = area.value.length;
|
|
count.innerText = len + ' / ' + maxChars;
|
|
count.style.color = len > maxChars ? '#e0245e' : '#536471';
|
|
});
|
|
btn.addEventListener('click', () => {
|
|
if(!area.value.trim()) return;
|
|
if(area.value.length > maxChars) return;
|
|
btn.disabled = true;
|
|
fetch('<?php echo esc_url(rest_url("ansico/v1/create-micropost")); ?>', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': '<?php echo wp_create_nonce("wp_rest"); ?>' },
|
|
body: JSON.stringify({ text: area.value })
|
|
}).then(r => r.json()).then(data => {
|
|
if(data.success) { area.value = ''; window.location.reload(); } else { btn.disabled = false; }
|
|
}).catch(() => {
|
|
btn.disabled = false;
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
function ansico_render_micropost_list($attributes) {
|
|
if ( is_front_page() ) { $paged = ( get_query_var( 'page' ) ) ? get_query_var( 'page' ) : 1; }
|
|
else { $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; }
|
|
|
|
$search_query = isset($_GET['ms']) ? sanitize_text_field($_GET['ms']) : '';
|
|
$is_single_micropost = is_singular('micropost');
|
|
$tag_filter = isset($attributes['tagFilter']) ? sanitize_text_field($attributes['tagFilter']) : '';
|
|
|
|
if ( empty($tag_filter) && is_tax('micropost_tag') ) {
|
|
$current_term = get_queried_object();
|
|
if ( $current_term && isset($current_term->slug) ) $tag_filter = $current_term->slug;
|
|
}
|
|
|
|
$author_filter = is_author() ? get_queried_object_id() : 0;
|
|
$ppp = isset($attributes['postsPerPage']) ? intval($attributes['postsPerPage']) : 20;
|
|
|
|
$query_args = array(
|
|
'post_type' => 'micropost',
|
|
'posts_per_page' => $is_single_micropost ? 1 : $ppp,
|
|
'paged' => $paged,
|
|
'orderby' => 'date',
|
|
'order' => 'DESC'
|
|
);
|
|
if (!empty($search_query)) {
|
|
$matching_ids = ansico_get_micropost_ids_matching_search( $search_query );
|
|
$query_args['post__in'] = !empty($matching_ids) ? $matching_ids : array(0);
|
|
}
|
|
if ($is_single_micropost) $query_args['p'] = get_the_ID();
|
|
if ($author_filter) $query_args['author'] = $author_filter;
|
|
if (!empty($tag_filter)) {
|
|
$tag_filter = ltrim($tag_filter, '#');
|
|
$query_args['tax_query'] = array(array('taxonomy' => 'micropost_tag', 'field' => 'slug', 'terms' => $tag_filter));
|
|
}
|
|
|
|
$query = new WP_Query($query_args);
|
|
|
|
ob_start();
|
|
|
|
// Vis forfatter intro hvis vi er på en forfatter side
|
|
if ( is_author() && $paged == 1 && empty($search_query) ) {
|
|
$author_id = get_queried_object_id();
|
|
echo ansico_render_author_intro_html( $author_id );
|
|
}
|
|
|
|
echo '<div class="ansico-micropost-list">';
|
|
if ($query->have_posts()) {
|
|
while ($query->have_posts()) {
|
|
$query->the_post();
|
|
$url = get_post_meta(get_the_ID(), 'ansico_micropost_url', true);
|
|
$time = get_post_meta(get_the_ID(), 'ansico_micropost_time', true);
|
|
echo ansico_get_tweet_html(get_the_author_meta('ID'), get_the_content(), $time, $url, null, get_the_ID());
|
|
}
|
|
if ( !$is_single_micropost ) {
|
|
$big = 999999999;
|
|
echo '<div class="ansico-pagination">';
|
|
echo paginate_links(array(
|
|
'base' => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
|
|
'format' => '?paged=%#%',
|
|
'current' => max(1, $paged),
|
|
'total' => $query->max_num_pages,
|
|
'prev_text' => '« Forrige',
|
|
'next_text' => __( 'Next »', 'ansico-some-plugin' ),
|
|
));
|
|
echo '</div>';
|
|
}
|
|
wp_reset_postdata();
|
|
}
|
|
echo '</div>';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
|
|
|
|
|
|
function ansico_render_micropost_top_tags($attributes) {
|
|
$tags_to_show = isset($attributes['tagsToShow']) ? intval($attributes['tagsToShow']) : 10;
|
|
if ($tags_to_show < 1) {
|
|
$tags_to_show = 1;
|
|
}
|
|
|
|
$terms = get_terms(array(
|
|
'taxonomy' => 'micropost_tag',
|
|
'hide_empty' => true,
|
|
'number' => $tags_to_show,
|
|
'orderby' => 'count',
|
|
'order' => 'DESC',
|
|
));
|
|
|
|
if (is_wp_error($terms) || empty($terms)) {
|
|
return '';
|
|
}
|
|
|
|
ob_start();
|
|
echo '<div class="ansico-micropost-top-tags-block">';
|
|
echo '<div class="ansico-micropost-top-tags-list">';
|
|
|
|
foreach ($terms as $term) {
|
|
$term_link = get_term_link($term);
|
|
if (is_wp_error($term_link)) {
|
|
continue;
|
|
}
|
|
|
|
echo '<a class="ansico-micropost-tag-pill" href="' . esc_url($term_link) . '">';
|
|
echo '<span class="ansico-micropost-tag-name">#' . esc_html($term->name) . '</span>';
|
|
echo '<span class="ansico-micropost-tag-count">' . intval($term->count) . '</span>';
|
|
echo '</a>';
|
|
}
|
|
|
|
echo '</div>';
|
|
echo '</div>';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
function ansico_render_micropost_comments($attributes) {
|
|
$comments_to_show = isset($attributes['commentsToShow']) ? intval($attributes['commentsToShow']) : 5;
|
|
if ($comments_to_show < 1) {
|
|
$comments_to_show = 1;
|
|
}
|
|
|
|
$comments = get_comments(array(
|
|
'status' => 'approve',
|
|
'number' => $comments_to_show,
|
|
'orderby' => 'comment_date_gmt',
|
|
'order' => 'DESC',
|
|
'post_type' => 'micropost',
|
|
'type__in' => array('', 'comment'),
|
|
));
|
|
|
|
if (empty($comments)) {
|
|
return '';
|
|
}
|
|
|
|
ob_start();
|
|
echo '<div class="ansico-micropost-comments-block">';
|
|
|
|
foreach ($comments as $comment) {
|
|
echo ansico_render_activity_comment_item($comment);
|
|
}
|
|
|
|
echo '</div>';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
|
|
function ansico_render_activity_comment_item( $comment ) {
|
|
$post_id = isset($comment->comment_post_ID) ? intval($comment->comment_post_ID) : 0;
|
|
if (!$post_id || get_post_type($post_id) !== 'micropost') {
|
|
return '';
|
|
}
|
|
|
|
$micropost_permalink = get_permalink($post_id);
|
|
$comment_permalink = get_comment_link($comment);
|
|
$reply_permalink = $micropost_permalink ? add_query_arg( 'replytocom', intval( $comment->comment_ID ), $micropost_permalink ) . '#respond' : '';
|
|
$author_url = '';
|
|
if ( is_object( $comment ) && ! empty( $comment->user_id ) ) {
|
|
$author_url = get_author_posts_url( (int) $comment->user_id );
|
|
} elseif ( is_object( $comment ) && ! empty( $comment->comment_author_url ) ) {
|
|
$author_url = $comment->comment_author_url;
|
|
}
|
|
$author_name = get_comment_author($comment);
|
|
$avatar = get_avatar($comment, 40, '', '', array('class' => 'ansico-tweet-avatar'));
|
|
$avatar_html = $author_url ? '<a class="ansico-comment-avatar-link" href="' . esc_url( $author_url ) . '">' . $avatar . '</a>' : $avatar;
|
|
$time_display = get_comment_date( get_option('date_format'), $comment ) . ' · ' . get_comment_time( get_option('time_format'), false, false, $comment );
|
|
$comment_text = ansico_get_formatted_comment_html( $comment );
|
|
$reply_count = get_comments(array(
|
|
'post_id' => $post_id,
|
|
'parent' => intval($comment->comment_ID),
|
|
'status' => 'approve',
|
|
'count' => true,
|
|
'type__in' => array('', 'comment'),
|
|
));
|
|
$like_button = ansico_render_like_button( 'comment', $comment->comment_ID );
|
|
|
|
ob_start();
|
|
echo '<article class="ansico-activity-item ansico-activity-item-comment ansico-micropost-wrapper">';
|
|
echo '<div class="ansico-some-tweet ansico-some-tweet-comment">';
|
|
|
|
echo '<div class="ansico-activity-comment-top-actions">';
|
|
if ($micropost_permalink) {
|
|
echo '<a class="ansico-action-btn ansico-activity-comment-top-action" href="' . esc_url($micropost_permalink) . '" title="' . esc_attr__( 'Go to micropost', 'ansico-some-plugin' ) . '" aria-label="' . esc_attr__( 'Go to micropost', 'ansico-some-plugin' ) . '">';
|
|
echo '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"></path><path d="M12 5l7 7-7 7"></path></svg>';
|
|
echo '</a>';
|
|
}
|
|
echo "<button class=\"ansico-action-btn ansico-activity-comment-top-action ansico-activity-copy-btn\" type=\"button\" onclick=\"navigator.clipboard.writeText('" . esc_js( $comment_permalink ) . "'); var el=this; el.classList.add('copied'); setTimeout(function(){el.classList.remove('copied');}, 2000);\" title=\"" . esc_attr__( 'Copy comment link', 'ansico-some-plugin' ) . "\" aria-label=\"" . esc_attr__( 'Copy comment link', 'ansico-some-plugin' ) . "\">";
|
|
echo '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>';
|
|
echo '</button>';
|
|
echo '</div>';
|
|
|
|
echo '<div class="ansico-comment-avatar-wrap">' . $avatar_html . '</div>';
|
|
echo '<div class="ansico-tweet-content ansico-comment-content-wrap">';
|
|
echo '<div class="ansico-tweet-header ansico-comment-header-row">';
|
|
|
|
if (!empty($author_url)) {
|
|
echo '<a class="ansico-tweet-name-link" href="' . esc_url($author_url) . '" rel="nofollow ugc"><span class="ansico-tweet-name">' . esc_html($author_name) . '</span></a>';
|
|
} else {
|
|
echo '<span class="ansico-tweet-name">' . esc_html($author_name) . '</span>';
|
|
}
|
|
|
|
echo '<span class="ansico-tweet-time">' . esc_html( wp_strip_all_tags( $time_display ) ) . '</span>';
|
|
echo '</div>';
|
|
echo '<div class="ansico-tweet-text ansico-comment-text-body">' . wp_kses_post( $comment_text ) . '</div>';
|
|
echo '<div class="ansico-tweet-actions-bottom ansico-activity-comment-actions">';
|
|
if ($like_button) {
|
|
echo $like_button;
|
|
}
|
|
if ($reply_permalink) {
|
|
echo '<a class="ansico-action-btn ansico-comment-btn ansico-activity-reply-btn" href="' . esc_url($reply_permalink) . '" title="' . esc_attr__( 'Reply to this comment', 'ansico-some-plugin' ) . '" aria-label="' . esc_attr__( 'Reply to this comment', 'ansico-some-plugin' ) . '">';
|
|
echo '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>';
|
|
echo '<span class="ansico-comment-count">' . intval($reply_count) . '</span>';
|
|
echo '</a>';
|
|
}
|
|
echo '</div>';
|
|
echo '</div>';
|
|
echo '</div>';
|
|
echo '</article>';
|
|
|
|
return ob_get_clean();
|
|
}
|
|
|
|
function ansico_render_micropost_activity($attributes) {
|
|
global $wpdb;
|
|
|
|
$items_per_page = isset($attributes['itemsPerPage']) ? intval($attributes['itemsPerPage']) : 10;
|
|
if ($items_per_page < 1) {
|
|
$items_per_page = 1;
|
|
}
|
|
|
|
$current_page = isset($_GET['ansico_activity_page']) ? intval($_GET['ansico_activity_page']) : 1;
|
|
if ($current_page < 1) {
|
|
$current_page = 1;
|
|
}
|
|
|
|
$offset = ($current_page - 1) * $items_per_page;
|
|
|
|
$posts_table = $wpdb->posts;
|
|
$comments_table = $wpdb->comments;
|
|
|
|
$total_posts = (int) $wpdb->get_var(
|
|
"SELECT COUNT(ID) FROM {$posts_table} WHERE post_type = 'micropost' AND post_status = 'publish'"
|
|
);
|
|
|
|
$total_comments = (int) $wpdb->get_var(
|
|
"SELECT COUNT(c.comment_ID)
|
|
FROM {$comments_table} c
|
|
INNER JOIN {$posts_table} p ON c.comment_post_ID = p.ID
|
|
WHERE c.comment_approved = '1'
|
|
AND (c.comment_type = '' OR c.comment_type = 'comment')
|
|
AND p.post_type = 'micropost'
|
|
AND p.post_status = 'publish'"
|
|
);
|
|
|
|
$total_items = $total_posts + $total_comments;
|
|
if ($total_items < 1) {
|
|
return '';
|
|
}
|
|
|
|
$query = $wpdb->prepare(
|
|
"(SELECT ID AS object_id, post_date_gmt AS event_date_gmt, 'post' AS event_type
|
|
FROM {$posts_table}
|
|
WHERE post_type = 'micropost' AND post_status = 'publish')
|
|
UNION ALL
|
|
(SELECT c.comment_ID AS object_id, c.comment_date_gmt AS event_date_gmt, 'comment' AS event_type
|
|
FROM {$comments_table} c
|
|
INNER JOIN {$posts_table} p ON c.comment_post_ID = p.ID
|
|
WHERE c.comment_approved = '1'
|
|
AND (c.comment_type = '' OR c.comment_type = 'comment')
|
|
AND p.post_type = 'micropost'
|
|
AND p.post_status = 'publish')
|
|
ORDER BY event_date_gmt DESC
|
|
LIMIT %d OFFSET %d",
|
|
$items_per_page,
|
|
$offset
|
|
);
|
|
|
|
$rows = $wpdb->get_results($query);
|
|
if (empty($rows)) {
|
|
return '';
|
|
}
|
|
|
|
ob_start();
|
|
echo '<div class="ansico-micropost-activity-block">';
|
|
|
|
foreach ($rows as $row) {
|
|
if ($row->event_type === 'post') {
|
|
$post = get_post((int) $row->object_id);
|
|
if (!$post || $post->post_status !== 'publish' || $post->post_type !== 'micropost') {
|
|
continue;
|
|
}
|
|
$url = get_post_meta($post->ID, 'ansico_micropost_url', true);
|
|
$time = get_post_meta($post->ID, 'ansico_micropost_time', true);
|
|
echo '<div class="ansico-activity-item ansico-activity-item-post">';
|
|
echo ansico_get_tweet_html($post->post_author, $post->post_content, $time, $url, null, $post->ID);
|
|
echo '</div>';
|
|
} else {
|
|
$comment = get_comment((int) $row->object_id);
|
|
if (!$comment) {
|
|
continue;
|
|
}
|
|
echo ansico_render_activity_comment_item($comment);
|
|
}
|
|
}
|
|
|
|
$total_pages = (int) ceil($total_items / $items_per_page);
|
|
if ($total_pages > 1) {
|
|
$pagination = paginate_links(array(
|
|
'base' => esc_url_raw(add_query_arg('ansico_activity_page', '%#%')),
|
|
'format' => '',
|
|
'current' => $current_page,
|
|
'total' => $total_pages,
|
|
'type' => 'list',
|
|
'prev_text' => '« Forrige',
|
|
'next_text' => __( 'Next »', 'ansico-some-plugin' ),
|
|
));
|
|
|
|
if ($pagination) {
|
|
echo '<nav class="ansico-activity-pagination" aria-label="Micropost aktivitet sider">' . wp_kses_post($pagination) . '</nav>';
|
|
}
|
|
}
|
|
|
|
echo '</div>';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
add_action( 'rest_api_init', function () {
|
|
register_rest_route( 'ansico/v1', '/create-micropost', array( 'methods' => 'POST', 'callback' => 'ansico_rest_create', 'permission_callback' => function() { return is_user_logged_in(); } ) );
|
|
register_rest_route( 'ansico/v1', '/toggle-like', array(
|
|
'methods' => 'POST',
|
|
'callback' => 'ansico_rest_toggle_like',
|
|
'permission_callback' => function() { return is_user_logged_in(); },
|
|
) );
|
|
});
|
|
|
|
function ansico_rest_create($req) {
|
|
$text = sanitize_textarea_field($req['text']);
|
|
$max_chars = ansico_get_micropost_max_chars();
|
|
if (empty($text)) {
|
|
return array('success' => false, 'message' => 'Tom micropost.');
|
|
}
|
|
if ( function_exists( 'mb_strlen' ) ? mb_strlen( $text ) > $max_chars : strlen( $text ) > $max_chars ) {
|
|
return array('success' => false, 'message' => __( 'Micropost is too long.', 'ansico-some-plugin' ));
|
|
}
|
|
$post_id = wp_insert_post(array('post_type' => 'micropost', 'post_content' => $text, 'post_status' => 'publish', 'comment_status' => 'open'));
|
|
if ($post_id) {
|
|
update_post_meta($post_id, 'ansico_micropost_time', current_time('mysql'));
|
|
update_post_meta($post_id, 'ansico_micropost_url', get_permalink($post_id));
|
|
return array('success' => true);
|
|
}
|
|
return array('success' => false, 'message' => __( 'Could not create micropost.', 'ansico-some-plugin' ));
|
|
}
|
|
|
|
function ansico_fetch_metadata_internal($url) {
|
|
$response = wp_remote_get( $url );
|
|
if ( is_wp_error( $response ) ) return null;
|
|
$html = wp_remote_retrieve_body( $response );
|
|
libxml_use_internal_errors(true);
|
|
$doc = new DOMDocument();
|
|
@$doc->loadHTML( mb_convert_encoding( $html, 'HTML-ENTITIES', 'UTF-8' ) );
|
|
libxml_clear_errors();
|
|
$res = array('title' => '', 'image' => '', 'domain' => str_replace('www.', '', wp_parse_url($url, PHP_URL_HOST)));
|
|
$tags = $doc->getElementsByTagName('meta');
|
|
foreach ($tags as $tag) {
|
|
if ($tag->getAttribute('property') === 'og:title') $res['title'] = $tag->getAttribute('content');
|
|
if ($tag->getAttribute('property') === 'og:image') $res['image'] = $tag->getAttribute('content');
|
|
}
|
|
if(empty($res['title'])) { $t = $doc->getElementsByTagName('title'); if($t->length > 0) $res['title'] = $t->item(0)->nodeValue; }
|
|
return $res;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
5. AVATAR FILTERS
|
|
========================================================================== */
|
|
add_filter( 'get_avatar_url', function( $url, $id_or_email, $args ) {
|
|
$user_id = null;
|
|
if ( is_numeric( $id_or_email ) ) { $user_id = $id_or_email; }
|
|
elseif ( is_object( $id_or_email ) && isset( $id_or_email->user_id ) ) { $user_id = $id_or_email->user_id; }
|
|
if ( $user_id ) {
|
|
$custom = get_user_meta( $user_id, 'ansico_avatar_url', true );
|
|
if ( $custom ) return $custom;
|
|
}
|
|
return $url;
|
|
}, 10, 3 );
|
|
|
|
add_action( 'show_user_profile', 'ansico_avatar_field' );
|
|
add_action( 'edit_user_profile', 'ansico_avatar_field' );
|
|
function ansico_avatar_field($user) {
|
|
$url = get_user_meta($user->ID, 'ansico_avatar_url', true);
|
|
echo '<h3>' . esc_html__( 'Profilbillede', 'ansico-some-plugin' ) . '</h3><table class="form-table"><tr><th>Profilbillede</th><td><img id="ansico-avatar-preview" src="'.esc_url($url).'" style="width:120px; height:120px; object-fit:cover; display:'.($url?'block':'none').'; border-radius:50%;"/><input type="hidden" name="ansico_avatar_url" id="ansico-avatar-url" value="'.esc_attr($url).'"/><button class="button" id="ansico-upload-button" style="margin-top:10px;">Upload</button> <button class="button" id="ansico-remove-button" style="margin-top:10px;">Remove</button></td></tr></table>';
|
|
|
|
echo '<h3>' . esc_html__( 'Social profiles', 'ansico-some-plugin' ) . '</h3>';
|
|
echo '<table class="form-table" role="presentation">';
|
|
foreach ( ansico_get_social_profile_fields() as $key => $field ) {
|
|
$profile_url = get_user_meta( $user->ID, 'ansico_social_' . $key . '_url', true );
|
|
$show_on_profile = ! empty( get_user_meta( $user->ID, 'ansico_social_' . $key . '_show', true ) );
|
|
echo '<tr>';
|
|
echo '<th><label for="ansico-social-' . esc_attr( $key ) . '">' . esc_html( $field['label'] ) . '</label></th>';
|
|
echo '<td>';
|
|
echo '<div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">';
|
|
echo '<input type="url" class="regular-text" id="ansico-social-' . esc_attr( $key ) . '" name="ansico_social[' . esc_attr( $key ) . '][url]" value="' . esc_attr( $profile_url ) . '" placeholder="https://" />';
|
|
echo '<label style="display:inline-flex; align-items:center; gap:6px;"><input type="checkbox" name="ansico_social[' . esc_attr( $key ) . '][show]" value="1" ' . checked( $show_on_profile, true, false ) . ' /> ' . esc_html__( 'Show on profile', 'ansico-some-plugin' ) . '</label>';
|
|
echo '</div>';
|
|
echo '</td>';
|
|
echo '</tr>';
|
|
}
|
|
echo '</table>';
|
|
}
|
|
|
|
|
|
function ansico_rest_toggle_like( WP_REST_Request $request ) {
|
|
$object_type = sanitize_key( (string) $request->get_param( 'object_type' ) );
|
|
$object_id = intval( $request->get_param( 'object_id' ) );
|
|
|
|
if ( ! in_array( $object_type, array( 'post', 'comment' ), true ) ) {
|
|
return new WP_Error( 'ansico_like_invalid_type', __( 'Invalid like type.', 'ansico-some-plugin' ), array( 'status' => 400 ) );
|
|
}
|
|
|
|
$result = ansico_toggle_like( $object_type, $object_id, get_current_user_id() );
|
|
if ( is_wp_error( $result ) ) {
|
|
return $result;
|
|
}
|
|
|
|
return rest_ensure_response( array(
|
|
'liked' => ! empty( $result['liked'] ),
|
|
'count' => intval( $result['count'] ),
|
|
) );
|
|
}
|
|
|
|
add_action( 'personal_options_update', 'ansico_save_avatar' );
|
|
add_action( 'edit_user_profile_update', 'ansico_save_avatar' );
|
|
function ansico_save_avatar($user_id) {
|
|
if(isset($_POST['ansico_avatar_url'])) update_user_meta($user_id, 'ansico_avatar_url', esc_url_raw($_POST['ansico_avatar_url']));
|
|
|
|
$social_input = isset( $_POST['ansico_social'] ) && is_array( $_POST['ansico_social'] ) ? $_POST['ansico_social'] : array();
|
|
foreach ( ansico_get_social_profile_fields() as $key => $field ) {
|
|
$row = isset( $social_input[ $key ] ) && is_array( $social_input[ $key ] ) ? $social_input[ $key ] : array();
|
|
$url = isset( $row['url'] ) ? esc_url_raw( trim( wp_unslash( $row['url'] ) ) ) : '';
|
|
$show = ! empty( $row['show'] ) ? '1' : '';
|
|
update_user_meta( $user_id, 'ansico_social_' . $key . '_url', $url );
|
|
update_user_meta( $user_id, 'ansico_social_' . $key . '_show', $show );
|
|
}
|
|
}
|
|
|
|
add_action( 'admin_enqueue_scripts', function( $hook ) {
|
|
if ( 'profile.php' === $hook || 'user-edit.php' === $hook ) {
|
|
wp_enqueue_media();
|
|
wp_enqueue_script( 'ansico-admin', plugins_url( 'admin-script.js', __FILE__ ), array( 'jquery' ), ANSICO_SOME_PLUGIN_VERSION, true );
|
|
wp_localize_script(
|
|
'ansico-admin',
|
|
'ansicoAdminSettings',
|
|
array(
|
|
'cleanUpProfileSettings' => ! empty( get_option( 'ansico_clean_up_profile_settings', '' ) ),
|
|
'labels' => array(
|
|
'profile' => __( 'Profile', 'ansico-some-plugin' ),
|
|
'federation' => __( 'Federation', 'ansico-some-plugin' ),
|
|
'otherSettings' => __( 'Other settings', 'ansico-some-plugin' ),
|
|
),
|
|
)
|
|
);
|
|
}
|
|
} );
|
|
|
|
add_action( 'admin_head-profile.php', 'ansico_render_profile_cleanup_admin_css' );
|
|
add_action( 'admin_head-user-edit.php', 'ansico_render_profile_cleanup_admin_css' );
|
|
function ansico_render_profile_cleanup_admin_css() {
|
|
if ( empty( get_option( 'ansico_clean_up_profile_settings', '' ) ) ) {
|
|
return;
|
|
}
|
|
?>
|
|
<style>
|
|
.ansico-profile-tabs-nav {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin: 20px 0 24px;
|
|
border-bottom: 1px solid #dcdcde;
|
|
padding-bottom: 0;
|
|
}
|
|
.ansico-profile-tabs-nav .ansico-profile-tab-button {
|
|
border: 1px solid #dcdcde;
|
|
border-bottom: none;
|
|
background: #f6f7f7;
|
|
color: #1d2327;
|
|
padding: 10px 14px;
|
|
margin: 0;
|
|
border-radius: 6px 6px 0 0;
|
|
cursor: pointer;
|
|
font-weight: 600;
|
|
}
|
|
.ansico-profile-tabs-nav .ansico-profile-tab-button.is-active {
|
|
background: #fff;
|
|
position: relative;
|
|
top: 1px;
|
|
}
|
|
.ansico-profile-tab-panel {
|
|
display: none;
|
|
}
|
|
.ansico-profile-tab-panel.is-active {
|
|
display: block;
|
|
}
|
|
.ansico-profile-tab-panel h2:first-child,
|
|
.ansico-profile-tab-panel h3:first-child {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.ansico-profile-tab-panel {
|
|
padding-bottom: 96px;
|
|
}
|
|
.ansico-profile-card {
|
|
background: #fff;
|
|
border: 1px solid #dcdcde;
|
|
border-radius: 16px;
|
|
padding: 18px 22px;
|
|
margin: 0 0 18px;
|
|
box-shadow: 0 1px 2px rgba(0,0,0,.04);
|
|
}
|
|
.ansico-profile-card > h2,
|
|
.ansico-profile-card > h3 {
|
|
margin-top: 0;
|
|
margin-bottom: 16px;
|
|
}
|
|
.ansico-profile-card .form-table th {
|
|
width: 220px;
|
|
}
|
|
.ansico-profile-subheading-row th {
|
|
width: auto !important;
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: .04em;
|
|
color: #50575e;
|
|
padding-top: 18px;
|
|
padding-bottom: 8px;
|
|
}
|
|
.ansico-profile-inline-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 16px;
|
|
margin-bottom: 10px;
|
|
}
|
|
.ansico-profile-inline-label {
|
|
display: block;
|
|
font-weight: 600;
|
|
margin: 0 0 6px;
|
|
color: #1d2327;
|
|
}
|
|
.ansico-profile-inline-control input[type="text"],
|
|
.ansico-profile-inline-control input[type="email"],
|
|
.ansico-profile-inline-control input[type="url"] {
|
|
width: 100%;
|
|
}
|
|
.ansico-profile-card-avatar .form-table th {
|
|
display: none;
|
|
}
|
|
.ansico-profile-card-avatar .form-table td {
|
|
padding-left: 0;
|
|
}
|
|
.ansico-profile-hero-card {
|
|
overflow: hidden;
|
|
padding-top: 0;
|
|
}
|
|
.ansico-profile-hero-card > h2,
|
|
.ansico-profile-hero-card > h3 {
|
|
padding-top: 18px;
|
|
padding-left: 22px;
|
|
padding-right: 22px;
|
|
margin-bottom: 12px;
|
|
}
|
|
.ansico-profile-cover-table {
|
|
width: min(100%, 820px);
|
|
margin: 0 auto 0;
|
|
border-collapse: separate;
|
|
border-spacing: 0;
|
|
}
|
|
.ansico-profile-cover-row th {
|
|
display: none;
|
|
}
|
|
.ansico-profile-cover-row td {
|
|
padding: 0 0 12px !important;
|
|
}
|
|
.ansico-profile-cover-row img {
|
|
width: 100%;
|
|
max-width: none;
|
|
height: 180px;
|
|
object-fit: cover;
|
|
display: block;
|
|
border-radius: 16px;
|
|
}
|
|
|
|
.ansico-header-trigger {
|
|
width: 100%;
|
|
min-height: 180px;
|
|
border: 0;
|
|
background: #f6f7f7;
|
|
padding: 0;
|
|
display: block;
|
|
cursor: pointer;
|
|
overflow: hidden;
|
|
border-radius: 16px;
|
|
}
|
|
.ansico-header-trigger img {
|
|
width: 100%;
|
|
max-width: none;
|
|
height: 180px;
|
|
object-fit: cover;
|
|
display: block;
|
|
border-radius: 16px;
|
|
}
|
|
.ansico-header-placeholder {
|
|
min-height: 180px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #50575e;
|
|
font-weight: 600;
|
|
}
|
|
.ansico-header-hidden-button {
|
|
display: none !important;
|
|
}
|
|
.ansico-header-actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
margin-top: 10px;
|
|
flex-wrap: wrap;
|
|
}
|
|
.ansico-header-actions .button,
|
|
.ansico-header-actions button,
|
|
.ansico-header-actions input[type="button"],
|
|
.ansico-header-actions input[type="submit"] {
|
|
margin: 0 !important;
|
|
}
|
|
.ansico-header-remove-button {
|
|
margin-top: 0 !important;
|
|
}
|
|
.ansico-profile-hero-card.has-cover .ansico-avatar-cell {
|
|
margin-top: -58px;
|
|
margin-left: 48px;
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
.ansico-profile-hero-card.has-cover .ansico-avatar-remove-button {
|
|
margin-left: 48px;
|
|
}
|
|
.ansico-avatar-cell {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: 12px;
|
|
}
|
|
.ansico-avatar-trigger {
|
|
width: 120px;
|
|
height: 120px;
|
|
border-radius: 999px;
|
|
border: 1px solid #dcdcde;
|
|
background: #f6f7f7;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
overflow: hidden;
|
|
padding: 0;
|
|
}
|
|
.ansico-avatar-trigger img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
display: block !important;
|
|
border-radius: 999px;
|
|
}
|
|
.ansico-avatar-placeholder {
|
|
color: #50575e;
|
|
font-weight: 600;
|
|
}
|
|
.ansico-avatar-hidden-button {
|
|
display: none !important;
|
|
}
|
|
.ansico-avatar-remove-button {
|
|
margin-top: 0 !important;
|
|
}
|
|
.ansico-profile-submit-wrap {
|
|
margin-top: 24px;
|
|
padding: 16px 0 0;
|
|
border-top: 1px solid #dcdcde;
|
|
display: block;
|
|
position: sticky;
|
|
bottom: 0;
|
|
background: #fff;
|
|
z-index: 5;
|
|
}
|
|
.ansico-profile-submit-wrap .submit,
|
|
.ansico-profile-submit-wrap p.submit {
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
</style>
|
|
<?php
|
|
}
|
|
|
|
function ansico_render_micropost_search() {
|
|
$val = '';
|
|
if ( isset( $_GET['ms'] ) ) {
|
|
$val = esc_attr( wp_unslash( $_GET['ms'] ) );
|
|
} elseif ( isset( $_GET['s'] ) ) {
|
|
$val = esc_attr( wp_unslash( $_GET['s'] ) );
|
|
}
|
|
|
|
$search_url = get_post_type_archive_link( 'micropost' );
|
|
if ( ! $search_url ) {
|
|
$search_url = home_url( '/micropost/' );
|
|
}
|
|
|
|
ob_start(); ?>
|
|
<div class="ansico-micropost-search-wrap" style="margin-bottom: 20px;">
|
|
<form method="get" action="<?php echo esc_url( $search_url ); ?>" style="display: flex; gap: 8px;">
|
|
<input type="text" name="ms" value="<?php echo $val; ?>" placeholder="<?php echo esc_attr__( 'Search microposts...', 'ansico-some-plugin' ); ?>" style="flex: 1; border: 1px solid #eff3f4; border-radius: 9999px; padding: 8px 15px;" />
|
|
<button type="submit" class="wp-element-button" style="background: #1d9bf0; color: #fff; border: none; border-radius: 9999px; padding: 8px 20px; cursor: pointer; font-weight: bold;"><?php echo esc_html__( 'Search', 'ansico-some-plugin' ); ?></button>
|
|
</form>
|
|
</div>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ==========================================================================
|
|
6. FSE / SITE EDITOR OVERRIDES
|
|
========================================================================== */
|
|
add_filter( 'render_block', 'ansico_force_fse_micropost_layout', 10, 2 );
|
|
function ansico_force_fse_micropost_layout( $block_content, $block ) {
|
|
if ( is_admin() ) return $block_content;
|
|
|
|
// Find ud af hvilket indlæg blokken forsøger at vise
|
|
$post_id = isset($block['context']['postId']) ? $block['context']['postId'] : get_the_ID();
|
|
|
|
// Tjek om vi rent faktisk kigger på et micropost
|
|
if ( $post_id && get_post_type($post_id) === 'micropost' ) {
|
|
|
|
// FSE standard-blokke vi VIL skjule, fordi vores tweet-html allerede indeholder denne data
|
|
$hidden_blocks = array( 'core/post-title', 'core/post-date', 'core/post-author', 'core/post-author-name', 'core/post-terms', 'core/post-featured-image', 'core/read-more', 'core/avatar', 'core/post-author-biography', 'core/comment-author-name' );
|
|
if ( in_array( $block['blockName'], $hidden_blocks ) ) {
|
|
return ''; // Skjul blokken
|
|
}
|
|
|
|
// Hvis WordPress forsøger at vise indholdet, overskriver vi det med vores fulde tweet-design
|
|
if ( in_array( $block['blockName'], array( 'core/post-content', 'core/post-excerpt' ) ) ) {
|
|
wp_enqueue_style('ansico-style'); // Sørg for at plugin CSS indlæses, når standardblokken overskrives
|
|
$author_id = get_post_field( 'post_author', $post_id );
|
|
$url = get_post_meta($post_id, 'ansico_micropost_url', true);
|
|
$time = get_post_meta($post_id, 'ansico_micropost_time', true);
|
|
$raw_content = get_post_field( 'post_content', $post_id );
|
|
|
|
return ansico_get_tweet_html($author_id, $raw_content, $time, $url, null, $post_id);
|
|
}
|
|
}
|
|
|
|
return $block_content;
|
|
}
|
|
|
|
add_action( 'wp_footer', 'ansico_focus_script_v2' );
|
|
function ansico_focus_script_v2() {
|
|
?>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
function focusComment() {
|
|
setTimeout(function() {
|
|
var input = document.getElementById('comment');
|
|
if (input) {
|
|
input.focus();
|
|
var val = input.value; input.value = ''; input.value = val;
|
|
}
|
|
}, 300);
|
|
}
|
|
|
|
if (window.location.hash === '#respond') { focusComment(); }
|
|
|
|
document.body.addEventListener('click', function(e) {
|
|
var replyTrigger = e.target.closest('.comment-reply-link') || e.target.closest('.ansico-comment-btn');
|
|
if (replyTrigger) { focusComment(); }
|
|
|
|
var likeButton = e.target.closest('[data-ansico-like]');
|
|
if (!likeButton) {
|
|
return;
|
|
}
|
|
|
|
if (likeButton.disabled || likeButton.getAttribute('aria-disabled') === 'true') {
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
|
|
if (likeButton.classList.contains('is-busy')) {
|
|
return;
|
|
}
|
|
|
|
likeButton.classList.add('is-busy');
|
|
|
|
fetch('<?php echo esc_url( rest_url( 'ansico/v1/toggle-like' ) ); ?>', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-WP-Nonce': '<?php echo esc_js( wp_create_nonce( 'wp_rest' ) ); ?>'
|
|
},
|
|
body: JSON.stringify({
|
|
object_type: likeButton.getAttribute('data-object-type'),
|
|
object_id: likeButton.getAttribute('data-object-id')
|
|
})
|
|
}).then(function(response) {
|
|
return response.json().then(function(data) {
|
|
return { ok: response.ok, data: data };
|
|
});
|
|
}).then(function(result) {
|
|
if (!result.ok) {
|
|
throw new Error((result.data && result.data.message) ? result.data.message : __( 'Could not register like.', 'ansico-some-plugin' ));
|
|
}
|
|
|
|
likeButton.classList.toggle('is-liked', !!result.data.liked);
|
|
likeButton.setAttribute('title', result.data.liked ? 'Fjern like' : 'Like');
|
|
likeButton.setAttribute('aria-label', result.data.liked ? 'Fjern like' : 'Like');
|
|
var count = likeButton.querySelector('.ansico-like-count');
|
|
if (count) {
|
|
count.textContent = parseInt(result.data.count || 0, 10);
|
|
}
|
|
}).catch(function(error) {
|
|
window.alert(error && error.message ? error.message : __( 'Could not register like.', 'ansico-some-plugin' ));
|
|
}).finally(function() {
|
|
likeButton.classList.remove('is-busy');
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|