wpMandrill - Version 1.11

Version Description

  • ADDED: screenshot-4.jpg
  • FIXED: Emails delivered % in Mandrill stats
  • ADDED: Limiting the numbers of senders that the Mandrill stats reports.
  • FIXED: Limiting the numbers of days to 30 in Daily Sending Volume graph in Mandrill stats reports.
  • ADDED: Visual notification in the dashboard widget while loading.
  • ADDED: Support for sockets when CURL is not present.
Download this release

Release Info

Developer MC_Will
Plugin Icon wp plugin wpMandrill
Version 1.11
Comparing to
See all releases

Code changes from version 1.10 to 1.11

Files changed (5) hide show
  1. js/mandrill.js +1 -1
  2. lib/mandrill.class.php +120 -24
  3. readme.txt +16 -0
  4. stats.php +1 -1
  5. wpmandrill.php +46 -23
js/mandrill.js CHANGED
@@ -43,7 +43,7 @@ function showStats() {
43
var filter = jQuery("#filter option:selected").val();
44
var display = jQuery("#display option:selected").val();
45
jQuery('#loading_data').css('display','block');
46
-
47
jQuery.ajax({
48
type: 'POST',
49
url: ajaxurl,
43
var filter = jQuery("#filter option:selected").val();
44
var display = jQuery("#display option:selected").val();
45
jQuery('#loading_data').css('display','block');
46
+
47
jQuery.ajax({
48
type: 'POST',
49
url: ajaxurl,
lib/mandrill.class.php CHANGED
@@ -1,24 +1,24 @@
1
<?php
2
3
- class Mandrill_Exception extends Exception {
4
- }
5
6
class Mandrill {
7
const API_VERSION = '1.0';
8
const END_POINT = 'https://mandrillapp.com/api/';
9
10
var $api;
11
12
// PHP 4.0
13
- function Mandrill() {$this->__construct();}
14
15
// PHP 5.0
16
function __construct($api) {
17
if ( empty($api) ) throw new Mandrill_Exception('Invalid API key');
18
try {
19
20
- $response = $this->request('users/ping', array( 'key' => $api ) );
21
- if ( $response != 'PONG!' ) throw new Mandrill_Exception('Invalid API key');
22
23
$this->api = $api;
24
@@ -42,6 +42,8 @@ class Mandrill {
42
if( !isset($args['key']) )
43
$args['key'] = $this->api;
44
45
$api_version = self::API_VERSION;
46
$dot_output = ('json' == $output) ? '' : ".{$output}";
47
@@ -50,8 +52,20 @@ class Mandrill {
50
switch ($http) {
51
52
case 'GET':
53
54
$url .= '?' . http_build_query($args);
55
$response = $this->http_request($url, array(),'GET');
56
break;
57
@@ -388,37 +402,119 @@ class Mandrill {
388
}
389
390
function http_request($url, $fields = array(), $method = 'POST') {
391
- if( !ini_get('safe_mode') ){
392
- set_time_limit(2 * 60);
393
- }
394
395
if ( !in_array( $method, array('POST','GET') ) ) $method = 'POST';
396
if ( !isset( $fields['key']) ) $fields['key'] = $this->api;
397
398
$fields = is_array($fields) ? http_build_query($fields) : $fields;
399
if ( defined('WP_DEBUG') && WP_DEBUG !== false ) {
400
error_log( "\nMandrill::http_request: URL: $url - Fields: $fields\n" );
401
}
402
403
- $ch = curl_init();
404
- curl_setopt($ch, CURLOPT_URL, $url);
405
-
406
- curl_setopt($ch, CURLOPT_POST, $method == 'POST');
407
-
408
- curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
409
-
410
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
411
- curl_setopt($ch, CURLOPT_HEADER, false);
412
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
413
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2 * 60 * 1000);
414
415
- $response = curl_exec($ch);
416
- $info = curl_getinfo($ch);
417
- $error = curl_error($ch);
418
419
- curl_close($ch);
420
421
- return array('header' => $info, 'body' => $response, 'error' => $error);
422
}
423
424
static function getAttachmentStruct($path) {
1
<?php
2
3
+ class Mandrill_Exception extends Exception {}
4
5
class Mandrill {
6
const API_VERSION = '1.0';
7
const END_POINT = 'https://mandrillapp.com/api/';
8
9
var $api;
10
+ var $output;
11
12
// PHP 4.0
13
+ function Mandrill() { $this->__construct(); }
14
15
// PHP 5.0
16
function __construct($api) {
17
if ( empty($api) ) throw new Mandrill_Exception('Invalid API key');
18
try {
19
20
+ $response = $this->request('users/ping2', array( 'key' => $api ) );
21
+ if ( !isset($response['PING']) || $response['PING'] != 'PONG!' ) throw new Mandrill_Exception('Invalid API key');
22
23
$this->api = $api;
24
42
if( !isset($args['key']) )
43
$args['key'] = $this->api;
44
45
+ $this->output = $output;
46
+
47
$api_version = self::API_VERSION;
48
$dot_output = ('json' == $output) ? '' : ".{$output}";
49
52
switch ($http) {
53
54
case 'GET':
55
+ //some distribs change arg sep to &amp; by default
56
+ $sep_changed = false;
57
+ if (ini_get("arg_separator.output")!="&"){
58
+ $sep_changed = true;
59
+ $orig_sep = ini_get("arg_separator.output");
60
+ ini_set("arg_separator.output", "&");
61
+ }
62
63
$url .= '?' . http_build_query($args);
64
+
65
+ if ($sep_changed){
66
+ ini_set("arg_separator.output", $orig_sep);
67
+ }
68
+
69
$response = $this->http_request($url, array(),'GET');
70
break;
71
402
}
403
404
function http_request($url, $fields = array(), $method = 'POST') {
405
406
if ( !in_array( $method, array('POST','GET') ) ) $method = 'POST';
407
if ( !isset( $fields['key']) ) $fields['key'] = $this->api;
408
409
+ //some distribs change arg sep to &amp; by default
410
+ $sep_changed = false;
411
+ if (ini_get("arg_separator.output")!="&"){
412
+ $sep_changed = true;
413
+ $orig_sep = ini_get("arg_separator.output");
414
+ ini_set("arg_separator.output", "&");
415
+ }
416
+
417
$fields = is_array($fields) ? http_build_query($fields) : $fields;
418
+
419
+ if ($sep_changed) {
420
+ ini_set("arg_separator.output", $orig_sep);
421
+ }
422
+
423
if ( defined('WP_DEBUG') && WP_DEBUG !== false ) {
424
error_log( "\nMandrill::http_request: URL: $url - Fields: $fields\n" );
425
}
426
427
+ if( function_exists('curl_init') && function_exists('curl_exec') ) {
428
+
429
+ if( !ini_get('safe_mode') ){
430
+ set_time_limit(2 * 60);
431
+ }
432
433
+ $ch = curl_init();
434
+ curl_setopt($ch, CURLOPT_URL, $url);
435
+
436
+ curl_setopt($ch, CURLOPT_POST, $method == 'POST');
437
+
438
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
439
+
440
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
441
+ curl_setopt($ch, CURLOPT_HEADER, false);
442
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
443
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2 * 60 * 1000);
444
+
445
+ $response = curl_exec($ch);
446
+ $info = curl_getinfo($ch);
447
+ $error = curl_error($ch);
448
+
449
+ curl_close($ch);
450
451
+ } elseif( function_exists( 'fsockopen' ) ) {
452
+ $parsed_url = parse_url($url);
453
+
454
+ $host = $parsed_url['host'];
455
+ if ( isset($parsed_url['path']) ) {
456
+ $path = $parsed_url['path'];
457
+ } else {
458
+ $path = '/';
459
+ }
460
+
461
+ $params = '';
462
+ if (isset($parsed_url['query'])) {
463
+ $params = $parsed_url['query'] . '&' . $fields;
464
+ } elseif ( trim($fields) != '' ) {
465
+ $params = $fields;
466
+ }
467
+
468
+ if (isset($parsed_url['port'])) {
469
+ $port = $parsed_url['port'];
470
+ } else {
471
+ $port = ($parsed_url['scheme'] == 'https') ? 443 : 80;
472
+ }
473
+
474
+ $response = false;
475
+
476
+ $errno = '';
477
+ $errstr = '';
478
+ ob_start();
479
+ $fp = fsockopen( 'ssl://'.$host, $port, $errno, $errstr, 5 );
480
+
481
+ if( $fp !== false ) {
482
+ stream_set_timeout($fp, 30);
483
+
484
+ $payload = "$method $path HTTP/1.0\r\n" .
485
+ "Host: $host\r\n" .
486
+ "Connection: close\r\n" .
487
+ "Content-type: application/x-www-form-urlencoded\r\n" .
488
+ "Content-length: " . strlen($params) . "\r\n" .
489
+ "Connection: close\r\n\r\n" .
490
+ $params;
491
+ fwrite($fp, $payload);
492
+ stream_set_timeout($fp, 30);
493
+
494
+ $info = stream_get_meta_data($fp);
495
+ while ((!feof($fp)) && (!$info["timed_out"])) {
496
+ $response .= fread($fp, 4096);
497
+ $info = stream_get_meta_data($fp);
498
+ }
499
+
500
+ fclose( $fp );
501
+ ob_end_clean();
502
+
503
+ list($headers, $response) = explode("\r\n\r\n", $response, 2);
504
+
505
+ if(ini_get("magic_quotes_runtime")) $response = stripslashes($response);
506
+ $info = array('http_code' => 200);
507
+ } else {
508
+ ob_end_clean();
509
+ $info = array('http_code' => 500);
510
+ throw new Exception($errstr,$errno);
511
+ }
512
+ $error = '';
513
+ } else {
514
+ throw new Mandrill_Exception("No valid HTTP transport found", -99);
515
+ }
516
517
+ return array('header' => $info, 'body' => $response, 'error' => $error);
518
}
519
520
static function getAttachmentStruct($path) {
readme.txt CHANGED
@@ -67,14 +67,30 @@ wpMandrill is currently localized in the following languages:
67
68
* Spanish (es_ES)
69
70
== Screenshots ==
71
72
1. Settings screen
73
2. Statistics
74
3. Dashboard widget
75
76
== Changelog ==
77
78
= 1.10 =
79
* ADDED: Blank .po file for other translations :)
80
* ADDED: Some debugging messages just in case need arises.
67
68
* Spanish (es_ES)
69
70
+ == Known Issues ==
71
+
72
+ * Daily statistics will show data for the first 20 senders (emails) registered.
73
+ * Daily statistics will show data for the first 40 tags registered.
74
+
75
+ If your account has more than 20 senders registered or more than 40 tags used, the detailed daily statisticas might show incompleted data.
76
+
77
== Screenshots ==
78
79
1. Settings screen
80
2. Statistics
81
3. Dashboard widget
82
+ 4. Dashboard widget Settings
83
84
== Changelog ==
85
86
+ = 1.11 =
87
+ * ADDED: screenshot-4.jpg
88
+ * FIXED: Emails delivered % in Mandrill stats
89
+ * ADDED: Limiting the numbers of senders that the Mandrill stats reports.
90
+ * FIXED: Limiting the numbers of days to 30 in Daily Sending Volume graph in Mandrill stats reports.
91
+ * ADDED: Visual notification in the dashboard widget while loading.
92
+ * ADDED: Support for sockets when CURL is not present.
93
+
94
= 1.10 =
95
* ADDED: Blank .po file for other translations :)
96
* ADDED: Some debugging messages just in case need arises.
stats.php CHANGED
@@ -40,7 +40,7 @@ $lit['clickrate'] = __('Click Rate',self::WPDOMAIN);
40
<div class="stat_box"><?php _e('Reputation:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['reputation']?>%</span></div>
41
<div class="stat_box"><?php _e('Quota:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['hourly_quota']?> <?php _e('sends/hour', wpMandrill::WPDOMAIN); ?></span></div>
42
<div class="stat_box"><?php _e('Emails sent:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['sent']?></span></div>
43
- <div class="stat_box"><?php _e('Emails delivered:', wpMandrill::WPDOMAIN); ?><br/><span><?=$delivered?> (<?=$delivered*100/($stats['general']['stats']['sent']?$stats['general']['stats']['sent']:1)?>%)</span></div>
44
<div class="stat_box"><?php _e('Tracked opens:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['opens']?></span></div>
45
<div class="stat_box"><?php _e('Tracked clicks:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['clicks']?></span></div>
46
<?php
40
<div class="stat_box"><?php _e('Reputation:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['reputation']?>%</span></div>
41
<div class="stat_box"><?php _e('Quota:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['hourly_quota']?> <?php _e('sends/hour', wpMandrill::WPDOMAIN); ?></span></div>
42
<div class="stat_box"><?php _e('Emails sent:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['sent']?></span></div>
43
+ <div class="stat_box"><?php _e('Emails delivered:', wpMandrill::WPDOMAIN); ?><br/><span><?=$delivered?> (<?=number_format( $delivered*100 / ( ($stats['general']['stats']['sent'])?$stats['general']['stats']['sent']:1 ) ,2); ?>%)</span></div>
44
<div class="stat_box"><?php _e('Tracked opens:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['opens']?></span></div>
45
<div class="stat_box"><?php _e('Tracked clicks:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['clicks']?></span></div>
46
<?php
wpmandrill.php CHANGED
@@ -5,7 +5,7 @@ Description: wpMandrill sends emails, generated by WordPress using Mandrill.
5
Author: Mandrill
6
Author URI: http://mandrillapp.com/
7
Plugin URI: http://connect.mailchimp.com/integrations/wpmandrill
8
- Version: 1.10
9
Text Domain: wpmandrill
10
*/
11
/* Copyright 2012 MailChimp (email : will@mailchimp.com )
@@ -674,9 +674,9 @@ jQuery(document).bind( 'ready', function() {
674
} else {
675
$result = array();
676
677
- $result['sent'] = 0;
678
- $result['queue'] = 0;
679
- $result['rejected'] = 0;
680
681
foreach ( $test as $email ) {
682
if ( !isset($result[$email['status']]) ) $result[$email['status']] = 0;
@@ -875,6 +875,7 @@ jQuery(document).bind( 'ready', function() {
875
$container = self::$mandrill->tags_list();
876
foreach ( $container as $tag ) {
877
$data[$tag['tag']] = self::$mandrill->tags_info($tag['tag']);
878
}
879
$stats['tags'] = $data;
880
@@ -882,6 +883,7 @@ jQuery(document).bind( 'ready', function() {
882
$container = self::$mandrill->senders_list();
883
foreach ( $container as $sender ) {
884
$data[$sender['address']] = self::$mandrill->senders_info($sender['address']);
885
}
886
$stats['senders'] = $data;
887
@@ -959,17 +961,15 @@ jQuery(document).bind( 'ready', function() {
959
if ( !isset($graph_data['hourly']['opens'][$hour]) ) $graph_data['hourly']['opens'][$hour] = 0;
960
if ( !isset($graph_data['hourly']['clicks'][$hour]) ) $graph_data['hourly']['clicks'][$hour] = 0;
961
962
- if ( !isset($graph_data['daily']['delivered'][$day]) ) $graph_data['daily']['delivered'][$day] = 0;
963
- if ( !isset($graph_data['daily']['opens'][$day]) ) $graph_data['daily']['opens'][$day] = 0;
964
- if ( !isset($graph_data['daily']['clicks'][$day]) ) $graph_data['daily']['clicks'][$day] = 0;
965
-
966
$graph_data['hourly']['delivered'][$hour] += $data['sent'] - $data['hard_bounces'] - $data['soft_bounces'] - $data['rejects'];
967
$graph_data['hourly']['opens'][$hour] += $data['unique_opens'];
968
$graph_data['hourly']['clicks'][$hour] += $data['unique_clicks'];
969
970
- $graph_data['daily']['delivered'][$day] += $data['sent'] - $data['hard_bounces'] - $data['soft_bounces'] - $data['rejects'];
971
- $graph_data['daily']['opens'][$day] += $data['unique_opens'];
972
- $graph_data['daily']['clicks'][$day] += $data['unique_clicks'];
973
}
974
}
975
}
@@ -1165,7 +1165,7 @@ jQuery(document).bind( 'ready', function() {
1165
1166
$js .= '
1167
<div style="height:400px;">
1168
- <div id="filtered_recent"></div>
1169
</div>
1170
<script type="text/javascript">
1171
jQuery(document).bind( \'ready\', function() {
@@ -1253,14 +1253,14 @@ jQuery(document).bind( \'ready\', function() {
1253
}
1254
},
1255
series: [{
1256
- name: '{$lit['unopened']}',
1257
- data: [{$unopens['recent']}]
1258
- }, {
1259
name: '{$lit['bounced']}',
1260
data: [{$bounces['recent']}]
1261
}, {
1262
name: '{$lit['opened']}',
1263
data: [{$opens['recent']}]
1264
}]
1265
});
1266
});
@@ -1500,15 +1500,27 @@ jQuery(function () {
1500
}
1501
},
1502
series: [{
1503
- name: '{$lit['unopened']}',
1504
- data: [{$unopens['recent']}]
1505
- }, {
1506
name: '{$lit['bounced']}',
1507
data: [{$bounces['recent']}]
1508
}, {
1509
name: '{$lit['opened']}',
1510
data: [{$opens['recent']}]
1511
- }]
1512
});
1513
chart = new Highcharts.Chart({
1514
chart: {
@@ -1589,15 +1601,26 @@ jQuery(function () {
1589
}
1590
},
1591
series: [{
1592
- name: '{$lit['unopened']}',
1593
- data: [{$unopens['oldest']}]
1594
- }, {
1595
name: '{$lit['bounced']}',
1596
data: [{$bounces['oldest']}]
1597
}, {
1598
name: '{$lit['opened']}',
1599
data: [{$opens['oldest']}]
1600
- }]
1601
});
1602
});
1603
JS;
5
Author: Mandrill
6
Author URI: http://mandrillapp.com/
7
Plugin URI: http://connect.mailchimp.com/integrations/wpmandrill
8
+ Version: 1.11
9
Text Domain: wpmandrill
10
*/
11
/* Copyright 2012 MailChimp (email : will@mailchimp.com )
674
} else {
675
$result = array();
676
677
+ $result['sent'] = 0;
678
+ $result['queue'] = 0;
679
+ $result['rejected'] = 0;
680
681
foreach ( $test as $email ) {
682
if ( !isset($result[$email['status']]) ) $result[$email['status']] = 0;
875
$container = self::$mandrill->tags_list();
876
foreach ( $container as $tag ) {
877
$data[$tag['tag']] = self::$mandrill->tags_info($tag['tag']);
878
+ if ( count($data) >= 40 ) break;
879
}
880
$stats['tags'] = $data;
881
883
$container = self::$mandrill->senders_list();
884
foreach ( $container as $sender ) {
885
$data[$sender['address']] = self::$mandrill->senders_info($sender['address']);
886
+ if ( count($data) >= 20 ) break;
887
}
888
$stats['senders'] = $data;
889
961
if ( !isset($graph_data['hourly']['opens'][$hour]) ) $graph_data['hourly']['opens'][$hour] = 0;
962
if ( !isset($graph_data['hourly']['clicks'][$hour]) ) $graph_data['hourly']['clicks'][$hour] = 0;
963
964
$graph_data['hourly']['delivered'][$hour] += $data['sent'] - $data['hard_bounces'] - $data['soft_bounces'] - $data['rejects'];
965
$graph_data['hourly']['opens'][$hour] += $data['unique_opens'];
966
$graph_data['hourly']['clicks'][$hour] += $data['unique_clicks'];
967
968
+ if ( isset($graph_data['daily']['delivered'][$day]) ) {
969
+ $graph_data['daily']['delivered'][$day] += $data['sent'] - $data['hard_bounces'] - $data['soft_bounces'] - $data['rejects'];
970
+ $graph_data['daily']['opens'][$day] += $data['unique_opens'];
971
+ $graph_data['daily']['clicks'][$day] += $data['unique_clicks'];
972
+ }
973
}
974
}
975
}
1165
1166
$js .= '
1167
<div style="height:400px;">
1168
+ <div id="filtered_recent">Loading...</div>
1169
</div>
1170
<script type="text/javascript">
1171
jQuery(document).bind( \'ready\', function() {
1253
}
1254
},
1255
series: [{
1256
name: '{$lit['bounced']}',
1257
data: [{$bounces['recent']}]
1258
}, {
1259
name: '{$lit['opened']}',
1260
data: [{$opens['recent']}]
1261
+ }, {
1262
+ name: '{$lit['unopened']}',
1263
+ data: [{$unopens['recent']}]
1264
}]
1265
});
1266
});
1500
}
1501
},
1502
series: [{
1503
name: '{$lit['bounced']}',
1504
data: [{$bounces['recent']}]
1505
}, {
1506
name: '{$lit['opened']}',
1507
data: [{$opens['recent']}]
1508
+ }, {
1509
+ name: '{$lit['unopened']}',
1510
+ data: [{$unopens['recent']}]
1511
+ }],
1512
+ colors: [
1513
+ '#AA4643',
1514
+ '#89A54E',
1515
+ '#4572A7',
1516
+ '#80699B',
1517
+ '#3D96AE',
1518
+ '#DB843D',
1519
+ '#92A8CD',
1520
+ '#A47D7C',
1521
+ '#B5CA92'
1522
+ ]
1523
+
1524
});
1525
chart = new Highcharts.Chart({
1526
chart: {
1601
}
1602
},
1603
series: [{
1604
name: '{$lit['bounced']}',
1605
data: [{$bounces['oldest']}]
1606
}, {
1607
name: '{$lit['opened']}',
1608
data: [{$opens['oldest']}]
1609
+ }, {
1610
+ name: '{$lit['unopened']}',
1611
+ data: [{$unopens['oldest']}]
1612
+ }],
1613
+ colors: [
1614
+ '#AA4643',
1615
+ '#89A54E',
1616
+ '#4572A7',
1617
+ '#80699B',
1618
+ '#3D96AE',
1619
+ '#DB843D',
1620
+ '#92A8CD',
1621
+ '#A47D7C',
1622
+ '#B5CA92'
1623
+ ]
1624
});
1625
});
1626
JS;