<?php
/*
Name:  WordPress Post Like System
Description:  A simple and efficient post like system for WordPress.
Version:      0.4
Author:       Jon Masterson
Author URI:   http://jonmasterson.com/

License:
Copyright (C) 2014 Jon Masterson

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * (1) Enqueue scripts for like system
 * Moved to main.js
 */

/**
 * (2) Save like data
 */
add_action( 'wp_ajax_nopriv_jm-post-like', 'jm_post_like' );
add_action( 'wp_ajax_jm-post-like', 'jm_post_like' );
function jm_post_like() {
	$nonce = $_POST['nonce'];
	if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) ) {
		die ( 'Nope!' );
	}

	if ( isset( $_POST['jm_post_like'] ) ) {

		$post_id         = sanitize_key( $_POST['post_id'] ); // post id
		$post_like_count = get_post_meta( $post_id, "_ic_like", true ); // post like count

		if ( function_exists( 'wp_cache_post_change' ) ) { // invalidate WP Super Cache if exists
			$GLOBALS["super_cache_enabled"] = 1;
			wp_cache_post_change( $post_id );
		}

		if ( is_user_logged_in() ) { // user is logged in
			$user_id     = get_current_user_id(); // current user
			$meta_POSTS  = get_user_option( "_liked_posts", $user_id ); // post ids from user meta
			$meta_USERS  = get_post_meta( $post_id, "_user_liked" ); // user ids from post meta
			$liked_POSTS = null; // setup array variable
			$liked_USERS = null; // setup array variable

			if ( count( $meta_POSTS ) != 0 ) { // meta exists, set up values
				$liked_POSTS = $meta_POSTS;
			}

			if ( ! is_array( $liked_POSTS ) ) // make array just in case
			{
				$liked_POSTS = array();
			}

			if ( count( $meta_USERS ) != 0 ) { // meta exists, set up values
				$liked_USERS = $meta_USERS[0];
			}

			if ( ! is_array( $liked_USERS ) ) // make array just in case
			{
				$liked_USERS = array();
			}

			$liked_POSTS[ 'post-' . $post_id ] = $post_id; // Add post id to user meta array
			$liked_USERS[ 'user-' . $user_id ] = $user_id; // add user id to post meta array
			$user_likes                        = count( $liked_POSTS ); // count user likes

			if ( ! AlreadyLiked( $post_id ) ) { // like the post
				update_post_meta( $post_id, "_user_liked", $liked_USERS ); // Add user ID to post meta
				update_post_meta( $post_id, "_ic_like", ++ $post_like_count ); // +1 count post meta
				update_user_option( $user_id, "_liked_posts", $liked_POSTS ); // Add post ID to user meta
				update_user_option( $user_id, "_user_like_count", $user_likes ); // +1 count user meta
				echo esc_html( $post_like_count ); // update count on front end

			} else { // unlike the post
				$pid_key = array_search( $post_id, $liked_POSTS ); // find the key
				$uid_key = array_search( $user_id, $liked_USERS ); // find the key
				unset( $liked_POSTS[ $pid_key ] ); // remove from array
				unset( $liked_USERS[ $uid_key ] ); // remove from array
				$user_likes = count( $liked_POSTS ); // recount user likes
				update_post_meta( $post_id, "_user_liked", $liked_USERS ); // Remove user ID from post meta
				update_post_meta( $post_id, "_ic_like", -- $post_like_count ); // -1 count post meta
				update_user_option( $user_id, "_liked_posts", $liked_POSTS ); // Remove post ID from user meta
				update_user_option( $user_id, "_user_like_count", $user_likes ); // -1 count user meta
				echo "already" . esc_html( $post_like_count ); // update count on front end

			}

		} else { // user is not logged in (anonymous)
			if ( function_exists( 'insight_core_get_remote_addr' ) ) {
				$ip = insight_core_get_remote_addr();
			} else {
				$ip = '0.0.0.0';
			}
			$meta_IPS  = get_post_meta( $post_id, "_user_IP" ); // stored IP addresses
			$liked_IPS = null; // set up array variable

			if ( count( $meta_IPS ) != 0 ) { // meta exists, set up values
				$liked_IPS = $meta_IPS[0];
			}

			if ( ! is_array( $liked_IPS ) ) // make array just in case
			{
				$liked_IPS = array();
			}

			if ( ! in_array( $ip, $liked_IPS ) ) // if IP not in array
			{
				$liked_IPS[ 'ip-' . $ip ] = $ip;
			} // add IP to array

			if ( ! AlreadyLiked( $post_id ) ) { // like the post
				update_post_meta( $post_id, "_user_IP", $liked_IPS ); // Add user IP to post meta
				update_post_meta( $post_id, "_ic_like", ++ $post_like_count ); // +1 count post meta
				echo esc_html( $post_like_count ); // update count on front end

			} else { // unlike the post
				$ip_key = array_search( $ip, $liked_IPS ); // find the key
				unset( $liked_IPS[ $ip_key ] ); // remove from array
				update_post_meta( $post_id, "_user_IP", $liked_IPS ); // Remove user IP from post meta
				update_post_meta( $post_id, "_ic_like", -- $post_like_count ); // -1 count post meta
				echo "already" . esc_html( $post_like_count ); // update count on front end

			}
		}

		echo esc_html( $post_like_count < 1 ) ? '' : ' ' . ( $post_like_count == 1 ? esc_html__( 'Like', 'tm-9studio' ) : esc_html__( 'Likes', 'tm-9studio' ) );
	}

	exit;
}

