Version Description
(2014.05.02) = - Bug fixes - Removed namespace usage in favor or a low-tech work around to be compliant with PHP 5.2 and lower
Download this release
Release Info
Developer | AndyGCook |
Plugin | HubSpot – Free Marketing Plugin for WordPress |
Version | 0.8.2 |
Comparing to | |
See all releases |
Code changes from version 0.7.0 to 0.8.2
- admin/inc/class-leadin-contact.php +2 -2
- admin/js/leadin-admin.js +1 -1
- admin/leadin-admin.php +18 -10
- admin/sass/.sass-cache/068a0951e0f44f5f7f1ab84833b671b75a0d1dd1/_clearfix.scssc +0 -0
- admin/sass/.sass-cache/068a0951e0f44f5f7f1ab84833b671b75a0d1dd1/_hacks.scssc +0 -0
- admin/sass/.sass-cache/0c3aa292b717031700a0344f604e0b99b479fc79/_susy.scssc +0 -0
- admin/sass/.sass-cache/0c3aa292b717031700a0344f604e0b99b479fc79/_susyone.scssc +0 -0
- admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_container.scssc +0 -0
- admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_end.scssc +0 -0
- admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_isolate.scssc +0 -0
- admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_span.scssc +0 -0
- admin/sass/.sass-cache/52467c9ff883780d88c16e980bb8d43c6f3f113f/_susy.scssc +0 -0
- admin/sass/.sass-cache/52467c9ff883780d88c16e980bb8d43c6f3f113f/_susyone.scssc +0 -0
- admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_background.scssc +0 -0
- admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_box-sizing.scssc +0 -0
- admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_clearfix.scssc +0 -0
- admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_prefix.scssc +0 -0
- admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_rem.scssc +0 -0
- admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_support.scssc +0 -0
- admin/sass/.sass-cache/5cb96857c5f923ac31761ca34fd727781525b482/_math.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_animation.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_appearance.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_background-clip.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_background-origin.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_background-size.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_border-radius.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_box-shadow.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_box-sizing.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_columns.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_filter.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_flexbox.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_font-face.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_hyphenation.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_images.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_inline-block.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_opacity.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_regions.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_text-shadow.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_transform.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_transition.scssc +0 -0
- admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_user-interface.scssc +0 -0
- admin/sass/.sass-cache/797a4968f0b8e5805efbffb5db3326f524464ef6/_float.scssc +0 -0
- admin/sass/.sass-cache/797a4968f0b8e5805efbffb5db3326f524464ef6/_shared.scssc +0 -0
- admin/sass/.sass-cache/797a4968f0b8e5805efbffb5db3326f524464ef6/_support.scssc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_contact_detail_page.sassc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_contacts_list_page.sassc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_grid.sassc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_powerups_page.sassc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_settings_page.sassc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_tables.sassc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_variables.sassc +0 -0
- admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/leadin-admin.sassc +0 -0
- admin/sass/.sass-cache/a1d71d7b609c5e9852c5bfc005fe6aac02f7590f/_css3.scssc +0 -0
- admin/sass/.sass-cache/a1d71d7b609c5e9852c5bfc005fe6aac02f7590f/_support.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_appearance.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_background-clip.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_background-origin.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_background-size.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_border-radius.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_box-shadow.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_box-sizing.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_box.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_columns.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_filter.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_font-face.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_hyphenation.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_images.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_inline-block.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_opacity.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_regions.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_shared.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_text-shadow.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_transform.scssc +0 -0
- admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_transition.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_background.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_functions.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_grid.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_isolation.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_margin.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_media.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_padding.scssc +0 -0
- admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_settings.scssc +0 -0
- admin/sass/.sass-cache/a9f64e5d5dd6c28c118d0281ab7b3986e2729ea7/_grid-background.scssc +0 -0
- admin/sass/.sass-cache/aa1b4daeb1aa66522abf94710543639284144823/_clearfix.scssc +0 -0
- admin/sass/.sass-cache/aa1b4daeb1aa66522abf94710543639284144823/_hacks.scssc +0 -0
- admin/sass/.sass-cache/ba1a1c8b7407a74496e0f1bb0af5e060acd9c6b4/_css3.scssc +0 -0
- admin/sass/.sass-cache/ba1a1c8b7407a74496e0f1bb0af5e060acd9c6b4/_support.scssc +0 -0
- admin/sass/.sass-cache/e4b1f93193ae29c5c808f60975dad0a21092da77/_units.scssc +0 -0
- admin/sass/.sass-cache/e4b1f93193ae29c5c808f60975dad0a21092da77/_vertical_rhythm.scssc +0 -0
- admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_background.scssc +0 -0
- admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_container.scssc +0 -0
- admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_direction.scssc +0 -0
- admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_margins.scssc +0 -0
- admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_output.scssc +0 -0
- admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_padding.scssc +0 -0
- admin/sass/.sass-cache/eba4af504693c8b2c03a74241844b1c5ab414495/_su.scssc +0 -0
- admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_contact_detail_page.sassc +0 -0
- admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_contacts_list_page.sassc +0 -0
- admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_settings_page.sassc +0 -0
- admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_tables.sassc +0 -0
- admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_variables.sassc +0 -0
- admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/leadin-admin.sassc +0 -0
- admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_grid.scssc +0 -0
- admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_maps.scssc +0 -0
- admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_settings.scssc +0 -0
- admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_validation.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_background.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_bleed.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_box-sizing.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_breakpoint-plugin.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_container.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_context.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_gallery.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_grids.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_gutters.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_isolate.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_margins.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_padding.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_rows.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_settings.scssc +0 -0
- admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_span.scssc +0 -0
- frontend/js/leadin.js +53 -11
- images/power-up-icon-constant-contact-list-sync.png +0 -0
- images/power-up-icon-constant-contact-list-sync@2x.png +0 -0
- images/power-up-icon-constant-contact-list-sync_small.png +0 -0
- images/power-up-icon-constant-contact-list-sync_small@2x.png +0 -0
- inc/class-emailer.php +7 -13
- inc/class-leadin-options.php +0 -149
- inc/leadin-ajax-functions.php +55 -17
- inc/leadin-functions.php +68 -2
- leadin.php +21 -9
- lib/mixpanel/Base/LI_MixpanelBase.php +68 -0
- lib/mixpanel/Base/MixpanelBase.php +5 -0
- lib/mixpanel/ConsumerStrategies/AbstractConsumer.php +2 -0
- lib/mixpanel/ConsumerStrategies/CurlConsumer.php +2 -0
- lib/mixpanel/ConsumerStrategies/FileConsumer.php +2 -0
- lib/mixpanel/ConsumerStrategies/LI_AbstractConsumer.php +58 -0
- lib/mixpanel/ConsumerStrategies/LI_CurlConsumer.php +222 -0
- lib/mixpanel/ConsumerStrategies/LI_FileConsumer.php +39 -0
- lib/mixpanel/ConsumerStrategies/LI_SocketConsumer.php +309 -0
- lib/mixpanel/ConsumerStrategies/SocketConsumer.php +2 -0
- lib/mixpanel/{Mixpanel.php → LI_Mixpanel.php} +10 -10
- lib/mixpanel/Producers/LI_MixpanelBaseProducer.php +230 -0
- lib/mixpanel/Producers/LI_MixpanelEvents.php +165 -0
- lib/mixpanel/Producers/LI_MixpanelPeople.php +139 -0
- lib/mixpanel/Producers/MixpanelBaseProducer.php +5 -3
- lib/mixpanel/Producers/MixpanelEvents.php +2 -0
- lib/mixpanel/Producers/MixpanelPeople.php +2 -0
- power-ups/constant-contact-list-sync.php +131 -0
- power-ups/constant-contact-list-sync/admin/constant-contact-list-sync-admin.php +205 -0
- power-ups/constant-contact-list-sync/inc/li_constant_contact.php +1114 -0
- power-ups/mailchimp-list-sync.php +1 -1
- power-ups/mailchimp-list-sync/admin/mailchimp-list-sync-admin.php +8 -7
- power-ups/mailchimp-list-sync/inc/MailChimp-API.php +1 -1
- power-ups/subscribe-widget.php +8 -2
- power-ups/subscribe-widget/admin/subscribe-widget-admin.php +81 -8
- power-ups/subscribe-widget/frontend/css/leadin-subscribe.css +0 -47
- power-ups/subscribe-widget/frontend/js/leadin-subscribe.js +5 -4
- readme.txt +36 -5
admin/inc/class-leadin-contact.php
CHANGED
@@ -118,7 +118,7 @@ class LI_Contact {
|
|
118 |
$sessions['session_' . $cur_array]['events']['event_' . $cur_event]['event_date'] = $event['event_date'];
|
119 |
|
120 |
// Set the first submission if it's not set and then leave it alone
|
121 |
-
if (
|
122 |
$lead->first_visit = $event['event_date'];
|
123 |
|
124 |
// Always overwrite the last_submission date which will end as last submission date
|
@@ -147,7 +147,7 @@ class LI_Contact {
|
|
147 |
$sessions['session_' . $cur_array]['events']['event_' . $cur_event]['activities'][] = $event;
|
148 |
|
149 |
// Set the first submission if it's not set and then leave it alone
|
150 |
-
if (
|
151 |
$lead->first_submission = $event['event_date'];
|
152 |
|
153 |
// Always overwrite the last_submission date which will end as last submission date
|
118 |
$sessions['session_' . $cur_array]['events']['event_' . $cur_event]['event_date'] = $event['event_date'];
|
119 |
|
120 |
// Set the first submission if it's not set and then leave it alone
|
121 |
+
if ( ! isset($lead->first_visit) )
|
122 |
$lead->first_visit = $event['event_date'];
|
123 |
|
124 |
// Always overwrite the last_submission date which will end as last submission date
|
147 |
$sessions['session_' . $cur_array]['events']['event_' . $cur_event]['activities'][] = $event;
|
148 |
|
149 |
// Set the first submission if it's not set and then leave it alone
|
150 |
+
if ( ! isset($lead->first_submission) )
|
151 |
$lead->first_submission = $event['event_date'];
|
152 |
|
153 |
// Always overwrite the last_submission date which will end as last submission date
|
admin/js/leadin-admin.js
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
jQuery(document).ready( function ( $ ) {
|
2 |
-
|
3 |
});
|
1 |
jQuery(document).ready( function ( $ ) {
|
2 |
+
|
3 |
});
|
admin/leadin-admin.php
CHANGED
@@ -138,11 +138,8 @@ class WPLeadInAdmin {
|
|
138 |
function leadin_options_section_heading ( )
|
139 |
{
|
140 |
?>
|
141 |
-
<
|
142 |
-
|
143 |
-
<p>The next time a visitor fills out a form on your WordPress site with an email address, LeadIn will send you an email with the contact's referral source and page view history.</p>
|
144 |
-
<p>All of your visitor's form submissions are stored in your <a href='<?php echo get_bloginfo('wpurl');?>/wp-admin/admin.php?page=leadin_contacts'>LeadIn Contacts</a>.</p>
|
145 |
-
</div>
|
146 |
<?php
|
147 |
|
148 |
$this->print_hidden_settings_fields();
|
@@ -156,6 +153,7 @@ class WPLeadInAdmin {
|
|
156 |
$li_db_version = ( $options['li_db_version'] ? $options['li_db_version'] : LEADIN_DB_VERSION );
|
157 |
$ignore_settings_popup = ( $options['ignore_settings_popup'] ? $options['ignore_settings_popup'] : 0 );
|
158 |
$onboarding_complete = ( $options['onboarding_complete'] ? $options['onboarding_complete'] : 0 );
|
|
|
159 |
|
160 |
printf(
|
161 |
'<input id="li_installed" type="hidden" name="leadin_options[li_installed]" value="%d"/>',
|
@@ -176,6 +174,11 @@ class WPLeadInAdmin {
|
|
176 |
'<input id="onboarding_complete" type="hidden" name="leadin_options[onboarding_complete]" value="%d"/>',
|
177 |
$onboarding_complete
|
178 |
);
|
|
|
|
|
|
|
|
|
|
|
179 |
}
|
180 |
|
181 |
function update_option_leadin_options_callback ( $old_value, $new_value )
|
@@ -303,12 +306,12 @@ class WPLeadInAdmin {
|
|
303 |
function li_email_callback ()
|
304 |
{
|
305 |
$options = get_option('leadin_options');
|
306 |
-
$li_email = ( $options['li_email'] ? $options['li_email'] :
|
307 |
-
|
308 |
printf(
|
309 |
-
'<input id="li_email" type="text" id="title" name="leadin_options[li_email]" value="%s" size="50"/><br/><span class="description">Separate multiple emails with commas
|
310 |
$li_email
|
311 |
-
);
|
312 |
}
|
313 |
|
314 |
/**
|
@@ -475,8 +478,13 @@ class WPLeadInAdmin {
|
|
475 |
{
|
476 |
?>
|
477 |
<div id="leadin-footer">
|
478 |
-
<p class="support"
|
|
|
|
|
|
|
|
|
479 |
<p class="sharing"><a href="https://twitter.com/leadinapp" class="twitter-follow-button" data-show-count="false">Follow @leadinapp</a>
|
|
|
480 |
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script></p>
|
481 |
</div>
|
482 |
<!-- begin SnapEngage code -->
|
138 |
function leadin_options_section_heading ( )
|
139 |
{
|
140 |
?>
|
141 |
+
<p style='color: #090; font-weight: bold;'>Visitor tracking is installed and tracking visitors.</p>
|
142 |
+
<p>The next time a visitor fills out a form on your WordPress site with an email address, LeadIn will send you an email with the contact's referral source and page view history.</p>
|
|
|
|
|
|
|
143 |
<?php
|
144 |
|
145 |
$this->print_hidden_settings_fields();
|
153 |
$li_db_version = ( $options['li_db_version'] ? $options['li_db_version'] : LEADIN_DB_VERSION );
|
154 |
$ignore_settings_popup = ( $options['ignore_settings_popup'] ? $options['ignore_settings_popup'] : 0 );
|
155 |
$onboarding_complete = ( $options['onboarding_complete'] ? $options['onboarding_complete'] : 0 );
|
156 |
+
$data_recovered = ( $options['data_recovered'] ? $options['data_recovered'] : 0 );
|
157 |
|
158 |
printf(
|
159 |
'<input id="li_installed" type="hidden" name="leadin_options[li_installed]" value="%d"/>',
|
174 |
'<input id="onboarding_complete" type="hidden" name="leadin_options[onboarding_complete]" value="%d"/>',
|
175 |
$onboarding_complete
|
176 |
);
|
177 |
+
|
178 |
+
printf(
|
179 |
+
'<input id="data_recovered" type="hidden" name="leadin_options[data_recovered]" value="%d"/>',
|
180 |
+
$data_recovered
|
181 |
+
);
|
182 |
}
|
183 |
|
184 |
function update_option_leadin_options_callback ( $old_value, $new_value )
|
306 |
function li_email_callback ()
|
307 |
{
|
308 |
$options = get_option('leadin_options');
|
309 |
+
$li_email = ( isset($options['li_email']) && $options['li_email'] ? $options['li_email'] : '' ); // Get email from plugin settings, if none set, use admin email
|
310 |
+
|
311 |
printf(
|
312 |
+
'<input id="li_email" type="text" id="title" name="leadin_options[li_email]" value="%s" size="50"/><br/><span class="description">Separate multiple emails with commas. Leave blank to disable email notifications.</span>',
|
313 |
$li_email
|
314 |
+
);
|
315 |
}
|
316 |
|
317 |
/**
|
478 |
{
|
479 |
?>
|
480 |
<div id="leadin-footer">
|
481 |
+
<p class="support">
|
482 |
+
<a href="http://leadin.com">LeadIn</a> <?php echo LEADIN_PLUGIN_VERSION?>
|
483 |
+
<span style="padding: 0px 5px;">|</span> Need help? <a href="#" onclick="return SnapEngage.startLink();">Contact us</a>
|
484 |
+
<span style="padding: 0px 5px;">|</span> Love Leadin? <a href="http://wordpress.org/support/view/plugin-reviews/leadin?rate=5#postform">Review us</a>
|
485 |
+
</p>
|
486 |
<p class="sharing"><a href="https://twitter.com/leadinapp" class="twitter-follow-button" data-show-count="false">Follow @leadinapp</a>
|
487 |
+
|
488 |
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script></p>
|
489 |
</div>
|
490 |
<!-- begin SnapEngage code -->
|
admin/sass/.sass-cache/068a0951e0f44f5f7f1ab84833b671b75a0d1dd1/_clearfix.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/068a0951e0f44f5f7f1ab84833b671b75a0d1dd1/_hacks.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/0c3aa292b717031700a0344f604e0b99b479fc79/_susy.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/0c3aa292b717031700a0344f604e0b99b479fc79/_susyone.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_container.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_end.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_isolate.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/38f6ef42965a6f3d0db78c73e0225721577524c6/_span.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/52467c9ff883780d88c16e980bb8d43c6f3f113f/_susy.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/52467c9ff883780d88c16e980bb8d43c6f3f113f/_susyone.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_background.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_box-sizing.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_clearfix.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_prefix.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_rem.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/5b0ded2c21a8382c081077cb9f130cd662c5ce8e/_support.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/5cb96857c5f923ac31761ca34fd727781525b482/_math.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_animation.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_appearance.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_background-clip.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_background-origin.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_background-size.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_border-radius.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_box-shadow.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_box-sizing.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_columns.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_filter.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_flexbox.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_font-face.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_hyphenation.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_images.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_inline-block.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_opacity.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_regions.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_text-shadow.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_transform.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_transition.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/652c361299b1c66982df1f07df999b752c83fdf9/_user-interface.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/797a4968f0b8e5805efbffb5db3326f524464ef6/_float.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/797a4968f0b8e5805efbffb5db3326f524464ef6/_shared.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/797a4968f0b8e5805efbffb5db3326f524464ef6/_support.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_contact_detail_page.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_contacts_list_page.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_grid.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_powerups_page.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_settings_page.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_tables.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/_variables.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/7feb88049015a4dff396a24786f85814ae06425c/leadin-admin.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/a1d71d7b609c5e9852c5bfc005fe6aac02f7590f/_css3.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a1d71d7b609c5e9852c5bfc005fe6aac02f7590f/_support.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_appearance.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_background-clip.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_background-origin.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_background-size.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_border-radius.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_box-shadow.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_box-sizing.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_box.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_columns.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_filter.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_font-face.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_hyphenation.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_images.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_inline-block.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_opacity.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_regions.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_shared.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_text-shadow.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_transform.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a2b7e568cca225148f3e4dc8c9c0bdfe1174b763/_transition.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_background.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_functions.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_grid.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_isolation.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_margin.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_media.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_padding.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a3876a0695ee0091b635892c2b539b865026ee33/_settings.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/a9f64e5d5dd6c28c118d0281ab7b3986e2729ea7/_grid-background.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/aa1b4daeb1aa66522abf94710543639284144823/_clearfix.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/aa1b4daeb1aa66522abf94710543639284144823/_hacks.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/ba1a1c8b7407a74496e0f1bb0af5e060acd9c6b4/_css3.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/ba1a1c8b7407a74496e0f1bb0af5e060acd9c6b4/_support.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e4b1f93193ae29c5c808f60975dad0a21092da77/_units.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e4b1f93193ae29c5c808f60975dad0a21092da77/_vertical_rhythm.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_background.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_container.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_direction.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_margins.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_output.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/e84f61336d179205ae6530d80482c1682976ab4e/_padding.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/eba4af504693c8b2c03a74241844b1c5ab414495/_su.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_contact_detail_page.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_contacts_list_page.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_settings_page.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_tables.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/_variables.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/f44f973eb6f81b0c357f9f23e88bc1c2233de3b4/leadin-admin.sassc
DELETED
Binary file
|
admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_grid.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_maps.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_settings.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fc4f4268225416ca556db305ea34784cf502478b/_validation.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_background.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_bleed.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_box-sizing.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_breakpoint-plugin.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_container.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_context.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_gallery.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_grids.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_gutters.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_isolate.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_margins.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_padding.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_rows.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_settings.scssc
DELETED
Binary file
|
admin/sass/.sass-cache/fd9de46f5118e2ba495163d7bc711998018af17d/_span.scssc
DELETED
Binary file
|
frontend/js/leadin.js
CHANGED
@@ -12,10 +12,22 @@ jQuery(document).ready( function ( $ ) {
|
|
12 |
if ( li_submission_cookie )
|
13 |
{
|
14 |
var submission_data = JSON.parse(li_submission_cookie);
|
15 |
-
leadin_insert_form_submission(
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
}
|
20 |
|
21 |
if ( !hashkey )
|
@@ -63,8 +75,11 @@ function leadin_submit_form ( $form, $, form_type )
|
|
63 |
{
|
64 |
var $this = $form;
|
65 |
|
66 |
-
var form_fields
|
67 |
-
var lead_email
|
|
|
|
|
|
|
68 |
var form_submission_type = ( form_type ? form_type : 'lead' );
|
69 |
|
70 |
// Excludes hidden input fields + submit inputs
|
@@ -163,6 +178,15 @@ function leadin_submit_form ( $form, $, form_type )
|
|
163 |
|
164 |
if ( $value.indexOf('@') != -1 && $value.indexOf('.') != -1 && !lead_email )
|
165 |
lead_email = $value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
});
|
167 |
|
168 |
var radio_groups = [];
|
@@ -249,6 +273,9 @@ function leadin_submit_form ( $form, $, form_type )
|
|
249 |
"submission_hash": submission_hash,
|
250 |
"hashkey": hashkey,
|
251 |
"lead_email": lead_email,
|
|
|
|
|
|
|
252 |
"page_title": page_title,
|
253 |
"page_url": page_url,
|
254 |
"json_form_fields": json_form_fields,
|
@@ -257,10 +284,22 @@ function leadin_submit_form ( $form, $, form_type )
|
|
257 |
|
258 |
$.cookie("li_submission", JSON.stringify(form_submission), {path: "/", domain: ""});
|
259 |
|
260 |
-
leadin_insert_form_submission(
|
261 |
-
|
262 |
-
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
}
|
265 |
else // No lead - submit form as usual
|
266 |
{
|
@@ -349,7 +388,7 @@ function leadin_insert_lead ( hashkey, page_referrer ) {
|
|
349 |
});
|
350 |
}
|
351 |
|
352 |
-
function leadin_insert_form_submission ( submission_haskey, hashkey, page_title, page_url, json_fields, lead_email, form_submission_type, Callback )
|
353 |
{
|
354 |
jQuery.ajax({
|
355 |
type: 'POST',
|
@@ -362,6 +401,9 @@ function leadin_insert_form_submission ( submission_haskey, hashkey, page_title,
|
|
362 |
"li_url": page_url,
|
363 |
"li_fields": json_fields,
|
364 |
"li_email": lead_email,
|
|
|
|
|
|
|
365 |
"li_submission_type": form_submission_type
|
366 |
},
|
367 |
success: function(data){
|
12 |
if ( li_submission_cookie )
|
13 |
{
|
14 |
var submission_data = JSON.parse(li_submission_cookie);
|
15 |
+
leadin_insert_form_submission(
|
16 |
+
submission_data.submission_hash,
|
17 |
+
submission_data.hashkey,
|
18 |
+
submission_data.page_title,
|
19 |
+
submission_data.page_url,
|
20 |
+
submission_data.json_form_fields,
|
21 |
+
submission_data.lead_email,
|
22 |
+
submission_data.lead_first_name,
|
23 |
+
submission_data.lead_last_name,
|
24 |
+
submission_data.lead_phone,
|
25 |
+
submission_data.form_submission_type,
|
26 |
+
function ( data ) {
|
27 |
+
// Form was submitted successfully before page reload. Delete cookie for this submission
|
28 |
+
$.removeCookie('li_submission', {path: "/", domain: ""});
|
29 |
+
}
|
30 |
+
);
|
31 |
}
|
32 |
|
33 |
if ( !hashkey )
|
75 |
{
|
76 |
var $this = $form;
|
77 |
|
78 |
+
var form_fields = [];
|
79 |
+
var lead_email = '';
|
80 |
+
var lead_first_name = '';
|
81 |
+
var lead_last_name = '';
|
82 |
+
var lead_phone = '';
|
83 |
var form_submission_type = ( form_type ? form_type : 'lead' );
|
84 |
|
85 |
// Excludes hidden input fields + submit inputs
|
178 |
|
179 |
if ( $value.indexOf('@') != -1 && $value.indexOf('.') != -1 && !lead_email )
|
180 |
lead_email = $value;
|
181 |
+
|
182 |
+
if ( $element.attr('id') == 'leadin-subscribe-fname')
|
183 |
+
lead_first_name = $value;
|
184 |
+
|
185 |
+
if ( $element.attr('id') == 'leadin-subscribe-lname')
|
186 |
+
lead_last_name = $value;
|
187 |
+
|
188 |
+
if ( $element.attr('id') == 'leadin-subscribe-phone')
|
189 |
+
lead_phone = $value;
|
190 |
});
|
191 |
|
192 |
var radio_groups = [];
|
273 |
"submission_hash": submission_hash,
|
274 |
"hashkey": hashkey,
|
275 |
"lead_email": lead_email,
|
276 |
+
"lead_first_name": lead_first_name,
|
277 |
+
"lead_last_name": lead_last_name,
|
278 |
+
"lead_phone": lead_phone,
|
279 |
"page_title": page_title,
|
280 |
"page_url": page_url,
|
281 |
"json_form_fields": json_form_fields,
|
284 |
|
285 |
$.cookie("li_submission", JSON.stringify(form_submission), {path: "/", domain: ""});
|
286 |
|
287 |
+
leadin_insert_form_submission(
|
288 |
+
submission_hash,
|
289 |
+
hashkey,
|
290 |
+
page_title,
|
291 |
+
page_url,
|
292 |
+
json_form_fields,
|
293 |
+
lead_email,
|
294 |
+
lead_first_name,
|
295 |
+
lead_last_name,
|
296 |
+
lead_phone,
|
297 |
+
form_submission_type,
|
298 |
+
function ( data ) {
|
299 |
+
// Form was executed 100% successfully before page reload. Delete cookie for this submission
|
300 |
+
$.removeCookie('li_submission', {path: "/", domain: ""});
|
301 |
+
}
|
302 |
+
);
|
303 |
}
|
304 |
else // No lead - submit form as usual
|
305 |
{
|
388 |
});
|
389 |
}
|
390 |
|
391 |
+
function leadin_insert_form_submission ( submission_haskey, hashkey, page_title, page_url, json_fields, lead_email, lead_first_name, lead_last_name, lead_phone, form_submission_type, Callback )
|
392 |
{
|
393 |
jQuery.ajax({
|
394 |
type: 'POST',
|
401 |
"li_url": page_url,
|
402 |
"li_fields": json_fields,
|
403 |
"li_email": lead_email,
|
404 |
+
"li_first_name": lead_first_name,
|
405 |
+
"li_last_name": lead_last_name,
|
406 |
+
"li_phone": lead_phone,
|
407 |
"li_submission_type": form_submission_type
|
408 |
},
|
409 |
success: function(data){
|
images/power-up-icon-constant-contact-list-sync.png
ADDED
Binary file
|
images/power-up-icon-constant-contact-list-sync@2x.png
ADDED
Binary file
|
images/power-up-icon-constant-contact-list-sync_small.png
ADDED
Binary file
|
images/power-up-icon-constant-contact-list-sync_small@2x.png
ADDED
Binary file
|
inc/class-emailer.php
CHANGED
@@ -95,9 +95,10 @@ class LI_Emailer {
|
|
95 |
// Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
|
96 |
$body = wordwrap($body, 900, "\r\n");
|
97 |
|
|
|
98 |
$headers = "From: LeadIn <team@leadin.com>\r\n";
|
99 |
-
$headers.= "Reply-To: LeadIn <
|
100 |
-
$headers.= "X-Mailer: PHP/" . phpversion()."\r\n";
|
101 |
$headers.= "MIME-Version: 1.0\r\n";
|
102 |
$headers.= "Content-type: text/html; charset=utf-8\r\n";
|
103 |
|
@@ -108,27 +109,19 @@ class LI_Emailer {
|
|
108 |
if ( $history->submission->form_type == "comment" )
|
109 |
{
|
110 |
$subject = "New comment posted on " . $history->submission->form_page_title;
|
111 |
-
leadin_track_plugin_activity("New comment");
|
112 |
$subject .= " by " . $history->lead->lead_email;
|
113 |
}
|
114 |
else if ( $history->submission->form_type == "subscribe" )
|
115 |
{
|
116 |
$subject = "New subscriber from " . $history->submission->form_page_title;
|
117 |
-
leadin_track_plugin_activity("New subscriber");
|
118 |
$this->send_subscriber_confirmation_email($history);
|
119 |
}
|
120 |
else
|
121 |
{
|
122 |
if ( $history->new_contact )
|
123 |
-
{
|
124 |
$subject = "New lead from " . get_bloginfo('name') . " - Say hello to " . $history->lead->lead_email;
|
125 |
-
leadin_track_plugin_activity("New lead");
|
126 |
-
}
|
127 |
else
|
128 |
-
{
|
129 |
$subject = "Lead from " . get_bloginfo('name') . " - Say hello again to " . $history->lead->lead_email;
|
130 |
-
leadin_track_plugin_activity("Returning lead");
|
131 |
-
}
|
132 |
}
|
133 |
|
134 |
$email_sent = wp_mail($to, $subject, $body, $headers);
|
@@ -416,13 +409,14 @@ class LI_Emailer {
|
|
416 |
|
417 |
// Email Base close
|
418 |
$body .= '</center></td></tr></table></body></html>';
|
|
|
419 |
|
420 |
// Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
|
421 |
$body = wordwrap($body, 900, "\r\n");
|
422 |
|
423 |
-
$headers = "From: LeadIn <
|
424 |
-
$headers.= "Reply-To: LeadIn <
|
425 |
-
$headers.= "X-Mailer: PHP/" . phpversion()."\r\n";
|
426 |
$headers.= "MIME-Version: 1.0\r\n";
|
427 |
$headers.= "Content-type: text/html; charset=utf-8\r\n";
|
428 |
|
95 |
// Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
|
96 |
$body = wordwrap($body, 900, "\r\n");
|
97 |
|
98 |
+
$from = $history->lead->lead_email;
|
99 |
$headers = "From: LeadIn <team@leadin.com>\r\n";
|
100 |
+
$headers.= "Reply-To: LeadIn <" . $from . ">\r\n";
|
101 |
+
$headers.= "X-Mailer: PHP/" . phpversion() . "\r\n";
|
102 |
$headers.= "MIME-Version: 1.0\r\n";
|
103 |
$headers.= "Content-type: text/html; charset=utf-8\r\n";
|
104 |
|
109 |
if ( $history->submission->form_type == "comment" )
|
110 |
{
|
111 |
$subject = "New comment posted on " . $history->submission->form_page_title;
|
|
|
112 |
$subject .= " by " . $history->lead->lead_email;
|
113 |
}
|
114 |
else if ( $history->submission->form_type == "subscribe" )
|
115 |
{
|
116 |
$subject = "New subscriber from " . $history->submission->form_page_title;
|
|
|
117 |
$this->send_subscriber_confirmation_email($history);
|
118 |
}
|
119 |
else
|
120 |
{
|
121 |
if ( $history->new_contact )
|
|
|
122 |
$subject = "New lead from " . get_bloginfo('name') . " - Say hello to " . $history->lead->lead_email;
|
|
|
|
|
123 |
else
|
|
|
124 |
$subject = "Lead from " . get_bloginfo('name') . " - Say hello again to " . $history->lead->lead_email;
|
|
|
|
|
125 |
}
|
126 |
|
127 |
$email_sent = wp_mail($to, $subject, $body, $headers);
|
409 |
|
410 |
// Email Base close
|
411 |
$body .= '</center></td></tr></table></body></html>';
|
412 |
+
$from = apply_filters( 'li_subscribe_from', $leadin_email );
|
413 |
|
414 |
// Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
|
415 |
$body = wordwrap($body, 900, "\r\n");
|
416 |
|
417 |
+
$headers = "From: LeadIn <" . $from . ">\r\n";
|
418 |
+
$headers.= "Reply-To: LeadIn <" . $from . ">\r\n";
|
419 |
+
$headers.= "X-Mailer: PHP/" . phpversion() . "\r\n";
|
420 |
$headers.= "MIME-Version: 1.0\r\n";
|
421 |
$headers.= "Content-type: text/html; charset=utf-8\r\n";
|
422 |
|
inc/class-leadin-options.php
DELETED
@@ -1,149 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class LeadInOptions {
|
4 |
-
|
5 |
-
/*public static function get_option_names( $type = 'compact' ) {
|
6 |
-
switch ( $type ) {
|
7 |
-
case 'non-compact' :
|
8 |
-
case 'non_compact' :
|
9 |
-
return array(
|
10 |
-
'register',
|
11 |
-
'activated',
|
12 |
-
'active_modules',
|
13 |
-
'do_activate',
|
14 |
-
'log',
|
15 |
-
'publicize',
|
16 |
-
'widget_twitter',
|
17 |
-
'wpcc_options',
|
18 |
-
);
|
19 |
-
}
|
20 |
-
|
21 |
-
return array(
|
22 |
-
'id', // (int) The Client ID/WP.com Blog ID of this site.
|
23 |
-
'blog_token', // (string) The Client Secret/Blog Token of this site.
|
24 |
-
'user_token', // (string) The User Token of this site. (deprecated)
|
25 |
-
'publicize_connections', // (array) An array of Publicize connections from WordPress.com
|
26 |
-
'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com.
|
27 |
-
'user_tokens', // (array) User Tokens for each user of this site who has connected to jetpack.wordpress.com.
|
28 |
-
'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time
|
29 |
-
'old_version', // (string) Used to determine which modules are the most recently added. previous_version:time
|
30 |
-
'fallback_no_verify_ssl_certs', // (int) Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
|
31 |
-
'time_diff', // (int) Offset between Jetpack server's clocks and this server's clocks. Jetpack Server Time = time() + (int) Jetpack_Options::get_option( 'time_diff' )
|
32 |
-
'public', // (int|bool) If we think this site is public or not (1, 0), false if we haven't yet tried to figure it out.
|
33 |
-
'videopress', // (array) VideoPress options array.
|
34 |
-
'is_network_site', // (int|bool) If we think this site is a network or a single blog (1, 0), false if we haven't yet tried to figue it out.
|
35 |
-
'social_links', // (array) The specified links for each social networking site.
|
36 |
-
'identity_crisis_whitelist', // (array) An array of options, each having an array of the values whitelisted for it.
|
37 |
-
'gplus_authors', // (array) The Google+ authorship information for connected users.
|
38 |
-
'last_heartbeat', // (int) The timestamp of the last heartbeat that fired.
|
39 |
-
);
|
40 |
-
}*/
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
|
44 |
-
*
|
45 |
-
* @param string $name Option name
|
46 |
-
* @param mixed $default (optional)
|
47 |
-
*/
|
48 |
-
public static function get_option( $name, $default = false ) {
|
49 |
-
if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
|
50 |
-
return get_option( "jetpack_$name" );
|
51 |
-
} else if ( !in_array( $name, self::get_option_names() ) ) {
|
52 |
-
trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
|
53 |
-
return false;
|
54 |
-
}
|
55 |
-
|
56 |
-
$options = get_option( 'jetpack_options' );
|
57 |
-
if ( is_array( $options ) && isset( $options[$name] ) ) {
|
58 |
-
return $options[$name];
|
59 |
-
}
|
60 |
-
|
61 |
-
return $default;
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
|
66 |
-
*
|
67 |
-
* @param string $name Option name
|
68 |
-
* @param mixed $value Option value
|
69 |
-
*/
|
70 |
-
public static function update_option( $name, $value ) {
|
71 |
-
if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
|
72 |
-
return update_option( "jetpack_$name", $value );
|
73 |
-
} else if ( !in_array( $name, self::get_option_names() ) ) {
|
74 |
-
trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
|
75 |
-
return false;
|
76 |
-
}
|
77 |
-
|
78 |
-
$options = get_option( 'jetpack_options' );
|
79 |
-
if ( !is_array( $options ) ) {
|
80 |
-
$options = array();
|
81 |
-
}
|
82 |
-
|
83 |
-
$options[$name] = $value;
|
84 |
-
|
85 |
-
return update_option( 'jetpack_options', $options );
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
|
90 |
-
*
|
91 |
-
* @param array $array array( option name => option value, ... )
|
92 |
-
*/
|
93 |
-
public static function update_options( $array ) {
|
94 |
-
$names = array_keys( $array );
|
95 |
-
|
96 |
-
foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
|
97 |
-
trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
|
98 |
-
unset( $array[$unknown_name] );
|
99 |
-
}
|
100 |
-
|
101 |
-
foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
|
102 |
-
update_option( "jetpack_$name", $array[$name] );
|
103 |
-
unset( $array[$name] );
|
104 |
-
}
|
105 |
-
|
106 |
-
$options = get_option( 'jetpack_options' );
|
107 |
-
if ( !is_array( $options ) ) {
|
108 |
-
$options = array();
|
109 |
-
}
|
110 |
-
|
111 |
-
return update_option( 'jetpack_options', array_merge( $options, $array ) );
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Deletes the given option. May be passed multiple option names as an array.
|
116 |
-
* Updates jetpack_options and/or deletes jetpack_$name as appropriate.
|
117 |
-
*
|
118 |
-
* @param string|array $names
|
119 |
-
*/
|
120 |
-
public static function delete_option( $names ) {
|
121 |
-
$names = (array) $names;
|
122 |
-
|
123 |
-
foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
|
124 |
-
trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
|
125 |
-
}
|
126 |
-
|
127 |
-
foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
|
128 |
-
delete_option( "jetpack_$name" );
|
129 |
-
}
|
130 |
-
|
131 |
-
$options = get_option( 'jetpack_options' );
|
132 |
-
if ( !is_array( $options ) ) {
|
133 |
-
$options = array();
|
134 |
-
}
|
135 |
-
|
136 |
-
$to_delete = array_intersect( $names, self::get_option_names(), array_keys( $options ) );
|
137 |
-
if ( $to_delete ) {
|
138 |
-
foreach ( $to_delete as $name ) {
|
139 |
-
unset( $options[$name] );
|
140 |
-
}
|
141 |
-
|
142 |
-
return update_option( 'jetpack_options', $options );
|
143 |
-
}
|
144 |
-
|
145 |
-
return true;
|
146 |
-
}
|
147 |
-
|
148 |
-
}
|
149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/leadin-ajax-functions.php
CHANGED
@@ -20,7 +20,7 @@ function leadin_check_merged_contact ()
|
|
20 |
$q = $wpdb->prepare("SELECT hashkey, merged_hashkeys FROM li_leads WHERE merged_hashkeys LIKE '%%%s%%'", like_escape($stale_hash));
|
21 |
$row = $wpdb->get_row($q);
|
22 |
|
23 |
-
if ( isset($row->hashkey) )
|
24 |
{
|
25 |
// One final update to set all the previous pageviews to the new hashkey
|
26 |
$q = $wpdb->prepare("UPDATE li_pageviews SET lead_hashkey = %s WHERE lead_hashkey = %s", $row->hashkey, $stale_hash);
|
@@ -31,10 +31,12 @@ function leadin_check_merged_contact ()
|
|
31 |
$wpdb->query($q);
|
32 |
|
33 |
// Remove the passed hash from the merged hashkeys for the row
|
34 |
-
$merged_hashkeys = explode(',', $row->merged_hashkeys);
|
35 |
-
$merged_hashkeys = leadin_array_delete($merged_hashkeys, "'" . $stale_hash . "'");
|
36 |
|
37 |
-
|
|
|
|
|
|
|
38 |
$wpdb->query($q);
|
39 |
|
40 |
$q = $wpdb->prepare("DELETE FROM li_leads WHERE hashkey LIKE '%%%s%%'", like_escape($stale_hash));
|
@@ -134,9 +136,12 @@ function leadin_insert_form_submission ()
|
|
134 |
$page_url = $_POST['li_url'];
|
135 |
$form_json = $_POST['li_fields'];
|
136 |
$email = $_POST['li_email'];
|
|
|
|
|
|
|
137 |
$submission_type = $_POST['li_submission_type'];
|
138 |
$options = get_option('leadin_options');
|
139 |
-
$li_admin_email = ( $options['li_email'] ) ? $options['li_email'] :
|
140 |
|
141 |
// Check to see if the form_hashkey exists, and if it does, don't run the insert or send the email
|
142 |
$q = $wpdb->prepare("SELECT form_hashkey FROM li_submissions WHERE form_hashkey = %s", $submission_hash);
|
@@ -144,6 +149,7 @@ function leadin_insert_form_submission ()
|
|
144 |
|
145 |
if ( $submission_hash_exists )
|
146 |
{
|
|
|
147 |
return 1;
|
148 |
exit;
|
149 |
}
|
@@ -151,6 +157,7 @@ function leadin_insert_form_submission ()
|
|
151 |
// Don't send the lead email when an administrator is leaving a comment or when the commenter's email is the same as the leadin email
|
152 |
if ( !(current_user_can('administrator') && $submission_type == 'comment') && !(strstr($li_admin_email, $email) && $submission_type == 'comment') )
|
153 |
{
|
|
|
154 |
$q = $wpdb->prepare("SELECT * FROM li_leads WHERE hashkey = %s", $hashkey);
|
155 |
$contact = $wpdb->get_row($q);
|
156 |
|
@@ -158,11 +165,12 @@ function leadin_insert_form_submission ()
|
|
158 |
$q = $wpdb->prepare("SELECT lead_email, hashkey, merged_hashkeys, lead_status FROM li_leads WHERE lead_email = %s AND hashkey != %s", $email, $hashkey);
|
159 |
$existing_contacts = $wpdb->get_results($q);
|
160 |
|
|
|
161 |
$existing_contact_status = 'lead';
|
162 |
|
163 |
// Setup the string for the existing hashkeys
|
164 |
$existing_contact_hashkeys = $contact->merged_hashkeys;
|
165 |
-
if ( $contact->merged_hashkeys )
|
166 |
$existing_contact_hashkeys .= ',';
|
167 |
|
168 |
// Do some merging if the email exists already in the contact table
|
@@ -173,9 +181,11 @@ function leadin_insert_form_submission ()
|
|
173 |
// Start with the existing contact's hashkeys and create a string containg comma-deliminated hashes
|
174 |
$existing_contact_hashkeys .= "'" . $existing_contacts[$i]->hashkey . "'";
|
175 |
|
|
|
176 |
if ( $existing_contacts[$i]->merged_hashkeys )
|
177 |
$existing_contact_hashkeys .= "," . $existing_contacts[$i]->merged_hashkeys;
|
178 |
|
|
|
179 |
if ( $i != count($existing_contacts)-1 )
|
180 |
$existing_contact_hashkeys .= ",";
|
181 |
|
@@ -188,6 +198,12 @@ function leadin_insert_form_submission ()
|
|
188 |
$existing_contact_status = 'subscribe';
|
189 |
}
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
// Update all the previous pageviews to the new hashkey
|
192 |
$q = $wpdb->prepare("UPDATE li_pageviews SET lead_hashkey = %s WHERE lead_hashkey IN ( $existing_contact_hashkeys )", $hashkey);
|
193 |
$wpdb->query($q);
|
@@ -197,7 +213,7 @@ function leadin_insert_form_submission ()
|
|
197 |
$wpdb->query($q);
|
198 |
}
|
199 |
|
200 |
-
// Prevent
|
201 |
$q = $wpdb->prepare("DELETE FROM li_submissions WHERE form_hashkey = %s", $submission_hash);
|
202 |
$wpdb->query($q);
|
203 |
|
@@ -205,12 +221,12 @@ function leadin_insert_form_submission ()
|
|
205 |
$result = $wpdb->insert(
|
206 |
'li_submissions',
|
207 |
array(
|
208 |
-
'form_hashkey'
|
209 |
-
'lead_hashkey'
|
210 |
-
'form_page_title'
|
211 |
-
'form_page_url'
|
212 |
-
'form_fields'
|
213 |
-
'form_type'
|
214 |
),
|
215 |
array(
|
216 |
'%s', '%s', '%s', '%s', '%s', '%s'
|
@@ -244,13 +260,35 @@ function leadin_insert_form_submission ()
|
|
244 |
if ( in_array('mailchimp_list_sync', $active_power_ups) )
|
245 |
{
|
246 |
global $leadin_mailchimp_list_sync_wp;
|
247 |
-
$leadin_mailchimp_list_sync_wp->push_mailchimp_subscriber_to_list($email);
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
}
|
249 |
}
|
250 |
|
251 |
-
|
252 |
-
|
253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
|
255 |
return $rows_updated;
|
256 |
}
|
20 |
$q = $wpdb->prepare("SELECT hashkey, merged_hashkeys FROM li_leads WHERE merged_hashkeys LIKE '%%%s%%'", like_escape($stale_hash));
|
21 |
$row = $wpdb->get_row($q);
|
22 |
|
23 |
+
if ( isset($row->hashkey) && $stale_hash )
|
24 |
{
|
25 |
// One final update to set all the previous pageviews to the new hashkey
|
26 |
$q = $wpdb->prepare("UPDATE li_pageviews SET lead_hashkey = %s WHERE lead_hashkey = %s", $row->hashkey, $stale_hash);
|
31 |
$wpdb->query($q);
|
32 |
|
33 |
// Remove the passed hash from the merged hashkeys for the row
|
34 |
+
$merged_hashkeys = array_unique(array_filter(explode(',', $row->merged_hashkeys)));
|
|
|
35 |
|
36 |
+
// Delete the stale hash from the merged hashkeys array
|
37 |
+
$merged_hashkeys = leadin_array_delete($merged_hashkeys, "'" . $stale_hash . "'");
|
38 |
+
|
39 |
+
$q = $wpdb->prepare("UPDATE li_leads SET merged_hashkeys = %s WHERE hashkey = %s", rtrim(implode(',', $merged_hashkeys), ','), $row->hashkey);
|
40 |
$wpdb->query($q);
|
41 |
|
42 |
$q = $wpdb->prepare("DELETE FROM li_leads WHERE hashkey LIKE '%%%s%%'", like_escape($stale_hash));
|
136 |
$page_url = $_POST['li_url'];
|
137 |
$form_json = $_POST['li_fields'];
|
138 |
$email = $_POST['li_email'];
|
139 |
+
$first_name = $_POST['li_first_name'];
|
140 |
+
$last_name = $_POST['li_last_name'];
|
141 |
+
$phone = $_POST['li_phone'];
|
142 |
$submission_type = $_POST['li_submission_type'];
|
143 |
$options = get_option('leadin_options');
|
144 |
+
$li_admin_email = ( isset($options['li_email']) ) ? $options['li_email'] : '';
|
145 |
|
146 |
// Check to see if the form_hashkey exists, and if it does, don't run the insert or send the email
|
147 |
$q = $wpdb->prepare("SELECT form_hashkey FROM li_submissions WHERE form_hashkey = %s", $submission_hash);
|
149 |
|
150 |
if ( $submission_hash_exists )
|
151 |
{
|
152 |
+
// The form has been inserted successful so send back a trigger to clear the cache cooke on the front end
|
153 |
return 1;
|
154 |
exit;
|
155 |
}
|
157 |
// Don't send the lead email when an administrator is leaving a comment or when the commenter's email is the same as the leadin email
|
158 |
if ( !(current_user_can('administrator') && $submission_type == 'comment') && !(strstr($li_admin_email, $email) && $submission_type == 'comment') )
|
159 |
{
|
160 |
+
// Get the contact row tied to hashkey
|
161 |
$q = $wpdb->prepare("SELECT * FROM li_leads WHERE hashkey = %s", $hashkey);
|
162 |
$contact = $wpdb->get_row($q);
|
163 |
|
165 |
$q = $wpdb->prepare("SELECT lead_email, hashkey, merged_hashkeys, lead_status FROM li_leads WHERE lead_email = %s AND hashkey != %s", $email, $hashkey);
|
166 |
$existing_contacts = $wpdb->get_results($q);
|
167 |
|
168 |
+
// Set the default contact life cycle status to lead
|
169 |
$existing_contact_status = 'lead';
|
170 |
|
171 |
// Setup the string for the existing hashkeys
|
172 |
$existing_contact_hashkeys = $contact->merged_hashkeys;
|
173 |
+
if ( $contact->merged_hashkeys && count($existing_contacts) )
|
174 |
$existing_contact_hashkeys .= ',';
|
175 |
|
176 |
// Do some merging if the email exists already in the contact table
|
181 |
// Start with the existing contact's hashkeys and create a string containg comma-deliminated hashes
|
182 |
$existing_contact_hashkeys .= "'" . $existing_contacts[$i]->hashkey . "'";
|
183 |
|
184 |
+
// Add any of those existing contact row's merged hashkeys
|
185 |
if ( $existing_contacts[$i]->merged_hashkeys )
|
186 |
$existing_contact_hashkeys .= "," . $existing_contacts[$i]->merged_hashkeys;
|
187 |
|
188 |
+
// Add a comma delimiter
|
189 |
if ( $i != count($existing_contacts)-1 )
|
190 |
$existing_contact_hashkeys .= ",";
|
191 |
|
198 |
$existing_contact_status = 'subscribe';
|
199 |
}
|
200 |
|
201 |
+
// Remove duplicates from the array
|
202 |
+
$existing_contact_hashkeys = implode(',', array_unique(explode(',', $existing_contact_hashkeys)));
|
203 |
+
|
204 |
+
// Safety precaution - trim any trailing commas
|
205 |
+
$existing_contact_hashkeys = rtrim($existing_contact_hashkeys, ',');
|
206 |
+
|
207 |
// Update all the previous pageviews to the new hashkey
|
208 |
$q = $wpdb->prepare("UPDATE li_pageviews SET lead_hashkey = %s WHERE lead_hashkey IN ( $existing_contact_hashkeys )", $hashkey);
|
209 |
$wpdb->query($q);
|
213 |
$wpdb->query($q);
|
214 |
}
|
215 |
|
216 |
+
// Prevent duplicate form submission entries by deleting existing submissions if it didn't finish the process before the web page refreshed
|
217 |
$q = $wpdb->prepare("DELETE FROM li_submissions WHERE form_hashkey = %s", $submission_hash);
|
218 |
$wpdb->query($q);
|
219 |
|
221 |
$result = $wpdb->insert(
|
222 |
'li_submissions',
|
223 |
array(
|
224 |
+
'form_hashkey' => $submission_hash,
|
225 |
+
'lead_hashkey' => $hashkey,
|
226 |
+
'form_page_title' => $page_title,
|
227 |
+
'form_page_url' => $page_url,
|
228 |
+
'form_fields' => $form_json,
|
229 |
+
'form_type' => $submission_type
|
230 |
),
|
231 |
array(
|
232 |
'%s', '%s', '%s', '%s', '%s', '%s'
|
260 |
if ( in_array('mailchimp_list_sync', $active_power_ups) )
|
261 |
{
|
262 |
global $leadin_mailchimp_list_sync_wp;
|
263 |
+
$leadin_mailchimp_list_sync_wp->push_mailchimp_subscriber_to_list($email, $first_name, $last_name, $phone);
|
264 |
+
}
|
265 |
+
|
266 |
+
if ( in_array('constant_contact_list_sync', $active_power_ups) )
|
267 |
+
{
|
268 |
+
global $leadin_constant_contact_list_sync_wp;
|
269 |
+
$leadin_constant_contact_list_sync_wp->push_constant_contact_subscriber_to_list($email, $first_name, $last_name, $phone);
|
270 |
}
|
271 |
}
|
272 |
|
273 |
+
if ( $contact_status == "comment" )
|
274 |
+
leadin_track_plugin_activity("New comment");
|
275 |
+
else if ( $contact_status == "subscribe" )
|
276 |
+
leadin_track_plugin_activity("New subscriber");
|
277 |
+
else
|
278 |
+
{
|
279 |
+
$history = $this->get_lead_history($hashkey);
|
280 |
+
if ( $history->new_contact )
|
281 |
+
leadin_track_plugin_activity("New lead");
|
282 |
+
else
|
283 |
+
leadin_track_plugin_activity("Returning lead");
|
284 |
+
}
|
285 |
+
|
286 |
+
if ( $li_admin_email )
|
287 |
+
{
|
288 |
+
// Send the contact email
|
289 |
+
$li_emailer = new LI_Emailer();
|
290 |
+
$li_emailer->send_new_lead_email($hashkey);
|
291 |
+
}
|
292 |
|
293 |
return $rows_updated;
|
294 |
}
|
inc/leadin-functions.php
CHANGED
@@ -113,7 +113,7 @@ function leadin_get_current_user ()
|
|
113 |
function leadin_register_user ()
|
114 |
{
|
115 |
$leadin_user = leadin_get_current_user();
|
116 |
-
$mp =
|
117 |
|
118 |
// @push mixpanel event for updated email
|
119 |
$mp->identify($leadin_user['user_id']);
|
@@ -193,7 +193,7 @@ function leadin_track_plugin_activity ( $activity_desc )
|
|
193 |
get_currentuserinfo();
|
194 |
$user_id = md5(get_bloginfo('wpurl'));
|
195 |
|
196 |
-
$mp =
|
197 |
$mp->track($activity_desc, array("distinct_id" => $user_id, '$wp-url' => get_bloginfo('wpurl'), '$wp-version' => $wp_version, '$li-version' => LEADIN_PLUGIN_VERSION));
|
198 |
|
199 |
return true;
|
@@ -247,4 +247,70 @@ function leadin_get_value_by_key ( $key_value, $array )
|
|
247 |
|
248 |
return null;
|
249 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
?>
|
113 |
function leadin_register_user ()
|
114 |
{
|
115 |
$leadin_user = leadin_get_current_user();
|
116 |
+
$mp = LI_Mixpanel::getInstance(MIXPANEL_PROJECT_TOKEN);
|
117 |
|
118 |
// @push mixpanel event for updated email
|
119 |
$mp->identify($leadin_user['user_id']);
|
193 |
get_currentuserinfo();
|
194 |
$user_id = md5(get_bloginfo('wpurl'));
|
195 |
|
196 |
+
$mp = LI_Mixpanel::getInstance(MIXPANEL_PROJECT_TOKEN);
|
197 |
$mp->track($activity_desc, array("distinct_id" => $user_id, '$wp-url' => get_bloginfo('wpurl'), '$wp-version' => $wp_version, '$li-version' => LEADIN_PLUGIN_VERSION));
|
198 |
|
199 |
return true;
|
247 |
|
248 |
return null;
|
249 |
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Data recovery algorithm for 0.7.2 upgrade
|
253 |
+
*
|
254 |
+
*/
|
255 |
+
function leadin_recover_contact_data ()
|
256 |
+
{
|
257 |
+
global $wpdb;
|
258 |
+
|
259 |
+
$q = $wpdb->prepare("SELECT * FROM li_submissions WHERE form_fields LIKE '%%%s%%' AND form_fields LIKE '%%%s%%'", '@', '.');
|
260 |
+
$submissions = $wpdb->get_results($q);
|
261 |
+
|
262 |
+
if ( count($submissions) )
|
263 |
+
{
|
264 |
+
foreach ( $submissions as $submission )
|
265 |
+
{
|
266 |
+
$json = json_decode(stripslashes($submission->form_fields), TRUE);
|
267 |
+
|
268 |
+
foreach ( $json as $object )
|
269 |
+
{
|
270 |
+
if ( strstr($object['value'], '@') && strstr($object['value'], '@') && strlen($object['value']) <= 254 )
|
271 |
+
{
|
272 |
+
// check to see if the contact exists and if it does, skip the data recovery
|
273 |
+
$q = $wpdb->prepare("SELECT lead_email FROM li_leads WHERE lead_email = %s", $object['value']);
|
274 |
+
$exists = $wpdb->get_var($q);
|
275 |
+
|
276 |
+
if ( $exists )
|
277 |
+
continue;
|
278 |
+
|
279 |
+
// get the original data
|
280 |
+
$q = $wpdb->prepare("SELECT pageview_date, pageview_source FROM li_pageviews WHERE lead_hashkey = %s ORDER BY pageview_date ASC LIMIT 1", $submission->lead_hashkey);
|
281 |
+
$first_pageview = $wpdb->get_row($q);
|
282 |
+
|
283 |
+
// recreate the contact
|
284 |
+
$q = $wpdb->prepare("INSERT INTO li_leads ( lead_date, hashkey, lead_source, lead_email, lead_status ) VALUES ( %s, %s, %s, %s, %s )",
|
285 |
+
( $first_pageview->pageview_date ? $first_pageview->pageview_date : $submission->form_date),
|
286 |
+
$submission->lead_hashkey,
|
287 |
+
( $first_pageview->pageview_source ? $first_pageview->pageview_source : ''),
|
288 |
+
$object['value'],
|
289 |
+
$submission->form_type
|
290 |
+
);
|
291 |
+
|
292 |
+
$wpdb->query($q);
|
293 |
+
}
|
294 |
+
}
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
leadin_update_option('leadin_options', 'data_recovered', 1);
|
299 |
+
}
|
300 |
+
|
301 |
+
function sort_power_ups ( $power_ups, $ordered_power_ups )
|
302 |
+
{
|
303 |
+
$ordered = array();
|
304 |
+
$i = 0;
|
305 |
+
foreach ( $ordered_power_ups as $key )
|
306 |
+
{
|
307 |
+
if ( in_array($key, $power_ups) )
|
308 |
+
{
|
309 |
+
array_push($ordered, $key);
|
310 |
+
$i++;
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
return $ordered;
|
315 |
+
}
|
316 |
?>
|
leadin.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: LeadIn
|
4 |
Plugin URI: http://leadin.com
|
5 |
Description: LeadIn is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
|
6 |
-
Version: 0.
|
7 |
Author: Andy Cook, Nelson Joyce
|
8 |
Author URI: http://leadin.com
|
9 |
License: GPL2
|
@@ -26,7 +26,7 @@ if ( !defined('LEADIN_DB_VERSION') )
|
|
26 |
define('LEADIN_DB_VERSION', '0.6.2');
|
27 |
|
28 |
if ( !defined('LEADIN_PLUGIN_VERSION') )
|
29 |
-
define('LEADIN_PLUGIN_VERSION', '0.
|
30 |
|
31 |
if ( !defined('MIXPANEL_PROJECT_TOKEN') )
|
32 |
define('MIXPANEL_PROJECT_TOKEN', 'a9615503ec58a6bce2c646a58390eac1');
|
@@ -43,7 +43,8 @@ require_once(LEADIN_PLUGIN_DIR . '/inc/leadin-functions.php');
|
|
43 |
require_once(LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php');
|
44 |
require_once(LEADIN_PLUGIN_DIR . '/power-ups/contacts.php');
|
45 |
require_once(LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-list-sync.php');
|
46 |
-
require_once(LEADIN_PLUGIN_DIR . '/
|
|
|
47 |
|
48 |
//=============================================
|
49 |
// WPLeadIn Class
|
@@ -88,11 +89,12 @@ class WPLeadIn {
|
|
88 |
if ( ($li_options['li_installed'] != 1) || (!is_array($li_options)) )
|
89 |
{
|
90 |
$opt = array(
|
91 |
-
'li_installed'
|
92 |
-
'li_db_version'
|
93 |
-
'li_email'
|
94 |
-
'onboarding_complete'
|
95 |
-
'ignore_settings_popup'
|
|
|
96 |
);
|
97 |
|
98 |
update_option('leadin_options', $opt);
|
@@ -218,6 +220,12 @@ class WPLeadIn {
|
|
218 |
update_option('leadin_active_power_ups', serialize($auto_activate));
|
219 |
}
|
220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
// Set the database version if it doesn't exist
|
222 |
if ( isset($li_options['li_db_version']) )
|
223 |
{
|
@@ -391,6 +399,10 @@ class WPLeadIn {
|
|
391 |
$files[] = $file;
|
392 |
}
|
393 |
|
|
|
|
|
|
|
|
|
394 |
closedir( $dir );
|
395 |
|
396 |
return $files;
|
@@ -399,7 +411,7 @@ class WPLeadIn {
|
|
399 |
/**
|
400 |
* Check whether or not a LeadIn power-up is active.
|
401 |
*
|
402 |
-
* @param string $power_up The slug of a
|
403 |
* @return bool
|
404 |
*
|
405 |
* @static
|
3 |
Plugin Name: LeadIn
|
4 |
Plugin URI: http://leadin.com
|
5 |
Description: LeadIn is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
|
6 |
+
Version: 0.8.2
|
7 |
Author: Andy Cook, Nelson Joyce
|
8 |
Author URI: http://leadin.com
|
9 |
License: GPL2
|
26 |
define('LEADIN_DB_VERSION', '0.6.2');
|
27 |
|
28 |
if ( !defined('LEADIN_PLUGIN_VERSION') )
|
29 |
+
define('LEADIN_PLUGIN_VERSION', '0.8.2');
|
30 |
|
31 |
if ( !defined('MIXPANEL_PROJECT_TOKEN') )
|
32 |
define('MIXPANEL_PROJECT_TOKEN', 'a9615503ec58a6bce2c646a58390eac1');
|
43 |
require_once(LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php');
|
44 |
require_once(LEADIN_PLUGIN_DIR . '/power-ups/contacts.php');
|
45 |
require_once(LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-list-sync.php');
|
46 |
+
require_once(LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-list-sync.php');
|
47 |
+
require_once(LEADIN_PLUGIN_DIR . '/lib/mixpanel/LI_Mixpanel.php');
|
48 |
|
49 |
//=============================================
|
50 |
// WPLeadIn Class
|
89 |
if ( ($li_options['li_installed'] != 1) || (!is_array($li_options)) )
|
90 |
{
|
91 |
$opt = array(
|
92 |
+
'li_installed' => 1,
|
93 |
+
'li_db_version' => LEADIN_DB_VERSION,
|
94 |
+
'li_email' => get_bloginfo('admin_email'),
|
95 |
+
'onboarding_complete' => 0,
|
96 |
+
'ignore_settings_popup' => 0,
|
97 |
+
'data_recovered' => 1
|
98 |
);
|
99 |
|
100 |
update_option('leadin_options', $opt);
|
220 |
update_option('leadin_active_power_ups', serialize($auto_activate));
|
221 |
}
|
222 |
|
223 |
+
// 0.7.2 bug fix - data recovery algorithm for deleted contacts
|
224 |
+
if ( ! isset($li_options['data_recovered']) )
|
225 |
+
{
|
226 |
+
leadin_recover_contact_data();
|
227 |
+
}
|
228 |
+
|
229 |
// Set the database version if it doesn't exist
|
230 |
if ( isset($li_options['li_db_version']) )
|
231 |
{
|
399 |
$files[] = $file;
|
400 |
}
|
401 |
|
402 |
+
$files = sort_power_ups($files, array(
|
403 |
+
LEADIN_PLUGIN_DIR . '/power-ups/contacts' . '.php', LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget' . '.php', LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-list-sync' . '.php', LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-list-sync' . '.php'
|
404 |
+
));
|
405 |
+
|
406 |
closedir( $dir );
|
407 |
|
408 |
return $files;
|
411 |
/**
|
412 |
* Check whether or not a LeadIn power-up is active.
|
413 |
*
|
414 |
+
* @param string $power_up The slug of a power-up
|
415 |
* @return bool
|
416 |
*
|
417 |
* @static
|
lib/mixpanel/Base/LI_MixpanelBase.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
9 |
+
|
10 |
+
|
11 |
+
class LI_Base_MixpanelBase {
|
12 |
+
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Default options that can be overridden via the $options constructor arg
|
16 |
+
* @var array
|
17 |
+
*/
|
18 |
+
private $_defaults = array(
|
19 |
+
"max_batch_size" => 50, // the max batch size Mixpanel will accept is 50,
|
20 |
+
"max_queue_size" => 1000, // the max num of items to hold in memory before flushing
|
21 |
+
"debug" => false, // enable/disable debug mode
|
22 |
+
"consumer" => "curl", // which consumer to use
|
23 |
+
"host" => "api.mixpanel.com", // the host name for api calls
|
24 |
+
"events_endpoint" => "/track", // host relative endpoint for events
|
25 |
+
"people_endpoint" => "/engage", // host relative endpoint for people updates
|
26 |
+
"use_ssl" => true, // use ssl when available
|
27 |
+
"error_callback" => null // callback to use on consumption failures
|
28 |
+
);
|
29 |
+
|
30 |
+
|
31 |
+
/**
|
32 |
+
* An array of options to be used by the Mixpanel library.
|
33 |
+
* @var array
|
34 |
+
*/
|
35 |
+
protected $_options = array();
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Construct a new MixpanelBase object and merge custom options with defaults
|
40 |
+
* @param array $options
|
41 |
+
*/
|
42 |
+
public function __construct($options = array()) {
|
43 |
+
$options = array_merge($this->_defaults, $options);
|
44 |
+
$this->_options = $options;
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Log a message to PHP's error log
|
50 |
+
* @param $msg
|
51 |
+
*/
|
52 |
+
protected function _log($msg) {
|
53 |
+
$arr = debug_backtrace();
|
54 |
+
$class = $arr[0]['class'];
|
55 |
+
$line = $arr[0]['line'];
|
56 |
+
error_log ( "[ $class - line $line ] : " . $msg );
|
57 |
+
}
|
58 |
+
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Returns true if in debug mode, false if in production mode
|
62 |
+
* @return bool
|
63 |
+
*/
|
64 |
+
protected function _debug() {
|
65 |
+
return array_key_exists("debug", $this->_options) && $this->_options["debug"] == true;
|
66 |
+
}
|
67 |
+
|
68 |
+
}
|
lib/mixpanel/Base/MixpanelBase.php
CHANGED
@@ -1,10 +1,15 @@
|
|
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 |
|
1 |
<?php
|
2 |
|
3 |
+
namespace LeadIn;
|
4 |
+
|
5 |
/**
|
6 |
* This a Base class which all Mixpanel classes extend from to provide some very basic
|
7 |
* debugging and logging functionality. It also serves to persist $_options across the library.
|
8 |
*
|
9 |
*/
|
10 |
+
|
11 |
+
|
12 |
+
|
13 |
class Base_MixpanelBase {
|
14 |
|
15 |
|
lib/mixpanel/ConsumerStrategies/AbstractConsumer.php
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
|
3 |
|
4 |
/**
|
1 |
<?php
|
2 |
+
namespace LeadIn;
|
3 |
+
|
4 |
require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
|
5 |
|
6 |
/**
|
lib/mixpanel/ConsumerStrategies/CurlConsumer.php
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
3 |
|
4 |
/**
|
1 |
<?php
|
2 |
+
namespace LeadIn;
|
3 |
+
|
4 |
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
5 |
|
6 |
/**
|
lib/mixpanel/ConsumerStrategies/FileConsumer.php
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
3 |
/**
|
4 |
* Consumes messages and writes them to a file
|
1 |
<?php
|
2 |
+
namespace LeadIn;
|
3 |
+
|
4 |
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
5 |
/**
|
6 |
* Consumes messages and writes them to a file
|
lib/mixpanel/ConsumerStrategies/LI_AbstractConsumer.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__) . "/../Base/LI_MixpanelBase.php");
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Provides some base methods for use by a Consumer implementation
|
7 |
+
*/
|
8 |
+
abstract class LI_ConsumerStrategies_AbstractConsumer extends LI_Base_MixpanelBase {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Creates a new AbstractConsumer
|
12 |
+
* @param array $options
|
13 |
+
*/
|
14 |
+
function __construct($options = array()) {
|
15 |
+
|
16 |
+
parent::__construct($options);
|
17 |
+
|
18 |
+
if ($this->_debug()) {
|
19 |
+
$this->_log("Instantiated new Consumer");
|
20 |
+
}
|
21 |
+
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Encode an array to be persisted
|
26 |
+
* @param array $params
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
+
protected function _encode($params) {
|
30 |
+
return base64_encode(json_encode($params));
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Handles errors that occur in a consumer
|
35 |
+
* @param $code
|
36 |
+
* @param $msg
|
37 |
+
*/
|
38 |
+
protected function _handleError($code, $msg) {
|
39 |
+
if (isset($this->_options['error_callback'])) {
|
40 |
+
$handler = $this->_options['error_callback'];
|
41 |
+
call_user_func($handler, $code, $msg);
|
42 |
+
}
|
43 |
+
|
44 |
+
if ($this->_debug()) {
|
45 |
+
$arr = debug_backtrace();
|
46 |
+
$class = get_class($arr[0]['object']);
|
47 |
+
$line = $arr[0]['line'];
|
48 |
+
error_log ( "[ $class - line $line ] : " . print_r($msg, true) );
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Persist a batch of messages in whatever way the implementer sees fit
|
54 |
+
* @param array $batch an array of messages to consume
|
55 |
+
* @return boolean success or fail
|
56 |
+
*/
|
57 |
+
abstract function persist($batch);
|
58 |
+
}
|
lib/mixpanel/ConsumerStrategies/LI_CurlConsumer.php
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Consumes messages and sends them to a host/endpoint using cURL
|
7 |
+
*/
|
8 |
+
class LI_ConsumerStrategies_CurlConsumer extends LI_ConsumerStrategies_AbstractConsumer {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var string the host to connect to (e.g. api.mixpanel.com)
|
12 |
+
*/
|
13 |
+
protected $_host;
|
14 |
+
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string the host-relative endpoint to write to (e.g. /engage)
|
18 |
+
*/
|
19 |
+
protected $_endpoint;
|
20 |
+
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var int connect_timeout The number of seconds to wait while trying to connect. Default is 5 seconds.
|
24 |
+
*/
|
25 |
+
protected $_connect_timeout;
|
26 |
+
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var int timeout The maximum number of seconds to allow cURL call to execute. Default is 30 seconds.
|
30 |
+
*/
|
31 |
+
protected $_timeout;
|
32 |
+
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string the protocol to use for the cURL connection
|
36 |
+
*/
|
37 |
+
protected $_protocol;
|
38 |
+
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @var bool|null true to fork the cURL process (using exec) or false to use PHP's cURL extension. false by default
|
42 |
+
*/
|
43 |
+
protected $_fork = null;
|
44 |
+
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Creates a new LI_CurlConsumer and assigns properties from the $options array
|
48 |
+
* @param array $options
|
49 |
+
* @throws Exception
|
50 |
+
*/
|
51 |
+
function __construct($options) {
|
52 |
+
parent::__construct($options);
|
53 |
+
|
54 |
+
$this->_host = $options['host'];
|
55 |
+
$this->_endpoint = $options['endpoint'];
|
56 |
+
$this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
|
57 |
+
$this->_timeout = array_key_exists('timeout', $options) ? $options['timeout'] : 30;
|
58 |
+
$this->_protocol = array_key_exists('use_ssl', $options) && $options['use_ssl'] == true ? "https" : "http";
|
59 |
+
$this->_fork = array_key_exists('fork', $options) ? ($options['fork'] == true) : false;
|
60 |
+
|
61 |
+
// ensure the environment is workable for the given settings
|
62 |
+
if ($this->_fork == true) {
|
63 |
+
$exists = function_exists('exec');
|
64 |
+
if (!$exists) {
|
65 |
+
throw new Exception('The "exec" function must exist to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
|
66 |
+
}
|
67 |
+
$disabled = explode(', ', ini_get('disable_functions'));
|
68 |
+
$enabled = !in_array('exec', $disabled);
|
69 |
+
if (!$enabled) {
|
70 |
+
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.');
|
71 |
+
}
|
72 |
+
} else {
|
73 |
+
if (!function_exists('curl_init')) {
|
74 |
+
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.');
|
75 |
+
}
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Write to the given host/endpoint using either a forked cURL process or using PHP's cURL extension
|
82 |
+
* @param array $batch
|
83 |
+
* @return bool
|
84 |
+
*/
|
85 |
+
public function persist($batch) {
|
86 |
+
if (count($batch) > 0) {
|
87 |
+
$data = "data=" . $this->_encode($batch);
|
88 |
+
$url = $this->_protocol . "://" . $this->_host . $this->_endpoint;
|
89 |
+
if ($this->_fork) {
|
90 |
+
return $this->_execute_forked($url, $data);
|
91 |
+
} else {
|
92 |
+
return $this->_execute($url, $data);
|
93 |
+
}
|
94 |
+
} else {
|
95 |
+
return true;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Write using the cURL php extension
|
102 |
+
* @param $url
|
103 |
+
* @param $data
|
104 |
+
* @return bool
|
105 |
+
*/
|
106 |
+
protected function _execute($url, $data) {
|
107 |
+
if ($this->_debug()) {
|
108 |
+
$this->_log("Making blocking cURL call to $url");
|
109 |
+
}
|
110 |
+
|
111 |
+
$ch = curl_init();
|
112 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
113 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
114 |
+
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_connect_timeout);
|
115 |
+
curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);
|
116 |
+
curl_setopt($ch, CURLOPT_POST, 1);
|
117 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
118 |
+
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
119 |
+
$response = curl_exec($ch);
|
120 |
+
if (false === $response) {
|
121 |
+
$curl_error = curl_error($ch);
|
122 |
+
$curl_errno = curl_errno($ch);
|
123 |
+
curl_close($ch);
|
124 |
+
$this->_handleError($curl_errno, $curl_error);
|
125 |
+
return false;
|
126 |
+
} else {
|
127 |
+
curl_close($ch);
|
128 |
+
if (trim($response) == "1") {
|
129 |
+
return true;
|
130 |
+
} else {
|
131 |
+
$this->_handleError(0, $response);
|
132 |
+
return false;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Write using a forked cURL process
|
140 |
+
* @param $url
|
141 |
+
* @param $data
|
142 |
+
* @return bool
|
143 |
+
*/
|
144 |
+
protected function _execute_forked($url, $data) {
|
145 |
+
|
146 |
+
if ($this->_debug()) {
|
147 |
+
$this->_log("Making forked cURL call to $url");
|
148 |
+
}
|
149 |
+
|
150 |
+
$exec = 'curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d ' . $data . ' "' . $url . '"';
|
151 |
+
|
152 |
+
if(!$this->_debug()) {
|
153 |
+
$exec .= " >/dev/null 2>&1 &";
|
154 |
+
}
|
155 |
+
|
156 |
+
exec($exec, $output, $return_var);
|
157 |
+
|
158 |
+
if ($return_var != 0) {
|
159 |
+
$this->_handleError($return_var, $output);
|
160 |
+
}
|
161 |
+
|
162 |
+
return $return_var == 0;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* @return int
|
167 |
+
*/
|
168 |
+
public function getConnectTimeout()
|
169 |
+
{
|
170 |
+
return $this->_connect_timeout;
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* @return string
|
175 |
+
*/
|
176 |
+
public function getEndpoint()
|
177 |
+
{
|
178 |
+
return $this->_endpoint;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* @return bool|null
|
183 |
+
*/
|
184 |
+
public function getFork()
|
185 |
+
{
|
186 |
+
return $this->_fork;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* @return string
|
191 |
+
*/
|
192 |
+
public function getHost()
|
193 |
+
{
|
194 |
+
return $this->_host;
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* @return array
|
199 |
+
*/
|
200 |
+
public function getOptions()
|
201 |
+
{
|
202 |
+
return $this->_options;
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* @return string
|
207 |
+
*/
|
208 |
+
public function getProtocol()
|
209 |
+
{
|
210 |
+
return $this->_protocol;
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* @return int
|
215 |
+
*/
|
216 |
+
public function getTimeout()
|
217 |
+
{
|
218 |
+
return $this->_timeout;
|
219 |
+
}
|
220 |
+
|
221 |
+
|
222 |
+
}
|
lib/mixpanel/ConsumerStrategies/LI_FileConsumer.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
|
4 |
+
/**
|
5 |
+
* Consumes messages and writes them to a file
|
6 |
+
*/
|
7 |
+
class ConsumerStrategies_LI_FileConsumer extends LI_ConsumerStrategies_AbstractConsumer {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @var string path to a file that we want to write the messages to
|
11 |
+
*/
|
12 |
+
private $_file;
|
13 |
+
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Creates a new LI_FileConsumer and assigns properties from the $options array
|
17 |
+
* @param array $options
|
18 |
+
*/
|
19 |
+
function __construct($options) {
|
20 |
+
parent::__construct($options);
|
21 |
+
|
22 |
+
// what file to write to?
|
23 |
+
$this->_file = array_key_exists("file", $options) ? $options['file'] : dirname(__FILE__)."/../../messages.txt";
|
24 |
+
}
|
25 |
+
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Append $batch to a file
|
29 |
+
* @param array $batch
|
30 |
+
* @return bool
|
31 |
+
*/
|
32 |
+
public function persist($batch) {
|
33 |
+
if (count($batch) > 0) {
|
34 |
+
return file_put_contents($this->_file, json_encode($batch)."\n", FILE_APPEND | LOCK_EX) !== false;
|
35 |
+
} else {
|
36 |
+
return true;
|
37 |
+
}
|
38 |
+
}
|
39 |
+
}
|
lib/mixpanel/ConsumerStrategies/LI_SocketConsumer.php
ADDED
@@ -0,0 +1,309 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
35 |
+
require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Consumes messages and writes them to host/endpoint using a persistent socket
|
39 |
+
*/
|
40 |
+
class LI_ConsumerStrategies_SocketConsumer extends LI_ConsumerStrategies_AbstractConsumer {
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @var string the host to connect to (e.g. api.mixpanel.com)
|
44 |
+
*/
|
45 |
+
private $_host;
|
46 |
+
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @var string the host-relative endpoint to write to (e.g. /engage)
|
50 |
+
*/
|
51 |
+
private $_endpoint;
|
52 |
+
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @var int connect_timeout the socket connection timeout in seconds
|
56 |
+
*/
|
57 |
+
private $_connect_timeout;
|
58 |
+
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @var string the protocol to use for the socket connection
|
62 |
+
*/
|
63 |
+
private $_protocol;
|
64 |
+
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @var resource holds the socket resource
|
68 |
+
*/
|
69 |
+
private $_socket;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* @var bool whether or not to wait for a response
|
73 |
+
*/
|
74 |
+
private $_async;
|
75 |
+
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Creates a new SocketConsumer and assigns properties from the $options array
|
79 |
+
* @param array $options
|
80 |
+
*/
|
81 |
+
public function __construct($options = array()) {
|
82 |
+
parent::__construct($options);
|
83 |
+
|
84 |
+
|
85 |
+
$this->_host = $options['host'];
|
86 |
+
$this->_endpoint = $options['endpoint'];
|
87 |
+
$this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
|
88 |
+
$this->_async = array_key_exists('async', $options) && $options['async'] === false ? false : true;
|
89 |
+
|
90 |
+
if (array_key_exists('use_ssl', $options) && $options['use_ssl'] == true) {
|
91 |
+
$this->_protocol = "ssl";
|
92 |
+
$this->_port = 443;
|
93 |
+
} else {
|
94 |
+
$this->_protocol = "tcp";
|
95 |
+
$this->_port = 80;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Write using a persistent socket connection.
|
102 |
+
* @param array $batch
|
103 |
+
* @return bool
|
104 |
+
*/
|
105 |
+
public function persist($batch) {
|
106 |
+
|
107 |
+
$socket = $this->_getSocket();
|
108 |
+
if (!is_resource($socket)) {
|
109 |
+
return false;
|
110 |
+
}
|
111 |
+
|
112 |
+
$data = "data=".$this->_encode($batch);
|
113 |
+
|
114 |
+
$body = "";
|
115 |
+
$body.= "POST ".$this->_endpoint." HTTP/1.1\r\n";
|
116 |
+
$body.= "Host: " . $this->_host . "\r\n";
|
117 |
+
$body.= "Content-Type: application/x-www-form-urlencoded\r\n";
|
118 |
+
$body.= "Accept: application/json\r\n";
|
119 |
+
$body.= "Content-length: " . strlen($data) . "\r\n";
|
120 |
+
$body.= "\r\n";
|
121 |
+
$body.= $data;
|
122 |
+
|
123 |
+
return $this->_write($socket, $body);
|
124 |
+
}
|
125 |
+
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Return cached socket if open or create a new persistent socket
|
129 |
+
* @return bool|resource
|
130 |
+
*/
|
131 |
+
private function _getSocket() {
|
132 |
+
if(is_resource($this->_socket)) {
|
133 |
+
|
134 |
+
if ($this->_debug()) {
|
135 |
+
$this->_log("Using existing socket");
|
136 |
+
}
|
137 |
+
|
138 |
+
return $this->_socket;
|
139 |
+
} else {
|
140 |
+
|
141 |
+
if ($this->_debug()) {
|
142 |
+
$this->_log("Creating new socket at ".time());
|
143 |
+
}
|
144 |
+
|
145 |
+
return $this->_createSocket();
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Attempt to open a new socket connection, cache it, and return the resource
|
151 |
+
* @param bool $retry
|
152 |
+
* @return bool|resource
|
153 |
+
*/
|
154 |
+
private function _createSocket($retry = true) {
|
155 |
+
try {
|
156 |
+
$socket = pfsockopen($this->_protocol . "://" . $this->_host, $this->_port, $err_no, $err_msg, $this->_connect_timeout);
|
157 |
+
|
158 |
+
if ($this->_debug()) {
|
159 |
+
$this->_log("Opening socket connection to " . $this->_protocol . "://" . $this->_host . ":" . $this->_port);
|
160 |
+
}
|
161 |
+
|
162 |
+
if ($err_no != 0) {
|
163 |
+
$this->_handleError($err_no, $err_msg);
|
164 |
+
return $retry == true ? $this->_createSocket(false) : false;
|
165 |
+
} else {
|
166 |
+
// cache the socket
|
167 |
+
$this->_socket = $socket;
|
168 |
+
return $socket;
|
169 |
+
}
|
170 |
+
|
171 |
+
} catch (Exception $e) {
|
172 |
+
$this->_handleError($e->getCode(), $e->getMessage());
|
173 |
+
return $retry == true ? $this->_createSocket(false) : false;
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Attempt to close and dereference a socket resource
|
179 |
+
*/
|
180 |
+
private function _destroySocket() {
|
181 |
+
$socket = $this->_socket;
|
182 |
+
$this->_socket = null;
|
183 |
+
fclose($socket);
|
184 |
+
}
|
185 |
+
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Write $data through the given $socket
|
189 |
+
* @param $socket
|
190 |
+
* @param $data
|
191 |
+
* @param bool $retry
|
192 |
+
* @return bool
|
193 |
+
*/
|
194 |
+
private function _write($socket, $data, $retry = true) {
|
195 |
+
|
196 |
+
$bytes_sent = 0;
|
197 |
+
$bytes_total = strlen($data);
|
198 |
+
$socket_closed = false;
|
199 |
+
$success = true;
|
200 |
+
$max_bytes_per_write = 8192;
|
201 |
+
|
202 |
+
// if we have no data to write just return true
|
203 |
+
if ($bytes_total == 0) {
|
204 |
+
return true;
|
205 |
+
}
|
206 |
+
|
207 |
+
// try to write the data
|
208 |
+
while (!$socket_closed && $bytes_sent < $bytes_total) {
|
209 |
+
|
210 |
+
try {
|
211 |
+
$bytes = fwrite($socket, $data, $max_bytes_per_write);
|
212 |
+
|
213 |
+
if ($this->_debug()) {
|
214 |
+
$this->_log("Socket wrote ".$bytes." bytes");
|
215 |
+
}
|
216 |
+
|
217 |
+
// if we actually wrote data, then remove the written portion from $data left to write
|
218 |
+
if ($bytes > 0) {
|
219 |
+
$data = substr($data, $max_bytes_per_write);
|
220 |
+
}
|
221 |
+
|
222 |
+
} catch (Exception $e) {
|
223 |
+
$this->_handleError($e->getCode(), $e->getMessage());
|
224 |
+
$socket_closed = true;
|
225 |
+
}
|
226 |
+
|
227 |
+
if (isset($bytes) && $bytes) {
|
228 |
+
$bytes_sent += $bytes;
|
229 |
+
} else {
|
230 |
+
$socket_closed = true;
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
// create a new socket if the current one is closed and retry the message
|
235 |
+
if ($socket_closed) {
|
236 |
+
|
237 |
+
$this->_destroySocket();
|
238 |
+
|
239 |
+
if ($retry) {
|
240 |
+
if ($this->_debug()) {
|
241 |
+
$this->_log("Retrying socket write...");
|
242 |
+
}
|
243 |
+
$socket = $this->_getSocket();
|
244 |
+
if ($socket) return $this->_write($socket, $data, false);
|
245 |
+
}
|
246 |
+
|
247 |
+
return false;
|
248 |
+
}
|
249 |
+
|
250 |
+
|
251 |
+
// only wait for the response in debug mode or if we explicitly want to be synchronous
|
252 |
+
if ($this->_debug() || !$this->_async) {
|
253 |
+
$res = $this->handleResponse(fread($socket, 2048));
|
254 |
+
if ($res["status"] != "200") {
|
255 |
+
$this->_handleError($res["status"], $res["body"]);
|
256 |
+
$success = false;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
|
260 |
+
return $success;
|
261 |
+
}
|
262 |
+
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Parse the response from a socket write (only used for debugging)
|
266 |
+
* @param $response
|
267 |
+
* @return array
|
268 |
+
*/
|
269 |
+
private function handleResponse($response) {
|
270 |
+
|
271 |
+
$lines = explode("\n", $response);
|
272 |
+
|
273 |
+
// extract headers
|
274 |
+
$headers = array();
|
275 |
+
foreach($lines as $line) {
|
276 |
+
$kvsplit = explode(":", $line);
|
277 |
+
if (count($kvsplit) == 2) {
|
278 |
+
$header = $kvsplit[0];
|
279 |
+
$value = $kvsplit[1];
|
280 |
+
$headers[$header] = trim($value);
|
281 |
+
}
|
282 |
+
|
283 |
+
}
|
284 |
+
|
285 |
+
// extract status
|
286 |
+
$line_one_exploded = explode(" ", $lines[0]);
|
287 |
+
$status = $line_one_exploded[1];
|
288 |
+
|
289 |
+
// extract body
|
290 |
+
$body = $lines[count($lines) - 1];
|
291 |
+
|
292 |
+
// if the connection has been closed lets kill the socket
|
293 |
+
if ($headers['Connection'] == "close") {
|
294 |
+
$this->_destroySocket();
|
295 |
+
if ($this->_debug()) {
|
296 |
+
$this->_log("Server told us connection closed so lets destroy the socket so it'll reconnect on next call");
|
297 |
+
}
|
298 |
+
}
|
299 |
+
|
300 |
+
$ret = array(
|
301 |
+
"status" => $status,
|
302 |
+
"body" => $body,
|
303 |
+
);
|
304 |
+
|
305 |
+
return $ret;
|
306 |
+
}
|
307 |
+
|
308 |
+
|
309 |
+
}
|
lib/mixpanel/ConsumerStrategies/SocketConsumer.php
CHANGED
@@ -31,6 +31,8 @@
|
|
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 |
/**
|
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 |
+
namespace LeadIn;
|
35 |
+
|
36 |
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
37 |
|
38 |
/**
|
lib/mixpanel/{Mixpanel.php → LI_Mixpanel.php}
RENAMED
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
require_once(dirname(__FILE__) . "/Base/
|
4 |
-
require_once(dirname(__FILE__) . "/Producers/
|
5 |
-
require_once(dirname(__FILE__) . "/Producers/
|
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
|
@@ -14,7 +14,7 @@ require_once(dirname(__FILE__) . "/Producers/MixpanelEvents.php");
|
|
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 "
|
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.
|
@@ -75,12 +75,12 @@ require_once(dirname(__FILE__) . "/Producers/MixpanelEvents.php");
|
|
75 |
* </tr>
|
76 |
* <tr>
|
77 |
* <td>connect_timeout</td>
|
78 |
-
* <td>In both the SocketConsumer and
|
79 |
* <td>5</td>
|
80 |
* </tr>
|
81 |
* <tr>
|
82 |
* <td>timeout</td>
|
83 |
-
* <td>In the
|
84 |
* <td>30</td>
|
85 |
* </tr>
|
86 |
* </table>
|
@@ -106,7 +106,7 @@ require_once(dirname(__FILE__) . "/Producers/MixpanelEvents.php");
|
|
106 |
* ));
|
107 |
*
|
108 |
*/
|
109 |
-
class
|
110 |
|
111 |
|
112 |
/**
|
@@ -137,8 +137,8 @@ class Mixpanel extends Base_MixpanelBase {
|
|
137 |
*/
|
138 |
public function __construct($token, $options = array()) {
|
139 |
parent::__construct($options);
|
140 |
-
$this->people = new
|
141 |
-
$this->_events = new
|
142 |
}
|
143 |
|
144 |
|
@@ -150,7 +150,7 @@ class Mixpanel extends Base_MixpanelBase {
|
|
150 |
*/
|
151 |
public static function getInstance($token, $options = array()) {
|
152 |
if(!isset(self::$_instance)) {
|
153 |
-
self::$_instance = new
|
154 |
}
|
155 |
return self::$_instance;
|
156 |
}
|
1 |
<?php
|
2 |
|
3 |
+
require_once(dirname(__FILE__) . "/Base/LI_MixpanelBase.php");
|
4 |
+
require_once(dirname(__FILE__) . "/Producers/LI_MixpanelPeople.php");
|
5 |
+
require_once(dirname(__FILE__) . "/Producers/LI_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
|
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 "LI_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.
|
75 |
* </tr>
|
76 |
* <tr>
|
77 |
* <td>connect_timeout</td>
|
78 |
+
* <td>In both the SocketConsumer and LI_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 LI_CurlConsumer (non-forked), it is used to determine how long the cURL call has to execute.
|
84 |
* <td>30</td>
|
85 |
* </tr>
|
86 |
* </table>
|
106 |
* ));
|
107 |
*
|
108 |
*/
|
109 |
+
class LI_Mixpanel extends LI_Base_MixpanelBase {
|
110 |
|
111 |
|
112 |
/**
|
137 |
*/
|
138 |
public function __construct($token, $options = array()) {
|
139 |
parent::__construct($options);
|
140 |
+
$this->people = new LI_Producers_MixpanelPeople($token, $options);
|
141 |
+
$this->_events = new LI_Producers_MixpanelEvents($token, $options);
|
142 |
}
|
143 |
|
144 |
|
150 |
*/
|
151 |
public static function getInstance($token, $options = array()) {
|
152 |
if(!isset(self::$_instance)) {
|
153 |
+
self::$_instance = new LI_Mixpanel($token, $options);
|
154 |
}
|
155 |
return self::$_instance;
|
156 |
}
|
lib/mixpanel/Producers/LI_MixpanelBaseProducer.php
ADDED
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__) . "/../Base/LI_MixpanelBase.php");
|
4 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_FileConsumer.php");
|
5 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_CurlConsumer.php");
|
6 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_SocketConsumer.php");
|
7 |
+
|
8 |
+
if (!function_exists('json_encode')) {
|
9 |
+
throw new Exception('The JSON PHP extension is required.');
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Provides some base methods for use by a message Producer
|
14 |
+
*/
|
15 |
+
abstract class LI_Producers_MixpanelBaseProducer extends LI_Base_MixpanelBase {
|
16 |
+
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var string a token associated to a Mixpanel project
|
20 |
+
*/
|
21 |
+
protected $_token;
|
22 |
+
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var array a queue to hold messages in memory before flushing in batches
|
26 |
+
*/
|
27 |
+
private $_queue = array();
|
28 |
+
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @var LI_ConsumerStrategies_AbstractConsumer the consumer to use when flushing messages
|
32 |
+
*/
|
33 |
+
private $_consumer = null;
|
34 |
+
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var array The list of available consumers
|
38 |
+
*/
|
39 |
+
private $_consumers = array(
|
40 |
+
"file" => "LI_ConsumerStrategies_FileConsumer",
|
41 |
+
"curl" => "LI_ConsumerStrategies_CurlConsumer",
|
42 |
+
"socket" => "LI_ConsumerStrategies_SocketConsumer"
|
43 |
+
);
|
44 |
+
|
45 |
+
|
46 |
+
/**
|
47 |
+
* If the queue reaches this size we'll auto-flush to prevent out of memory errors
|
48 |
+
* @var int
|
49 |
+
*/
|
50 |
+
protected $_max_queue_size = 1000;
|
51 |
+
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Creates a new MixpanelBaseProducer, assings Mixpanel project token, registers custom Consumers, and instantiates
|
55 |
+
* the desired consumer
|
56 |
+
* @param $token
|
57 |
+
* @param array $options
|
58 |
+
*/
|
59 |
+
public function __construct($token, $options = array()) {
|
60 |
+
|
61 |
+
parent::__construct($options);
|
62 |
+
|
63 |
+
// register any customer consumers
|
64 |
+
if (array_key_exists("consumers", $options)) {
|
65 |
+
$this->_consumers = array_merge($this->_consumers, $options['consumers']);
|
66 |
+
}
|
67 |
+
|
68 |
+
// set max queue size
|
69 |
+
if (array_key_exists("max_queue_size", $options)) {
|
70 |
+
$this->_max_queue_size = $options['max_queue_size'];
|
71 |
+
}
|
72 |
+
|
73 |
+
// associate token
|
74 |
+
$this->_token = $token;
|
75 |
+
|
76 |
+
if ($this->_debug()) {
|
77 |
+
$this->_log("Using token: ".$this->_token);
|
78 |
+
}
|
79 |
+
|
80 |
+
// instantiate the chosen consumer
|
81 |
+
$this->_consumer = $this->_getConsumer();
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Flush the queue when we destruct the client with retries
|
88 |
+
*/
|
89 |
+
public function __destruct() {
|
90 |
+
$attempts = 0;
|
91 |
+
$max_attempts = 10;
|
92 |
+
$success = false;
|
93 |
+
while (!$success && $attempts < $max_attempts) {
|
94 |
+
if ($this->_debug()) {
|
95 |
+
$this->_log("destruct flush attempt #".($attempts+1));
|
96 |
+
}
|
97 |
+
$success = $this->flush();
|
98 |
+
$attempts++;
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Iterate the queue and write in batches using the instantiated Consumer Strategy
|
105 |
+
* @param int $desired_batch_size
|
106 |
+
* @return bool whether or not the flush was successful
|
107 |
+
*/
|
108 |
+
public function flush($desired_batch_size = 50) {
|
109 |
+
$queue_size = count($this->_queue);
|
110 |
+
$succeeded = true;
|
111 |
+
if ($this->_debug()) {
|
112 |
+
$this->_log("Flush called - queue size: ".$queue_size);
|
113 |
+
}
|
114 |
+
|
115 |
+
while($queue_size > 0 && $succeeded) {
|
116 |
+
$batch_size = min(array($queue_size, $desired_batch_size, $this->_options['max_batch_size']));
|
117 |
+
$batch = array_splice($this->_queue, 0, $batch_size);
|
118 |
+
$succeeded = $this->_persist($batch);
|
119 |
+
|
120 |
+
if (!$succeeded) {
|
121 |
+
if ($this->_debug()) {
|
122 |
+
$this->_log("Batch consumption failed!");
|
123 |
+
}
|
124 |
+
$this->_queue = array_merge($batch, $this->_queue);
|
125 |
+
|
126 |
+
if ($this->_debug()) {
|
127 |
+
$this->_log("added batch back to queue, queue size is now $queue_size");
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
$queue_size = count($this->_queue);
|
132 |
+
|
133 |
+
if ($this->_debug()) {
|
134 |
+
$this->_log("Batch of $batch_size consumed, queue size is now $queue_size");
|
135 |
+
}
|
136 |
+
}
|
137 |
+
return $succeeded;
|
138 |
+
}
|
139 |
+
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Empties the queue without persisting any of the messages
|
143 |
+
*/
|
144 |
+
public function reset() {
|
145 |
+
$this->_queue = array();
|
146 |
+
}
|
147 |
+
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Returns the in-memory queue
|
151 |
+
* @return array
|
152 |
+
*/
|
153 |
+
public function getQueue() {
|
154 |
+
return $this->_queue;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Returns the current Mixpanel project token
|
159 |
+
* @return string
|
160 |
+
*/
|
161 |
+
public function getToken() {
|
162 |
+
return $this->_token;
|
163 |
+
}
|
164 |
+
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Given a strategy type, return a new PersistenceStrategy object
|
168 |
+
* @return LI_ConsumerStrategies_AbstractConsumer
|
169 |
+
*/
|
170 |
+
protected function _getConsumer() {
|
171 |
+
$key = $this->_options['consumer'];
|
172 |
+
$Strategy = $this->_consumers[$key];
|
173 |
+
if ($this->_debug()) {
|
174 |
+
$this->_log("Using consumer: " . $key . " -> " . $Strategy);
|
175 |
+
}
|
176 |
+
$this->_options['endpoint'] = $this->_getEndpoint();
|
177 |
+
|
178 |
+
return new $Strategy($this->_options);
|
179 |
+
}
|
180 |
+
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Add an array representing a message to be sent to Mixpanel to a queue.
|
184 |
+
* @param array $message
|
185 |
+
*/
|
186 |
+
public function enqueue($message = array()) {
|
187 |
+
array_push($this->_queue, $message);
|
188 |
+
|
189 |
+
// force a flush if we've reached our threshold
|
190 |
+
if (count($this->_queue) > $this->_max_queue_size) {
|
191 |
+
$this->flush();
|
192 |
+
}
|
193 |
+
|
194 |
+
if ($this->_debug()) {
|
195 |
+
$this->_log("Queued message: ".json_encode($message));
|
196 |
+
}
|
197 |
+
}
|
198 |
+
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Add an array representing a list of messages to be sent to Mixpanel to a queue.
|
202 |
+
* @param array $messages
|
203 |
+
*/
|
204 |
+
public function enqueueAll($messages = array()) {
|
205 |
+
foreach($messages as $message) {
|
206 |
+
$this->enqueue($message);
|
207 |
+
}
|
208 |
+
|
209 |
+
}
|
210 |
+
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Given an array of messages, persist it with the instantiated Persistence Strategy
|
214 |
+
* @param $message
|
215 |
+
* @return mixed
|
216 |
+
*/
|
217 |
+
protected function _persist($message) {
|
218 |
+
return $this->_consumer->persist($message);
|
219 |
+
}
|
220 |
+
|
221 |
+
|
222 |
+
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Return the endpoint that should be used by a consumer that consumes messages produced by this producer.
|
226 |
+
* @return string
|
227 |
+
*/
|
228 |
+
abstract function _getEndpoint();
|
229 |
+
|
230 |
+
}
|
lib/mixpanel/Producers/LI_MixpanelEvents.php
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__) . "/LI_MixpanelBaseProducer.php");
|
4 |
+
require_once(dirname(__FILE__) . "/LI_MixpanelPeople.php");
|
5 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_CurlConsumer.php");
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Provides an API to track events on Mixpanel
|
9 |
+
*/
|
10 |
+
class LI_Producers_MixpanelEvents extends LI_Producers_MixpanelBaseProducer {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* An array of properties to attach to every tracked event
|
14 |
+
* @var array
|
15 |
+
*/
|
16 |
+
private $_super_properties = array("mp_lib" => "php");
|
17 |
+
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Track an event defined by $event associated with metadata defined by $properties
|
21 |
+
* @param string $event
|
22 |
+
* @param array $properties
|
23 |
+
*/
|
24 |
+
public function track($event, $properties = array()) {
|
25 |
+
|
26 |
+
// if no token is passed in, use current token
|
27 |
+
if (!array_key_exists("token", $properties)) $properties['token'] = $this->_token;
|
28 |
+
|
29 |
+
// if no time is passed in, use the current time
|
30 |
+
if (!array_key_exists('time', $properties)) $properties['time'] = time();
|
31 |
+
|
32 |
+
$params['event'] = $event;
|
33 |
+
$params['properties'] = array_merge($this->_super_properties, $properties);
|
34 |
+
|
35 |
+
$this->enqueue($params);
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Register a property to be sent with every event. If the property has already been registered, it will be
|
41 |
+
* overwritten.
|
42 |
+
* @param string $property
|
43 |
+
* @param mixed $value
|
44 |
+
*/
|
45 |
+
public function register($property, $value) {
|
46 |
+
$this->_super_properties[$property] = $value;
|
47 |
+
}
|
48 |
+
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Register multiple properties to be sent with every event. If any of the properties have already been registered,
|
52 |
+
* they will be overwritten.
|
53 |
+
* @param array $props_and_vals
|
54 |
+
*/
|
55 |
+
public function registerAll($props_and_vals = array()) {
|
56 |
+
foreach($props_and_vals as $property => $value) {
|
57 |
+
$this->register($property, $value);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Register a property to be sent with every event. If the property has already been registered, it will NOT be
|
64 |
+
* overwritten.
|
65 |
+
* @param $property
|
66 |
+
* @param $value
|
67 |
+
*/
|
68 |
+
public function registerOnce($property, $value) {
|
69 |
+
if (!isset($this->_super_properties[$property])) {
|
70 |
+
$this->register($property, $value);
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Register multiple properties to be sent with every event. If any of the properties have already been registered,
|
77 |
+
* they will NOT be overwritten.
|
78 |
+
* @param array $props_and_vals
|
79 |
+
*/
|
80 |
+
public function registerAllOnce($props_and_vals = array()) {
|
81 |
+
foreach($props_and_vals as $property => $value) {
|
82 |
+
if (!isset($this->_super_properties[$property])) {
|
83 |
+
$this->register($property, $value);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Un-register an property to be sent with every event.
|
91 |
+
* @param string $property
|
92 |
+
*/
|
93 |
+
public function unregister($property) {
|
94 |
+
unset($this->_super_properties[$property]);
|
95 |
+
}
|
96 |
+
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Un-register a list of properties to be sent with every event.
|
100 |
+
* @param array $properties
|
101 |
+
*/
|
102 |
+
public function unregisterAll($properties) {
|
103 |
+
foreach($properties as $property) {
|
104 |
+
$this->unregister($property);
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get a property that is set to be sent with every event
|
111 |
+
* @param string $property
|
112 |
+
* @return mixed
|
113 |
+
*/
|
114 |
+
public function getProperty($property) {
|
115 |
+
return $this->_super_properties[$property];
|
116 |
+
}
|
117 |
+
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Identify the user you want to associate to tracked events
|
121 |
+
* @param string|int $user_id
|
122 |
+
*/
|
123 |
+
public function identify($user_id) {
|
124 |
+
$this->register("distinct_id", $user_id);
|
125 |
+
}
|
126 |
+
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Alias an existing id with a different unique id. This is helpful when you want to associate a generated id to
|
130 |
+
* a username or e-mail address.
|
131 |
+
*
|
132 |
+
* Because aliasing can be extremely vulnerable to race conditions and ordering issues, we'll make a synchronous
|
133 |
+
* call directly to Mixpanel when this method is called. If it fails we'll throw an Exception as subsequent
|
134 |
+
* events are likely to be incorrectly tracked.
|
135 |
+
* @param string|int $original_id
|
136 |
+
* @param string|int $new_id
|
137 |
+
* @return array $msg
|
138 |
+
* @throws Exception
|
139 |
+
*/
|
140 |
+
public function createAlias($original_id, $new_id) {
|
141 |
+
$msg = array(
|
142 |
+
"event" => '$create_alias',
|
143 |
+
"properties" => array("distinct_id" => $original_id, "alias" => $new_id, "token" => $this->_token)
|
144 |
+
);
|
145 |
+
|
146 |
+
$options = array_merge($this->_options, array("endpoint" => $this->_getEndpoint(), "fork" => false));
|
147 |
+
$LI_CurlConsumer = new LI_ConsumerStrategies_CurlConsumer($options);
|
148 |
+
$success = $LI_CurlConsumer->persist(array($msg));
|
149 |
+
if (!$success) {
|
150 |
+
//error_log("Creating Mixpanel Alias (original id: $original_id, new id: $new_id) failed");
|
151 |
+
//throw new Exception("Tried to create an alias but the call was not successful");
|
152 |
+
} else {
|
153 |
+
return $msg;
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Returns the "events" endpoint
|
160 |
+
* @return string
|
161 |
+
*/
|
162 |
+
function _getEndpoint() {
|
163 |
+
return $this->_options['events_endpoint'];
|
164 |
+
}
|
165 |
+
}
|
lib/mixpanel/Producers/LI_MixpanelPeople.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__) . "/LI_MixpanelBaseProducer.php");
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Provides an API to create/update profiles on Mixpanel
|
7 |
+
*/
|
8 |
+
class LI_Producers_MixpanelPeople extends LI_Producers_MixpanelBaseProducer {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Internal method to prepare a message given the message data
|
12 |
+
* @param $distinct_id
|
13 |
+
* @param $operation
|
14 |
+
* @param $value
|
15 |
+
* @param null $ip
|
16 |
+
* @return array
|
17 |
+
*/
|
18 |
+
private function _constructPayload($distinct_id, $operation, $value, $ip = null) {
|
19 |
+
$payload = array(
|
20 |
+
'$token' => $this->_token,
|
21 |
+
'$distinct_id' => $distinct_id,
|
22 |
+
$operation => $value
|
23 |
+
);
|
24 |
+
if ($ip !== null) $payload['$ip'] = $ip;
|
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 |
+
*/
|
35 |
+
public function set($distinct_id, $props, $ip = null) {
|
36 |
+
$payload = $this->_constructPayload($distinct_id, '$set', $props, $ip);
|
37 |
+
$this->enqueue($payload);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Set properties on a user record. If the profile does not exist, it creates it with these properties.
|
42 |
+
* If it does exist, it sets the properties to these values but WILL NOT overwrite existing values.
|
43 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
44 |
+
* @param array $props associative array of properties to set on the profile
|
45 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
46 |
+
*/
|
47 |
+
public function setOnce($distinct_id, $props, $ip = null) {
|
48 |
+
$payload = $this->_constructPayload($distinct_id, '$set_once', $props, $ip);
|
49 |
+
$this->enqueue($payload);
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Unset properties on a user record. If the profile does not exist, it creates it with no properties.
|
54 |
+
* If it does exist, it unsets these properties. NOTE: In other libraries we use 'unset' which is
|
55 |
+
* a reserved word in PHP.
|
56 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
57 |
+
* @param array $props associative array of properties to unset on the profile
|
58 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
59 |
+
*/
|
60 |
+
public function remove($distinct_id, $props, $ip = null) {
|
61 |
+
$payload = $this->_constructPayload($distinct_id, '$unset', $props, $ip);
|
62 |
+
$this->enqueue($payload);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Increments the value of a property on a user record. If the profile does not exist, it creates it and sets the
|
67 |
+
* property to the increment value.
|
68 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
69 |
+
* @param $prop string the property to increment
|
70 |
+
* @param int $val the amount to increment the property by
|
71 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
72 |
+
*/
|
73 |
+
public function increment($distinct_id, $prop, $val, $ip = null) {
|
74 |
+
$payload = $this->_constructPayload($distinct_id, '$add', array("$prop" => $val), $ip);
|
75 |
+
$this->enqueue($payload);
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Adds $val to a list located at $prop. If the property does not exist, it will be created. If $val is a string
|
80 |
+
* and the list is empty or does not exist, a new list with one value will be created.
|
81 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
82 |
+
* @param string $prop the property that holds the list
|
83 |
+
* @param string|array $val items to add to the list
|
84 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
85 |
+
*/
|
86 |
+
public function append($distinct_id, $prop, $val, $ip = null) {
|
87 |
+
$operation = gettype($val) == "array" ? '$union' : '$append';
|
88 |
+
$payload = $this->_constructPayload($distinct_id, $operation, array("$prop" => $val), $ip);
|
89 |
+
$this->enqueue($payload);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Adds a transaction to the user's profile for revenue tracking
|
94 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
95 |
+
* @param string $amount the transaction amount e.g. "20.50"
|
96 |
+
* @param null $timestamp the timestamp of when the transaction occurred (default to current timestamp)
|
97 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
98 |
+
*/
|
99 |
+
public function trackCharge($distinct_id, $amount, $timestamp = null, $ip = null) {
|
100 |
+
$timestamp = $timestamp == null ? time() : $timestamp;
|
101 |
+
$date_iso = date("c", $timestamp);
|
102 |
+
$transaction = array(
|
103 |
+
'$time' => $date_iso,
|
104 |
+
'$amount' => $amount
|
105 |
+
);
|
106 |
+
$val = array('$transactions' => $transaction);
|
107 |
+
$payload = $this->_constructPayload($distinct_id, '$append', $val, $ip);
|
108 |
+
$this->enqueue($payload);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Clear all transactions stored on a user's profile
|
113 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
114 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
115 |
+
*/
|
116 |
+
public function clearCharges($distinct_id, $ip = null) {
|
117 |
+
$payload = $this->_constructPayload($distinct_id, '$set', array('$transactions' => array()), $ip);
|
118 |
+
$this->enqueue($payload);
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Delete this profile from Mixpanel
|
123 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
124 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
125 |
+
*/
|
126 |
+
public function deleteUser($distinct_id, $ip = null) {
|
127 |
+
$payload = $this->_constructPayload($distinct_id, '$delete', "", $ip);
|
128 |
+
$this->enqueue($payload);
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Returns the "engage" endpoint
|
133 |
+
* @return string
|
134 |
+
*/
|
135 |
+
function _getEndpoint() {
|
136 |
+
return $this->_options['people_endpoint'];
|
137 |
+
}
|
138 |
+
|
139 |
+
}
|
lib/mixpanel/Producers/MixpanelBaseProducer.php
CHANGED
@@ -1,4 +1,6 @@
|
|
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");
|
@@ -36,9 +38,9 @@ abstract class Producers_MixpanelBaseProducer extends Base_MixpanelBase {
|
|
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 |
|
1 |
<?php
|
2 |
+
namespace LeadIn;
|
3 |
+
|
4 |
require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
|
5 |
require_once(dirname(__FILE__) . "/../ConsumerStrategies/FileConsumer.php");
|
6 |
require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
|
38 |
* @var array The list of available consumers
|
39 |
*/
|
40 |
private $_consumers = array(
|
41 |
+
"file" => "LeadIn\ConsumerStrategies_FileConsumer",
|
42 |
+
"curl" => "LeadIn\ConsumerStrategies_CurlConsumer",
|
43 |
+
"socket" => "LeadIn\ConsumerStrategies_SocketConsumer"
|
44 |
);
|
45 |
|
46 |
|
lib/mixpanel/Producers/MixpanelEvents.php
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
3 |
require_once(dirname(__FILE__) . "/MixpanelPeople.php");
|
4 |
require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
|
1 |
<?php
|
2 |
+
namespace LeadIn;
|
3 |
+
|
4 |
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
5 |
require_once(dirname(__FILE__) . "/MixpanelPeople.php");
|
6 |
require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
|
lib/mixpanel/Producers/MixpanelPeople.php
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
3 |
|
4 |
/**
|
1 |
<?php
|
2 |
+
namespace LeadIn;
|
3 |
+
|
4 |
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
5 |
|
6 |
/**
|
power-ups/constant-contact-list-sync.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Power-up Name: Contact Sync
|
4 |
+
* Power-up Class: WPConstantContactListSync
|
5 |
+
* Power-up Menu Text:
|
6 |
+
* Power-up Slug: constant_contact_list_sync
|
7 |
+
* Power-up Menu Link: settings
|
8 |
+
* Power-up URI: http://leadin.com/constant-contact-list-sync
|
9 |
+
* Power-up Description: Sync your subscribers to a Constant Contact email list.
|
10 |
+
* Power-up Icon: power-up-icon-constant-contact-list-sync
|
11 |
+
* Power-up Icon Small: power-up-icon-constant-contact-list-sync_small
|
12 |
+
* First Introduced: 0.8.0
|
13 |
+
* Power-up Tags: Newsletter, Email
|
14 |
+
* Auto Activate: No
|
15 |
+
*/
|
16 |
+
|
17 |
+
//=============================================
|
18 |
+
// Define Constants
|
19 |
+
//=============================================
|
20 |
+
|
21 |
+
if ( !defined('LEADIN_CONSTANT_CONTACT_LIST_SYNC_PATH') )
|
22 |
+
define('LEADIN_CONSTANT_CONTACT_LIST_SYNC_PATH', LEADIN_PATH . '/power-ups/constant-contact-list-sync');
|
23 |
+
|
24 |
+
if ( !defined('LEADIN_CONSTANT_CONTACT_LIST_SYNC_PLUGIN_DIR') )
|
25 |
+
define('LEADIN_CONSTANT_CONTACT_LIST_SYNC_PLUGIN_DIR', LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-list-sync');
|
26 |
+
|
27 |
+
if ( !defined('LEADIN_CONSTANT_CONTACT_LIST_SYNC_PLUGIN_SLUG') )
|
28 |
+
define('LEADIN_CONSTANT_CONTACT_LIST_SYNC_SLUG', basename(dirname(__FILE__)));
|
29 |
+
|
30 |
+
if ( !defined('LEADIN_CONSTANT_CONTACT_API_KEY') )
|
31 |
+
define('LEADIN_CONSTANT_CONTACT_API_KEY', 'p5hrzdhe2zrwbm76r2u7pvtc');
|
32 |
+
|
33 |
+
|
34 |
+
|
35 |
+
//=============================================
|
36 |
+
// Include Needed Files
|
37 |
+
//=============================================
|
38 |
+
require_once(LEADIN_CONSTANT_CONTACT_LIST_SYNC_PLUGIN_DIR . '/admin/constant-contact-list-sync-admin.php');
|
39 |
+
require_once(LEADIN_CONSTANT_CONTACT_LIST_SYNC_PLUGIN_DIR . '/inc/li_constant_contact.php');
|
40 |
+
|
41 |
+
//=============================================
|
42 |
+
// WPLeadIn Class
|
43 |
+
//=============================================
|
44 |
+
class WPConstantContactListSync extends WPLeadIn {
|
45 |
+
|
46 |
+
var $admin;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Class constructor
|
50 |
+
*/
|
51 |
+
function __construct ( $activated )
|
52 |
+
{
|
53 |
+
//=============================================
|
54 |
+
// Hooks & Filters
|
55 |
+
//=============================================
|
56 |
+
|
57 |
+
if ( ! $activated )
|
58 |
+
return false;
|
59 |
+
|
60 |
+
global $leadin_constant_contact_list_sync_wp;
|
61 |
+
$leadin_constant_contact_list_sync_wp = $this;
|
62 |
+
|
63 |
+
}
|
64 |
+
|
65 |
+
public function admin_init ( )
|
66 |
+
{
|
67 |
+
$admin_class = get_class($this) . 'Admin';
|
68 |
+
$this->admin = new $admin_class($this->icon_small);
|
69 |
+
}
|
70 |
+
|
71 |
+
function power_up_setup_callback ( )
|
72 |
+
{
|
73 |
+
$this->admin->power_up_setup_callback();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Activate the power-up
|
78 |
+
*/
|
79 |
+
function add_leadin_subscribe_defaults ()
|
80 |
+
{
|
81 |
+
$lis_options = get_option('leadin_subscribe_options');
|
82 |
+
|
83 |
+
if ( ($lis_options['li_susbscibe_installed'] != 1) || (!is_array($lis_options)) )
|
84 |
+
{
|
85 |
+
$opt = array(
|
86 |
+
'li_susbscibe_installed' => '1',
|
87 |
+
'li_subscribe_heading' => 'Sign up for my newsletter to get new posts by email'
|
88 |
+
);
|
89 |
+
|
90 |
+
update_option('leadin_subscribe_options', $opt);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
function push_constant_contact_subscriber_to_list ( $email = '', $first_name = '', $last_name = '', $phone = '' )
|
95 |
+
{
|
96 |
+
$options = get_option('leadin_cc_options');
|
97 |
+
$li_cc_subscribers_to_list = ( isset($options['li_cc_subscribers_to_list']) ? $options['li_cc_subscribers_to_list'] : '' );
|
98 |
+
|
99 |
+
if ( isset($options['li_cc_email']) && isset($options['li_cc_password']) && $options['li_cc_email'] && $options['li_cc_password'] && $li_cc_subscribers_to_list )
|
100 |
+
{
|
101 |
+
$this->constant_contact = new LI_ConstantContact($options['li_cc_email'], $options['li_cc_password'], LEADIN_CONSTANT_CONTACT_API_KEY, TRUE);
|
102 |
+
|
103 |
+
$contact = array();
|
104 |
+
|
105 |
+
if ( $email )
|
106 |
+
$contact['EmailAddress'] = $email;
|
107 |
+
|
108 |
+
if ( $first_name )
|
109 |
+
$contact['FirstName'] = $first_name;
|
110 |
+
|
111 |
+
if ( $last_name )
|
112 |
+
$contact['LastName'] = $last_name;
|
113 |
+
|
114 |
+
if ( $phone )
|
115 |
+
$contact['HomePhone'] = $phone;
|
116 |
+
|
117 |
+
if ( $phone )
|
118 |
+
$contact['WorkPhone'] = $phone;
|
119 |
+
|
120 |
+
$this->constant_contact->add_contact($contact, array($li_cc_subscribers_to_list));
|
121 |
+
}
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
//=============================================
|
126 |
+
// Subscribe Widget Init
|
127 |
+
//=============================================
|
128 |
+
|
129 |
+
global $leadin_constant_contact_list_sync_wp;
|
130 |
+
|
131 |
+
?>
|
power-ups/constant-contact-list-sync/admin/constant-contact-list-sync-admin.php
ADDED
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
//=============================================
|
3 |
+
// WPLeadInAdmin Class
|
4 |
+
//=============================================
|
5 |
+
class WPConstantContactListSyncAdmin extends WPLeadInAdmin {
|
6 |
+
|
7 |
+
var $power_up_settings_section = 'leadin_cc_options_section';
|
8 |
+
var $power_up_icon;
|
9 |
+
var $auth_set;
|
10 |
+
var $bad_api_call;
|
11 |
+
var $constant_contact;
|
12 |
+
var $lists;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class constructor
|
16 |
+
*/
|
17 |
+
function __construct ( $small_icon )
|
18 |
+
{
|
19 |
+
//=============================================
|
20 |
+
// Hooks & Filters
|
21 |
+
//=============================================
|
22 |
+
|
23 |
+
if ( is_admin() )
|
24 |
+
{
|
25 |
+
$this->power_up_icon = '<img src="' . LEADIN_PATH . '/images/' . $small_icon . '.png" class="power-up-settings-icon"/>';
|
26 |
+
add_action('admin_init', array($this, 'leadin_cc_build_settings_page'));
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
//=============================================
|
31 |
+
// Settings Page
|
32 |
+
//=============================================
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Creates settings options
|
36 |
+
*/
|
37 |
+
function leadin_cc_build_settings_page ()
|
38 |
+
{
|
39 |
+
global $leadin_constant_contact_list_sync_wp;
|
40 |
+
|
41 |
+
$options = get_option('leadin_cc_options');
|
42 |
+
|
43 |
+
register_setting('leadin_settings_options', 'leadin_cc_options', array($this, 'sanitize'));
|
44 |
+
|
45 |
+
// If the creds are set, check if they are any good by hitting the API
|
46 |
+
if ( isset($options['li_cc_email']) && isset($options['li_cc_password']) && $options['li_cc_email'] && $options['li_cc_password'] )
|
47 |
+
{
|
48 |
+
$this->auth_set = TRUE;
|
49 |
+
|
50 |
+
// Try to make a request using the authentication credentials
|
51 |
+
$this->lists = $this->li_cc_get_email_lists(LEADIN_CONSTANT_CONTACT_API_KEY, $options['li_cc_email'], $options['li_cc_password']);
|
52 |
+
|
53 |
+
if ( $this->constant_contact->cc_exception )
|
54 |
+
{
|
55 |
+
$this->bad_api_call = TRUE;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
add_settings_section($this->power_up_settings_section, $this->power_up_icon . "Constant Contact", array($this, 'cc_section_callback'), LEADIN_ADMIN_PATH);
|
60 |
+
|
61 |
+
if ( $this->auth_set && ! $this->bad_api_call )
|
62 |
+
{
|
63 |
+
add_settings_field('li_cc_subscribers_to_list', 'Add subscribers to list', array($this, 'li_cc_subscribers_to_list_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
|
64 |
+
}
|
65 |
+
else
|
66 |
+
{
|
67 |
+
add_settings_field('li_cc_email', 'Email', array($this, 'li_cc_email_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
|
68 |
+
add_settings_field('li_cc_password', 'Password', array($this, 'li_cc_password_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
function cc_section_callback ( )
|
73 |
+
{
|
74 |
+
if ( ! $this->auth_set )
|
75 |
+
echo 'Sign into your Constant Contact account below to setup Contact Sync';
|
76 |
+
else if ( $this->bad_api_call )
|
77 |
+
echo '<div id="message" class="updated below-h2 error"><p>' . $this->constant_contact->cc_exception . '</p></div>';
|
78 |
+
|
79 |
+
$this->print_hidden_settings_fields();
|
80 |
+
}
|
81 |
+
|
82 |
+
function print_hidden_settings_fields ()
|
83 |
+
{
|
84 |
+
// Hacky solution to solve the Settings API overwriting the default values
|
85 |
+
$options = get_option('leadin_cc_options');
|
86 |
+
$li_cc_email = ( $options['li_cc_email'] ? $options['li_cc_email'] : '' );
|
87 |
+
$li_cc_password = ( $options['li_cc_password'] ? $options['li_cc_password'] : '' );
|
88 |
+
|
89 |
+
if ( $li_cc_email )
|
90 |
+
{
|
91 |
+
printf(
|
92 |
+
'<input id="li_cc_email" type="hidden" name="leadin_cc_options[li_cc_email]" value="%s"/>',
|
93 |
+
$li_cc_email
|
94 |
+
);
|
95 |
+
}
|
96 |
+
|
97 |
+
if ( $li_cc_password )
|
98 |
+
{
|
99 |
+
printf(
|
100 |
+
'<input id="li_cc_password" type="hidden" name="leadin_cc_options[li_cc_password]" value="%s"/>',
|
101 |
+
$li_cc_password
|
102 |
+
);
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Sanitize each setting field as needed
|
108 |
+
*
|
109 |
+
* @param array $input Contains all settings fields as array keys
|
110 |
+
*/
|
111 |
+
public function sanitize ( $input )
|
112 |
+
{
|
113 |
+
$new_input = array();
|
114 |
+
|
115 |
+
if( isset( $input['li_cc_email'] ) )
|
116 |
+
$new_input['li_cc_email'] = sanitize_text_field( $input['li_cc_email'] );
|
117 |
+
|
118 |
+
if( isset( $input['li_cc_password'] ) )
|
119 |
+
$new_input['li_cc_password'] = sanitize_text_field( $input['li_cc_password'] );
|
120 |
+
|
121 |
+
if( isset( $input['li_cc_subscribers_to_list'] ) )
|
122 |
+
$new_input['li_cc_subscribers_to_list'] = sanitize_text_field( $input['li_cc_subscribers_to_list'] );
|
123 |
+
|
124 |
+
return $new_input;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Prints email input for settings page
|
129 |
+
*/
|
130 |
+
function li_cc_email_callback ()
|
131 |
+
{
|
132 |
+
$options = get_option('leadin_cc_options');
|
133 |
+
$li_cc_email = ( $options['li_cc_email'] ? $options['li_cc_email'] : '' ); // Get header from options, or show default
|
134 |
+
|
135 |
+
printf(
|
136 |
+
'<input id="li_cc_email" type="text" id="title" name="leadin_cc_options[li_cc_email]" value="%s" size="50"/>',
|
137 |
+
$li_cc_email
|
138 |
+
);
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Prints password input for settings page
|
143 |
+
*/
|
144 |
+
function li_cc_password_callback ()
|
145 |
+
{
|
146 |
+
$options = get_option('leadin_cc_options');
|
147 |
+
$li_cc_password = ( $options['li_cc_password'] ? $options['li_cc_password'] : '' ); // Get header from options, or show default
|
148 |
+
|
149 |
+
printf(
|
150 |
+
'<input id="li_cc_password" type="password" id="title" name="leadin_cc_options[li_cc_password]" value="%s" size="50"/>',
|
151 |
+
$li_cc_password
|
152 |
+
);
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Prints email input for settings page
|
157 |
+
*/
|
158 |
+
function li_cc_subscribers_to_list_callback ()
|
159 |
+
{
|
160 |
+
$options = get_option('leadin_cc_options');
|
161 |
+
$li_cc_subscribers_to_list = ( isset($options['li_cc_subscribers_to_list']) ? $options['li_cc_subscribers_to_list'] : '' ); // Get header from options, or show default
|
162 |
+
|
163 |
+
echo '<select id="li_cc_subscribers_to_list" name="leadin_cc_options[li_cc_subscribers_to_list]" ' . ( ! count($this->lists) ? 'disabled' : '' ) . '>';
|
164 |
+
|
165 |
+
if ( count($this->lists) )
|
166 |
+
{
|
167 |
+
$list_set = FALSE;
|
168 |
+
|
169 |
+
foreach ( $this->lists as $list )
|
170 |
+
{
|
171 |
+
// Skip over default lists
|
172 |
+
if ( $list['Name'] == 'Active' || $list['Name'] == 'Do Not Mail' || $list['Name'] == 'Removed' )
|
173 |
+
continue;
|
174 |
+
|
175 |
+
if ( urldecode($list['ListID']) == $li_cc_subscribers_to_list && !$list_set )
|
176 |
+
$list_set = TRUE;
|
177 |
+
|
178 |
+
echo '<option ' . ( urldecode($list['ListID']) == $li_cc_subscribers_to_list ? 'selected' : '' ) . ' value="' . urldecode($list['ListID']) . '">' . $list['Name'] . '</option>';
|
179 |
+
}
|
180 |
+
|
181 |
+
if ( !$list_set )
|
182 |
+
echo '<option selected value="">No list set...</option>';
|
183 |
+
}
|
184 |
+
else
|
185 |
+
{
|
186 |
+
echo '<option value="No lists...">No lists...</option>';
|
187 |
+
}
|
188 |
+
|
189 |
+
echo '</select>';
|
190 |
+
echo '<p><a href="https://login.constantcontact.com/login/login.sdo?goto=https://ui.constantcontact.com/rnavmap/distui/contacts" target="_blank">Create a new list on ConstantContact.com</a></p>';
|
191 |
+
}
|
192 |
+
|
193 |
+
function li_cc_get_email_lists ( $api_key, $username, $password )
|
194 |
+
{
|
195 |
+
$this->constant_contact = new LI_ConstantContact($username, $password, $api_key, FALSE);
|
196 |
+
$lists = $this->constant_contact->get_lists();
|
197 |
+
|
198 |
+
if ( count($lists) )
|
199 |
+
return $lists;
|
200 |
+
else
|
201 |
+
return FALSE;
|
202 |
+
}
|
203 |
+
}
|
204 |
+
|
205 |
+
?>
|
power-ups/constant-contact-list-sync/inc/li_constant_contact.php
ADDED
@@ -0,0 +1,1114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
global $cc_exception;
|
4 |
+
|
5 |
+
class LI_ConstantContact
|
6 |
+
{
|
7 |
+
var $auth;
|
8 |
+
var $api;
|
9 |
+
var $debug;
|
10 |
+
var $cc_exception;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* The ConstantContact contructor
|
14 |
+
*
|
15 |
+
* @param String $username - Your username
|
16 |
+
* @param String $password - Your password
|
17 |
+
* @param String $api_key - Your API Key
|
18 |
+
* @param Boolean $debug - Whether or not debugging output is displayed
|
19 |
+
* @param String $debug_style - Options are "cli" or "html". All it does is print "\n" or "<br>" for debugging output.
|
20 |
+
*/
|
21 |
+
|
22 |
+
public function __construct ( $username = '', $password = '', $api_key = '', $debug_enabled = FALSE, $debug_style = 'cli' )
|
23 |
+
{
|
24 |
+
$this->debug['enabled'] = $debug_enabled;
|
25 |
+
$this->debug['style'] = $debug_style;
|
26 |
+
$this->debug['last_response'] = 0;
|
27 |
+
$this->auth['username'] = $username;
|
28 |
+
$this->auth['password'] = $password;
|
29 |
+
$this->auth['api_key'] = $api_key;
|
30 |
+
$this->api['url'] = 'https://api.constantcontact.com/ws/customers/'.$username.'/';
|
31 |
+
$this->api['inner_url'] = 'http://api.constantcontact.com/ws/customers/'.$username.'/';
|
32 |
+
$this->api['relative_url'] = '/ws/customers/'.$username.'/';
|
33 |
+
}
|
34 |
+
|
35 |
+
//Main Functions
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Print debugging output
|
39 |
+
*
|
40 |
+
* @param String $string - String to print
|
41 |
+
*/
|
42 |
+
private function debug_print($string)
|
43 |
+
{
|
44 |
+
if($this->debug['enabled'])
|
45 |
+
{
|
46 |
+
$line_end = "\n";
|
47 |
+
if ($this->debug['style'] == 'html')
|
48 |
+
$line_end = "<br>";
|
49 |
+
print "ConstantContact Debug: $string{$line_end}";
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Fetch a URI from ConstantContact
|
55 |
+
*
|
56 |
+
* @param String $url - URL to connect to
|
57 |
+
* @param String $post - POST data to include
|
58 |
+
* @param String $fetch_as - Either array or xml for the return object
|
59 |
+
* @param String $call_type - NORMAL,PUT,DELETE
|
60 |
+
* @return Respose
|
61 |
+
*/
|
62 |
+
private function fetch($url,$post,$fetch_as='array',$call_type='NORMAL')
|
63 |
+
{
|
64 |
+
$this->debug_print("------------------ fetch ------------------");
|
65 |
+
|
66 |
+
$credentials=$this->auth['api_key'].'%'.$this->auth['username'].':'.$this->auth['password'];
|
67 |
+
|
68 |
+
$this->debug_print("Connecting to '".$url."'");
|
69 |
+
$this->debug_print("With Credentials '".$credentials."'");
|
70 |
+
|
71 |
+
$ch=curl_init();
|
72 |
+
|
73 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
74 |
+
curl_setopt($ch, CURLOPT_USERPWD, $credentials);
|
75 |
+
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
76 |
+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,1);
|
77 |
+
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
78 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
79 |
+
if(strlen(trim($post))>0)
|
80 |
+
{
|
81 |
+
if ($this->debug['style'] == 'cli')
|
82 |
+
$this->debug_print("And Posting:\n\n---START---\n".$post."\n---END---\n\n");
|
83 |
+
elseif ($this->debug['style'] == 'html')
|
84 |
+
$this->debug_print("And Posting:<pre>\n\n---START---\n".htmlspecialchars($post)."\n---END---\n\n</pre>");
|
85 |
+
if ($call_type == 'PUT')
|
86 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
|
87 |
+
elseif ($call_type == 'DELETE')
|
88 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
89 |
+
else
|
90 |
+
curl_setopt($ch, CURLOPT_POST, 1);
|
91 |
+
|
92 |
+
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
|
93 |
+
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/atom+xml'));
|
94 |
+
}
|
95 |
+
else
|
96 |
+
{
|
97 |
+
$this->debug_print("Not posting");
|
98 |
+
curl_setopt($ch, CURLOPT_POST, 0);
|
99 |
+
if ($call_type == 'PUT')
|
100 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
|
101 |
+
elseif ($call_type == 'DELETE')
|
102 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
103 |
+
}
|
104 |
+
|
105 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
106 |
+
|
107 |
+
$response = curl_exec($ch);
|
108 |
+
$response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
109 |
+
$this->debug_print("HTTP Response Code '".$response_code."'");
|
110 |
+
|
111 |
+
if ( ! in_array($response_code, array('201', '200', '204')) )
|
112 |
+
{
|
113 |
+
if ( $response_code == 401 )
|
114 |
+
{
|
115 |
+
$this->cc_exception = "Sorry, that username and password combination isn't right";
|
116 |
+
}
|
117 |
+
else if ( $response_code == 403 )
|
118 |
+
{
|
119 |
+
$this->cc_exception = "Your account is locked due to too many bad logins. You can try <a href='https://login.constantcontact.com/login/pwreset.sdo' target='_blank'>resetting your Constant Contact password</a> to unlock your account";
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
$this->debug['last_response'] = $response_code;
|
124 |
+
|
125 |
+
if ($this->debug['style'] == 'cli')
|
126 |
+
$this->debug_print("Received:\n\n---START---\n".$response."\n---END---\n\n");
|
127 |
+
elseif ($this->debug['style'] == 'html')
|
128 |
+
$this->debug_print("Received:<pre>\n\n---START---\n".htmlspecialchars($response)."\n---END---\n\n</pre>");
|
129 |
+
|
130 |
+
curl_close($ch);
|
131 |
+
if ($fetch_as == 'array')
|
132 |
+
return $this->xml_to_array($response);
|
133 |
+
else
|
134 |
+
return $response;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Converts XML data into a nested array
|
139 |
+
*
|
140 |
+
* @param String $contents - XML string
|
141 |
+
* @param Integers $get_attributes - Include attributes (default 1)
|
142 |
+
* @return Nested associative array
|
143 |
+
*/
|
144 |
+
public function xml_to_array($contents, $get_attributes=1)
|
145 |
+
{
|
146 |
+
if (!$contents)
|
147 |
+
return array();
|
148 |
+
|
149 |
+
if (!function_exists('xml_parser_create'))
|
150 |
+
{
|
151 |
+
$this->debug_print("ERROR: xml_parser_create function doesn't exist!");
|
152 |
+
return array();
|
153 |
+
}
|
154 |
+
|
155 |
+
$parser = xml_parser_create();
|
156 |
+
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
|
157 |
+
xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
|
158 |
+
xml_parse_into_struct( $parser, $contents, $xml_values );
|
159 |
+
xml_parser_free( $parser );
|
160 |
+
|
161 |
+
if (!$xml_values)
|
162 |
+
{
|
163 |
+
$this->debug_print("WARN: Could not parse xml_values!");
|
164 |
+
return;
|
165 |
+
}
|
166 |
+
|
167 |
+
$xml_array = array();
|
168 |
+
$parents = array();
|
169 |
+
$opened_tags = array();
|
170 |
+
$arr = array();
|
171 |
+
|
172 |
+
$current = &$xml_array;
|
173 |
+
|
174 |
+
foreach( $xml_values as $data)
|
175 |
+
{
|
176 |
+
unset($attributes,$value);
|
177 |
+
extract($data);
|
178 |
+
|
179 |
+
$result = '';
|
180 |
+
if ($get_attributes)
|
181 |
+
{
|
182 |
+
$result = array();
|
183 |
+
if (isset($value))
|
184 |
+
$result['value'] = $value;
|
185 |
+
if (isset($attributes))
|
186 |
+
{
|
187 |
+
foreach ($attributes as $attr => $val)
|
188 |
+
{
|
189 |
+
if ($get_attributes == 1)
|
190 |
+
$result['attr'][$attr] = $val;
|
191 |
+
}
|
192 |
+
}
|
193 |
+
}
|
194 |
+
elseif (isset($value))
|
195 |
+
$result = $value;
|
196 |
+
|
197 |
+
if ($type == "open")
|
198 |
+
{
|
199 |
+
$parent[$level-1] = &$current;
|
200 |
+
if (!is_array($current) || !in_array($tag, array_keys($current)))
|
201 |
+
{
|
202 |
+
$current[$tag] = $result;
|
203 |
+
$current = &$current[$tag];
|
204 |
+
}
|
205 |
+
else
|
206 |
+
{
|
207 |
+
if (isset($current[$tag][0]))
|
208 |
+
array_push($current[$tag], $result);
|
209 |
+
else
|
210 |
+
$current[$tag] = array($current[$tag],$result);
|
211 |
+
|
212 |
+
$last = count($current[$tag]) - 1;
|
213 |
+
$current = &$current[$tag][$last];
|
214 |
+
}
|
215 |
+
}
|
216 |
+
elseif ($type == "complete")
|
217 |
+
{
|
218 |
+
if (!isset($current[$tag]))
|
219 |
+
$current[$tag] = $result;
|
220 |
+
else
|
221 |
+
{
|
222 |
+
if ((is_array($current[$tag]) and $get_attributes == 0) || (isset($current[$tag][0]) and is_array($current[$tag][0]) and $get_attributes == 1))
|
223 |
+
array_push($current[$tag],$result);
|
224 |
+
else
|
225 |
+
$current[$tag] = array($current[$tag],$result);
|
226 |
+
}
|
227 |
+
}
|
228 |
+
elseif ($type == 'close')
|
229 |
+
$current = &$parent[$level-1];
|
230 |
+
}
|
231 |
+
return($xml_array);
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Converts id URL to numeric id
|
236 |
+
*
|
237 |
+
* @param String $url - ID URL
|
238 |
+
* @return Numeric ID
|
239 |
+
*/
|
240 |
+
public function id_from_url($url)
|
241 |
+
{
|
242 |
+
$temp = Array();
|
243 |
+
$temp = explode('/',trim($url));
|
244 |
+
return trim($temp[count($temp)-1]);
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Retrieves the XML service document
|
249 |
+
*
|
250 |
+
* @return XML service document
|
251 |
+
*/
|
252 |
+
public function get_service_doc_xml()
|
253 |
+
{
|
254 |
+
$url=$this->api_url;
|
255 |
+
$post='';
|
256 |
+
$response=$this->fetch($url,$post,'xml');
|
257 |
+
return $response;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
//Contact Functions
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Formats a contact array into the format we always return as
|
265 |
+
* Note:
|
266 |
+
* I like to do this because the atom specification has so much extraneous data
|
267 |
+
* that I just don't care about. This makes a sane array out of what is
|
268 |
+
* incredibly overcomplicated in my opinion.
|
269 |
+
*
|
270 |
+
* @param Array - Contact array as returned from fetch/xml_to_array
|
271 |
+
* @return Associative array in the format returned by this api
|
272 |
+
*/
|
273 |
+
public function format_contact($response)
|
274 |
+
{
|
275 |
+
$my_data = Array();
|
276 |
+
$my_data = $response['entry']['content']['Contact'];
|
277 |
+
$d = Array();
|
278 |
+
$d['ContactID'] = $this->id_from_url($my_data['attr']['id']);
|
279 |
+
unset($my_data['attr']);
|
280 |
+
foreach ($my_data as $dkey => $dval)
|
281 |
+
{
|
282 |
+
if ($dkey != 'ContactLists')
|
283 |
+
$d[$dkey] = $dval['value'];
|
284 |
+
else
|
285 |
+
{
|
286 |
+
$entries = Array();
|
287 |
+
if (isset($dval['ContactList']['link']))
|
288 |
+
$entries[] = $dval['ContactList'];
|
289 |
+
else
|
290 |
+
$entries = $dval['ContactList'];
|
291 |
+
|
292 |
+
foreach ($entries as $entry)
|
293 |
+
{
|
294 |
+
$e = Array();
|
295 |
+
$e['ListID'] = $this->id_from_url($entry['attr']['id']);
|
296 |
+
unset($entry['attr']);
|
297 |
+
unset($entry['link']);
|
298 |
+
foreach ($entry as $ekey => $eval)
|
299 |
+
$e[$ekey] = $eval['value'];
|
300 |
+
$d[$dkey][] = $e;
|
301 |
+
}
|
302 |
+
}
|
303 |
+
}
|
304 |
+
return $d;
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Return your list of contacts.
|
309 |
+
*
|
310 |
+
* @param String $key - Optionally specify a key to use for the array
|
311 |
+
* @param Boolean $unique - Whether the key you specified is unique
|
312 |
+
* @return Associative array containing your contacts indexed by whatever key specified.
|
313 |
+
*/
|
314 |
+
public function get_contacts($key='',$unique=true)
|
315 |
+
{
|
316 |
+
$ret = Array();
|
317 |
+
|
318 |
+
$url = $this->api['url'].'contacts';
|
319 |
+
$post = '';
|
320 |
+
$response = Array();
|
321 |
+
$response = $this->fetch($url,$post);
|
322 |
+
|
323 |
+
$entries = Array();
|
324 |
+
if (isset($response['feed']['entry']['link']))
|
325 |
+
$entries[] = $response['feed']['entry'];
|
326 |
+
else
|
327 |
+
$entries = $response['feed']['entry'];
|
328 |
+
foreach ($entries as $data)
|
329 |
+
{
|
330 |
+
$my_data = Array();
|
331 |
+
$my_data = $data['content']['Contact'];
|
332 |
+
$d = Array();
|
333 |
+
$d['ContactID'] = $this->id_from_url($my_data['attr']['id']);
|
334 |
+
unset($my_data['attr']);
|
335 |
+
foreach ($my_data as $dkey => $dval)
|
336 |
+
$d[$dkey] = $dval['value'];
|
337 |
+
|
338 |
+
if ($key)
|
339 |
+
{
|
340 |
+
if ($unique)
|
341 |
+
$ret[$d[$key]] = $d;
|
342 |
+
else
|
343 |
+
$ret[$d[$key]][] = $d;
|
344 |
+
}
|
345 |
+
else
|
346 |
+
$ret[] = $d;
|
347 |
+
}
|
348 |
+
return $ret;
|
349 |
+
}
|
350 |
+
|
351 |
+
/**
|
352 |
+
* Add a contact
|
353 |
+
* See Contact Data Format at http://developer.constantcontact.com/doc/contactCollection for all fields
|
354 |
+
*
|
355 |
+
* @param Array $data - An associative array containing all the contact data to add
|
356 |
+
* @param Array $lists - An array of list_ids to add this contact to
|
357 |
+
* @return Integer - ContactID for the new entry
|
358 |
+
*/
|
359 |
+
public function add_contact($data,$lists)
|
360 |
+
{
|
361 |
+
|
362 |
+
$updated = date('Y-m-d\TH:i:s\Z');
|
363 |
+
$xml_string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><entry xmlns='http://www.w3.org/2005/Atom'></entry>";
|
364 |
+
$xml_object = simplexml_load_string($xml_string);
|
365 |
+
$xml_object->addChild("title");
|
366 |
+
$xml_object->addChild("updated",$updated);
|
367 |
+
$author_node = $xml_object->addChild("author");
|
368 |
+
$author_node->addChild("name", ("CTCT Samples"));
|
369 |
+
$xml_object->addChild("id", 'data:,none');
|
370 |
+
$summary_node = $xml_object->addChild("summary");
|
371 |
+
$summary_node->addAttribute("type", "text");
|
372 |
+
$content_node = $xml_object->addChild("content");
|
373 |
+
$content_node->addAttribute("type", "application/vnd.ctct+xml");
|
374 |
+
$contact_node = $content_node->addChild("Contact");
|
375 |
+
$contact_node->addAttribute("xmlns", "http://ws.constantcontact.com/ns/1.0/");
|
376 |
+
$contact_node->addChild("OptInSource", 'ACTION_BY_CUSTOMER');
|
377 |
+
|
378 |
+
foreach ( $data as $key => $val )
|
379 |
+
{
|
380 |
+
$contact_node->addChild($key, $val);
|
381 |
+
}
|
382 |
+
|
383 |
+
$contactlists_node = $contact_node->addChild("ContactLists");
|
384 |
+
foreach ( $lists as $list )
|
385 |
+
{
|
386 |
+
$listNode = $contactlists_node->addChild("ContactList");
|
387 |
+
$listNode->addAttribute("id", $list);
|
388 |
+
}
|
389 |
+
|
390 |
+
$entry = $xml_object->asXML();
|
391 |
+
|
392 |
+
$url= $this->api['url'].'contacts';
|
393 |
+
|
394 |
+
$response = Array();
|
395 |
+
$response = $this->fetch($url, $entry);
|
396 |
+
if ( $this->debug['last_response'] <= 204 )
|
397 |
+
return $this->id_from_url($response['entry']['id']['value']);
|
398 |
+
else
|
399 |
+
return false;
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Returns detailed info for a particular contact.
|
404 |
+
*
|
405 |
+
* @param Integer $id - Contact ID of the contact requested.
|
406 |
+
* @return Associative array containing the contact's details
|
407 |
+
*/
|
408 |
+
public function get_contact($id)
|
409 |
+
{
|
410 |
+
$url = $this->api['url'].'contacts/'.$id;
|
411 |
+
$post = '';
|
412 |
+
$contact = Array();
|
413 |
+
$contact = $this->format_contact($this->fetch($url,$post));
|
414 |
+
|
415 |
+
if ($this->debug['last_response'] <= 204)
|
416 |
+
return $contact;
|
417 |
+
else
|
418 |
+
return false;
|
419 |
+
}
|
420 |
+
|
421 |
+
/**
|
422 |
+
* Edit a contact
|
423 |
+
* See Contact Data Format at http://developer.constantcontact.com/doc/contactCollection for all fields
|
424 |
+
*
|
425 |
+
* @param Integer $id - Contact ID of the contact to edit
|
426 |
+
* @param Array $data - An associative array containing all the contact data to edit
|
427 |
+
* @return Boolean - True on success and false on failure
|
428 |
+
*/
|
429 |
+
public function edit_contact($id,$data)
|
430 |
+
{
|
431 |
+
//Get the old xml from get_contact() and then post after replacing values that need replacing
|
432 |
+
$url = $this->api['url'].'contacts/'.$id;
|
433 |
+
$post = '';
|
434 |
+
$post = $this->fetch($url,$post,'xml');
|
435 |
+
|
436 |
+
foreach ($data as $key => $val)
|
437 |
+
$post = preg_replace("/<$key>.*?<\/{$key}>/s","<$key>$val</$key>",$post);
|
438 |
+
|
439 |
+
$this->fetch($url,$post,'array','PUT');
|
440 |
+
|
441 |
+
if ($this->debug['last_response'] <= 204)
|
442 |
+
return true;
|
443 |
+
else
|
444 |
+
return false;
|
445 |
+
}
|
446 |
+
|
447 |
+
/**
|
448 |
+
* Delete a contact
|
449 |
+
*
|
450 |
+
* @param Integer $id - Contact ID of the contact to delete
|
451 |
+
* @return Boolean - True on success and false on failure
|
452 |
+
*/
|
453 |
+
public function delete_contact($id)
|
454 |
+
{
|
455 |
+
//Get the old xml from get_contact() and then post after replacing values that need replacing
|
456 |
+
$url = $this->api['url'].'contacts/'.$id;
|
457 |
+
$post = '';
|
458 |
+
$this->fetch($url,$post,'array','DELETE');
|
459 |
+
|
460 |
+
if ($this->debug['last_response'] <= 204)
|
461 |
+
return true;
|
462 |
+
else
|
463 |
+
return false;
|
464 |
+
}
|
465 |
+
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Search for a contact by email
|
469 |
+
* See Contact Data Format at http://developer.constantcontact.com/doc/contactCollection for all fields
|
470 |
+
*
|
471 |
+
* @param String $email - Email address of the contact to search for
|
472 |
+
* @param Boolean $id_only - If true will return ContactID found otherwise will return all contact info
|
473 |
+
* @return Integer of found ContactID or Associative Array of contact info for found contact
|
474 |
+
*/
|
475 |
+
public function search_contact_by_email($email,$id_only=true)
|
476 |
+
{
|
477 |
+
//Get the old xml from get_contact() and then post after replacing values that need replacing
|
478 |
+
$url = $this->api['url'].'contacts?email='.urlencode(strtolower($email));
|
479 |
+
$response = Array();
|
480 |
+
$response = $this->fetch($url,$post);
|
481 |
+
|
482 |
+
if ($this->debug['last_response'] <= 204)
|
483 |
+
{
|
484 |
+
if ($id_only)
|
485 |
+
return $this->id_from_url($response['feed']['entry']['id']['value']);
|
486 |
+
else
|
487 |
+
return $this->get_contact($this->id_from_url($response['feed']['entry']['id']['value']));
|
488 |
+
}
|
489 |
+
else
|
490 |
+
return false;
|
491 |
+
}
|
492 |
+
|
493 |
+
/**
|
494 |
+
* Returns contacts updated since date your list of contacts.
|
495 |
+
*
|
496 |
+
* @param Date $date - Date should be in the format "Y-m-d H:i:s" (this is the datetime mysql spec)
|
497 |
+
* @param String $list_type - Type of contact to query for: active,removed,do-not-mail
|
498 |
+
* @param String $key - Optionally specify a key to use for the array
|
499 |
+
* @param Boolean $unique - Whether the key you specified is unique
|
500 |
+
* @return Associative array containing your contacts indexed by whatever key specified.
|
501 |
+
*/
|
502 |
+
public function search_contacts_by_date($date,$list_type='active',$key='',$unique=true)
|
503 |
+
{
|
504 |
+
//Format date to UTC atom spec
|
505 |
+
$atom_date = date('Y-m-d\TH:i:s\Z',strtotime($date)+date("Z"));
|
506 |
+
|
507 |
+
$ret = Array();
|
508 |
+
|
509 |
+
$url = $this->api['url'].'contacts?updatedsince='.$atom_date.'&listtype='.$list_type;
|
510 |
+
$post = '';
|
511 |
+
$response = Array();
|
512 |
+
$response = $this->fetch($url,$post);
|
513 |
+
|
514 |
+
$entries = Array();
|
515 |
+
if (isset($response['feed']['entry']['link']))
|
516 |
+
$entries[] = $response['feed']['entry'];
|
517 |
+
else
|
518 |
+
$entries = $response['feed']['entry'];
|
519 |
+
foreach ($entries as $data)
|
520 |
+
{
|
521 |
+
$my_data = Array();
|
522 |
+
$my_data = $data['content']['Contact'];
|
523 |
+
$d = Array();
|
524 |
+
$d['ContactID'] = $this->id_from_url($my_data['attr']['id']);
|
525 |
+
unset($my_data['attr']);
|
526 |
+
foreach ($my_data as $dkey => $dval)
|
527 |
+
$d[$dkey] = $dval['value'];
|
528 |
+
|
529 |
+
if ($key)
|
530 |
+
{
|
531 |
+
if ($unique)
|
532 |
+
$ret[$d[$key]] = $d;
|
533 |
+
else
|
534 |
+
$ret[$d[$key]][] = $d;
|
535 |
+
}
|
536 |
+
else
|
537 |
+
$ret[] = $d;
|
538 |
+
}
|
539 |
+
return $ret;
|
540 |
+
}
|
541 |
+
|
542 |
+
//List Functions
|
543 |
+
|
544 |
+
/**
|
545 |
+
* Formats a list array into the format we always return as
|
546 |
+
* Note:
|
547 |
+
* I like to do this because the atom specification has so much extraneous data
|
548 |
+
* that I just don't care about it. This makes a sane array out of what is
|
549 |
+
* incredibly overcomplicated in my opinion.
|
550 |
+
*
|
551 |
+
* @param Array - Contact array as returned from fetch/xml_to_array
|
552 |
+
* @return Associative array in the format returned by this api
|
553 |
+
*/
|
554 |
+
public function format_list($response)
|
555 |
+
{
|
556 |
+
$my_data = Array();
|
557 |
+
$my_data = $response['entry']['content']['ContactList'];
|
558 |
+
$d = Array();
|
559 |
+
$d['ListID'] = $this->id_from_url($my_data['attr']['id']);
|
560 |
+
unset($my_data['attr']);
|
561 |
+
unset($my_data['Members']);
|
562 |
+
foreach ($my_data as $key => $val)
|
563 |
+
$d[$key] = $val['value'];
|
564 |
+
return $d;
|
565 |
+
}
|
566 |
+
|
567 |
+
/**
|
568 |
+
* Add a list
|
569 |
+
* See List Data Format at http://developer.constantcontact.com/doc/contactLists for all fields
|
570 |
+
*
|
571 |
+
* @param Array $data - An associative array containing all the contact data to add
|
572 |
+
* @return Integer - ListID for the new entry
|
573 |
+
*/
|
574 |
+
public function add_list($data)
|
575 |
+
{
|
576 |
+
$updated = date('Y-m-d\TH:i:s\Z');
|
577 |
+
$post = <<<end
|
578 |
+
<entry xmlns="http://www.w3.org/2005/Atom">
|
579 |
+
<title type="text"> </title>
|
580 |
+
<updated>{$updated}</updated>
|
581 |
+
<author></author>
|
582 |
+
<id>data:,none</id>
|
583 |
+
<summary type="text">Contact</summary>
|
584 |
+
<content type="application/vnd.ctct+xml">
|
585 |
+
<ContactList xmlns="http://ws.constantcontact.com/ns/1.0/">
|
586 |
+
|
587 |
+
end;
|
588 |
+
|
589 |
+
foreach ($data as $key => $val)
|
590 |
+
$post .= "\t\t\t<$key>{$val}</$key>\n";
|
591 |
+
|
592 |
+
$post .= <<<end
|
593 |
+
</ContactList>
|
594 |
+
</content>
|
595 |
+
</entry>
|
596 |
+
end;
|
597 |
+
|
598 |
+
|
599 |
+
$url= $this->api['url'].'lists';
|
600 |
+
|
601 |
+
$response = Array();
|
602 |
+
$response = $this->fetch($url,$post);
|
603 |
+
if ($this->debug['last_response'] <= 204)
|
604 |
+
return $this->id_from_url($response['entry']['id']['value']);
|
605 |
+
else
|
606 |
+
return false;
|
607 |
+
}
|
608 |
+
|
609 |
+
/**
|
610 |
+
* Returns detailed info for a particular list.
|
611 |
+
*
|
612 |
+
* @param Integer $id - ListID of the list requested.
|
613 |
+
* @return Associative array containing the list's details
|
614 |
+
*/
|
615 |
+
public function get_list($id)
|
616 |
+
{
|
617 |
+
$url = $this->api['url'].'lists/'.$id;
|
618 |
+
$post = '';
|
619 |
+
$list = Array();
|
620 |
+
$list = $this->format_list($this->fetch($url,$post));
|
621 |
+
|
622 |
+
if ($this->debug['last_response'] <= 204)
|
623 |
+
return $list;
|
624 |
+
else
|
625 |
+
return false;
|
626 |
+
}
|
627 |
+
|
628 |
+
/**
|
629 |
+
* Edit a list
|
630 |
+
* See List Data Format at http://developer.constantcontact.com/doc/contactLists for all fields
|
631 |
+
*
|
632 |
+
* @param Integer $id - List ID of the list to edit
|
633 |
+
* @param Array $data - An associative array containing all the list data to edit
|
634 |
+
* @return Boolean - True on success and false on failure
|
635 |
+
*/
|
636 |
+
public function edit_list($id,$data)
|
637 |
+
{
|
638 |
+
//Get the old xml from get_list() and then post after replacing values that need replacing
|
639 |
+
$url = $this->api['url'].'lists/'.$id;
|
640 |
+
$post = '';
|
641 |
+
$post = $this->fetch($url,$post,'xml');
|
642 |
+
|
643 |
+
foreach ($data as $key => $val)
|
644 |
+
$post = preg_replace("/<$key>.*?<\/{$key}>/s","<$key>$val</$key>",$post);
|
645 |
+
|
646 |
+
$this->fetch($url,$post,'array','PUT');
|
647 |
+
|
648 |
+
if ($this->debug['last_response'] <= 204)
|
649 |
+
return true;
|
650 |
+
else
|
651 |
+
return false;
|
652 |
+
}
|
653 |
+
|
654 |
+
/**
|
655 |
+
* Return your lists.
|
656 |
+
*
|
657 |
+
* @param String $key - Optionally specify a key to use for the array
|
658 |
+
* @param Boolean $unique - Whether the key you specified is unique
|
659 |
+
* @return Associative array containing your lists indexed by whatever key specified.
|
660 |
+
*/
|
661 |
+
public function get_lists($key='',$unique=true)
|
662 |
+
{
|
663 |
+
$ret = Array();
|
664 |
+
|
665 |
+
$url = $this->api['url'].'lists';
|
666 |
+
$post = '';
|
667 |
+
$response = Array();
|
668 |
+
$response = $this->fetch($url,$post);
|
669 |
+
|
670 |
+
$entries = Array();
|
671 |
+
if (isset($response['feed']['entry']['link']))
|
672 |
+
$entries[] = $response['feed']['entry'];
|
673 |
+
else
|
674 |
+
$entries = $response['feed']['entry'];
|
675 |
+
foreach ($entries as $data)
|
676 |
+
{
|
677 |
+
$my_data = Array();
|
678 |
+
$my_data = $data['content']['ContactList'];
|
679 |
+
$d = Array();
|
680 |
+
//$d['ListID'] = $this->id_from_url($my_data['attr']['id']);
|
681 |
+
$d['ListID'] = $my_data['attr']['id'];
|
682 |
+
|
683 |
+
// Exclude the default lists like active, do-not-mail and removed
|
684 |
+
if ( ! is_numeric($this->id_from_url($my_data['attr']['id'])) )
|
685 |
+
continue;
|
686 |
+
|
687 |
+
unset($my_data['attr']);
|
688 |
+
foreach ($my_data as $dkey => $dval)
|
689 |
+
{
|
690 |
+
if ( isset($dval['value']) )
|
691 |
+
$d[$dkey] = $dval['value'];
|
692 |
+
}
|
693 |
+
|
694 |
+
if ($key)
|
695 |
+
{
|
696 |
+
if ($unique)
|
697 |
+
$ret[$d[$key]] = $d;
|
698 |
+
else
|
699 |
+
$ret[$d[$key]][] = $d;
|
700 |
+
}
|
701 |
+
else
|
702 |
+
$ret[] = $d;
|
703 |
+
}
|
704 |
+
return $ret;
|
705 |
+
}
|
706 |
+
|
707 |
+
/**
|
708 |
+
* Delete a list
|
709 |
+
*
|
710 |
+
* @param Integer $id - ListID of the list to delete
|
711 |
+
* @return Boolean - True on success and false on failure
|
712 |
+
*/
|
713 |
+
public function delete_list($id)
|
714 |
+
{
|
715 |
+
//Get the old xml from get_list() and then post after replacing values that need replacing
|
716 |
+
$url = $this->api['url'].'lists/'.$id;
|
717 |
+
$post = '';
|
718 |
+
$this->fetch($url,$post,'array','DELETE');
|
719 |
+
|
720 |
+
if ($this->debug['last_response'] <= 204)
|
721 |
+
return true;
|
722 |
+
else
|
723 |
+
return false;
|
724 |
+
}
|
725 |
+
|
726 |
+
//Subscription Functions
|
727 |
+
|
728 |
+
/**
|
729 |
+
* Add a subscription for an existing contact to a list
|
730 |
+
* See Contact Data Format at http://developer.constantcontact.com/doc/contactCollection for all fields
|
731 |
+
*
|
732 |
+
* @param Integer $contact_id - Contact ID of the contact to use
|
733 |
+
* @param Integer $list_id - List ID of the list to add the contact to
|
734 |
+
* @param String $optin_source - ACTION_BY_CUSTOMER or ACTION_BY_CLIENT depending on if this person is filling out a form for subscription in realtime
|
735 |
+
* @return Boolean - True on success and false on failure
|
736 |
+
*/
|
737 |
+
public function add_subscription($contact_id,$list_id,$optin_source='ACTION_BY_CUSTOMER')
|
738 |
+
{
|
739 |
+
//Get the old xml from get_contact() and then post after replacing values that need replacing
|
740 |
+
$url = $this->api['url'].'contacts/'.$contact_id;
|
741 |
+
$post = '';
|
742 |
+
$post = $this->fetch($url,$post,'xml');
|
743 |
+
|
744 |
+
if (!strstr($post,'</ContactLists>'))
|
745 |
+
$post = str_replace('</Contact>',"<ContactLists></ContactLists></Contact>",$post);
|
746 |
+
|
747 |
+
if (!strstr($post,'<OptInSource>'))
|
748 |
+
$post = str_replace('</Confirmed>',"</Confirmed>\n<OptInSource>$optin_source</OptInSource>",$post);
|
749 |
+
|
750 |
+
if (!strstr($post,'<ContactList id="'.$this->api['inner_url'].'lists/'.$list_id.'">'))
|
751 |
+
$post = str_replace('</ContactLists>','<ContactList id="'.$this->api['inner_url'].'lists/'.$list_id.'"></ContactList></ContactLists>',$post);
|
752 |
+
|
753 |
+
$this->fetch($url,$post,'array','PUT');
|
754 |
+
|
755 |
+
if ($this->debug['last_response'] <= 204)
|
756 |
+
return true;
|
757 |
+
else
|
758 |
+
return false;
|
759 |
+
}
|
760 |
+
|
761 |
+
/**
|
762 |
+
* Remove a subscription for an existing contact to a list
|
763 |
+
* See Contact Data Format at http://developer.constantcontact.com/doc/contactCollection for all fields
|
764 |
+
*
|
765 |
+
* @param Integer $contact_id - Contact ID of the contact to use
|
766 |
+
* @param Integer $list_id - List ID of the list to add the contact to
|
767 |
+
* @return Boolean - True on success and false on failure
|
768 |
+
*/
|
769 |
+
public function remove_subscription($contact_id,$list_id)
|
770 |
+
{
|
771 |
+
//Get the old xml from get_contact() and then post after replacing values that need replacing
|
772 |
+
$url = $this->api['url'].'contacts/'.$contact_id;
|
773 |
+
$post = '';
|
774 |
+
$post = $this->fetch($url,$post,'xml');
|
775 |
+
|
776 |
+
$post = preg_replace('/<ContactList id="'.str_replace('/','\/',$this->api['inner_url']).'lists\/'.$list_id.'">.*?<\/ContactList>/s','',$post);
|
777 |
+
|
778 |
+
$this->fetch($url,$post,'array','PUT');
|
779 |
+
|
780 |
+
if ($this->debug['last_response'] <= 204)
|
781 |
+
return true;
|
782 |
+
else
|
783 |
+
return false;
|
784 |
+
}
|
785 |
+
|
786 |
+
//Campaign Functions
|
787 |
+
|
788 |
+
/**
|
789 |
+
* Formats a campaign array into the format we always return as
|
790 |
+
* Note:
|
791 |
+
* I like to do this because the atom specification has so much extraneous data
|
792 |
+
* that I just don't care about it. This makes a sane array out of what is
|
793 |
+
* incredibly overcomplicated in my opinion.
|
794 |
+
*
|
795 |
+
* @param Array - Contact array as returned from fetch/xml_to_array
|
796 |
+
* @return Associative array in the format returned by this api
|
797 |
+
*/
|
798 |
+
public function format_campaign($response)
|
799 |
+
{
|
800 |
+
$my_data = Array();
|
801 |
+
$my_data = $response['entry']['content']['Campaign'];
|
802 |
+
$d = Array();
|
803 |
+
$d['CampaignID'] = $this->id_from_url($my_data['attr']['id']);
|
804 |
+
$d['FromID'] = $this->id_from_url($my_data['FromEmail']['Email']['attr']['id']);
|
805 |
+
$d['FromEmail'] = $my_data['FromEmail']['EmailAddress']['value'];
|
806 |
+
unset($my_data['FromEmail']);
|
807 |
+
unset($my_data['ReplyToEmail']);
|
808 |
+
|
809 |
+
unset($my_data['attr']);
|
810 |
+
foreach ($my_data as $dkey => $dval)
|
811 |
+
{
|
812 |
+
if ($dkey != 'ContactLists')
|
813 |
+
$d[$dkey] = $dval['value'];
|
814 |
+
else
|
815 |
+
{
|
816 |
+
$entries = Array();
|
817 |
+
if (isset($dval['ContactList']['link']))
|
818 |
+
$entries[] = $dval['ContactList'];
|
819 |
+
else
|
820 |
+
$entries = $dval['ContactList'];
|
821 |
+
|
822 |
+
foreach ($entries as $entry)
|
823 |
+
{
|
824 |
+
$e = Array();
|
825 |
+
$e['ListID'] = $this->id_from_url($entry['attr']['id']);
|
826 |
+
unset($entry['attr']);
|
827 |
+
unset($entry['link']);
|
828 |
+
foreach ($entry as $ekey => $eval)
|
829 |
+
$e[$ekey] = $eval['value'];
|
830 |
+
$d[$dkey][] = $e;
|
831 |
+
}
|
832 |
+
}
|
833 |
+
}
|
834 |
+
return $d;
|
835 |
+
}
|
836 |
+
|
837 |
+
/**
|
838 |
+
* Return your campaigns.
|
839 |
+
*
|
840 |
+
* @param String $key - Optionally specify a key to use for the array
|
841 |
+
* @param Boolean $unique - Whether the key you specified is unique
|
842 |
+
* @return Associative array containing your lists indexed by whatever key specified.
|
843 |
+
*/
|
844 |
+
public function get_campaigns($key='',$unique=true)
|
845 |
+
{
|
846 |
+
$ret = Array();
|
847 |
+
|
848 |
+
$url = $this->api['url'].'campaigns';
|
849 |
+
$post = '';
|
850 |
+
$response = Array();
|
851 |
+
$response = $this->fetch($url,$post);
|
852 |
+
|
853 |
+
$entries = Array();
|
854 |
+
if (isset($response['feed']['entry']['link']))
|
855 |
+
$entries[] = $response['feed']['entry'];
|
856 |
+
else
|
857 |
+
$entries = $response['feed']['entry'];
|
858 |
+
foreach ($entries as $data)
|
859 |
+
{
|
860 |
+
$my_data = Array();
|
861 |
+
$my_data = $data['content']['Campaign'];
|
862 |
+
$d = Array();
|
863 |
+
$d['CampaignID'] = $this->id_from_url($my_data['attr']['id']);
|
864 |
+
unset($my_data['attr']);
|
865 |
+
foreach ($my_data as $dkey => $dval)
|
866 |
+
$d[$dkey] = $dval['value'];
|
867 |
+
|
868 |
+
if ($key)
|
869 |
+
{
|
870 |
+
if ($unique)
|
871 |
+
$ret[$d[$key]] = $d;
|
872 |
+
else
|
873 |
+
$ret[$d[$key]][] = $d;
|
874 |
+
}
|
875 |
+
else
|
876 |
+
$ret[] = $d;
|
877 |
+
}
|
878 |
+
return $ret;
|
879 |
+
}
|
880 |
+
|
881 |
+
/**
|
882 |
+
* Add a campaign
|
883 |
+
* See Campaign Data Format at http://developer.constantcontact.com/doc/manageCampaigns for all fields
|
884 |
+
*
|
885 |
+
* @param Array $data - An associative array containing all the campaign data to add
|
886 |
+
* @param Array $lists - An array of ListIDs to have this campaign send to
|
887 |
+
* @param Array $from_id - FromID to use as the from email address
|
888 |
+
* @return Integer - CampaignID for the new entry
|
889 |
+
*/
|
890 |
+
public function add_campaign($data,$lists,$from_id)
|
891 |
+
{
|
892 |
+
$updated = date('Y-m-d\TH:i:s\Z');
|
893 |
+
$post = <<<end
|
894 |
+
<entry xmlns="http://www.w3.org/2005/Atom">
|
895 |
+
<link href="{$this->api['relative_url']}campaigns" rel="edit" />
|
896 |
+
<id>{$this->api['inner_url']}campaigns</id>
|
897 |
+
<title type="text">{$data['Name']}</title>
|
898 |
+
<updated>{$updated}</updated>
|
899 |
+
<author>
|
900 |
+
<name>Constant Contact</name>
|
901 |
+
</author>
|
902 |
+
<content type="application/vnd.ctct+xml">
|
903 |
+
<Campaign xmlns="http://ws.constantcontact.com/ns/1.0/" id="{$this->api['inner_url']}campaigns/">
|
904 |
+
|
905 |
+
end;
|
906 |
+
|
907 |
+
foreach ($data as $key => $val)
|
908 |
+
{
|
909 |
+
if ($key == 'Date')
|
910 |
+
$val = date('Y-m-d\TH:i:s\Z',strtotime($val)+date("Z"));
|
911 |
+
elseif ($key == 'EmailContent' || $key == 'StyleSheet' || $key == 'PermissionReminderText')
|
912 |
+
$val = urlencode($val);
|
913 |
+
elseif ($key == 'TextContent')
|
914 |
+
$val = urlencode('<Text>'.$val.'</Text>');
|
915 |
+
|
916 |
+
$post .= "\t\t\t<$key>{$val}</$key>\n";
|
917 |
+
}
|
918 |
+
|
919 |
+
$post .= "\t\t\t<ContactLists>\n";
|
920 |
+
foreach ($lists as $list_id)
|
921 |
+
$post .= "\t\t\t\t<ContactList id=\"{$this->api['inner_url']}lists/{$list_id}\" />\n";
|
922 |
+
|
923 |
+
$temp = Array();
|
924 |
+
$temp = get_from($from_id);
|
925 |
+
$email = $temp['EmailAddress'];
|
926 |
+
|
927 |
+
$post .= <<<end
|
928 |
+
</ContactLists>
|
929 |
+
<FromEmail>
|
930 |
+
<Email id="{$this->api['inner_url']}emailaddresses/$from_id">
|
931 |
+
<link xmlns="http://www.w3.org/2005/Atom" href="{$this->api['inner_url']}emailaddresses/$from_id" rel="self" />
|
932 |
+
</Email>
|
933 |
+
<EmailAddress>$email</EmailAddress>
|
934 |
+
</FromEmail>
|
935 |
+
<ReplyToEmail>
|
936 |
+
<Email id="{$this->api['inner_url']}emailaddresses/$from_id">
|
937 |
+
<link xmlns="http://www.w3.org/2005/Atom" href="{$this->api['inner_url']}emailaddresses/$from_id" rel="self" />
|
938 |
+
</Email>
|
939 |
+
<EmailAddress>$email</EmailAddress>
|
940 |
+
</ReplyToEmail>
|
941 |
+
|
942 |
+
end;
|
943 |
+
|
944 |
+
$post .= <<<end
|
945 |
+
</Campaign>
|
946 |
+
</content>
|
947 |
+
</entry>
|
948 |
+
end;
|
949 |
+
|
950 |
+
|
951 |
+
$url= $this->api['url'].'contacts';
|
952 |
+
|
953 |
+
$response = Array();
|
954 |
+
$response = $this->fetch($url,$post);
|
955 |
+
if ($this->debug['last_response'] <= 204)
|
956 |
+
return $this->id_from_url($response['entry']['id']['value']);
|
957 |
+
else
|
958 |
+
return false;
|
959 |
+
}
|
960 |
+
|
961 |
+
/**
|
962 |
+
* Returns detailed info for a particular campaign.
|
963 |
+
*
|
964 |
+
* @param Integer $id - Campaign ID of the campaign requested.
|
965 |
+
* @return Associative array containing the campaign's details
|
966 |
+
*/
|
967 |
+
public function get_campaign($id)
|
968 |
+
{
|
969 |
+
$url = $this->api['url'].'campaigns/'.$id;
|
970 |
+
$post = '';
|
971 |
+
$campaign = Array();
|
972 |
+
$campaign = $this->format_campaign($this->fetch($url,$post));
|
973 |
+
|
974 |
+
if ($this->debug['last_response'] <= 204)
|
975 |
+
return $campaign;
|
976 |
+
else
|
977 |
+
return false;
|
978 |
+
}
|
979 |
+
|
980 |
+
/**
|
981 |
+
* Edit a campaign
|
982 |
+
* See Campaign Data Format at http://developer.constantcontact.com/doc/manageCampaigns for all fields
|
983 |
+
*
|
984 |
+
* @param Integer $id - Campaign ID of the list to edit
|
985 |
+
* @param Array $data - An associative array containing all the campaign data to edit
|
986 |
+
* @return Boolean - True on success and false on failure
|
987 |
+
*/
|
988 |
+
public function edit_campaign($id,$data)
|
989 |
+
{
|
990 |
+
//Get the old xml from get_campaign() and then post after replacing values that need replacing
|
991 |
+
$url = $this->api['url'].'campaigns/'.$id;
|
992 |
+
$post = '';
|
993 |
+
$post = $this->fetch($url,$post,'xml');
|
994 |
+
|
995 |
+
foreach ($data as $key => $val)
|
996 |
+
$post = preg_replace("/<$key>.*?<\/{$key}>/s","<$key>$val</$key>",$post);
|
997 |
+
|
998 |
+
$this->fetch($url,$post,'array','PUT');
|
999 |
+
|
1000 |
+
if ($this->debug['last_response'] <= 204)
|
1001 |
+
return true;
|
1002 |
+
else
|
1003 |
+
return false;
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
/**
|
1007 |
+
* Delete a campaign
|
1008 |
+
*
|
1009 |
+
* @param Integer $id - CampaignID of the list to delete
|
1010 |
+
* @return Boolean - True on success and false on failure
|
1011 |
+
*/
|
1012 |
+
public function delete_campaign($id)
|
1013 |
+
{
|
1014 |
+
//Get the old xml from get_campaign() and then post after replacing values that need replacing
|
1015 |
+
$url = $this->api['url'].'campaigns/'.$id;
|
1016 |
+
$post = '';
|
1017 |
+
$this->fetch($url,$post,'array','DELETE');
|
1018 |
+
|
1019 |
+
if ($this->debug['last_response'] <= 204)
|
1020 |
+
return true;
|
1021 |
+
else
|
1022 |
+
return false;
|
1023 |
+
}
|
1024 |
+
|
1025 |
+
//From Functions
|
1026 |
+
|
1027 |
+
/**
|
1028 |
+
* Formats a list array into the format we always return as
|
1029 |
+
* Note:
|
1030 |
+
* I like to do this because the atom specification has so much extraneous data
|
1031 |
+
* that I just don't care about. This makes a sane array out of what is
|
1032 |
+
* incredibly overcomplicated in my opinion.
|
1033 |
+
*
|
1034 |
+
* @param Array - Contact array as returned from fetch/xml_to_array
|
1035 |
+
* @return Associative array in the format returned by this api
|
1036 |
+
*/
|
1037 |
+
public function format_from($response)
|
1038 |
+
{
|
1039 |
+
$my_data = Array();
|
1040 |
+
$my_data = $response['entry']['content']['Email'];
|
1041 |
+
$d = Array();
|
1042 |
+
$d['FromID'] = $this->id_from_url($my_data['attr']['id']);
|
1043 |
+
unset($my_data['attr']);
|
1044 |
+
foreach ($my_data as $key => $val)
|
1045 |
+
$d[$key] = $val['value'];
|
1046 |
+
return $d;
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
/**
|
1050 |
+
* Returns detailed info for a particular list.
|
1051 |
+
*
|
1052 |
+
* @param Integer $id - FromID of the from email requested.
|
1053 |
+
* @return Associative array containing the from's details
|
1054 |
+
*/
|
1055 |
+
public function get_from($id)
|
1056 |
+
{
|
1057 |
+
$url = $this->api['url'].'settings/emailaddresses/'.$id;
|
1058 |
+
$post = '';
|
1059 |
+
$from = Array();
|
1060 |
+
$from = $this->format_from($this->fetch($url,$post));
|
1061 |
+
|
1062 |
+
if ($this->debug['last_response'] <= 204)
|
1063 |
+
return $from;
|
1064 |
+
else
|
1065 |
+
return false;
|
1066 |
+
}
|
1067 |
+
|
1068 |
+
/**
|
1069 |
+
* Return your from email addresses.
|
1070 |
+
*
|
1071 |
+
* @param String $key - Optionally specify a key to use for the array
|
1072 |
+
* @param Boolean $unique - Whether the key you specified is unique
|
1073 |
+
* @return Associative array containing your lists indexed by whatever key specified.
|
1074 |
+
*/
|
1075 |
+
public function get_froms($key='',$unique=true)
|
1076 |
+
{
|
1077 |
+
$ret = Array();
|
1078 |
+
|
1079 |
+
$url = $this->api['url'].'settings/emailaddresses';
|
1080 |
+
$post = '';
|
1081 |
+
$response = Array();
|
1082 |
+
$response = $this->fetch($url,$post);
|
1083 |
+
|
1084 |
+
$entries = Array();
|
1085 |
+
if (isset($response['feed']['entry']['link']))
|
1086 |
+
$entries[] = $response['feed']['entry'];
|
1087 |
+
else
|
1088 |
+
$entries = $response['feed']['entry'];
|
1089 |
+
foreach ($entries as $data)
|
1090 |
+
{
|
1091 |
+
$my_data = Array();
|
1092 |
+
$my_data = $data['content']['Email'];
|
1093 |
+
$d = Array();
|
1094 |
+
$d['FromID'] = $this->id_from_url($my_data['attr']['id']);
|
1095 |
+
unset($my_data['attr']);
|
1096 |
+
foreach ($my_data as $dkey => $dval)
|
1097 |
+
$d[$dkey] = $dval['value'];
|
1098 |
+
|
1099 |
+
if ($key)
|
1100 |
+
{
|
1101 |
+
if ($unique)
|
1102 |
+
$ret[$d[$key]] = $d;
|
1103 |
+
else
|
1104 |
+
$ret[$d[$key]][] = $d;
|
1105 |
+
}
|
1106 |
+
else
|
1107 |
+
$ret[] = $d;
|
1108 |
+
}
|
1109 |
+
return $ret;
|
1110 |
+
}
|
1111 |
+
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
?>
|
power-ups/mailchimp-list-sync.php
CHANGED
@@ -92,7 +92,7 @@ class WPMailChimpListSync extends WPLeadIn {
|
|
92 |
|
93 |
if ( isset($options['li_mls_api_key']) && $options['li_mls_api_key'] && isset($options['li_mls_subscribers_to_list']) && $options['li_mls_subscribers_to_list'] )
|
94 |
{
|
95 |
-
$MailChimp = new
|
96 |
|
97 |
$subscribe = $MailChimp->call("lists/subscribe", array(
|
98 |
"id" => $options['li_mls_subscribers_to_list'],
|
92 |
|
93 |
if ( isset($options['li_mls_api_key']) && $options['li_mls_api_key'] && isset($options['li_mls_subscribers_to_list']) && $options['li_mls_subscribers_to_list'] )
|
94 |
{
|
95 |
+
$MailChimp = new LI_MailChimp($options['li_mls_api_key']);
|
96 |
|
97 |
$subscribe = $MailChimp->call("lists/subscribe", array(
|
98 |
"id" => $options['li_mls_subscribers_to_list'],
|
power-ups/mailchimp-list-sync/admin/mailchimp-list-sync-admin.php
CHANGED
@@ -82,25 +82,26 @@ class WPMailChimpListSyncAdmin extends WPLeadInAdmin {
|
|
82 |
function li_mls_subscribers_to_list_callback ()
|
83 |
{
|
84 |
$options = get_option('leadin_mls_options');
|
85 |
-
$li_mls_subscribers_to_list = ( isset($options['li_mls_subscribers_to_list']) ? $options['li_mls_subscribers_to_list'] : '' );
|
86 |
-
|
87 |
$lists = $this->li_mls_get_mailchimp_lists($options['li_mls_api_key']);
|
88 |
|
89 |
echo '<select id="li_mls_subscribers_to_list" name="leadin_mls_options[li_mls_subscribers_to_list]" ' . ( ! count($lists['data']) ? 'disabled' : '' ) . '>';
|
90 |
|
91 |
if ( count($lists['data']) )
|
92 |
{
|
|
|
|
|
93 |
foreach ( $lists['data'] as $list )
|
94 |
{
|
95 |
-
$list_set = FALSE;
|
96 |
if ( $list['id'] == $li_mls_subscribers_to_list && !$list_set )
|
97 |
$list_set = TRUE;
|
98 |
|
99 |
echo '<option ' . ( $list['id'] == $li_mls_subscribers_to_list ? 'selected' : '' ) . ' value="' . $list['id'] . '">' . $list['name'] . '</option>';
|
100 |
-
|
101 |
-
if ( !$list_set )
|
102 |
-
echo '<option selected value="">No list set...</option>';
|
103 |
}
|
|
|
|
|
|
|
104 |
}
|
105 |
else
|
106 |
{
|
@@ -114,7 +115,7 @@ class WPMailChimpListSyncAdmin extends WPLeadInAdmin {
|
|
114 |
|
115 |
function li_mls_get_mailchimp_lists ( $api_key )
|
116 |
{
|
117 |
-
$MailChimp = new
|
118 |
|
119 |
$lists = $MailChimp->call("lists/list", array(
|
120 |
"start" => 0, // optional, control paging of lists, start results at this list #, defaults to 1st page of data (page 0)
|
82 |
function li_mls_subscribers_to_list_callback ()
|
83 |
{
|
84 |
$options = get_option('leadin_mls_options');
|
85 |
+
$li_mls_subscribers_to_list = ( isset($options['li_mls_subscribers_to_list']) ? $options['li_mls_subscribers_to_list'] : '' );
|
86 |
+
|
87 |
$lists = $this->li_mls_get_mailchimp_lists($options['li_mls_api_key']);
|
88 |
|
89 |
echo '<select id="li_mls_subscribers_to_list" name="leadin_mls_options[li_mls_subscribers_to_list]" ' . ( ! count($lists['data']) ? 'disabled' : '' ) . '>';
|
90 |
|
91 |
if ( count($lists['data']) )
|
92 |
{
|
93 |
+
$list_set = FALSE;
|
94 |
+
|
95 |
foreach ( $lists['data'] as $list )
|
96 |
{
|
|
|
97 |
if ( $list['id'] == $li_mls_subscribers_to_list && !$list_set )
|
98 |
$list_set = TRUE;
|
99 |
|
100 |
echo '<option ' . ( $list['id'] == $li_mls_subscribers_to_list ? 'selected' : '' ) . ' value="' . $list['id'] . '">' . $list['name'] . '</option>';
|
|
|
|
|
|
|
101 |
}
|
102 |
+
|
103 |
+
if ( !$list_set )
|
104 |
+
echo '<option selected value="">No list set...</option>';
|
105 |
}
|
106 |
else
|
107 |
{
|
115 |
|
116 |
function li_mls_get_mailchimp_lists ( $api_key )
|
117 |
{
|
118 |
+
$MailChimp = new LI_MailChimp($api_key);
|
119 |
|
120 |
$lists = $MailChimp->call("lists/list", array(
|
121 |
"start" => 0, // optional, control paging of lists, start results at this list #, defaults to 1st page of data (page 0)
|
power-ups/mailchimp-list-sync/inc/MailChimp-API.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
* @author Drew McLellan <drew.mclellan@gmail.com>
|
15 |
* @version 1.1.1
|
16 |
*/
|
17 |
-
class
|
18 |
{
|
19 |
private $api_key;
|
20 |
private $api_endpoint = 'https://<dc>.api.mailchimp.com/2.0';
|
14 |
* @author Drew McLellan <drew.mclellan@gmail.com>
|
15 |
* @version 1.1.1
|
16 |
*/
|
17 |
+
class LI_MailChimp
|
18 |
{
|
19 |
private $api_key;
|
20 |
private $api_endpoint = 'https://<dc>.api.mailchimp.com/2.0';
|
power-ups/subscribe-widget.php
CHANGED
@@ -80,7 +80,9 @@ class WPLeadInSubscribe extends WPLeadIn {
|
|
80 |
'li_susbscibe_installed' => '1',
|
81 |
'li_subscribe_vex_class' => 'vex-theme-bottom-right-corner',
|
82 |
'li_subscribe_heading' => 'Sign up for my newsletter to get new posts by email',
|
83 |
-
'li_subscribe_btn_label' => 'SUBSCRIBE'
|
|
|
|
|
84 |
|
85 |
);
|
86 |
|
@@ -101,6 +103,8 @@ class WPLeadInSubscribe extends WPLeadIn {
|
|
101 |
echo '<input id="leadin-subscribe-vex-class" value="' . ( isset($lis_options['li_subscribe_vex_class']) ? $lis_options['li_subscribe_vex_class'] : 'vex-theme-bottom-right-corner' ) . '" type="hidden"/>';
|
102 |
echo '<input id="leadin-subscribe-heading" value="' . ( isset($lis_options['li_subscribe_heading']) ? $lis_options['li_subscribe_heading'] : 'Sign up for my newsletter to get new posts by email' ) . '" type="hidden"/>';
|
103 |
echo '<input id="leadin-subscribe-btn-label" value="' . ( isset($lis_options['li_subscribe_btn_label']) ? $lis_options['li_subscribe_btn_label'] : 'SUBSCRIBE' ) . '" type="hidden"/>';
|
|
|
|
|
104 |
|
105 |
// Div checked by media query for mobile
|
106 |
echo '<span id="leadin-subscribe-mobile-check"></span>';
|
@@ -128,9 +132,11 @@ class WPLeadInSubscribe extends WPLeadIn {
|
|
128 |
wp_enqueue_script('vex-dialog');
|
129 |
|
130 |
wp_register_style('leadin-subscribe-vex-css', LEADIN_SUBSCRIBE_WIDGET_PATH . '/frontend/css/vex.css');
|
131 |
-
|
132 |
wp_enqueue_style('leadin-subscribe-vex-css');
|
133 |
|
|
|
|
|
|
|
134 |
//wp_localize_script('leadin', 'li_ajax', array('ajax_url' => admin_url('admin-ajax.php')));
|
135 |
}
|
136 |
}
|
80 |
'li_susbscibe_installed' => '1',
|
81 |
'li_subscribe_vex_class' => 'vex-theme-bottom-right-corner',
|
82 |
'li_subscribe_heading' => 'Sign up for my newsletter to get new posts by email',
|
83 |
+
'li_subscribe_btn_label' => 'SUBSCRIBE',
|
84 |
+
'li_subscribe_name_fields' => '0',
|
85 |
+
'li_subscribe_phone_field' => '0'
|
86 |
|
87 |
);
|
88 |
|
103 |
echo '<input id="leadin-subscribe-vex-class" value="' . ( isset($lis_options['li_subscribe_vex_class']) ? $lis_options['li_subscribe_vex_class'] : 'vex-theme-bottom-right-corner' ) . '" type="hidden"/>';
|
104 |
echo '<input id="leadin-subscribe-heading" value="' . ( isset($lis_options['li_subscribe_heading']) ? $lis_options['li_subscribe_heading'] : 'Sign up for my newsletter to get new posts by email' ) . '" type="hidden"/>';
|
105 |
echo '<input id="leadin-subscribe-btn-label" value="' . ( isset($lis_options['li_subscribe_btn_label']) ? $lis_options['li_subscribe_btn_label'] : 'SUBSCRIBE' ) . '" type="hidden"/>';
|
106 |
+
echo '<input id="leadin-subscribe-name-fields" value="' . ( isset($lis_options['li_subscribe_name_fields']) ? $lis_options['li_subscribe_name_fields'] : '0' ) . '" type="hidden"/>';
|
107 |
+
echo '<input id="leadin-subscribe-phone-field" value="' . ( isset($lis_options['li_subscribe_phone_field']) ? $lis_options['li_subscribe_phone_field'] : '0' ) . '" type="hidden"/>';
|
108 |
|
109 |
// Div checked by media query for mobile
|
110 |
echo '<span id="leadin-subscribe-mobile-check"></span>';
|
132 |
wp_enqueue_script('vex-dialog');
|
133 |
|
134 |
wp_register_style('leadin-subscribe-vex-css', LEADIN_SUBSCRIBE_WIDGET_PATH . '/frontend/css/vex.css');
|
|
|
135 |
wp_enqueue_style('leadin-subscribe-vex-css');
|
136 |
|
137 |
+
wp_register_style('leadin-subscribe', LEADIN_SUBSCRIBE_WIDGET_PATH . '/frontend/css/leadin-subscribe.css');
|
138 |
+
wp_enqueue_style('leadin-subscribe');
|
139 |
+
|
140 |
//wp_localize_script('leadin', 'li_ajax', array('ajax_url' => admin_url('admin-ajax.php')));
|
141 |
}
|
142 |
}
|
power-ups/subscribe-widget/admin/subscribe-widget-admin.php
CHANGED
@@ -40,10 +40,48 @@ class WPLeadInSubscribeAdmin extends WPLeadInAdmin {
|
|
40 |
{
|
41 |
register_setting('leadin_settings_options', 'leadin_subscribe_options', array($this, 'sanitize'));
|
42 |
|
43 |
-
add_settings_section(
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
}
|
48 |
|
49 |
/**
|
@@ -64,6 +102,12 @@ class WPLeadInSubscribeAdmin extends WPLeadInAdmin {
|
|
64 |
if( isset( $input['li_subscribe_btn_label'] ) )
|
65 |
$new_input['li_subscribe_btn_label'] = sanitize_text_field( $input['li_subscribe_btn_label'] );
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
return $new_input;
|
68 |
}
|
69 |
|
@@ -77,7 +121,7 @@ class WPLeadInSubscribeAdmin extends WPLeadInAdmin {
|
|
77 |
|
78 |
echo '<select id="li_subscribe_vex_class" name="leadin_subscribe_options[li_subscribe_vex_class]">';
|
79 |
echo '<option value="vex-theme-bottom-right-corner"' . ( $li_subscribe_vex_class == 'vex-theme-bottom-right-corner' ? ' selected' : '' ) . '>Bottom right</option>';
|
80 |
-
echo '<option value="vex-theme-bottom-left-corner"' . ( $li_subscribe_vex_class == 'vex-theme-bottom-left-corner' ? ' selected' : '' ) . '>Bottom
|
81 |
echo '<option value="vex-theme-top"' . ( $li_subscribe_vex_class == 'vex-theme-top' ? ' selected' : '' ) . '>Top</option>';
|
82 |
echo '<option value="vex-theme-default"' . ( $li_subscribe_vex_class == 'vex-theme-default' ? ' selected' : '' ) . '>Pop-over content</option>';
|
83 |
echo '</select>';
|
@@ -92,7 +136,7 @@ class WPLeadInSubscribeAdmin extends WPLeadInAdmin {
|
|
92 |
$li_subscribe_heading = ( $options['li_subscribe_heading'] ? $options['li_subscribe_heading'] : 'Sign up for my newsletter to get new posts by email' ); // Get header from options, or show default
|
93 |
|
94 |
printf(
|
95 |
-
'<input id="li_subscribe_heading" type="text"
|
96 |
$li_subscribe_heading
|
97 |
);
|
98 |
}
|
@@ -106,11 +150,40 @@ class WPLeadInSubscribeAdmin extends WPLeadInAdmin {
|
|
106 |
$li_subscribe_btn_label = ( $options['li_subscribe_btn_label'] ? $options['li_subscribe_btn_label'] : 'SUBSCRIBE' ); // Get button text from options, or show default
|
107 |
|
108 |
printf(
|
109 |
-
'<input id="li_subscribe_btn_label" type="text"
|
110 |
$li_subscribe_btn_label
|
111 |
);
|
112 |
|
113 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
}
|
115 |
|
116 |
-
?>
|
40 |
{
|
41 |
register_setting('leadin_settings_options', 'leadin_subscribe_options', array($this, 'sanitize'));
|
42 |
|
43 |
+
add_settings_section(
|
44 |
+
$this->power_up_settings_section,
|
45 |
+
$this->power_up_icon . 'Subscribe Pop-up',
|
46 |
+
'',
|
47 |
+
LEADIN_ADMIN_PATH
|
48 |
+
);
|
49 |
+
|
50 |
+
add_settings_field(
|
51 |
+
'li_subscribe_vex_class',
|
52 |
+
'Pop-up Location',
|
53 |
+
array($this, 'li_subscribe_vex_class_callback'),
|
54 |
+
LEADIN_ADMIN_PATH,
|
55 |
+
$this->power_up_settings_section
|
56 |
+
);
|
57 |
+
add_settings_field(
|
58 |
+
'li_subscribe_heading',
|
59 |
+
'Pop-up header text',
|
60 |
+
array($this, 'li_subscribe_heading_callback'),
|
61 |
+
LEADIN_ADMIN_PATH,
|
62 |
+
$this->power_up_settings_section
|
63 |
+
);
|
64 |
+
add_settings_field(
|
65 |
+
'li_subscribe_btn_label',
|
66 |
+
'Button text',
|
67 |
+
array($this, 'li_subscribe_btn_label_callback'),
|
68 |
+
LEADIN_ADMIN_PATH,
|
69 |
+
$this->power_up_settings_section
|
70 |
+
);
|
71 |
+
add_settings_field(
|
72 |
+
'li_subscribe_name_fields',
|
73 |
+
'Include First and Last Name',
|
74 |
+
array($this, 'li_subscribe_name_fields_callback'),
|
75 |
+
LEADIN_ADMIN_PATH,
|
76 |
+
$this->power_up_settings_section
|
77 |
+
);
|
78 |
+
add_settings_field(
|
79 |
+
'li_subscribe_phone_field',
|
80 |
+
'Include Phone Number',
|
81 |
+
array($this, 'li_subscribe_phone_field_callback'),
|
82 |
+
LEADIN_ADMIN_PATH,
|
83 |
+
$this->power_up_settings_section
|
84 |
+
);
|
85 |
}
|
86 |
|
87 |
/**
|
102 |
if( isset( $input['li_subscribe_btn_label'] ) )
|
103 |
$new_input['li_subscribe_btn_label'] = sanitize_text_field( $input['li_subscribe_btn_label'] );
|
104 |
|
105 |
+
if( isset( $input['li_subscribe_name_fields'] ) )
|
106 |
+
$new_input['li_subscribe_name_fields'] = sanitize_text_field( $input['li_subscribe_name_fields'] );
|
107 |
+
|
108 |
+
if( isset( $input['li_subscribe_phone_field'] ) )
|
109 |
+
$new_input['li_subscribe_phone_field'] = sanitize_text_field( $input['li_subscribe_phone_field'] );
|
110 |
+
|
111 |
return $new_input;
|
112 |
}
|
113 |
|
121 |
|
122 |
echo '<select id="li_subscribe_vex_class" name="leadin_subscribe_options[li_subscribe_vex_class]">';
|
123 |
echo '<option value="vex-theme-bottom-right-corner"' . ( $li_subscribe_vex_class == 'vex-theme-bottom-right-corner' ? ' selected' : '' ) . '>Bottom right</option>';
|
124 |
+
echo '<option value="vex-theme-bottom-left-corner"' . ( $li_subscribe_vex_class == 'vex-theme-bottom-left-corner' ? ' selected' : '' ) . '>Bottom left</option>';
|
125 |
echo '<option value="vex-theme-top"' . ( $li_subscribe_vex_class == 'vex-theme-top' ? ' selected' : '' ) . '>Top</option>';
|
126 |
echo '<option value="vex-theme-default"' . ( $li_subscribe_vex_class == 'vex-theme-default' ? ' selected' : '' ) . '>Pop-over content</option>';
|
127 |
echo '</select>';
|
136 |
$li_subscribe_heading = ( $options['li_subscribe_heading'] ? $options['li_subscribe_heading'] : 'Sign up for my newsletter to get new posts by email' ); // Get header from options, or show default
|
137 |
|
138 |
printf(
|
139 |
+
'<input id="li_subscribe_heading" type="text" name="leadin_subscribe_options[li_subscribe_heading]" value="%s" size="50"/>',
|
140 |
$li_subscribe_heading
|
141 |
);
|
142 |
}
|
150 |
$li_subscribe_btn_label = ( $options['li_subscribe_btn_label'] ? $options['li_subscribe_btn_label'] : 'SUBSCRIBE' ); // Get button text from options, or show default
|
151 |
|
152 |
printf(
|
153 |
+
'<input id="li_subscribe_btn_label" type="text" name="leadin_subscribe_options[li_subscribe_btn_label]" value="%s" size="50"/>',
|
154 |
$li_subscribe_btn_label
|
155 |
);
|
156 |
|
157 |
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Prints first and last name checkbox for settings page
|
161 |
+
*/
|
162 |
+
function li_subscribe_name_fields_callback ()
|
163 |
+
{
|
164 |
+
$options = get_option('leadin_subscribe_options');
|
165 |
+
$li_subscribe_name_fields = ( $options['li_subscribe_name_fields'] ? $options['li_subscribe_name_fields'] : '0' ); // Get name field options from options, or show default
|
166 |
+
|
167 |
+
printf(
|
168 |
+
'<input id="li_subscribe_name_fields" type="checkbox" name="leadin_subscribe_options[li_subscribe_name_fields]" value="1"' . checked( 1, $options['li_subscribe_name_fields'], false ) . '/>',
|
169 |
+
$li_subscribe_name_fields
|
170 |
+
);
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Prints phone number checkbox for settings page
|
175 |
+
*/
|
176 |
+
function li_subscribe_phone_field_callback ()
|
177 |
+
{
|
178 |
+
$options = get_option('leadin_subscribe_options');
|
179 |
+
$li_subscribe_phone_field = ( $options['li_subscribe_phone_field'] ? $options['li_subscribe_phone_field'] : '0' ); // Get phone field preference from options, or show default
|
180 |
+
|
181 |
+
printf(
|
182 |
+
'<input id="li_subscribe_phone_field" type="checkbox" name="leadin_subscribe_options[li_subscribe_phone_field]" value="1"' . checked( 1, $options['li_subscribe_phone_field'], false ) . '/>',
|
183 |
+
$li_subscribe_phone_field
|
184 |
+
);
|
185 |
+
}
|
186 |
+
|
187 |
}
|
188 |
|
189 |
+
?>
|
power-ups/subscribe-widget/frontend/css/leadin-subscribe.css
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
.leadin-subscribe .vex-dialog-message{
|
2 |
-
font-weight: bold;
|
3 |
-
margin-bottom: 15px !important;
|
4 |
-
font-size: 18px !important;
|
5 |
-
}
|
6 |
-
|
7 |
-
.leadin-subscribe .vex-dialog-button{
|
8 |
-
background: #444444 !important;
|
9 |
-
margin-top: -10px !important;
|
10 |
-
}
|
11 |
-
|
12 |
-
.leadin-subscribe .vex-dialog-input input{
|
13 |
-
margin-bottom: 10px !important;
|
14 |
-
font-size: 18px !important;
|
15 |
-
}
|
16 |
-
|
17 |
-
.leadin-subscribe .vex-dialog-buttons input{
|
18 |
-
font-size: 14px !important;
|
19 |
-
color: #fff !important;
|
20 |
-
}
|
21 |
-
|
22 |
-
.leadin-subscribe .vex-close{
|
23 |
-
top: 5px !important;
|
24 |
-
right: 5px !important;
|
25 |
-
}
|
26 |
-
|
27 |
-
#leadin-subscribe-powered-by{
|
28 |
-
clear: both;
|
29 |
-
float: right;
|
30 |
-
font-size: 12px;
|
31 |
-
padding-top: 15px;
|
32 |
-
text-decoration: none;
|
33 |
-
font-weight: bold;
|
34 |
-
color: #3288e6;
|
35 |
-
}
|
36 |
-
|
37 |
-
#leadin-subscribe-powered-by:hover{
|
38 |
-
text-decoration: underline;
|
39 |
-
}
|
40 |
-
|
41 |
-
.leadin-subscribe .vex-content{
|
42 |
-
padding: 15px 15px 10px 15px !important;
|
43 |
-
}
|
44 |
-
|
45 |
-
@media only screen and (max-width: 760px) {
|
46 |
-
#leadin-subscribe-mobile-check { display: none; }
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
power-ups/subscribe-widget/frontend/js/leadin-subscribe.js
CHANGED
@@ -38,7 +38,7 @@ function bind_leadin_subscribe_widget ()
|
|
38 |
if ($(window).scrollTop() + $(window).height() > $(document).height() / 2) {
|
39 |
subscribe.open();
|
40 |
} else {
|
41 |
-
subscribe.close();
|
42 |
}
|
43 |
});
|
44 |
};
|
@@ -52,15 +52,16 @@ function bind_leadin_subscribe_widget ()
|
|
52 |
showCloseButton: true,
|
53 |
className: 'leadin-subscribe ' + $('#leadin-subscribe-vex-class').val(),
|
54 |
message: $('#leadin-subscribe-heading').val(),
|
55 |
-
input: '' +
|
56 |
-
'<input id="leadin-subscribe-
|
|
|
57 |
buttons: [$.extend({}, vex.dialog.buttons.YES, { text: ( $('#leadin-subscribe-btn-label').val() ? $('#leadin-subscribe-btn-label').val() : 'SUBSCRIBE' ) })],
|
58 |
onSubmit: function ( data )
|
59 |
{
|
60 |
$('.vex-dialog-form').fadeOut(300, function ( e ) {
|
61 |
$('.vex-dialog-form').html(
|
62 |
'<div class="vex-close"></div>' +
|
63 |
-
'<h3>Thanks
|
64 |
'<div>' +
|
65 |
'<span class="powered-by">Powered by LeadIn</span>' +
|
66 |
'<a href="http://leadin.com/wordpress-subscribe-widget/?utm_campaign=subscribe_widget&utm_medium=email&utm_source=' + window.location.host + '"><img alt="LeadIn" height="20px" width="99px" src="http://leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/Leadin_logo@2x.png" alt="leadin.com"/></a>' +
|
38 |
if ($(window).scrollTop() + $(window).height() > $(document).height() / 2) {
|
39 |
subscribe.open();
|
40 |
} else {
|
41 |
+
//subscribe.close();
|
42 |
}
|
43 |
});
|
44 |
};
|
52 |
showCloseButton: true,
|
53 |
className: 'leadin-subscribe ' + $('#leadin-subscribe-vex-class').val(),
|
54 |
message: $('#leadin-subscribe-heading').val(),
|
55 |
+
input: '<input id="leadin-subscribe-email" name="email" type="email" placeholder="Email address" required />' +
|
56 |
+
(($('#leadin-subscribe-name-fields').val()==0) ? '' : '<input id="leadin-subscribe-fname" name="fname" type="text" placeholder="First Name" required /><input id="leadin-subscribe-lname" name="lname" type="text" placeholder="Last Name" required />') +
|
57 |
+
(($('#leadin-subscribe-phone-field').val()==0) ? '' : '<input id="leadin-subscribe-phone" name="phone" type="tel" placeholder="Phone" required />'),
|
58 |
buttons: [$.extend({}, vex.dialog.buttons.YES, { text: ( $('#leadin-subscribe-btn-label').val() ? $('#leadin-subscribe-btn-label').val() : 'SUBSCRIBE' ) })],
|
59 |
onSubmit: function ( data )
|
60 |
{
|
61 |
$('.vex-dialog-form').fadeOut(300, function ( e ) {
|
62 |
$('.vex-dialog-form').html(
|
63 |
'<div class="vex-close"></div>' +
|
64 |
+
'<h3>Thanks!<br>You should receive a confirmation email in your inbox shortly.</h3>' +
|
65 |
'<div>' +
|
66 |
'<span class="powered-by">Powered by LeadIn</span>' +
|
67 |
'<a href="http://leadin.com/wordpress-subscribe-widget/?utm_campaign=subscribe_widget&utm_medium=email&utm_source=' + window.location.host + '"><img alt="LeadIn" height="20px" width="99px" src="http://leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/Leadin_logo@2x.png" alt="leadin.com"/></a>' +
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: andygcook, nelsonjoyce
|
3 |
Tags: lead tracking, visitor tracking, analytics, crm, marketing automation, inbound marketing, subscription, marketing, lead generation, mailchimp
|
4 |
Requires at least: 3.7
|
5 |
-
Tested up to: 3.
|
6 |
-
Stable tag: 0.
|
7 |
|
8 |
LeadIn is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
|
9 |
|
@@ -88,14 +88,45 @@ To ensure quality we've tested the most popular WordPress form builder plugins.
|
|
88 |
|
89 |
== Changelog ==
|
90 |
|
91 |
-
Current version: 0.
|
92 |
-
Current version release: 2014-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
= 0.7.0 (2014.04.10) =
|
95 |
|
96 |
= Enhancements =
|
97 |
- MailChimp List Sync power-up
|
98 |
-
- Added new themes (bottom right, bottom left, top and pop-up) to the
|
99 |
|
100 |
= 0.6.2 (2014.04.07) =
|
101 |
- Bug fixes
|
2 |
Contributors: andygcook, nelsonjoyce
|
3 |
Tags: lead tracking, visitor tracking, analytics, crm, marketing automation, inbound marketing, subscription, marketing, lead generation, mailchimp
|
4 |
Requires at least: 3.7
|
5 |
+
Tested up to: 3.9.0
|
6 |
+
Stable tag: 0.8.2
|
7 |
|
8 |
LeadIn is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
|
9 |
|
88 |
|
89 |
== Changelog ==
|
90 |
|
91 |
+
- Current version: 0.8.2
|
92 |
+
- Current version release: 2014-05-02
|
93 |
+
|
94 |
+
= 0.8.2 (2014.05.02) =
|
95 |
+
- Bug fixes
|
96 |
+
- Removed namespace usage in favor or a low-tech work around to be compliant with PHP 5.2 and lower
|
97 |
+
|
98 |
+
= 0.8.1 (2014.04.30) =
|
99 |
+
- Bug fixes
|
100 |
+
- Namespaced duplicate classes
|
101 |
+
|
102 |
+
= 0.8.0 (2014.04.30) =
|
103 |
+
- Bug fixes
|
104 |
+
- Fix scrolling issue with subscribe pop-up
|
105 |
+
- Duplicate class bug fixes
|
106 |
+
|
107 |
+
= Enhancements =
|
108 |
+
- Add optional first name, last name and phone fields for subscribe pop-up
|
109 |
+
- Change out contact notification emails to be from settings email address
|
110 |
+
- Ability to disable contact notification emails
|
111 |
+
- Constant Contact list sync power-up
|
112 |
+
- Sync optional contact fields (name + phone) to email service provider power-ups
|
113 |
+
|
114 |
+
= 0.7.2 (2014.04.18) =
|
115 |
+
- Bug fixes
|
116 |
+
- Fix contact deletion bug
|
117 |
+
- Implement data recovery fix for contacts
|
118 |
+
- Bug fixes to contact merging
|
119 |
+
|
120 |
+
|
121 |
+
= 0.7.1 (2014.04.11) =
|
122 |
+
- Bug fixes
|
123 |
+
- SVN bug fix that did not add the MailChimp List sync power-up
|
124 |
|
125 |
= 0.7.0 (2014.04.10) =
|
126 |
|
127 |
= Enhancements =
|
128 |
- MailChimp List Sync power-up
|
129 |
+
- Added new themes (bottom right, bottom left, top and pop-up) to the WordPress Subscribe Widget power-up
|
130 |
|
131 |
= 0.6.2 (2014.04.07) =
|
132 |
- Bug fixes
|