* @package AnsPress */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } /** * Mention hooks */ class AP_Mentions_Hooks{ /** * Initialize class * @since 2.4.8 Removed `$ap` args. */ public function __construct() { anspress()->add_action( 'tiny_mce_before_init', __CLASS__, 'tiny_mce_before_init' ); // Return if mention is disabled. if( ap_opt('disable_mentions') ){ return; } anspress()->add_filter( 'ap_pre_insert_question', __CLASS__, 'linkyfy_mentions' ); anspress()->add_filter( 'ap_pre_insert_answer', __CLASS__, 'linkyfy_mentions' ); anspress()->add_filter( 'ap_pre_update_question', __CLASS__, 'linkyfy_mentions' ); anspress()->add_filter( 'ap_pre_update_answer', __CLASS__, 'linkyfy_mentions' ); anspress()->add_action( 'ap_ajax_search_mentions', __CLASS__, 'search_mentions' ); } /** * Linkyfy mentions before contents get inserted to database. * @param string $content Post content. * @return string */ public static function linkyfy_mentions($post_arr) { $post_arr['post_content'] = ap_linkyfy_mentions( $post_arr['post_content'] ); return $post_arr; } /** * Search metion user name and login. * @since 3.0.0 */ public static function search_mentions( ) { if ( ! ap_verify_default_nonce() ) { wp_die(); } $term = ap_sanitize_unslash( 'term', 'request' ); wp_send_json( ap_search_mentions( false, $term ) ); } /** * For some reason advance TinyMCE editor won't shows up. * To fix that issue, adding after init callback to forcely show editor. * @param array $initArray Editor callbacks. * @return array * @since 3.0.0 */ public static function tiny_mce_before_init($initArray) { $initArray['setup'] = 'function(ed) { ed.on("init", function() { tinyMCE.activeEditor.show(); if( typeof atwho !== "undefined"){ ed.on("keydown", function(e) { if(e.keyCode == 13 && jQuery(ed.contentDocument.activeElement).atwho("isSelecting")) return false }); } }); }'; $initArray['init_instance_callback'] = 'function(ed) { if( typeof atwho !== "undefined"){ jQuery(ed.contentDocument.activeElement).atwho(at_config); } }'; $initArray['autoresize_min_height'] = 300; $initArray['autoresize_max_height'] = 10000; return $initArray; } } /** * Surround mentions with anchor tag. * @param string $content Post content. * @return string */ function ap_linkyfy_mentions($content) { if ( ! ap_opt( 'base_before_user_perma' ) ) { $base = home_url( '/'.ap_get_user_page_slug().'/' ); } else { $base = ap_get_link_to( ap_get_user_page_slug() ); } // Find mentions and wrap with anchor. $content = preg_replace( '/(?!]*?>)@(\w+)(?![^<]*?<\/a>)/', '@$1 ', $content ); return $content; } /** * Find mentioned users in a post. * @param string $content Post or comment contents. * @return array|false */ function ap_find_mentioned_users( $content ) { global $wpdb; // Find all mentions in content. preg_match_all( '/(?:[\s.]|^)@(\w+)/', $content, $matches ); if ( is_array( $matches ) && count( $matches ) > 0 && ! empty( $matches[0] ) ) { $user_logins = array(); // Remove duplicates. $unique_logins = array_unique( $matches[0] ); foreach ( $unique_logins as $user_login ) { $user_logins[] = sanitize_title_for_query( sanitize_user( wp_unslash( $user_login ), true ) ); } if ( count( $user_logins ) == 0 ) { return false; } $user_logins_s = "'". implode( "','", $user_logins ) ."'"; $key = md5( $user_logins_s ); $cache = wp_cache_get( $key, 'ap_user_ids' ); if ( false !== $cache ) { return $cache; } $query = $wpdb->prepare( "SELECT id, user_login FROM $wpdb->users WHERE user_login IN ($user_logins_s)" ); $result = $wpdb->get_results( $query ); wp_cache_set( $key, $result, 'ap_user_ids' ); return $result; } return false; } /** * Return current question users with login and display name. * If search is passed then it will search for user. * @param boolean|integer $question_id Question iD. * @param boolean|string $search Search string. * @return array * @since 3.0.0 */ function ap_search_mentions( $question_id = false, $search = false ) { global $wpdb; if ( false === $question_id ) { $question_id = get_question_id(); } if ( false !== $search ) { $search = sanitize_text_field( $search ); $query = $wpdb->prepare( "SELECT DISTINCT u.display_name as name, u.user_login as login FROM $wpdb->users u WHERE display_name LIKE '%%%s%%' OR user_login LIKE '%%%s%%' LIMIT 20", $search, $search ); } else { $query = $wpdb->prepare( "SELECT DISTINCT u.display_name as name, u.user_login as login FROM $wpdb->users u LEFT JOIN $wpdb->ap_activity a ON u.ID = a.user_id WHERE question_id = %d LIMIT 20", $question_id ); } $key = md5( $query ); $cache = wp_cache_get( $key, 'ap_participants' ); if ( false !== $cache ) { return $cache; } $rows = $wpdb->get_results( $query ); wp_cache_set( $key, $rows, 'ap_participants' ); return $rows; }