/**
 * (3) Test if user already liked post
 */
function AlreadyLiked( $post_id ) { // test if user liked before
	if ( is_user_logged_in() ) { // user is logged in
		$user_id     = get_current_user_id(); // current user
		$meta_USERS  = get_post_meta( $post_id, "_user_liked" ); // user ids from post meta
		$liked_USERS = ""; // set up array variable

		if ( count( $meta_USERS ) != 0 ) { // meta exists, set up values
			$liked_USERS = $meta_USERS[0];
		}

		if ( ! is_array( $liked_USERS ) ) // make array just in case
		{
			$liked_USERS = array();
		}

		if ( in_array( $user_id, $liked_USERS ) ) { // True if User ID in array
			return true;
		}

		return false;

	} else { // user is anonymous, use IP address for voting

		if ( function_exists( 'insight_core_get_remote_addr' ) ) {
			$ip = insight_core_get_remote_addr();
		} else {
			$ip = '0.0.0.0';
		}
		$meta_IPS  = get_post_meta( $post_id, "_user_IP" ); // get previously voted IP address
		$liked_IPS = ""; // set up array variable

		if ( count( $meta_IPS ) != 0 ) { // meta exists, set up values
			$liked_IPS = $meta_IPS[0];
		}

		if ( ! is_array( $liked_IPS ) ) // make array just in case
		{
			$liked_IPS = array();
		}

		if ( in_array( $ip, $liked_IPS ) ) { // True is IP in array
			return true;
		}

		return false;
	}

}

/**
 * (4) Front end button
 */
function getPostLikeLink( $post_id ) {
	$like_count = get_post_meta( $post_id, "_ic_like", true ); // get post likes
	$count      = ( empty( $like_count ) || ( $like_count <= 0 ) ) ? '0 Like' : sprintf( _n( '%s Like', '%s Likes', $like_count, 'tm-9studio' ), $like_count );
	if ( AlreadyLiked( $post_id ) ) {
		$class = esc_attr( ' liked' );
		$title = esc_attr__( 'Unlike', 'tm-9studio' );
	} else {
		$class = esc_attr( '' );
		$title = esc_attr__( 'Like', 'tm-9studio' );
	}

	$output = '<a href="#" class="like-btn jm-post-like' . esc_attr( $class ) . '" data-post_id="' . esc_attr( $post_id ) . '" title="' . esc_attr( $title ) . '">' . $count . '</a>';

	return $output;
}

/**
 * (5) Retrieve User Likes and Show on Profile
 */
