423 lines
14 KiB
PHP
423 lines
14 KiB
PHP
<?php
|
|
include '../backend.php';
|
|
require_once('../vendor/autoload.php');
|
|
require_once(__DIR__ . '/lock.php');
|
|
|
|
use \SendGrid\Mail\Mail;
|
|
|
|
/**
|
|
* Get Sendgrid Report
|
|
*/
|
|
class Custom_Report {
|
|
|
|
// curl setup private
|
|
private $curl;
|
|
|
|
protected $api_url;
|
|
protected $key;
|
|
protected $replica_conn;
|
|
protected $sendgrid_api;
|
|
protected $sendgrid_from;
|
|
protected $sendgrid_name;
|
|
|
|
public function __construct() {
|
|
global $savvyext;
|
|
$this->api_url = $savvyext->cfgReadChar('sendgrid.api_url');
|
|
$this->key = $savvyext->cfgReadChar('sendgrid.api_key');
|
|
|
|
// connect replica database
|
|
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
|
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
|
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
|
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
|
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
|
$db_conn = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
|
$this->replica_conn = pg_connect($db_conn);
|
|
|
|
// get range of days to retrieve data
|
|
$this->_2week = self::getDaysOfWeek( $week = -2 );
|
|
$this->_1week = self::getDaysOfWeek( $week = -1 );
|
|
|
|
// sendgrid api
|
|
$this->sendgrid_api = $savvyext->cfgReadChar('mailsend.api_key');
|
|
$this->sendgrid_from = $savvyext->cfgReadChar('mailsend.from');
|
|
$this->sendgrid_name = $savvyext->cfgReadChar('mailsend.name');
|
|
}
|
|
|
|
/**
|
|
* Write errors log
|
|
* @param string $action action name
|
|
* @param string $message error message
|
|
* @return
|
|
*/
|
|
private static function logs( $message ) {
|
|
$log = 'Date: ' .date("F j, Y, g:i a").PHP_EOL.
|
|
'Attempt: '.PHP_EOL.
|
|
sprintf('%s', is_array($message) ? json_encode($message): $message).PHP_EOL.
|
|
'-------------------------'.PHP_EOL;
|
|
file_put_contents( './logs/log_'.date('j.n.Y').'log', $log, FILE_APPEND );
|
|
}
|
|
|
|
/**
|
|
* Return range days from monday to sunday of week
|
|
* @param number $weekOffset number of week
|
|
* @return array
|
|
*/
|
|
private static function getDaysOfWeek( $weekOffset ) {
|
|
$date = new DateTime();
|
|
$date->setIsoDate( $date->format('o'), $date->format('W') + $weekOffset );
|
|
|
|
return array(
|
|
'monday' => $date->format('Y-m-d'),
|
|
'sunday' => $date->modify('+6 day')->format('Y-m-d')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Separation array by range of dates
|
|
* @param array $datas list data need to be separation
|
|
* @param string $start start date
|
|
* @param string $end end date
|
|
* @return array new arrays
|
|
*/
|
|
private static function separationByDates( $datas, $start, $end ) {
|
|
$new_array = array();
|
|
foreach ( $datas as $key => $data ) {
|
|
if ( $start <= $data['dates'] and $data['dates'] <= $end ) {
|
|
array_push( $new_array, $data );
|
|
unset( $datas[$key] );
|
|
}
|
|
}
|
|
|
|
return array( 'old_array' => $datas, 'new_array' => $new_array );
|
|
}
|
|
|
|
/**
|
|
* Check the time to run the cronjob
|
|
* @return bool
|
|
*/
|
|
private static function check_weekly_time() {
|
|
$timestamp = time();
|
|
if ( date( 'D', $timestamp ) === 'Mon' ) {
|
|
return true;
|
|
}
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* Prepare cURL to call SendGrid API
|
|
* @param string|null $endpoint api endpoint
|
|
* @param array $params api params
|
|
* @return mixed
|
|
*/
|
|
protected function getSendgrid(string $endpoint = null, $params = array()) {
|
|
// prepare url api
|
|
$api_call = sprintf( '%s%s?%s', $this->api_url, $endpoint, http_build_query($params) );
|
|
$ch = curl_init($api_call);
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
|
'Content-Type: application/json',
|
|
'Authorization: ' . $this->key
|
|
));
|
|
|
|
// check cURL error
|
|
$error = curl_error($ch);
|
|
if ($error) {
|
|
throw new Exception('Response with errors: ' . is_array($error) ? json_decode($error) : $error );
|
|
}
|
|
|
|
$response = json_decode( curl_exec($ch), true );
|
|
if (isset($response['errors'])) {
|
|
$message = is_array($response['errors']) ? json_decode($response['errors']) : response['errors'];
|
|
throw new Exception('Response with errors: ' . $message);
|
|
}
|
|
|
|
if (isset($results['results']) && !count($results['results'])) {
|
|
throw new Exception('Response with empty data');
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* execute pg query
|
|
* @param string $query sql query
|
|
* @return array results
|
|
*/
|
|
protected function execute_pg_query( $query ) {
|
|
try {
|
|
$do = pg_query( $this->replica_conn, $query );
|
|
if ( $errors = pg_last_error( $this->replica_conn ) ) {
|
|
throw new Exception( $errors );
|
|
}
|
|
$results = pg_fetch_all( $do );
|
|
if ( ! $results ) {
|
|
throw new Exception( 'Results not found!' );
|
|
}
|
|
// Separation results by dates
|
|
$results = self::separationByDates( $results, $this->_1week['monday'], $this->_1week['sunday'] );
|
|
return $results;
|
|
} catch (Exception $e) {
|
|
self::logs('Errors', $e->getMessage());
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate chart image
|
|
* @return string image src
|
|
*/
|
|
protected function generate_chart_images( $chartLabels, $chartValues ) {
|
|
$chartConfig = array(
|
|
'type' => 'line',
|
|
'backgroundColor' => 'transparent',
|
|
'data' => array(
|
|
'labels' => $chartLabels,
|
|
'datasets' => array(
|
|
array(
|
|
'label' => sprintf( 'from %s - to %s', $this->_2week['monday'], $this->_2week['sunday'] ),
|
|
'backgroundColor' => '#36A2EB',
|
|
'borderColor' => '#36A2EB',
|
|
'borderDash' => [5, 5],
|
|
'fill' => false,
|
|
'data' => array_values( $chartValues['old_value'] )
|
|
),
|
|
array(
|
|
'label' => sprintf( 'from %s - to %s', $this->_1week['monday'], $this->_1week['sunday'] ),
|
|
'backgroundColor' => '#F93784',
|
|
'borderColor' => '#F93784',
|
|
'fill' => false,
|
|
'data' => array_values( $chartValues['new_value'] )
|
|
)
|
|
)
|
|
),
|
|
'options' => array(
|
|
'responsive' => true,
|
|
'plugins' => array(
|
|
'datalabels' => array(
|
|
'display' => true,
|
|
'align' => 'top',
|
|
'backgroundColor' => '#FFFFFF',
|
|
'borderRadius' => 3,
|
|
'borderWidth' => 1,
|
|
'borderColor' => '#B8B8B8',
|
|
'font' => array(
|
|
'size' => 8
|
|
)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
$chartConfig = json_encode( $chartConfig );
|
|
$result = preg_replace( '/(")(function.*?})(")/m', '$2', $chartConfig);
|
|
$imageUrl = 'https://quickchart.io/chart?w=500&h=200&c=' . urlencode($result);
|
|
|
|
return $imageUrl;
|
|
}
|
|
|
|
/**
|
|
* Get tracking installed os
|
|
* @return array
|
|
*/
|
|
public function get_tracking_installed() {
|
|
// prepare sql to retrieve data
|
|
// by range days
|
|
$query = sprintf("
|
|
SELECT md.created as dates,
|
|
SUM(case when mdp.platform = 'Android' then 1 else 0 end) as Android,
|
|
SUM(case when mdp.platform = 'iOS' then 1 else 0 end) as iOS
|
|
FROM members_devices md
|
|
LEFT JOIN members_device_platforms mdp ON md.platform_id = mdp.id
|
|
WHERE md.created BETWEEN '%s' AND '%s'
|
|
AND md.member_id IN (SELECT id FROM members WHERE status = 1)
|
|
GROUP BY dates
|
|
", $this->_2week['monday'], $this->_1week['sunday']);
|
|
// run query
|
|
$results = $this->execute_pg_query( $query );
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Get number users who subscribed the deals
|
|
* @return int numbers
|
|
*/
|
|
public function get_subscribe_deals() {
|
|
$query = sprintf("
|
|
SELECT mca.subscribe as dates, count(DISTINCT m.email)
|
|
FROM members_card_assign mca
|
|
LEFT JOIN main_cards mc ON mca.card_id = mc.id
|
|
LEFT JOIN members m ON mca.member_id = m.id
|
|
WHERE mca.subscribe IS NOT NULL AND mc.button1_action IN ('GOOFFERS')
|
|
AND mca.subscribe BETWEEN '%s' AND '%s'
|
|
GROUP BY dates
|
|
", $this->_2week['monday'], $this->_1week['sunday']);
|
|
// run query
|
|
$results = $this->execute_pg_query( $query );
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Get number user who filled profile
|
|
* @return int numbers
|
|
*/
|
|
public function get_user_filled_profile() {
|
|
$query = sprintf("
|
|
SELECT greatest(m.added, mba.added, ot.created, md.created) as Dates, count(DISTINCT m.email)
|
|
FROM members m
|
|
INNER JOIN members_bank_accounts mba ON m.id = mba.member_id
|
|
INNER JOIN oauth2_tokens ot ON m.id = ot.member_id
|
|
INNER JOIN members_devices md on m.id = md.member_id
|
|
WHERE ((m.max_budget <> 0) IS NOT FALSE AND mba.status = 1 AND md.player_id is not null)
|
|
AND (greatest(m.added, mba.added, ot.created, md.created) BETWEEN '%s' AND '%s')
|
|
GROUP BY Dates
|
|
", $this->_2week['monday'], $this->_1week['sunday'] );
|
|
// run query
|
|
$results = $this->execute_pg_query( $query );
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Get sendgrid tracking data
|
|
* @return array properties of data
|
|
*/
|
|
public function get_sendgrid_tracking() {
|
|
try {
|
|
$params = array(
|
|
'aggregated_by' => 'week',
|
|
'start_date' => $this->_2week['monday'],
|
|
'end_date' => $this->_1week['sunday']
|
|
);
|
|
$results = $this->getSendgrid( $endpoint = 'stats', $params );
|
|
// check error api call
|
|
if ( isset( $results['errors'] ) ) {
|
|
$message = $results['errors'][0]['message'];
|
|
throw new Exception( $message );
|
|
}
|
|
$combineResults = array();
|
|
foreach ( $results as $key => $value ) {
|
|
$combineResults[] = array(
|
|
'dates' => $value['date'],
|
|
'data' => $value['stats'][0]['metrics']
|
|
);
|
|
}
|
|
$results = self::separationByDates( $combineResults, $this->_1week['monday'], $this->_1week['sunday'] );
|
|
return $results;
|
|
} catch (Exception $e) {
|
|
self::logs($action_name, $e->getMessage());
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* BKO tracking data
|
|
* @return string chart image
|
|
*/
|
|
public function bko_tracking() {
|
|
// tracking install device
|
|
$install = $this->get_tracking_installed();
|
|
// tracking user subscribe deals
|
|
$subscribe = $this->get_subscribe_deals();
|
|
// tracking user filled profile
|
|
$profile = $this->get_user_filled_profile();
|
|
|
|
$data = array(
|
|
'old_value' => array(
|
|
'android' => count( array_filter( $install['old_array'], function($e) {return $e['android'] > 0; } ) ),
|
|
'ios' => count( array_filter( $install['old_array'], function($e) {return $e['ios'] > 0; } ) ),
|
|
'subs' => count( $subscribe['old_array'] ),
|
|
'profile' => count( $profile['old_array'] )
|
|
),
|
|
'new_value' => array(
|
|
'android' => count( array_filter( $install['new_array'], function($e) {return $e['android'] > 0; } ) ),
|
|
'ios' => count( array_filter( $install['new_array'], function($e) {return $e['ios'] > 0; } ) ),
|
|
'subs' => count( $subscribe['new_array'] ),
|
|
'profile' => count( $profile['new_array'] )
|
|
)
|
|
);
|
|
$labels = array( 'Android install', 'iOS install', 'Subscribe deals', 'Filled profile' );
|
|
// get chart image
|
|
$imgSrc = $this->generate_chart_images( $labels, $data );
|
|
return $imgSrc;
|
|
}
|
|
|
|
/**
|
|
* SendGrid tracking data
|
|
* @return string chart image
|
|
*/
|
|
public function sendgrid_tracking() {
|
|
$tracking = $this->get_sendgrid_tracking();
|
|
if ( ! $tracking ) {
|
|
return;
|
|
}
|
|
|
|
$data = array();
|
|
foreach ( $tracking as $key => $item ) {
|
|
$data[ $key ] = array(
|
|
'delivered' => array_sum( array_column( $item[0], 'delivered') ),
|
|
'processed' => array_sum( array_column( $item[0], 'processed') ),
|
|
'unique_clicks' => array_sum( array_column( $item[0], 'unique_clicks') ),
|
|
'unique_opens' => array_sum( array_column( $item[0], 'unique_opens') ),
|
|
);
|
|
}
|
|
$data = array(
|
|
'old_value' => $data['old_array'],
|
|
'new_value' => $data['new_array']
|
|
);
|
|
$labels = array( 'Delivered', 'Processed', 'Unique Clicks', 'Unique Opens' );
|
|
// get chart image
|
|
$imgSrc = $this->generate_chart_images( $labels, $data );
|
|
return $imgSrc;
|
|
}
|
|
|
|
/**
|
|
* Send custom email report
|
|
* @return mixed
|
|
*/
|
|
public function sendEmail() {
|
|
// check weekly report time
|
|
self::check_weekly_time();
|
|
|
|
$bko_tracking = $this->bko_tracking();
|
|
$sendgrid_tracking = $this->sendgrid_tracking();
|
|
// include email template
|
|
ob_start();
|
|
require_once('./email/custom-report.php');
|
|
$mail_html = ob_get_clean();
|
|
|
|
try {
|
|
$email = new \SendGrid\Mail\Mail();
|
|
$email->setFrom( $this->sendgrid_from, $this->sendgrid_name );
|
|
$email->setSubject( 'Float Weekly Report' );
|
|
$toEmails = array(
|
|
'stew@float.sg' => 'Stew',
|
|
'olu@float.sg' => 'Olu',
|
|
'valeriy@float.sg' => 'Valeriy',
|
|
'tokslaw@float.sg' => 'Tokslaw',
|
|
'jeff@float.sg' => 'Jeff',
|
|
'chelsea@float.sg' => 'Chelsea'
|
|
);
|
|
$email->addTos( $toEmails );
|
|
$email->addContent( 'text/html', $mail_html );
|
|
$sendgrid = new \SendGrid( $this->sendgrid_api );
|
|
$response = $sendgrid->send( $email );
|
|
if ( $response->statusCode() !== 202 ) {
|
|
throw new Exception( 'Send custom report get errors' );
|
|
}
|
|
echo 'Success';
|
|
} catch (Exception $e) {
|
|
echo 'Custom report could not be sent. Mailer Error: ', $e->getMessage();
|
|
self::logs( 'Custom report could not be sent. Mailer Error: ', $e->getMessage() );
|
|
exit();
|
|
}
|
|
}
|
|
}
|
|
|
|
$api = new Custom_Report();
|
|
$api->sendEmail(); |