<?php
/**
 * title: shared_count
 * description: Retrieve social media links/shares/likes/upvotes/views
 * x-feature: google+, facebook, linkedin, reddit, twitter, stumbleupon, delicious
 * version: 0.1.1
 *
 * Query multiple online portals for common user upvotes. Returns a list for making
 * a summary total.
 *
 */


#-- load curl/curl_multi() wrapper
if (!function_exists("curl")) {
    include("./curl.php");  //fossil.include-once.org/hybrid7/doc/trunk/php7/curl.php
}



/**
 * Retrieve number of links from social media portals to given $url.
 *
 * Runs HTTP requests in parallel, and imposes a maximum timeout.
 *
 *
 */
function social_links_count($url) {
    $url = rawurlencode($url);

    // define APIs
    $services = array(
        "twitter" => "http://urls.api.twitter.com/1/urls/count.json?url=$url",
        "linkedin" => "http://www.linkedin.com/countserv/count/share?url=$url&format=json",
        "facebook" => "http://api.facebook.com/restserver.php?method=links.getStats&format=json&urls=$url",
        "google" => curl("https://clients6.google.com/rpc")
            ->HttpHeader(array("Content-type: application/json"))
            ->PostFields(json_encode(array(array(   // guess who's unwieldy
                "method"=>"pos.plusones.get",  "id"=>"p",  "jsonrpc"=>"2.0",  "key"=>"p",  "apiVersion"=>"v1",
                "params"=>array("nolog"=>TRUE,  "id"=>rawurldecode($url),  "source"=>"widget",  "userId"=>"@viewer",  "groupId"=>"@self"),
            )))),
        "reddit" => "http://www.reddit.com/api/info.json?url=$url",
        "sumbleupon" => "http://www.stumbleupon.com/services/1.01/badge.getinfo?url=$url",
        "delicious" => "http://feeds.delicious.com/v2/json/urlinfo/data?url=$url",
        "pinterest" => curl("http://api.pinterest.com/v1/urls/count.json?url=$url"),
    );

    // run and extract scores    
    return(
        array_map(
           "json_rx_count",
           curl_multi($services)->exec(0.75)
        )
    );
}



/**
 * Since we have unambiguous and concise JSON blobs, it's sufficient and less
 * overhead to just extract the numbers we're looking for.
 *
 * This also avoids looping over the reddit result lists manually, and integer
 * casting afterwards.
 *
 */
function json_rx_count($string, $rx="count|score|views|total_count|total_posts") {

    if (preg_match_all("/(?<!\\\\)\"(?:$rx)\"\s*:\s*\"?(\d+)/", $string, $uu)) {

        return array_sum($uu[1]);
    }
}




/**
 * Simple caching wrapper
 *
 */
function cache_fn($fn, $args, $ttl=7200) {

    // check cache
    $p = serialize($args);
    $cache = json_decode(file_get_contents("./$fn.cache.json"), TRUE);
    if (isset($cache[$p]) and (time() < $cache[$p]["time"] + $ttl)) {
        return $cache[$p]["data"];
    }

    // get data
    $data = call_user_func_array($fn, (array)$args);
    
    // update cache
    $cache[$p] = array("time"=>time(), "data"=>$data);
    file_put_contents("./$fn.cache.json", json_encode($cache, JSON_PRETTY_PRINT), LOCK_EX);

    return $data;
}


?>