add_action( 'show_user_profile', 'show_user_likes' );
add_action( 'edit_user_profile', 'show_user_likes' );
function show_user_likes( $user ) { ?>
    <table class="form-table">
        <tr>
            <th><label for="user_likes"><?php esc_html_e( 'You Like:', 'tm-9studio' ); ?></label></th>
            <td>
				<?php
				$user_likes = get_user_option( "_liked_posts", $user->ID );
				if ( ! empty( $user_likes ) && count( $user_likes ) > 0 ) {
					$the_likes = $user_likes;
				} else {
					$the_likes = '';
				}
				if ( ! is_array( $the_likes ) ) {
					$the_likes = array();
				}
				$count = count( $the_likes );
				$i     = 0;
				if ( $count > 0 ) {
					$like_list = '';
					echo "<p>\n";
					foreach ( $the_likes as $the_like ) {
						$i ++;
						$like_list .= "<a href=\"" . esc_url( get_permalink( $the_like ) ) . "\" title=\"" . esc_attr( get_the_title( $the_like ) ) . "\">" . get_the_title( $the_like ) . "</a>\n";
						if ( $count != $i ) {
							$like_list .= " &middot; ";
						} else {
							$like_list .= "</p>\n";
						}
					}
					echo wp_kses( $like_list, wp_kses_allowed_html( 'post' ) );
				} else {
					echo "<p>" . esc_html_e( 'You don\'t like anything yet.', 'tm-9studio' ) . "</p>\n";
				} ?>
            </td>
        </tr>
    </table>
<?php }

/**
 * (6) Add a shortcode to your posts instead
 * type [jmliker] in your post to output the button
 */
function jm_like_shortcode() {
	return getPostLikeLink( get_the_ID() );
}

/**
 * (7) If the user is logged in, output a list of posts that the user likes
 * Markup assumes sidebar/widget usage
 */
function frontEndUserLikes() {
	if ( is_user_logged_in() ) { // user is logged in
		$like_list  = '';
		$user_id    = get_current_user_id(); // current user
		$user_likes = get_user_option( "_liked_posts", $user_id );
		if ( ! empty( $user_likes ) && count( $user_likes ) > 0 ) {
			$the_likes = $user_likes;
		} else {
			$the_likes = '';
		}
		if ( ! is_array( $the_likes ) ) {
			$the_likes = array();
		}
		$count = count( $the_likes );
		if ( $count > 0 ) {
			$limited_likes = array_slice( $the_likes, 0, 5 ); // this will limit the number of posts returned to 5
			$like_list     .= "<aside>\n";
			$like_list     .= "<h3>" . esc_html__( 'You Like:', 'tm-9studio' ) . "</h3>\n";
			$like_list     .= "<ul>\n";
			foreach ( $limited_likes as $the_like ) {
				$like_list .= "<li><a href='" . esc_url( get_permalink( $the_like ) ) . "' title='" . esc_attr( get_the_title( $the_like ) ) . "'>" . get_the_title( $the_like ) . "</a></li>\n";
			}
			$like_list .= "</ul>\n";
			$like_list .= "</aside>\n";
		}
		echo wp_kses( $like_list, wp_kses_allowed_html( 'post' ) );
	}
}

/**
 * (8) Outputs a list of the 5 posts with the most user likes TODAY
 * Markup assumes sidebar/widget usage
 */
function jm_most_popular_today() {
	global $post;
	$today     = date( 'j' );
	$year      = date( 'Y' );
	$args      = array(
		'year'           => $year,
		'day'            => $today,
		'post_type'      => array( 'post', 'enter-your-comma-separated-post-types-here' ),
		'meta_query'     => array(
			array(
				'key'     => '_ic_like',
				'value'   => '0',
				'compare' => '>'
			)
		),
		'meta_key'       => '_ic_like',
		'orderby'        => 'meta_value_num',
		'order'          => 'DESC',
		'posts_per_page' => 5
	);
	$pop_posts = new WP_Query( $args );
	if ( $pop_posts->have_posts() ) {
		echo "<aside>\n";
		echo "<h3>" . esc_html_e( 'Today\'s Most Popular Posts', 'tm-9studio' ) . "</h3>\n";
		echo "<ul>\n";
		while ( $pop_posts->have_posts() ) {
			$pop_posts->the_post();
			echo "<li><a href='" . get_permalink( $post->ID ) . "'>" . get_the_title() . "</a></li>\n";
		}
		echo "</ul>\n";
		echo "</aside>\n";
	}
	wp_reset_postdata();
}

