<?php

/*
 * Plugin Name: Ajax Pageview
 * Plugin Description: Contabiliza os pageviews por ajax
 * Author: hacklab/
 */

class AjaxPageviews {
    /**
     *
     * @var wpdb
     */
    static $wpdb;

    static $post_types = [];

    static function init() {
        global $wpdb;

        self::$wpdb = $wpdb;
        
        add_action('wp_enqueue_scripts', [__CLASS__, 'scripts']);
        add_action('wp_ajax_nopriv_ajaxpv', [__CLASS__, 'action']);
        add_action('wp_loaded', [__CLASS__, 'set_post_types']);

        self::db_updates();
    }

    static function scripts() {
        if(!is_user_logged_in() && (is_single() || is_home() || is_front_page())){  
            wp_enqueue_script('ajax-pageview', plugin_dir_url(__FILE__) . '/ajax-pv.js', 'jquery', false, true);
            wp_localize_script('ajax-pageview', 'ajaxurl', admin_url('admin-ajax.php'));

            wp_localize_script('ajax-pageview', 'ajaxpv', base_convert(get_the_ID(), 10, 36));

            $post_type_hash = self::post_type_hash(is_front_page() ? 'frontpage' : get_post_type());

            wp_localize_script('ajax-pageview', 'ajaxpt', $post_type_hash);
        }
    }

    static function activation() {
        // https://codex.wordpress.org/Creating_Tables_with_Plugins
        global $wpdb;
        $table_name = $wpdb->prefix . "pageviews";

        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE $table_name (
          id bigint NOT NULL AUTO_INCREMENT,
          time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
          post_type varchar(20) NOT NULL,
          post_id bigint(20) unsigned NOT NULL,
          PRIMARY KEY (id)
        ) $charset_collate;";

        require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
        dbDelta($sql);
    }

    static function post_type_hash($post_type){
        return md5(__METHOD__ . $post_type);
    }

    static function set_post_types(){
        $post_types = get_post_types();
        $post_types['frontpage'] = 'frontpage';
        foreach($post_types as $post_type){
            $hash = self::post_type_hash($post_type);
            self::$post_types[$hash] = $post_type;
        }
    }

    static function action() {
        if (isset($_POST['ajaxpv']) && isset($_POST['ajaxpt'])) {
            $post_id = base_convert($_POST['ajaxpv'], 36, 10);
            $post_type = isset(self::$post_types[$_POST['ajaxpt']]) ? self::$post_types[$_POST['ajaxpt']] : null;

            if ($post_type && self::get_post_id_from_referer() == $post_id) {
                self::add_pageview($post_id, $post_type);
            }
        }
    }

    static function add_pageview($post_id, $post_type) {
        $table_name = self::$wpdb->prefix . "pageviews";

        self::$wpdb->insert($table_name, ['post_id' => $post_id, 'post_type' => $post_type]);
    }

    static function get_post_id_from_referer() {
        if (isset($_SERVER['HTTP_REFERER'])) {
            return url_to_postid($_SERVER['HTTP_REFERER']);
        }
    }

    static function get_top_viewed($num = 10, $args = []){
        $args += [
            'post_type' => 'post',
            'from' => date('Y-m-d', strtotime('-14 days')),
            'to' => null
        ];

        $table_name = self::$wpdb->prefix . "pageviews";

        $where = [];
        if($args['post_type']){
            if(!is_array($args['post_type'])){
                $args['post_type'] = [$args['post_type']];
            }
            
            $args['post_type'] = array_map(function($item) { return "'$item'"; }, $args['post_type']);
            $args['post_type'] = implode(",", $args['post_type']);
        
            $where[] = "post_type IN ({$args['post_type']})";
        }

        if($args['from']){
            $where[] = "time >= '{$args['from']}'";
        }

        if($args['to']){
            $where[] = "time <= '{$args['to']}'";
        }

        $where = implode(' AND ', $where);

        if($where){
            $where = 'WHERE ' . $where . ' AND post_id IN (SELECT ID FROM ' . self::$wpdb->posts . ')';
        }
        
        $limit = '';
        if($num != -1){
            $limit = "LIMIT {$num}";
        } 

        $ids = self::$wpdb->get_results("SELECT COUNT(id) AS num, post_id FROM {$table_name} {$where} GROUP BY post_id ORDER BY num DESC $limit");
        
        return $ids;
    }

    static function db_updates(){
        if(!defined( 'DOING_CRON' )){
            return false;
        }
        $wpdb = self::$wpdb;

        $table_name = $wpdb->prefix . "pageviews";

        $updates = [
            'id to bigint' => function() use($wpdb, $table_name) {
                $wpdb->query("ALTER TABLE $table_name MODIFY id BIGINT UNSIGNED AUTO_INCREMENT;");
            }
        ];

        foreach($updates as $key => $fn){
            $option_name = __METHOD__ . ':' . $key;
            if(!get_option($option_name)){
                $fn();
                add_option($option_name, true);
            }
        }
    }
}

add_action('init', function(){
    AjaxPageviews::init();
});

register_activation_hook(__FILE__, ['AjaxPageviews', 'activation']);