Sidekick - Version 2.5.5

Version Description

  • Clean up of tracking routines
  • Additional security around preference saving (Thank You Joost - @yoast)
  • Fixes to global CSS rules (Thank You Joost - @yoast)
  • Network admin screen has clearler titling for options
Download this release

Release Info

Developer raptor235
Plugin Icon 128x128 Sidekick
Version 2.5.5
Comparing to
See all releases

Code changes from version 2.5.4 to 2.5.5

js/sidekick_admin.js CHANGED
@@ -204,7 +204,7 @@ function updateStatCounts(increment){
204
 
205
  function sk_populate(data){
206
 
207
- // console.log('sk_populate %o',data);
208
 
209
  jQuery('.sk_walkthrough_list').html('');
210
 
@@ -247,7 +247,7 @@ function sk_populate(data){
247
 
248
  // Clear out disabled wts so that compatibility doesn't screen out wts from this screen. Put it back after we're done.
249
 
250
- // console.groupCollapsed('Checking Compatibilities');
251
 
252
  _.each(data.payload.buckets,function(bucket,key){
253
 
@@ -304,7 +304,7 @@ function sk_populate(data){
304
 
305
  jQuery('.configure').show(); //
306
 
307
- // console.groupEnd();//
308
 
309
  } else { //
310
  jQuery('#' + this.cacheId).remove();
@@ -382,6 +382,8 @@ function load_sk_library($key){
382
  },
383
  success: function(data){
384
 
 
 
385
  if (sk_config.library + 'domains/cache?domainKey=' + sk_config.activation_id == sk_url) {
386
  if (!data.payload) {
387
  jQuery('.sk_license_status').html('Invalid Key').css({color: 'red'});
@@ -391,6 +393,7 @@ function load_sk_library($key){
391
  }
392
 
393
  if (!data.payload) {
 
394
  load_sk_library();
395
  return false;
396
  }
@@ -406,6 +409,7 @@ function load_sk_library($key){
406
  }
407
 
408
  function setup_sk_admin(){
 
409
  if (jQuery('.sidekick_admin').length === 0) {
410
  return;
411
  }
@@ -469,6 +473,7 @@ function setup_sk_admin(){
469
  }
470
  }
471
 
472
- window.onload = function(){
473
- setup_sk_admin();
474
- }
 
204
 
205
  function sk_populate(data){
206
 
207
+ console.log('sk_populate %o',data);
208
 
209
  jQuery('.sk_walkthrough_list').html('');
210
 
247
 
248
  // Clear out disabled wts so that compatibility doesn't screen out wts from this screen. Put it back after we're done.
249
 
250
+ console.groupCollapsed('Checking Compatibilities');
251
 
252
  _.each(data.payload.buckets,function(bucket,key){
253
 
304
 
305
  jQuery('.configure').show(); //
306
 
307
+ console.groupEnd();//
308
 
309
  } else { //
310
  jQuery('#' + this.cacheId).remove();
382
  },
383
  success: function(data){
384
 
385
+ console.log('%csuccess %o','color: green',data);
386
+
387
  if (sk_config.library + 'domains/cache?domainKey=' + sk_config.activation_id == sk_url) {
388
  if (!data.payload) {
389
  jQuery('.sk_license_status').html('Invalid Key').css({color: 'red'});
393
  }
394
 
395
  if (!data.payload) {
396
+ console.log('loading again');
397
  load_sk_library();
398
  return false;
399
  }
409
  }
410
 
411
  function setup_sk_admin(){
412
+ console.log('setup_sk_admin');
413
  if (jQuery('.sidekick_admin').length === 0) {
414
  return;
415
  }
473
  }
474
  }
475
 
476
+ // window.onload = function(){
477
+ // console.log('init setup_sk_admin');
478
+ // setup_sk_admin();
479
+ // }
libs/licensing.php CHANGED
@@ -62,8 +62,6 @@ if (!class_exists('sidekickMassActivator')) {
62
  update_option('sk_email', $email);
63
  restore_current_blog();
64
 
65
- $this->track('Mass Activate', array('domain' => $domain, 'email' => $email));
66
-
67
  if (isset($checked_blogs['deactivated'][$blog_id])) {
68
  $checked_blogs['active'][$blog_id] = $checked_blogs['deactivated'][$blog_id];
69
  unset($checked_blogs['deactivated'][$blog_id]);
@@ -78,7 +76,6 @@ if (!class_exists('sidekickMassActivator')) {
78
  delete_option('sk_auto_activation_error');
79
  } else {
80
 
81
- $this->track('Mass Activate Error', array('domain' => $domain, 'message' => $result->message, 'email' => $email));
82
  update_option('sk_auto_activation_error', $result->message);
83
  // wp_mail( 'support@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
84
  wp_mail('bart@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
@@ -106,16 +103,6 @@ if (!class_exists('sidekickMassActivator')) {
106
  }
107
  }
108
 
109
- function track($event, $data = array()) {
110
- if (file_exists(realpath(dirname(__FILE__)) . '/mixpanel/Mixpanel.php')) {
111
- require_once(realpath(dirname(__FILE__)) . '/mixpanel/Mixpanel.php');
112
- $mp = Mixpanel::getInstance("965556434c5ae652a44f24b85b442263");
113
- $domain = str_replace("http://", "", $_SERVER["SERVER_NAME"]);
114
-
115
- $mp->track($event, $data);
116
- }
117
- }
118
-
119
  function activate_batch() {
120
  $checked_blogs = get_option('sk_checked_blogs');
121
  $count = 0;
@@ -487,8 +474,6 @@ if (!class_exists('sidekickMassActivator')) {
487
  $is_ms_admin = true;
488
  $affiliate_id = $this->getAffiliateId();
489
 
490
- $this->track(array('what' => 'Network Settings Page', 'where' => 'plugin'));
491
-
492
  require_once('ms_admin_page.php');
493
  }
494
  }
62
  update_option('sk_email', $email);
63
  restore_current_blog();
64
 
 
 
65
  if (isset($checked_blogs['deactivated'][$blog_id])) {
66
  $checked_blogs['active'][$blog_id] = $checked_blogs['deactivated'][$blog_id];
67
  unset($checked_blogs['deactivated'][$blog_id]);
76
  delete_option('sk_auto_activation_error');
77
  } else {
78
 
 
79
  update_option('sk_auto_activation_error', $result->message);
80
  // wp_mail( 'support@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
81
  wp_mail('bart@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
103
  }
104
  }
105
 
 
 
 
 
 
 
 
 
 
 
106
  function activate_batch() {
107
  $checked_blogs = get_option('sk_checked_blogs');
108
  $count = 0;
474
  $is_ms_admin = true;
475
  $affiliate_id = $this->getAffiliateId();
476
 
 
 
477
  require_once('ms_admin_page.php');
478
  }
479
  }
libs/mixpanel/Base/MixpanelBase.php DELETED
@@ -1,65 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * This a Base class which all Mixpanel classes extend from to provide some very basic
5
- * debugging and logging functionality. It also serves to persist $_options across the library.
6
- *
7
- */
8
- class Base_MixpanelBase {
9
-
10
-
11
- /**
12
- * Default options that can be overridden via the $options constructor arg
13
- * @var array
14
- */
15
- private $_defaults = array(
16
- "max_batch_size" => 50, // the max batch size Mixpanel will accept is 50,
17
- "max_queue_size" => 1000, // the max num of items to hold in memory before flushing
18
- "debug" => false, // enable/disable debug mode
19
- "consumer" => "curl", // which consumer to use
20
- "host" => "api.mixpanel.com", // the host name for api calls
21
- "events_endpoint" => "/track", // host relative endpoint for events
22
- "people_endpoint" => "/engage", // host relative endpoint for people updates
23
- "use_ssl" => true, // use ssl when available
24
- "error_callback" => null // callback to use on consumption failures
25
- );
26
-
27
-
28
- /**
29
- * An array of options to be used by the Mixpanel library.
30
- * @var array
31
- */
32
- protected $_options = array();
33
-
34
-
35
- /**
36
- * Construct a new MixpanelBase object and merge custom options with defaults
37
- * @param array $options
38
- */
39
- public function __construct($options = array()) {
40
- $options = array_merge($this->_defaults, $options);
41
- $this->_options = $options;
42
- }
43
-
44
-
45
- /**
46
- * Log a message to PHP's error log
47
- * @param $msg
48
- */
49
- protected function _log($msg) {
50
- $arr = debug_backtrace();
51
- $class = $arr[0]['class'];
52
- $line = $arr[0]['line'];
53
- error_log ( "[ $class - line $line ] : " . $msg );
54
- }
55
-
56
-
57
- /**
58
- * Returns true if in debug mode, false if in production mode
59
- * @return bool
60
- */
61
- protected function _debug() {
62
- return array_key_exists("debug", $this->_options) && $this->_options["debug"] == true;
63
- }
64
-
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/ConsumerStrategies/AbstractConsumer.php DELETED
@@ -1,57 +0,0 @@
1
- <?php
2
- require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
3
-
4
- /**
5
- * Provides some base methods for use by a Consumer implementation
6
- */
7
- abstract class ConsumerStrategies_AbstractConsumer extends Base_MixpanelBase {
8
-
9
- /**
10
- * Creates a new AbstractConsumer
11
- * @param array $options
12
- */
13
- function __construct($options = array()) {
14
-
15
- parent::__construct($options);
16
-
17
- if ($this->_debug()) {
18
- $this->_log("Instantiated new Consumer");
19
- }
20
-
21
- }
22
-
23
- /**
24
- * Encode an array to be persisted
25
- * @param array $params
26
- * @return string
27
- */
28
- protected function _encode($params) {
29
- return base64_encode(json_encode($params));
30
- }
31
-
32
- /**
33
- * Handles errors that occur in a consumer
34
- * @param $code
35
- * @param $msg
36
- */
37
- protected function _handleError($code, $msg) {
38
- if (isset($this->_options['error_callback'])) {
39
- $handler = $this->_options['error_callback'];
40
- call_user_func($handler, $code, $msg);
41
- }
42
-
43
- if ($this->_debug()) {
44
- $arr = debug_backtrace();
45
- $class = get_class($arr[0]['object']);
46
- $line = $arr[0]['line'];
47
- error_log ( "[ $class - line $line ] : " . print_r($msg, true) );
48
- }
49
- }
50
-
51
- /**
52
- * Persist a batch of messages in whatever way the implementer sees fit
53
- * @param array $batch an array of messages to consume
54
- * @return boolean success or fail
55
- */
56
- abstract function persist($batch);
57
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/ConsumerStrategies/CurlConsumer.php DELETED
@@ -1,221 +0,0 @@
1
- <?php
2
- require_once(dirname(__FILE__) . "/AbstractConsumer.php");
3
-
4
- /**
5
- * Consumes messages and sends them to a host/endpoint using cURL
6
- */
7
- class ConsumerStrategies_CurlConsumer extends ConsumerStrategies_AbstractConsumer {
8
-
9
- /**
10
- * @var string the host to connect to (e.g. api.mixpanel.com)
11
- */
12
- protected $_host;
13
-
14
-
15
- /**
16
- * @var string the host-relative endpoint to write to (e.g. /engage)
17
- */
18
- protected $_endpoint;
19
-
20
-
21
- /**
22
- * @var int connect_timeout The number of seconds to wait while trying to connect. Default is 5 seconds.
23
- */
24
- protected $_connect_timeout;
25
-
26
-
27
- /**
28
- * @var int timeout The maximum number of seconds to allow cURL call to execute. Default is 30 seconds.
29
- */
30
- protected $_timeout;
31
-
32
-
33
- /**
34
- * @var string the protocol to use for the cURL connection
35
- */
36
- protected $_protocol;
37
-
38
-
39
- /**
40
- * @var bool|null true to fork the cURL process (using exec) or false to use PHP's cURL extension. false by default
41
- */
42
- protected $_fork = null;
43
-
44
-
45
- /**
46
- * Creates a new CurlConsumer and assigns properties from the $options array
47
- * @param array $options
48
- * @throws Exception
49
- */
50
- function __construct($options) {
51
- parent::__construct($options);
52
-
53
- $this->_host = $options['host'];
54
- $this->_endpoint = $options['endpoint'];
55
- $this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
56
- $this->_timeout = array_key_exists('timeout', $options) ? $options['timeout'] : 30;
57
- $this->_protocol = array_key_exists('use_ssl', $options) && $options['use_ssl'] == true ? "https" : "http";
58
- $this->_fork = array_key_exists('fork', $options) ? ($options['fork'] == true) : false;
59
-
60
- // ensure the environment is workable for the given settings
61
- if ($this->_fork == true) {
62
- $exists = function_exists('exec');
63
- if (!$exists) {
64
- throw new Exception('The "exec" function must exist to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
65
- }
66
- $disabled = explode(', ', ini_get('disable_functions'));
67
- $enabled = !in_array('exec', $disabled);
68
- if (!$enabled) {
69
- throw new Exception('The "exec" function must be enabled to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
70
- }
71
- } else {
72
- if (!function_exists('curl_init')) {
73
- throw new Exception('The cURL PHP extension is required to use the cURL consumer with fork = false. Try setting fork = true or use another consumer.');
74
- }
75
- }
76
- }
77
-
78
-
79
- /**
80
- * Write to the given host/endpoint using either a forked cURL process or using PHP's cURL extension
81
- * @param array $batch
82
- * @return bool
83
- */
84
- public function persist($batch) {
85
- if (count($batch) > 0) {
86
- $data = "data=" . $this->_encode($batch);
87
- $url = $this->_protocol . "://" . $this->_host . $this->_endpoint;
88
- if ($this->_fork) {
89
- return $this->_execute_forked($url, $data);
90
- } else {
91
- return $this->_execute($url, $data);
92
- }
93
- } else {
94
- return true;
95
- }
96
- }
97
-
98
-
99
- /**
100
- * Write using the cURL php extension
101
- * @param $url
102
- * @param $data
103
- * @return bool
104
- */
105
- protected function _execute($url, $data) {
106
- if ($this->_debug()) {
107
- $this->_log("Making blocking cURL call to $url");
108
- }
109
-
110
- $ch = curl_init();
111
- curl_setopt($ch, CURLOPT_URL, $url);
112
- curl_setopt($ch, CURLOPT_HEADER, 0);
113
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_connect_timeout);
114
- curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);
115
- curl_setopt($ch, CURLOPT_POST, 1);
116
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
117
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
118
- $response = curl_exec($ch);
119
- if (false === $response) {
120
- $curl_error = curl_error($ch);
121
- $curl_errno = curl_errno($ch);
122
- curl_close($ch);
123
- $this->_handleError($curl_errno, $curl_error);
124
- return false;
125
- } else {
126
- curl_close($ch);
127
- if (trim($response) == "1") {
128
- return true;
129
- } else {
130
- $this->_handleError(0, $response);
131
- return false;
132
- }
133
- }
134
- }
135
-
136
-
137
- /**
138
- * Write using a forked cURL process
139
- * @param $url
140
- * @param $data
141
- * @return bool
142
- */
143
- protected function _execute_forked($url, $data) {
144
-
145
- if ($this->_debug()) {
146
- $this->_log("Making forked cURL call to $url");
147
- }
148
-
149
- $exec = 'curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d ' . $data . ' "' . $url . '"';
150
-
151
- if(!$this->_debug()) {
152
- $exec .= " >/dev/null 2>&1 &";
153
- }
154
-
155
- exec($exec, $output, $return_var);
156
-
157
- if ($return_var != 0) {
158
- $this->_handleError($return_var, $output);
159
- }
160
-
161
- return $return_var == 0;
162
- }
163
-
164
- /**
165
- * @return int
166
- */
167
- public function getConnectTimeout()
168
- {
169
- return $this->_connect_timeout;
170
- }
171
-
172
- /**
173
- * @return string
174
- */
175
- public function getEndpoint()
176
- {
177
- return $this->_endpoint;
178
- }
179
-
180
- /**
181
- * @return bool|null
182
- */
183
- public function getFork()
184
- {
185
- return $this->_fork;
186
- }
187
-
188
- /**
189
- * @return string
190
- */
191
- public function getHost()
192
- {
193
- return $this->_host;
194
- }
195
-
196
- /**
197
- * @return array
198
- */
199
- public function getOptions()
200
- {
201
- return $this->_options;
202
- }
203
-
204
- /**
205
- * @return string
206
- */
207
- public function getProtocol()
208
- {
209
- return $this->_protocol;
210
- }
211
-
212
- /**
213
- * @return int
214
- */
215
- public function getTimeout()
216
- {
217
- return $this->_timeout;
218
- }
219
-
220
-
221
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/ConsumerStrategies/FileConsumer.php DELETED
@@ -1,38 +0,0 @@
1
- <?php
2
- require_once(dirname(__FILE__) . "/AbstractConsumer.php");
3
- /**
4
- * Consumes messages and writes them to a file
5
- */
6
- class ConsumerStrategies_FileConsumer extends ConsumerStrategies_AbstractConsumer {
7
-
8
- /**
9
- * @var string path to a file that we want to write the messages to
10
- */
11
- private $_file;
12
-
13
-
14
- /**
15
- * Creates a new FileConsumer and assigns properties from the $options array
16
- * @param array $options
17
- */
18
- function __construct($options) {
19
- parent::__construct($options);
20
-
21
- // what file to write to?
22
- $this->_file = array_key_exists("file", $options) ? $options['file'] : dirname(__FILE__)."/../../messages.txt";
23
- }
24
-
25
-
26
- /**
27
- * Append $batch to a file
28
- * @param array $batch
29
- * @return bool
30
- */
31
- public function persist($batch) {
32
- if (count($batch) > 0) {
33
- return file_put_contents($this->_file, json_encode($batch)."\n", FILE_APPEND | LOCK_EX) !== false;
34
- } else {
35
- return true;
36
- }
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/ConsumerStrategies/SocketConsumer.php DELETED
@@ -1,308 +0,0 @@
1
- <?php
2
- /**
3
- * Portions of this class were borrowed from
4
- * https://github.com/segmentio/analytics-php/blob/master/lib/Analytics/Consumer/Socket.php.
5
- * Thanks for the work!
6
- *
7
- * WWWWWW||WWWWWW
8
- * W W W||W W W
9
- * ||
10
- * ( OO )__________
11
- * / | \
12
- * /o o| MIT \
13
- * \___/||_||__||_|| *
14
- * || || || ||
15
- * _||_|| _||_||
16
- * (__|__|(__|__|
17
- * (The MIT License)
18
- *
19
- * Copyright (c) 2013 Segment.io Inc. friends@segment.io
20
- *
21
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
22
- * documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
23
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
24
- * permit persons to whom the Software is furnished to do so, subject to the following conditions:
25
- *
26
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
27
- * Software.
28
- *
29
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
30
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
31
- * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
32
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
- */
34
- require_once(dirname(__FILE__) . "/AbstractConsumer.php");
35
-
36
- /**
37
- * Consumes messages and writes them to host/endpoint using a persistent socket
38
- */
39
- class ConsumerStrategies_SocketConsumer extends ConsumerStrategies_AbstractConsumer {
40
-
41
- /**
42
- * @var string the host to connect to (e.g. api.mixpanel.com)
43
- */
44
- private $_host;
45
-
46
-
47
- /**
48
- * @var string the host-relative endpoint to write to (e.g. /engage)
49
- */
50
- private $_endpoint;
51
-
52
-
53
- /**
54
- * @var int connect_timeout the socket connection timeout in seconds
55
- */
56
- private $_connect_timeout;
57
-
58
-
59
- /**
60
- * @var string the protocol to use for the socket connection
61
- */
62
- private $_protocol;
63
-
64
-
65
- /**
66
- * @var resource holds the socket resource
67
- */
68
- private $_socket;
69
-
70
- /**
71
- * @var bool whether or not to wait for a response
72
- */
73
- private $_async;
74
-
75
-
76
- /**
77
- * Creates a new SocketConsumer and assigns properties from the $options array
78
- * @param array $options
79
- */
80
- public function __construct($options = array()) {
81
- parent::__construct($options);
82
-
83
-
84
- $this->_host = $options['host'];
85
- $this->_endpoint = $options['endpoint'];
86
- $this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
87
- $this->_async = array_key_exists('async', $options) && $options['async'] === false ? false : true;
88
-
89
- if (array_key_exists('use_ssl', $options) && $options['use_ssl'] == true) {
90
- $this->_protocol = "ssl";
91
- $this->_port = 443;
92
- } else {
93
- $this->_protocol = "tcp";
94
- $this->_port = 80;
95
- }
96
- }
97
-
98
-
99
- /**
100
- * Write using a persistent socket connection.
101
- * @param array $batch
102
- * @return bool
103
- */
104
- public function persist($batch) {
105
-
106
- $socket = $this->_getSocket();
107
- if (!is_resource($socket)) {
108
- return false;
109
- }
110
-
111
- $data = "data=".$this->_encode($batch);
112
-
113
- $body = "";
114
- $body.= "POST ".$this->_endpoint." HTTP/1.1\r\n";
115
- $body.= "Host: " . $this->_host . "\r\n";
116
- $body.= "Content-Type: application/x-www-form-urlencoded\r\n";
117
- $body.= "Accept: application/json\r\n";
118
- $body.= "Content-length: " . strlen($data) . "\r\n";
119
- $body.= "\r\n";
120
- $body.= $data;
121
-
122
- return $this->_write($socket, $body);
123
- }
124
-
125
-
126
- /**
127
- * Return cached socket if open or create a new persistent socket
128
- * @return bool|resource
129
- */
130
- private function _getSocket() {
131
- if(is_resource($this->_socket)) {
132
-
133
- if ($this->_debug()) {
134
- $this->_log("Using existing socket");
135
- }
136
-
137
- return $this->_socket;
138
- } else {
139
-
140
- if ($this->_debug()) {
141
- $this->_log("Creating new socket at ".time());
142
- }
143
-
144
- return $this->_createSocket();
145
- }
146
- }
147
-
148
- /**
149
- * Attempt to open a new socket connection, cache it, and return the resource
150
- * @param bool $retry
151
- * @return bool|resource
152
- */
153
- private function _createSocket($retry = true) {
154
- try {
155
- $socket = pfsockopen($this->_protocol . "://" . $this->_host, $this->_port, $err_no, $err_msg, $this->_connect_timeout);
156
-
157
- if ($this->_debug()) {
158
- $this->_log("Opening socket connection to " . $this->_protocol . "://" . $this->_host . ":" . $this->_port);
159
- }
160
-
161
- if ($err_no != 0) {
162
- $this->_handleError($err_no, $err_msg);
163
- return $retry == true ? $this->_createSocket(false) : false;
164
- } else {
165
- // cache the socket
166
- $this->_socket = $socket;
167
- return $socket;
168
- }
169
-
170
- } catch (Exception $e) {
171
- $this->_handleError($e->getCode(), $e->getMessage());
172
- return $retry == true ? $this->_createSocket(false) : false;
173
- }
174
- }
175
-
176
- /**
177
- * Attempt to close and dereference a socket resource
178
- */
179
- private function _destroySocket() {
180
- $socket = $this->_socket;
181
- $this->_socket = null;
182
- fclose($socket);
183
- }
184
-
185
-
186
- /**
187
- * Write $data through the given $socket
188
- * @param $socket
189
- * @param $data
190
- * @param bool $retry
191
- * @return bool
192
- */
193
- private function _write($socket, $data, $retry = true) {
194
-
195
- $bytes_sent = 0;
196
- $bytes_total = strlen($data);
197
- $socket_closed = false;
198
- $success = true;
199
- $max_bytes_per_write = 8192;
200
-
201
- // if we have no data to write just return true
202
- if ($bytes_total == 0) {
203
- return true;
204
- }
205
-
206
- // try to write the data
207
- while (!$socket_closed && $bytes_sent < $bytes_total) {
208
-
209
- try {
210
- $bytes = fwrite($socket, $data, $max_bytes_per_write);
211
-
212
- if ($this->_debug()) {
213
- $this->_log("Socket wrote ".$bytes." bytes");
214
- }
215
-
216
- // if we actually wrote data, then remove the written portion from $data left to write
217
- if ($bytes > 0) {
218
- $data = substr($data, $max_bytes_per_write);
219
- }
220
-
221
- } catch (Exception $e) {
222
- $this->_handleError($e->getCode(), $e->getMessage());
223
- $socket_closed = true;
224
- }
225
-
226
- if (isset($bytes) && $bytes) {
227
- $bytes_sent += $bytes;
228
- } else {
229
- $socket_closed = true;
230
- }
231
- }
232
-
233
- // create a new socket if the current one is closed and retry the message
234
- if ($socket_closed) {
235
-
236
- $this->_destroySocket();
237
-
238
- if ($retry) {
239
- if ($this->_debug()) {
240
- $this->_log("Retrying socket write...");
241
- }
242
- $socket = $this->_getSocket();
243
- if ($socket) return $this->_write($socket, $data, false);
244
- }
245
-
246
- return false;
247
- }
248
-
249
-
250
- // only wait for the response in debug mode or if we explicitly want to be synchronous
251
- if ($this->_debug() || !$this->_async) {
252
- $res = $this->handleResponse(fread($socket, 2048));
253
- if ($res["status"] != "200") {
254
- $this->_handleError($res["status"], $res["body"]);
255
- $success = false;
256
- }
257
- }
258
-
259
- return $success;
260
- }
261
-
262
-
263
- /**
264
- * Parse the response from a socket write (only used for debugging)
265
- * @param $response
266
- * @return array
267
- */
268
- private function handleResponse($response) {
269
-
270
- $lines = explode("\n", $response);
271
-
272
- // extract headers
273
- $headers = array();
274
- foreach($lines as $line) {
275
- $kvsplit = explode(":", $line);
276
- if (count($kvsplit) == 2) {
277
- $header = $kvsplit[0];
278
- $value = $kvsplit[1];
279
- $headers[$header] = trim($value);
280
- }
281
-
282
- }
283
-
284
- // extract status
285
- $line_one_exploded = explode(" ", $lines[0]);
286
- $status = $line_one_exploded[1];
287
-
288
- // extract body
289
- $body = $lines[count($lines) - 1];
290
-
291
- // if the connection has been closed lets kill the socket
292
- if ($headers['Connection'] == "close") {
293
- $this->_destroySocket();
294
- if ($this->_debug()) {
295
- $this->_log("Server told us connection closed so lets destroy the socket so it'll reconnect on next call");
296
- }
297
- }
298
-
299
- $ret = array(
300
- "status" => $status,
301
- "body" => $body,
302
- );
303
-
304
- return $ret;
305
- }
306
-
307
-
308
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/Mixpanel.php DELETED
@@ -1,302 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/Base/MixpanelBase.php");
4
- require_once(dirname(__FILE__) . "/Producers/MixpanelPeople.php");
5
- require_once(dirname(__FILE__) . "/Producers/MixpanelEvents.php");
6
-
7
- /**
8
- * This is the main class for the Mixpanel PHP Library which provides all of the methods you need to track events and
9
- * create/update profiles.
10
- *
11
- * Architecture
12
- * -------------
13
- *
14
- * This library is built such that all messages are buffered in an in-memory "queue"
15
- * The queue will be automatically flushed at the end of every request. Alternatively, you can call "flush()" manually
16
- * at any time. Flushed messages will be passed to a Consumer's "persist" method. The library comes with a handful of
17
- * Consumers. The "CurlConsumer" is used by default which will send the messages to Mixpanel using forked cURL processes.
18
- * You can implement your own custom Consumer to customize how a message is sent to Mixpanel. This can be useful when
19
- * you want to put messages onto a distributed queue (such as ActiveMQ or Kestrel) instead of writing to Mixpanel in
20
- * the user thread.
21
- *
22
- * Options
23
- * -------------
24
- *
25
- * <table width="100%" cellpadding="5">
26
- * <tr>
27
- * <th>Option</th>
28
- * <th>Description</th>
29
- * <th>Default</th>
30
- * </tr>
31
- * <tr>
32
- * <td>max_queue_size</td>
33
- * <td>The maximum number of items to buffer in memory before flushing</td>
34
- * <td>1000</td>
35
- * </tr>
36
- * <tr>
37
- * <td>debug</td>
38
- * <td>Enable/disable debug mode</td>
39
- * <td>false</td>
40
- * </tr>
41
- * <tr>
42
- * <td>consumer</td>
43
- * <td>The consumer to use for writing messages</td>
44
- * <td>curl</td>
45
- * </tr>
46
- * <tr>
47
- * <td>consumers</td>
48
- * <td>An array of custom consumers in the format array(consumer_key => class_name)</td>
49
- * <td>null</td>
50
- * </tr>
51
- * <tr>
52
- * <td>host</td>
53
- * <td>The host name for api calls (used by some consumers)</td>
54
- * <td>api.mixpanel.com</td>
55
- * </tr>
56
- * <tr>
57
- * <td>events_endpoint</td>
58
- * <td>The endpoint for tracking events (relative to the host)</td>
59
- * <td>/events</td>
60
- * </tr>
61
- * <tr>
62
- * <td>people_endpoint</td>
63
- * <td>The endpoint for making people updates (relative to the host)</td>
64
- * <td>/engage</td>
65
- * </tr>
66
- * <tr>
67
- * <td>use_ssl</td>
68
- * <td>Tell the consumer whether or not to use ssl (when available)</td>
69
- * <td>true</td>
70
- * </tr>
71
- * <tr>
72
- * <td>error_callback</td>
73
- * <td>The name of a function to be called on consumption failures</td>
74
- * <td>null</td>
75
- * </tr>
76
- * <tr>
77
- * <td>connect_timeout</td>
78
- * <td>In both the SocketConsumer and CurlConsumer, this is used for the connection timeout (i.e. How long it has take to actually make a connection).
79
- * <td>5</td>
80
- * </tr>
81
- * <tr>
82
- * <td>timeout</td>
83
- * <td>In the CurlConsumer (non-forked), it is used to determine how long the cURL call has to execute.
84
- * <td>30</td>
85
- * </tr>
86
- * </table>
87
- *
88
- * Example: Tracking an Event
89
- * -------------
90
- *
91
- * $mp = Mixpanel::getInstance("MY_TOKEN");
92
- *
93
- * $mp->track("My Event");
94
- *
95
- * Example: Setting Profile Properties
96
- * -------------
97
- *
98
- * $mp = Mixpanel::getInstance("MY_TOKEN", array("use_ssl" => false));
99
- *
100
- * $mp->people->set(12345, array(
101
- * '$first_name' => "John",
102
- * '$last_name' => "Doe",
103
- * '$email' => "john.doe@example.com",
104
- * '$phone' => "5555555555",
105
- * 'Favorite Color' => "red"
106
- * ));
107
- *
108
- */
109
- class Mixpanel extends Base_MixpanelBase {
110
-
111
-
112
- /**
113
- * An instance of the MixpanelPeople class (used to create/update profiles)
114
- * @var MixpanelPeople
115
- */
116
- public $people;
117
-
118
-
119
- /**
120
- * An instance of the MixpanelEvents class
121
- * @var Producers_MixpanelEvents
122
- */
123
- private $_events;
124
-
125
-
126
- /**
127
- * An instance of the Mixpanel class (for singleton use)
128
- * @var Mixpanel
129
- */
130
- private static $_instance;
131
-
132
-
133
- /**
134
- * Instantiates a new Mixpanel instance.
135
- * @param $token
136
- * @param array $options
137
- */
138
- public function __construct($token, $options = array()) {
139
- parent::__construct($options);
140
- $this->people = new Producers_MixpanelPeople($token, $options);
141
- $this->_events = new Producers_MixpanelEvents($token, $options);
142
- }
143
-
144
-
145
- /**
146
- * Returns a singleton instance of Mixpanel
147
- * @param $token
148
- * @param array $options
149
- * @return Mixpanel
150
- */
151
- public static function getInstance($token, $options = array()) {
152
- if(!isset(self::$_instance)) {
153
- self::$_instance = new Mixpanel($token, $options);
154
- }
155
- return self::$_instance;
156
- }
157
-
158
-
159
- /**
160
- * Add an array representing a message to be sent to Mixpanel to the in-memory queue.
161
- * @param array $message
162
- */
163
- public function enqueue($message = array()) {
164
- $this->_events->enqueue($message);
165
- }
166
-
167
-
168
- /**
169
- * Add an array representing a list of messages to be sent to Mixpanel to a queue.
170
- * @param array $messages
171
- */
172
- public function enqueueAll($messages = array()) {
173
- $this->_events->enqueueAll($messages);
174
- }
175
-
176
-
177
- /**
178
- * Flush the events queue
179
- * @param int $desired_batch_size
180
- */
181
- public function flush($desired_batch_size = 50) {
182
- $this->_events->flush($desired_batch_size);
183
- }
184
-
185
-
186
- /**
187
- * Empty the events queue
188
- */
189
- public function reset() {
190
- $this->_events->reset();
191
- }
192
-
193
-
194
- /**
195
- * Identify the user you want to associate to tracked events
196
- * @param string|int $user_id
197
- */
198
- public function identify($user_id) {
199
- $this->_events->identify($user_id);
200
- }
201
-
202
- /**
203
- * Track an event defined by $event associated with metadata defined by $properties
204
- * @param string $event
205
- * @param array $properties
206
- */
207
- public function track($event, $properties = array()) {
208
- $this->_events->track($event, $properties);
209
- }
210
-
211
-
212
- /**
213
- * Register a property to be sent with every event.
214
- *
215
- * If the property has already been registered, it will be
216
- * overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
217
- * @param string $property
218
- * @param mixed $value
219
- */
220
- public function register($property, $value) {
221
- $this->_events->register($property, $value);
222
- }
223
-
224
-
225
- /**
226
- * Register multiple properties to be sent with every event.
227
- *
228
- * If any of the properties have already been registered,
229
- * they will be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
230
- * instance.
231
- * @param array $props_and_vals
232
- */
233
- public function registerAll($props_and_vals = array()) {
234
- $this->_events->registerAll($props_and_vals);
235
- }
236
-
237
-
238
- /**
239
- * Register a property to be sent with every event.
240
- *
241
- * If the property has already been registered, it will NOT be
242
- * overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
243
- * @param $property
244
- * @param $value
245
- */
246
- public function registerOnce($property, $value) {
247
- $this->_events->registerOnce($property, $value);
248
- }
249
-
250
-
251
- /**
252
- * Register multiple properties to be sent with every event.
253
- *
254
- * If any of the properties have already been registered,
255
- * they will NOT be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
256
- * instance.
257
- * @param array $props_and_vals
258
- */
259
- public function registerAllOnce($props_and_vals = array()) {
260
- $this->_events->registerAllOnce($props_and_vals);
261
- }
262
-
263
-
264
- /**
265
- * Un-register an property to be sent with every event.
266
- * @param string $property
267
- */
268
- public function unregister($property) {
269
- $this->_events->unregister($property);
270
- }
271
-
272
-
273
- /**
274
- * Un-register a list of properties to be sent with every event.
275
- * @param array $properties
276
- */
277
- public function unregisterAll($properties) {
278
- $this->_events->unregisterAll($properties);
279
- }
280
-
281
-
282
- /**
283
- * Get a property that is set to be sent with every event
284
- * @param string $property
285
- * @return mixed
286
- */
287
- public function getProperty($property)
288
- {
289
- return $this->_events->getProperty($property);
290
- }
291
-
292
-
293
- /**
294
- * Alias an existing id with a different unique id. This is helpful when you want to associate a generated id
295
- * (such as a session id) to a user id or username.
296
- * @param string|int $original_id
297
- * @param string|int $new_id
298
- */
299
- public function createAlias($original_id, $new_id) {
300
- $this->_events->createAlias($original_id, $new_id);
301
- }
302
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/Producers/MixpanelBaseProducer.php DELETED
@@ -1,229 +0,0 @@
1
- <?php
2
- require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
3
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/FileConsumer.php");
4
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
5
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/SocketConsumer.php");
6
-
7
- if (!function_exists('json_encode')) {
8
- throw new Exception('The JSON PHP extension is required.');
9
- }
10
-
11
- /**
12
- * Provides some base methods for use by a message Producer
13
- */
14
- abstract class Producers_MixpanelBaseProducer extends Base_MixpanelBase {
15
-
16
-
17
- /**
18
- * @var string a token associated to a Mixpanel project
19
- */
20
- protected $_token;
21
-
22
-
23
- /**
24
- * @var array a queue to hold messages in memory before flushing in batches
25
- */
26
- private $_queue = array();
27
-
28
-
29
- /**
30
- * @var ConsumerStrategies_AbstractConsumer the consumer to use when flushing messages
31
- */
32
- private $_consumer = null;
33
-
34
-
35
- /**
36
- * @var array The list of available consumers
37
- */
38
- private $_consumers = array(
39
- "file" => "ConsumerStrategies_FileConsumer",
40
- "curl" => "ConsumerStrategies_CurlConsumer",
41
- "socket" => "ConsumerStrategies_SocketConsumer"
42
- );
43
-
44
-
45
- /**
46
- * If the queue reaches this size we'll auto-flush to prevent out of memory errors
47
- * @var int
48
- */
49
- protected $_max_queue_size = 1000;
50
-
51
-
52
- /**
53
- * Creates a new MixpanelBaseProducer, assings Mixpanel project token, registers custom Consumers, and instantiates
54
- * the desired consumer
55
- * @param $token
56
- * @param array $options
57
- */
58
- public function __construct($token, $options = array()) {
59
-
60
- parent::__construct($options);
61
-
62
- // register any customer consumers
63
- if (array_key_exists("consumers", $options)) {
64
- $this->_consumers = array_merge($this->_consumers, $options['consumers']);
65
- }
66
-
67
- // set max queue size
68
- if (array_key_exists("max_queue_size", $options)) {
69
- $this->_max_queue_size = $options['max_queue_size'];
70
- }
71
-
72
- // associate token
73
- $this->_token = $token;
74
-
75
- if ($this->_debug()) {
76
- $this->_log("Using token: ".$this->_token);
77
- }
78
-
79
- // instantiate the chosen consumer
80
- $this->_consumer = $this->_getConsumer();
81
-
82
- }
83
-
84
-
85
- /**
86
- * Flush the queue when we destruct the client with retries
87
- */
88
- public function __destruct() {
89
- $attempts = 0;
90
- $max_attempts = 10;
91
- $success = false;
92
- while (!$success && $attempts < $max_attempts) {
93
- if ($this->_debug()) {
94
- $this->_log("destruct flush attempt #".($attempts+1));
95
- }
96
- $success = $this->flush();
97
- $attempts++;
98
- }
99
- }
100
-
101
-
102
- /**
103
- * Iterate the queue and write in batches using the instantiated Consumer Strategy
104
- * @param int $desired_batch_size
105
- * @return bool whether or not the flush was successful
106
- */
107
- public function flush($desired_batch_size = 50) {
108
- $queue_size = count($this->_queue);
109
- $succeeded = true;
110
- if ($this->_debug()) {
111
- $this->_log("Flush called - queue size: ".$queue_size);
112
- }
113
-
114
- while($queue_size > 0 && $succeeded) {
115
- $batch_size = min(array($queue_size, $desired_batch_size, $this->_options['max_batch_size']));
116
- $batch = array_splice($this->_queue, 0, $batch_size);
117
- $succeeded = $this->_persist($batch);
118
-
119
- if (!$succeeded) {
120
- if ($this->_debug()) {
121
- $this->_log("Batch consumption failed!");
122
- }
123
- $this->_queue = array_merge($batch, $this->_queue);
124
-
125
- if ($this->_debug()) {
126
- $this->_log("added batch back to queue, queue size is now $queue_size");
127
- }
128
- }
129
-
130
- $queue_size = count($this->_queue);
131
-
132
- if ($this->_debug()) {
133
- $this->_log("Batch of $batch_size consumed, queue size is now $queue_size");
134
- }
135
- }
136
- return $succeeded;
137
- }
138
-
139
-
140
- /**
141
- * Empties the queue without persisting any of the messages
142
- */
143
- public function reset() {
144
- $this->_queue = array();
145
- }
146
-
147
-
148
- /**
149
- * Returns the in-memory queue
150
- * @return array
151
- */
152
- public function getQueue() {
153
- return $this->_queue;
154
- }
155
-
156
- /**
157
- * Returns the current Mixpanel project token
158
- * @return string
159
- */
160
- public function getToken() {
161
- return $this->_token;
162
- }
163
-
164
-
165
- /**
166
- * Given a strategy type, return a new PersistenceStrategy object
167
- * @return ConsumerStrategies_AbstractConsumer
168
- */
169
- protected function _getConsumer() {
170
- $key = $this->_options['consumer'];
171
- $Strategy = $this->_consumers[$key];
172
- if ($this->_debug()) {
173
- $this->_log("Using consumer: " . $key . " -> " . $Strategy);
174
- }
175
- $this->_options['endpoint'] = $this->_getEndpoint();
176
-
177
- return new $Strategy($this->_options);
178
- }
179
-
180
-
181
- /**
182
- * Add an array representing a message to be sent to Mixpanel to a queue.
183
- * @param array $message
184
- */
185
- public function enqueue($message = array()) {
186
- array_push($this->_queue, $message);
187
-
188
- // force a flush if we've reached our threshold
189
- if (count($this->_queue) > $this->_max_queue_size) {
190
- $this->flush();
191
- }
192
-
193
- if ($this->_debug()) {
194
- $this->_log("Queued message: ".json_encode($message));
195
- }
196
- }
197
-
198
-
199
- /**
200
- * Add an array representing a list of messages to be sent to Mixpanel to a queue.
201
- * @param array $messages
202
- */
203
- public function enqueueAll($messages = array()) {
204
- foreach($messages as $message) {
205
- $this->enqueue($message);
206
- }
207
-
208
- }
209
-
210
-
211
- /**
212
- * Given an array of messages, persist it with the instantiated Persistence Strategy
213
- * @param $message
214
- * @return mixed
215
- */
216
- protected function _persist($message) {
217
- return $this->_consumer->persist($message);
218
- }
219
-
220
-
221
-
222
-
223
- /**
224
- * Return the endpoint that should be used by a consumer that consumes messages produced by this producer.
225
- * @return string
226
- */
227
- abstract function _getEndpoint();
228
-
229
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/Producers/MixpanelEvents.php DELETED
@@ -1,164 +0,0 @@
1
- <?php
2
- require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
3
- require_once(dirname(__FILE__) . "/MixpanelPeople.php");
4
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
5
-
6
- /**
7
- * Provides an API to track events on Mixpanel
8
- */
9
- class Producers_MixpanelEvents extends Producers_MixpanelBaseProducer {
10
-
11
- /**
12
- * An array of properties to attach to every tracked event
13
- * @var array
14
- */
15
- private $_super_properties = array("mp_lib" => "php");
16
-
17
-
18
- /**
19
- * Track an event defined by $event associated with metadata defined by $properties
20
- * @param string $event
21
- * @param array $properties
22
- */
23
- public function track($event, $properties = array()) {
24
-
25
- // if no token is passed in, use current token
26
- if (!array_key_exists("token", $properties)) $properties['token'] = $this->_token;
27
-
28
- // if no time is passed in, use the current time
29
- if (!array_key_exists('time', $properties)) $properties['time'] = time();
30
-
31
- $params['event'] = $event;
32
- $params['properties'] = array_merge($this->_super_properties, $properties);
33
-
34
- $this->enqueue($params);
35
- }
36
-
37
-
38
- /**
39
- * Register a property to be sent with every event. If the property has already been registered, it will be
40
- * overwritten.
41
- * @param string $property
42
- * @param mixed $value
43
- */
44
- public function register($property, $value) {
45
- $this->_super_properties[$property] = $value;
46
- }
47
-
48
-
49
- /**
50
- * Register multiple properties to be sent with every event. If any of the properties have already been registered,
51
- * they will be overwritten.
52
- * @param array $props_and_vals
53
- */
54
- public function registerAll($props_and_vals = array()) {
55
- foreach($props_and_vals as $property => $value) {
56
- $this->register($property, $value);
57
- }
58
- }
59
-
60
-
61
- /**
62
- * Register a property to be sent with every event. If the property has already been registered, it will NOT be
63
- * overwritten.
64
- * @param $property
65
- * @param $value
66
- */
67
- public function registerOnce($property, $value) {
68
- if (!isset($this->_super_properties[$property])) {
69
- $this->register($property, $value);
70
- }
71
- }
72
-
73
-
74
- /**
75
- * Register multiple properties to be sent with every event. If any of the properties have already been registered,
76
- * they will NOT be overwritten.
77
- * @param array $props_and_vals
78
- */
79
- public function registerAllOnce($props_and_vals = array()) {
80
- foreach($props_and_vals as $property => $value) {
81
- if (!isset($this->_super_properties[$property])) {
82
- $this->register($property, $value);
83
- }
84
- }
85
- }
86
-
87
-
88
- /**
89
- * Un-register an property to be sent with every event.
90
- * @param string $property
91
- */
92
- public function unregister($property) {
93
- unset($this->_super_properties[$property]);
94
- }
95
-
96
-
97
- /**
98
- * Un-register a list of properties to be sent with every event.
99
- * @param array $properties
100
- */
101
- public function unregisterAll($properties) {
102
- foreach($properties as $property) {
103
- $this->unregister($property);
104
- }
105
- }
106
-
107
-
108
- /**
109
- * Get a property that is set to be sent with every event
110
- * @param string $property
111
- * @return mixed
112
- */
113
- public function getProperty($property) {
114
- return $this->_super_properties[$property];
115
- }
116
-
117
-
118
- /**
119
- * Identify the user you want to associate to tracked events
120
- * @param string|int $user_id
121
- */
122
- public function identify($user_id) {
123
- $this->register("distinct_id", $user_id);
124
- }
125
-
126
-
127
- /**
128
- * Alias an existing id with a different unique id. This is helpful when you want to associate a generated id to
129
- * a username or e-mail address.
130
- *
131
- * Because aliasing can be extremely vulnerable to race conditions and ordering issues, we'll make a synchronous
132
- * call directly to Mixpanel when this method is called. If it fails we'll throw an Exception as subsequent
133
- * events are likely to be incorrectly tracked.
134
- * @param string|int $original_id
135
- * @param string|int $new_id
136
- * @return array $msg
137
- * @throws Exception
138
- */
139
- public function createAlias($original_id, $new_id) {
140
- $msg = array(
141
- "event" => '$create_alias',
142
- "properties" => array("distinct_id" => $original_id, "alias" => $new_id, "token" => $this->_token)
143
- );
144
-
145
- $options = array_merge($this->_options, array("endpoint" => $this->_getEndpoint(), "fork" => false));
146
- $curlConsumer = new ConsumerStrategies_CurlConsumer($options);
147
- $success = $curlConsumer->persist(array($msg));
148
- if (!$success) {
149
- error_log("Creating Mixpanel Alias (original id: $original_id, new id: $new_id) failed");
150
- throw new Exception("Tried to create an alias but the call was not successful");
151
- } else {
152
- return $msg;
153
- }
154
- }
155
-
156
-
157
- /**
158
- * Returns the "events" endpoint
159
- * @return string
160
- */
161
- function _getEndpoint() {
162
- return $this->_options['events_endpoint'];
163
- }
164
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/mixpanel/Producers/MixpanelPeople.php DELETED
@@ -1,147 +0,0 @@
1
- <?php
2
- require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
3
-
4
- /**
5
- * Provides an API to create/update profiles on Mixpanel
6
- */
7
- class Producers_MixpanelPeople extends Producers_MixpanelBaseProducer {
8
-
9
- /**
10
- * Internal method to prepare a message given the message data
11
- * @param $distinct_id
12
- * @param $operation
13
- * @param $value
14
- * @param null $ip
15
- * @return array
16
- */
17
- private function _constructPayload($distinct_id, $operation, $value, $ip = null, $ignore_time = false) {
18
- $payload = array(
19
- '$token' => $this->_token,
20
- '$distinct_id' => $distinct_id,
21
- $operation => $value
22
- );
23
- if ($ip !== null) $payload['$ip'] = $ip;
24
- if ($ignore_time === true) $payload['$ignore_time'] = true;
25
- return $payload;
26
- }
27
-
28
- /**
29
- * Set properties on a user record. If the profile does not exist, it creates it with these properties.
30
- * If it does exist, it sets the properties to these values, overwriting existing values.
31
- * @param string|int $distinct_id the distinct_id or alias of a user
32
- * @param array $props associative array of properties to set on the profile
33
- * @param string|null $ip the ip address of the client (used for geo-location)
34
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
35
- */
36
- public function set($distinct_id, $props, $ip = null, $ignore_time = false) {
37
- $payload = $this->_constructPayload($distinct_id, '$set', $props, $ip, $ignore_time);
38
- $this->enqueue($payload);
39
- }
40
-
41
- /**
42
- * Set properties on a user record. If the profile does not exist, it creates it with these properties.
43
- * If it does exist, it sets the properties to these values but WILL NOT overwrite existing values.
44
- * @param string|int $distinct_id the distinct_id or alias of a user
45
- * @param array $props associative array of properties to set on the profile
46
- * @param string|null $ip the ip address of the client (used for geo-location)
47
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
48
- */
49
- public function setOnce($distinct_id, $props, $ip = null, $ignore_time = false) {
50
- $payload = $this->_constructPayload($distinct_id, '$set_once', $props, $ip, $ignore_time);
51
- $this->enqueue($payload);
52
- }
53
-
54
- /**
55
- * Unset properties on a user record. If the profile does not exist, it creates it with no properties.
56
- * If it does exist, it unsets these properties. NOTE: In other libraries we use 'unset' which is
57
- * a reserved word in PHP.
58
- * @param string|int $distinct_id the distinct_id or alias of a user
59
- * @param array $props associative array of properties to unset on the profile
60
- * @param string|null $ip the ip address of the client (used for geo-location)
61
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
62
- */
63
- public function remove($distinct_id, $props, $ip = null, $ignore_time = false) {
64
- $payload = $this->_constructPayload($distinct_id, '$unset', $props, $ip, $ignore_time);
65
- $this->enqueue($payload);
66
- }
67
-
68
- /**
69
- * Increments the value of a property on a user record. If the profile does not exist, it creates it and sets the
70
- * property to the increment value.
71
- * @param string|int $distinct_id the distinct_id or alias of a user
72
- * @param $prop string the property to increment
73
- * @param int $val the amount to increment the property by
74
- * @param string|null $ip the ip address of the client (used for geo-location)
75
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
76
- */
77
- public function increment($distinct_id, $prop, $val, $ip = null, $ignore_time = false) {
78
- $payload = $this->_constructPayload($distinct_id, '$add', array("$prop" => $val), $ip, $ignore_time);
79
- $this->enqueue($payload);
80
- }
81
-
82
- /**
83
- * Adds $val to a list located at $prop. If the property does not exist, it will be created. If $val is a string
84
- * and the list is empty or does not exist, a new list with one value will be created.
85
- * @param string|int $distinct_id the distinct_id or alias of a user
86
- * @param string $prop the property that holds the list
87
- * @param string|array $val items to add to the list
88
- * @param string|null $ip the ip address of the client (used for geo-location)
89
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
90
- */
91
- public function append($distinct_id, $prop, $val, $ip = null, $ignore_time = false) {
92
- $operation = gettype($val) == "array" ? '$union' : '$append';
93
- $payload = $this->_constructPayload($distinct_id, $operation, array("$prop" => $val), $ip, $ignore_time);
94
- $this->enqueue($payload);
95
- }
96
-
97
- /**
98
- * Adds a transaction to the user's profile for revenue tracking
99
- * @param string|int $distinct_id the distinct_id or alias of a user
100
- * @param string $amount the transaction amount e.g. "20.50"
101
- * @param null $timestamp the timestamp of when the transaction occurred (default to current timestamp)
102
- * @param string|null $ip the ip address of the client (used for geo-location)
103
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
104
- */
105
- public function trackCharge($distinct_id, $amount, $timestamp = null, $ip = null, $ignore_time = false) {
106
- $timestamp = $timestamp == null ? time() : $timestamp;
107
- $date_iso = date("c", $timestamp);
108
- $transaction = array(
109
- '$time' => $date_iso,
110
- '$amount' => $amount
111
- );
112
- $val = array('$transactions' => $transaction);
113
- $payload = $this->_constructPayload($distinct_id, '$append', $val, $ip, $ignore_time);
114
- $this->enqueue($payload);
115
- }
116
-
117
- /**
118
- * Clear all transactions stored on a user's profile
119
- * @param string|int $distinct_id the distinct_id or alias of a user
120
- * @param string|null $ip the ip address of the client (used for geo-location)
121
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
122
- */
123
- public function clearCharges($distinct_id, $ip = null, $ignore_time = false) {
124
- $payload = $this->_constructPayload($distinct_id, '$set', array('$transactions' => array()), $ip, $ignore_time);
125
- $this->enqueue($payload);
126
- }
127
-
128
- /**
129
- * Delete this profile from Mixpanel
130
- * @param string|int $distinct_id the distinct_id or alias of a user
131
- * @param string|null $ip the ip address of the client (used for geo-location)
132
- * @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
133
- */
134
- public function deleteUser($distinct_id, $ip = null, $ignore_time = false) {
135
- $payload = $this->_constructPayload($distinct_id, '$delete', "", $ip, $ignore_time);
136
- $this->enqueue($payload);
137
- }
138
-
139
- /**
140
- * Returns the "engage" endpoint
141
- * @return string
142
- */
143
- function _getEndpoint() {
144
- return $this->_options['people_endpoint'];
145
- }
146
-
147
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.sidekick.pro
4
  Tags: help, tutorial, tutorials,screencast, self-help, training, learn, learning, sidekick, guide, teach, video, manual, videos, wphelp, support, instructions, question, questions, answers, answer, clippy, q&a, wpuniversity, helper, walkthrough
5
  Requires at least: 3.7
6
  Tested up to: 4.2
7
- Stable tag: 2.5.4
8
  License: GNU Version 2 or Any Later Version
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -145,6 +145,12 @@ We read and respond to every piece of feedback we get.
145
 
146
  == Changelog ==
147
 
 
 
 
 
 
 
148
  = 2.5.4 =
149
  * Fixes to MultiSite saving setting (Thank You Gabe from justaddcontent.com)
150
 
4
  Tags: help, tutorial, tutorials,screencast, self-help, training, learn, learning, sidekick, guide, teach, video, manual, videos, wphelp, support, instructions, question, questions, answers, answer, clippy, q&a, wpuniversity, helper, walkthrough
5
  Requires at least: 3.7
6
  Tested up to: 4.2
7
+ Stable tag: 2.5.5
8
  License: GNU Version 2 or Any Later Version
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
145
 
146
  == Changelog ==
147
 
148
+ = 2.5.5 =
149
+ * Clean up of tracking routines
150
+ * Additional security around preference saving (Thank You Joost - @yoast)
151
+ * Fixes to global CSS rules (Thank You Joost - @yoast)
152
+ * Network admin screen has clearler titling for options
153
+
154
  = 2.5.4 =
155
  * Fixes to MultiSite saving setting (Thank You Gabe from justaddcontent.com)
156
 
sidekick.php CHANGED
@@ -6,7 +6,7 @@ Plugin URL: http://wordpress.org/plugins/sidekick/
6
  Description: Adds a real-time WordPress training walkthroughs right in your Dashboard
7
  Requires at least: 4.0
8
  Tested up to: 4.1.1
9
- Version: 2.5.4
10
  Author: Sidekick.pro
11
  Author URI: http://www.sidekick.pro
12
  */
@@ -25,7 +25,7 @@ if (!class_exists('Sidekick')){
25
  function __construct(){
26
  if (!defined('SK_API')) define('SK_API','//apiv2.sidekick.pro/');
27
  if (!defined('SK_TRACKING_API')) define('SK_TRACKING_API','//tracking.sidekick.pro/');
28
- if (!defined('SK_CACHE_PREFIX')) define('SK_CACHE_PREFIX',str_replace('.', '_', '2.5.4'));
29
  }
30
 
31
  function enqueue_required(){
@@ -51,16 +51,6 @@ if (!class_exists('Sidekick')){
51
  add_submenu_page( 'options-general.php', 'Sidekick', 'Sidekick', 'activate_plugins','sidekick', array(&$this,'admin_page'));
52
  }
53
 
54
- function ajax_save(){
55
- if (current_user_can('install_plugins')) {
56
- if (isset($_POST['sk_composer_button']) && $_POST['sk_composer_button'] == "true") {
57
- update_option( 'sk_composer_button', true );
58
- } elseif (isset($_POST['sk_composer_button']) && $_POST['sk_composer_button'] == "false") {
59
- delete_option('sk_composer_button');
60
- }
61
- }
62
- }
63
-
64
  function admin_page(){
65
 
66
  if ( empty( $_POST ) || check_admin_referer( 'update_sk_settings' ) ) {
@@ -103,8 +93,6 @@ if (!class_exists('Sidekick')){
103
  $status = 'Checking...';
104
  }
105
 
106
- $this->track(array('event' => 'Settings Page', 'what' => 'Settings Page', 'where' => 'plugin'));
107
-
108
  global $wp_version;
109
  if (version_compare($wp_version, '3.9', '<=')) {
110
  $error = "Sorry, Sidekick requires WordPress 3.9 or higher to function.";
@@ -251,8 +239,6 @@ if (!class_exists('Sidekick')){
251
  $sk_hide_config_taskbar_button = true;
252
  }
253
 
254
-
255
-
256
  $sk_config = array(
257
  "compatibilities" => array(
258
  "comment_count" => $sk_config_data->get_comments(),
@@ -289,9 +275,8 @@ if (!class_exists('Sidekick')){
289
  "show_login" => (get_option( 'sk_just_activated' )) ? true : false, // open drawer automatically, same as just_activated
290
 
291
  // WordPress
292
- "embedded" => false,
293
- "embedPartner" => SK_EMBEDDED_PARTNER, // for tracking purposes if sidekick has been embeded in another WordPress plugin or theme
294
- "plugin_version" => '2.5.4', // WordPress plugin version
295
  "site_url" => $sk_config_data->get_domain(),
296
  "domain" => str_replace("http://","",$_SERVER["SERVER_NAME"]),
297
  "plugin_url" => admin_url("admin.php?page=sidekick"),
@@ -308,7 +293,6 @@ if (!class_exists('Sidekick')){
308
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_statuses());
309
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_types_and_statuses());
310
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_framework());
311
-
312
  $sk_config = apply_filters('sk_config',$sk_config);
313
 
314
  delete_option( 'sk_just_activated' );
@@ -327,59 +311,6 @@ if (!class_exists('Sidekick')){
327
  <?php
328
  }
329
 
330
- function track($data){
331
- mlog('track');
332
-
333
- if (file_exists(realpath(dirname(__FILE__)) . '/libs/mixpanel/Mixpanel.php')) {
334
- require_once(realpath(dirname(__FILE__)) . '/libs/mixpanel/Mixpanel.php');
335
- $mp = Mixpanel::getInstance("965556434c5ae652a44f24b85b442263");
336
- $domain = str_replace("http://","",$_SERVER["SERVER_NAME"]);
337
-
338
- if (isset($data['type'])) {
339
- switch ($data['type']) {
340
- case 'activate':
341
- $mp->track("Activate - Plugin", array("domain" => $domain));
342
- break;
343
-
344
- case 'deactivate':
345
- $mp->track("Deactivate - Plugin", array("domain" => $domain));
346
- break;
347
-
348
- default:
349
- if (isset($data['event'])) {
350
- $mp->track($data['event'], array("domain" => $domain));
351
- }
352
- break;
353
- }
354
- } else {
355
- if (isset($data['event'])) {
356
- $mp->track($data['event'], array("domain" => $domain));
357
- }
358
- }
359
-
360
-
361
- }
362
-
363
- $response = wp_remote_post( SK_TRACKING_API . 'event', array(
364
- 'method' => 'POST',
365
- 'timeout' => 45,
366
- 'redirection' => 5,
367
- 'httpversion' => '1.0',
368
- 'blocking' => true,
369
- 'headers' => array(),
370
- 'body' => $data,
371
- 'cookies' => array()
372
- )
373
- );
374
- mlog('$response',$response);
375
- }
376
-
377
- function activate($return = false){
378
- if (isset($_POST['activation_id']) && current_user_can('install_plugins')) {
379
- update_option('sk_activation_id',$_POST['activation_id']);
380
- }
381
- }
382
-
383
  function activate_plugin(){
384
  update_option( 'sk_firstuse', true );
385
  update_option( 'sk_do_activation_redirect', true );
@@ -397,7 +328,7 @@ if (!class_exists('Sidekick')){
397
  function check_ver(){
398
 
399
  if (isset($_GET['sk_ver_check'])){
400
- $data = json_encode('2.5.4');
401
 
402
  if(array_key_exists('callback', $_GET)){
403
 
@@ -423,12 +354,28 @@ if (!class_exists('Sidekick')){
423
  function admin_notice() {
424
  global $current_user ;
425
  if ( ! get_user_meta($current_user->ID, 'sk_ignore_notice') ) {
426
- printf ('<div class="updated"><p>Need help with WordPress? Click HELP ME in the bottom left corner to get started! <a href="%1$s">Hide</a></p></div>','?sk_ignore_notice=1');
 
 
 
 
 
 
 
 
 
 
 
427
  }
428
  }
429
 
430
  function admin_notice_ignore() {
431
  global $current_user;
 
 
 
 
 
432
  if ( isset($_GET['sk_ignore_notice'])) {
433
  add_user_meta($current_user->ID, 'sk_ignore_notice', true);
434
  }
@@ -437,23 +384,19 @@ if (!class_exists('Sidekick')){
437
  // Clear transients for cached sk_config_data
438
 
439
  function delete_sk_get_comments(){
440
- mlog("delete_sk_get_comments");
441
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_comments');
442
  }
443
 
444
  function delete_sk_get_post_types(){
445
- mlog('delete sk_get_post_types');
446
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_post_types');
447
  delete_transient('sk_' . SK_CACHE_PREFIX . '_post_statuses');
448
  }
449
 
450
  function delete_sk_get_user_data(){
451
- mlog('delete sk_get_user_data');
452
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_user_data');
453
  }
454
 
455
  function delete_sk_get_plugins(){
456
- mlog('delete sk_get_plugins');
457
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_plugins');
458
  }
459
 
@@ -469,8 +412,6 @@ if (!class_exists('Sidekick')){
469
  add_action('admin_init', array($sidekick,'redirect'));
470
  add_action('admin_init', array($sidekick,'admin_notice_ignore'));
471
  add_action('admin_menu', array($sidekick,'setup_menu'));
472
- add_action('wp_ajax_sk_activate', array($sidekick,'activate'));
473
- add_action('wp_ajax_sk_save', array($sidekick,'ajax_save'));
474
  add_action('admin_notices', array($sidekick,'admin_notice'));
475
  add_action('admin_footer', array($sidekick,'footer'));
476
  add_action('customize_controls_print_footer_scripts', array($sidekick,'footer'));
6
  Description: Adds a real-time WordPress training walkthroughs right in your Dashboard
7
  Requires at least: 4.0
8
  Tested up to: 4.1.1
9
+ Version: 2.5.5
10
  Author: Sidekick.pro
11
  Author URI: http://www.sidekick.pro
12
  */
25
  function __construct(){
26
  if (!defined('SK_API')) define('SK_API','//apiv2.sidekick.pro/');
27
  if (!defined('SK_TRACKING_API')) define('SK_TRACKING_API','//tracking.sidekick.pro/');
28
+ if (!defined('SK_CACHE_PREFIX')) define('SK_CACHE_PREFIX',str_replace('.', '_', '2.5.5'));
29
  }
30
 
31
  function enqueue_required(){
51
  add_submenu_page( 'options-general.php', 'Sidekick', 'Sidekick', 'activate_plugins','sidekick', array(&$this,'admin_page'));
52
  }
53
 
 
 
 
 
 
 
 
 
 
 
54
  function admin_page(){
55
 
56
  if ( empty( $_POST ) || check_admin_referer( 'update_sk_settings' ) ) {
93
  $status = 'Checking...';
94
  }
95
 
 
 
96
  global $wp_version;
97
  if (version_compare($wp_version, '3.9', '<=')) {
98
  $error = "Sorry, Sidekick requires WordPress 3.9 or higher to function.";
239
  $sk_hide_config_taskbar_button = true;
240
  }
241
 
 
 
242
  $sk_config = array(
243
  "compatibilities" => array(
244
  "comment_count" => $sk_config_data->get_comments(),
275
  "show_login" => (get_option( 'sk_just_activated' )) ? true : false, // open drawer automatically, same as just_activated
276
 
277
  // WordPress
278
+ "embed_partner_id" => SK_EMBEDDED_PARTNER, // for tracking purposes if sidekick has been embeded in another WordPress plugin or theme
279
+ "plugin_version" => '2.5.5', // WordPress plugin version
 
280
  "site_url" => $sk_config_data->get_domain(),
281
  "domain" => str_replace("http://","",$_SERVER["SERVER_NAME"]),
282
  "plugin_url" => admin_url("admin.php?page=sidekick"),
293
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_statuses());
294
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_types_and_statuses());
295
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_framework());
 
296
  $sk_config = apply_filters('sk_config',$sk_config);
297
 
298
  delete_option( 'sk_just_activated' );
311
  <?php
312
  }
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  function activate_plugin(){
315
  update_option( 'sk_firstuse', true );
316
  update_option( 'sk_do_activation_redirect', true );
328
  function check_ver(){
329
 
330
  if (isset($_GET['sk_ver_check'])){
331
+ $data = json_encode('2.5.5');
332
 
333
  if(array_key_exists('callback', $_GET)){
334
 
354
  function admin_notice() {
355
  global $current_user ;
356
  if ( ! get_user_meta($current_user->ID, 'sk_ignore_notice') ) {
357
+ printf ('<div class="updated sidekick_welcome">
358
+ <p>
359
+ <b>Need help with WordPress?</b> - You can always find help in the bottom left corner, just click the Help button.</b>
360
+ </p>
361
+ <p>
362
+ <a href="javascript: sidekick.play_intro(true); Sidekick.Events.trigger(\'track_play_intro\',{location: \'welcome_header\'})" class="sk_wp_primary button button-primary">
363
+ What\'s Sidekick?
364
+ </a>
365
+ <a href="%1$s" class="button-secondary button skip">No Thanks</a>
366
+ </p>
367
+ </div>',
368
+ wp_nonce_url('?sk_ignore_notice=1','hide_msg', 'sk_nonce'));
369
  }
370
  }
371
 
372
  function admin_notice_ignore() {
373
  global $current_user;
374
+
375
+ if (!isset($_GET['sk_nonce']) || !wp_verify_nonce($_GET['sk_nonce'], 'hide_msg')) {
376
+ return false;
377
+ }
378
+
379
  if ( isset($_GET['sk_ignore_notice'])) {
380
  add_user_meta($current_user->ID, 'sk_ignore_notice', true);
381
  }
384
  // Clear transients for cached sk_config_data
385
 
386
  function delete_sk_get_comments(){
 
387
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_comments');
388
  }
389
 
390
  function delete_sk_get_post_types(){
 
391
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_post_types');
392
  delete_transient('sk_' . SK_CACHE_PREFIX . '_post_statuses');
393
  }
394
 
395
  function delete_sk_get_user_data(){
 
396
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_user_data');
397
  }
398
 
399
  function delete_sk_get_plugins(){
 
400
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_plugins');
401
  }
402
 
412
  add_action('admin_init', array($sidekick,'redirect'));
413
  add_action('admin_init', array($sidekick,'admin_notice_ignore'));
414
  add_action('admin_menu', array($sidekick,'setup_menu'));
 
 
415
  add_action('admin_notices', array($sidekick,'admin_notice'));
416
  add_action('admin_footer', array($sidekick,'footer'));
417
  add_action('customize_controls_print_footer_scripts', array($sidekick,'footer'));
sidekick_embed.php CHANGED
@@ -8,7 +8,7 @@ Description: Adds a real-time WordPress training walkthroughs right in your Dash
8
  We recommend not activating SIDEKICK automatically for people but via an Opt-In process when they configure your own theme or plugin.
9
  Requires at least: 4.0
10
  Tested up to: 4.1.1
11
- Version: 2.5.4
12
  Author: Sidekick.pro
13
  Author URI: http://www.sidekick.pro
14
  */
@@ -30,7 +30,7 @@ if (!$sidekick_active && !class_exists('Sidekick')){
30
  function __construct(){
31
  if (!defined('SK_API')) define('SK_API','//apiv2.sidekick.pro/');
32
  if (!defined('SK_TRACKING_API')) define('SK_TRACKING_API','//tracking.sidekick.pro/');
33
- if (!defined('SK_CACHE_PREFIX')) define('SK_CACHE_PREFIX',str_replace('.', '_', '2.5.4'));
34
  }
35
 
36
  function enqueue_required(){
@@ -56,16 +56,6 @@ if (!$sidekick_active && !class_exists('Sidekick')){
56
  add_submenu_page( 'options-general.php', 'Sidekick', 'Sidekick', 'activate_plugins','sidekick', array(&$this,'admin_page'));
57
  }
58
 
59
- function ajax_save(){
60
- if (current_user_can('install_plugins')) {
61
- if (isset($_POST['sk_composer_button']) && $_POST['sk_composer_button'] == "true") {
62
- update_option( 'sk_composer_button', true );
63
- } elseif (isset($_POST['sk_composer_button']) && $_POST['sk_composer_button'] == "false") {
64
- delete_option('sk_composer_button');
65
- }
66
- }
67
- }
68
-
69
  function admin_page(){
70
 
71
  if ( empty( $_POST ) || check_admin_referer( 'update_sk_settings' ) ) {
@@ -108,8 +98,6 @@ if (!$sidekick_active && !class_exists('Sidekick')){
108
  $status = 'Checking...';
109
  }
110
 
111
- $this->track(array('event' => 'Settings Page', 'what' => 'Settings Page', 'where' => 'plugin'));
112
-
113
  global $wp_version;
114
  if (version_compare($wp_version, '3.9', '<=')) {
115
  $error = "Sorry, Sidekick requires WordPress 3.9 or higher to function.";
@@ -510,8 +498,6 @@ if (!$sidekick_active && !class_exists('Sidekick')){
510
  $sk_hide_config_taskbar_button = true;
511
  }
512
 
513
-
514
-
515
  $sk_config = array(
516
  "compatibilities" => array(
517
  "comment_count" => $sk_config_data->get_comments(),
@@ -548,9 +534,8 @@ if (!$sidekick_active && !class_exists('Sidekick')){
548
  "show_login" => (get_option( 'sk_just_activated' )) ? true : false, // open drawer automatically, same as just_activated
549
 
550
  // WordPress
551
- "embedded" => false,
552
- "embedPartner" => SK_EMBEDDED_PARTNER, // for tracking purposes if sidekick has been embeded in another WordPress plugin or theme
553
- "plugin_version" => '2.5.4', // WordPress plugin version
554
  "site_url" => $sk_config_data->get_domain(),
555
  "domain" => str_replace("http://","",$_SERVER["SERVER_NAME"]),
556
  "plugin_url" => admin_url("admin.php?page=sidekick"),
@@ -567,7 +552,6 @@ if (!$sidekick_active && !class_exists('Sidekick')){
567
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_statuses());
568
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_types_and_statuses());
569
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_framework());
570
-
571
  $sk_config = apply_filters('sk_config',$sk_config);
572
 
573
  delete_option( 'sk_just_activated' );
@@ -586,59 +570,6 @@ if (!$sidekick_active && !class_exists('Sidekick')){
586
  <?php
587
  }
588
 
589
- function track($data){
590
- mlog('track');
591
-
592
- if (file_exists(realpath(dirname(__FILE__)) . '/libs/mixpanel/Mixpanel.php')) {
593
- require_once(realpath(dirname(__FILE__)) . '/libs/mixpanel/Mixpanel.php');
594
- $mp = Mixpanel::getInstance("965556434c5ae652a44f24b85b442263");
595
- $domain = str_replace("http://","",$_SERVER["SERVER_NAME"]);
596
-
597
- if (isset($data['type'])) {
598
- switch ($data['type']) {
599
- case 'activate':
600
- $mp->track("Activate - Plugin", array("domain" => $domain));
601
- break;
602
-
603
- case 'deactivate':
604
- $mp->track("Deactivate - Plugin", array("domain" => $domain));
605
- break;
606
-
607
- default:
608
- if (isset($data['event'])) {
609
- $mp->track($data['event'], array("domain" => $domain));
610
- }
611
- break;
612
- }
613
- } else {
614
- if (isset($data['event'])) {
615
- $mp->track($data['event'], array("domain" => $domain));
616
- }
617
- }
618
-
619
-
620
- }
621
-
622
- $response = wp_remote_post( SK_TRACKING_API . 'event', array(
623
- 'method' => 'POST',
624
- 'timeout' => 45,
625
- 'redirection' => 5,
626
- 'httpversion' => '1.0',
627
- 'blocking' => true,
628
- 'headers' => array(),
629
- 'body' => $data,
630
- 'cookies' => array()
631
- )
632
- );
633
- mlog('$response',$response);
634
- }
635
-
636
- function activate($return = false){
637
- if (isset($_POST['activation_id']) && current_user_can('install_plugins')) {
638
- update_option('sk_activation_id',$_POST['activation_id']);
639
- }
640
- }
641
-
642
  function activate_plugin(){
643
  update_option( 'sk_firstuse', true );
644
  update_option( 'sk_do_activation_redirect', true );
@@ -656,7 +587,7 @@ if (!$sidekick_active && !class_exists('Sidekick')){
656
  function check_ver(){
657
 
658
  if (isset($_GET['sk_ver_check'])){
659
- $data = json_encode('2.5.4');
660
 
661
  if(array_key_exists('callback', $_GET)){
662
 
@@ -682,12 +613,28 @@ if (!$sidekick_active && !class_exists('Sidekick')){
682
  function admin_notice() {
683
  global $current_user ;
684
  if ( ! get_user_meta($current_user->ID, 'sk_ignore_notice') ) {
685
- printf ('<div class="updated"><p>Need help with WordPress? Click HELP ME in the bottom left corner to get started! <a href="%1$s">Hide</a></p></div>','?sk_ignore_notice=1');
 
 
 
 
 
 
 
 
 
 
 
686
  }
687
  }
688
 
689
  function admin_notice_ignore() {
690
  global $current_user;
 
 
 
 
 
691
  if ( isset($_GET['sk_ignore_notice'])) {
692
  add_user_meta($current_user->ID, 'sk_ignore_notice', true);
693
  }
@@ -696,23 +643,19 @@ if (!$sidekick_active && !class_exists('Sidekick')){
696
  // Clear transients for cached sk_config_data
697
 
698
  function delete_sk_get_comments(){
699
- mlog("delete_sk_get_comments");
700
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_comments');
701
  }
702
 
703
  function delete_sk_get_post_types(){
704
- mlog('delete sk_get_post_types');
705
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_post_types');
706
  delete_transient('sk_' . SK_CACHE_PREFIX . '_post_statuses');
707
  }
708
 
709
  function delete_sk_get_user_data(){
710
- mlog('delete sk_get_user_data');
711
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_user_data');
712
  }
713
 
714
  function delete_sk_get_plugins(){
715
- mlog('delete sk_get_plugins');
716
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_plugins');
717
  }
718
 
@@ -728,8 +671,6 @@ if (!$sidekick_active && !class_exists('Sidekick')){
728
  add_action('admin_init', array($sidekick,'redirect'));
729
  add_action('admin_init', array($sidekick,'admin_notice_ignore'));
730
  add_action('admin_menu', array($sidekick,'setup_menu'));
731
- add_action('wp_ajax_sk_activate', array($sidekick,'activate'));
732
- add_action('wp_ajax_sk_save', array($sidekick,'ajax_save'));
733
  add_action('admin_notices', array($sidekick,'admin_notice'));
734
  add_action('admin_footer', array($sidekick,'footer'));
735
  add_action('customize_controls_print_footer_scripts', array($sidekick,'footer'));
@@ -811,8 +752,6 @@ if (!$sidekick_active && !class_exists('sidekickMassActivator')) {
811
  update_option('sk_email', $email);
812
  restore_current_blog();
813
 
814
- $this->track('Mass Activate', array('domain' => $domain, 'email' => $email));
815
-
816
  if (isset($checked_blogs['deactivated'][$blog_id])) {
817
  $checked_blogs['active'][$blog_id] = $checked_blogs['deactivated'][$blog_id];
818
  unset($checked_blogs['deactivated'][$blog_id]);
@@ -827,7 +766,6 @@ if (!$sidekick_active && !class_exists('sidekickMassActivator')) {
827
  delete_option('sk_auto_activation_error');
828
  } else {
829
 
830
- $this->track('Mass Activate Error', array('domain' => $domain, 'message' => $result->message, 'email' => $email));
831
  update_option('sk_auto_activation_error', $result->message);
832
  // wp_mail( 'support@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
833
  wp_mail('bart@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
@@ -855,16 +793,6 @@ if (!$sidekick_active && !class_exists('sidekickMassActivator')) {
855
  }
856
  }
857
 
858
- function track($event, $data = array()) {
859
- if (file_exists(realpath(dirname(__FILE__)) . '/mixpanel/Mixpanel.php')) {
860
- require_once(realpath(dirname(__FILE__)) . '/mixpanel/Mixpanel.php');
861
- $mp = Mixpanel::getInstance("965556434c5ae652a44f24b85b442263");
862
- $domain = str_replace("http://", "", $_SERVER["SERVER_NAME"]);
863
-
864
- $mp->track($event, $data);
865
- }
866
- }
867
-
868
  function activate_batch() {
869
  $checked_blogs = get_option('sk_checked_blogs');
870
  $count = 0;
@@ -1236,8 +1164,6 @@ if (!$sidekick_active && !class_exists('sidekickMassActivator')) {
1236
  $is_ms_admin = true;
1237
  $affiliate_id = $this->getAffiliateId();
1238
 
1239
- $this->track(array('what' => 'Network Settings Page', 'where' => 'plugin'));
1240
-
1241
  ?>
1242
  ?> <!-- ms_admin_page.php -->
1243
 
8
  We recommend not activating SIDEKICK automatically for people but via an Opt-In process when they configure your own theme or plugin.
9
  Requires at least: 4.0
10
  Tested up to: 4.1.1
11
+ Version: 2.5.5
12
  Author: Sidekick.pro
13
  Author URI: http://www.sidekick.pro
14
  */
30
  function __construct(){
31
  if (!defined('SK_API')) define('SK_API','//apiv2.sidekick.pro/');
32
  if (!defined('SK_TRACKING_API')) define('SK_TRACKING_API','//tracking.sidekick.pro/');
33
+ if (!defined('SK_CACHE_PREFIX')) define('SK_CACHE_PREFIX',str_replace('.', '_', '2.5.5'));
34
  }
35
 
36
  function enqueue_required(){
56
  add_submenu_page( 'options-general.php', 'Sidekick', 'Sidekick', 'activate_plugins','sidekick', array(&$this,'admin_page'));
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
59
  function admin_page(){
60
 
61
  if ( empty( $_POST ) || check_admin_referer( 'update_sk_settings' ) ) {
98
  $status = 'Checking...';
99
  }
100
 
 
 
101
  global $wp_version;
102
  if (version_compare($wp_version, '3.9', '<=')) {
103
  $error = "Sorry, Sidekick requires WordPress 3.9 or higher to function.";
498
  $sk_hide_config_taskbar_button = true;
499
  }
500
 
 
 
501
  $sk_config = array(
502
  "compatibilities" => array(
503
  "comment_count" => $sk_config_data->get_comments(),
534
  "show_login" => (get_option( 'sk_just_activated' )) ? true : false, // open drawer automatically, same as just_activated
535
 
536
  // WordPress
537
+ "embed_partner_id" => SK_EMBEDDED_PARTNER, // for tracking purposes if sidekick has been embeded in another WordPress plugin or theme
538
+ "plugin_version" => '2.5.5', // WordPress plugin version
 
539
  "site_url" => $sk_config_data->get_domain(),
540
  "domain" => str_replace("http://","",$_SERVER["SERVER_NAME"]),
541
  "plugin_url" => admin_url("admin.php?page=sidekick"),
552
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_statuses());
553
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_post_types_and_statuses());
554
  $sk_config['compatibilities'] = array_merge($sk_config['compatibilities'],$sk_config_data->get_framework());
 
555
  $sk_config = apply_filters('sk_config',$sk_config);
556
 
557
  delete_option( 'sk_just_activated' );
570
  <?php
571
  }
572
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
  function activate_plugin(){
574
  update_option( 'sk_firstuse', true );
575
  update_option( 'sk_do_activation_redirect', true );
587
  function check_ver(){
588
 
589
  if (isset($_GET['sk_ver_check'])){
590
+ $data = json_encode('2.5.5');
591
 
592
  if(array_key_exists('callback', $_GET)){
593
 
613
  function admin_notice() {
614
  global $current_user ;
615
  if ( ! get_user_meta($current_user->ID, 'sk_ignore_notice') ) {
616
+ printf ('<div class="updated sidekick_welcome">
617
+ <p>
618
+ <b>Need help with WordPress?</b> - You can always find help in the bottom left corner, just click the Help button.</b>
619
+ </p>
620
+ <p>
621
+ <a href="javascript: sidekick.play_intro(true); Sidekick.Events.trigger(\'track_play_intro\',{location: \'welcome_header\'})" class="sk_wp_primary button button-primary">
622
+ What\'s Sidekick?
623
+ </a>
624
+ <a href="%1$s" class="button-secondary button skip">No Thanks</a>
625
+ </p>
626
+ </div>',
627
+ wp_nonce_url('?sk_ignore_notice=1','hide_msg', 'sk_nonce'));
628
  }
629
  }
630
 
631
  function admin_notice_ignore() {
632
  global $current_user;
633
+
634
+ if (!isset($_GET['sk_nonce']) || !wp_verify_nonce($_GET['sk_nonce'], 'hide_msg')) {
635
+ return false;
636
+ }
637
+
638
  if ( isset($_GET['sk_ignore_notice'])) {
639
  add_user_meta($current_user->ID, 'sk_ignore_notice', true);
640
  }
643
  // Clear transients for cached sk_config_data
644
 
645
  function delete_sk_get_comments(){
 
646
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_comments');
647
  }
648
 
649
  function delete_sk_get_post_types(){
 
650
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_post_types');
651
  delete_transient('sk_' . SK_CACHE_PREFIX . '_post_statuses');
652
  }
653
 
654
  function delete_sk_get_user_data(){
 
655
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_user_data');
656
  }
657
 
658
  function delete_sk_get_plugins(){
 
659
  delete_transient('sk_' . SK_CACHE_PREFIX . '_get_plugins');
660
  }
661
 
671
  add_action('admin_init', array($sidekick,'redirect'));
672
  add_action('admin_init', array($sidekick,'admin_notice_ignore'));
673
  add_action('admin_menu', array($sidekick,'setup_menu'));
 
 
674
  add_action('admin_notices', array($sidekick,'admin_notice'));
675
  add_action('admin_footer', array($sidekick,'footer'));
676
  add_action('customize_controls_print_footer_scripts', array($sidekick,'footer'));
752
  update_option('sk_email', $email);
753
  restore_current_blog();
754
 
 
 
755
  if (isset($checked_blogs['deactivated'][$blog_id])) {
756
  $checked_blogs['active'][$blog_id] = $checked_blogs['deactivated'][$blog_id];
757
  unset($checked_blogs['deactivated'][$blog_id]);
766
  delete_option('sk_auto_activation_error');
767
  } else {
768
 
 
769
  update_option('sk_auto_activation_error', $result->message);
770
  // wp_mail( 'support@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
771
  wp_mail('bart@sidekick.pro', 'Failed Mass Domain Add', json_encode($result));
793
  }
794
  }
795
 
 
 
 
 
 
 
 
 
 
 
796
  function activate_batch() {
797
  $checked_blogs = get_option('sk_checked_blogs');
798
  $count = 0;
1164
  $is_ms_admin = true;
1165
  $affiliate_id = $this->getAffiliateId();
1166
 
 
 
1167
  ?>
1168
  ?> <!-- ms_admin_page.php -->
1169