/home/arranoyd/magicraft/wp-content/plugins/clicky/frontend/class-clicky-visitor-graph.php
<?php
/**
* @package Yoast\Clicky\FrontEnd
*/
/**
* Backend Class the Clicky plugin
*/
class Clicky_Visitor_Graph {
/**
* Will hold the color of bars in our image
*
* @var int
*/
private $bar_color;
/**
* Will hold the visitor values for each hour
*
* @var array
*/
private $bar_values = array();
/**
* Height of the generated image
*
* @var float
*/
private $bar_width = 0.02;
/**
* The width of the gap between two bars
*
* @var int
*/
private $gap;
/**
* Holds the generated image
*
* @var resource
*/
private $img;
/**
* Height of the generated image
*
* @var int
*/
private $img_height = 20;
/**
* Width of the generated image
*
* @var int
*/
private $img_width = 99;
/**
* This holds the plugins options
*
* @var array
*/
private $options = array();
/**
* The ratio between a value and the overall image height
*
* @var int
*/
private $ratio;
/**
* Class constructor
*/
public function __construct() {
if ( ! function_exists( 'imagecreate' ) ) {
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$this->options = Clicky_Options::instance()->get();
if ( empty( $this->options['site_id'] ) || empty( $this->options['site_key'] ) ) {
return;
}
if ( isset( $this->options['disable_stats'] ) && $this->options['disable_stats'] ) {
return;
}
add_action( 'wp_head', array( $this, 'stats_css' ) );
add_action( 'admin_bar_menu', array( $this, 'stats_admin_bar_menu' ), 100 );
}
/**
* Creates (CSS for) head for the admin menu bar
*
* @link https://codex.wordpress.org/Function_Reference/add_action
*/
public function stats_css() {
$ext = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.css' : '.min.css';
echo "\n";
echo "<style type='text/css'>\n";
readfile( CLICKY_PLUGIN_DIR_PATH . '/css/adminbar' . $ext );
echo "\n";
echo "</style>\n";
}
/**
* Adds Clicky (graph) to the admin bar of the website
*
* @param object $wp_admin_bar Class that contains all information for the admin bar. Passed by reference.
*
* @link https://codex.wordpress.org/Class_Reference/WP_Admin_Bar
*/
public function stats_admin_bar_menu( $wp_admin_bar ) {
$img_src = $this->create_graph();
if ( false === $img_src ) {
return;
}
$url = 'https://secure.getclicky.com/stats/?site_id=' . $this->options['site_id'];
$title = __( 'Visitors over 48 hours. Click for more Clicky Site Stats.', 'clicky' );
$menu = array(
'id' => 'clickystats',
'title' => "<img width='99' height='20' src='" . $img_src . "' alt='" . esc_attr( $title ) . "' title='" . esc_attr( $title ) . "' />",
'href' => $url,
);
$wp_admin_bar->add_menu( $menu );
}
/**
* Creates the graph to be used in the admin bar
*
* @return bool|string Returns base64-encoded image on success (String) or fail (boolean) on failure
*/
private function create_graph() {
$result = $this->retrieve_clicky_api_details();
if ( false === $result ) {
return false;
}
if ( count( $this->bar_values ) < 1 ) {
return false;
}
$this->create_base_image();
$this->calculate_ratio();
$this->add_bars_to_image();
return $this->build_img();
}
/**
* Retrieve the visitor data from the Clicky API
*
* @link https://codex.wordpress.org/Function_Reference/wp_remote_get
*/
private function retrieve_clicky_api_details() {
$args = array(
'site_id' => $this->options['site_id'],
'sitekey' => $this->options['site_key'],
'type' => 'visitors',
'hourly' => 1,
'date' => 'last-3-days',
'output' => 'json',
);
$url = 'https://api.getclicky.com/api/stats/4?' . http_build_query( $args );
$resp = wp_remote_get( $url );
if ( is_wp_error( $resp ) || ! isset( $resp['response']['code'] ) || $resp['response']['code'] != 200 ) {
return false;
}
$results = $this->parse_clicky_results( $resp['body'] );
if ( ! is_array( $results ) ) {
return false;
}
$this->bar_values = $results;
return true;
}
/**
* Parse the Clicky results into a usable array
*
* @param array $json JSON encoded object of results.
*
* @return array|bool
*/
private function parse_clicky_results( $json ) {
$json = json_decode( $json );
if ( empty( $json ) ) {
return false;
}
if ( isset( $json[0]->error ) ) {
return false;
}
$hours = 0;
$values = array();
foreach ( $json[0]->dates as $date ) {
foreach ( $date->items as $item ) {
if ( $hours === 48 ) {
break 2;
}
$values[] = $item->value;
$hours ++;
}
}
$values = array_reverse( $values );
return $values;
}
/**
* Creates the basic rectangle we'll project the bars on
*/
private function create_base_image() {
$this->img = imagecreate( $this->img_width, $this->img_height );
$black = imagecolorallocate( $this->img, 0, 0, 0 );
$background_color = imagecolortransparent( $this->img, $black );
imagefilledrectangle( $this->img, 0, 0, $this->img_width, $this->img_height, $background_color );
}
/**
* Calculate the ratio between the max value of the bar values and the image height to adjust bars length
*/
private function calculate_ratio() {
$max_value = max( $this->bar_values );
if ( $max_value === 0 ) {
$max_value = 1;
}
$this->ratio = ( $this->img_height / $max_value );
}
/**
* Create the individual bars on the image
*/
private function add_bars_to_image() {
$this->bar_color = imagecolorallocate( $this->img, 240, 240, 240 );
$total_bars = count( $this->bar_values ); // Normally 48, but less if there's less data.
$this->gap = ( ( $this->img_width - $total_bars * $this->bar_width ) / ( $total_bars + 1 ) );
foreach ( $this->bar_values as $key => $value ) {
$this->create_bar( $key, $value );
}
}
/**
* Create an individual bar on the image
*
* @param int $index Offset.
* @param int $height Height.
*/
private function create_bar( $index, $height ) {
$xAxis1 = ( $this->gap + $index * ( $this->gap + $this->bar_width ) );
$xAxis2 = ( $xAxis1 + $this->bar_width );
$yAxis1 = ( $this->img_height - intval( $height * $this->ratio ) );
$yAxis2 = $this->img_height;
imagefilledrectangle( $this->img, $xAxis1, $yAxis1, $xAxis2, $yAxis2, $this->bar_color );
}
/**
* Use the image input to build a PNG then returns it as a base64 encoded image usable in a src tag
*
* @return string
*/
private function build_img() {
ob_start();
imagepng( $this->img );
$image = ob_get_contents();
ob_end_clean();
$image = 'data:image/png;base64,' . base64_encode( $image );
return $image;
}
}