/**
 * (9) Outputs a list of the 5 posts with the most user likes for THIS MONTH
 * Markup assumes sidebar/widget usage
 */
function jm_most_popular_month() {
	global $post;
	$month     = date( 'm' );
	$year      = date( 'Y' );
	$args      = array(
		'year'           => $year,
		'monthnum'       => $month,
		'post_type'      => array( 'post', 'enter-your-comma-separated-post-types-here' ),
		'meta_query'     => array(
			array(
				'key'     => '_ic_like',
				'value'   => '0',
				'compare' => '>'
			)
		),
		'meta_key'       => '_ic_like',
		'orderby'        => 'meta_value_num',
		'order'          => 'DESC',
		'posts_per_page' => 5
	);
	$pop_posts = new WP_Query( $args );
	if ( $pop_posts->have_posts() ) {
		echo "<aside>\n";
		echo "<h3>" . esc_html_e( 'This Month\'s Most Popular Posts', 'tm-9studio' ) . "</h3>\n";
		echo "<ul>\n";
		while ( $pop_posts->have_posts() ) {
			$pop_posts->the_post();
			echo "<li><a href='" . get_permalink( $post->ID ) . "'>" . get_the_title() . "</a></li>\n";
		}
		echo "</ul>\n";
		echo "</aside>\n";
	}
	wp_reset_postdata();
}

/**
 * (10) Outputs a list of the 5 posts with the most user likes for THIS WEEK
 * Markup assumes sidebar/widget usage
 */
function jm_most_popular_week() {
	global $post;
	$week      = date( 'W' );
	$year      = date( 'Y' );
	$args      = array(
		'year'           => $year,
		'w'              => $week,
		'post_type'      => array( 'post', 'enter-your-comma-separated-post-types-here' ),
		'meta_query'     => array(
			array(
				'key'     => '_ic_like',
				'value'   => '0',
				'compare' => '>'
			)
		),
		'meta_key'       => '_ic_like',
		'orderby'        => 'meta_value_num',
		'order'          => 'DESC',
		'posts_per_page' => 5
	);
	$pop_posts = new WP_Query( $args );
	if ( $pop_posts->have_posts() ) {
		echo "<aside>\n";
		echo "<h3>" . esc_html_e( 'This Week\'s Most Popular Posts', 'tm-9studio' ) . "</h3>\n";
		echo "<ul>\n";
		while ( $pop_posts->have_posts() ) {
			$pop_posts->the_post();
			echo "<li><a href='" . get_permalink( $post->ID ) . "'>" . get_the_title() . "</a></li>\n";
		}
		echo "</ul>\n";
		echo "</aside>\n";
	}
	wp_reset_postdata();
}

/**
 * (11) Outputs a list of the 5 posts with the most user likes for ALL TIME
 * Markup assumes sidebar/widget usage
 */
function jm_most_popular() {
	global $post;
	echo "<aside>\n";
	echo "<h3>" . esc_html_e( 'Most Popular Posts', 'tm-9studio' ) . "</h3>\n";
	echo "<ul>\n";
	$args      = array(
		'post_type'      => array( 'post', 'enter-your-comma-separated-post-types-here' ),
		'meta_query'     => array(
			array(
				'key'     => '_ic_like',
				'value'   => '0',
				'compare' => '>'
			)
		),
		'meta_key'       => '_ic_like',
		'orderby'        => 'meta_value_num',
		'order'          => 'DESC',
		'posts_per_page' => 5
	);
	$pop_posts = new WP_Query( $args );
	while ( $pop_posts->have_posts() ) {
		$pop_posts->the_post();
		echo "<li><a href='" . get_permalink( $post->ID ) . "'>" . get_the_title() . "</a></li>\n";
	}
	wp_reset_postdata();
	echo "</ul>\n";
	echo "</aside>\n";
}
