Version Description
/ 18.09.2018 = * Additional code improvements * Minor issues fix
Download this release
Release Info
Developer | supsystic.com |
Plugin | Popup by Supsystic |
Version | 1.9.38 |
Comparing to | |
See all releases |
Code changes from version 1.9.20 to 1.9.38
- classes/html.php +12 -0
- classes/installer.php +2 -2
- classes/utils.php +12 -6
- config.php +5 -1
- js/admin.options.js +15 -15
- js/common.js +2 -2
- js/common.min.js +2 -0
- js/core.js +3 -3
- js/core.min.js +2 -0
- js/google.recaptcha.js +32 -0
- js/wp.tabs.js +3 -3
- modules/options/models/options.php +2 -2
- modules/popup/controller.php +3 -1
- modules/popup/css/admin.popup.css +5 -2
- modules/popup/css/frontend.popup.css +4 -2
- modules/popup/css/frontend.popup.min.css +2 -0
- modules/popup/js/admin.popup.edit.js +1 -0
- modules/popup/js/admin.popup.js +1 -1
- modules/popup/js/frontend.popup.js +36 -12
- modules/popup/js/frontend.popup.min.js +2 -0
- modules/popup/mod.php +6 -3
- modules/popup/views/popup.php +9 -2
- modules/popup/views/tpl/popupEditAdminDesignOpts.php +9 -0
- modules/popup/views/tpl/popupEditAdminMainOpts.php +20 -2
- modules/popup/views/tpl/popupEditAdminSubOpts.php +43 -1
- modules/subscribe/classes/Batch.php +150 -150
- modules/subscribe/classes/MailChimp.php +450 -450
- modules/subscribe/classes/Webhook.php +82 -82
- modules/subscribe/classes/mailPoetV3.php +13 -13
- modules/subscribe/mod.php +6 -0
- modules/subscribe/models/subscribe.php +15 -1
- modules/supsystic_promo/js/admin.tour.js +1 -1
- modules/supsystic_promo/mod.php +1 -0
- modules/supsystic_promo/models/classes/lib/Base/MixpanelBase.php +64 -64
- modules/supsystic_promo/models/classes/lib/ConsumerStrategies/AbstractConsumer.php +56 -56
- modules/supsystic_promo/models/classes/lib/ConsumerStrategies/CurlConsumer.php +220 -220
- modules/supsystic_promo/models/classes/lib/ConsumerStrategies/FileConsumer.php +37 -37
- modules/supsystic_promo/models/classes/lib/ConsumerStrategies/SocketConsumer.php +307 -307
- modules/supsystic_promo/models/classes/lib/Mixpanel.php +302 -302
- modules/supsystic_promo/models/classes/lib/Producers/MixpanelBaseProducer.php +228 -228
- modules/supsystic_promo/models/classes/lib/Producers/MixpanelEvents.php +163 -163
- modules/supsystic_promo/models/classes/lib/Producers/MixpanelPeople.php +147 -147
- modules/supsystic_promo/views/tpl/adminTour.php +2 -2
- modules/supsystic_promo/views/tpl/pluginDeactivation.php +77 -77
- modules/templates/mod.php +3 -3
- modules/tgm_promo/classes/class-tgm-plugin-activation.php +3853 -3853
- modules/tgm_promo/mod.php +46 -46
- pps.php +3 -1
- readme.txt +382 -524
classes/html.php
CHANGED
@@ -733,6 +733,18 @@ class htmlPps {
|
|
733 |
}
|
734 |
return $value === true ? $arr[ $key ] : $arr[ $key ] == $value;
|
735 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
736 |
static public function nonceForAction( $action ) {
|
737 |
return self::hidden('_wpnonce', array('value' => wp_create_nonce(strtolower($action))));
|
738 |
}
|
733 |
}
|
734 |
return $value === true ? $arr[ $key ] : $arr[ $key ] == $value;
|
735 |
}
|
736 |
+
static public function recaptcha($name, $params = array()) {
|
737 |
+
framePps::_()->addScript('google.recaptcha', 'https://www.google.com/recaptcha/api.js?render=explicit&onload=ppsInitCaptcha');
|
738 |
+
framePps::_()->addScript('google.recaptcha.frontend', PPS_JS_PATH. 'google.recaptcha.js');
|
739 |
+
|
740 |
+
$res = '<div class="g-recaptcha" '
|
741 |
+
. 'data-sitekey="'. $params['sitekey']. '" '
|
742 |
+
. (isset($params['theme']) ? 'data-theme="'. $params['theme']. '" ' : '')
|
743 |
+
. (isset($params['type']) ? 'data-type="'. $params['type']. '" ' : '')
|
744 |
+
. (isset($params['size']) ? 'data-size="'. $params['size']. '" ' : '')
|
745 |
+
. '></div>';
|
746 |
+
return $res;
|
747 |
+
}
|
748 |
static public function nonceForAction( $action ) {
|
749 |
return self::hidden('_wpnonce', array('value' => wp_create_nonce(strtolower($action))));
|
750 |
}
|
classes/installer.php
CHANGED
@@ -545,7 +545,7 @@ class installerPps {
|
|
545 |
if(!dbPps::exist('@__popup', 'id', '40')) { // Second set of additional templates
|
546 |
dbPps::query('INSERT INTO @__popup (id,label,active,original_id,params,html,css,img_preview,show_on,show_to,show_pages,type_id,date_created,sort_order) VALUES
|
547 |
("40","List Building Neo","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoxMDoic2hvd19wYWdlcyI7czozOiJhbGwiO3M6MTQ6InNob3dfdGltZV9mcm9tIjtzOjc6IjEyOjAwYW0iO3M6MTI6InNob3dfdGltZV90byI7czo3OiIxMjowMGFtIjtzOjE0OiJzaG93X2RhdGVfZnJvbSI7czowOiIiO3M6MTI6InNob3dfZGF0ZV90byI7czowOiIiO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoxNToiY291bnRfdGltZXNfbnVtIjtzOjE6IjEiO3M6MTU6ImNvdW50X3RpbWVzX21lcyI7czozOiJkYXkiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9zZWFyY2hfZW5naW5lc19zaG93IjtzOjE6IjAiO3M6MTg6ImhpZGVfcHJlZ191cmxfc2hvdyI7czoxOiIwIjtzOjEzOiJoaWRlX3ByZWdfdXJsIjtzOjA6IiI7czoyNDoiaGlkZV9mb3JfdXNlcl9yb2xlc19zaG93IjtzOjE6IjAiO31zOjM6InRwbCI7YTo2Mjp7czo1OiJ3aWR0aCI7czozOiI4MjQiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18wIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjZjRmNGY0IjtzOjk6ImJnX3R5cGVfMSI7czozOiJpbWciO3M6ODoiYmdfaW1nXzEiO3M6NDI6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL25ldy1mb3JtLWJnLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjNGQ0ZDRkIjtzOjk6ImJnX3R5cGVfMiI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMiI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiIzAwZWFlYSI7czo5OiJiZ190eXBlXzMiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18zIjtzOjQ0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9uZXctZm9ybS1sb2dvLnBuZyI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjYzZjNmM2IjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzAwMDAwMCI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjIwOiJjaXJjbGVfYmlnX25ld19jbG9zZSI7czo3OiJidWxsZXRzIjtzOjE0OiJjaXJjbGVfYmlnX25ldyI7czoxMToibGF5ZXJlZF9wb3MiO3M6MDoiIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjEwNzoiVGhlIEJlc3QgV29yZFByZXNzIFBvcFVwIG9wdGluIHBsdWdpbiB0byBoZWxwIHlvdSBnYWluIG1vcmUgc3Vic2NyaWJlcnMsIHNvY2lhbCBmb2xsb3dlcnMgb3IgYWR2ZXJ0aXNlbWVudC4iO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6MTM6ImVuYl9mb290X25vdGUiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE5OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4NCllvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTSUdOLVVQISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfc3ViamVjdCI7czo0MDoiTmV3IFN1YnNjcmliZXIgb24gTXkgV29yZFByZXNzIFRlc3QgU2l0ZSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjEyOiJzdGF0X2dhX2NvZGUiO3M6MDoiIjtzOjU6InR4dF8wIjtzOjM4MToiPHA+UG9wdXAgYnkgU3Vwc3lzdGljIGxldHMgeW91IGVhc2lseSBjcmVhdGUgZWxlZ2FudCBvdmVybGFwcGluZyB3aW5kb3dzIHdpdGggdW5saW1pdGVkIGZlYXR1cmVzLiBQb3AtdXBzIHdpdGggU2xpZGVyLCBMaWdodGJveCwgQ29udGFjdCBhbmQgU3Vic2NyaXB0aW9uIGZvcm1zIGFuZCBtb3JlOjwvcD48dWw+PGxpPjxzdHJvbmc+VW5saW1pdGVkIENvbnRlbnQgQ3VzdG9taXphdGlvbjwvc3Ryb25nPjwvbGk+PGxpPjxzdHJvbmc+QXV0byBPcGVuIFBvcHVwczwvc3Ryb25nPjwvbGk+PGxpPjxzdHJvbmc+Q29udGFjdCBGb3JtIHdpdGggcG9wLXVwPC9zdHJvbmc+PC9saT48bGk+PHN0cm9uZz5Qb3B1cCBPcGVuaW5nIEFuaW1hdGlvPC9zdHJvbmc+bnM8L2xpPjwvdWw+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link href=\"https://fonts.googleapis.com/css?family=Montserrat\" rel=\"stylesheet\"> \r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n [if bg_type_3 == \'img\']\r\n <img src=\"[bg_img_3]\" class=\"ppsLogo\" />\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \"Montserrat\",\"Trebuchet MS\",\"Helvetica Neue\",Helvetica,Arial,Sans-Serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #4d4d4d;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 66%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n vertical-align: top;\r\n padding: 30px 20px;\r\n [if bg_type_0 == \'color\']\r\n background-color: [bg_color_0];\r\n background-image: none;\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 30px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n margin-bottom: 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n display: table-cell;\r\n width: 34%;\r\n height: 100%;\r\n text-align: center;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-color: [bg_color_1];\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 10px;\r\n font-size: 17px;\r\n background-color: #fff;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -5px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n [if bg_type_2 == \'color\']\r\n background-color: [bg_color_2];\r\n border-bottom: 3px solid {{ adjust_brightness(popup.params.tpl.bg_color_2, -50) }};\r\n background-image: none;\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 2px 2px 1px #555;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 ul {\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #fff;\r\n font-size: x-small;\r\n line-height: 14px;\r\n margin: 5px 30px 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsLogo {\r\n \r\n}","list-building-neo.jpg","1","1","1","1","2015-01-10 18:59:43","1"),
|
548 |
-
("41","Bright Girl","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoxMDoic2hvd19wYWdlcyI7czozOiJhbGwiO3M6MTQ6InNob3dfdGltZV9mcm9tIjtzOjc6IjEyOjAwYW0iO3M6MTI6InNob3dfdGltZV90byI7czo3OiIxMjowMGFtIjtzOjE0OiJzaG93X2RhdGVfZnJvbSI7czowOiIiO3M6MTI6InNob3dfZGF0ZV90byI7czowOiIiO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoxNToiY291bnRfdGltZXNfbnVtIjtzOjE6IjEiO3M6MTU6ImNvdW50X3RpbWVzX21lcyI7czozOiJkYXkiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9zZWFyY2hfZW5naW5lc19zaG93IjtzOjE6IjAiO3M6MTg6ImhpZGVfcHJlZ191cmxfc2hvdyI7czoxOiIwIjtzOjEzOiJoaWRlX3ByZWdfdXJsIjtzOjA6IiI7czoyNDoiaGlkZV9mb3JfdXNlcl9yb2xlc19zaG93IjtzOjE6IjAiO31zOjM6InRwbCI7YTo2Mjp7czo1OiJ3aWR0aCI7czozOiI4MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18wIjtzOjQxOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9iYWNrZ3JvdW5kLmpwZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjOTkwYTIyIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czozOToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvYnV0dG9uLTEucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czozNzoiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvZ2lybC0yLnBuZyI7czoxMDoiYmdfY29sb3JfMiI7czowOiIiO3M6OToiYmdfdHlwZV8zIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18zIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjM2QzZDNkIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiI2ZmNDQxMSI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjOTc5Njk2IjtzOjE1OiJyZXNwb25zaXZlX21vZGUiO3M6MzoiZGVmIjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjI3OiJjbG9zZS1ibGFjay1pbi13aGl0ZS1jaXJjbGUiO3M6NzoiYnVsbGV0cyI7czo0OiJ0aWNrIjtzOjExOiJsYXllcmVkX3BvcyI7czowOiIiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MjI6IlN1YnNjcmliZSBhbmQgR2V0IE5ld3MiO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjExNzoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MjU6InN1Yl9tYWlsY2hpbXBfZ3JvdXBzX2Z1bGwiO3M6MDoiIjtzOjEwOiJzdWJfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo2OntzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoyMDoic3ViX3R4dF9leGlzdHNfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjI6IkdvIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19zdWJqZWN0IjtzOjQwOiJOZXcgU3Vic2NyaWJlciBvbiBNeSBXb3JkUHJlc3MgVGVzdCBTaXRlIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIGlzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6MTI6InN0YXRfZ2FfY29kZSI7czowOiIiO3M6NToidHh0XzAiO3M6MTczOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmUuPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNCI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link href=\"https://fonts.googleapis.com/css?family=Montserrat\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupListsInner\">\r\n <div class=\"ppsPopupTblCols\">\r\n [if bg_type_2 == \'img\']\r\n <div class=\"ppsPopupLeftCol\">\r\n <img src=\"[bg_img_2]\" class=\"ppsLogo\" />\r\n </div>\r\n [endif]\r\n <div class=\"ppsPopupRightCol\">\r\n <div class=\"ppsBigArrow\"></div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupTxt_0\">[txt_0]</div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Montserrat\",Helvetica,Arial,sans-serif;\r\n font-size: 14px;\r\n [if bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [elseif bg_type_0 == \'color\']\r\n background: [bg_color_0];\r\nbackground: -moz-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: -webkit-gradient(left top, right top, color-stop(0%, [bg_color_0]), color-stop(31%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }}), color-stop(56%, rgba(201,3,49,1)), color-stop(67%, rgba(201,3,49,1)));\r\nbackground: -webkit-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: -o-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: -ms-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: linear-gradient(to right, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nfilter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'[bg_color_0]\', endColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }}\', GradientType=1 );\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #fff;\r\n font-size: 31px;\r\n line-height: 1.2;\r\n text-align: center;\r\n margin-bottom: 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupListsInner {\r\n [if bg_type_0 == \'color\']\r\n background: {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}; /* Old browsers */\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* FF3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%,[bg_color_0])); /* Chrome,Safari4+ */\r\n background: -webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Chrome10+,Safari5.1+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Opera 12+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* IE10+ */\r\n background: radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* W3C */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'#eaeaea\',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 .ppsTxtContent {\r\n padding: 10px 10px 10px 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n font-size: 12px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTblCols {\r\n display: table;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLeftCol {\r\n display: table-cell;\r\n padding: 0;\r\n [if enb_subscribe]\r\n width: 40%;\r\n [else]\r\n width: 30%;\r\n min-height: 60%;\r\n [endif]\r\n vertical-align: top;\r\n}\r\n#ppsPopupShell_[ID] .ppsLogo {\r\n width: auto;\r\n height: auto;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupRightCol {\r\n color: #fff;\r\n width: 60%;\r\n display: table-cell;\r\n padding: 50px 40px 20px;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 50px 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 35px;\r\n border-radius: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n background: [bg_color_1];\r\n border: 1px solid transparent;\r\n color: #000;\r\n padding-left: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n margin-left: -15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding: 20px 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: 1px solid #fff;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n border-radius: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n right: -20px !important;\r\n top: -10px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n [if enb_subscribe]\r\n color: #979696;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [else]\r\n margin-top: 10px;\r\n color: #979696;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n [if enb_subscribe]\r\n [else]\r\n margin-top: 130px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] li{\r\n font-weight: bold;\r\n font-size: 13px;\r\n padding-top: 3px;\r\n padding-bottom: 3px;\r\n color: #737E86;\r\n}","girl-2.jpg","1","1","1","1","2015-01-13 19:22:48","1"),
|
549 |
("42","Sign Up Classic","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoxMDoic2hvd19wYWdlcyI7czozOiJhbGwiO3M6MTQ6InNob3dfdGltZV9mcm9tIjtzOjc6IjEyOjAwYW0iO3M6MTI6InNob3dfdGltZV90byI7czo3OiIxMjowMGFtIjtzOjE0OiJzaG93X2RhdGVfZnJvbSI7czowOiIiO3M6MTI6InNob3dfZGF0ZV90byI7czowOiIiO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoxNToiY291bnRfdGltZXNfbnVtIjtzOjE6IjEiO3M6MTU6ImNvdW50X3RpbWVzX21lcyI7czozOiJkYXkiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9zZWFyY2hfZW5naW5lc19zaG93IjtzOjE6IjAiO3M6MTg6ImhpZGVfcHJlZ191cmxfc2hvdyI7czoxOiIwIjtzOjEzOiJoaWRlX3ByZWdfdXJsIjtzOjA6IiI7czoyNDoiaGlkZV9mb3JfdXNlcl9yb2xlc19zaG93IjtzOjE6IjAiO31zOjM6InRwbCI7YTo1NTp7czo1OiJ3aWR0aCI7czozOiI0MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMCI7czo0OToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvc2lnbi11cC1jbGFzc2ljLWJnLnBuZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjYzlhZTk0IjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiIzljODU3MCI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiNmZmZmZmYiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiI2Y5ZTZjZSI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzU4NTg1OCI7czoxNzoicmVpZHJlY3Rfb25fY2xvc2UiO3M6MDoiIjtzOjk6ImNsb3NlX2J0biI7czoxMToid2hpbGVfY2xvc2UiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjA6IiI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czozMToiU2lnbiBVcDxiciAvPlRvIE91ciBOZXdzbGV0dGVyISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo3OiJTSUdOIFVQIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19zdWJqZWN0IjtzOjQwOiJOZXcgU3Vic2NyaWJlciBvbiBNeSBXb3JkUHJlc3MgVGVzdCBTaXRlIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6MTI6InN0YXRfZ2FfY29kZSI7czowOiIiO3M6NToidHh0XzAiO3M6MTcyOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmU8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIyIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link href=\"https://fonts.googleapis.com/css?family=Dancing+Script|Gloria+Hallelujah|Hind|Pacifico|Satisfy\" rel=\"stylesheet\"> \r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \"Hind\",\"arial\",arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #4d4d4d;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n width: 100%;\r\n display: table-cell;\r\n padding: 40px;\r\n [if bg_type_0 == \'color\']\r\n background-color: [bg_color_0];\r\n background-image: none;\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-family: \"Dancing Script\", arial;\r\n font-size: 40px;\r\n line-height: 40px;\r\n font-weight: bold;\r\n margin-bottom: 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n margin-bottom: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 0;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 10px;\r\n \r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -4px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n background-image: none;\r\n border: 1px solid #fff;\r\n box-shadow: 0 0 0 4px [bg_color_1];\r\n width: calc(100% - 8px);\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n border-width: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n width: 100%;\r\n font-size: 14px;\r\n margin-bottom: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n right: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm {\r\n margin-top:20px;\r\n}","sign-up-classic.jpg","1","1","1","1","2015-01-10 18:59:43","1")');
|
550 |
}
|
551 |
if(!dbPps::exist('@__popup', 'id', '43')) {
|
@@ -555,7 +555,7 @@ class installerPps {
|
|
555 |
("45","XMas Sale","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMzoib3ZlcmxheV9jbGljayI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjExMTp7czo1OiJ3aWR0aCI7czozOiI2NzUiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjUyOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8yMDE2LXEzNTkteG1hc19yaWJib24ucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8yIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18yIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMiI7czo3OiIjYWVkMWRlIjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiI2Y0MTMwZiI7czo5OiJiZ190eXBlXzQiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzQiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl80IjtzOjc6IiNmZmZmZmYiO3M6MTA6ImZvbnRfbGFiZWwiO3M6MTA6IkFsZXggQnJ1c2giO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiI2ZmZmZmZiI7czoxMDoiZm9udF90eHRfMCI7czoxMjoiSm9zZWZpbiBTYW5zIjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjZmZmZmZmIjtzOjExOiJmb250X2Zvb3RlciI7czoxMjoiSm9zZWZpbiBTYW5zIjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjNGY0ZjRmIjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjQ6Im5vbmUiO3M6NzoiYnVsbGV0cyI7czo4OiJwb3BfaWNvbiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjU6ImxhYmVsIjtzOjE1OiJDaHJpc3RtYXMgUGFydHkiO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjExODoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6ODoiYW5pbV9rZXkiO3M6MTA6InNsaWRlX2Rvd24iO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MjU6InN1Yl9tYWlsY2hpbXBfZ3JvdXBzX2Z1bGwiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTY6InN1Yl9ncl9jeWNsZV9kYXkiO3M6MToiMCI7czoxMzoic3ViX2ljX2FwcF9pZCI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfdXNlciI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfcGFzcyI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMzoic3ViX3NmX2FwcF9pZCI7czowOiIiO3M6MTQ6InN1Yl9ja19hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX21lbV9hY2NfaWQiO3M6MDoiIjtzOjE1OiJzdWJfbWVtX3B1ZF9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfbWVtX3ByaXZfa2V5IjtzOjA6IiI7czoxNDoic3ViX3NiX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfdjZfYXBpX2tleSI7czowOiIiO3M6MTI6InN1Yl92dGlnX3VybCI7czowOiIiO3M6MTM6InN1Yl92dGlnX25hbWUiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ19rZXkiO3M6MDoiIjtzOjE2OiJzdWJfeW1scF9hcGlfa2V5IjtzOjA6IiI7czoxMzoic3ViX3ltbHBfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9uYW1lIjtzOjA6IiI7czoxMToic3ViXzRkX3Bhc3MiO3M6MDoiIjtzOjEwOiJzdWJfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo2OntzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoyMDoic3ViX3R4dF9leGlzdHNfZW1haWwiO3M6MjM6IkVtcHR5ICBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czoxNzoiR0VUIFlPVVIgRElTQ09VTlQiO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJzdWJfbmV3X3N1YmplY3QiO3M6Mjk6Ik5ldyBzdWJzY3JpYmVyIGZvciBbc2l0ZW5hbWVdIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIGlzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6ODoibG9naW5fYnkiO3M6ODoidXNlcm5hbWUiO3M6MTg6ImxvZ2luX3JlZGlyZWN0X3VybCI7czowOiIiO3M6MTU6ImxvZ2luX2J0bl9sYWJlbCI7czoxMDoi0JvQvtCz0LjQvSI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiLQmNC80Y8iO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6MTk1OiLQodGB0YvQu9C60LAg0LTQu9GPINC/0L7QtNGC0LLQtdGA0LbQtNC10L3QuNGPINCx0YvQuyDQvtGC0L/RgNCw0LLQu9C10L3QsCDQvdCwINCy0LDRiCDQsNC00YDQtdGBINGN0LvQtdC60YLRgNC+0L3QvdC+0Lkg0L/QvtGH0YLRiy4g0J/RgNC+0LLQtdGA0YzRgtC1INCy0LDRiNGDINGN0LvQtdC60YLRgNC+0L3QvdGD0Y4g0L/QvtGH0YLRgyEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czo0Mzoi0KHQv9Cw0YHQuNCx0L4g0LfQsCDRgNC10LPQuNGB0YLRgNCw0YbQuNGOISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjU4OiLQn9GD0YHRgtC+0Lkg0LjQu9C4INC90LXQtNC10LnRgdGC0LLQuNGC0LXQu9GM0L3Ri9C5IGVtYWlsIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czo2MToi0J/QvtC00YLQstC10YDQtNC40YLQtSDRgNC10LPQuNGB0YLRgNCw0YbQuNGOINC90LAgW3NpdGVuYW1lXSI7czoyNToicmVnX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MzM0OiLQktGLINC30LDRgNC10LPQuNGB0YLRgNC40YDQvtCy0LDQvdGLINC90LAg0YHQsNC50YLQtSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uINCh0LvQtdC00YPQudGC0LUgIDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4g0LTQu9GPINC30LDQstC10YDRiNC10L3QuNGPINGA0LXQs9C40YHRgtGA0LDRhtC40LguINCV0YHQu9C4INCy0Ysg0L3QtSDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0LvQuNGB0Ywg0LfQtNC10YHRjCAtINC/0YDQvtGB0YLQviDQuNCz0L3QvtGA0LjRgNGD0LnRgtC1INGN0YLQviDRgdC+0L7QsdGJ0LXQvdC40LUuIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjQ1OiJbc2l0ZW5hbWVdICDQktCw0Ygg0LvQvtCz0LjQvSDQuCDQv9Cw0YDQvtC70YwiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjcxOiLQm9C+0LPQuNC9OiBbdXNlcl9sb2dpbl08YnIgLz7Qn9Cw0YDQvtC70Yw6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxNzc6ItCjINCy0LDRgSDQvdC+0LLRi9C5INC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjCDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCDQstC+0YIg0LjQvdGE0L7RgNC80LDRhtC40Y8g0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GPOiA8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxMjoiY29udGFjdF9mb3JtIjtzOjI6IjIwIjtzOjEyOiJzdGF0X2dhX2NvZGUiO3M6MDoiIjtzOjU6InR4dF8wIjtzOjcxOiI8cD5XZSBoYXZlIHNvbWV0aGluZyBmb3IgRVZFUllPTkUgb24gWU9VUiBsaXN0LiBTYXZlIFVwIHRvIDcwJSBPRkYhPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNSI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link href=\"https://fonts.googleapis.com/css?family=Oxygen\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsTopBgWrapper\">\r\n <div class=\"ppsWrapImgWr\">\r\n [if bg_type_1 == \"img\"]\r\n <img src=\"[bg_img_1]\" class=\"ppsImgWr\"/>\r\n [endif]\r\n </div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div class=\"ppsSnow\"></div>\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n \r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n <div class=\"\"></div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Oxygen\";\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background-color: [bg_color_0];\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0 0 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n\r\n}\r\n\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n \r\n color: #4f4f4f;\r\n text-align: center;\r\n border: 2px solid #aaa;\r\n font-family: \"Oxygen\";\r\n font-size: 16px;\r\n font-weight: normal;\r\n width: 100%;\r\n display:block;\r\n margin-top: 10px;\r\n height: 45px;\r\n \r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n [if bg_type_4 == \"color\"]\r\n background: [bg_color_4];\r\n [elseif bg_type_4 == \"img\"]\r\n background-image: url(\"[bg_img_4]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n height: auto;\r\n padding-top: 9px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display:inline-block;\r\n margin-top: 0px\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n margin-top: 10px;\r\n font-size: 16px;\r\n color: #4f4f4f;\r\n text-align: center;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n display:block;\r\n height: 45px;\r\n color: #fff;\r\n font-size: 18px;\r\n width: 100%;\r\n margin: 10px 0;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n border: 0 solid transparent;\r\n cursor: pointer;\r\n text-transform: none;\r\n padding: 0;\r\n font-weight: 700;\r\n font-family: \"Oxygen\";\r\n [if bg_type_3 == \"color\"]\r\n background: [bg_color_3];\r\n [elseif bg_type_3 == \"img\"]\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n display: inline-block;\r\n margin: 40px 0 0;\r\n width: 40%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopBgWrapper {\r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n padding: 30px 0;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapImgWr {\r\n display: inline-block;\r\n text-align: center;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsImgWr {\r\n display: inline-block;\r\n max-width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 50px;\r\n font-family: \"Oxygen\";\r\n position: relative;\r\n z-index: 100;\r\n width: 90%;\r\n display: inline-block;\r\n padding-top: 30px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n font-family: \"Oxygen\";\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n font-size: 20px;\r\n padding-top: 30px;\r\n font-weight: bold;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n display: inline-block;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n color: #4f4f4f;\r\n margin: 5px 0px;\r\n text-align: center;\r\n width: 80%;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}","x-mas-sale.png","1","1","1","11","2015-01-10 18:59:43","45"),
|
556 |
("46","Merry Christmas","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMzoib3ZlcmxheV9jbGljayI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjEwNDp7czo1OiJ3aWR0aCI7czozOiI3MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czozOiJpbWciO3M6ODoiYmdfaW1nXzAiO3M6NDY6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzLzIwMTZfMzYwX255dF9iZy5wbmciO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjUxOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8yMDE2XzM2MF9ueXRfdG9wX2ltZy5wbmciO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzIiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzIiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiMxMzMxNmMiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmOWU2Y2UiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6NDoibm9uZSI7czo3OiJidWxsZXRzIjtzOjExOiJsaXN0c19ncmVlbiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjU6ImxhYmVsIjtzOjA6IiI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTQ6InN1Yl9zYl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX3Y2X2FwaV9rZXkiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ191cmwiO3M6MDoiIjtzOjEzOiJzdWJfdnRpZ19uYW1lIjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfa2V5IjtzOjA6IiI7czoxNjoic3ViX3ltbHBfYXBpX2tleSI7czowOiIiO3M6MTM6InN1Yl95bWxwX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9wYXNzIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6MTE6IllvdXIgZS1tYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fXM6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6OToiWW91ciBuYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoyMDoic3ViX3R4dF9leGlzdHNfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjE1OiJKb2luIHJpZ2h0IG5vdyEiO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJzdWJfbmV3X3N1YmplY3QiO3M6Mjk6Ik5ldyBTdWJzY3JpYmVyIG9uICBbc2l0ZW5hbWVdIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6ODoibG9naW5fYnkiO3M6ODoidXNlcm5hbWUiO3M6MTg6ImxvZ2luX3JlZGlyZWN0X3VybCI7czowOiIiO3M6MTU6ImxvZ2luX2J0bl9sYWJlbCI7czoxMDoi0JvQvtCz0LjQvSI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiLQmNC80Y8iO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6MTk1OiLQodGB0YvQu9C60LAg0LTQu9GPINC/0L7QtNGC0LLQtdGA0LbQtNC10L3QuNGPINCx0YvQuyDQvtGC0L/RgNCw0LLQu9C10L3QsCDQvdCwINCy0LDRiCDQsNC00YDQtdGBINGN0LvQtdC60YLRgNC+0L3QvdC+0Lkg0L/QvtGH0YLRiy4g0J/RgNC+0LLQtdGA0YzRgtC1INCy0LDRiNGDINGN0LvQtdC60YLRgNC+0L3QvdGD0Y4g0L/QvtGH0YLRgyEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czo0Mzoi0KHQv9Cw0YHQuNCx0L4g0LfQsCDRgNC10LPQuNGB0YLRgNCw0YbQuNGOISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjU4OiLQn9GD0YHRgtC+0Lkg0LjQu9C4INC90LXQtNC10LnRgdGC0LLQuNGC0LXQu9GM0L3Ri9C5IGVtYWlsIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czo2MToi0J/QvtC00YLQstC10YDQtNC40YLQtSDRgNC10LPQuNGB0YLRgNCw0YbQuNGOINC90LAgW3NpdGVuYW1lXSI7czoyNToicmVnX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MzM0OiLQktGLINC30LDRgNC10LPQuNGB0YLRgNC40YDQvtCy0LDQvdGLINC90LAg0YHQsNC50YLQtSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uINCh0LvQtdC00YPQudGC0LUgIDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4g0LTQu9GPINC30LDQstC10YDRiNC10L3QuNGPINGA0LXQs9C40YHRgtGA0LDRhtC40LguINCV0YHQu9C4INCy0Ysg0L3QtSDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0LvQuNGB0Ywg0LfQtNC10YHRjCAtINC/0YDQvtGB0YLQviDQuNCz0L3QvtGA0LjRgNGD0LnRgtC1INGN0YLQviDRgdC+0L7QsdGJ0LXQvdC40LUuIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjQ1OiJbc2l0ZW5hbWVdICDQktCw0Ygg0LvQvtCz0LjQvSDQuCDQv9Cw0YDQvtC70YwiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjcxOiLQm9C+0LPQuNC9OiBbdXNlcl9sb2dpbl08YnIgLz7Qn9Cw0YDQvtC70Yw6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxNzc6ItCjINCy0LDRgSDQvdC+0LLRi9C5INC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjCDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCDQstC+0YIg0LjQvdGE0L7RgNC80LDRhtC40Y8g0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GPOiA8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxMjoiY29udGFjdF9mb3JtIjtzOjI6IjIwIjtzOjEyOiJzdGF0X2dhX2NvZGUiO3M6MDoiIjtzOjU6InR4dF8wIjtzOjA6IiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiMyI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link href=\"https://fonts.googleapis.com/css?family=Gentium+Basic\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsWrapTopImg\">\r\n [if bg_type_1 == \"img\"]\r\n <img src=\"[bg_img_1]\" class=\"ppsTopImg\"/>\r\n [endif]\r\n </div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsBottomCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Gentium Basic\", arial;\r\n font-size: 13px;\r\n font-weight: normal;\r\n color: #000;\r\n text-align: center;\r\n}\r\n\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n width: 100%;\r\n padding: 40px;\r\n [if bg_type_0 == \"color\"]\r\n background-color: [bg_color_0];\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapTopImg {\r\n display: inline-block;\r\n text-align: center;\r\n width: 100%;\r\n margin-bottom: 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopImg {\r\n display: inline-block;\r\n max-width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n min-height: 200px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n width: 60%;\r\n display: inline-block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=password],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: \"Gentium Basic\", arial;\r\n font-size: 17px;\r\n font-weight: normal;\r\n border: 1px solid transparent;\r\n width: 100%;\r\n display: block;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n height: 41px;\r\n margin: 10px 0 0;\r\n text-transform: none;\r\n \r\n padding-left: 15px;\r\n background-image: none;\r\n background-repeat: no-repeat;\r\n background-color: #fff;\r\n color: #13316c;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n margin: 0;\r\n min-height: 41px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n font-family: \"Gentium Basic\", arial;\r\n font-size: 17px;\r\n font-weight: normal;\r\n display: block;\r\n margin: 10px 0 0;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n height: auto;\r\n padding-top: 9px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text], \r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n padding-left: 35px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/user-black-icon.png\");\r\n background-position: 12px center;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/email-black-icon.png\");\r\n background-position: 10px center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n background: -moz-linear-gradient(top, {{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }} 26%, [bg_color_2] 100%);\r\n background: -webkit-linear-gradient(top, {{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }} 26%,[bg_color_2] 100%);\r\n background: linear-gradient(to bottom, {{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }} 26%,[bg_color_2] 100%);\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }}\", endColorstr=\"[bg_color_2]\",GradientType=0 );\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n height: 41px;\r\n text-transform: none;\r\n margin: 10px 0 0;\r\n -webkit-box-shadow: 2px 2px 6px 2px rgba(0, 0, 0, 0.75);\r\n -moz-box-shadow: 2px 2px 6px 2px rgba(0, 0, 0, 0.75);\r\n box-shadow: 2px 2px 6px 2px rgba(0, 0, 0, 0.75);\r\n padding: 0;\r\n cursor: pointer;\r\n color: #fff;\r\n font-size: 20px;\r\n font-family: \"Gentium Basic\", arial;\r\n font-weight: normal;\r\n border: 1px solid transparent;\r\n width: 100%;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n -webkit-box-shadow: 2px 2px 7px 2px rgba(0, 0, 0, 0.75);\r\n -moz-box-shadow: 2px 2px 7px 2px rgba(0, 0, 0, 0.75);\r\n box-shadow: 2px 2px 7px 2px rgba(0, 0, 0, 0.75);\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 40px;\r\n line-height: 40px;\r\n font-weight: bold;\r\n margin: 0 30px 30px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n width: 100%;\r\n font-size: 14px;\r\n margin: 0 30px 20px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n right: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n color: #585858;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm {\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg {\r\n margin: 0px;\r\n}","merry-christmas.png","1","1","1","11","2015-01-10 18:59:43","46"),
|
557 |
("47","Christmas Recipes","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMzoib3ZlcmxheV9jbGljayI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjExNzp7czo1OiJ3aWR0aCI7czozOiI0MzgiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjM5OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8zNjUtMS1iZy5wbmciO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzIiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzIiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiMwMjAxMDEiO3M6OToiYmdfdHlwZV8zIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18zIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjZmZiMmIyIjtzOjEwOiJmb250X2xhYmVsIjtzOjEwOiJBbGV4IEJydXNoIjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiNmZmZmZmYiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czoxMDoiZm9udF90eHRfMSI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMSI7czo3OiIjRkZCMkIyIjtzOjEwOiJmb250X3R4dF8yIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8yIjtzOjc6IiMzMzMzMzMiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiNiN2I3YjciO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6NDoibm9uZSI7czo3OiJidWxsZXRzIjtzOjg6InBvcF9pY29uIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6NToibGFiZWwiO3M6MTU6IkNocmlzdG1hcyBQYXJ0eSI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJlbmJfdHh0XzEiO3M6MToiMSI7czo5OiJlbmJfdHh0XzIiO3M6MToiMSI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMzoiTk8sIFRIQU5LIFlPVSI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6ODoiYW5pbV9rZXkiO3M6NDoibm9uZSI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoyNToic3ViX21haWxjaGltcF9ncm91cHNfZnVsbCI7czowOiIiO3M6MTQ6InN1Yl9ncl9hcGlfa2V5IjtzOjA6IiI7czoxNjoic3ViX2dyX2N5Y2xlX2RheSI7czoxOiIwIjtzOjEzOiJzdWJfaWNfYXBwX2lkIjtzOjA6IiI7czoxNToic3ViX2ljX2FwcF91c2VyIjtzOjA6IiI7czoxNToic3ViX2ljX2FwcF9wYXNzIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV91cmwiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX2tleSI7czowOiIiO3M6MTg6InN1Yl9hcl9mb3JtX2FjdGlvbiI7czowOiIiO3M6MTA6InN1Yl9zZ2FfaWQiO3M6MDoiIjtzOjE1OiJzdWJfc2dhX2xpc3RfaWQiO3M6MDoiIjtzOjIxOiJzdWJfc2dhX2FjdGl2YXRlX2NvZGUiO3M6MDoiIjtzOjEzOiJzdWJfc2ZfYXBwX2lkIjtzOjA6IiI7czoxNDoic3ViX2NrX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfbWVtX2FjY19pZCI7czowOiIiO3M6MTU6InN1Yl9tZW1fcHVkX2tleSI7czowOiIiO3M6MTY6InN1Yl9tZW1fcHJpdl9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfc2JfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl92Nl9hcGlfa2V5IjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfdXJsIjtzOjA6IiI7czoxMzoic3ViX3Z0aWdfbmFtZSI7czowOiIiO3M6MTI6InN1Yl92dGlnX2tleSI7czowOiIiO3M6MTY6InN1Yl95bWxwX2FwaV9rZXkiO3M6MDoiIjtzOjEzOiJzdWJfeW1scF9uYW1lIjtzOjA6IiI7czoxMToic3ViXzRkX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfcGFzcyI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjY6e3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjIwOiJzdWJfdHh0X2V4aXN0c19lbWFpbCI7czoyMzoiRW1wdHkgIG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjg6IkRPV05MT0FEIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19zdWJqZWN0IjtzOjI5OiJOZXcgc3Vic2NyaWJlciBmb3IgW3NpdGVuYW1lXSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6MTA6ItCb0L7Qs9C40L0iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6Njoi0JjQvNGPIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjE5NToi0KHRgdGL0LvQutCwINC00LvRjyDQv9C+0LTRgtCy0LXRgNC20LTQtdC90LjRjyDQsdGL0Lsg0L7RgtC/0YDQsNCy0LvQtdC90LAg0L3QsCDQstCw0Ygg0LDQtNGA0LXRgSDRjdC70LXQutGC0YDQvtC90L3QvtC5INC/0L7Rh9GC0YsuINCf0YDQvtCy0LXRgNGM0YLQtSDQstCw0YjRgyDRjdC70LXQutGC0YDQvtC90L3Rg9GOINC/0L7Rh9GC0YMhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6NDM6ItCh0L/QsNGB0LjQsdC+INC30LAg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czo1ODoi0J/Rg9GB0YLQvtC5INC40LvQuCDQvdC10LTQtdC50YHRgtCy0LjRgtC10LvRjNC90YvQuSBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6NjE6ItCf0L7QtNGC0LLQtdGA0LTQuNGC0LUg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiDQvdCwIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjMzNDoi0JLRiyDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0L3RiyDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiDQodC70LXQtNGD0LnRgtC1ICA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+INC00LvRjyDQt9Cw0LLQtdGA0YjQtdC90LjRjyDRgNC10LPQuNGB0YLRgNCw0YbQuNC4LiDQldGB0LvQuCDQstGLINC90LUg0LfQsNGA0LXQs9C40YHRgtGA0LjRgNC+0LLQsNC70LjRgdGMINC30LTQtdGB0YwgLSDQv9GA0L7RgdGC0L4g0LjQs9C90L7RgNC40YDRg9C50YLQtSDRjdGC0L4g0YHQvtC+0LHRidC10L3QuNC1LiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czo0NToiW3NpdGVuYW1lXSAg0JLQsNGIINC70L7Qs9C40L0g0Lgg0L/QsNGA0L7Qu9GMIjtzOjI4OiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo3MToi0JvQvtCz0LjQvTogW3VzZXJfbG9naW5dPGJyIC8+0J/QsNGA0L7Qu9GMOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MTM6InJlZ19uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJyZWdfbmV3X21lc3NhZ2UiO3M6MTc3OiLQoyDQstCw0YEg0L3QvtCy0YvQuSDQv9C+0LvRjNC30L7QstCw0YLQtdC70Ywg0L3QsCDRgdCw0LnRgtC1IDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwg0LLQvtGCINC40L3RhNC+0YDQvNCw0YbQuNGPINC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjzogPGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6MTI6ImNvbnRhY3RfZm9ybSI7czoyOiIyMCI7czoxMjoic3RhdF9nYV9jb2RlIjtzOjA6IiI7czo1OiJ0eHRfMCI7czoxNjoiPHA+RlJFRSBESUVUPC9wPiI7czo1OiJ0eHRfMSI7czoxNjoiPHA+TUVBTCBQTEFOPC9wPiI7czo1OiJ0eHRfMiI7czo0MjoiPHA+TG93LUNhcnAgUmVjaXBlcyBZb3XigJlsbCBGYWxsIEZvciE8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjMiO319","<link href=\"https://fonts.google.com/?query=Open+sans&selection.family=Open+Sans:400,700\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsTopBgWrapper\">\r\n <div class=\"ppsWrapImgWr\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsBtmBgWrapper\">\r\n [if enb_txt_2]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_2 ppsPopupTxt_2\">\r\n [txt_2]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [if enb_foot_note]\r\n <a href=\"#\" class=\"ppsFootNote ppsPopupClose\">\r\n [foot_note]\r\n </a>\r\n [endif]\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n \r\n [endif]\r\n </div>\r\n <div class=\"ppsBtmLine\"></div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Open Sans\", arial;\r\n font-size: 13px;\r\n line-height: normal;\r\n font-weight: normal;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background-color: [bg_color_0];\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0;\r\n}\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n margin: 10px 0 0;\r\n font-size: 16px;\r\n font-family: \"Open Sans\", arial;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n border: 2px solid #ccc;\r\n width: 100%;\r\n display:block;\r\n background: #fff;\r\n color: #4f4f4f;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n font-size: 16px;\r\n font-family: \"Open Sans\", arial;\r\n border: 2px solid #ccc;\r\n display: inline-block;\r\n background: #fff;\r\n color: #4f4f4f;\r\n text-align: center;\r\n height: 45px;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n color: #333333;\r\n display: block;\r\n margin: 10px 0 0;\r\n font-size: 16px;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n height: 45px;\r\n}\r\n#ppsPopupShell_[ID] input[type=submit] {\r\n font-family: \"Open Sans\", arial;\r\n display:inline-block;\r\n color: #fff;\r\n font-size: 18px;\r\n width: auto;\r\n margin: 10px 0;\r\n -webkit-border-radius: 35px;\r\n -moz-border-radius: 35px;\r\n border-radius: 35px;\r\n border: 0 solid transparent;\r\n cursor: pointer;\r\n text-transform: none;\r\n padding: 13px 88px 7px 60px;\r\n font-weight: 700;\r\n text-shadow: 1px 2px 0px #86B80E;\r\n text-decoration: none;text-decoration: none;\r\n \r\n -webkit-box-shadow: 1px 4px 0 0 rgba(134, 184, 14, 1);\r\n -moz-box-shadow: 1px 4px 0 0 rgba(134, 184, 14, 1);\r\n box-shadow: 1px 4px 0 0 rgba(134, 184, 14, 1);\r\n\r\n background-color: #9cd610;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/365-1-arr-dwn.png\");\r\n background-position: 79% 13px;\r\n background-repeat: no-repeat;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input.butt + a.ppsPopupClose {\r\n display: inline-block !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n display: inline-block;\r\n margin: 20px 0 20px;\r\n width: 60%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopBgWrapper {\r\n [if bg_type_1 == \"color\"]\r\n background: [bg_color_1];\r\n [elseif bg_type_1 == \"img\"]\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n padding: 70px 0 0;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapImgWr {\r\n [if bg_type_2 == \"color\"]\r\n background: {{ hex_to_rgba_str(popup.params.tpl.bg_color_2, 0.5) }};\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n display: inline-block;\r\n min-height: 130px;\r\n padding: 10px 0;\r\n text-align: center;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsImgWr {\r\n display: inline-block;\r\n max-width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 50px;\r\n position: relative;\r\n z-index: 100;\r\n width: 90%;\r\n display: inline-block;\r\n padding-top: 30px;\r\n font-family: \"Open Sans\", arial;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n font-size: 63px;\r\n font-weight: bold;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n color: #ffb2b2;\r\n font-size: 56px;\r\n font-weight: bold;\r\n line-height: 51px;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 {\r\n color: #333333;\r\n font-size: 21px;\r\n font-weight: bold;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsBtmBgWrapper {\r\n padding: 20px 0 0;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsBtnOne:hover {\r\n text-decoration: none;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsBtmLine {\r\n height: 5px;\r\n \r\n [if bg_type_3 == \"color\"]\r\n background: {{ hex_to_rgba_str(popup.params.tpl.bg_color_3, 0.5) }} !important;\r\n [elseif bg_type_3 == \"img\"]\r\n background-image: url(\"[bg_img_3]\") !important;\r\n background-repeat: no-repeat !important; \r\n background-size: cover !important;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n z-index: 1000;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n border-bottom: 2px dotted #b7b7b7;\r\n color: #b7b7b7;\r\n display: none !important;\r\n margin: 10px 0;\r\n text-decoration: none; \r\n background: none !important;\r\n font-size: 16px;\r\n height: auto !important;\r\n position: static !important;\r\n width: auto !important;\r\n top: 0 !important;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote:hover {\r\n text-decoration: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}","christmas-1-prev.png","1","1","1","11","2015-01-10 18:59:43","47"),
|
558 |
-
("48","Christmas mood","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjExODp7czo1OiJ3aWR0aCI7czozOiI1MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjQ0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8zNjUtMi10b3AtaW1nLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjZmZmZmZmIjtzOjk6ImJnX3R5cGVfMiI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMiI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiI2Y0ZjRmNCI7czo5OiJiZ190eXBlXzMiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzMiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8zIjtzOjc6IiNlZjI4MjEiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMzMzMzMzIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmMjM2MmQiO3M6MTA6ImZvbnRfdHh0XzEiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzEiO3M6NzoiIzMzMzMzMyI7czoxMDoiZm9udF90eHRfMiI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMiI7czo3OiIjMzMzMzMzIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjMDE2ODIzIjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjk6InJlZF9jbG9zZSI7czo3OiJidWxsZXRzIjtzOjg6InBvcF9pY29uIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MTA6IlNhdmUgdXAgdG8iO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZW5iX3R4dF8xIjtzOjE6IjEiO3M6OToiZW5iX3R4dF8yIjtzOjE6IjEiO3M6MTM6ImVuYl9mb290X25vdGUiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6Mjg6IkNvdW50aW51ZSB3aXRob3V0IDUwJSBjb3Vwb24iO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo0OiJib3h5IjtzOjg6ImFuaW1fa2V5IjtzOjEwOiJzbGlkZV9kb3duIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTQ6InN1Yl9zYl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX3Y2X2FwaV9rZXkiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ191cmwiO3M6MDoiIjtzOjEzOiJzdWJfdnRpZ19uYW1lIjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfa2V5IjtzOjA6IiI7czoxNjoic3ViX3ltbHBfYXBpX2tleSI7czowOiIiO3M6MTM6InN1Yl95bWxwX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9wYXNzIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YTo2OntzOjQ6Im5hbWUiO2E6Njp7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjExOiJZb3VyIGUtbWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO31pOjExO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjI6IjExIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czoyOiIxMSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjEiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31pOjIyO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjI6IjIyIjtzOjQ6Imh0bWwiO3M6ODoidGV4dGFyZWEiO3M6NToibGFiZWwiO3M6MjoiMjIiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIxIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9aTozMzthOjg6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czoyOiIzMyI7czo0OiJodG1sIjtzOjk6InNlbGVjdGJveCI7czo1OiJsYWJlbCI7czoyOiIzMyI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjEiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO3M6Nzoib3B0aW9ucyI7YToyOntpOjA7YToyOntzOjQ6Im5hbWUiO3M6NjoiYXNmYXNmIjtzOjU6ImxhYmVsIjtzOjM6InNhZiI7fWk6MTthOjI6e3M6NDoibmFtZSI7czo2OiJhc2Zhc2YiO3M6NToibGFiZWwiO3M6ODoiYXNmZGFzZGYiO319fWk6NTU7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6MjoiNTUiO3M6NDoiaHRtbCI7czo4OiJjaGVja2JveCI7czo1OiJsYWJlbCI7czoyOiI1NSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjEiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIzOiJFbXB0eSAgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6NzoiU2lnbiBVcCI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfc3ViamVjdCI7czoyOToiTmV3IHN1YnNjcmliZXIgZm9yIFtzaXRlbmFtZV0iO3M6MTU6InN1Yl9uZXdfbWVzc2FnZSI7czoxMjk6IllvdSBoYXZlIG5ldyBzdWJzY3JpYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgaXMgc3Vic2NyaWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo4OiJsb2dpbl9ieSI7czo4OiJ1c2VybmFtZSI7czoxODoibG9naW5fcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoxNToibG9naW5fYnRuX2xhYmVsIjtzOjEwOiLQm9C+0LPQuNC9IjtzOjIzOiJyZWdfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxMzoicmVnX2J0bl9sYWJlbCI7czo4OiJSZWdpc3RlciI7czoxMDoicmVnX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6ItCY0LzRjyI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJyZWdfdHh0X2NvbmZpcm1fc2VudCI7czoxOTU6ItCh0YHRi9C70LrQsCDQtNC70Y8g0L/QvtC00YLQstC10YDQttC00LXQvdC40Y8g0LHRi9C7INC+0YLQv9GA0LDQstC70LXQvdCwINC90LAg0LLQsNGIINCw0LTRgNC10YEg0Y3Qu9C10LrRgtGA0L7QvdC90L7QuSDQv9C+0YfRgtGLLiDQn9GA0L7QstC10YDRjNGC0LUg0LLQsNGI0YMg0Y3Qu9C10LrRgtGA0L7QvdC90YPRjiDQv9C+0YfRgtGDISI7czoxNToicmVnX3R4dF9zdWNjZXNzIjtzOjQzOiLQodC/0LDRgdC40LHQviDQt9CwINGA0LXQs9C40YHRgtGA0LDRhtC40Y4hIjtzOjIxOiJyZWdfdHh0X2ludmFsaWRfZW1haWwiO3M6NTg6ItCf0YPRgdGC0L7QuSDQuNC70Lgg0L3QtdC00LXQudGB0YLQstC40YLQtdC70YzQvdGL0LkgZW1haWwiO3M6MTY6InJlZ19yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjYxOiLQn9C+0LTRgtCy0LXRgNC00LjRgtC1INGA0LXQs9C40YHRgtGA0LDRhtC40Y4g0L3QsCBbc2l0ZW5hbWVdIjtzOjI1OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czozMzQ6ItCS0Ysg0LfQsNGA0LXQs9C40YHRgtGA0LjRgNC+0LLQsNC90Ysg0L3QsCDRgdCw0LnRgtC1IDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4g0KHQu9C10LTRg9C50YLQtSAgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiDQtNC70Y8g0LfQsNCy0LXRgNGI0LXQvdC40Y8g0YDQtdCz0LjRgdGC0YDQsNGG0LjQuC4g0JXRgdC70Lgg0LLRiyDQvdC1INC30LDRgNC10LPQuNGB0YLRgNC40YDQvtCy0LDQu9C40YHRjCDQt9C00LXRgdGMIC0g0L/RgNC+0YHRgtC+INC40LPQvdC+0YDQuNGA0YPQudGC0LUg0Y3RgtC+INGB0L7QvtCx0YnQtdC90LjQtS4iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6NDU6IltzaXRlbmFtZV0gINCS0LDRiCDQu9C+0LPQuNC9INC4INC/0LDRgNC+0LvRjCI7czoyODoicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NzE6ItCb0L7Qs9C40L06IFt1c2VyX2xvZ2luXTxiciAvPtCf0LDRgNC+0LvRjDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjEzOiJyZWdfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToicmVnX25ld19tZXNzYWdlIjtzOjE3Nzoi0KMg0LLQsNGBINC90L7QstGL0Lkg0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GMINC90LAg0YHQsNC50YLQtSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sINCy0L7RgiDQuNC90YTQvtGA0LzQsNGG0LjRjyDQv9C+0LvRjNC30L7QstCw0YLQtdC70Y86IDxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjEyOiJjb250YWN0X2Zvcm0iO3M6MjoiMjAiO3M6MTI6InN0YXRfZ2FfY29kZSI7czowOiIiO3M6NToidHh0XzAiO3M6MTM6IjxwPjUwJU9GRjwvcD4iO3M6NToidHh0XzEiO3M6Mzc6IjxwPkluc3RhbnTCoCBhY2Nlc3MgdG8gdGhlIGNvdXBvbjwvcD4iO3M6NToidHh0XzIiO3M6MTEwOiI8cD5CeSBjbGlja2luZyBcIlNpZ24gVXBcIiB5b3UgYWdyZWU8YnIgLz4gdG8gPGEgY2xhc3M9XCJwcHNUeHQzTGlua1wiIGhyZWY9XCIjXCI+VGVybXMgYW5kIENvbmRpdGlvbnM8L2E+PC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNCI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIzIjt9fQ==","<link href=\"https://fonts.googleapis.com/css?family=Alex+Brush|Josefin+Sans\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsWrapTopImg\">\r\n [if bg_type_1 == \"img\"]\r\n <img src=\"[bg_img_1]\" class=\"ppsTopImg\"/>\r\n [endif]\r\n </div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n <div class=\"ppsTxt1Separator\"></div>\r\n [endif]\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_txt_2]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_2 ppsPopupTxt_2\">\r\n [txt_2]\r\n </div>\r\n [endif]\r\n <div class=\"ppsTxt1Separator\"></div>\r\n [if enb_foot_note]\r\n <a href=\"#\" class=\"ppsFootNote ppsPopupClose\">\r\n [foot_note]\r\n </a>\r\n [endif]\r\n \r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n \r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: arial;\r\n font-size: 13px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\", endColorstr=\"[bg_color_0]\",GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0 0 40px;\r\n [if bg_type_3 == \"color\"]\r\n border: 3px solid [bg_color_3];\r\n [endif]\r\n \r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell{\r\n display: inline-block;\r\n margin: 0;\r\n width: 60%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=password],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n -webkit-border-radius: 0px;\r\n -moz-border-radius: 0px;\r\n border-radius: 0px;\r\n border: 1px solid transparent;\r\n height: 47px;\r\n padding: 0;\r\n margin: 10px 0;\r\n display:block;\r\n text-align: center;\r\n color: #016823;\r\n font-weight: normal;\r\n font-size: 18px;\r\n font-family: arial;\r\n \r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n margin: 0px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea { \r\n height: auto;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n display:block;\r\n margin: 10px 0 0;\r\n color: #016823;\r\n font-weight: normal;\r\n font-size: 18px;\r\n font-family: arial;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input::-webkit-input-placeholder { /* Chrome/Opera/Safari */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input::-moz-placeholder { /* Firefox 19+ */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell inpu:-ms-input-placeholder { /* IE 10+ */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input:-moz-placeholder { /* Firefox 18- */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n \r\n width: 100%;\r\n -webkit-border-radius: 0px;\r\n -moz-border-radius: 0px;\r\n border-radius: 0px;\r\n border: 1px solid transparent;\r\n height: 47px;\r\n padding: 0;\r\n margin: 10px 0;\r\n text-align: center;\r\n font-family: arial;\r\n \r\n color: #fff;\r\n cursor: pointer;\r\n text-transform: none;\r\n font-weight: 700;\r\n font-size: 20px;\r\n display: inline-block;\r\n border: 1px solid transparent;\r\n \r\n background-color: #016823;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/365-2-right-arr.png\");\r\n background-position: 90% center;\r\n background-repeat: no-repeat;\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapTopImg {\r\n display: inline-block;\r\n text-align: center;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopImg {\r\n display: inline-block;\r\n max-width: 70%;\r\n}\r\n\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-family: arial;\r\n font-size: 35px;\r\n padding: 20px 20px 0; \r\n text-align: center;\r\n line-height: 45px;\r\n position: relative;\r\n z-index: 100;\r\n color: #333333;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n font-family: arial;\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n color: #f2362d;\r\n font-size: 70px;\r\n font-weight: bold;\r\n line-height: 60px;\r\n margin: 10px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n color: #333333;\r\n font-size: 18px;\r\n padding: 10px 0;\r\n}\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 {\r\n display: block;\r\n font-size: 16px;\r\n margin: 0 auto 15px;\r\n text-align: center;\r\n width: 90%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 a {\r\n color: #f44b44;\r\n text-decoration: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 a:hover {\r\n text-decoration: none;\r\n}\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsTxt1Separator {\r\n background-color: #cccccc;\r\n display: block;\r\n height: 1px;\r\n margin: 0 auto;\r\n width: 15%;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n z-index: 1000 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n background: none !important;\r\n border-bottom: 2px solid #016823;\r\n color: #016823;\r\n display: inline-block !important;\r\n font-size: 16px;\r\n height: auto !important;\r\n margin: 10px 0;\r\n position: static !important;\r\n text-decoration: none;\r\n top: 0 !important;\r\n width: auto !important;\r\n \r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}\r\n","christmas-2-prev.png","1","1","1","11","2015-01-10 18:59:43","48"),
|
559 |
("49","Let it Snow","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjEwODp7czo1OiJ3aWR0aCI7czozOiI3MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjQ0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8zNjUtMy10b3AtaW1nLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjM2QzZDNkIjtzOjk6ImJnX3R5cGVfMiI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMiI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzMiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzMiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8zIjtzOjc6IiNmZmUwMDEiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmZmZmZmYiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiNjYmNiY2IiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6ImNsYXNzeV9ncmV5IjtzOjc6ImJ1bGxldHMiO3M6ODoicG9wX2ljb24iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo1OiJsYWJlbCI7czoxMDoiU2F2ZSB1cCB0byI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czozMjoiTm8sIHRoYW5rIHlvdS4gSeKAmW0gZ29vZCAgdG8gZ28iO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo0OiJib3h5IjtzOjg6ImFuaW1fa2V5IjtzOjEwOiJzbGlkZV9kb3duIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTQ6InN1Yl9zYl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX3Y2X2FwaV9rZXkiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ191cmwiO3M6MDoiIjtzOjEzOiJzdWJfdnRpZ19uYW1lIjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfa2V5IjtzOjA6IiI7czoxNjoic3ViX3ltbHBfYXBpX2tleSI7czowOiIiO3M6MTM6InN1Yl95bWxwX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9wYXNzIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Njp7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjExOiJZb3VyIGUtbWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIzOiJFbXB0eSAgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6MzU6IllFUywgSSB3YW50IHRvIGdldCBtb3JlIFN1YnNjcmliZXJzIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19zdWJqZWN0IjtzOjI5OiJOZXcgc3Vic2NyaWJlciBmb3IgW3NpdGVuYW1lXSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6MTA6ItCb0L7Qs9C40L0iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6Njoi0JjQvNGPIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjE5NToi0KHRgdGL0LvQutCwINC00LvRjyDQv9C+0LTRgtCy0LXRgNC20LTQtdC90LjRjyDQsdGL0Lsg0L7RgtC/0YDQsNCy0LvQtdC90LAg0L3QsCDQstCw0Ygg0LDQtNGA0LXRgSDRjdC70LXQutGC0YDQvtC90L3QvtC5INC/0L7Rh9GC0YsuINCf0YDQvtCy0LXRgNGM0YLQtSDQstCw0YjRgyDRjdC70LXQutGC0YDQvtC90L3Rg9GOINC/0L7Rh9GC0YMhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6NDM6ItCh0L/QsNGB0LjQsdC+INC30LAg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czo1ODoi0J/Rg9GB0YLQvtC5INC40LvQuCDQvdC10LTQtdC50YHRgtCy0LjRgtC10LvRjNC90YvQuSBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6NjE6ItCf0L7QtNGC0LLQtdGA0LTQuNGC0LUg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiDQvdCwIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjMzNDoi0JLRiyDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0L3RiyDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiDQodC70LXQtNGD0LnRgtC1ICA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+INC00LvRjyDQt9Cw0LLQtdGA0YjQtdC90LjRjyDRgNC10LPQuNGB0YLRgNCw0YbQuNC4LiDQldGB0LvQuCDQstGLINC90LUg0LfQsNGA0LXQs9C40YHRgtGA0LjRgNC+0LLQsNC70LjRgdGMINC30LTQtdGB0YwgLSDQv9GA0L7RgdGC0L4g0LjQs9C90L7RgNC40YDRg9C50YLQtSDRjdGC0L4g0YHQvtC+0LHRidC10L3QuNC1LiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czo0NToiW3NpdGVuYW1lXSAg0JLQsNGIINC70L7Qs9C40L0g0Lgg0L/QsNGA0L7Qu9GMIjtzOjI4OiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo3MToi0JvQvtCz0LjQvTogW3VzZXJfbG9naW5dPGJyIC8+0J/QsNGA0L7Qu9GMOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MTM6InJlZ19uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJyZWdfbmV3X21lc3NhZ2UiO3M6MTc3OiLQoyDQstCw0YEg0L3QvtCy0YvQuSDQv9C+0LvRjNC30L7QstCw0YLQtdC70Ywg0L3QsCDRgdCw0LnRgtC1IDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwg0LLQvtGCINC40L3RhNC+0YDQvNCw0YbQuNGPINC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjzogPGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6MTI6InN0YXRfZ2FfY29kZSI7czowOiIiO3M6NToidHh0XzAiO3M6MTIzOiI8cD5EbyBZb3UgV2FudCBUbzxzdHJvbmc+IEluY3JlYXNlPC9zdHJvbmc+IDxiciAvPllvdXIgU3Vic2NyaWJlcnMgPGJyIC8+PHN0cm9uZz5VcCBUbyA3MDAlPC9zdHJvbmc+IDxzdHJvbmc+Pzwvc3Ryb25nPjwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjQiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMSI7fX0=","<link href=\"https://fonts.googleapis.com/css?family=Alex+Brush|Josefin+Sans\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsWrapTopImg\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [if enb_foot_note]\r\n <a href=\"#\" class=\"ppsFootNote ppsPopupClose\">\r\n [foot_note]\r\n </a>\r\n [endif]\r\n \r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: arial;\r\n font-size: 13px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\", endColorstr=\"[bg_color_0]\",GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0 0 40px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsWrapTopImg {\r\n [if bg_type_1 == \"color\"]\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\", endColorstr=\"[bg_color_1]\",GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \"img\"]\r\n background-image: url(\"[bg_img_1]\");\r\n background-position: center bottom;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n min-height: 210px;\r\n padding: 40px 0 85px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell{\r\n display: inline-block;\r\n margin: 0;\r\n position: relative;\r\n z-index: 100;\r\n width: 90%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n position: relative;\r\n padding: 5px 0;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input {\r\n width: 100%;\r\n -webkit-border-radius: 0px;\r\n -moz-border-radius: 0px;\r\n border-radius: 0px;\r\n border: 0 solid transparent;\r\n height: 47px;\r\n padding: 0;\r\n margin: 0;\r\n display:block;\r\n font-family: arial;\r\n text-align: center;\r\n}\r\n\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=password],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n border: 1px solid #01a2ea;\r\n color: #777777;\r\n font-size: 18px;\r\n font-family: arial;\r\n font-weight: normal;\r\n height: 45px;\r\n padding: 0 20px;\r\n width: 100%;\r\n display:block;\r\n text-align: center;\r\n margin-top: 10px;\r\n \r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n margin-top: 0px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n font-size: 18px;\r\n font-family: arial;\r\n font-weight: normal;\r\n margin-top: 10px;\r\n display:block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n border: 1px solid #01a2ea;\r\n color: #777777;\r\n font-size: 18px;\r\n height: auto;\r\n padding: 20px 20px 50px;\r\n margin-top: 10px;\r\n \r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: 10px solid #fff;\r\n color: #333333;\r\n cursor: pointer;\r\n font-weight: 600;\r\n font-size: 20px;\r\n height: auto;\r\n display: inline-block;\r\n padding: 15px 0 13px;\r\n bottom: 65px;\r\n \r\n -webkit-border-radius: 20px;\r\n -moz-border-radius: 20px;\r\n border-radius: 20px;\r\n position: absolute;\r\n text-transform: none;\r\n left: 5%;\r\n width: 90%;\r\n \r\n [if bg_type_3 == \"color\"]\r\n background: [bg_color_3] !important;\r\n [elseif bg_type_3 == \"img\"]\r\n background-image: url(\"[bg_img_3]\") !important;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]::-webkit-input-placeholder { /* Chrome/Opera/Safari */\r\n color: #999999;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]::-moz-placeholder { /* Firefox 19+ */\r\n color: #999999;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]:-ms-input-placeholder { /* IE 10+ */\r\n color: #999999;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]:-moz-placeholder { /* Firefox 18- */\r\n color: #999999;\r\n}\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-family: arial;\r\n font-size: 35px;\r\n padding: 20px 20px 0; \r\n text-align: center;\r\n line-height: 45px;\r\n position: relative;\r\n z-index: 100;\r\n color: #fff;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n font-family: arial;\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n word-wrap: break-word;\r\n line-height: 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n color: #fff;\r\n font-size: 53px;\r\n line-height: 50px;\r\n margin: 10px 0;\r\n text-shadow: 2px 2px 0 #01a2ea;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] + .ppsFootNote {\r\n display: inline-block !important;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n -webkit-border-radius: 10px;\r\n -moz-border-radius: 10px;\r\n border-radius: 10px;\r\n \r\n background: none !important;\r\n border: 2px solid #cbcbcb;\r\n color: #cbcbcb;\r\n display: none !important;\r\n font-size: 16px;\r\n font-weight: bold;\r\n height: auto !important;\r\n margin: 60px 30px 0;\r\n padding: 5px 20px;\r\n position: static !important;\r\n text-decoration: none;\r\n top: 0 !important;\r\n width: auto !important;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n z-index: 1000 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}\r\n","christmas-3-prev.png","1","1","1","11","2015-01-10 18:59:43","49")');
|
560 |
}
|
561 |
if(dbPps::get('SELECT COUNT(*) AS total FROM @__popup WHERE id = 5 AND original_id = 0', 'one')) {
|
545 |
if(!dbPps::exist('@__popup', 'id', '40')) { // Second set of additional templates
|
546 |
dbPps::query('INSERT INTO @__popup (id,label,active,original_id,params,html,css,img_preview,show_on,show_to,show_pages,type_id,date_created,sort_order) VALUES
|
547 |
("40","List Building Neo","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoxMDoic2hvd19wYWdlcyI7czozOiJhbGwiO3M6MTQ6InNob3dfdGltZV9mcm9tIjtzOjc6IjEyOjAwYW0iO3M6MTI6InNob3dfdGltZV90byI7czo3OiIxMjowMGFtIjtzOjE0OiJzaG93X2RhdGVfZnJvbSI7czowOiIiO3M6MTI6InNob3dfZGF0ZV90byI7czowOiIiO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoxNToiY291bnRfdGltZXNfbnVtIjtzOjE6IjEiO3M6MTU6ImNvdW50X3RpbWVzX21lcyI7czozOiJkYXkiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9zZWFyY2hfZW5naW5lc19zaG93IjtzOjE6IjAiO3M6MTg6ImhpZGVfcHJlZ191cmxfc2hvdyI7czoxOiIwIjtzOjEzOiJoaWRlX3ByZWdfdXJsIjtzOjA6IiI7czoyNDoiaGlkZV9mb3JfdXNlcl9yb2xlc19zaG93IjtzOjE6IjAiO31zOjM6InRwbCI7YTo2Mjp7czo1OiJ3aWR0aCI7czozOiI4MjQiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18wIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjZjRmNGY0IjtzOjk6ImJnX3R5cGVfMSI7czozOiJpbWciO3M6ODoiYmdfaW1nXzEiO3M6NDI6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL25ldy1mb3JtLWJnLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjNGQ0ZDRkIjtzOjk6ImJnX3R5cGVfMiI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMiI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiIzAwZWFlYSI7czo5OiJiZ190eXBlXzMiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18zIjtzOjQ0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9uZXctZm9ybS1sb2dvLnBuZyI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjYzZjNmM2IjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzAwMDAwMCI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjIwOiJjaXJjbGVfYmlnX25ld19jbG9zZSI7czo3OiJidWxsZXRzIjtzOjE0OiJjaXJjbGVfYmlnX25ldyI7czoxMToibGF5ZXJlZF9wb3MiO3M6MDoiIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjEwNzoiVGhlIEJlc3QgV29yZFByZXNzIFBvcFVwIG9wdGluIHBsdWdpbiB0byBoZWxwIHlvdSBnYWluIG1vcmUgc3Vic2NyaWJlcnMsIHNvY2lhbCBmb2xsb3dlcnMgb3IgYWR2ZXJ0aXNlbWVudC4iO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6MTM6ImVuYl9mb290X25vdGUiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE5OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4NCllvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTSUdOLVVQISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfc3ViamVjdCI7czo0MDoiTmV3IFN1YnNjcmliZXIgb24gTXkgV29yZFByZXNzIFRlc3QgU2l0ZSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjEyOiJzdGF0X2dhX2NvZGUiO3M6MDoiIjtzOjU6InR4dF8wIjtzOjM4MToiPHA+UG9wdXAgYnkgU3Vwc3lzdGljIGxldHMgeW91IGVhc2lseSBjcmVhdGUgZWxlZ2FudCBvdmVybGFwcGluZyB3aW5kb3dzIHdpdGggdW5saW1pdGVkIGZlYXR1cmVzLiBQb3AtdXBzIHdpdGggU2xpZGVyLCBMaWdodGJveCwgQ29udGFjdCBhbmQgU3Vic2NyaXB0aW9uIGZvcm1zIGFuZCBtb3JlOjwvcD48dWw+PGxpPjxzdHJvbmc+VW5saW1pdGVkIENvbnRlbnQgQ3VzdG9taXphdGlvbjwvc3Ryb25nPjwvbGk+PGxpPjxzdHJvbmc+QXV0byBPcGVuIFBvcHVwczwvc3Ryb25nPjwvbGk+PGxpPjxzdHJvbmc+Q29udGFjdCBGb3JtIHdpdGggcG9wLXVwPC9zdHJvbmc+PC9saT48bGk+PHN0cm9uZz5Qb3B1cCBPcGVuaW5nIEFuaW1hdGlvPC9zdHJvbmc+bnM8L2xpPjwvdWw+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link href=\"https://fonts.googleapis.com/css?family=Montserrat\" rel=\"stylesheet\"> \r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n [if bg_type_3 == \'img\']\r\n <img src=\"[bg_img_3]\" class=\"ppsLogo\" />\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \"Montserrat\",\"Trebuchet MS\",\"Helvetica Neue\",Helvetica,Arial,Sans-Serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #4d4d4d;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 66%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n vertical-align: top;\r\n padding: 30px 20px;\r\n [if bg_type_0 == \'color\']\r\n background-color: [bg_color_0];\r\n background-image: none;\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 30px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n margin-bottom: 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n display: table-cell;\r\n width: 34%;\r\n height: 100%;\r\n text-align: center;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-color: [bg_color_1];\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 10px;\r\n font-size: 17px;\r\n background-color: #fff;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -5px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n [if bg_type_2 == \'color\']\r\n background-color: [bg_color_2];\r\n border-bottom: 3px solid {{ adjust_brightness(popup.params.tpl.bg_color_2, -50) }};\r\n background-image: none;\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 2px 2px 1px #555;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 ul {\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #fff;\r\n font-size: x-small;\r\n line-height: 14px;\r\n margin: 5px 30px 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsLogo {\r\n \r\n}","list-building-neo.jpg","1","1","1","1","2015-01-10 18:59:43","1"),
|
548 |
+
("41","Bright Girl","1","0","YTozOntzOjQ6Im1haW4iO2E6MzE6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czoxNDoidmlzaXRfcGFnZV9jbnQiO3M6MDoiIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI2OiJjbG9zZV9vbl9hZnRlcl9hY3Rpb25fdGltZSI7czoxOiIxIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjE0OiJzaG93X3RpbWVfZnJvbSI7czo3OiIxMjowMGFtIjtzOjEyOiJzaG93X3RpbWVfdG8iO3M6NzoiMTI6MDBhbSI7czoxNDoic2hvd19kYXRlX2Zyb20iO3M6MDoiIjtzOjEyOiJzaG93X2RhdGVfdG8iO3M6MDoiIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MTU6ImNvdW50X3RpbWVzX251bSI7czoxOiIxIjtzOjE1OiJjb3VudF90aW1lc19tZXMiO3M6MzoiZGF5IjtzOjIxOiJoaWRlX2Zvcl9kZXZpY2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9mb3JfcG9zdF90eXBlc19zaG93IjtzOjE6IjAiO3M6MTc6ImhpZGVfZm9yX2lwc19zaG93IjtzOjE6IjAiO3M6MTI6ImhpZGVfZm9yX2lwcyI7czowOiIiO3M6MjM6ImhpZGVfZm9yX2NvdW50cmllc19zaG93IjtzOjE6IjAiO3M6MjM6ImhpZGVfZm9yX2xhbmd1YWdlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfc2VhcmNoX2VuZ2luZXNfc2hvdyI7czoxOiIwIjtzOjE4OiJoaWRlX3ByZWdfdXJsX3Nob3ciO3M6MToiMCI7czoxMzoiaGlkZV9wcmVnX3VybCI7czowOiIiO3M6MjQ6ImhpZGVfZm9yX3VzZXJfcm9sZXNfc2hvdyI7czoxOiIwIjt9czozOiJ0cGwiO2E6MTE0OntzOjU6IndpZHRoIjtzOjM6IjgwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czoxNToiYmdfb3ZlcmxheV90eXBlIjtzOjU6ImNvbG9yIjtzOjE2OiJiZ19vdmVybGF5X2NvbG9yIjtzOjQ6IiMwMDAiO3M6MTQ6ImJnX292ZXJsYXlfaW1nIjtzOjA6IiI7czoxODoiYmdfb3ZlcmxheV9pbWdfcG9zIjtzOjc6InN0cmV0Y2giO3M6OToiYmdfdHlwZV8wIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18wIjtzOjQxOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9iYWNrZ3JvdW5kLmpwZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjOTkwYTIyIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czozOToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvYnV0dG9uLTEucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czozNzoiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvZ2lybC0yLnBuZyI7czoxMDoiYmdfY29sb3JfMiI7czowOiIiO3M6OToiYmdfdHlwZV8zIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18zIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjM2QzZDNkIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiI2ZmNDQxMSI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjOTc5Njk2IjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjI3OiJjbG9zZS1ibGFjay1pbi13aGl0ZS1jaXJjbGUiO3M6NzoiYnVsbGV0cyI7czo0OiJ0aWNrIjtzOjE5OiJsYXllcl9yZWxfc2VsZWN0b3JzIjtzOjA6IiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjIyOiJTdWJzY3JpYmUgYW5kIEdldCBOZXdzIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTc6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTQ6InN1Yl9zYl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX3Y2X2FwaV9rZXkiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ191cmwiO3M6MDoiIjtzOjEzOiJzdWJfdnRpZ19uYW1lIjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfa2V5IjtzOjA6IiI7czoxNjoic3ViX3ltbHBfYXBpX2tleSI7czowOiIiO3M6MTM6InN1Yl95bWxwX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9wYXNzIjtzOjA6IiI7czoxNjoic3ViX2Rtc19hcGlfdXNlciI7czowOiIiO3M6MjA6InN1Yl9kbXNfYXBpX3Bhc3N3b3JkIjtzOjA6IiI7czoxMzoic3ViX2Rtc19vcHRpbiI7czo3OiJVbmtub3duIjtzOjEwOiJzdWJfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO3M6MTA6InNldF9wcmVzZXQiO3M6MDoiIjt9czo1OiJlbWFpbCI7YTo4OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MTA6InNldF9wcmVzZXQiO3M6MDoiIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6OToiYmxhY2tsaXN0IjtzOjA6IiI7czoxNToiYmxhY2tsaXN0X2Vycm9yIjtzOjI2OiJZb3VyIGVtYWlsIGlzIGluIGJsYWNrbGlzdCI7czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czoyOiJHbyI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfc3ViamVjdCI7czo0MDoiTmV3IFN1YnNjcmliZXIgb24gTXkgV29yZFByZXNzIFRlc3QgU2l0ZSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6NToiTG9naW4iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJyZWdfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToicmVnX3R4dF9zdWNjZXNzIjtzOjI3OiJUaGFuayB5b3UgZm9yIHJlZ2lzdHJhdGlvbiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gcmVnaXN0cmF0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NjoiWW91IHJlZ2lzdGVyZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgcmVnaXN0cmF0aW9uLiBJZiB5b3UgZGlkIG5vdCByZWdpc3RlciBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjEzOiJyZWdfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToicmVnX25ld19tZXNzYWdlIjtzOjEyMToiWW91IGhhdmUgbmV3IG1lbWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIG1lbWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxMjoic3RhdF9nYV9jb2RlIjtzOjA6IiI7czo1OiJ0eHRfMCI7czoxNzM6IjxwPlBvcHVwIGJ5IFN1cHN5c3RpYyBsZXRzIHlvdSBlYXNpbHkgY3JlYXRlIGVsZWdhbnQgb3ZlcmxhcHBpbmcgd2luZG93cyB3aXRoIHVubGltaXRlZCBmZWF0dXJlcy4gUG9wLXVwcyB3aXRoIFNsaWRlciwgTGlnaHRib3gsIENvbnRhY3QgYW5kIFN1YnNjcmlwdGlvbiBmb3JtcyBhbmQgbW9yZS48L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link href=\"https://fonts.googleapis.com/css?family=Montserrat\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupListsInner\">\r\n <div class=\"ppsPopupTblCols\">\r\n [if bg_type_2 == \'img\']\r\n <div class=\"ppsPopupLeftCol\">\r\n <img src=\"[bg_img_2]\" class=\"ppsLogo\" />\r\n </div>\r\n [endif]\r\n <div class=\"ppsPopupRightCol\">\r\n <div class=\"ppsBigArrow\"></div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupTxt_0\">[txt_0]</div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Montserrat\",Helvetica,Arial,sans-serif;\r\n font-size: 14px;\r\n [if bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [elseif bg_type_0 == \'color\']\r\n background: [bg_color_0];\r\nbackground: -moz-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: -webkit-gradient(left top, right top, color-stop(0%, [bg_color_0]), color-stop(31%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }}), color-stop(56%, rgba(201,3,49,1)), color-stop(67%, rgba(201,3,49,1)));\r\nbackground: -webkit-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: -o-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: -ms-linear-gradient(left, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nbackground: linear-gradient(to right, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }} 31%, rgba(201,3,49,1) 56%, rgba(201,3,49,1) 67%);\r\nfilter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'[bg_color_0]\', endColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 80) }}\', GradientType=1 );\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #fff;\r\n font-size: 31px;\r\n line-height: 1.2;\r\n text-align: center;\r\n margin-bottom: 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupListsInner {\r\n [if bg_type_0 == \'color\']\r\n background: {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}; /* Old browsers */\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* FF3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%,[bg_color_0])); /* Chrome,Safari4+ */\r\n background: -webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Chrome10+,Safari5.1+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Opera 12+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* IE10+ */\r\n background: radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* W3C */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'#eaeaea\',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 .ppsTxtContent {\r\n padding: 10px 10px 10px 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n font-size: 12px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTblCols {\r\n display: table;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLeftCol {\r\n display: table-cell;\r\n padding: 0;\r\n [if enb_subscribe]\r\n width: 40%;\r\n [else]\r\n width: 30%;\r\n min-height: 60%;\r\n [endif]\r\n vertical-align: top;\r\n}\r\n#ppsPopupShell_[ID] .ppsLogo {\r\n width: auto;\r\n height: auto;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupRightCol {\r\n color: #fff;\r\n width: 60%;\r\n display: table-cell;\r\n padding: 50px 40px 20px;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 50px 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 35px;\r\n border-radius: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=password],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n background: [bg_color_1];\r\n border: 1px solid transparent;\r\n color: #000;\r\n padding-left: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n margin-left: -15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding: 20px 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: 1px solid #fff;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n border-radius: 0;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n right: -20px !important;\r\n top: -10px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n [if enb_subscribe]\r\n color: #979696;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [else]\r\n margin-top: 10px;\r\n color: #979696;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n [if enb_subscribe]\r\n [else]\r\n margin-top: 130px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] li{\r\n font-weight: bold;\r\n font-size: 13px;\r\n padding-top: 3px;\r\n padding-bottom: 3px;\r\n color: #737E86;\r\n}","girl-2.jpg","1","1","1","1","2015-01-13 19:22:48","1"),
|
549 |
("42","Sign Up Classic","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoxMDoic2hvd19wYWdlcyI7czozOiJhbGwiO3M6MTQ6InNob3dfdGltZV9mcm9tIjtzOjc6IjEyOjAwYW0iO3M6MTI6InNob3dfdGltZV90byI7czo3OiIxMjowMGFtIjtzOjE0OiJzaG93X2RhdGVfZnJvbSI7czowOiIiO3M6MTI6InNob3dfZGF0ZV90byI7czowOiIiO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoxNToiY291bnRfdGltZXNfbnVtIjtzOjE6IjEiO3M6MTU6ImNvdW50X3RpbWVzX21lcyI7czozOiJkYXkiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9zZWFyY2hfZW5naW5lc19zaG93IjtzOjE6IjAiO3M6MTg6ImhpZGVfcHJlZ191cmxfc2hvdyI7czoxOiIwIjtzOjEzOiJoaWRlX3ByZWdfdXJsIjtzOjA6IiI7czoyNDoiaGlkZV9mb3JfdXNlcl9yb2xlc19zaG93IjtzOjE6IjAiO31zOjM6InRwbCI7YTo1NTp7czo1OiJ3aWR0aCI7czozOiI0MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMCI7czo0OToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvc2lnbi11cC1jbGFzc2ljLWJnLnBuZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjYzlhZTk0IjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiIzljODU3MCI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiNmZmZmZmYiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiI2Y5ZTZjZSI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzU4NTg1OCI7czoxNzoicmVpZHJlY3Rfb25fY2xvc2UiO3M6MDoiIjtzOjk6ImNsb3NlX2J0biI7czoxMToid2hpbGVfY2xvc2UiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjA6IiI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czozMToiU2lnbiBVcDxiciAvPlRvIE91ciBOZXdzbGV0dGVyISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo3OiJTSUdOIFVQIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19zdWJqZWN0IjtzOjQwOiJOZXcgU3Vic2NyaWJlciBvbiBNeSBXb3JkUHJlc3MgVGVzdCBTaXRlIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6MTI6InN0YXRfZ2FfY29kZSI7czowOiIiO3M6NToidHh0XzAiO3M6MTcyOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmU8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIyIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link href=\"https://fonts.googleapis.com/css?family=Dancing+Script|Gloria+Hallelujah|Hind|Pacifico|Satisfy\" rel=\"stylesheet\"> \r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \"Hind\",\"arial\",arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #4d4d4d;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n width: 100%;\r\n display: table-cell;\r\n padding: 40px;\r\n [if bg_type_0 == \'color\']\r\n background-color: [bg_color_0];\r\n background-image: none;\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-family: \"Dancing Script\", arial;\r\n font-size: 40px;\r\n line-height: 40px;\r\n font-weight: bold;\r\n margin-bottom: 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n margin-bottom: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 0;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 10px;\r\n \r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -4px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n background-image: none;\r\n border: 1px solid #fff;\r\n box-shadow: 0 0 0 4px [bg_color_1];\r\n width: calc(100% - 8px);\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n border-width: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n width: 100%;\r\n font-size: 14px;\r\n margin-bottom: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n right: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm {\r\n margin-top:20px;\r\n}","sign-up-classic.jpg","1","1","1","1","2015-01-10 18:59:43","1")');
|
550 |
}
|
551 |
if(!dbPps::exist('@__popup', 'id', '43')) {
|
555 |
("45","XMas Sale","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMzoib3ZlcmxheV9jbGljayI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjExMTp7czo1OiJ3aWR0aCI7czozOiI2NzUiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjUyOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8yMDE2LXEzNTkteG1hc19yaWJib24ucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8yIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18yIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMiI7czo3OiIjYWVkMWRlIjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiI2Y0MTMwZiI7czo5OiJiZ190eXBlXzQiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzQiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl80IjtzOjc6IiNmZmZmZmYiO3M6MTA6ImZvbnRfbGFiZWwiO3M6MTA6IkFsZXggQnJ1c2giO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiI2ZmZmZmZiI7czoxMDoiZm9udF90eHRfMCI7czoxMjoiSm9zZWZpbiBTYW5zIjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjZmZmZmZmIjtzOjExOiJmb250X2Zvb3RlciI7czoxMjoiSm9zZWZpbiBTYW5zIjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjNGY0ZjRmIjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjQ6Im5vbmUiO3M6NzoiYnVsbGV0cyI7czo4OiJwb3BfaWNvbiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjU6ImxhYmVsIjtzOjE1OiJDaHJpc3RtYXMgUGFydHkiO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjExODoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6ODoiYW5pbV9rZXkiO3M6MTA6InNsaWRlX2Rvd24iO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MjU6InN1Yl9tYWlsY2hpbXBfZ3JvdXBzX2Z1bGwiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTY6InN1Yl9ncl9jeWNsZV9kYXkiO3M6MToiMCI7czoxMzoic3ViX2ljX2FwcF9pZCI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfdXNlciI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfcGFzcyI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMzoic3ViX3NmX2FwcF9pZCI7czowOiIiO3M6MTQ6InN1Yl9ja19hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX21lbV9hY2NfaWQiO3M6MDoiIjtzOjE1OiJzdWJfbWVtX3B1ZF9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfbWVtX3ByaXZfa2V5IjtzOjA6IiI7czoxNDoic3ViX3NiX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfdjZfYXBpX2tleSI7czowOiIiO3M6MTI6InN1Yl92dGlnX3VybCI7czowOiIiO3M6MTM6InN1Yl92dGlnX25hbWUiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ19rZXkiO3M6MDoiIjtzOjE2OiJzdWJfeW1scF9hcGlfa2V5IjtzOjA6IiI7czoxMzoic3ViX3ltbHBfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9uYW1lIjtzOjA6IiI7czoxMToic3ViXzRkX3Bhc3MiO3M6MDoiIjtzOjEwOiJzdWJfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo2OntzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoyMDoic3ViX3R4dF9leGlzdHNfZW1haWwiO3M6MjM6IkVtcHR5ICBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czoxNzoiR0VUIFlPVVIgRElTQ09VTlQiO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJzdWJfbmV3X3N1YmplY3QiO3M6Mjk6Ik5ldyBzdWJzY3JpYmVyIGZvciBbc2l0ZW5hbWVdIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIGlzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6ODoibG9naW5fYnkiO3M6ODoidXNlcm5hbWUiO3M6MTg6ImxvZ2luX3JlZGlyZWN0X3VybCI7czowOiIiO3M6MTU6ImxvZ2luX2J0bl9sYWJlbCI7czoxMDoi0JvQvtCz0LjQvSI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiLQmNC80Y8iO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6MTk1OiLQodGB0YvQu9C60LAg0LTQu9GPINC/0L7QtNGC0LLQtdGA0LbQtNC10L3QuNGPINCx0YvQuyDQvtGC0L/RgNCw0LLQu9C10L3QsCDQvdCwINCy0LDRiCDQsNC00YDQtdGBINGN0LvQtdC60YLRgNC+0L3QvdC+0Lkg0L/QvtGH0YLRiy4g0J/RgNC+0LLQtdGA0YzRgtC1INCy0LDRiNGDINGN0LvQtdC60YLRgNC+0L3QvdGD0Y4g0L/QvtGH0YLRgyEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czo0Mzoi0KHQv9Cw0YHQuNCx0L4g0LfQsCDRgNC10LPQuNGB0YLRgNCw0YbQuNGOISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjU4OiLQn9GD0YHRgtC+0Lkg0LjQu9C4INC90LXQtNC10LnRgdGC0LLQuNGC0LXQu9GM0L3Ri9C5IGVtYWlsIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czo2MToi0J/QvtC00YLQstC10YDQtNC40YLQtSDRgNC10LPQuNGB0YLRgNCw0YbQuNGOINC90LAgW3NpdGVuYW1lXSI7czoyNToicmVnX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MzM0OiLQktGLINC30LDRgNC10LPQuNGB0YLRgNC40YDQvtCy0LDQvdGLINC90LAg0YHQsNC50YLQtSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uINCh0LvQtdC00YPQudGC0LUgIDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4g0LTQu9GPINC30LDQstC10YDRiNC10L3QuNGPINGA0LXQs9C40YHRgtGA0LDRhtC40LguINCV0YHQu9C4INCy0Ysg0L3QtSDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0LvQuNGB0Ywg0LfQtNC10YHRjCAtINC/0YDQvtGB0YLQviDQuNCz0L3QvtGA0LjRgNGD0LnRgtC1INGN0YLQviDRgdC+0L7QsdGJ0LXQvdC40LUuIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjQ1OiJbc2l0ZW5hbWVdICDQktCw0Ygg0LvQvtCz0LjQvSDQuCDQv9Cw0YDQvtC70YwiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjcxOiLQm9C+0LPQuNC9OiBbdXNlcl9sb2dpbl08YnIgLz7Qn9Cw0YDQvtC70Yw6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxNzc6ItCjINCy0LDRgSDQvdC+0LLRi9C5INC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjCDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCDQstC+0YIg0LjQvdGE0L7RgNC80LDRhtC40Y8g0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GPOiA8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxMjoiY29udGFjdF9mb3JtIjtzOjI6IjIwIjtzOjEyOiJzdGF0X2dhX2NvZGUiO3M6MDoiIjtzOjU6InR4dF8wIjtzOjcxOiI8cD5XZSBoYXZlIHNvbWV0aGluZyBmb3IgRVZFUllPTkUgb24gWU9VUiBsaXN0LiBTYXZlIFVwIHRvIDcwJSBPRkYhPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNSI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link href=\"https://fonts.googleapis.com/css?family=Oxygen\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsTopBgWrapper\">\r\n <div class=\"ppsWrapImgWr\">\r\n [if bg_type_1 == \"img\"]\r\n <img src=\"[bg_img_1]\" class=\"ppsImgWr\"/>\r\n [endif]\r\n </div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div class=\"ppsSnow\"></div>\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n \r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n <div class=\"\"></div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Oxygen\";\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background-color: [bg_color_0];\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0 0 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n\r\n}\r\n\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n \r\n color: #4f4f4f;\r\n text-align: center;\r\n border: 2px solid #aaa;\r\n font-family: \"Oxygen\";\r\n font-size: 16px;\r\n font-weight: normal;\r\n width: 100%;\r\n display:block;\r\n margin-top: 10px;\r\n height: 45px;\r\n \r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n [if bg_type_4 == \"color\"]\r\n background: [bg_color_4];\r\n [elseif bg_type_4 == \"img\"]\r\n background-image: url(\"[bg_img_4]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n height: auto;\r\n padding-top: 9px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display:inline-block;\r\n margin-top: 0px\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n margin-top: 10px;\r\n font-size: 16px;\r\n color: #4f4f4f;\r\n text-align: center;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n display:block;\r\n height: 45px;\r\n color: #fff;\r\n font-size: 18px;\r\n width: 100%;\r\n margin: 10px 0;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n border: 0 solid transparent;\r\n cursor: pointer;\r\n text-transform: none;\r\n padding: 0;\r\n font-weight: 700;\r\n font-family: \"Oxygen\";\r\n [if bg_type_3 == \"color\"]\r\n background: [bg_color_3];\r\n [elseif bg_type_3 == \"img\"]\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n display: inline-block;\r\n margin: 40px 0 0;\r\n width: 40%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopBgWrapper {\r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n padding: 30px 0;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapImgWr {\r\n display: inline-block;\r\n text-align: center;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsImgWr {\r\n display: inline-block;\r\n max-width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 50px;\r\n font-family: \"Oxygen\";\r\n position: relative;\r\n z-index: 100;\r\n width: 90%;\r\n display: inline-block;\r\n padding-top: 30px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n font-family: \"Oxygen\";\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n font-size: 20px;\r\n padding-top: 30px;\r\n font-weight: bold;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n display: inline-block;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n color: #4f4f4f;\r\n margin: 5px 0px;\r\n text-align: center;\r\n width: 80%;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}","x-mas-sale.png","1","1","1","11","2015-01-10 18:59:43","45"),
|
556 |
("46","Merry Christmas","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMzoib3ZlcmxheV9jbGljayI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjEwNDp7czo1OiJ3aWR0aCI7czozOiI3MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czozOiJpbWciO3M6ODoiYmdfaW1nXzAiO3M6NDY6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzLzIwMTZfMzYwX255dF9iZy5wbmciO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjUxOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8yMDE2XzM2MF9ueXRfdG9wX2ltZy5wbmciO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzIiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzIiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiMxMzMxNmMiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmOWU2Y2UiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6NDoibm9uZSI7czo3OiJidWxsZXRzIjtzOjExOiJsaXN0c19ncmVlbiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjU6ImxhYmVsIjtzOjA6IiI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTQ6InN1Yl9zYl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX3Y2X2FwaV9rZXkiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ191cmwiO3M6MDoiIjtzOjEzOiJzdWJfdnRpZ19uYW1lIjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfa2V5IjtzOjA6IiI7czoxNjoic3ViX3ltbHBfYXBpX2tleSI7czowOiIiO3M6MTM6InN1Yl95bWxwX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9wYXNzIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6MTE6IllvdXIgZS1tYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fXM6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6OToiWW91ciBuYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoyMDoic3ViX3R4dF9leGlzdHNfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjE1OiJKb2luIHJpZ2h0IG5vdyEiO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJzdWJfbmV3X3N1YmplY3QiO3M6Mjk6Ik5ldyBTdWJzY3JpYmVyIG9uICBbc2l0ZW5hbWVdIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6ODoibG9naW5fYnkiO3M6ODoidXNlcm5hbWUiO3M6MTg6ImxvZ2luX3JlZGlyZWN0X3VybCI7czowOiIiO3M6MTU6ImxvZ2luX2J0bl9sYWJlbCI7czoxMDoi0JvQvtCz0LjQvSI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiLQmNC80Y8iO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6MTk1OiLQodGB0YvQu9C60LAg0LTQu9GPINC/0L7QtNGC0LLQtdGA0LbQtNC10L3QuNGPINCx0YvQuyDQvtGC0L/RgNCw0LLQu9C10L3QsCDQvdCwINCy0LDRiCDQsNC00YDQtdGBINGN0LvQtdC60YLRgNC+0L3QvdC+0Lkg0L/QvtGH0YLRiy4g0J/RgNC+0LLQtdGA0YzRgtC1INCy0LDRiNGDINGN0LvQtdC60YLRgNC+0L3QvdGD0Y4g0L/QvtGH0YLRgyEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czo0Mzoi0KHQv9Cw0YHQuNCx0L4g0LfQsCDRgNC10LPQuNGB0YLRgNCw0YbQuNGOISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjU4OiLQn9GD0YHRgtC+0Lkg0LjQu9C4INC90LXQtNC10LnRgdGC0LLQuNGC0LXQu9GM0L3Ri9C5IGVtYWlsIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czo2MToi0J/QvtC00YLQstC10YDQtNC40YLQtSDRgNC10LPQuNGB0YLRgNCw0YbQuNGOINC90LAgW3NpdGVuYW1lXSI7czoyNToicmVnX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MzM0OiLQktGLINC30LDRgNC10LPQuNGB0YLRgNC40YDQvtCy0LDQvdGLINC90LAg0YHQsNC50YLQtSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uINCh0LvQtdC00YPQudGC0LUgIDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4g0LTQu9GPINC30LDQstC10YDRiNC10L3QuNGPINGA0LXQs9C40YHRgtGA0LDRhtC40LguINCV0YHQu9C4INCy0Ysg0L3QtSDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0LvQuNGB0Ywg0LfQtNC10YHRjCAtINC/0YDQvtGB0YLQviDQuNCz0L3QvtGA0LjRgNGD0LnRgtC1INGN0YLQviDRgdC+0L7QsdGJ0LXQvdC40LUuIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjQ1OiJbc2l0ZW5hbWVdICDQktCw0Ygg0LvQvtCz0LjQvSDQuCDQv9Cw0YDQvtC70YwiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjcxOiLQm9C+0LPQuNC9OiBbdXNlcl9sb2dpbl08YnIgLz7Qn9Cw0YDQvtC70Yw6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxNzc6ItCjINCy0LDRgSDQvdC+0LLRi9C5INC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjCDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCDQstC+0YIg0LjQvdGE0L7RgNC80LDRhtC40Y8g0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GPOiA8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxMjoiY29udGFjdF9mb3JtIjtzOjI6IjIwIjtzOjEyOiJzdGF0X2dhX2NvZGUiO3M6MDoiIjtzOjU6InR4dF8wIjtzOjA6IiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiMyI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link href=\"https://fonts.googleapis.com/css?family=Gentium+Basic\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsWrapTopImg\">\r\n [if bg_type_1 == \"img\"]\r\n <img src=\"[bg_img_1]\" class=\"ppsTopImg\"/>\r\n [endif]\r\n </div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsBottomCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Gentium Basic\", arial;\r\n font-size: 13px;\r\n font-weight: normal;\r\n color: #000;\r\n text-align: center;\r\n}\r\n\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n width: 100%;\r\n padding: 40px;\r\n [if bg_type_0 == \"color\"]\r\n background-color: [bg_color_0];\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapTopImg {\r\n display: inline-block;\r\n text-align: center;\r\n width: 100%;\r\n margin-bottom: 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopImg {\r\n display: inline-block;\r\n max-width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n min-height: 200px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n width: 60%;\r\n display: inline-block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=password],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: \"Gentium Basic\", arial;\r\n font-size: 17px;\r\n font-weight: normal;\r\n border: 1px solid transparent;\r\n width: 100%;\r\n display: block;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n height: 41px;\r\n margin: 10px 0 0;\r\n text-transform: none;\r\n \r\n padding-left: 15px;\r\n background-image: none;\r\n background-repeat: no-repeat;\r\n background-color: #fff;\r\n color: #13316c;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n margin: 0;\r\n min-height: 41px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n font-family: \"Gentium Basic\", arial;\r\n font-size: 17px;\r\n font-weight: normal;\r\n display: block;\r\n margin: 10px 0 0;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n height: auto;\r\n padding-top: 9px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text], \r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n padding-left: 35px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/user-black-icon.png\");\r\n background-position: 12px center;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/email-black-icon.png\");\r\n background-position: 10px center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n background: -moz-linear-gradient(top, {{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }} 26%, [bg_color_2] 100%);\r\n background: -webkit-linear-gradient(top, {{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }} 26%,[bg_color_2] 100%);\r\n background: linear-gradient(to bottom, {{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }} 26%,[bg_color_2] 100%);\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_2, 75) }}\", endColorstr=\"[bg_color_2]\",GradientType=0 );\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n height: 41px;\r\n text-transform: none;\r\n margin: 10px 0 0;\r\n -webkit-box-shadow: 2px 2px 6px 2px rgba(0, 0, 0, 0.75);\r\n -moz-box-shadow: 2px 2px 6px 2px rgba(0, 0, 0, 0.75);\r\n box-shadow: 2px 2px 6px 2px rgba(0, 0, 0, 0.75);\r\n padding: 0;\r\n cursor: pointer;\r\n color: #fff;\r\n font-size: 20px;\r\n font-family: \"Gentium Basic\", arial;\r\n font-weight: normal;\r\n border: 1px solid transparent;\r\n width: 100%;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n -webkit-box-shadow: 2px 2px 7px 2px rgba(0, 0, 0, 0.75);\r\n -moz-box-shadow: 2px 2px 7px 2px rgba(0, 0, 0, 0.75);\r\n box-shadow: 2px 2px 7px 2px rgba(0, 0, 0, 0.75);\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 40px;\r\n line-height: 40px;\r\n font-weight: bold;\r\n margin: 0 30px 30px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n width: 100%;\r\n font-size: 14px;\r\n margin: 0 30px 20px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n right: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n color: #585858;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm {\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg {\r\n margin: 0px;\r\n}","merry-christmas.png","1","1","1","11","2015-01-10 18:59:43","46"),
|
557 |
("47","Christmas Recipes","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMzoib3ZlcmxheV9jbGljayI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjExNzp7czo1OiJ3aWR0aCI7czozOiI0MzgiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjM5OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8zNjUtMS1iZy5wbmciO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzIiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzIiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiMwMjAxMDEiO3M6OToiYmdfdHlwZV8zIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18zIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjZmZiMmIyIjtzOjEwOiJmb250X2xhYmVsIjtzOjEwOiJBbGV4IEJydXNoIjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiNmZmZmZmYiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czoxMDoiZm9udF90eHRfMSI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMSI7czo3OiIjRkZCMkIyIjtzOjEwOiJmb250X3R4dF8yIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8yIjtzOjc6IiMzMzMzMzMiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiNiN2I3YjciO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6NDoibm9uZSI7czo3OiJidWxsZXRzIjtzOjg6InBvcF9pY29uIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6NToibGFiZWwiO3M6MTU6IkNocmlzdG1hcyBQYXJ0eSI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJlbmJfdHh0XzEiO3M6MToiMSI7czo5OiJlbmJfdHh0XzIiO3M6MToiMSI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMzoiTk8sIFRIQU5LIFlPVSI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6ODoiYW5pbV9rZXkiO3M6NDoibm9uZSI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoyNToic3ViX21haWxjaGltcF9ncm91cHNfZnVsbCI7czowOiIiO3M6MTQ6InN1Yl9ncl9hcGlfa2V5IjtzOjA6IiI7czoxNjoic3ViX2dyX2N5Y2xlX2RheSI7czoxOiIwIjtzOjEzOiJzdWJfaWNfYXBwX2lkIjtzOjA6IiI7czoxNToic3ViX2ljX2FwcF91c2VyIjtzOjA6IiI7czoxNToic3ViX2ljX2FwcF9wYXNzIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV91cmwiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX2tleSI7czowOiIiO3M6MTg6InN1Yl9hcl9mb3JtX2FjdGlvbiI7czowOiIiO3M6MTA6InN1Yl9zZ2FfaWQiO3M6MDoiIjtzOjE1OiJzdWJfc2dhX2xpc3RfaWQiO3M6MDoiIjtzOjIxOiJzdWJfc2dhX2FjdGl2YXRlX2NvZGUiO3M6MDoiIjtzOjEzOiJzdWJfc2ZfYXBwX2lkIjtzOjA6IiI7czoxNDoic3ViX2NrX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfbWVtX2FjY19pZCI7czowOiIiO3M6MTU6InN1Yl9tZW1fcHVkX2tleSI7czowOiIiO3M6MTY6InN1Yl9tZW1fcHJpdl9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfc2JfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl92Nl9hcGlfa2V5IjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfdXJsIjtzOjA6IiI7czoxMzoic3ViX3Z0aWdfbmFtZSI7czowOiIiO3M6MTI6InN1Yl92dGlnX2tleSI7czowOiIiO3M6MTY6InN1Yl95bWxwX2FwaV9rZXkiO3M6MDoiIjtzOjEzOiJzdWJfeW1scF9uYW1lIjtzOjA6IiI7czoxMToic3ViXzRkX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfcGFzcyI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjY6e3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjIwOiJzdWJfdHh0X2V4aXN0c19lbWFpbCI7czoyMzoiRW1wdHkgIG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjg6IkRPV05MT0FEIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19zdWJqZWN0IjtzOjI5OiJOZXcgc3Vic2NyaWJlciBmb3IgW3NpdGVuYW1lXSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6MTA6ItCb0L7Qs9C40L0iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6Njoi0JjQvNGPIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjE5NToi0KHRgdGL0LvQutCwINC00LvRjyDQv9C+0LTRgtCy0LXRgNC20LTQtdC90LjRjyDQsdGL0Lsg0L7RgtC/0YDQsNCy0LvQtdC90LAg0L3QsCDQstCw0Ygg0LDQtNGA0LXRgSDRjdC70LXQutGC0YDQvtC90L3QvtC5INC/0L7Rh9GC0YsuINCf0YDQvtCy0LXRgNGM0YLQtSDQstCw0YjRgyDRjdC70LXQutGC0YDQvtC90L3Rg9GOINC/0L7Rh9GC0YMhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6NDM6ItCh0L/QsNGB0LjQsdC+INC30LAg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czo1ODoi0J/Rg9GB0YLQvtC5INC40LvQuCDQvdC10LTQtdC50YHRgtCy0LjRgtC10LvRjNC90YvQuSBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6NjE6ItCf0L7QtNGC0LLQtdGA0LTQuNGC0LUg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiDQvdCwIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjMzNDoi0JLRiyDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0L3RiyDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiDQodC70LXQtNGD0LnRgtC1ICA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+INC00LvRjyDQt9Cw0LLQtdGA0YjQtdC90LjRjyDRgNC10LPQuNGB0YLRgNCw0YbQuNC4LiDQldGB0LvQuCDQstGLINC90LUg0LfQsNGA0LXQs9C40YHRgtGA0LjRgNC+0LLQsNC70LjRgdGMINC30LTQtdGB0YwgLSDQv9GA0L7RgdGC0L4g0LjQs9C90L7RgNC40YDRg9C50YLQtSDRjdGC0L4g0YHQvtC+0LHRidC10L3QuNC1LiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czo0NToiW3NpdGVuYW1lXSAg0JLQsNGIINC70L7Qs9C40L0g0Lgg0L/QsNGA0L7Qu9GMIjtzOjI4OiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo3MToi0JvQvtCz0LjQvTogW3VzZXJfbG9naW5dPGJyIC8+0J/QsNGA0L7Qu9GMOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MTM6InJlZ19uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJyZWdfbmV3X21lc3NhZ2UiO3M6MTc3OiLQoyDQstCw0YEg0L3QvtCy0YvQuSDQv9C+0LvRjNC30L7QstCw0YLQtdC70Ywg0L3QsCDRgdCw0LnRgtC1IDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwg0LLQvtGCINC40L3RhNC+0YDQvNCw0YbQuNGPINC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjzogPGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6MTI6ImNvbnRhY3RfZm9ybSI7czoyOiIyMCI7czoxMjoic3RhdF9nYV9jb2RlIjtzOjA6IiI7czo1OiJ0eHRfMCI7czoxNjoiPHA+RlJFRSBESUVUPC9wPiI7czo1OiJ0eHRfMSI7czoxNjoiPHA+TUVBTCBQTEFOPC9wPiI7czo1OiJ0eHRfMiI7czo0MjoiPHA+TG93LUNhcnAgUmVjaXBlcyBZb3XigJlsbCBGYWxsIEZvciE8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjMiO319","<link href=\"https://fonts.google.com/?query=Open+sans&selection.family=Open+Sans:400,700\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsTopBgWrapper\">\r\n <div class=\"ppsWrapImgWr\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsBtmBgWrapper\">\r\n [if enb_txt_2]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_2 ppsPopupTxt_2\">\r\n [txt_2]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [if enb_foot_note]\r\n <a href=\"#\" class=\"ppsFootNote ppsPopupClose\">\r\n [foot_note]\r\n </a>\r\n [endif]\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n \r\n [endif]\r\n </div>\r\n <div class=\"ppsBtmLine\"></div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: \"Open Sans\", arial;\r\n font-size: 13px;\r\n line-height: normal;\r\n font-weight: normal;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background-color: [bg_color_0];\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0;\r\n}\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n margin: 10px 0 0;\r\n font-size: 16px;\r\n font-family: \"Open Sans\", arial;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n border: 2px solid #ccc;\r\n width: 100%;\r\n display:block;\r\n background: #fff;\r\n color: #4f4f4f;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n font-size: 16px;\r\n font-family: \"Open Sans\", arial;\r\n border: 2px solid #ccc;\r\n display: inline-block;\r\n background: #fff;\r\n color: #4f4f4f;\r\n text-align: center;\r\n height: 45px;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n border-radius: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n color: #333333;\r\n display: block;\r\n margin: 10px 0 0;\r\n font-size: 16px;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n height: 45px;\r\n}\r\n#ppsPopupShell_[ID] input[type=submit] {\r\n font-family: \"Open Sans\", arial;\r\n display:inline-block;\r\n color: #fff;\r\n font-size: 18px;\r\n width: auto;\r\n margin: 10px 0;\r\n -webkit-border-radius: 35px;\r\n -moz-border-radius: 35px;\r\n border-radius: 35px;\r\n border: 0 solid transparent;\r\n cursor: pointer;\r\n text-transform: none;\r\n padding: 13px 88px 7px 60px;\r\n font-weight: 700;\r\n text-shadow: 1px 2px 0px #86B80E;\r\n text-decoration: none;text-decoration: none;\r\n \r\n -webkit-box-shadow: 1px 4px 0 0 rgba(134, 184, 14, 1);\r\n -moz-box-shadow: 1px 4px 0 0 rgba(134, 184, 14, 1);\r\n box-shadow: 1px 4px 0 0 rgba(134, 184, 14, 1);\r\n\r\n background-color: #9cd610;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/365-1-arr-dwn.png\");\r\n background-position: 79% 13px;\r\n background-repeat: no-repeat;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input.butt + a.ppsPopupClose {\r\n display: inline-block !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n display: inline-block;\r\n margin: 20px 0 20px;\r\n width: 60%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopBgWrapper {\r\n [if bg_type_1 == \"color\"]\r\n background: [bg_color_1];\r\n [elseif bg_type_1 == \"img\"]\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n padding: 70px 0 0;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapImgWr {\r\n [if bg_type_2 == \"color\"]\r\n background: {{ hex_to_rgba_str(popup.params.tpl.bg_color_2, 0.5) }};\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n display: inline-block;\r\n min-height: 130px;\r\n padding: 10px 0;\r\n text-align: center;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsImgWr {\r\n display: inline-block;\r\n max-width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-size: 50px;\r\n position: relative;\r\n z-index: 100;\r\n width: 90%;\r\n display: inline-block;\r\n padding-top: 30px;\r\n font-family: \"Open Sans\", arial;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n font-size: 63px;\r\n font-weight: bold;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n color: #ffb2b2;\r\n font-size: 56px;\r\n font-weight: bold;\r\n line-height: 51px;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 {\r\n color: #333333;\r\n font-size: 21px;\r\n font-weight: bold;\r\n font-family: \"Open Sans\", arial;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsBtmBgWrapper {\r\n padding: 20px 0 0;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsBtnOne:hover {\r\n text-decoration: none;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsBtmLine {\r\n height: 5px;\r\n \r\n [if bg_type_3 == \"color\"]\r\n background: {{ hex_to_rgba_str(popup.params.tpl.bg_color_3, 0.5) }} !important;\r\n [elseif bg_type_3 == \"img\"]\r\n background-image: url(\"[bg_img_3]\") !important;\r\n background-repeat: no-repeat !important; \r\n background-size: cover !important;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n z-index: 1000;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n border-bottom: 2px dotted #b7b7b7;\r\n color: #b7b7b7;\r\n display: none !important;\r\n margin: 10px 0;\r\n text-decoration: none; \r\n background: none !important;\r\n font-size: 16px;\r\n height: auto !important;\r\n position: static !important;\r\n width: auto !important;\r\n top: 0 !important;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote:hover {\r\n text-decoration: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}","christmas-1-prev.png","1","1","1","11","2015-01-10 18:59:43","47"),
|
558 |
+
("48","Christmas mood","1","0","YTozOntzOjQ6Im1haW4iO2E6MzE6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czoxNDoidmlzaXRfcGFnZV9jbnQiO3M6MDoiIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI2OiJjbG9zZV9vbl9hZnRlcl9hY3Rpb25fdGltZSI7czoxOiIxIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjE0OiJzaG93X3RpbWVfZnJvbSI7czo3OiIxMjowMGFtIjtzOjEyOiJzaG93X3RpbWVfdG8iO3M6NzoiMTI6MDBhbSI7czoxNDoic2hvd19kYXRlX2Zyb20iO3M6MDoiIjtzOjEyOiJzaG93X2RhdGVfdG8iO3M6MDoiIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MTU6ImNvdW50X3RpbWVzX251bSI7czoxOiIxIjtzOjE1OiJjb3VudF90aW1lc19tZXMiO3M6MzoiZGF5IjtzOjIxOiJoaWRlX2Zvcl9kZXZpY2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9mb3JfcG9zdF90eXBlc19zaG93IjtzOjE6IjAiO3M6MTc6ImhpZGVfZm9yX2lwc19zaG93IjtzOjE6IjAiO3M6MTI6ImhpZGVfZm9yX2lwcyI7czowOiIiO3M6MjM6ImhpZGVfZm9yX2NvdW50cmllc19zaG93IjtzOjE6IjAiO3M6MjM6ImhpZGVfZm9yX2xhbmd1YWdlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfc2VhcmNoX2VuZ2luZXNfc2hvdyI7czoxOiIwIjtzOjE4OiJoaWRlX3ByZWdfdXJsX3Nob3ciO3M6MToiMCI7czoxMzoiaGlkZV9wcmVnX3VybCI7czowOiIiO3M6MjQ6ImhpZGVfZm9yX3VzZXJfcm9sZXNfc2hvdyI7czoxOiIwIjt9czozOiJ0cGwiO2E6MTI1OntzOjU6IndpZHRoIjtzOjM6IjUwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czoxNToiYmdfb3ZlcmxheV90eXBlIjtzOjU6ImNvbG9yIjtzOjE2OiJiZ19vdmVybGF5X2NvbG9yIjtzOjQ6IiMwMDAiO3M6MTQ6ImJnX292ZXJsYXlfaW1nIjtzOjA6IiI7czoxODoiYmdfb3ZlcmxheV9pbWdfcG9zIjtzOjc6InN0cmV0Y2giO3M6OToiYmdfdHlwZV8wIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18wIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjZmZmZmZmIjtzOjk6ImJnX3R5cGVfMSI7czozOiJpbWciO3M6ODoiYmdfaW1nXzEiO3M6NDQ6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzLzM2NS0yLXRvcC1pbWcucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8yIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18yIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMiI7czo3OiIjZjRmNGY0IjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiI2VmMjgyMSI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiMzMzMzMzMiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiI2YyMzYyZCI7czoxMDoiZm9udF90eHRfMSI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMSI7czo3OiIjMzMzMzMzIjtzOjEwOiJmb250X3R4dF8yIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8yIjtzOjc6IiMzMzMzMzMiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiMwMTY4MjMiO3M6MTU6InJlc3BvbnNpdmVfbW9kZSI7czozOiJkZWYiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6OToicmVkX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6ODoicG9wX2ljb24iO3M6MTk6ImxheWVyX3JlbF9zZWxlY3RvcnMiO3M6MDoiIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MTA6IlNhdmUgdXAgdG8iO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZW5iX3R4dF8xIjtzOjE6IjEiO3M6OToiZW5iX3R4dF8yIjtzOjE6IjEiO3M6MTM6ImVuYl9mb290X25vdGUiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6Mjg6IkNvdW50aW51ZSB3aXRob3V0IDUwJSBjb3Vwb24iO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo0OiJib3h5IjtzOjg6ImFuaW1fa2V5IjtzOjEwOiJzbGlkZV9kb3duIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTQ6InN1Yl9zYl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX3Y2X2FwaV9rZXkiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ191cmwiO3M6MDoiIjtzOjEzOiJzdWJfdnRpZ19uYW1lIjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfa2V5IjtzOjA6IiI7czoxNjoic3ViX3ltbHBfYXBpX2tleSI7czowOiIiO3M6MTM6InN1Yl95bWxwX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9wYXNzIjtzOjA6IiI7czoxNjoic3ViX2Rtc19hcGlfdXNlciI7czowOiIiO3M6MjA6InN1Yl9kbXNfYXBpX3Bhc3N3b3JkIjtzOjA6IiI7czoxMzoic3ViX2Rtc19vcHRpbiI7czo3OiJVbmtub3duIjtzOjEwOiJzdWJfZmllbGRzIjthOjY6e3M6NDoibmFtZSI7YTo3OntzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO3M6MTA6InNldF9wcmVzZXQiO3M6MDoiIjt9czo1OiJlbWFpbCI7YTo4OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjExOiJZb3VyIGUtbWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MTA6InNldF9wcmVzZXQiO3M6MDoiIjtzOjM6ImVuYiI7czoxOiIxIjt9aToxMTthOjg6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czoyOiIxMSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6MjoiMTEiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIxIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjtzOjEwOiJzZXRfcHJlc2V0IjtzOjA6IiI7fWk6MjI7YTo4OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6MjoiMjIiO3M6NDoiaHRtbCI7czo4OiJ0ZXh0YXJlYSI7czo1OiJsYWJlbCI7czoyOiIyMiI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjEiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO3M6MTA6InNldF9wcmVzZXQiO3M6MDoiIjt9aTozMzthOjk6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czoyOiIzMyI7czo0OiJodG1sIjtzOjk6InNlbGVjdGJveCI7czo1OiJsYWJlbCI7czoyOiIzMyI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjEiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO3M6MTA6InNldF9wcmVzZXQiO3M6MDoiIjtzOjc6Im9wdGlvbnMiO2E6Mjp7aTowO2E6Mjp7czo0OiJuYW1lIjtzOjY6ImFzZmFzZiI7czo1OiJsYWJlbCI7czozOiJzYWYiO31pOjE7YToyOntzOjQ6Im5hbWUiO3M6NjoiYXNmYXNmIjtzOjU6ImxhYmVsIjtzOjg6ImFzZmRhc2RmIjt9fX1pOjU1O2E6ODp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjI6IjU1IjtzOjQ6Imh0bWwiO3M6ODoiY2hlY2tib3giO3M6NToibGFiZWwiO3M6MjoiNTUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIxIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjtzOjEwOiJzZXRfcHJlc2V0IjtzOjA6IiI7fX1zOjk6ImJsYWNrbGlzdCI7czowOiIiO3M6MTU6ImJsYWNrbGlzdF9lcnJvciI7czoyNjoiWW91ciBlbWFpbCBpcyBpbiBibGFja2xpc3QiO3M6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjIwOiJzdWJfdHh0X2V4aXN0c19lbWFpbCI7czoyMzoiRW1wdHkgIG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE3OiJzY3JlcHBpQGdtYWlsLmxvYyI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE3OiJzY3JlcHBpQGdtYWlsLmxvYyI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjc6IlNpZ24gVXAiO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTc6InNjcmVwcGlAZ21haWwubG9jIjtzOjE1OiJzdWJfbmV3X3N1YmplY3QiO3M6Mjk6Ik5ldyBzdWJzY3JpYmVyIGZvciBbc2l0ZW5hbWVdIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIGlzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6OToiZW5iX2xvZ2luIjtzOjE6IjEiO3M6ODoibG9naW5fYnkiO3M6ODoidXNlcm5hbWUiO3M6MTg6ImxvZ2luX3JlZGlyZWN0X3VybCI7czowOiIiO3M6MTU6ImxvZ2luX2J0bl9sYWJlbCI7czo1OiJMb2dpbiI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiLQmNC80Y8iO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6MTk1OiLQodGB0YvQu9C60LAg0LTQu9GPINC/0L7QtNGC0LLQtdGA0LbQtNC10L3QuNGPINCx0YvQuyDQvtGC0L/RgNCw0LLQu9C10L3QsCDQvdCwINCy0LDRiCDQsNC00YDQtdGBINGN0LvQtdC60YLRgNC+0L3QvdC+0Lkg0L/QvtGH0YLRiy4g0J/RgNC+0LLQtdGA0YzRgtC1INCy0LDRiNGDINGN0LvQtdC60YLRgNC+0L3QvdGD0Y4g0L/QvtGH0YLRgyEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czo0Mzoi0KHQv9Cw0YHQuNCx0L4g0LfQsCDRgNC10LPQuNGB0YLRgNCw0YbQuNGOISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjU4OiLQn9GD0YHRgtC+0Lkg0LjQu9C4INC90LXQtNC10LnRgdGC0LLQuNGC0LXQu9GM0L3Ri9C5IGVtYWlsIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czo2MToi0J/QvtC00YLQstC10YDQtNC40YLQtSDRgNC10LPQuNGB0YLRgNCw0YbQuNGOINC90LAgW3NpdGVuYW1lXSI7czoyNToicmVnX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNzoic2NyZXBwaUBnbWFpbC5sb2MiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MzM0OiLQktGLINC30LDRgNC10LPQuNGB0YLRgNC40YDQvtCy0LDQvdGLINC90LAg0YHQsNC50YLQtSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uINCh0LvQtdC00YPQudGC0LUgIDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4g0LTQu9GPINC30LDQstC10YDRiNC10L3QuNGPINGA0LXQs9C40YHRgtGA0LDRhtC40LguINCV0YHQu9C4INCy0Ysg0L3QtSDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0LvQuNGB0Ywg0LfQtNC10YHRjCAtINC/0YDQvtGB0YLQviDQuNCz0L3QvtGA0LjRgNGD0LnRgtC1INGN0YLQviDRgdC+0L7QsdGJ0LXQvdC40LUuIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjQ1OiJbc2l0ZW5hbWVdICDQktCw0Ygg0LvQvtCz0LjQvSDQuCDQv9Cw0YDQvtC70YwiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTc6InNjcmVwcGlAZ21haWwubG9jIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjcxOiLQm9C+0LPQuNC9OiBbdXNlcl9sb2dpbl08YnIgLz7Qn9Cw0YDQvtC70Yw6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNzoic2NyZXBwaUBnbWFpbC5sb2MiO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxNzc6ItCjINCy0LDRgSDQvdC+0LLRi9C5INC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjCDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCDQstC+0YIg0LjQvdGE0L7RgNC80LDRhtC40Y8g0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GPOiA8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxMjoic3RhdF9nYV9jb2RlIjtzOjA6IiI7czo1OiJ0eHRfMCI7czoxMzoiPHA+NTAlT0ZGPC9wPiI7czo1OiJ0eHRfMSI7czozNzoiPHA+SW5zdGFudMKgIGFjY2VzcyB0byB0aGUgY291cG9uPC9wPiI7czo1OiJ0eHRfMiI7czoxMTA6IjxwPkJ5IGNsaWNraW5nIFwiU2lnbiBVcFwiIHlvdSBhZ3JlZTxiciAvPiB0byA8YSBjbGFzcz1cInBwc1R4dDNMaW5rXCIgaHJlZj1cIiNcIj5UZXJtcyBhbmQgQ29uZGl0aW9uczwvYT48L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjMiO319","<link href=\"https://fonts.googleapis.com/css?family=Alex+Brush|Josefin+Sans\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsWrapTopImg\">\r\n [if bg_type_1 == \"img\"]\r\n <img src=\"[bg_img_1]\" class=\"ppsTopImg\"/>\r\n [endif]\r\n </div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n <div class=\"ppsTxt1Separator\"></div>\r\n [endif]\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_txt_2]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_2 ppsPopupTxt_2\">\r\n [txt_2]\r\n </div>\r\n [endif]\r\n <div class=\"ppsTxt1Separator\"></div>\r\n [if enb_foot_note]\r\n <a href=\"#\" class=\"ppsFootNote ppsPopupClose\">\r\n [foot_note]\r\n </a>\r\n [endif]\r\n \r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n \r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: arial;\r\n font-size: 13px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\", endColorstr=\"[bg_color_0]\",GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0 0 40px;\r\n [if bg_type_3 == \"color\"]\r\n border: 3px solid [bg_color_3];\r\n [endif]\r\n \r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell{\r\n display: inline-block;\r\n margin: 0;\r\n width: 60%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n margin-top: 0px;\r\n}\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=password],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n -webkit-border-radius: 0px;\r\n -moz-border-radius: 0px;\r\n border-radius: 0px;\r\n border: 1px solid transparent;\r\n height: 47px;\r\n padding: 0;\r\n margin: 10px 0;\r\n display:block;\r\n text-align: center;\r\n color: #016823;\r\n font-weight: normal;\r\n font-size: 18px;\r\n font-family: arial;\r\n \r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n margin: 0px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea { \r\n height: auto;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n display:block;\r\n margin: 10px 0 0;\r\n color: #016823;\r\n font-weight: normal;\r\n font-size: 18px;\r\n font-family: arial;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input::-webkit-input-placeholder { /* Chrome/Opera/Safari */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input::-moz-placeholder { /* Firefox 19+ */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell inpu:-ms-input-placeholder { /* IE 10+ */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input:-moz-placeholder { /* Firefox 18- */\r\n color: #016823;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n \r\n width: 100%;\r\n -webkit-border-radius: 0px;\r\n -moz-border-radius: 0px;\r\n border-radius: 0px;\r\n border: 1px solid transparent;\r\n height: 47px;\r\n padding: 0;\r\n margin: 10px 0;\r\n text-align: center;\r\n font-family: arial;\r\n \r\n color: #fff;\r\n cursor: pointer;\r\n text-transform: none;\r\n font-weight: 700;\r\n font-size: 20px;\r\n display: inline-block;\r\n border: 1px solid transparent;\r\n \r\n background-color: #016823;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/365-2-right-arr.png\");\r\n background-position: 90% center;\r\n background-repeat: no-repeat;\r\n}\r\n#ppsPopupShell_[ID] .ppsWrapTopImg {\r\n display: inline-block;\r\n text-align: center;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsTopImg {\r\n display: inline-block;\r\n max-width: 70%;\r\n}\r\n\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-family: arial;\r\n font-size: 35px;\r\n padding: 20px 20px 0; \r\n text-align: center;\r\n line-height: 45px;\r\n position: relative;\r\n z-index: 100;\r\n color: #333333;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n font-family: arial;\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n color: #f2362d;\r\n font-size: 70px;\r\n font-weight: bold;\r\n line-height: 60px;\r\n margin: 10px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n color: #333333;\r\n font-size: 18px;\r\n padding: 10px 0;\r\n}\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 {\r\n display: block;\r\n font-size: 16px;\r\n margin: 0 auto 15px;\r\n text-align: center;\r\n width: 90%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 a {\r\n color: #f44b44;\r\n text-decoration: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_2 a:hover {\r\n text-decoration: none;\r\n}\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsTxt1Separator {\r\n background-color: #cccccc;\r\n display: block;\r\n height: 1px;\r\n margin: 0 auto;\r\n width: 15%;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n z-index: 1000 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n background: none !important;\r\n border-bottom: 2px solid #016823;\r\n color: #016823;\r\n display: inline-block !important;\r\n font-size: 16px;\r\n height: auto !important;\r\n margin: 10px 0;\r\n position: static !important;\r\n text-decoration: none;\r\n top: 0 !important;\r\n width: auto !important;\r\n \r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}\r\n","christmas-2-prev.png","1","1","1","11","2015-01-10 18:59:43","48"),
|
559 |
("49","Let it Snow","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjEwODp7czo1OiJ3aWR0aCI7czozOiI3MDAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6MTU6ImJnX292ZXJsYXlfdHlwZSI7czo1OiJjb2xvciI7czoxNjoiYmdfb3ZlcmxheV9jb2xvciI7czo0OiIjMDAwIjtzOjE0OiJiZ19vdmVybGF5X2ltZyI7czowOiIiO3M6MTg6ImJnX292ZXJsYXlfaW1nX3BvcyI7czo3OiJzdHJldGNoIjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18xIjtzOjQ0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8zNjUtMy10b3AtaW1nLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjM2QzZDNkIjtzOjk6ImJnX3R5cGVfMiI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMiI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzMiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzMiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8zIjtzOjc6IiNmZmUwMDEiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmZmZmZmYiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiNjYmNiY2IiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6ImNsYXNzeV9ncmV5IjtzOjc6ImJ1bGxldHMiO3M6ODoicG9wX2ljb24iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo1OiJsYWJlbCI7czoxMDoiU2F2ZSB1cCB0byI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czozMjoiTm8sIHRoYW5rIHlvdS4gSeKAmW0gZ29vZCAgdG8gZ28iO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo0OiJib3h5IjtzOjg6ImFuaW1fa2V5IjtzOjEwOiJzbGlkZV9kb3duIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTQ6InN1Yl9zYl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX3Y2X2FwaV9rZXkiO3M6MDoiIjtzOjEyOiJzdWJfdnRpZ191cmwiO3M6MDoiIjtzOjEzOiJzdWJfdnRpZ19uYW1lIjtzOjA6IiI7czoxMjoic3ViX3Z0aWdfa2V5IjtzOjA6IiI7czoxNjoic3ViX3ltbHBfYXBpX2tleSI7czowOiIiO3M6MTM6InN1Yl95bWxwX25hbWUiO3M6MDoiIjtzOjExOiJzdWJfNGRfbmFtZSI7czowOiIiO3M6MTE6InN1Yl80ZF9wYXNzIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Njp7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjExOiJZb3VyIGUtbWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIzOiJFbXB0eSAgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6MzU6IllFUywgSSB3YW50IHRvIGdldCBtb3JlIFN1YnNjcmliZXJzIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19zdWJqZWN0IjtzOjI5OiJOZXcgc3Vic2NyaWJlciBmb3IgW3NpdGVuYW1lXSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6MTA6ItCb0L7Qs9C40L0iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6Njoi0JjQvNGPIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjE5NToi0KHRgdGL0LvQutCwINC00LvRjyDQv9C+0LTRgtCy0LXRgNC20LTQtdC90LjRjyDQsdGL0Lsg0L7RgtC/0YDQsNCy0LvQtdC90LAg0L3QsCDQstCw0Ygg0LDQtNGA0LXRgSDRjdC70LXQutGC0YDQvtC90L3QvtC5INC/0L7Rh9GC0YsuINCf0YDQvtCy0LXRgNGM0YLQtSDQstCw0YjRgyDRjdC70LXQutGC0YDQvtC90L3Rg9GOINC/0L7Rh9GC0YMhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6NDM6ItCh0L/QsNGB0LjQsdC+INC30LAg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czo1ODoi0J/Rg9GB0YLQvtC5INC40LvQuCDQvdC10LTQtdC50YHRgtCy0LjRgtC10LvRjNC90YvQuSBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6NjE6ItCf0L7QtNGC0LLQtdGA0LTQuNGC0LUg0YDQtdCz0LjRgdGC0YDQsNGG0LjRjiDQvdCwIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjMzNDoi0JLRiyDQt9Cw0YDQtdCz0LjRgdGC0YDQuNGA0L7QstCw0L3RiyDQvdCwINGB0LDQudGC0LUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiDQodC70LXQtNGD0LnRgtC1ICA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+INC00LvRjyDQt9Cw0LLQtdGA0YjQtdC90LjRjyDRgNC10LPQuNGB0YLRgNCw0YbQuNC4LiDQldGB0LvQuCDQstGLINC90LUg0LfQsNGA0LXQs9C40YHRgtGA0LjRgNC+0LLQsNC70LjRgdGMINC30LTQtdGB0YwgLSDQv9GA0L7RgdGC0L4g0LjQs9C90L7RgNC40YDRg9C50YLQtSDRjdGC0L4g0YHQvtC+0LHRidC10L3QuNC1LiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czo0NToiW3NpdGVuYW1lXSAg0JLQsNGIINC70L7Qs9C40L0g0Lgg0L/QsNGA0L7Qu9GMIjtzOjI4OiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo3MToi0JvQvtCz0LjQvTogW3VzZXJfbG9naW5dPGJyIC8+0J/QsNGA0L7Qu9GMOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MTM6InJlZ19uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJyZWdfbmV3X21lc3NhZ2UiO3M6MTc3OiLQoyDQstCw0YEg0L3QvtCy0YvQuSDQv9C+0LvRjNC30L7QstCw0YLQtdC70Ywg0L3QsCDRgdCw0LnRgtC1IDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwg0LLQvtGCINC40L3RhNC+0YDQvNCw0YbQuNGPINC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjzogPGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6MTI6InN0YXRfZ2FfY29kZSI7czowOiIiO3M6NToidHh0XzAiO3M6MTIzOiI8cD5EbyBZb3UgV2FudCBUbzxzdHJvbmc+IEluY3JlYXNlPC9zdHJvbmc+IDxiciAvPllvdXIgU3Vic2NyaWJlcnMgPGJyIC8+PHN0cm9uZz5VcCBUbyA3MDAlPC9zdHJvbmc+IDxzdHJvbmc+Pzwvc3Ryb25nPjwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjQiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMSI7fX0=","<link href=\"https://fonts.googleapis.com/css?family=Alex+Brush|Josefin+Sans\" rel=\"stylesheet\">\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"ppsWrapTopImg\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [if enb_foot_note]\r\n <a href=\"#\" class=\"ppsFootNote ppsPopupClose\">\r\n [foot_note]\r\n </a>\r\n [endif]\r\n \r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: arial;\r\n font-size: 13px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n [if bg_type_0 == \"color\"]\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\", endColorstr=\"[bg_color_0]\",GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \"img\"]\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n position: relative;\r\n text-align: center;\r\n padding: 0 0 40px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsWrapTopImg {\r\n [if bg_type_1 == \"color\"]\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\"{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\", endColorstr=\"[bg_color_1]\",GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \"img\"]\r\n background-image: url(\"[bg_img_1]\");\r\n background-position: center bottom;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n min-height: 210px;\r\n padding: 40px 0 85px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell{\r\n display: inline-block;\r\n margin: 0;\r\n position: relative;\r\n z-index: 100;\r\n width: 90%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n position: relative;\r\n padding: 5px 0;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input {\r\n width: 100%;\r\n -webkit-border-radius: 0px;\r\n -moz-border-radius: 0px;\r\n border-radius: 0px;\r\n border: 0 solid transparent;\r\n height: 47px;\r\n padding: 0;\r\n margin: 0;\r\n display:block;\r\n font-family: arial;\r\n text-align: center;\r\n}\r\n\r\n/*For all Elements*/\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=password],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n border: 1px solid #01a2ea;\r\n color: #777777;\r\n font-size: 18px;\r\n font-family: arial;\r\n font-weight: normal;\r\n height: 45px;\r\n padding: 0 20px;\r\n width: 100%;\r\n display:block;\r\n text-align: center;\r\n margin-top: 10px;\r\n \r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n margin-top: 0px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeForm input:first-child {\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label {\r\n font-size: 18px;\r\n font-family: arial;\r\n font-weight: normal;\r\n margin-top: 10px;\r\n display:block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell label span {\r\n display: inline-block;\r\n padding-right: 2px;\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=radio],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=checkbox] {\r\n vertical-align: middle;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n border: 1px solid #01a2ea;\r\n color: #777777;\r\n font-size: 18px;\r\n height: auto;\r\n padding: 20px 20px 50px;\r\n margin-top: 10px;\r\n \r\n [if bg_type_2 == \"color\"]\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \"img\"]\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: 10px solid #fff;\r\n color: #333333;\r\n cursor: pointer;\r\n font-weight: 600;\r\n font-size: 20px;\r\n height: auto;\r\n display: inline-block;\r\n padding: 15px 0 13px;\r\n bottom: 65px;\r\n \r\n -webkit-border-radius: 20px;\r\n -moz-border-radius: 20px;\r\n border-radius: 20px;\r\n position: absolute;\r\n text-transform: none;\r\n left: 5%;\r\n width: 90%;\r\n \r\n [if bg_type_3 == \"color\"]\r\n background: [bg_color_3] !important;\r\n [elseif bg_type_3 == \"img\"]\r\n background-image: url(\"[bg_img_3]\") !important;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]::-webkit-input-placeholder { /* Chrome/Opera/Safari */\r\n color: #999999;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]::-moz-placeholder { /* Firefox 19+ */\r\n color: #999999;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]:-ms-input-placeholder { /* IE 10+ */\r\n color: #999999;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email]:-moz-placeholder { /* Firefox 18- */\r\n color: #999999;\r\n}\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-family: arial;\r\n font-size: 35px;\r\n padding: 20px 20px 0; \r\n text-align: center;\r\n line-height: 45px;\r\n position: relative;\r\n z-index: 100;\r\n color: #fff;\r\n word-wrap: break-word;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n font-family: arial;\r\n margin: 0;\r\n padding: 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt p {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n width: 90%;\r\n position: relative;\r\n z-index: 100;\r\n word-wrap: break-word;\r\n line-height: 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n color: #fff;\r\n font-size: 53px;\r\n line-height: 50px;\r\n margin: 10px 0;\r\n text-shadow: 2px 2px 0 #01a2ea;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] + .ppsFootNote {\r\n display: inline-block !important;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n -webkit-border-radius: 10px;\r\n -moz-border-radius: 10px;\r\n border-radius: 10px;\r\n \r\n background: none !important;\r\n border: 2px solid #cbcbcb;\r\n color: #cbcbcb;\r\n display: none !important;\r\n font-size: 16px;\r\n font-weight: bold;\r\n height: auto !important;\r\n margin: 60px 30px 0;\r\n padding: 5px 20px;\r\n position: static !important;\r\n text-decoration: none;\r\n top: 0 !important;\r\n width: auto !important;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n z-index: 1000 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: center;\r\n}\r\n","christmas-3-prev.png","1","1","1","11","2015-01-10 18:59:43","49")');
|
560 |
}
|
561 |
if(dbPps::get('SELECT COUNT(*) AS total FROM @__popup WHERE id = 5 AND original_id = 0', 'one')) {
|
classes/utils.php
CHANGED
@@ -337,14 +337,16 @@ class utilsPps {
|
|
337 |
add_action('activated_plugin', array(framePps::_(), 'savePluginActivationErrors'));
|
338 |
}
|
339 |
if (function_exists('is_multisite') && is_multisite()) {
|
340 |
-
|
341 |
$blog_id = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
342 |
foreach ($blog_id as $id) {
|
343 |
if (switch_to_blog($id)) {
|
344 |
installerPps::init();
|
|
|
345 |
}
|
346 |
}
|
347 |
-
|
|
|
348 |
return;
|
349 |
} else {
|
350 |
installerPps::init();
|
@@ -359,14 +361,16 @@ class utilsPps {
|
|
359 |
static public function deletePlugin() {
|
360 |
global $wpdb;
|
361 |
if (function_exists('is_multisite') && is_multisite()) {
|
362 |
-
|
363 |
$blog_id = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
364 |
foreach ($blog_id as $id) {
|
365 |
if (switch_to_blog($id)) {
|
366 |
installerPps::delete();
|
|
|
367 |
}
|
368 |
}
|
369 |
-
|
|
|
370 |
return;
|
371 |
} else {
|
372 |
installerPps::delete();
|
@@ -375,14 +379,16 @@ class utilsPps {
|
|
375 |
static public function deactivatePlugin() {
|
376 |
global $wpdb;
|
377 |
if (function_exists('is_multisite') && is_multisite()) {
|
378 |
-
|
379 |
$blog_id = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
380 |
foreach ($blog_id as $id) {
|
381 |
if (switch_to_blog($id)) {
|
382 |
installerPps::deactivate();
|
|
|
383 |
}
|
384 |
}
|
385 |
-
|
|
|
386 |
return;
|
387 |
} else {
|
388 |
installerPps::deactivate();
|
337 |
add_action('activated_plugin', array(framePps::_(), 'savePluginActivationErrors'));
|
338 |
}
|
339 |
if (function_exists('is_multisite') && is_multisite()) {
|
340 |
+
// $orig_id = $wpdb->blogid;
|
341 |
$blog_id = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
342 |
foreach ($blog_id as $id) {
|
343 |
if (switch_to_blog($id)) {
|
344 |
installerPps::init();
|
345 |
+
restore_current_blog();
|
346 |
}
|
347 |
}
|
348 |
+
// restore_current_blog();
|
349 |
+
// switch_to_blog($orig_id);
|
350 |
return;
|
351 |
} else {
|
352 |
installerPps::init();
|
361 |
static public function deletePlugin() {
|
362 |
global $wpdb;
|
363 |
if (function_exists('is_multisite') && is_multisite()) {
|
364 |
+
// $orig_id = $wpdb->blogid;
|
365 |
$blog_id = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
366 |
foreach ($blog_id as $id) {
|
367 |
if (switch_to_blog($id)) {
|
368 |
installerPps::delete();
|
369 |
+
restore_current_blog();
|
370 |
}
|
371 |
}
|
372 |
+
// restore_current_blog();
|
373 |
+
// switch_to_blog($orig_id);
|
374 |
return;
|
375 |
} else {
|
376 |
installerPps::delete();
|
379 |
static public function deactivatePlugin() {
|
380 |
global $wpdb;
|
381 |
if (function_exists('is_multisite') && is_multisite()) {
|
382 |
+
// $orig_id = $wpdb->blogid;
|
383 |
$blog_id = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
384 |
foreach ($blog_id as $id) {
|
385 |
if (switch_to_blog($id)) {
|
386 |
installerPps::deactivate();
|
387 |
+
restore_current_blog();
|
388 |
}
|
389 |
}
|
390 |
+
// restore_current_blog();
|
391 |
+
// switch_to_blog($orig_id);
|
392 |
return;
|
393 |
} else {
|
394 |
installerPps::deactivate();
|
config.php
CHANGED
@@ -48,7 +48,7 @@
|
|
48 |
define('PPS_EOL', "\n");
|
49 |
|
50 |
define('PPS_PLUGIN_INSTALLED', true);
|
51 |
-
define('PPS_VERSION', '1.9.
|
52 |
define('PPS_USER', 'user');
|
53 |
|
54 |
define('PPS_CLASS_PREFIX', 'ppsc');
|
@@ -77,6 +77,10 @@
|
|
77 |
* Plugin name
|
78 |
*/
|
79 |
define('PPS_WP_PLUGIN_NAME', 'PopUp by Supsystic');
|
|
|
|
|
|
|
|
|
80 |
/**
|
81 |
* Custom defined for plugin
|
82 |
*/
|
48 |
define('PPS_EOL', "\n");
|
49 |
|
50 |
define('PPS_PLUGIN_INSTALLED', true);
|
51 |
+
define('PPS_VERSION', '1.9.38');
|
52 |
define('PPS_USER', 'user');
|
53 |
|
54 |
define('PPS_CLASS_PREFIX', 'ppsc');
|
77 |
* Plugin name
|
78 |
*/
|
79 |
define('PPS_WP_PLUGIN_NAME', 'PopUp by Supsystic');
|
80 |
+
/**
|
81 |
+
* Allow minification
|
82 |
+
*/
|
83 |
+
define('PPS_MINIFY_ASSETS', true);
|
84 |
/**
|
85 |
* Custom defined for plugin
|
86 |
*/
|
js/admin.options.js
CHANGED
@@ -9,7 +9,7 @@ jQuery(document).ready(function(){
|
|
9 |
if(typeof(ppsActiveTab) != 'undefined' && ppsActiveTab != 'main_page' && jQuery('#toplevel_page_popup-wp-supsystic').hasClass('wp-has-current-submenu')) {
|
10 |
var subMenus = jQuery('#toplevel_page_popup-wp-supsystic').find('.wp-submenu li');
|
11 |
subMenus.removeClass('current').each(function(){
|
12 |
-
if(jQuery(this).find('a[href$="&tab='+ ppsActiveTab+ '"]').
|
13 |
jQuery(this).addClass('current');
|
14 |
}
|
15 |
});
|
@@ -34,7 +34,7 @@ jQuery(document).ready(function(){
|
|
34 |
}
|
35 |
}, 1000);
|
36 |
|
37 |
-
if(jQuery('.ppsInputsWithDescrForm').
|
38 |
jQuery('.ppsInputsWithDescrForm').find('input[type=checkbox][data-optkey]').change(function(){
|
39 |
var optKey = jQuery(this).data('optkey')
|
40 |
, descShell = jQuery('#ppsFormOptDetails_'+ optKey);
|
@@ -71,7 +71,7 @@ jQuery(document).ready(function(){
|
|
71 |
});
|
72 |
});
|
73 |
// Go to Top button init
|
74 |
-
if(jQuery('#ppsPopupGoToTopBtn').
|
75 |
jQuery('#ppsPopupGoToTopBtn').click(function(){
|
76 |
jQuery('html, body').animate({
|
77 |
scrollTop: 0
|
@@ -89,24 +89,24 @@ jQuery(document).ready(function(){
|
|
89 |
//, animation: 'swing'
|
90 |
, maxWidth: 450
|
91 |
};
|
92 |
-
if(jQuery('.supsystic-tooltip').
|
93 |
tooltipsterSettings.position = 'top-left';
|
94 |
jQuery('.supsystic-tooltip').tooltipster( tooltipsterSettings );
|
95 |
}
|
96 |
-
if(jQuery('.supsystic-tooltip-bottom').
|
97 |
tooltipsterSettings.position = 'bottom-left';
|
98 |
jQuery('.supsystic-tooltip-bottom').tooltipster( tooltipsterSettings );
|
99 |
}
|
100 |
-
if(jQuery('.supsystic-tooltip-left').
|
101 |
tooltipsterSettings.position = 'left';
|
102 |
jQuery('.supsystic-tooltip-left').tooltipster( tooltipsterSettings );
|
103 |
}
|
104 |
-
if(jQuery('.supsystic-tooltip-right').
|
105 |
tooltipsterSettings.position = 'right';
|
106 |
jQuery('.supsystic-tooltip-right').tooltipster( tooltipsterSettings );
|
107 |
}*/
|
108 |
ppsInitTooltips();
|
109 |
-
if(jQuery('.ppsCopyTextCode').
|
110 |
setTimeout(function(){ // Give it some time - wait until all other elements will be initialized
|
111 |
var cloneWidthElement = jQuery('<span class="sup-shortcode" />').appendTo('.supsystic-plugin');
|
112 |
jQuery('.ppsCopyTextCode').attr('readonly', 'readonly').click(function(){
|
@@ -204,7 +204,7 @@ function ppsInitStickyItem() {
|
|
204 |
, docHeight = jQuery(document).height()
|
205 |
, wasSticking = false
|
206 |
, wasUnSticking = false;
|
207 |
-
/*if(jQuery('#wpbody-content .update-nag').
|
208 |
wpTollbarHeight += parseInt(jQuery('#wpbody-content .update-nag').outerHeight());
|
209 |
}*/
|
210 |
for(var i = 0; i < stickiItemsSelectors.length; i++) {
|
@@ -292,10 +292,10 @@ function ppsInitStickyItem() {
|
|
292 |
});
|
293 |
}
|
294 |
if(wasSticking) {
|
295 |
-
if(jQuery('#ppsPopupGoToTop').
|
296 |
jQuery('#ppsPopupGoToTop').show();
|
297 |
} else if(wasUnSticking) {
|
298 |
-
if(jQuery('#ppsPopupGoToTop').
|
299 |
jQuery('#ppsPopupGoToTop').hide();
|
300 |
}
|
301 |
});
|
@@ -318,7 +318,7 @@ function ppsInitCustomCheckRadio(selector) {
|
|
318 |
var checkId = jQuery(this).attr('id');
|
319 |
if(checkId && checkId != '' && strpos(checkId, 'cb_') === 0) {
|
320 |
var parentTblId = str_replace(checkId, 'cb_', '');
|
321 |
-
if(parentTblId && parentTblId != '' && jQuery('#'+ parentTblId).
|
322 |
jQuery('#'+ parentTblId).find('input[type=checkbox]').iCheck('update');
|
323 |
}
|
324 |
}
|
@@ -509,7 +509,7 @@ function ppsInitMainPromoPopup() {
|
|
509 |
}
|
510 |
if(isRadio) {
|
511 |
jQuery('input[name="'+ jQuery(this).attr('name')+ '"]:first').parents('label:first').click();
|
512 |
-
if(jQuery(this).parents('.iradio_minimal:first').
|
513 |
var self = this;
|
514 |
setTimeout(function(){
|
515 |
jQuery(self).parents('.iradio_minimal:first').removeClass('checked');
|
@@ -517,9 +517,9 @@ function ppsInitMainPromoPopup() {
|
|
517 |
}
|
518 |
}
|
519 |
var parent = null;
|
520 |
-
if(jQuery(this).parents('#ppsPopupMainOpts').
|
521 |
parent = jQuery(this).parents('label:first');
|
522 |
-
} else if(jQuery(this).parents('.ppsPopupOptRow:first').
|
523 |
parent = jQuery(this).parents('.ppsPopupOptRow:first');
|
524 |
} else {
|
525 |
parent = jQuery(this).parents('tr:first');
|
9 |
if(typeof(ppsActiveTab) != 'undefined' && ppsActiveTab != 'main_page' && jQuery('#toplevel_page_popup-wp-supsystic').hasClass('wp-has-current-submenu')) {
|
10 |
var subMenus = jQuery('#toplevel_page_popup-wp-supsystic').find('.wp-submenu li');
|
11 |
subMenus.removeClass('current').each(function(){
|
12 |
+
if(jQuery(this).find('a[href$="&tab='+ ppsActiveTab+ '"]').length) {
|
13 |
jQuery(this).addClass('current');
|
14 |
}
|
15 |
});
|
34 |
}
|
35 |
}, 1000);
|
36 |
|
37 |
+
if(jQuery('.ppsInputsWithDescrForm').length) {
|
38 |
jQuery('.ppsInputsWithDescrForm').find('input[type=checkbox][data-optkey]').change(function(){
|
39 |
var optKey = jQuery(this).data('optkey')
|
40 |
, descShell = jQuery('#ppsFormOptDetails_'+ optKey);
|
71 |
});
|
72 |
});
|
73 |
// Go to Top button init
|
74 |
+
if(jQuery('#ppsPopupGoToTopBtn').length) {
|
75 |
jQuery('#ppsPopupGoToTopBtn').click(function(){
|
76 |
jQuery('html, body').animate({
|
77 |
scrollTop: 0
|
89 |
//, animation: 'swing'
|
90 |
, maxWidth: 450
|
91 |
};
|
92 |
+
if(jQuery('.supsystic-tooltip').length) {
|
93 |
tooltipsterSettings.position = 'top-left';
|
94 |
jQuery('.supsystic-tooltip').tooltipster( tooltipsterSettings );
|
95 |
}
|
96 |
+
if(jQuery('.supsystic-tooltip-bottom').length) {
|
97 |
tooltipsterSettings.position = 'bottom-left';
|
98 |
jQuery('.supsystic-tooltip-bottom').tooltipster( tooltipsterSettings );
|
99 |
}
|
100 |
+
if(jQuery('.supsystic-tooltip-left').length) {
|
101 |
tooltipsterSettings.position = 'left';
|
102 |
jQuery('.supsystic-tooltip-left').tooltipster( tooltipsterSettings );
|
103 |
}
|
104 |
+
if(jQuery('.supsystic-tooltip-right').length) {
|
105 |
tooltipsterSettings.position = 'right';
|
106 |
jQuery('.supsystic-tooltip-right').tooltipster( tooltipsterSettings );
|
107 |
}*/
|
108 |
ppsInitTooltips();
|
109 |
+
if(jQuery('.ppsCopyTextCode').length) {
|
110 |
setTimeout(function(){ // Give it some time - wait until all other elements will be initialized
|
111 |
var cloneWidthElement = jQuery('<span class="sup-shortcode" />').appendTo('.supsystic-plugin');
|
112 |
jQuery('.ppsCopyTextCode').attr('readonly', 'readonly').click(function(){
|
204 |
, docHeight = jQuery(document).height()
|
205 |
, wasSticking = false
|
206 |
, wasUnSticking = false;
|
207 |
+
/*if(jQuery('#wpbody-content .update-nag').length) { // Not used for now
|
208 |
wpTollbarHeight += parseInt(jQuery('#wpbody-content .update-nag').outerHeight());
|
209 |
}*/
|
210 |
for(var i = 0; i < stickiItemsSelectors.length; i++) {
|
292 |
});
|
293 |
}
|
294 |
if(wasSticking) {
|
295 |
+
if(jQuery('#ppsPopupGoToTop').length)
|
296 |
jQuery('#ppsPopupGoToTop').show();
|
297 |
} else if(wasUnSticking) {
|
298 |
+
if(jQuery('#ppsPopupGoToTop').length)
|
299 |
jQuery('#ppsPopupGoToTop').hide();
|
300 |
}
|
301 |
});
|
318 |
var checkId = jQuery(this).attr('id');
|
319 |
if(checkId && checkId != '' && strpos(checkId, 'cb_') === 0) {
|
320 |
var parentTblId = str_replace(checkId, 'cb_', '');
|
321 |
+
if(parentTblId && parentTblId != '' && jQuery('#'+ parentTblId).length) {
|
322 |
jQuery('#'+ parentTblId).find('input[type=checkbox]').iCheck('update');
|
323 |
}
|
324 |
}
|
509 |
}
|
510 |
if(isRadio) {
|
511 |
jQuery('input[name="'+ jQuery(this).attr('name')+ '"]:first').parents('label:first').click();
|
512 |
+
if(jQuery(this).parents('.iradio_minimal:first').length) {
|
513 |
var self = this;
|
514 |
setTimeout(function(){
|
515 |
jQuery(self).parents('.iradio_minimal:first').removeClass('checked');
|
517 |
}
|
518 |
}
|
519 |
var parent = null;
|
520 |
+
if(jQuery(this).parents('#ppsPopupMainOpts').length) {
|
521 |
parent = jQuery(this).parents('label:first');
|
522 |
+
} else if(jQuery(this).parents('.ppsPopupOptRow:first').length) {
|
523 |
parent = jQuery(this).parents('.ppsPopupOptRow:first');
|
524 |
} else {
|
525 |
parent = jQuery(this).parents('tr:first');
|
js/common.js
CHANGED
@@ -27,7 +27,7 @@ jQuery.fn.tagName = function() {
|
|
27 |
return this.get(0).tagName;
|
28 |
}
|
29 |
jQuery.fn.exists = function(){
|
30 |
-
return (jQuery(this).
|
31 |
}
|
32 |
function isNumber(val) {
|
33 |
return /^\d+/.test(val);
|
@@ -142,7 +142,7 @@ function toeReload(url) {
|
|
142 |
}
|
143 |
jQuery.fn.toeRebuildSelect = function(data, useIdAsValue, val) {
|
144 |
if(jQuery(this).tagName() == 'SELECT' && typeof(data) == 'object') {
|
145 |
-
if(jQuery(data).
|
146 |
if(typeof(val) == 'undefined')
|
147 |
val = false;
|
148 |
if(jQuery(this).children('option').length) {
|
27 |
return this.get(0).tagName;
|
28 |
}
|
29 |
jQuery.fn.exists = function(){
|
30 |
+
return (jQuery(this).length > 0 ? true : false);
|
31 |
}
|
32 |
function isNumber(val) {
|
33 |
return /^\d+/.test(val);
|
142 |
}
|
143 |
jQuery.fn.toeRebuildSelect = function(data, useIdAsValue, val) {
|
144 |
if(jQuery(this).tagName() == 'SELECT' && typeof(data) == 'object') {
|
145 |
+
if(jQuery(data).length > 0) {
|
146 |
if(typeof(val) == 'undefined')
|
147 |
val = false;
|
148 |
if(jQuery(this).children('option').length) {
|
js/common.min.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
|
2 |
+
jQuery.fn.nextInArray=function(b){var c=0;for(var a=0;a<this.length;a++){if(this[a]==b){c=a+1;break}}if(c>this.length-1){c=0}return this[c]};jQuery.fn.clearForm=function(){return this.each(function(){var b=this.type,a=this.tagName.toLowerCase();if(a=="form"){return jQuery(":input",this).clearForm()}if(b=="text"||b=="password"||a=="textarea"){this.value=""}else{if(b=="checkbox"||b=="radio"){this.checked=false}else{if(a=="select"){this.selectedIndex=-1}}}})};jQuery.fn.tagName=function(){return this.get(0).tagName};jQuery.fn.exists=function(){return(jQuery(this).length>0?true:false)};function isNumber(a){return/^\d+/.test(a)}function pushDataToParam(e,a){a=a?a:"";var d=[];for(var c in e){var b=a&&a!=""?a+"["+c+"]":c;if(typeof(e[c])==="array"||typeof(e[c])==="object"){d=jQuery.merge(d,pushDataToParam(e[c],b))}else{d.push(b+"="+e[c])}}return d}jQuery.fn.serializeAnythingPps=function(d,b){var c=b?{}:[],a=jQuery(this).find(":input").get();jQuery.each(a,function(){if(this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type))){var e=jQuery(this).val();if(b){c[this.name]=e}else{c.push(encodeURIComponent(this.name)+"="+encodeURIComponent(e))}}});if(typeof(d)!="undefined"&&d){c=jQuery.merge(c,pushDataToParam(d))}return b?c:c.join("&").replace(/%20/g,"+")};jQuery.fn.serializeAssoc=function(){var a=[];jQuery.each(this.serializeArray(),function(c,e){var b=e.name.match(/(.*?)\[(.*?)\]/);if(b!==null){var d=b[1];var f=b[2];if(!a[d]){a[d]=[]}if(a[d][f]){if(jQuery.isArray(a[d][f])){a[d][f].push(e.value)}else{a[d][f]=[];a[d][f].push(e.value)}}else{a[d][f]=e.value}}else{if(a[e.name]){if(jQuery.isArray(a[e.name])){a[e.name].push(e.value)}else{a[e.name]=[];a[e.name].push(e.value)}}else{a[e.name]=e.value}}});return a};function str_replace(c,d,b){var a=c.split(d);return a.join(b)}function pps_str_replace(c,d,b){var a=c.split(d);return a.join(b)}function nameToClassId(a){return str_replace(str_replace(a,"]",""),"[","")}function strpos(b,c,d){var a=b.indexOf(c,d);return a>=0?a:false}function extend(b,a){var c=function(){};c.prototype=a.prototype;b.prototype=new c();b.prototype.constructor=b;b.superclass=a.prototype}function toeRedirect(b,a){if(a){var c=window.open(b,"_blank");if(c){c.focus()}else{document.location.href=b}}else{document.location.href=b}}function toeReload(a){if(a){toeRedirect(a)}document.location.reload()}jQuery.fn.toeRebuildSelect=function(b,c,d){if(jQuery(this).tagName()=="SELECT"&&typeof(b)=="object"){if(jQuery(b).length>0){if(typeof(d)=="undefined"){d=false}if(jQuery(this).children("option").length){jQuery(this).children("option").remove()}if(typeof(c)=="undefined"){c=false}var a="";for(var e in b){a="";if(d&&((c&&e==d)||(b[e]==d))){a="selected"}jQuery(this).append('<option value="'+(c?e:b[e])+'" '+a+">"+b[e]+"</option>")}}}};function toeInArray(c,b){if(typeof(b)=="object"){for(var a in b){if(b[a]==c){return a}}}else{if(typeof(b)=="array"){return jQuery.inArray(c,b)}}return -1}jQuery.fn.setReadonly=function(){jQuery(this).addClass("toeReadonly").attr("readonly","readonly")};jQuery.fn.unsetReadonly=function(){jQuery(this).removeClass("toeReadonly").removeAttr("readonly","readonly")};jQuery.fn.getClassId=function(a,c){var b=jQuery(this).attr("class");b=b.substr(strpos(b,a+"_"));if(strpos(b," ")){b=b.substr(0,strpos(b," "))}b=b.split("_");b=b[1];return b};function toeTextIncDec(a,c){var b=parseInt(jQuery("#"+a).val());if(isNaN(b)){b=0}if(!(c<0&&b<1)){b+=c}jQuery("#"+a).val(b)}function toeStrFirstUp(b){b+="";var a=b.charAt(0).toUpperCase();return a+b.substr(1)}function parseStr(q,g){var a=String(q).replace(/^&/,"").replace(/&$/,"").split("&"),h=a.length,t,r,e,n,v,l,k,c,s,u,w,o,d,m,f,b=function(i){return decodeURIComponent(i.replace(/\+/g,"%20"))};if(!g){g={}}for(t=0;t<h;t++){u=a[t].split("=");w=b(u[0]);o=(u.length<2)?"":b(u[1]);while(w.charAt(0)===" "){w=w.slice(1)}if(w.indexOf("\x00")>-1){w=w.slice(0,w.indexOf("\x00"))}if(w&&w.charAt(0)!=="["){m=[];d=0;for(r=0;r<w.length;r++){if(w.charAt(r)==="["&&!d){d=r+1}else{if(w.charAt(r)==="]"){if(d){if(!m.length){m.push(w.slice(0,d-1))}m.push(w.substr(d,r-d));d=0;if(w.charAt(r+1)!=="["){break}}}}}if(!m.length){m=[w]}for(r=0;r<m[0].length;r++){s=m[0].charAt(r);if(s===" "||s==="."||s==="["){m[0]=m[0].substr(0,r)+"_"+m[0].substr(r+1)}if(s==="["){break}}l=g;for(r=0,f=m.length;r<f;r++){w=m[r].replace(/^['"]/,"").replace(/['"]$/,"");k=r!==m.length-1;v=l;if((w!==""&&w!==" ")||r===0){if(l[w]===c){l[w]={}}l=l[w]}else{e=-1;for(n in l){if(l.hasOwnProperty(n)){if(+n>e&&n.match(/^\d+$/g)){e=+n}}}w=e+1}}v[w]=o}}return g}function toeListablePps(b){this.params=jQuery.extend({},b);this.table=jQuery(this.params.table);this.paging=jQuery(this.params.paging);this.perPage=this.params.perPage;this.list=this.params.list;this.count=this.params.count;this.page=this.params.page;this.pagingCallback=this.params.pagingCallback;var a=this;this.draw=function(k,j){this.table.find("tr").not(".ppsExample, .ppsTblHeader").remove();var n=this.table.find(".ppsExample");for(var e in k){var o=n.clone();for(var l in k[e]){var f=o.find("."+l);if(f.size()){var m=f.attr("valueTo");if(m){var c=k[e][l];var h=f.attr(m);if(h){c=h+" "+c}f.attr(m,c)}else{f.html(k[e][l])}}}o.removeClass("ppsExample").show();this.table.append(o)}if(this.paging){this.paging.html("");if(j&&j>k.length&&this.perPage){for(var e=1;e<=Math.ceil(j/this.perPage);e++){var d=e-1,g=(d==this.page)?jQuery("<b/>"):jQuery("<a/>");if(d!=this.page){g.attr("href","#"+d).click(function(){if(a.pagingCallback&&typeof(a.pagingCallback)=="function"){a.pagingCallback(parseInt(jQuery(this).attr("href").replace("#","")));return false}})}g.addClass("toePagingElement").html(e);this.paging.append(g);if(e%20==0&&e){this.paging.append("<br />")}}}}};if(this.list){this.draw(this.list,this.count)}}function setCookiePps(a,e,b){var f=new Date();f.setDate(f.getDate()+b);var c="";if(typeof(e)=="array"||typeof(e)=="object"){c="_JSON:"+JSON.stringify(e)}else{c=e}var d=escape(c)+((b==null)?"":"; expires="+f.toUTCString())+"; path=/";document.cookie=a+"="+d}function getCookiePps(a){var c=document.cookie.split(a+"=");if(c.length==2){var b=unescape(c.pop().split(";").shift());if(b.indexOf("_JSON:")===0){b=JSON.parse(b.split("_JSON:").pop())}return b}return null}function delCookiePps(a){document.cookie=a+"=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"}function callUserFuncArray(cb,parameters){var func;if(typeof cb==="string"){func=(typeof this[cb]==="function")?this[cb]:func=(new Function(null,"return "+cb))()}else{if(Object.prototype.toString.call(cb)==="[object Array]"){func=(typeof cb[0]=="string")?eval(cb[0]+"['"+cb[1]+"']"):func=cb[0][cb[1]]}else{if(typeof cb==="function"){func=cb}}}if(typeof func!=="function"){throw new Error(func+" is not a valid function")}return(typeof cb[0]==="string")?func.apply(eval(cb[0]),parameters):(typeof cb[0]!=="object")?func.apply(null,parameters):func.apply(cb[0],parameters)}jQuery.fn.zoom=function(b,a){a=a?a:"center center";jQuery(this).data("zoom",b);return jQuery(this).css({"-moz-transform":"scale("+b+")","-moz-transform-origin":a,"-o-transform":"scale("+b+")","-o-transform-origin":a,"-webkit-transform":"scale("+b+")","-webkit-transform-origin":a,transform:"scale("+b+")","transform-origin":a})};jQuery.fn.ppsZoom=function(b,a){a=a?a:"center center";jQuery(this).data("zoom",b);return jQuery(this).css({"-moz-transform":"scale("+b+")","-moz-transform-origin":a,"-o-transform":"scale("+b+")","-o-transform-origin":a,"-webkit-transform":"scale("+b+")","-webkit-transform-origin":a,transform:"scale("+b+")","transform-origin":a})};jQuery.fn.scrollWidth=function(){var c=document.createElement("p");c.style.width="100%";c.style.height="200px";var d=document.createElement("div");d.style.position="absolute";d.style.top="0px";d.style.left="0px";d.style.visibility="hidden";d.style.width="200px";d.style.height="150px";d.style.overflow="hidden";d.appendChild(c);document.body.appendChild(d);var b=c.offsetWidth;d.style.overflow="scroll";var a=c.offsetWidth;if(b==a){a=d.clientWidth}document.body.removeChild(d);return(b-a)};function toeGetImgAttachId(a){var d=jQuery(a).attr("class"),c=0;if(d&&d!=""){var b=d.match(/wp-image-(\d+)/);if(b&&b[1]){c=parseInt(b[1])}}return c}function toeGetHashParams(){var a=window.location.hash.split("#"),c=[];for(var b in a){if(a[b]&&a[b]!=""){c.push(a[b])}}return c}function getDataLcs(a){this.data,this.dataChecked;if(!this.dataChecked){if(window.location.search){this.data=parseStr(window.location.search.substr(1))}this.dataChecked=true}return typeof(a)!=="undefined"&&this.data?this.data[a]:this.data}function traverseElement(a,b,c,e){if(!/^(script|style)$/.test(a.tagName)){var d=a.lastChild;while(d){if(d.nodeType==1){traverseElement(d,b,c,e)}else{if(d.nodeType==3){c(d,b,e)}}d=d.previousSibling}}}function textReplacerFunc(b,a,c){b.data=b.data.replace(a,c)}function replaceWords(c,d){var a=document.createElement("div");a.innerHTML=c;for(var b in d){traverseElement(a,new RegExp(b,"g"),textReplacerFunc,d[b])}return a.innerHTML}function toeSelectText(b){var d=document,e=jQuery(b).get(0),a,c;if(d.body.createTextRange){a=d.body.createTextRange();a.moveToElementText(e);a.select()}else{if(window.getSelection){c=window.getSelection();a=d.createRange();a.selectNodeContents(e);c.removeAllRanges();c.addRange(a)}}}jQuery.fn.animationDuration=function(c,a){if(a){c=parseFloat(c)/1000}var b=c+"s";return jQuery(this).css({"webkit-animation-duration":b,"-moz-animation-duration":b,"-o-animation-duration":b,"animation-duration":b})};function ppsStrToMs(e){var f=e.split(" ");if(f.length==2){e=f[0]+" ";var d=f[1].split(":");for(var c=0;c<3;c++){e+=d[c]?d[c]:"00";if(c<2){e+=":"}}}var a=new Date(str_replace(e,"-","/")),b=0;if(a){b=a.getTime()}return b}Date.prototype.format=function(d){var b="";var f=Date.replaceChars;for(var c=0;c<d.length;c++){var a=d.charAt(c);if(c-1>=0&&d.charAt(c-1)=="\\"){b+=a}else{if(f[a]){b+=f[a].call(this)}else{if(a!="\\"){b+=a}}}}return b};Date.replaceChars={shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],longMonths:["January","February","March","April","May","June","July","August","September","October","November","December"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],longDays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],d:function(){return(this.getDate()<10?"0":"")+this.getDate()},D:function(){return Date.replaceChars.shortDays[this.getDay()]},j:function(){return this.getDate()},l:function(){return Date.replaceChars.longDays[this.getDay()]},N:function(){return this.getDay()+1},S:function(){return this.getDate()%10==1&&this.getDate()!=11?"st":this.getDate()%10==2&&this.getDate()!=12?"nd":this.getDate()%10==3&&this.getDate()!=13?"rd":"th"},w:function(){return this.getDay()},z:function(){var a=new Date(this.getFullYear(),0,1);return Math.ceil((this-a)/86400000)},W:function(){var a=new Date(this.getFullYear(),0,1);return Math.ceil(((this-a)/86400000+a.getDay()+1)/7)},F:function(){return Date.replaceChars.longMonths[this.getMonth()]},m:function(){return(this.getMonth()<9?"0":"")+(this.getMonth()+1)},M:function(){return Date.replaceChars.shortMonths[this.getMonth()]},n:function(){return this.getMonth()+1},t:function(){var a=new Date;return(new Date(a.getFullYear(),a.getMonth(),0)).getDate()},L:function(){var a=this.getFullYear();return a%400==0||a%100!=0&&a%4==0},o:function(){var a=new Date(this.valueOf());a.setDate(a.getDate()-(this.getDay()+6)%7+3);return a.getFullYear()},Y:function(){return this.getFullYear()},y:function(){return(""+this.getFullYear()).substr(2)},a:function(){return this.getHours()<12?"am":"pm"},A:function(){return this.getHours()<12?"AM":"PM"},B:function(){return Math.floor(((this.getUTCHours()+1)%24+this.getUTCMinutes()/60+this.getUTCSeconds()/3600)*1000/24)},g:function(){return this.getHours()%12||12},G:function(){return this.getHours()},h:function(){return((this.getHours()%12||12)<10?"0":"")+(this.getHours()%12||12)},H:function(){return(this.getHours()<10?"0":"")+this.getHours()},i:function(){return(this.getMinutes()<10?"0":"")+this.getMinutes()},s:function(){return(this.getSeconds()<10?"0":"")+this.getSeconds()},u:function(){var a=this.getMilliseconds();return(a<10?"00":a<100?"0":"")+a},e:function(){return"Not Yet Supported"},I:function(){var c=null;for(var a=0;a<12;++a){var d=new Date(this.getFullYear(),a,1);var b=d.getTimezoneOffset();if(c===null){c=b}else{if(b<c){c=b;break}else{if(b>c){break}}}}return this.getTimezoneOffset()==c|0},O:function(){return(-this.getTimezoneOffset()<0?"-":"+")+(Math.abs(this.getTimezoneOffset()/60)<10?"0":"")+Math.abs(this.getTimezoneOffset()/60)+"00"},P:function(){return(-this.getTimezoneOffset()<0?"-":"+")+(Math.abs(this.getTimezoneOffset()/60)<10?"0":"")+Math.abs(this.getTimezoneOffset()/60)+":00"},T:function(){var b=this.getMonth();this.setMonth(0);var a=this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/,"$1");this.setMonth(b);return a},Z:function(){return -this.getTimezoneOffset()*60},c:function(){return this.format("Y-m-d\\TH:i:sP")},r:function(){return this.toString()},U:function(){return this.getTime()/1000}};function isMobilePps(){var a=false;if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0,4))){a=true}return a}function isNumericPps(a){if(jQuery.isNumeric){return jQuery.isNumeric(a)}return !isNaN(parseFloat(a))&&isFinite(a)}function disableScrollPps(b){var a=jQuery(b);a.data("prev-overflow",a.css("overflow")).css("overflow","hidden")}function enableScrollPps(b){var a=jQuery(b);var c=a.data("prev-overflow");if(!c||c==""){c="visible"}a.css("overflow",c)}function randPps(b,a,d){var c=(Math.random()*(a-b))+b;return d?c:Math.round(c)};
|
js/core.js
CHANGED
@@ -85,8 +85,8 @@ jQuery.fn.sendFormPps = function(params) {
|
|
85 |
if(params.btn) {
|
86 |
jQuery(params.btn).attr('disabled', 'disabled');
|
87 |
// Font awesome usage
|
88 |
-
params.btnIconElement = jQuery(params.btn).find('.fa').
|
89 |
-
if(jQuery(params.btn).find('.fa').
|
90 |
params.btnIconElement
|
91 |
.data('prev-class', params.btnIconElement.attr('class'))
|
92 |
.attr('class', 'fa fa-spinner fa-spin');
|
@@ -248,7 +248,7 @@ function toeOptTimeoutHideDescriptionPps() {
|
|
248 |
*/
|
249 |
function toeOptShowDescriptionPps(description, x, y, moveToLeft) {
|
250 |
if(typeof(description) != 'undefined' && description != '') {
|
251 |
-
if(!jQuery('#ppsOptDescription').
|
252 |
jQuery('body').append('<div id="ppsOptDescription"></div>');
|
253 |
}
|
254 |
if(moveToLeft)
|
85 |
if(params.btn) {
|
86 |
jQuery(params.btn).attr('disabled', 'disabled');
|
87 |
// Font awesome usage
|
88 |
+
params.btnIconElement = jQuery(params.btn).find('.fa').length ? jQuery(params.btn).find('.fa') : jQuery(params.btn);
|
89 |
+
if(jQuery(params.btn).find('.fa').length) {
|
90 |
params.btnIconElement
|
91 |
.data('prev-class', params.btnIconElement.attr('class'))
|
92 |
.attr('class', 'fa fa-spinner fa-spin');
|
248 |
*/
|
249 |
function toeOptShowDescriptionPps(description, x, y, moveToLeft) {
|
250 |
if(typeof(description) != 'undefined' && description != '') {
|
251 |
+
if(!jQuery('#ppsOptDescription').length) {
|
252 |
jQuery('body').append('<div id="ppsOptDescription"></div>');
|
253 |
}
|
254 |
if(moveToLeft)
|
js/core.min.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
|
2 |
+
if(typeof(PPS_DATA)=="undefined"){var PPS_DATA={}}if(isNumber(PPS_DATA.animationSpeed)){PPS_DATA.animationSpeed=parseInt(PPS_DATA.animationSpeed)}else{if(jQuery.inArray(PPS_DATA.animationSpeed,["fast","slow"])==-1){PPS_DATA.animationSpeed="fast"}}PPS_DATA.showSubscreenOnCenter=parseInt(PPS_DATA.showSubscreenOnCenter);var sdLoaderImgPps='<img src="'+PPS_DATA.loader+'" />';var g_ppsAnimationSpeed=300;jQuery.fn.showLoaderPps=function(){return jQuery(this).html(sdLoaderImgPps)};jQuery.fn.appendLoaderPps=function(){jQuery(this).append(sdLoaderImgPps)};jQuery.sendFormPps=function(a){return jQuery("<br />").sendFormPps(a)};jQuery.fn.sendFormPps=function(e){var b=null;if(!e){e={fid:false,msgElID:false,onSuccess:false}}if(e.fid){b=jQuery("#"+fid)}else{b=jQuery(this)}var c=(jQuery(b).tagName()=="FORM");var f=new Array();if(e.data){f=e.data}else{if(c){f=jQuery(b).serialize()}}if(e.appendData){var h=typeof(f)=="string";var k=[];for(var g in e.appendData){if(h){k.push(g+"="+e.appendData[g])}else{f[g]=e.appendData[g]}}if(h){f+="&"+k.join("&")}}var d=null;if(e.msgElID){if(e.msgElID=="noMessages"){d=false}else{if(typeof(e.msgElID)=="object"){d=e.msgElID}else{d=jQuery("#"+e.msgElID)}}}if(typeof(e.inputsWraper)=="string"){b=jQuery("#"+e.inputsWraper);c=true}if(c&&b){jQuery(b).find("*").removeClass("ppsInputError")}if(d&&!e.btn){jQuery(d).removeClass("ppsSuccessMsg").removeClass("ppsErrorMsg");if(!e.btn){jQuery(d).showLoaderPps()}}if(e.btn){jQuery(e.btn).attr("disabled","disabled");e.btnIconElement=jQuery(e.btn).find(".fa").length?jQuery(e.btn).find(".fa"):jQuery(e.btn);if(jQuery(e.btn).find(".fa").length){e.btnIconElement.data("prev-class",e.btnIconElement.attr("class")).attr("class","fa fa-spinner fa-spin")}}var a="";if(typeof(e.url)!="undefined"){a=e.url}else{if(typeof(ajaxurl)=="undefined"||typeof(ajaxurl)!=="string"){a=PPS_DATA.ajaxurl}else{a=ajaxurl}}jQuery(".ppsErrorForField").hide(PPS_DATA.animationSpeed);var j=e.dataType?e.dataType:"json";if(typeof(f)=="string"){f+="&pl="+PPS_DATA.PPS_CODE;f+="&reqType=ajax"}else{f.pl=PPS_DATA.PPS_CODE;f.reqType="ajax"}jQuery.ajax({url:a,data:f,type:"POST",dataType:j,success:function(i){toeProcessAjaxResponsePps(i,d,b,c,e);if(e.clearMsg){setTimeout(function(){if(d){jQuery(d).animateClear()}},typeof(e.clearMsg)=="boolean"?5000:e.clearMsg)}}})};jQuery.fn.animateClear=function(){var a=jQuery("<span>"+jQuery(this).html()+"</span>");jQuery(this).html(a);jQuery(a).hide(PPS_DATA.animationSpeed,function(){jQuery(a).remove()})};jQuery.fn.animateRemovePps=function(a,b){a=a==undefined?PPS_DATA.animationSpeed:a;jQuery(this).hide(a,function(){jQuery(this).remove();if(typeof(b)==="function"){b()}})};function toeProcessAjaxResponsePps(h,e,c,d,f){if(typeof(f)=="undefined"){f={}}if(typeof(e)=="string"){e=jQuery("#"+e)}if(e){jQuery(e).html("")}if(f.btn){jQuery(f.btn).removeAttr("disabled");if(f.btnIconElement){f.btnIconElement.attr("class",f.btnIconElement.data("prev-class"))}}if(typeof(h)=="object"){if(h.error){if(e){jQuery(e).removeClass("ppsSuccessMsg").addClass("ppsErrorMsg")}var j=[];for(var a in h.errors){if(d){var b=jQuery(c).find('[name*="'+a+'"]');b.addClass("ppsInputError");if(b.attr("placeholder")){}if(!b.data("keyup-error-remove-binded")){b.keydown(function(){jQuery(this).removeClass("ppsInputError")}).data("keyup-error-remove-binded",1)}}if(jQuery(".ppsErrorForField.toe_"+nameToClassId(a)+"").exists()){jQuery(".ppsErrorForField.toe_"+nameToClassId(a)+"").show().html(h.errors[a])}else{if(e){jQuery(e).append(h.errors[a]).append("<br />")}else{j.push(h.errors[a])}}}if(j.length&&f.btn&&jQuery.fn.dialog&&!e){jQuery('<div title="'+toeLangPps("Really small warning :)")+'" />').html(j.join("<br />")).appendTo("body").dialog({modal:true,width:"500px"})}}else{if(h.messages.length){if(e){jQuery(e).removeClass("ppsErrorMsg").addClass("ppsSuccessMsg");for(var g=0;g<h.messages.length;g++){jQuery(e).append(h.messages[g]).append("<br />")}}}}}if(f.onSuccess&&typeof(f.onSuccess)=="function"){f.onSuccess(h)}}function getDialogElementPps(){return jQuery("<div/>").appendTo(jQuery("body"))}function toeOptionPps(a){if(PPS_DATA.options&&PPS_DATA.options[a]){return PPS_DATA.options[a]}return false}function toeLangPps(a){if(PPS_DATA.siteLang&&PPS_DATA.siteLang[a]){return PPS_DATA.siteLang[a]}return a}function toePagesPps(a){if(typeof(PPS_DATA)!="undefined"&&PPS_DATA[a]){return PPS_DATA[a]}return false}function toeOptTimeoutHideDescriptionPps(){jQuery("#ppsOptDescription").removeAttr("toeFixTip");setTimeout(function(){if(!jQuery("#ppsOptDescription").attr("toeFixTip")){toeOptHideDescriptionPps()}},500)}function toeOptShowDescriptionPps(b,a,d,c){if(typeof(b)!="undefined"&&b!=""){if(!jQuery("#ppsOptDescription").length){jQuery("body").append('<div id="ppsOptDescription"></div>')}if(c){jQuery("#ppsOptDescription").css("right",jQuery(window).width()-(a-10))}else{jQuery("#ppsOptDescription").css("left",a+10)}jQuery("#ppsOptDescription").css("top",d);jQuery("#ppsOptDescription").show(200);jQuery("#ppsOptDescription").html(b)}}function toeOptHideDescriptionPps(){jQuery("#ppsOptDescription").removeAttr("toeFixTip");jQuery("#ppsOptDescription").hide(200)}function toeInArrayPps(c,b){if(b){for(var a in b){if(b[a]==c){return true}}}return false}function toeShowDialogCustomized(b,a){a=jQuery.extend({resizable:false,width:500,height:300,closeOnEscape:true,open:function(c,d){jQuery(".ui-dialog-titlebar").css({"background-color":"#222222","background-image":"none",border:"none",margin:"0",padding:"0","border-radius":"0",color:"#CFCFCF",height:"27px"});jQuery(".ui-dialog-titlebar-close").css({background:'url("'+PPS_DATA.cssPath+'img/tb-close.png") no-repeat scroll 0 0 transparent',border:"0",width:"15px",height:"15px",padding:"0","border-radius":"0",margin:"7px 7px 0"}).html("");jQuery(".ui-dialog").css({"border-radius":"3px","background-color":"#FFFFFF","background-image":"none",padding:"1px","z-index":"300000",position:"fixed",top:"60px"});jQuery(".ui-dialog-buttonpane").css({"background-color":"#FFFFFF"});jQuery(".ui-dialog-title").css({color:"#CFCFCF",font:"12px sans-serif",padding:"6px 10px 0"});if(a.openCallback&&typeof(a.openCallback)=="function"){a.openCallback(c,d)}jQuery(".ui-widget-overlay").css({"z-index":jQuery(c.target).parents(".ui-dialog:first").css("z-index")-1,"background-image":"none"});if(a.modal&&a.closeOnBg){jQuery(".ui-widget-overlay").unbind("click").bind("click",function(){jQuery(b).dialog("close")})}}},a);return jQuery(b).dialog(a)}function toeSliderMove(a,b){var c=jQuery(a.target).attr("id");jQuery("#toeSliderDisplay_"+c).html(b.value);jQuery("#toeSliderInput_"+c).val(b.value).change()}function ppsCorrectJqueryUsed(){return(typeof(jQuery.fn.sendFormPps)==="function")}function ppsReloadCoreJs(d,e){var c="",b=["common.js","core.js"];for(var a=0;a<b.length;a++){c+='<script type="text/javascript" class="ppsReloadedScript" src="'+PPS_DATA.jsPath+b[a]+'"><\/script>'}jQuery("head").append(c);if(d){_ppsRunClbAfterCoreReload(d,e)}}function _ppsRunClbAfterCoreReload(a,b){if(ppsCorrectJqueryUsed()){callUserFuncArray(a,b);return}setTimeout(function(){ppsCorrectJqueryUsed(a,b)},500)};
|
js/google.recaptcha.js
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function ppsInitCaptcha( $elements ) {
|
2 |
+
if(typeof(grecaptcha) === 'undefined' || typeof(grecaptcha.render) === 'undefined') {
|
3 |
+
// We set this function to be returned when google api loaded - onload=ppsInitCaptcha
|
4 |
+
/*setTimeout(function(){
|
5 |
+
ppsInitCaptcha( $elements );
|
6 |
+
}, 500);*/
|
7 |
+
return;
|
8 |
+
}
|
9 |
+
$elements = $elements ? $elements : jQuery(document).find('.g-recaptcha');
|
10 |
+
if($elements && $elements.size()) {
|
11 |
+
$elements.each(function(){
|
12 |
+
var $this = jQuery(this);
|
13 |
+
if(typeof $this.data('recaptcha-widget-id') == 'undefined') {
|
14 |
+
var dataForInit = {}
|
15 |
+
, elementData = $this.data()
|
16 |
+
, elementId = $this.attr('id');
|
17 |
+
if(!elementId) {
|
18 |
+
elementId = 'ppsRecaptcha_'+ (Math.floor(Math.random() * 100000));
|
19 |
+
$this.attr('id', elementId);
|
20 |
+
}
|
21 |
+
if(elementData) {
|
22 |
+
for(var key in elementData) {
|
23 |
+
if(typeof(elementData[ key ]) === 'string') {
|
24 |
+
dataForInit[ key ] = elementData[ key ];
|
25 |
+
}
|
26 |
+
}
|
27 |
+
}
|
28 |
+
$this.data('recaptcha-widget-id', grecaptcha.render(elementId, dataForInit));
|
29 |
+
}
|
30 |
+
});
|
31 |
+
}
|
32 |
+
}
|
js/wp.tabs.js
CHANGED
@@ -17,9 +17,9 @@
|
|
17 |
});
|
18 |
});
|
19 |
var locationHash = document.location.hash;
|
20 |
-
if(locationHash && locationHash != '' && $this.find(locationHash) && $this.find(locationHash).
|
21 |
$this.wpTabs('activate', locationHash);
|
22 |
-
if(jQuery(locationHash).
|
23 |
// Avoid scrolling to hashes
|
24 |
jQuery(window).load(function(){
|
25 |
setTimeout(function(){
|
@@ -38,7 +38,7 @@
|
|
38 |
, activate: function(selector) {
|
39 |
return this.each(function(){
|
40 |
var $this = $(this);
|
41 |
-
if($this.find(selector).
|
42 |
this._activeTab = selector;
|
43 |
var navigations = $this.find('.nav-tab-wrapper:first').find('a.nav-tab:not(.notTab)');
|
44 |
if(!this._firstInit) {
|
17 |
});
|
18 |
});
|
19 |
var locationHash = document.location.hash;
|
20 |
+
if(locationHash && locationHash != '' && $this.find(locationHash) && $this.find(locationHash).length) {
|
21 |
$this.wpTabs('activate', locationHash);
|
22 |
+
if(jQuery(locationHash).length) {
|
23 |
// Avoid scrolling to hashes
|
24 |
jQuery(window).load(function(){
|
25 |
setTimeout(function(){
|
38 |
, activate: function(selector) {
|
39 |
return this.each(function(){
|
40 |
var $this = $(this);
|
41 |
+
if($this.find(selector).length) {
|
42 |
this._activeTab = selector;
|
43 |
var navigations = $this.find('.nav-tab-wrapper:first').find('a.nav-tab:not(.notTab)');
|
44 |
if(!this._firstInit) {
|
modules/options/models/options.php
CHANGED
@@ -13,7 +13,7 @@ class optionsModelPps extends modelPps {
|
|
13 |
}
|
14 |
public function save($optKey, $val, $ignoreDbUpdate = false) {
|
15 |
$this->_loadOptValues();
|
16 |
-
if(!isset($this->_values[ $optKey ]) || $this->_values[ $optKey ]['value']
|
17 |
if(isset($this->_values[ $optKey ]) || !isset($this->_values[ $optKey ]['value']))
|
18 |
$this->_values[ $optKey ] = array();
|
19 |
$this->_values[ $optKey ]['value'] = $val;
|
@@ -35,7 +35,7 @@ class optionsModelPps extends modelPps {
|
|
35 |
$this->_loadOptValues();
|
36 |
foreach($options as $cKey => $cData) {
|
37 |
foreach($cData['opts'] as $optKey => $optData) {
|
38 |
-
$value =
|
39 |
$changedOn = 0;
|
40 |
// Retrive value from saved options
|
41 |
if(isset($this->_values[ $optKey ])) {
|
13 |
}
|
14 |
public function save($optKey, $val, $ignoreDbUpdate = false) {
|
15 |
$this->_loadOptValues();
|
16 |
+
if(!isset($this->_values[ $optKey ]) || $this->_values[ $optKey ]['value'] !== $val) {
|
17 |
if(isset($this->_values[ $optKey ]) || !isset($this->_values[ $optKey ]['value']))
|
18 |
$this->_values[ $optKey ] = array();
|
19 |
$this->_values[ $optKey ]['value'] = $val;
|
35 |
$this->_loadOptValues();
|
36 |
foreach($options as $cKey => $cData) {
|
37 |
foreach($cData['opts'] as $optKey => $optData) {
|
38 |
+
$value = '';
|
39 |
$changedOn = 0;
|
40 |
// Retrive value from saved options
|
41 |
if(isset($this->_values[ $optKey ])) {
|
modules/popup/controller.php
CHANGED
@@ -225,6 +225,7 @@ class popupControllerPps extends controllerPps {
|
|
225 |
$forPromo = (int) reqPps::getVar('for_promo');
|
226 |
$forWix = (int) reqPps::getVar('for_wix');
|
227 |
$selectColumns = array('id','label','active','original_id','params','html','css','img_preview','show_on','show_to','show_pages','type_id','date_created','sort_order');
|
|
|
228 |
if($forWix) {
|
229 |
$contentKeys = array('popup_id', 'html', 'css');
|
230 |
/*foreach($contentKeys as $k) {
|
@@ -261,7 +262,8 @@ class popupControllerPps extends controllerPps {
|
|
261 |
if($addToKeys && (!$forWix || ($forWix && !in_array($k, $contentKeys)))) {
|
262 |
$allKeys[] = $k;
|
263 |
}
|
264 |
-
|
|
|
265 |
}
|
266 |
$valuesArr[] = '('. implode(',', $arr). ')';
|
267 |
}
|
225 |
$forPromo = (int) reqPps::getVar('for_promo');
|
226 |
$forWix = (int) reqPps::getVar('for_wix');
|
227 |
$selectColumns = array('id','label','active','original_id','params','html','css','img_preview','show_on','show_to','show_pages','type_id','date_created','sort_order');
|
228 |
+
$link = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
|
229 |
if($forWix) {
|
230 |
$contentKeys = array('popup_id', 'html', 'css');
|
231 |
/*foreach($contentKeys as $k) {
|
262 |
if($addToKeys && (!$forWix || ($forWix && !in_array($k, $contentKeys)))) {
|
263 |
$allKeys[] = $k;
|
264 |
}
|
265 |
+
//$arr[] = '"'. $wpdb->_real_escape($v). '"';
|
266 |
+
$arr[] = '"'. mysqli_real_escape_string($link, $v). '"';
|
267 |
}
|
268 |
$valuesArr[] = '('. implode(',', $arr). ')';
|
269 |
}
|
modules/popup/css/admin.popup.css
CHANGED
@@ -357,14 +357,17 @@ a.ppsSwitchShowHideOptLink:hover {
|
|
357 |
background-color: rgb(2, 28, 87) !important;
|
358 |
color: #fff;
|
359 |
}
|
360 |
-
.ppsSnow{
|
361 |
background: none;
|
362 |
background-image: url("http://supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow1.png"), url("http://supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow2.png"), url("http://supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow3.png");
|
363 |
-webkit-animation: snow 10s linear infinite;
|
364 |
-moz-animation: snow 10s linear infinite;
|
365 |
-ms-animation: snow 10s linear infinite;
|
366 |
animation: snow 10s linear infinite;
|
367 |
-
z-index: 0
|
|
|
|
|
|
|
368 |
}
|
369 |
@keyframes snow {
|
370 |
0% {background-position: 0px 0px, 0px 0px, 0px 0px;}
|
357 |
background-color: rgb(2, 28, 87) !important;
|
358 |
color: #fff;
|
359 |
}
|
360 |
+
.ppsSnow {
|
361 |
background: none;
|
362 |
background-image: url("http://supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow1.png"), url("http://supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow2.png"), url("http://supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow3.png");
|
363 |
-webkit-animation: snow 10s linear infinite;
|
364 |
-moz-animation: snow 10s linear infinite;
|
365 |
-ms-animation: snow 10s linear infinite;
|
366 |
animation: snow 10s linear infinite;
|
367 |
+
z-index: 0;
|
368 |
+
}
|
369 |
+
.ppsReCaptchaShell {
|
370 |
+
padding: 5px;
|
371 |
}
|
372 |
@keyframes snow {
|
373 |
0% {background-position: 0px 0px, 0px 0px, 0px 0px;}
|
modules/popup/css/frontend.popup.css
CHANGED
@@ -39,12 +39,14 @@
|
|
39 |
color: #4ae8ea !important;;
|
40 |
}
|
41 |
.ppsPopupPreloadImg {
|
42 |
-
width:
|
43 |
-
height:
|
44 |
position: absolute !important;
|
45 |
top: -9999px !important;
|
46 |
left: -9999px !important;
|
47 |
opacity: 0 !important;
|
|
|
|
|
48 |
}
|
49 |
.ppsPopupShell .alignleft {
|
50 |
float: left;
|
39 |
color: #4ae8ea !important;;
|
40 |
}
|
41 |
.ppsPopupPreloadImg {
|
42 |
+
width: auto !important;
|
43 |
+
height: auto !important;
|
44 |
position: absolute !important;
|
45 |
top: -9999px !important;
|
46 |
left: -9999px !important;
|
47 |
opacity: 0 !important;
|
48 |
+
display: none !important;
|
49 |
+
visibility: hidden !important;
|
50 |
}
|
51 |
.ppsPopupShell .alignleft {
|
52 |
float: left;
|
modules/popup/css/frontend.popup.min.css
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
|
2 |
+
.ppsPopupShell{position:fixed;display:none;z-index:999999999}#ppsPopupBgOverlay{display:none;width:100%;height:100%;top:0;left:0;position:fixed;z-index:999999998;background-color:#000;opacity:.5}.ppsSubFlexLoader{position:fixed;display:none;z-index:1000002;width:40px;height:8px}.ppsPopupShell .ppsInputError{border:1px solid #fa4e7f!important;color:#fa4e7f!important}.ppsPopupShell .ppsErrorMsg{color:#fa4e7f!important;padding:5px;margin:5px 0}.ppsPopupShell .ppsSuccessMsg{padding:5px;margin:5px 0;text-align:center;color:#4ae8ea!important}.ppsPopupPreloadImg{width:auto!important;height:auto!important;position:absolute!important;top:-9999px!important;left:-9999px!important;opacity:0!important;display:none!important;visibility:hidden!important}.ppsPopupShell .alignleft{float:left;margin:7px 10px 10px 0}.ppsPopupShell .alignright{float:right;margin:7px 0 10px 10px}.ppsPopupShell .container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width:768px){.ppsPopupShell .container{width:540px}}@media(min-width:992px){.ppsPopupShell .container{width:750px}}@media(min-width:1200px){.ppsPopupShell .container{width:960px}}.ppsSnow{background:0;background-image:url("//supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow1.png"),url("//supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow2.png"),url("//supsystic-42d7.kxcdn.com/_assets/popup/img/assets/2016_ht_1_snow3.png");position:absolute;top:0;left:0;height:100%;width:100%;-webkit-animation:snow 10s linear infinite;-moz-animation:snow 10s linear infinite;-ms-animation:snow 10s linear infinite;animation:snow 10s linear infinite;z-index:0}@keyframes snow{0%{background-position:0 0,0px 0,0px 0}50%{background-position:500px 500px,100px 200px,-100px 150px}100%{background-position:500px 1000px,200px 400px,-100px 300px}}@-moz-keyframes snow{0%{background-position:0 0,0px 0,0px 0}50%{background-position:500px 500px,100px 200px,-100px 150px}100%{background-position:400px 1000px,200px 400px,100px 300px}}@-webkit-keyframes snow{0%{background-position:0 0,0px 0,0px 0}50%{background-position:500px 500px,100px 200px,-100px 150px}100%{background-position:500px 1000px,200px 400px,-100px 300px}}@-ms-keyframes snow{0%{background-position:0 0,0px 0,0px 0}50%{background-position:500px 500px,100px 200px,-100px 150px}100%{background-position:500px 1000px,200px 400px,-100px 300px}}.ppsRePassLnk{text-decoration:none;color:#555d66}
|
modules/popup/js/admin.popup.edit.js
CHANGED
@@ -456,6 +456,7 @@ jQuery(document).ready(function(){
|
|
456 |
}
|
457 |
}).change();
|
458 |
}
|
|
|
459 |
});
|
460 |
function ppsAddEmailAttach(params) {
|
461 |
var $parent = params.$parentShell
|
456 |
}
|
457 |
}).change();
|
458 |
}
|
459 |
+
jQuery("#ppsPopupEditTabs .tooltipstered").removeAttr("title");
|
460 |
});
|
461 |
function ppsAddEmailAttach(params) {
|
462 |
var $parent = params.$parentShell
|
modules/popup/js/admin.popup.js
CHANGED
@@ -5,7 +5,7 @@ jQuery(document).ready(function(){
|
|
5 |
} else { // Creating new popup
|
6 |
ppsInitCreatePopupDialog();
|
7 |
}
|
8 |
-
if(jQuery('.ppsTplPrevImg').
|
9 |
ppsAdjustPreviewSize();
|
10 |
jQuery(window).resize(function(){
|
11 |
ppsAdjustPreviewSize();
|
5 |
} else { // Creating new popup
|
6 |
ppsInitCreatePopupDialog();
|
7 |
}
|
8 |
+
if(jQuery('.ppsTplPrevImg').length) { // If on creation page
|
9 |
ppsAdjustPreviewSize();
|
10 |
jQuery(window).resize(function(){
|
11 |
ppsAdjustPreviewSize();
|
modules/popup/js/frontend.popup.js
CHANGED
@@ -8,6 +8,7 @@ jQuery(document).ready(function(){
|
|
8 |
ppsPopups = typeof(ppsPopups) === 'undefined' ? [] : ppsPopups;
|
9 |
ppsPopups = ppsPopups.concat( ppsPopupsFromFooter );
|
10 |
}
|
|
|
11 |
if(typeof(ppsPopups) !== 'undefined' && ppsPopups && ppsPopups.length) {
|
12 |
ppsInitBgOverlay();
|
13 |
jQuery(document).trigger('ppsBeforePopupsInit', ppsPopups);
|
@@ -519,7 +520,12 @@ function _ppsPopupAddStat( popup, action, smType, isUnique ) {
|
|
519 |
});
|
520 |
jQuery(document).trigger('ppsAfterPopupsStatAdded', {popup: popup, action: action, smType: smType, is_unique: isUnique});
|
521 |
}
|
522 |
-
|
|
|
|
|
|
|
|
|
|
|
523 |
/**
|
524 |
* Show popup
|
525 |
* @param {mixed} popup Popup object or it's ID
|
@@ -764,6 +770,9 @@ function _ppsCheckContactForm(params) {
|
|
764 |
}, 1000);
|
765 |
return;
|
766 |
}
|
|
|
|
|
|
|
767 |
$forms.each(function(){
|
768 |
var viewHtmlId = jQuery(this).attr('id')
|
769 |
, form = g_cfsForms.getByViewHtmlId( viewHtmlId );
|
@@ -934,7 +943,9 @@ function ppsClosePopup(popup) {
|
|
934 |
enableScrollPps('body');
|
935 |
}
|
936 |
// Check redirect after close option
|
937 |
-
if(popup.params.tpl.
|
|
|
|
|
938 |
toeRedirect(popup.params.tpl.reidrect_on_close, parseInt(popup.params.tpl.reidrect_on_close_new_wnd));
|
939 |
}
|
940 |
_ppsPopupAddStat( popup, 'close' ); // Save close popup statistics
|
@@ -1073,7 +1084,7 @@ function ppsHideBgOverlay(popup) {
|
|
1073 |
function ppsBindPopupActions(popup) {
|
1074 |
var $shell = ppsGetPopupShell( popup );
|
1075 |
// TODO: make usage of ppsPopupSubscribeSuccess() function only after success subscribe process, not after subscribe action
|
1076 |
-
if($shell.find('.ppsSubscribeForm_aweber').
|
1077 |
$shell.find('.ppsSubscribeForm_aweber').submit(function(){
|
1078 |
if(jQuery(this).find('input[name=email]').val()) {
|
1079 |
ppsPopupSubscribeSuccess( popup );
|
@@ -1081,13 +1092,13 @@ function ppsBindPopupActions(popup) {
|
|
1081 |
});
|
1082 |
}
|
1083 |
// Check build-in PopUp subscribe links
|
1084 |
-
if($shell.find('.ppsSmLink').
|
1085 |
$shell.find('.ppsSmLink').click(function(){
|
1086 |
_ppsPopupSetActionDone(popup, 'share', jQuery(this).data('type'));
|
1087 |
});
|
1088 |
}
|
1089 |
// Check Social Share by Supsystic plugin links in PopUp
|
1090 |
-
if($shell.find('.supsystic-social-sharing').
|
1091 |
$shell.find('.supsystic-social-sharing a').click(function(){
|
1092 |
var socHost = this.hostname
|
1093 |
, socType = ''; // Social network type key
|
@@ -1110,7 +1121,7 @@ function ppsBindPopupActions(popup) {
|
|
1110 |
}
|
1111 |
});
|
1112 |
}
|
1113 |
-
if($shell.find('.fb_iframe_widget').
|
1114 |
_ppsBindFbLikeBtnAction(popup);
|
1115 |
}
|
1116 |
/*For age verification templates*/
|
@@ -1288,15 +1299,28 @@ function _ppsBindClickHrefSaving() {
|
|
1288 |
for(var i = 0; i < ppsPopups.length; i++) {
|
1289 |
if(ppsPopups[ i ].params
|
1290 |
&& ppsPopups[ i ].params.tpl
|
1291 |
-
&& parseInt(ppsPopups[ i ].params.tpl.sub_redirect_to_btn_url)
|
1292 |
) {
|
1293 |
-
var $btn = jQuery('[onclick*="ppsShowPopup('+ ppsPopups[ i ].id+ ')"]')
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1298 |
}
|
1299 |
}
|
|
|
1300 |
}
|
1301 |
function ppsAddShowClb( id, clb ) {
|
1302 |
if(!g_ppsShowCallbacks[ id ]) {
|
8 |
ppsPopups = typeof(ppsPopups) === 'undefined' ? [] : ppsPopups;
|
9 |
ppsPopups = ppsPopups.concat( ppsPopupsFromFooter );
|
10 |
}
|
11 |
+
jQuery(document).trigger('ppsBeforePopupsStartInit', ppsPopups);
|
12 |
if(typeof(ppsPopups) !== 'undefined' && ppsPopups && ppsPopups.length) {
|
13 |
ppsInitBgOverlay();
|
14 |
jQuery(document).trigger('ppsBeforePopupsInit', ppsPopups);
|
520 |
});
|
521 |
jQuery(document).trigger('ppsAfterPopupsStatAdded', {popup: popup, action: action, smType: smType, is_unique: isUnique});
|
522 |
}
|
523 |
+
function ppsShowPopUpOnClick( popup, element ) {
|
524 |
+
if(isNumericPps( popup ))
|
525 |
+
popup = ppsGetPopupById( popup );
|
526 |
+
_ppsSaveClickHref(popup, jQuery(element));
|
527 |
+
ppsShowPopup( popup );
|
528 |
+
}
|
529 |
/**
|
530 |
* Show popup
|
531 |
* @param {mixed} popup Popup object or it's ID
|
770 |
}, 1000);
|
771 |
return;
|
772 |
}
|
773 |
+
if(typeof(cfsCheckInitForms) !== 'undefined') {
|
774 |
+
cfsCheckInitForms($shell);
|
775 |
+
}
|
776 |
$forms.each(function(){
|
777 |
var viewHtmlId = jQuery(this).attr('id')
|
778 |
, form = g_cfsForms.getByViewHtmlId( viewHtmlId );
|
943 |
enableScrollPps('body');
|
944 |
}
|
945 |
// Check redirect after close option
|
946 |
+
if(parseInt(popup.params.tpl.close_redirect_to_btn_url) && popup.params.close_redirect_to_btn_url_href) {
|
947 |
+
toeRedirect(popup.params.close_redirect_to_btn_url_href, parseInt(popup.params.tpl.reidrect_on_close_new_wnd));
|
948 |
+
} else if(popup.params.tpl.reidrect_on_close && popup.params.tpl.reidrect_on_close != '') {
|
949 |
toeRedirect(popup.params.tpl.reidrect_on_close, parseInt(popup.params.tpl.reidrect_on_close_new_wnd));
|
950 |
}
|
951 |
_ppsPopupAddStat( popup, 'close' ); // Save close popup statistics
|
1084 |
function ppsBindPopupActions(popup) {
|
1085 |
var $shell = ppsGetPopupShell( popup );
|
1086 |
// TODO: make usage of ppsPopupSubscribeSuccess() function only after success subscribe process, not after subscribe action
|
1087 |
+
if($shell.find('.ppsSubscribeForm_aweber').length) {
|
1088 |
$shell.find('.ppsSubscribeForm_aweber').submit(function(){
|
1089 |
if(jQuery(this).find('input[name=email]').val()) {
|
1090 |
ppsPopupSubscribeSuccess( popup );
|
1092 |
});
|
1093 |
}
|
1094 |
// Check build-in PopUp subscribe links
|
1095 |
+
if($shell.find('.ppsSmLink').length) {
|
1096 |
$shell.find('.ppsSmLink').click(function(){
|
1097 |
_ppsPopupSetActionDone(popup, 'share', jQuery(this).data('type'));
|
1098 |
});
|
1099 |
}
|
1100 |
// Check Social Share by Supsystic plugin links in PopUp
|
1101 |
+
if($shell.find('.supsystic-social-sharing').length) {
|
1102 |
$shell.find('.supsystic-social-sharing a').click(function(){
|
1103 |
var socHost = this.hostname
|
1104 |
, socType = ''; // Social network type key
|
1121 |
}
|
1122 |
});
|
1123 |
}
|
1124 |
+
if($shell.find('.fb_iframe_widget').length) {
|
1125 |
_ppsBindFbLikeBtnAction(popup);
|
1126 |
}
|
1127 |
/*For age verification templates*/
|
1299 |
for(var i = 0; i < ppsPopups.length; i++) {
|
1300 |
if(ppsPopups[ i ].params
|
1301 |
&& ppsPopups[ i ].params.tpl
|
1302 |
+
&& (parseInt(ppsPopups[ i ].params.tpl.sub_redirect_to_btn_url) || parseInt(ppsPopups[ i ].params.tpl.close_redirect_to_btn_url))
|
1303 |
) {
|
1304 |
+
var $btn = jQuery('[onclick*="ppsShowPopup('+ ppsPopups[ i ].id+ ')"]');
|
1305 |
+
ppsPopups[ i ] = _ppsSaveClickHref(ppsPopups[ i ], $btn);
|
1306 |
+
}
|
1307 |
+
}
|
1308 |
+
}
|
1309 |
+
function _ppsSaveClickHref(popup, $element) {
|
1310 |
+
if(popup.params
|
1311 |
+
&& popup.params.tpl
|
1312 |
+
&& $element
|
1313 |
+
&& $element.length
|
1314 |
+
) {
|
1315 |
+
var href = $element.attr('href');
|
1316 |
+
if(parseInt(popup.params.tpl.sub_redirect_to_btn_url)) {
|
1317 |
+
popup.params.sub_redirect_to_btn_url_href = href;
|
1318 |
+
}
|
1319 |
+
if(parseInt(popup.params.tpl.close_redirect_to_btn_url)) {
|
1320 |
+
popup.params.close_redirect_to_btn_url_href = href;
|
1321 |
}
|
1322 |
}
|
1323 |
+
return popup;
|
1324 |
}
|
1325 |
function ppsAddShowClb( id, clb ) {
|
1326 |
if(!g_ppsShowCallbacks[ id ]) {
|
modules/popup/js/frontend.popup.min.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
|
2 |
+
var g_ppsWindowLoaded=false,g_ppsIsPageCached=false,g_ppsIsPageCachedChecked=false,g_ppsShowCallbacks={},g_ppsClks={};jQuery(document).ready(function(){if(typeof(ppsPopupsFromFooter)!=="undefined"&&ppsPopupsFromFooter&&ppsPopupsFromFooter.length){ppsPopups=typeof(ppsPopups)==="undefined"?[]:ppsPopups;ppsPopups=ppsPopups.concat(ppsPopupsFromFooter)}jQuery(document).trigger("ppsBeforePopupsStartInit",ppsPopups);if(typeof(ppsPopups)!=="undefined"&&ppsPopups&&ppsPopups.length){ppsInitBgOverlay();jQuery(document).trigger("ppsBeforePopupsInit",ppsPopups);for(var a=0;a<ppsPopups.length;a++){jQuery("body").append(ppsPopups[a].rendered_html);ppsMovePopupStyles(ppsPopups[a]);ppsBindPopupLove(ppsPopups[a]);ppsBindPopupLoad(ppsPopups[a]);ppsBindPopupShow(ppsPopups[a]);ppsBindPopupActions(ppsPopups[a]);ppsBindPopupClose(ppsPopups[a]);ppsBindPopupSubscribers(ppsPopups[a]);ppsBindPopupForceShow(ppsPopups[a]);ppsCheckPopupGetNotices(ppsPopups[a])}_ppsBindOnElementClickPopups();_ppsBindClickHrefSaving();setTimeout(_ppsBindOnElementClickPopups,300);jQuery(document).trigger("ppsAfterPopupsInit",ppsPopups);jQuery(window).resize(function(){for(var b=0;b<ppsPopups.length;b++){if(ppsPopups[b].is_visible){_ppsPositionPopup({popup:ppsPopups[b]})}}});setTimeout(function(){g_ppsWindowLoaded=true},5000)}});jQuery(window).load(function(){g_ppsWindowLoaded=true;for(var a=0;a<ppsPopups.length;a++){if(ppsPopups[a].is_visible){_ppsPositionPopup({popup:ppsPopups[a]})}}});function _ppsAddPopUpClick(b,a){g_ppsClks[b]=a}function _ppsGetPopUpClick(a){return g_ppsClks[a]}function _ppsCheckPopupOnFollowClk(e){var a=e.href,d=e.hash,b=window.location.href,c=window.location.hash;if(d){if(d&&d!=""){a=str_replace(a,d,"")}if(c&&c!=""){b=str_replace(b,c,"")}if(strpos(a,"/",a.length-1)!==false){a=a.substr(0,a.length-1)}if(strpos(b,"/",b.length-1)!==false){b=b.substr(0,b.length-1)}if(b==a){setTimeout(function(){toeReload()},100)}}}function _ppsBindOnElementClickPopups(){var b=jQuery('[href*="#ppsShowPopUp_"]:not(.ppsClickBinded)');if(b&&b.size()){b.each(function(){jQuery(this).click(function(){var d=jQuery(this).attr("href");if(d&&d!=""){d=d.split("_");d=d[1]?parseInt(d[1]):0;if(d){var c=ppsGetPopupById(d);if(c&&c.params.main.show_on=="link_follow"){_ppsCheckPopupOnFollowClk(this);return true}_ppsAddPopUpClick(d,this);if(!_ppsPopupBindDelay(d,"show_on_click_on_el_delay","show_on_click_on_el_enb_delay")){ppsShowPopup(d)}}else{_ppsCheckPopupOnFollowClk(this);return true}}return false})}).addClass("ppsClickBinded")}var a=jQuery('[title*="#ppsShowPopUp_"]:not(.ppsClickBinded)');if(a&&a.size()){a.each(function(){var e=jQuery(this).attr("title"),c=e.match(/#ppsShowPopUp_(\d+)/);if(c&&c.length==2){var d=parseInt(c[1]);if(d){jQuery(this).data("popup-id",d).attr("title",str_replace(e,c[0],"")).click(function(){var f=jQuery(this).data("popup-id");_ppsAddPopUpClick(f,this);if(!_ppsPopupBindDelay(f,"show_on_click_on_el_delay","show_on_click_on_el_enb_delay")){ppsShowPopup(f)}return false})}}}).addClass("ppsClickBinded")}}function ppsMovePopupStyles(a){var b=jQuery('<style type="text/css" />'),c=jQuery("#ppsPopupStylesHidden_"+a.view_id);b.appendTo("body").html(c.html());c.remove()}function ppsBindPopupLove(b){if(parseInt(toeOptionPps("add_love_link"))){var a=ppsGetPopupShell(b);a.append(toeOptionPps("love_link_html"))}}function ppsBindPopupLoad(d){var e=jQuery(".ppsPopupPreloadImg_"+d.view_id);d._imgsCount=e.size();if(d._imgsCount){d._imgsLoaded=false;d._imgsLoadedCount=0;e.bind("load error",function(){d._imgsLoadedCount++;if(d._imgsLoadedCount>=d._imgsCount){d._imgsLoaded=true;var g=ppsGetPopupShell(d);g.trigger("ppsShowPopupAfterAllImgs",d)}})}else{if(toeInArrayPps(d.type,["iframe","pdf"])){d._imgsLoaded=false;var c=ppsGetPopupShell(d);c.find(".ppsMainFrame").bind("load error",function(){var g=d._imgsLoaded;d._imgsLoaded=true;if(!g){setTimeout(function(){c.trigger("ppsShowPopupAfterAllImgs",d)},1000)}})}else{d._imgsLoaded=true}}var c=ppsGetPopupShell(d),f=c.find("img"),b=f?f.size():0;if(b){if(d._imgsCount){var a=false;e.each(function(){var g=jQuery(this),h=g.attr("src");f.each(function(){var i=jQuery(this),j=i.attr("src");if(j==h){f=f.filter(this);a=true;return false}})});if(a){b=f.size()}}if(b){f.bind("load error",function(){b--;if(b<=0&&d.is_visible){_ppsPositionPopup({shell:c,popup:d,recalc:true})}})}}}function ppsBindPopupShow(a){_ppsCheckBindVideo({popup:a});switch(a.params.main.show_on){case"page_load":if(!_ppsPopupBindDelay(a,"show_on_page_load_delay","show_on_page_load_enb_delay")){if(a.type=="fb_like"){a.render_with_fb_load=true}else{ppsCheckShowPopup(a)}}break;case"click_on_page":jQuery(document).click(function(){if(!a.click_on_page_displayed){ppsCheckShowPopup(a);a.click_on_page_displayed=true}});break;case"click_on_element":break;case"scroll_window":jQuery(window).scroll(function(){if(parseInt(a.params.main.show_on_scroll_window_enb_perc_scroll)){var e=parseInt(a.params.main.show_on_scroll_window_perc_scroll);if(e){var h=jQuery(document).height(),b=jQuery(window).height(),c=jQuery(window).scrollTop(),g=h-b,f=c*100/g;if(g>0&&f<e){return}}}if(!a.scroll_window_displayed){var d=0;if(a.params.main.show_on_scroll_window_enb_delay&&parseInt(a.params.main.show_on_scroll_window_enb_delay)){a.params.main.show_on_scroll_window_delay=parseInt(a.params.main.show_on_scroll_window_delay);if(a.params.main.show_on_scroll_window_delay){d=a.params.main.show_on_scroll_window_delay*1000}}if(d){setTimeout(function(){ppsCheckShowPopup(a)},d)}else{ppsCheckShowPopup(a)}a.scroll_window_displayed=true}});break}}function ppsBindPopupClose(b){var a=ppsGetPopupShell(b);a.find(".ppsPopupClose").click(function(){ppsClosePopup(b);return false})}function ppsBindPopupSubscribers(b){if(b.params.tpl.enb_subscribe){var a=ppsGetPopupShell(b),d=a.find(".ppsSubscribeForm"),e=d.find(".ppsPopupClose");switch(b.params.tpl.sub_dest){case"aweber":break;case"wordpress":case"mailchimp":case"mailpoet":default:d.submit(function(){var g=jQuery(this).find("input[type=submit]"),h=this,i=jQuery(this).find(".ppsSubMsg");g.attr("disabled","disabled");jQuery(this).sendFormPps({msgElID:i,onSuccess:function(k){jQuery(h).find("input[type=submit]").removeAttr("disabled");if(!k.error){var j=jQuery(h).parents(".ppsSubscribeShell"),l=jQuery(h).find(".ppsPopupClose");if(l&&l.size()){l.appendTo(j)}i.appendTo(j);jQuery(h).animateRemovePps(300,function(){_ppsPositionPopup({shell:a,popup:b,recalc:true})});var n=a.find(".ppsHideAfterSubscribe");if(n&&n.size()){n.animateRemovePps(300)}ppsPopupSubscribeSuccess(b);var m=b.params.sub_redirect_to_btn_url_href?b.params.sub_redirect_to_btn_url_href:false;if(!m&&k.data&&k.data.redirect){m=k.data.redirect}if(m){toeRedirect(m,parseInt(b.params.tpl.sub_redirect_new_wnd))}}else{_ppsPopupAddStat(b,"subscribe_error");if(k.data&&k.data.emailExistsRedirect){ppsPopupSubscribeSuccess(b,{ignoreSendStat:true});toeRedirect(k.data.emailExistsRedirect)}}}});return false});break}if(e&&e.size()){e.keydown(function(g){if(g.keyCode==13){d.submit();return false}})}if(navigator.userAgent.indexOf("Safari")>-1&&!(navigator.userAgent.indexOf("Chrome")>-1)){var c=a.get(0).getElementsByTagName("form");if(c&&c.length){for(var f=0;f<c.length;f++){c[f].noValidate=true;c[f].addEventListener("submit",function(g){if(!g.target.checkValidity()){g.preventDefault();jQuery(this).find(".ppsSubMsg").addClass("ppsErrorMsg").html("Please fill-in all fields")}},false)}}}}}function ppsCheckShowPopup(b,e){if(isNumericPps(b)){b=ppsGetPopupById(b)}var h="pps_show_"+b.id,l=getCookiePps(h),n=b.params.main.show_to=="count_times",f="pps_times_showed_"+b.id,a=parseInt(getCookiePps(f));if(b.params.main.show_to=="first_time_visit"&&l){return}if(n&&l&&l!="1"){var g=(new Date(l)).getTime(),i=(new Date()).getTime();if(g){var m=(i-g)/1000,d=3600,k=parseInt(b.params.main.count_times_num);if(a&&k&&a>=k){if((b.params.main.count_times_mes=="hour"&&m<d)||(b.params.main.count_times_mes=="day"&&m<24*d)||(b.params.main.count_times_mes=="week"&&m<7*24*d)||(b.params.main.count_times_mes=="month"&&m<30*24*d)){return}if(a>=k){a=0}}}}if(!l||n){var j=parseInt(b.params.main.show_to_first_time_visit_days);j=isNaN(j)||n?30:j;if(!j){j=null}var c=n?(new Date()).toString():"1";setCookiePps("pps_show_"+b.id,c,j);if(n){setCookiePps(f,(a?a+1:1),30)}}var o=_ppsPopupGetActionDone(b);if(b.params.main.show_to=="until_make_action"&&o){return}if(_ppsCheckDisplayTime(b)){return}e=e||{};e.isUnique=l?0:1;ppsShowPopup(b,e);return false}function _ppsCheckDisplayTime(b){if(isNumericPps(b)){b=ppsGetPopupById(b)}if(b.params.main.enb_show_time&&b.params.main.show_time_from&&b.params.main.show_time_to&&b.params.main.show_time_from!=b.params.main.show_time_to){var f=function(i){var h=strpos(i,"pm")!==false?12:0;var g=parseFloat(str_replace(str_replace(str_replace(i,"am",""),"pm",""),":","."));if(toeInArray(g,[12,12.3])===-1){g+=h}else{if(!h){g-=12}}return g};var a=f(b.params.main.show_time_from),d=f(b.params.main.show_time_to),e=new Date(),c=e.getHours()+(e.getMinutes()/100);if(c<a||c>d){return true}}return false}function _ppsPopupGetActionDone(a){if(isNumericPps(a)){a=ppsGetPopupById(a)}var d="pps_actions_"+a.id,e=getCookiePps(d);if(e){if(a.type=="age_verify"&&e.age_verify&&a.params.opts_attrs.btns_number){var b=false;for(var c=0;c<a.params.opts_attrs.btns_number;c++){if(a.params.tpl["is_btn_primary_"+c]){if(c==e.age_verify){return true}b=true}}if(b){return false}}return true}return false}function _ppsPopupSetActionDone(b,d,c,g){g=g||{};if(isNumericPps(b)){b=ppsGetPopupById(b)}c=c!==null?c:"";var e="pps_actions_"+b.id,f=getCookiePps(e);if(!f){f={}}if(d=="age_verify"){f[d]=c}else{f[d]=1}var a=parseInt(b.params.main.show_to_until_make_action_days);a=isNaN(a)?30:a;if(!a){a=null}setCookiePps(e,f,a);if(!g.ignoreSendStat){_ppsPopupAddStat(b,d,c)}jQuery(document).trigger("ppsAfterPopupsActionDone",{popup:b,action:d,smType:c})}function _ppsPopupAddStat(a,d,b,c){if(a&&a.params&&a.params.tpl.dsbl_stats){return}jQuery.sendFormPps({msgElID:"noMessages",data:{mod:"statistics",action:"add",id:a.id,type:d,sm_type:b,is_unique:c,connect_hash:a.connect_hash}});jQuery(document).trigger("ppsAfterPopupsStatAdded",{popup:a,action:d,smType:b,is_unique:c})}function ppsShowPopUpOnClick(a,b){if(isNumericPps(a)){a=ppsGetPopupById(a)}_ppsSaveClickHref(a,jQuery(b));ppsShowPopup(a)}function ppsShowPopup(b,d){if(!ppsCorrectJqueryUsed()){ppsReloadCoreJs(ppsShowPopup,[b,d]);return}d=d||{};if(isNumericPps(b)){b=ppsGetPopupById(b)}var a=ppsGetPopupShell(b);if(!b._imgsLoaded){a.bind("ppsShowPopupAfterAllImgs",function(){ppsShowPopup(b,d)});return}a.data("view-id",b.view_id);if(_ppsCheckIsPageCached()){_ppsUpdatePopupNonces(b)}_ppsPopupAddStat(b,"show",0,d.isUnique);if(!d.ignoreBgOverlay){ppsShowBgOverlay(b)}if(g_ppsWindowLoaded&&!d.ignorePosition){_ppsPositionPopup({shell:a,popup:b})}if(b.params.tpl.anim&&!b.resized_for_wnd){_ppsHandlePopupAnimationShow(b,a)}else{a.show()}if(toeInArrayPps(b.type,["iframe"])){var c=a.find(".ppsMainFrame");if(c&&c.size()){c.css("width","auto");c.css("width","100%")}}_ppsCheckPlayVideo({popup:b,shell:a});_ppsIframesForReload({popup:b,shell:a});_ppsCheckInnerScripts({popup:b,shell:a});setTimeout(function(){_ppsCheckMap({popup:b,shell:a});_ppsSocialIcons({popup:b,shell:a});_ppsCheckContactForm({popup:b,shell:a});_ppsCheckVideos({popup:b,shell:a})},100);_ppsCheckPublication({popup:b,shell:a});if(b.params.tpl.dsbl_wnd_scroll){disableScrollPps("html");disableScrollPps("body")}b.is_visible=true;b.is_rendered=true;jQuery(document).trigger("ppsAfterPopupsActionShow",b);runShowClb(b,a);if(toeInArrayPps(b.type,["iframe"])){if(b.params.tpl.iframe_display_only&&b.params.tpl.iframe_display_only!=""&&typeof(_ppsIFrameDisplayOnly)=="function"&&!b.params.tpl._iframeDisplayOnlyBinded){_ppsIFrameDisplayOnly(b)}}}function _ppsCheckVideos(b){if(b.popup.type=="video"&&b.popup.params.tpl.video_type=="youtube"&&b.popup.params.tpl.video_autoplay){var a=b.shell.find("iframe:first");a.attr("src",a.attr("src")+"&autoplay=1")}}function _ppsHandlePopupAnimationShow(a,b){var c=a.params.tpl.anim.old?"magictime":"animated";b.animationDuration(a.params.tpl.anim_duration,true);b.removeClass(a.params.tpl.anim.hide_class);b.addClass(c+" "+a.params.tpl.anim.show_class).show();setTimeout(function(){b.removeClass(c+" "+a.params.tpl.anim.show_class)},parseInt(a.params.tpl.anim_duration))}function _ppsHandlePopupAnimationHide(a,b){var c=a.params.tpl.anim.old?"magictime":"animated";b.removeClass(a.params.tpl.anim.show_class).addClass(a.params.tpl.anim.hide_class);setTimeout(function(){b.removeClass(c).hide();ppsHideBgOverlay(a)},a.params.tpl.anim_duration)}function _ppsIframesForReload(c){var a=c.popup,b=c.shell?c.shell:ppsGetPopupShell(a);if(b.find("iframe")){b.find("iframe").each(function(){var d=jQuery(this).attr("src");if(d){if(d.indexOf("www.google.com/maps/embed")!==-1){this.src=this.src}}})}}function _ppsIsIframeForHide(e){e=e||{};if(e.popup.type=="video"){return true}var b=e.shell?e.shell:ppsGetPopupShell(e.popup),d=b?b.find("iframe"):false,a=false;if(d&&d.size()){var c=["youtube","vimeo","dtbaker"];d.each(function(){var f=jQuery(this).data("original-src"),h=jQuery(this).attr("src");if(h||f){for(var g=0;g<c.length;g++){if((h&&h.indexOf(c[g])!==-1)||(f&&f.indexOf(c[g])!==-1)){a=true;return false}}}})}return a}function _ppsCheckBindVideo(c){c=c||{};if(_ppsIsIframeForHide(c)){var a=c.shell?c.shell:ppsGetPopupShell(c.popup),b=a?a.find("iframe,video"):false;if(b&&b.size()){b.each(function(){jQuery(this).data("original-src",jQuery(this).attr("src"));jQuery(this).attr("src","")})}}}function _ppsCheckPlayVideo(c){c=c||{};if(_ppsIsIframeForHide(c)){var a=c.shell?c.shell:ppsGetPopupShell(c.popup),b=a?a.find("iframe,video"):false;if(b&&b.size()){b.each(function(){var d=jQuery(this).data("original-src"),e=jQuery(this).attr("src");if(d&&d!=""&&(!e||e=="")){jQuery(this).attr("src",d)}})}}}function _ppsCheckStopVideo(c){c=c||{};if(_ppsIsIframeForHide(c)){var a=c.shell?c.shell:ppsGetPopupShell(c.popup),b=a?a.find("iframe,video"):false;if(c.popup.params.tpl.video_extra_full_screen){return}if(b&&b.size()){b.each(function(){jQuery(this).attr("src","")})}}}function _ppsCheckInnerScripts(b){b=b||{};var a=b.shell?b.shell:ppsGetPopupShell(b.popup);var c=a.find("script");if(c&&c.size()){c.each(function(){var d=jQuery(this).attr("src");if(d&&d!=""){jQuery.getScript(d)}})}}function _ppsCheckMap(c){c=c||{};var a=c.shell?c.shell:ppsGetPopupShell(c.popup),b=a.find(".gmp_map_opts");if(b&&b.size()){if(typeof(gmpGetMapByViewId)==="undefined"){setTimeout(function(){_ppsCheckMap(c)},1000);return}b.each(function(){var d=jQuery(this).data("view-id"),e=gmpGetMapByViewId(d);if(e){e.fullRefresh?e.fullRefresh():e.refresh()}else{var f=gmpGetMapInfoByViewId(d);gmpInitMapOnPage(f)}})}}function _ppsCheckContactForm(b){b=b||{};var a=b.shell?b.shell:ppsGetPopupShell(b.popup),c=a.find(".cfsFormShell");if(c&&c.size()){if(typeof(g_cfsForms)==="undefined"){setTimeout(function(){_ppsCheckContactForm(b)},1000);return}if(typeof(cfsCheckInitForms)!=="undefined"){cfsCheckInitForms(a)}c.each(function(){var d=jQuery(this).attr("id"),e=g_cfsForms.getByViewHtmlId(d);if(e){e.refresh()}else{g_cfsForms.add(g_cfsForms.getFormDataByViewHtmlId(d))}})}}function _ppsSocialIcons(c){c=c||{};var b=c.shell?c.shell:ppsGetPopupShell(c.popup),a=b.find(".supsystic-social-sharing:not(.supsystic-social-sharing-loaded)");if(a&&a.size()&&typeof(window.initSupsysticSocialSharing)!=="undefined"){a.each(function(){window.initSupsysticSocialSharing(this)})}}function _ppsCheckPublication(c){c=c||{};var a=c.shell?c.shell:ppsGetPopupShell(c.popup),b=a.find(".dpsBookStageShell");if(b&&b.size()){b.each(function(){if(typeof(dpsBookMng)=="undefined"){dpsBookMng=new dpsBookManager()}var e=jQuery(this).find(".dpsBook").data("bookid"),d=dpsBookMng.getById(e);if(d){d.getHtml().turn("destroy");d.getStage().parent().html(d._baseHtml);d._init(true)}else{dpsInitBookOnPage(dpsBookInfoByTermId(e));dpsBindBookActions(e)}})}}function _ppsPositionPopup(s){s=s||{};s.popup=s.popup&&typeof(s.popup)!=="object"?ppsGetPopupById(s.popup):s.popup;var h=s.shell?s.shell:ppsGetPopupShell(s.popup);if(h){var t=s.wndWidth?s.wndWidth:jQuery(window).width(),p=s.wndHeight?s.wndHeight:jQuery(window).height(),m=h.outerWidth(),c=h.outerHeight(),q=false,k=false,r=false,b=t-10,i=p-10,n=1,f=h.hasClass("ppsResponsiveInside");if(c>=i&&!f&&!(s.popup&&s.popup._notResizeHeight)){var o=s.recalc?false:parseInt(h.data("init-height"));if(!o){o=c;h.data("init-height",o)}n=i/o;q=r=true}if(m>=b&&!f){var e=s.recalc?false:parseInt(h.data("init-width"));if(!e){e=m;h.data("init-width",e)}var a=b/e;if(a<n){n=a}q=k=true}if(q){if(s.popup.params.tpl.responsive_mode=="width_only"){if(k){var g=m-h.width();h.css({width:"calc(100% - "+(g+20)+"px)"})}else{var e=parseInt(h.data("init-width"));if(e&&e<b){h.css({width:e})}}if(r){h.css({position:"absolute"})}else{h.css({position:"fixed"})}}else{var l={left:"center",top:"center"};h.ppsZoom(n,l.left+" "+l.top)}h.data("resized",1);m=h.outerWidth();c=h.outerHeight()}else{if(h.data("resized")){if(s.popup.params.tpl.responsive_mode=="width_only"){var e=parseInt(h.data("init-width"));if(e&&e<b){h.css({width:e})}h.css({position:"fixed"})}}}s.popup.resized_for_wnd=q;jQuery(document).trigger("ppsResize",{popup:s.popup,shell:h,wndWidth:t,wndHeight:p});if(!h.positioned_outside){var d=(t-m)/2,j=(p-c)/2;d=d<0?0:d;j=j<0?0:j;if(k){d-=(e-e*a)/2}if(r&&s.popup.params.tpl.responsive_mode!="width_only"){j-=(o-o*n)/2}h.css({left:d,top:j})}}else{console.log("CAN NOT FIND POPUP SHELL TO RESIZE!")}}function ppsClosePopup(a){if(isNumericPps(a)){a=ppsGetPopupById(a)}var b=ppsGetPopupShell(a);if(a.params.tpl.anim){_ppsHandlePopupAnimationHide(a,b)}else{b.hide();ppsHideBgOverlay(a)}_ppsCheckStopVideo({shell:b,popup:a});if(a.params.tpl.dsbl_wnd_scroll){enableScrollPps("html");enableScrollPps("body")}if(parseInt(a.params.tpl.close_redirect_to_btn_url)&&a.params.close_redirect_to_btn_url_href){toeRedirect(a.params.close_redirect_to_btn_url_href,parseInt(a.params.tpl.reidrect_on_close_new_wnd))}else{if(a.params.tpl.reidrect_on_close&&a.params.tpl.reidrect_on_close!=""){toeRedirect(a.params.tpl.reidrect_on_close,parseInt(a.params.tpl.reidrect_on_close_new_wnd))}}_ppsPopupAddStat(a,"close");a.is_visible=false}function ppsGetPopupShell(a){if(isNumericPps(a)){a=ppsGetPopupById(a)}return jQuery("#ppsPopupShell_"+a.view_id)}function ppsGetPopupById(b){for(var a=0;a<ppsPopups.length;a++){if(ppsPopups[a].id==b){return ppsPopups[a]}}return false}function ppsGetPopupByViewId(a){for(var b=0;b<ppsPopups.length;b++){if(ppsPopups[b].view_id==a){return ppsPopups[b]}}return false}function ppsInitBgOverlay(){jQuery("body").append('<div id="ppsPopupBgOverlay" />');jQuery("#ppsPopupBgOverlay").click(function(){if(ppsPopups&&ppsPopups.length){for(var a=0;a<ppsPopups.length;a++){if(ppsPopups[a]&&ppsPopups[a].params&&ppsPopups[a].params.main&&ppsPopups[a].params.main.close_on&&ppsPopups[a].params.main.close_on=="overlay_click"){ppsClosePopup(ppsPopups[a])}}}})}function ppsShowBgOverlay(b){if(b&&isNumericPps(b)){b=ppsGetPopupById(b)}if(b.ignore_background){return}var a=jQuery("#ppsPopupBgOverlay");a.css({"background-position":"","background-repeat":"","background-attachment":"","-webkit-background-size":"","-moz-background-size":"","-o-background-size":"","background-size":"","background-color":"","background-url":""}).removeClass("ppsSnow");if(b&&b.params){if(typeof(b.params.tpl.bg_overlay_opacity)!=="undefined"){if(!b.params.tpl.bg_overlay_opacity||b.params.tpl.bg_overlay_opacity==""){b.params.tpl.bg_overlay_opacity=0}var c=parseFloat(b.params.tpl.bg_overlay_opacity);if(!isNaN(c)){a.css({opacity:c})}}if(typeof(b.params.tpl.bg_overlay_type)!=="undefined"){switch(b.params.tpl.bg_overlay_type){case"color":a.css({"background-color":b.params.tpl.bg_overlay_color});break;case"img":if(b.params.tpl.bg_overlay_img){switch(b.params.tpl.bg_overlay_img_pos){case"stretch":a.css({"background-position":"center center","background-repeat":"no-repeat","background-attachment":"fixed","-webkit-background-size":"cover","-moz-background-size":"cover","-o-background-size":"cover","background-size":"cover"});break;case"center":a.css({"background-position":"center center","background-repeat":"no-repeat","background-attachment":"scroll","-webkit-background-size":"auto","-moz-background-size":"auto","-o-background-size":"auto","background-size":"auto"});break;case"tile":a.css({"background-position":"left top","background-repeat":"repeat","background-attachment":"scroll","-webkit-background-size":"auto","-moz-background-size":"auto","-o-background-size":"auto","background-size":"auto"});break}a.css({"background-image":'url("'+b.params.tpl.bg_overlay_img+'")'})}break;case"snow":a.addClass("ppsSnow");break}}}a.show()}function ppsHideBgOverlay(a){if(a&&isNumericPps(a)){a=ppsGetPopupById(a)}if(a.ignore_background){return}jQuery("#ppsPopupBgOverlay").hide()}function ppsBindPopupActions(b){var a=ppsGetPopupShell(b);if(a.find(".ppsSubscribeForm_aweber").length){a.find(".ppsSubscribeForm_aweber").submit(function(){if(jQuery(this).find("input[name=email]").val()){ppsPopupSubscribeSuccess(b)}})}if(a.find(".ppsSmLink").length){a.find(".ppsSmLink").click(function(){_ppsPopupSetActionDone(b,"share",jQuery(this).data("type"))})}if(a.find(".supsystic-social-sharing").length){a.find(".supsystic-social-sharing a").click(function(){var d=this.hostname,e="";if(d&&d!=""){switch(d){case"www.facebook.com":e="facebook";break;case"plus.google.com":e="googleplus";break;case"twitter.com":e="twitter";break;default:e=d;break}_ppsPopupSetActionDone(b,"share",e)}})}if(a.find(".fb_iframe_widget").length){_ppsBindFbLikeBtnAction(b)}if(b.type=="age_verify"){var c=a.find(".ppsBtn");if(c&&c.size()){c.click(function(){var e=jQuery(this).attr("class").split(" "),f=0;if(e&&e.length){for(var d=0;d<e.length;d++){if(e[d].indexOf("ppsBtn_")===0){f=parseInt(e[d].split("_")[1]);break}}}_ppsPopupSetActionDone(b,"age_verify",f)})}}}function _ppsBindFbLikeBtnAction(a){if(typeof(FB)==="undefined"){setTimeout(function(){_ppsBindFbLikeBtnAction(a)},500);return}FB.Event.subscribe("edge.create",function(b){_ppsPopupSetActionDone(a,"fb_like")});FB.Event.subscribe("xfbml.render",function(b){setTimeout(function(){setTimeout(function(){_ppsPositionPopup({popup:a})},1000);if(a.render_with_fb_load){ppsCheckShowPopup(a);_ppsPositionPopup({popup:a})}else{_ppsPositionPopup({popup:a})}},1000)})}function ppsPopupSubscribeSuccess(a,b){if(a&&isNumericPps(a)){a=ppsGetPopupById(a)}_ppsPopupSetActionDone(a,"subscribe",false,b)}function _ppsPopupBindDelay(a,d,c){if(a&&isNumericPps(a)){a=ppsGetPopupById(a)}var b=(a.params.main[c]&&parseInt(a.params.main[c])&&parseInt(a.params.main[d]))?(parseInt(a.params.main[d])*1000):0;if(b){if(d=="show_on_page_load_delay"&&parseInt(a.params.main.enb_page_load_global_delay)){a.start_time=(new Date).getTime();_ppsPopupBindUnloadDelay(d,a);var e=parseInt(getCookiePps("pps_un_"+d+"_"+a.id));if(e&&e>0){b-=e;if(b<0){b=0}}}setTimeout(function(){ppsCheckShowPopup(a)},b);return true}return false}function _ppsPopupBindUnloadDelay(b,a){jQuery(window).unload(function(){var c=a.is_rendered?0:(new Date()).getTime()-a.start_time;setCookiePps("pps_un_"+b+"_"+a.id,c)})}function ppsBindPopupForceShow(a){if(a.params.main.show_on!="link_follow"){var b=toeGetHashParams();if(b&&b.length&&toeInArray("ppsShowPopUp_"+a.id,b)!==-1){ppsCheckShowPopup(a)}}}function ppsCheckPopupGetNotices(a){var c={errors:getDataLcs("ppsErrors"),messages:getDataLcs("ppsMsgs")};if(c.errors){c.error=true}if(c.errors||c.messages){var b=ppsGetPopupShell(a);toeProcessAjaxResponsePps(c,b.find(".ppsSubMsg"))}}function _ppsCheckIsPageCached(){if(g_ppsIsPageCachedChecked){return g_ppsIsPageCached}jQuery("*:not(iframe,video,object)").contents().filter(function(){return this.nodeType==8}).each(function(a,b){if(b.nodeValue&&(b.nodeValue.indexOf("Performance optimized by W3 Total Cache")!==-1||b.nodeValue.indexOf("Cached page generated by WP-Super-Cache")!==-1)){g_ppsIsPageCached=true;return false}});g_ppsIsPageCachedChecked=true;return g_ppsIsPageCached}function _ppsUpdatePopupNonces(b){if(!b._nonces_updated){var a=ppsGetPopupShell(b),e=a.find("form"),d=[],c=["ppsSubscribeForm","ppsLoginForm","ppsRegForm"];if(e&&e.size()){e.each(function(){for(var f=0;f<c.length;f++){if(jQuery(this).hasClass(c[f])){d.push(c[f])}}})}if(d&&d.length){jQuery.sendFormPps({msgElID:"noMessages",data:{mod:"popup",action:"updateNonce",id:b.id,get_for:d},onSuccess:function(g){if(!g.error&&g.data.update_for){var f=ppsGetPopupShell(b);for(var h in g.data.update_for){f.find("."+h).find('input[name="_wpnonce"]').val(g.data.update_for[h])}}}})}b._nonces_updated=true}}function _ppsBindClickHrefSaving(){for(var a=0;a<ppsPopups.length;a++){if(ppsPopups[a].params&&ppsPopups[a].params.tpl&&(parseInt(ppsPopups[a].params.tpl.sub_redirect_to_btn_url)||parseInt(ppsPopups[a].params.tpl.close_redirect_to_btn_url))){var b=jQuery('[onclick*="ppsShowPopup('+ppsPopups[a].id+')"]');ppsPopups[a]=_ppsSaveClickHref(ppsPopups[a],b)}}}function _ppsSaveClickHref(b,a){if(b.params&&b.params.tpl&&a&&a.length){var c=a.attr("href");if(parseInt(b.params.tpl.sub_redirect_to_btn_url)){b.params.sub_redirect_to_btn_url_href=c}if(parseInt(b.params.tpl.close_redirect_to_btn_url)){b.params.close_redirect_to_btn_url_href=c}}return b}function ppsAddShowClb(b,a){if(!g_ppsShowCallbacks[b]){g_ppsShowCallbacks[b]=[]}g_ppsShowCallbacks[b].push(a)}function runShowClb(a,c){if(a&&isNumericPps(a)){a=ppsGetPopupById(a)}if(g_ppsShowCallbacks[a.id]&&g_ppsShowCallbacks[a.id].length){for(var b=0;b<g_ppsShowCallbacks[a.id].length;b++){if(typeof(g_ppsShowCallbacks[a.id][b])==="function"){g_ppsShowCallbacks[a.id][b](a,c)}}}};
|
modules/popup/mod.php
CHANGED
@@ -133,6 +133,7 @@ class popupPps extends modulePps {
|
|
133 |
if(is_object($post) && isset($post->post_content)) {
|
134 |
if((preg_match_all('/\[\s*'. PPS_SHORTCODE_CLICK. '.+id\s*\=.*(?P<POPUP_ID>\d+)\]/iUs', $post->post_content, $matches)
|
135 |
|| preg_match_all('/ppsShowPopup\s*\(\s*(?P<POPUP_ID>\d+)\s*\)\s*;*/iUs', $post->post_content, $matches)
|
|
|
136 |
|| preg_match_all('/\"\#ppsShowPopUp_(?P<POPUP_ID>\d+)\"/iUs', $post->post_content, $matches)
|
137 |
|| preg_match_all('/ppsCheckShowPopup\s*\(\s*(?P<POPUP_ID>\d+)\s*\)\s*;*/iUs', $post->post_content, $matches)
|
138 |
) && isset($matches['POPUP_ID'])
|
@@ -314,7 +315,8 @@ class popupPps extends modulePps {
|
|
314 |
'sub_sga_id', 'sub_sga_list_id', 'sub_sga_activate_code', 'sub_gr_api_key', 'sub_ac_api_url', 'sub_ac_api_key',
|
315 |
'sub_ac_lists', 'sub_mr_lists', 'sub_gr_api_key', 'sub_gr_lists', 'cycle_day', 'sub_ic_app_id', 'sub_ic_app_user', 'sub_ic_app_pass', 'sub_ic_lists',
|
316 |
'sub_ck_api_key', 'sub_mem_acc_id', 'sub_mem_pud_key', 'sub_mem_priv_key', 'sub_4d_name', 'sub_4d_pass', 'sub_ymlp_api_key', 'sub_ymlp_name',
|
317 |
-
'sub_vtig_url', 'sub_vtig_name', 'sub_vtig_key', 'sub_v6_api_key', 'sub_dms_api_user', 'sub_dms_api_password'
|
|
|
318 |
foreach($popups as $i => $p) {
|
319 |
if(isset($p['params']['tpl']['anim_key']) && !empty($p['params']['tpl']['anim_key']) && $p['params']['tpl']['anim_key'] != 'none') {
|
320 |
$popups[ $i ]['params']['tpl']['anim'] = $this->getView()->getAnimationByKey( $p['params']['tpl']['anim_key'] );
|
@@ -338,9 +340,10 @@ class popupPps extends modulePps {
|
|
338 |
}
|
339 |
if(!$renderedBefore) {
|
340 |
framePps::_()->getModule('templates')->loadCoreJs();
|
341 |
-
|
|
|
342 |
framePps::_()->addJSVar('frontend.popup', $jsListVarName, $popups);
|
343 |
-
framePps::_()->addStyle('frontend.popup', $this->getModPath(). 'css/frontend.popup.css');
|
344 |
// Detect what animation library should be loaded. Be advised that they can be used both in same time.
|
345 |
$loadOldAnims = $loadNewAnims = false;
|
346 |
foreach($popups as $p) {
|
133 |
if(is_object($post) && isset($post->post_content)) {
|
134 |
if((preg_match_all('/\[\s*'. PPS_SHORTCODE_CLICK. '.+id\s*\=.*(?P<POPUP_ID>\d+)\]/iUs', $post->post_content, $matches)
|
135 |
|| preg_match_all('/ppsShowPopup\s*\(\s*(?P<POPUP_ID>\d+)\s*\)\s*;*/iUs', $post->post_content, $matches)
|
136 |
+
|| preg_match_all('/ppsShowPopUpOnClick\s*\(\s*(?P<POPUP_ID>\d+)\s*\,\s*this/iUs', $post->post_content, $matches)
|
137 |
|| preg_match_all('/\"\#ppsShowPopUp_(?P<POPUP_ID>\d+)\"/iUs', $post->post_content, $matches)
|
138 |
|| preg_match_all('/ppsCheckShowPopup\s*\(\s*(?P<POPUP_ID>\d+)\s*\)\s*;*/iUs', $post->post_content, $matches)
|
139 |
) && isset($matches['POPUP_ID'])
|
315 |
'sub_sga_id', 'sub_sga_list_id', 'sub_sga_activate_code', 'sub_gr_api_key', 'sub_ac_api_url', 'sub_ac_api_key',
|
316 |
'sub_ac_lists', 'sub_mr_lists', 'sub_gr_api_key', 'sub_gr_lists', 'cycle_day', 'sub_ic_app_id', 'sub_ic_app_user', 'sub_ic_app_pass', 'sub_ic_lists',
|
317 |
'sub_ck_api_key', 'sub_mem_acc_id', 'sub_mem_pud_key', 'sub_mem_priv_key', 'sub_4d_name', 'sub_4d_pass', 'sub_ymlp_api_key', 'sub_ymlp_name',
|
318 |
+
'sub_vtig_url', 'sub_vtig_name', 'sub_vtig_key', 'sub_v6_api_key', 'sub_dms_api_user', 'sub_dms_api_password',
|
319 |
+
'capt_site_key', 'capt_secret_key', 'sub_mm_username', 'sub_mm_api_key', 'sub_mm_lists');
|
320 |
foreach($popups as $i => $p) {
|
321 |
if(isset($p['params']['tpl']['anim_key']) && !empty($p['params']['tpl']['anim_key']) && $p['params']['tpl']['anim_key'] != 'none') {
|
322 |
$popups[ $i ]['params']['tpl']['anim'] = $this->getView()->getAnimationByKey( $p['params']['tpl']['anim_key'] );
|
340 |
}
|
341 |
if(!$renderedBefore) {
|
342 |
framePps::_()->getModule('templates')->loadCoreJs();
|
343 |
+
$assetSuf = PPS_MINIFY_ASSETS ? '.min' : '';
|
344 |
+
framePps::_()->addScript('frontend.popup', $this->getModPath(). 'js/frontend.popup'. $assetSuf. '.js');
|
345 |
framePps::_()->addJSVar('frontend.popup', $jsListVarName, $popups);
|
346 |
+
framePps::_()->addStyle('frontend.popup', $this->getModPath(). 'css/frontend.popup'. $assetSuf. '.css');
|
347 |
// Detect what animation library should be loaded. Be advised that they can be used both in same time.
|
348 |
$loadOldAnims = $loadNewAnims = false;
|
349 |
foreach($popups as $p) {
|
modules/popup/views/popup.php
CHANGED
@@ -345,7 +345,7 @@ class popupViewPps extends viewPps {
|
|
345 |
'tabs' => array(
|
346 |
'label' => __('Tabs to render', PPS_LANG_CODE),
|
347 |
'html' => 'selectlist',
|
348 |
-
'def' => array('timeline'),
|
349 |
'options' => array('timeline' => __('Timeline', PPS_LANG_CODE), 'events' => __('Events', PPS_LANG_CODE), 'messages' => __('Messages', PPS_LANG_CODE)),
|
350 |
'desc' => __('Tabs to render i.e. timeline, events, messages. You can select several tabs here.', PPS_LANG_CODE)),
|
351 |
'hide_cover' => array(
|
@@ -619,9 +619,16 @@ class popupViewPps extends viewPps {
|
|
619 |
$styles = array(
|
620 |
'background-image' => 'url("'. $bullets['img_url']. '");'
|
621 |
);
|
622 |
-
if(isset($bullets['add_style']))
|
|
|
|
|
|
|
623 |
$styles = array_merge($styles, $bullets['add_style']);
|
|
|
624 |
if(function_exists('is_rtl') && is_rtl()) {
|
|
|
|
|
|
|
625 |
$styles = array_merge($styles, $bullets['rtl_style']);
|
626 |
}
|
627 |
return '#ppsPopupShell_'. $popup['view_id']. ' ul li { '. utilsPps::arrToCss($styles). ' }';
|
345 |
'tabs' => array(
|
346 |
'label' => __('Tabs to render', PPS_LANG_CODE),
|
347 |
'html' => 'selectlist',
|
348 |
+
//'def' => array('timeline'), //no default value for now - let it be empty
|
349 |
'options' => array('timeline' => __('Timeline', PPS_LANG_CODE), 'events' => __('Events', PPS_LANG_CODE), 'messages' => __('Messages', PPS_LANG_CODE)),
|
350 |
'desc' => __('Tabs to render i.e. timeline, events, messages. You can select several tabs here.', PPS_LANG_CODE)),
|
351 |
'hide_cover' => array(
|
619 |
$styles = array(
|
620 |
'background-image' => 'url("'. $bullets['img_url']. '");'
|
621 |
);
|
622 |
+
if(isset($bullets['add_style'])) {
|
623 |
+
foreach($bullets['add_style'] as $i => $s) {
|
624 |
+
$bullets['add_style'][ $i ] = $s. ' !important';
|
625 |
+
}
|
626 |
$styles = array_merge($styles, $bullets['add_style']);
|
627 |
+
}
|
628 |
if(function_exists('is_rtl') && is_rtl()) {
|
629 |
+
foreach($bullets['rtl_style'] as $i => $s) {
|
630 |
+
$bullets['rtl_style'][ $i ] = $s. ' !important';
|
631 |
+
}
|
632 |
$styles = array_merge($styles, $bullets['rtl_style']);
|
633 |
}
|
634 |
return '#ppsPopupShell_'. $popup['view_id']. ' ul li { '. utilsPps::arrToCss($styles). ' }';
|
modules/popup/views/tpl/popupEditAdminDesignOpts.php
CHANGED
@@ -131,9 +131,13 @@
|
|
131 |
? $this->popup['params']['tpl']['fb_like_opts'][ $fKey ]
|
132 |
: (isset($fData['def']) ? $fData['def'] : '');
|
133 |
}
|
|
|
134 |
if($fKey == 'href') {
|
135 |
$htmlParams['attrs'] = 'style="width: 100%"';
|
136 |
}
|
|
|
|
|
|
|
137 |
?>
|
138 |
<tr>
|
139 |
<th scope="row" class="col-w-1perc">
|
@@ -347,6 +351,11 @@
|
|
347 |
'checked' => htmlPps::checkedOpt($this->popup['params']['tpl'], 'reidrect_on_close_new_wnd')))?>
|
348 |
<?php _e('Open in a new window (tab)', PPS_LANG_CODE)?>
|
349 |
</label>
|
|
|
|
|
|
|
|
|
|
|
350 |
</td>
|
351 |
</tr>
|
352 |
<?php if(in_array($this->popup['type'], array(PPS_IFRAME))) {?>
|
131 |
? $this->popup['params']['tpl']['fb_like_opts'][ $fKey ]
|
132 |
: (isset($fData['def']) ? $fData['def'] : '');
|
133 |
}
|
134 |
+
$htmlParams['attrs'] = '';
|
135 |
if($fKey == 'href') {
|
136 |
$htmlParams['attrs'] = 'style="width: 100%"';
|
137 |
}
|
138 |
+
if(in_array($html, array('selectlist'))) {
|
139 |
+
$htmlParams['attrs'] = 'class="chosen" data-placeholder="'. __('Select Tabs to Render', PPS_LANG_CODE). '"';
|
140 |
+
}
|
141 |
?>
|
142 |
<tr>
|
143 |
<th scope="row" class="col-w-1perc">
|
351 |
'checked' => htmlPps::checkedOpt($this->popup['params']['tpl'], 'reidrect_on_close_new_wnd')))?>
|
352 |
<?php _e('Open in a new window (tab)', PPS_LANG_CODE)?>
|
353 |
</label>
|
354 |
+
<label class="supsystic-tooltip" title="<?php _e('If you set PopUp to Show On -> Click on certain link, and this link have href parameter - you can redirect your users there after PopUp close.', PPS_LANG_CODE)?>">
|
355 |
+
<?php echo htmlPps::checkbox('params[tpl][close_redirect_to_btn_url]', array(
|
356 |
+
'checked' => htmlPps::checkedOpt($this->popup['params']['tpl'], 'close_redirect_to_btn_url')))?>
|
357 |
+
<?php _e('Redirect to button URL', PPS_LANG_CODE)?>
|
358 |
+
</label>
|
359 |
</td>
|
360 |
</tr>
|
361 |
<?php if(in_array($this->popup['type'], array(PPS_IFRAME))) {?>
|
modules/popup/views/tpl/popupEditAdminMainOpts.php
CHANGED
@@ -65,7 +65,7 @@
|
|
65 |
<br />
|
66 |
<?php _e('Or, if you know HTML basics, - you can insert "onclick" attribute to any of your element from code below', PPS_LANG_CODE)?>:<br />
|
67 |
<?php echo htmlPps::text('ppsCopyTextCode', array(
|
68 |
-
'value' => esc_html('onclick="
|
69 |
'attrs' => 'data-parent-selector=".ppsPopupMainOptSect" class="ppsCopyTextCode"'));?><br />
|
70 |
<?php _e('Or you can even use it for your Menu item, just add code', PPS_LANG_CODE)?>:<br />
|
71 |
<?php echo htmlPps::text('ppsCopyTextCode', array(
|
@@ -254,7 +254,25 @@
|
|
254 |
<span class="supsystic-tooltip-right" title="<?php echo esc_html(__('If enabled - this will show PopUp in admin area too - like on frontend.', PPS_LANG_CODE))?>">
|
255 |
<?php _e('Show in Admin Area', PPS_LANG_CODE)?>
|
256 |
</span>
|
257 |
-
</label
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
</section>
|
259 |
<section class="ppsPopupMainOptSect">
|
260 |
<span class="ppsOptLabel"><?php _e('When to close PopUp', PPS_LANG_CODE)?></span>
|
65 |
<br />
|
66 |
<?php _e('Or, if you know HTML basics, - you can insert "onclick" attribute to any of your element from code below', PPS_LANG_CODE)?>:<br />
|
67 |
<?php echo htmlPps::text('ppsCopyTextCode', array(
|
68 |
+
'value' => esc_html('onclick="ppsShowPopUpOnClick('. $this->popup['id'] .', this); return false;"'),
|
69 |
'attrs' => 'data-parent-selector=".ppsPopupMainOptSect" class="ppsCopyTextCode"'));?><br />
|
70 |
<?php _e('Or you can even use it for your Menu item, just add code', PPS_LANG_CODE)?>:<br />
|
71 |
<?php echo htmlPps::text('ppsCopyTextCode', array(
|
254 |
<span class="supsystic-tooltip-right" title="<?php echo esc_html(__('If enabled - this will show PopUp in admin area too - like on frontend.', PPS_LANG_CODE))?>">
|
255 |
<?php _e('Show in Admin Area', PPS_LANG_CODE)?>
|
256 |
</span>
|
257 |
+
</label><br />
|
258 |
+
<label class="ppsPopupMainOptLbl" data-name="Visit several Pages">
|
259 |
+
<?php echo htmlPps::radiobutton('params[main][show_on]', array(
|
260 |
+
'attrs' => 'class="ppsProOpt"',
|
261 |
+
'value' => 'visit_several_pages',
|
262 |
+
'checked' => htmlPps::checkedOpt($this->popup['params']['main'], 'show_on', 'visit_several_pages')))?>
|
263 |
+
<span class="supsystic-tooltip-right" title="<?php echo esc_html(__('PopUp will appear after your site visitor will visit required pages number on your site.', PPS_LANG_CODE))?>">
|
264 |
+
<?php _e('Visit several Pages', PPS_LANG_CODE)?>
|
265 |
+
</span>
|
266 |
+
<?php if(!$this->isPro) {?>
|
267 |
+
<span class="ppsProOptMiniLabel"><a target="_blank" href="<?php echo framePps::_()->getModule('supsystic_promo')->generateMainLink('utm_source=plugin&utm_medium=visit_several_pages&utm_campaign=popup');?>"><?php _e('PRO option', PPS_LANG_CODE)?></a></span>
|
268 |
+
<?php }?>
|
269 |
+
</label><br />
|
270 |
+
<div id="ppsOptDesc_params_main_show_on_visit_several_pages" style="display: none;" class="ppsOptDescParamsShell supsystic-tooltip-right" title="<?php _e('Enter here number of pages that need to be visited by user before PopUp will be shown.', PPS_LANG_CODE)?>">
|
271 |
+
<?php _e('Pages number to visit', PPS_LANG_CODE)?>:<br />
|
272 |
+
<?php echo htmlPps::text('params[main][visit_page_cnt]', array(
|
273 |
+
'value' => isset($this->popup['params']['main']['visit_page_cnt']) ? $this->popup['params']['main']['visit_page_cnt'] : '',
|
274 |
+
'attrs' => 'class=""'));?>
|
275 |
+
</div><br />
|
276 |
</section>
|
277 |
<section class="ppsPopupMainOptSect">
|
278 |
<span class="ppsOptLabel"><?php _e('When to close PopUp', PPS_LANG_CODE)?></span>
|
modules/popup/views/tpl/popupEditAdminSubOpts.php
CHANGED
@@ -246,6 +246,7 @@
|
|
246 |
'ymlp' => array('label' => __('Your Mailing List Provider (Ymlp)', PPS_LANG_CODE)),
|
247 |
'fourdem' => array('label' => __('4Dem.it', PPS_LANG_CODE)),
|
248 |
'dotmailer' => array('label' => __('Dotmailer', PPS_LANG_CODE)),
|
|
|
249 |
);
|
250 |
?>
|
251 |
<script type="text/javascript">
|
@@ -382,6 +383,48 @@
|
|
382 |
</span>
|
383 |
<?php }?>
|
384 |
</label>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
</fieldset>
|
386 |
</div>
|
387 |
<table class="form-table ppsSubShellOptsTbl">
|
@@ -478,7 +521,6 @@
|
|
478 |
<?php echo htmlPps::checkbox('params[tpl][sub_redirect_to_btn_url]', array(
|
479 |
'checked' => htmlPps::checkedOpt($this->popup['params']['tpl'], 'sub_redirect_to_btn_url')))?>
|
480 |
<?php _e('Redirect to button URL', PPS_LANG_CODE)?>
|
481 |
-
|
482 |
</label>
|
483 |
</td>
|
484 |
</tr>
|
246 |
'ymlp' => array('label' => __('Your Mailing List Provider (Ymlp)', PPS_LANG_CODE)),
|
247 |
'fourdem' => array('label' => __('4Dem.it', PPS_LANG_CODE)),
|
248 |
'dotmailer' => array('label' => __('Dotmailer', PPS_LANG_CODE)),
|
249 |
+
'madmimi' => array('label' => __('Mad Mimi', PPS_LANG_CODE)),
|
250 |
);
|
251 |
?>
|
252 |
<script type="text/javascript">
|
383 |
</span>
|
384 |
<?php }?>
|
385 |
</label>
|
386 |
+
<div style="clear: both;"></div>
|
387 |
+
<div class="ppsReCaptchaShell">
|
388 |
+
<label>
|
389 |
+
<?php echo htmlPps::checkbox('params[tpl][enb_captcha]', array(
|
390 |
+
'checked' => htmlPps::checkedOpt($this->popup['params']['tpl'], 'enb_captcha'),
|
391 |
+
'attrs' => 'class="ppsProOpt"',
|
392 |
+
))?>
|
393 |
+
<?php _e('Re-Captcha', PPS_LANG_CODE)?>
|
394 |
+
</label>
|
395 |
+
<?php if(!$this->isPro) {?>
|
396 |
+
<span class="ppsProOptMiniLabel" style="margin-bottom: 0; margin-top: -5px;">
|
397 |
+
<a target="_blank" href="<?php echo framePps::_()->getModule('supsystic_promo')->generateMainLink('utm_source=plugin&utm_medium=re_captcha&utm_campaign=popup');?>"><?php _e('PRO option', PPS_LANG_CODE)?></a>
|
398 |
+
</span>
|
399 |
+
<?php } else { ?>
|
400 |
+
<div class="ppsReCaptchaOptsShell">
|
401 |
+
<table class="form-table ppsSubShellOptsTbl">
|
402 |
+
<tr>
|
403 |
+
<th scope="row">
|
404 |
+
<?php _e('ReCaptcha Site Key', PPS_LANG_CODE)?>
|
405 |
+
<i class="fa fa-question supsystic-tooltip" title="<?php echo esc_html(sprintf(__('Your site key, generated on <a href="%s" target="_blank">%s</a>.', PPS_LANG_CODE), 'https://www.google.com/recaptcha/admin#list', 'https://www.google.com/recaptcha/admin#list'))?>"></i>
|
406 |
+
</th>
|
407 |
+
<td>
|
408 |
+
<?php echo htmlPps::text('params[tpl][capt_site_key]', array(
|
409 |
+
'value' => (isset($this->popup['params']['tpl']['capt_site_key']) ? $this->popup['params']['tpl']['capt_site_key'] : ''),
|
410 |
+
))?>
|
411 |
+
</td>
|
412 |
+
</tr>
|
413 |
+
<tr>
|
414 |
+
<th scope="row">
|
415 |
+
<?php _e('ReCaptcha Secret Key', PPS_LANG_CODE)?>
|
416 |
+
<i class="fa fa-question supsystic-tooltip" title="<?php echo esc_html(sprintf(__('Your secret key, generated on <a href="%s" target="_blank">%s</a>.', PPS_LANG_CODE), 'https://www.google.com/recaptcha/admin#list', 'https://www.google.com/recaptcha/admin#list'))?>"></i>
|
417 |
+
</th>
|
418 |
+
<td>
|
419 |
+
<?php echo htmlPps::text('params[tpl][capt_secret_key]', array(
|
420 |
+
'value' => (isset($this->popup['params']['tpl']['capt_secret_key']) ? $this->popup['params']['tpl']['capt_secret_key'] : ''),
|
421 |
+
))?>
|
422 |
+
</td>
|
423 |
+
</tr>
|
424 |
+
</table>
|
425 |
+
</div>
|
426 |
+
<?php } ?>
|
427 |
+
</div>
|
428 |
</fieldset>
|
429 |
</div>
|
430 |
<table class="form-table ppsSubShellOptsTbl">
|
521 |
<?php echo htmlPps::checkbox('params[tpl][sub_redirect_to_btn_url]', array(
|
522 |
'checked' => htmlPps::checkedOpt($this->popup['params']['tpl'], 'sub_redirect_to_btn_url')))?>
|
523 |
<?php _e('Redirect to button URL', PPS_LANG_CODE)?>
|
|
|
524 |
</label>
|
525 |
</td>
|
526 |
</tr>
|
modules/subscribe/classes/Batch.php
CHANGED
@@ -1,150 +1,150 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* A MailChimp Batch operation.
|
4 |
-
* http://developer.mailchimp.com/documentation/mailchimp/reference/batches/
|
5 |
-
*
|
6 |
-
* @author Drew McLellan <drew.mclellan@gmail.com>
|
7 |
-
*/
|
8 |
-
class Batch
|
9 |
-
{
|
10 |
-
private $MailChimp;
|
11 |
-
|
12 |
-
private $operations = array();
|
13 |
-
private $batch_id;
|
14 |
-
|
15 |
-
public function __construct(MailChimp $MailChimp, $batch_id = null)
|
16 |
-
{
|
17 |
-
$this->MailChimp = $MailChimp;
|
18 |
-
$this->batch_id = $batch_id;
|
19 |
-
}
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Add an HTTP DELETE request operation to the batch - for deleting data
|
23 |
-
* @param string $id ID for the operation within the batch
|
24 |
-
* @param string $method URL of the API request method
|
25 |
-
* @return void
|
26 |
-
*/
|
27 |
-
public function delete($id, $method)
|
28 |
-
{
|
29 |
-
$this->queueOperation('DELETE', $id, $method);
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Add an HTTP GET request operation to the batch - for retrieving data
|
34 |
-
* @param string $id ID for the operation within the batch
|
35 |
-
* @param string $method URL of the API request method
|
36 |
-
* @param array $args Assoc array of arguments (usually your data)
|
37 |
-
* @return void
|
38 |
-
*/
|
39 |
-
public function get($id, $method, $args = array())
|
40 |
-
{
|
41 |
-
$this->queueOperation('GET', $id, $method, $args);
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Add an HTTP PATCH request operation to the batch - for performing partial updates
|
46 |
-
* @param string $id ID for the operation within the batch
|
47 |
-
* @param string $method URL of the API request method
|
48 |
-
* @param array $args Assoc array of arguments (usually your data)
|
49 |
-
* @return void
|
50 |
-
*/
|
51 |
-
public function patch($id, $method, $args = array())
|
52 |
-
{
|
53 |
-
$this->queueOperation('PATCH', $id, $method, $args);
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Add an HTTP POST request operation to the batch - for creating and updating items
|
58 |
-
* @param string $id ID for the operation within the batch
|
59 |
-
* @param string $method URL of the API request method
|
60 |
-
* @param array $args Assoc array of arguments (usually your data)
|
61 |
-
* @return void
|
62 |
-
*/
|
63 |
-
public function post($id, $method, $args = array())
|
64 |
-
{
|
65 |
-
$this->queueOperation('POST', $id, $method, $args);
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Add an HTTP PUT request operation to the batch - for creating new items
|
70 |
-
* @param string $id ID for the operation within the batch
|
71 |
-
* @param string $method URL of the API request method
|
72 |
-
* @param array $args Assoc array of arguments (usually your data)
|
73 |
-
* @return void
|
74 |
-
*/
|
75 |
-
public function put($id, $method, $args = array())
|
76 |
-
{
|
77 |
-
$this->queueOperation('PUT', $id, $method, $args);
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Execute the batch request
|
82 |
-
* @param int $timeout Request timeout in seconds (optional)
|
83 |
-
* @return array|false Assoc array of API response, decoded from JSON
|
84 |
-
*/
|
85 |
-
public function execute($timeout = 10)
|
86 |
-
{
|
87 |
-
$req = array('operations' => $this->operations);
|
88 |
-
|
89 |
-
$result = $this->MailChimp->post('batches', $req, $timeout);
|
90 |
-
|
91 |
-
if ($result && isset($result['id'])) {
|
92 |
-
$this->batch_id = $result['id'];
|
93 |
-
}
|
94 |
-
|
95 |
-
return $result;
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* Check the status of a batch request. If the current instance of the Batch object
|
100 |
-
* was used to make the request, the batch_id is already known and is therefore optional.
|
101 |
-
* @param string $batch_id ID of the batch about which to enquire
|
102 |
-
* @return array|false Assoc array of API response, decoded from JSON
|
103 |
-
*/
|
104 |
-
public function check_status($batch_id = null)
|
105 |
-
{
|
106 |
-
if ($batch_id === null && $this->batch_id) {
|
107 |
-
$batch_id = $this->batch_id;
|
108 |
-
}
|
109 |
-
|
110 |
-
return $this->MailChimp->get('batches/' . $batch_id);
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Get operations
|
115 |
-
* @return array
|
116 |
-
*/
|
117 |
-
public function get_operations()
|
118 |
-
{
|
119 |
-
return $this->operations;
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* Add an operation to the internal queue.
|
124 |
-
* @param string $http_verb GET, POST, PUT, PATCH or DELETE
|
125 |
-
* @param string $id ID for the operation within the batch
|
126 |
-
* @param string $method URL of the API request method
|
127 |
-
* @param array $args Assoc array of arguments (usually your data)
|
128 |
-
* @return void
|
129 |
-
*/
|
130 |
-
private function queueOperation($http_verb, $id, $method, $args = null)
|
131 |
-
{
|
132 |
-
$operation = array(
|
133 |
-
'operation_id' => $id,
|
134 |
-
'method' => $http_verb,
|
135 |
-
'path' => $method,
|
136 |
-
);
|
137 |
-
|
138 |
-
if ($args) {
|
139 |
-
if($http_verb == 'GET') {
|
140 |
-
$key = 'params';
|
141 |
-
$operation[$key] = $args;
|
142 |
-
} else {
|
143 |
-
$key = 'body';
|
144 |
-
$operation[$key] = json_encode($args);
|
145 |
-
}
|
146 |
-
}
|
147 |
-
|
148 |
-
$this->operations[] = $operation;
|
149 |
-
}
|
150 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* A MailChimp Batch operation.
|
4 |
+
* http://developer.mailchimp.com/documentation/mailchimp/reference/batches/
|
5 |
+
*
|
6 |
+
* @author Drew McLellan <drew.mclellan@gmail.com>
|
7 |
+
*/
|
8 |
+
class Batch
|
9 |
+
{
|
10 |
+
private $MailChimp;
|
11 |
+
|
12 |
+
private $operations = array();
|
13 |
+
private $batch_id;
|
14 |
+
|
15 |
+
public function __construct(MailChimp $MailChimp, $batch_id = null)
|
16 |
+
{
|
17 |
+
$this->MailChimp = $MailChimp;
|
18 |
+
$this->batch_id = $batch_id;
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Add an HTTP DELETE request operation to the batch - for deleting data
|
23 |
+
* @param string $id ID for the operation within the batch
|
24 |
+
* @param string $method URL of the API request method
|
25 |
+
* @return void
|
26 |
+
*/
|
27 |
+
public function delete($id, $method)
|
28 |
+
{
|
29 |
+
$this->queueOperation('DELETE', $id, $method);
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Add an HTTP GET request operation to the batch - for retrieving data
|
34 |
+
* @param string $id ID for the operation within the batch
|
35 |
+
* @param string $method URL of the API request method
|
36 |
+
* @param array $args Assoc array of arguments (usually your data)
|
37 |
+
* @return void
|
38 |
+
*/
|
39 |
+
public function get($id, $method, $args = array())
|
40 |
+
{
|
41 |
+
$this->queueOperation('GET', $id, $method, $args);
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Add an HTTP PATCH request operation to the batch - for performing partial updates
|
46 |
+
* @param string $id ID for the operation within the batch
|
47 |
+
* @param string $method URL of the API request method
|
48 |
+
* @param array $args Assoc array of arguments (usually your data)
|
49 |
+
* @return void
|
50 |
+
*/
|
51 |
+
public function patch($id, $method, $args = array())
|
52 |
+
{
|
53 |
+
$this->queueOperation('PATCH', $id, $method, $args);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Add an HTTP POST request operation to the batch - for creating and updating items
|
58 |
+
* @param string $id ID for the operation within the batch
|
59 |
+
* @param string $method URL of the API request method
|
60 |
+
* @param array $args Assoc array of arguments (usually your data)
|
61 |
+
* @return void
|
62 |
+
*/
|
63 |
+
public function post($id, $method, $args = array())
|
64 |
+
{
|
65 |
+
$this->queueOperation('POST', $id, $method, $args);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Add an HTTP PUT request operation to the batch - for creating new items
|
70 |
+
* @param string $id ID for the operation within the batch
|
71 |
+
* @param string $method URL of the API request method
|
72 |
+
* @param array $args Assoc array of arguments (usually your data)
|
73 |
+
* @return void
|
74 |
+
*/
|
75 |
+
public function put($id, $method, $args = array())
|
76 |
+
{
|
77 |
+
$this->queueOperation('PUT', $id, $method, $args);
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Execute the batch request
|
82 |
+
* @param int $timeout Request timeout in seconds (optional)
|
83 |
+
* @return array|false Assoc array of API response, decoded from JSON
|
84 |
+
*/
|
85 |
+
public function execute($timeout = 10)
|
86 |
+
{
|
87 |
+
$req = array('operations' => $this->operations);
|
88 |
+
|
89 |
+
$result = $this->MailChimp->post('batches', $req, $timeout);
|
90 |
+
|
91 |
+
if ($result && isset($result['id'])) {
|
92 |
+
$this->batch_id = $result['id'];
|
93 |
+
}
|
94 |
+
|
95 |
+
return $result;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Check the status of a batch request. If the current instance of the Batch object
|
100 |
+
* was used to make the request, the batch_id is already known and is therefore optional.
|
101 |
+
* @param string $batch_id ID of the batch about which to enquire
|
102 |
+
* @return array|false Assoc array of API response, decoded from JSON
|
103 |
+
*/
|
104 |
+
public function check_status($batch_id = null)
|
105 |
+
{
|
106 |
+
if ($batch_id === null && $this->batch_id) {
|
107 |
+
$batch_id = $this->batch_id;
|
108 |
+
}
|
109 |
+
|
110 |
+
return $this->MailChimp->get('batches/' . $batch_id);
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Get operations
|
115 |
+
* @return array
|
116 |
+
*/
|
117 |
+
public function get_operations()
|
118 |
+
{
|
119 |
+
return $this->operations;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Add an operation to the internal queue.
|
124 |
+
* @param string $http_verb GET, POST, PUT, PATCH or DELETE
|
125 |
+
* @param string $id ID for the operation within the batch
|
126 |
+
* @param string $method URL of the API request method
|
127 |
+
* @param array $args Assoc array of arguments (usually your data)
|
128 |
+
* @return void
|
129 |
+
*/
|
130 |
+
private function queueOperation($http_verb, $id, $method, $args = null)
|
131 |
+
{
|
132 |
+
$operation = array(
|
133 |
+
'operation_id' => $id,
|
134 |
+
'method' => $http_verb,
|
135 |
+
'path' => $method,
|
136 |
+
);
|
137 |
+
|
138 |
+
if ($args) {
|
139 |
+
if($http_verb == 'GET') {
|
140 |
+
$key = 'params';
|
141 |
+
$operation[$key] = $args;
|
142 |
+
} else {
|
143 |
+
$key = 'body';
|
144 |
+
$operation[$key] = json_encode($args);
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
$this->operations[] = $operation;
|
149 |
+
}
|
150 |
+
}
|
modules/subscribe/classes/MailChimp.php
CHANGED
@@ -1,450 +1,450 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Super-simple, minimum abstraction MailChimp API v3 wrapper
|
4 |
-
* MailChimp API v3: http://developer.mailchimp.com
|
5 |
-
* This wrapper: https://github.com/drewm/mailchimp-api
|
6 |
-
*
|
7 |
-
* @author Drew McLellan <drew.mclellan@gmail.com>
|
8 |
-
* @version 2.2
|
9 |
-
*/
|
10 |
-
class MailChimpPps
|
11 |
-
{
|
12 |
-
private $api_key;
|
13 |
-
private $api_endpoint = 'https://<dc>.api.mailchimp.com/3.0';
|
14 |
-
|
15 |
-
const TIMEOUT = 10;
|
16 |
-
|
17 |
-
/* SSL Verification
|
18 |
-
Read before disabling:
|
19 |
-
http://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/
|
20 |
-
*/
|
21 |
-
public $verify_ssl = true;
|
22 |
-
|
23 |
-
private $request_successful = false;
|
24 |
-
private $last_error = '';
|
25 |
-
private $last_response = array();
|
26 |
-
private $last_request = array();
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Create a new instance
|
30 |
-
* @param string $api_key Your MailChimp API key
|
31 |
-
* @param string $api_endpoint Optional custom API endpoint
|
32 |
-
* @throws \Exception
|
33 |
-
*/
|
34 |
-
public function __construct($api_key, $api_endpoint = null)
|
35 |
-
{
|
36 |
-
$this->api_key = $api_key;
|
37 |
-
|
38 |
-
if ($api_endpoint === null) {
|
39 |
-
if (strpos($this->api_key, '-') === false) {
|
40 |
-
throw new Exception("Invalid MailChimp API key `{$api_key}` supplied.");
|
41 |
-
}
|
42 |
-
list(, $data_center) = explode('-', $this->api_key);
|
43 |
-
$this->api_endpoint = str_replace('<dc>', $data_center, $this->api_endpoint);
|
44 |
-
} else {
|
45 |
-
$this->api_endpoint = $api_endpoint;
|
46 |
-
}
|
47 |
-
|
48 |
-
$this->last_response = array('headers' => null, 'body' => null);
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Create a new instance of a Batch request. Optionally with the ID of an existing batch.
|
53 |
-
* @param string $batch_id Optional ID of an existing batch, if you need to check its status for example.
|
54 |
-
* @return Batch New Batch object.
|
55 |
-
*/
|
56 |
-
public function new_batch($batch_id = null)
|
57 |
-
{
|
58 |
-
return new Batch($this, $batch_id);
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* @return string The url to the API endpoint
|
63 |
-
*/
|
64 |
-
public function getApiEndpoint()
|
65 |
-
{
|
66 |
-
return $this->api_endpoint;
|
67 |
-
}
|
68 |
-
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Convert an email address into a 'subscriber hash' for identifying the subscriber in a method URL
|
72 |
-
* @param string $email The subscriber's email address
|
73 |
-
* @return string Hashed version of the input
|
74 |
-
*/
|
75 |
-
public function subscriberHash($email)
|
76 |
-
{
|
77 |
-
return md5(strtolower($email));
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Was the last request successful?
|
82 |
-
* @return bool True for success, false for failure
|
83 |
-
*/
|
84 |
-
public function success()
|
85 |
-
{
|
86 |
-
return $this->request_successful;
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Get the last error returned by either the network transport, or by the API.
|
91 |
-
* If something didn't work, this should contain the string describing the problem.
|
92 |
-
* @return string|false describing the error
|
93 |
-
*/
|
94 |
-
public function getLastError()
|
95 |
-
{
|
96 |
-
return $this->last_error ?: false;
|
97 |
-
}
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Get an array containing the HTTP headers and the body of the API response.
|
101 |
-
* @return array Assoc array with keys 'headers' and 'body'
|
102 |
-
*/
|
103 |
-
public function getLastResponse()
|
104 |
-
{
|
105 |
-
return $this->last_response;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Get an array containing the HTTP headers and the body of the API request.
|
110 |
-
* @return array Assoc array
|
111 |
-
*/
|
112 |
-
public function getLastRequest()
|
113 |
-
{
|
114 |
-
return $this->last_request;
|
115 |
-
}
|
116 |
-
|
117 |
-
/**
|
118 |
-
* Make an HTTP DELETE request - for deleting data
|
119 |
-
* @param string $method URL of the API request method
|
120 |
-
* @param array $args Assoc array of arguments (if any)
|
121 |
-
* @param int $timeout Timeout limit for request in seconds
|
122 |
-
* @return array|false Assoc array of API response, decoded from JSON
|
123 |
-
*/
|
124 |
-
public function delete($method, $args = array(), $timeout = self::TIMEOUT)
|
125 |
-
{
|
126 |
-
return $this->makeRequest('delete', $method, $args, $timeout);
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* Make an HTTP GET request - for retrieving data
|
131 |
-
* @param string $method URL of the API request method
|
132 |
-
* @param array $args Assoc array of arguments (usually your data)
|
133 |
-
* @param int $timeout Timeout limit for request in seconds
|
134 |
-
* @return array|false Assoc array of API response, decoded from JSON
|
135 |
-
*/
|
136 |
-
public function get($method, $args = array(), $timeout = self::TIMEOUT)
|
137 |
-
{
|
138 |
-
return $this->makeRequest('get', $method, $args, $timeout);
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Make an HTTP PATCH request - for performing partial updates
|
143 |
-
* @param string $method URL of the API request method
|
144 |
-
* @param array $args Assoc array of arguments (usually your data)
|
145 |
-
* @param int $timeout Timeout limit for request in seconds
|
146 |
-
* @return array|false Assoc array of API response, decoded from JSON
|
147 |
-
*/
|
148 |
-
public function patch($method, $args = array(), $timeout = self::TIMEOUT)
|
149 |
-
{
|
150 |
-
return $this->makeRequest('patch', $method, $args, $timeout);
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Make an HTTP POST request - for creating and updating items
|
155 |
-
* @param string $method URL of the API request method
|
156 |
-
* @param array $args Assoc array of arguments (usually your data)
|
157 |
-
* @param int $timeout Timeout limit for request in seconds
|
158 |
-
* @return array|false Assoc array of API response, decoded from JSON
|
159 |
-
*/
|
160 |
-
public function post($method, $args = array(), $timeout = self::TIMEOUT)
|
161 |
-
{
|
162 |
-
return $this->makeRequest('post', $method, $args, $timeout);
|
163 |
-
}
|
164 |
-
|
165 |
-
/**
|
166 |
-
* Make an HTTP PUT request - for creating new items
|
167 |
-
* @param string $method URL of the API request method
|
168 |
-
* @param array $args Assoc array of arguments (usually your data)
|
169 |
-
* @param int $timeout Timeout limit for request in seconds
|
170 |
-
* @return array|false Assoc array of API response, decoded from JSON
|
171 |
-
*/
|
172 |
-
public function put($method, $args = array(), $timeout = self::TIMEOUT)
|
173 |
-
{
|
174 |
-
return $this->makeRequest('put', $method, $args, $timeout);
|
175 |
-
}
|
176 |
-
|
177 |
-
/**
|
178 |
-
* Performs the underlying HTTP request. Not very exciting.
|
179 |
-
* @param string $http_verb The HTTP verb to use: get, post, put, patch, delete
|
180 |
-
* @param string $method The API method to be called
|
181 |
-
* @param array $args Assoc array of parameters to be passed
|
182 |
-
* @param int $timeout
|
183 |
-
* @return array|false Assoc array of decoded result
|
184 |
-
* @throws \Exception
|
185 |
-
*/
|
186 |
-
private function makeRequest($http_verb, $method, $args = array(), $timeout = self::TIMEOUT)
|
187 |
-
{
|
188 |
-
if (!function_exists('curl_init') || !function_exists('curl_setopt')) {
|
189 |
-
throw new Exception("cURL support is required, but can't be found.");
|
190 |
-
}
|
191 |
-
|
192 |
-
$url = $this->api_endpoint . '/' . $method;
|
193 |
-
|
194 |
-
$response = $this->prepareStateForRequest($http_verb, $method, $url, $timeout);
|
195 |
-
|
196 |
-
$ch = curl_init();
|
197 |
-
curl_setopt($ch, CURLOPT_URL, $url);
|
198 |
-
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
199 |
-
'Accept: application/vnd.api+json',
|
200 |
-
'Content-Type: application/vnd.api+json',
|
201 |
-
'Authorization: apikey ' . $this->api_key
|
202 |
-
));
|
203 |
-
curl_setopt($ch, CURLOPT_USERAGENT, 'DrewM/MailChimp-API/3.0 (github.com/drewm/mailchimp-api)');
|
204 |
-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
205 |
-
curl_setopt($ch, CURLOPT_VERBOSE, true);
|
206 |
-
curl_setopt($ch, CURLOPT_HEADER, true);
|
207 |
-
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
208 |
-
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl);
|
209 |
-
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
|
210 |
-
curl_setopt($ch, CURLOPT_ENCODING, '');
|
211 |
-
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
|
212 |
-
|
213 |
-
switch ($http_verb) {
|
214 |
-
case 'post':
|
215 |
-
curl_setopt($ch, CURLOPT_POST, true);
|
216 |
-
$this->attachRequestPayload($ch, $args);
|
217 |
-
break;
|
218 |
-
|
219 |
-
case 'get':
|
220 |
-
$query = http_build_query($args, '', '&');
|
221 |
-
curl_setopt($ch, CURLOPT_URL, $url . '?' . $query);
|
222 |
-
break;
|
223 |
-
|
224 |
-
case 'delete':
|
225 |
-
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
226 |
-
break;
|
227 |
-
|
228 |
-
case 'patch':
|
229 |
-
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
|
230 |
-
$this->attachRequestPayload($ch, $args);
|
231 |
-
break;
|
232 |
-
|
233 |
-
case 'put':
|
234 |
-
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
|
235 |
-
$this->attachRequestPayload($ch, $args);
|
236 |
-
break;
|
237 |
-
}
|
238 |
-
|
239 |
-
$responseContent = curl_exec($ch);
|
240 |
-
$response['headers'] = curl_getinfo($ch);
|
241 |
-
$response = $this->setResponseState($response, $responseContent, $ch);
|
242 |
-
$formattedResponse = $this->formatResponse($response);
|
243 |
-
|
244 |
-
curl_close($ch);
|
245 |
-
|
246 |
-
$this->determineSuccess($response, $formattedResponse, $timeout);
|
247 |
-
|
248 |
-
return $formattedResponse;
|
249 |
-
}
|
250 |
-
|
251 |
-
/**
|
252 |
-
* @param string $http_verb
|
253 |
-
* @param string $method
|
254 |
-
* @param string $url
|
255 |
-
* @param integer $timeout
|
256 |
-
*/
|
257 |
-
private function prepareStateForRequest($http_verb, $method, $url, $timeout)
|
258 |
-
{
|
259 |
-
$this->last_error = '';
|
260 |
-
|
261 |
-
$this->request_successful = false;
|
262 |
-
|
263 |
-
$this->last_response = array(
|
264 |
-
'headers' => null, // array of details from curl_getinfo()
|
265 |
-
'httpHeaders' => null, // array of HTTP headers
|
266 |
-
'body' => null // content of the response
|
267 |
-
);
|
268 |
-
|
269 |
-
$this->last_request = array(
|
270 |
-
'method' => $http_verb,
|
271 |
-
'path' => $method,
|
272 |
-
'url' => $url,
|
273 |
-
'body' => '',
|
274 |
-
'timeout' => $timeout,
|
275 |
-
);
|
276 |
-
|
277 |
-
return $this->last_response;
|
278 |
-
}
|
279 |
-
|
280 |
-
/**
|
281 |
-
* Get the HTTP headers as an array of header-name => header-value pairs.
|
282 |
-
*
|
283 |
-
* The "Link" header is parsed into an associative array based on the
|
284 |
-
* rel names it contains. The original value is available under
|
285 |
-
* the "_raw" key.
|
286 |
-
*
|
287 |
-
* @param string $headersAsString
|
288 |
-
* @return array
|
289 |
-
*/
|
290 |
-
private function getHeadersAsArray($headersAsString)
|
291 |
-
{
|
292 |
-
$headers = array();
|
293 |
-
|
294 |
-
foreach (explode("\r\n", $headersAsString) as $i => $line) {
|
295 |
-
if ($i === 0) { // HTTP code
|
296 |
-
continue;
|
297 |
-
}
|
298 |
-
|
299 |
-
$line = trim($line);
|
300 |
-
if (empty($line)) {
|
301 |
-
continue;
|
302 |
-
}
|
303 |
-
|
304 |
-
list($key, $value) = explode(': ', $line);
|
305 |
-
|
306 |
-
if ($key == 'Link') {
|
307 |
-
$value = array_merge(
|
308 |
-
array('_raw' => $value),
|
309 |
-
$this->getLinkHeaderAsArray($value)
|
310 |
-
);
|
311 |
-
}
|
312 |
-
|
313 |
-
$headers[$key] = $value;
|
314 |
-
}
|
315 |
-
|
316 |
-
return $headers;
|
317 |
-
}
|
318 |
-
|
319 |
-
/**
|
320 |
-
* Extract all rel => URL pairs from the provided Link header value
|
321 |
-
*
|
322 |
-
* Mailchimp only implements the URI reference and relation type from
|
323 |
-
* RFC 5988, so the value of the header is something like this:
|
324 |
-
*
|
325 |
-
* 'https://us13.api.mailchimp.com/schema/3.0/Lists/Instance.json; rel="describedBy", <https://us13.admin.mailchimp.com/lists/members/?id=XXXX>; rel="dashboard"'
|
326 |
-
*
|
327 |
-
* @param string $linkHeaderAsString
|
328 |
-
* @return array
|
329 |
-
*/
|
330 |
-
private function getLinkHeaderAsArray($linkHeaderAsString)
|
331 |
-
{
|
332 |
-
$urls = array();
|
333 |
-
|
334 |
-
if (preg_match_all('/<(.*?)>\s*;\s*rel="(.*?)"\s*/', $linkHeaderAsString, $matches)) {
|
335 |
-
foreach ($matches[2] as $i => $relName) {
|
336 |
-
$urls[$relName] = $matches[1][$i];
|
337 |
-
}
|
338 |
-
}
|
339 |
-
|
340 |
-
return $urls;
|
341 |
-
}
|
342 |
-
|
343 |
-
/**
|
344 |
-
* Encode the data and attach it to the request
|
345 |
-
* @param resource $ch cURL session handle, used by reference
|
346 |
-
* @param array $data Assoc array of data to attach
|
347 |
-
*/
|
348 |
-
private function attachRequestPayload(&$ch, $data)
|
349 |
-
{
|
350 |
-
// supsystic
|
351 |
-
if(version_compare(phpversion(), '5.3') >= 0) {
|
352 |
-
$encoded = json_encode($data, JSON_FORCE_OBJECT);
|
353 |
-
} else {
|
354 |
-
$encoded = json_encode($data);
|
355 |
-
}
|
356 |
-
//////
|
357 |
-
$this->last_request['body'] = $encoded;
|
358 |
-
curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded);
|
359 |
-
}
|
360 |
-
|
361 |
-
/**
|
362 |
-
* Decode the response and format any error messages for debugging
|
363 |
-
* @param array $response The response from the curl request
|
364 |
-
* @return array|false The JSON decoded into an array
|
365 |
-
*/
|
366 |
-
private function formatResponse($response)
|
367 |
-
{
|
368 |
-
$this->last_response = $response;
|
369 |
-
|
370 |
-
if (!empty($response['body'])) {
|
371 |
-
return json_decode($response['body'], true);
|
372 |
-
}
|
373 |
-
|
374 |
-
return false;
|
375 |
-
}
|
376 |
-
|
377 |
-
/**
|
378 |
-
* Do post-request formatting and setting state from the response
|
379 |
-
* @param array $response The response from the curl request
|
380 |
-
* @param string $responseContent The body of the response from the curl request
|
381 |
-
* * @return array The modified response
|
382 |
-
*/
|
383 |
-
private function setResponseState($response, $responseContent, $ch)
|
384 |
-
{
|
385 |
-
if ($responseContent === false) {
|
386 |
-
$this->last_error = curl_error($ch);
|
387 |
-
} else {
|
388 |
-
|
389 |
-
$headerSize = $response['headers']['header_size'];
|
390 |
-
|
391 |
-
$response['httpHeaders'] = $this->getHeadersAsArray(substr($responseContent, 0, $headerSize));
|
392 |
-
$response['body'] = substr($responseContent, $headerSize);
|
393 |
-
|
394 |
-
if (isset($response['headers']['request_header'])) {
|
395 |
-
$this->last_request['headers'] = $response['headers']['request_header'];
|
396 |
-
}
|
397 |
-
}
|
398 |
-
|
399 |
-
return $response;
|
400 |
-
}
|
401 |
-
|
402 |
-
/**
|
403 |
-
* Check if the response was successful or a failure. If it failed, store the error.
|
404 |
-
* @param array $response The response from the curl request
|
405 |
-
* @param array|false $formattedResponse The response body payload from the curl request
|
406 |
-
* @param int $timeout The timeout supplied to the curl request.
|
407 |
-
* @return bool If the request was successful
|
408 |
-
*/
|
409 |
-
private function determineSuccess($response, $formattedResponse, $timeout)
|
410 |
-
{
|
411 |
-
$status = $this->findHTTPStatus($response, $formattedResponse);
|
412 |
-
|
413 |
-
if ($status >= 200 && $status <= 299) {
|
414 |
-
$this->request_successful = true;
|
415 |
-
return true;
|
416 |
-
}
|
417 |
-
|
418 |
-
if (isset($formattedResponse['detail'])) {
|
419 |
-
$this->last_error = sprintf('%d: %s', $formattedResponse['status'], $formattedResponse['detail']);
|
420 |
-
return false;
|
421 |
-
}
|
422 |
-
|
423 |
-
if( $timeout > 0 && $response['headers'] && $response['headers']['total_time'] >= $timeout ) {
|
424 |
-
$this->last_error = sprintf('Request timed out after %f seconds.', $response['headers']['total_time'] );
|
425 |
-
return false;
|
426 |
-
}
|
427 |
-
|
428 |
-
$this->last_error = 'Unknown error, call getLastResponse() to find out what happened.';
|
429 |
-
return false;
|
430 |
-
}
|
431 |
-
|
432 |
-
/**
|
433 |
-
* Find the HTTP status code from the headers or API response body
|
434 |
-
* @param array $response The response from the curl request
|
435 |
-
* @param array|false $formattedResponse The response body payload from the curl request
|
436 |
-
* @return int HTTP status code
|
437 |
-
*/
|
438 |
-
private function findHTTPStatus($response, $formattedResponse)
|
439 |
-
{
|
440 |
-
if (!empty($response['headers']) && isset($response['headers']['http_code'])) {
|
441 |
-
return (int) $response['headers']['http_code'];
|
442 |
-
}
|
443 |
-
|
444 |
-
if (!empty($response['body']) && isset($formattedResponse['status'])) {
|
445 |
-
return (int) $formattedResponse['status'];
|
446 |
-
}
|
447 |
-
|
448 |
-
return 418;
|
449 |
-
}
|
450 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Super-simple, minimum abstraction MailChimp API v3 wrapper
|
4 |
+
* MailChimp API v3: http://developer.mailchimp.com
|
5 |
+
* This wrapper: https://github.com/drewm/mailchimp-api
|
6 |
+
*
|
7 |
+
* @author Drew McLellan <drew.mclellan@gmail.com>
|
8 |
+
* @version 2.2
|
9 |
+
*/
|
10 |
+
class MailChimpPps
|
11 |
+
{
|
12 |
+
private $api_key;
|
13 |
+
private $api_endpoint = 'https://<dc>.api.mailchimp.com/3.0';
|
14 |
+
|
15 |
+
const TIMEOUT = 10;
|
16 |
+
|
17 |
+
/* SSL Verification
|
18 |
+
Read before disabling:
|
19 |
+
http://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/
|
20 |
+
*/
|
21 |
+
public $verify_ssl = true;
|
22 |
+
|
23 |
+
private $request_successful = false;
|
24 |
+
private $last_error = '';
|
25 |
+
private $last_response = array();
|
26 |
+
private $last_request = array();
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Create a new instance
|
30 |
+
* @param string $api_key Your MailChimp API key
|
31 |
+
* @param string $api_endpoint Optional custom API endpoint
|
32 |
+
* @throws \Exception
|
33 |
+
*/
|
34 |
+
public function __construct($api_key, $api_endpoint = null)
|
35 |
+
{
|
36 |
+
$this->api_key = $api_key;
|
37 |
+
|
38 |
+
if ($api_endpoint === null) {
|
39 |
+
if (strpos($this->api_key, '-') === false) {
|
40 |
+
throw new Exception("Invalid MailChimp API key `{$api_key}` supplied.");
|
41 |
+
}
|
42 |
+
list(, $data_center) = explode('-', $this->api_key);
|
43 |
+
$this->api_endpoint = str_replace('<dc>', $data_center, $this->api_endpoint);
|
44 |
+
} else {
|
45 |
+
$this->api_endpoint = $api_endpoint;
|
46 |
+
}
|
47 |
+
|
48 |
+
$this->last_response = array('headers' => null, 'body' => null);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Create a new instance of a Batch request. Optionally with the ID of an existing batch.
|
53 |
+
* @param string $batch_id Optional ID of an existing batch, if you need to check its status for example.
|
54 |
+
* @return Batch New Batch object.
|
55 |
+
*/
|
56 |
+
public function new_batch($batch_id = null)
|
57 |
+
{
|
58 |
+
return new Batch($this, $batch_id);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @return string The url to the API endpoint
|
63 |
+
*/
|
64 |
+
public function getApiEndpoint()
|
65 |
+
{
|
66 |
+
return $this->api_endpoint;
|
67 |
+
}
|
68 |
+
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Convert an email address into a 'subscriber hash' for identifying the subscriber in a method URL
|
72 |
+
* @param string $email The subscriber's email address
|
73 |
+
* @return string Hashed version of the input
|
74 |
+
*/
|
75 |
+
public function subscriberHash($email)
|
76 |
+
{
|
77 |
+
return md5(strtolower($email));
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Was the last request successful?
|
82 |
+
* @return bool True for success, false for failure
|
83 |
+
*/
|
84 |
+
public function success()
|
85 |
+
{
|
86 |
+
return $this->request_successful;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Get the last error returned by either the network transport, or by the API.
|
91 |
+
* If something didn't work, this should contain the string describing the problem.
|
92 |
+
* @return string|false describing the error
|
93 |
+
*/
|
94 |
+
public function getLastError()
|
95 |
+
{
|
96 |
+
return $this->last_error ?: false;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Get an array containing the HTTP headers and the body of the API response.
|
101 |
+
* @return array Assoc array with keys 'headers' and 'body'
|
102 |
+
*/
|
103 |
+
public function getLastResponse()
|
104 |
+
{
|
105 |
+
return $this->last_response;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Get an array containing the HTTP headers and the body of the API request.
|
110 |
+
* @return array Assoc array
|
111 |
+
*/
|
112 |
+
public function getLastRequest()
|
113 |
+
{
|
114 |
+
return $this->last_request;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Make an HTTP DELETE request - for deleting data
|
119 |
+
* @param string $method URL of the API request method
|
120 |
+
* @param array $args Assoc array of arguments (if any)
|
121 |
+
* @param int $timeout Timeout limit for request in seconds
|
122 |
+
* @return array|false Assoc array of API response, decoded from JSON
|
123 |
+
*/
|
124 |
+
public function delete($method, $args = array(), $timeout = self::TIMEOUT)
|
125 |
+
{
|
126 |
+
return $this->makeRequest('delete', $method, $args, $timeout);
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Make an HTTP GET request - for retrieving data
|
131 |
+
* @param string $method URL of the API request method
|
132 |
+
* @param array $args Assoc array of arguments (usually your data)
|
133 |
+
* @param int $timeout Timeout limit for request in seconds
|
134 |
+
* @return array|false Assoc array of API response, decoded from JSON
|
135 |
+
*/
|
136 |
+
public function get($method, $args = array(), $timeout = self::TIMEOUT)
|
137 |
+
{
|
138 |
+
return $this->makeRequest('get', $method, $args, $timeout);
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Make an HTTP PATCH request - for performing partial updates
|
143 |
+
* @param string $method URL of the API request method
|
144 |
+
* @param array $args Assoc array of arguments (usually your data)
|
145 |
+
* @param int $timeout Timeout limit for request in seconds
|
146 |
+
* @return array|false Assoc array of API response, decoded from JSON
|
147 |
+
*/
|
148 |
+
public function patch($method, $args = array(), $timeout = self::TIMEOUT)
|
149 |
+
{
|
150 |
+
return $this->makeRequest('patch', $method, $args, $timeout);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Make an HTTP POST request - for creating and updating items
|
155 |
+
* @param string $method URL of the API request method
|
156 |
+
* @param array $args Assoc array of arguments (usually your data)
|
157 |
+
* @param int $timeout Timeout limit for request in seconds
|
158 |
+
* @return array|false Assoc array of API response, decoded from JSON
|
159 |
+
*/
|
160 |
+
public function post($method, $args = array(), $timeout = self::TIMEOUT)
|
161 |
+
{
|
162 |
+
return $this->makeRequest('post', $method, $args, $timeout);
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Make an HTTP PUT request - for creating new items
|
167 |
+
* @param string $method URL of the API request method
|
168 |
+
* @param array $args Assoc array of arguments (usually your data)
|
169 |
+
* @param int $timeout Timeout limit for request in seconds
|
170 |
+
* @return array|false Assoc array of API response, decoded from JSON
|
171 |
+
*/
|
172 |
+
public function put($method, $args = array(), $timeout = self::TIMEOUT)
|
173 |
+
{
|
174 |
+
return $this->makeRequest('put', $method, $args, $timeout);
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Performs the underlying HTTP request. Not very exciting.
|
179 |
+
* @param string $http_verb The HTTP verb to use: get, post, put, patch, delete
|
180 |
+
* @param string $method The API method to be called
|
181 |
+
* @param array $args Assoc array of parameters to be passed
|
182 |
+
* @param int $timeout
|
183 |
+
* @return array|false Assoc array of decoded result
|
184 |
+
* @throws \Exception
|
185 |
+
*/
|
186 |
+
private function makeRequest($http_verb, $method, $args = array(), $timeout = self::TIMEOUT)
|
187 |
+
{
|
188 |
+
if (!function_exists('curl_init') || !function_exists('curl_setopt')) {
|
189 |
+
throw new Exception("cURL support is required, but can't be found.");
|
190 |
+
}
|
191 |
+
|
192 |
+
$url = $this->api_endpoint . '/' . $method;
|
193 |
+
|
194 |
+
$response = $this->prepareStateForRequest($http_verb, $method, $url, $timeout);
|
195 |
+
|
196 |
+
$ch = curl_init();
|
197 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
198 |
+
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
199 |
+
'Accept: application/vnd.api+json',
|
200 |
+
'Content-Type: application/vnd.api+json',
|
201 |
+
'Authorization: apikey ' . $this->api_key
|
202 |
+
));
|
203 |
+
curl_setopt($ch, CURLOPT_USERAGENT, 'DrewM/MailChimp-API/3.0 (github.com/drewm/mailchimp-api)');
|
204 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
205 |
+
curl_setopt($ch, CURLOPT_VERBOSE, true);
|
206 |
+
curl_setopt($ch, CURLOPT_HEADER, true);
|
207 |
+
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
208 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl);
|
209 |
+
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
|
210 |
+
curl_setopt($ch, CURLOPT_ENCODING, '');
|
211 |
+
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
|
212 |
+
|
213 |
+
switch ($http_verb) {
|
214 |
+
case 'post':
|
215 |
+
curl_setopt($ch, CURLOPT_POST, true);
|
216 |
+
$this->attachRequestPayload($ch, $args);
|
217 |
+
break;
|
218 |
+
|
219 |
+
case 'get':
|
220 |
+
$query = http_build_query($args, '', '&');
|
221 |
+
curl_setopt($ch, CURLOPT_URL, $url . '?' . $query);
|
222 |
+
break;
|
223 |
+
|
224 |
+
case 'delete':
|
225 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
226 |
+
break;
|
227 |
+
|
228 |
+
case 'patch':
|
229 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
|
230 |
+
$this->attachRequestPayload($ch, $args);
|
231 |
+
break;
|
232 |
+
|
233 |
+
case 'put':
|
234 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
|
235 |
+
$this->attachRequestPayload($ch, $args);
|
236 |
+
break;
|
237 |
+
}
|
238 |
+
|
239 |
+
$responseContent = curl_exec($ch);
|
240 |
+
$response['headers'] = curl_getinfo($ch);
|
241 |
+
$response = $this->setResponseState($response, $responseContent, $ch);
|
242 |
+
$formattedResponse = $this->formatResponse($response);
|
243 |
+
|
244 |
+
curl_close($ch);
|
245 |
+
|
246 |
+
$this->determineSuccess($response, $formattedResponse, $timeout);
|
247 |
+
|
248 |
+
return $formattedResponse;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* @param string $http_verb
|
253 |
+
* @param string $method
|
254 |
+
* @param string $url
|
255 |
+
* @param integer $timeout
|
256 |
+
*/
|
257 |
+
private function prepareStateForRequest($http_verb, $method, $url, $timeout)
|
258 |
+
{
|
259 |
+
$this->last_error = '';
|
260 |
+
|
261 |
+
$this->request_successful = false;
|
262 |
+
|
263 |
+
$this->last_response = array(
|
264 |
+
'headers' => null, // array of details from curl_getinfo()
|
265 |
+
'httpHeaders' => null, // array of HTTP headers
|
266 |
+
'body' => null // content of the response
|
267 |
+
);
|
268 |
+
|
269 |
+
$this->last_request = array(
|
270 |
+
'method' => $http_verb,
|
271 |
+
'path' => $method,
|
272 |
+
'url' => $url,
|
273 |
+
'body' => '',
|
274 |
+
'timeout' => $timeout,
|
275 |
+
);
|
276 |
+
|
277 |
+
return $this->last_response;
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* Get the HTTP headers as an array of header-name => header-value pairs.
|
282 |
+
*
|
283 |
+
* The "Link" header is parsed into an associative array based on the
|
284 |
+
* rel names it contains. The original value is available under
|
285 |
+
* the "_raw" key.
|
286 |
+
*
|
287 |
+
* @param string $headersAsString
|
288 |
+
* @return array
|
289 |
+
*/
|
290 |
+
private function getHeadersAsArray($headersAsString)
|
291 |
+
{
|
292 |
+
$headers = array();
|
293 |
+
|
294 |
+
foreach (explode("\r\n", $headersAsString) as $i => $line) {
|
295 |
+
if ($i === 0) { // HTTP code
|
296 |
+
continue;
|
297 |
+
}
|
298 |
+
|
299 |
+
$line = trim($line);
|
300 |
+
if (empty($line)) {
|
301 |
+
continue;
|
302 |
+
}
|
303 |
+
|
304 |
+
list($key, $value) = explode(': ', $line);
|
305 |
+
|
306 |
+
if ($key == 'Link') {
|
307 |
+
$value = array_merge(
|
308 |
+
array('_raw' => $value),
|
309 |
+
$this->getLinkHeaderAsArray($value)
|
310 |
+
);
|
311 |
+
}
|
312 |
+
|
313 |
+
$headers[$key] = $value;
|
314 |
+
}
|
315 |
+
|
316 |
+
return $headers;
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Extract all rel => URL pairs from the provided Link header value
|
321 |
+
*
|
322 |
+
* Mailchimp only implements the URI reference and relation type from
|
323 |
+
* RFC 5988, so the value of the header is something like this:
|
324 |
+
*
|
325 |
+
* 'https://us13.api.mailchimp.com/schema/3.0/Lists/Instance.json; rel="describedBy", <https://us13.admin.mailchimp.com/lists/members/?id=XXXX>; rel="dashboard"'
|
326 |
+
*
|
327 |
+
* @param string $linkHeaderAsString
|
328 |
+
* @return array
|
329 |
+
*/
|
330 |
+
private function getLinkHeaderAsArray($linkHeaderAsString)
|
331 |
+
{
|
332 |
+
$urls = array();
|
333 |
+
|
334 |
+
if (preg_match_all('/<(.*?)>\s*;\s*rel="(.*?)"\s*/', $linkHeaderAsString, $matches)) {
|
335 |
+
foreach ($matches[2] as $i => $relName) {
|
336 |
+
$urls[$relName] = $matches[1][$i];
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
return $urls;
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Encode the data and attach it to the request
|
345 |
+
* @param resource $ch cURL session handle, used by reference
|
346 |
+
* @param array $data Assoc array of data to attach
|
347 |
+
*/
|
348 |
+
private function attachRequestPayload(&$ch, $data)
|
349 |
+
{
|
350 |
+
// supsystic
|
351 |
+
if(version_compare(phpversion(), '5.3') >= 0) {
|
352 |
+
$encoded = json_encode($data, JSON_FORCE_OBJECT);
|
353 |
+
} else {
|
354 |
+
$encoded = json_encode($data);
|
355 |
+
}
|
356 |
+
//////
|
357 |
+
$this->last_request['body'] = $encoded;
|
358 |
+
curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded);
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* Decode the response and format any error messages for debugging
|
363 |
+
* @param array $response The response from the curl request
|
364 |
+
* @return array|false The JSON decoded into an array
|
365 |
+
*/
|
366 |
+
private function formatResponse($response)
|
367 |
+
{
|
368 |
+
$this->last_response = $response;
|
369 |
+
|
370 |
+
if (!empty($response['body'])) {
|
371 |
+
return json_decode($response['body'], true);
|
372 |
+
}
|
373 |
+
|
374 |
+
return false;
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Do post-request formatting and setting state from the response
|
379 |
+
* @param array $response The response from the curl request
|
380 |
+
* @param string $responseContent The body of the response from the curl request
|
381 |
+
* * @return array The modified response
|
382 |
+
*/
|
383 |
+
private function setResponseState($response, $responseContent, $ch)
|
384 |
+
{
|
385 |
+
if ($responseContent === false) {
|
386 |
+
$this->last_error = curl_error($ch);
|
387 |
+
} else {
|
388 |
+
|
389 |
+
$headerSize = $response['headers']['header_size'];
|
390 |
+
|
391 |
+
$response['httpHeaders'] = $this->getHeadersAsArray(substr($responseContent, 0, $headerSize));
|
392 |
+
$response['body'] = substr($responseContent, $headerSize);
|
393 |
+
|
394 |
+
if (isset($response['headers']['request_header'])) {
|
395 |
+
$this->last_request['headers'] = $response['headers']['request_header'];
|
396 |
+
}
|
397 |
+
}
|
398 |
+
|
399 |
+
return $response;
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Check if the response was successful or a failure. If it failed, store the error.
|
404 |
+
* @param array $response The response from the curl request
|
405 |
+
* @param array|false $formattedResponse The response body payload from the curl request
|
406 |
+
* @param int $timeout The timeout supplied to the curl request.
|
407 |
+
* @return bool If the request was successful
|
408 |
+
*/
|
409 |
+
private function determineSuccess($response, $formattedResponse, $timeout)
|
410 |
+
{
|
411 |
+
$status = $this->findHTTPStatus($response, $formattedResponse);
|
412 |
+
|
413 |
+
if ($status >= 200 && $status <= 299) {
|
414 |
+
$this->request_successful = true;
|
415 |
+
return true;
|
416 |
+
}
|
417 |
+
|
418 |
+
if (isset($formattedResponse['detail'])) {
|
419 |
+
$this->last_error = sprintf('%d: %s', $formattedResponse['status'], $formattedResponse['detail']);
|
420 |
+
return false;
|
421 |
+
}
|
422 |
+
|
423 |
+
if( $timeout > 0 && $response['headers'] && $response['headers']['total_time'] >= $timeout ) {
|
424 |
+
$this->last_error = sprintf('Request timed out after %f seconds.', $response['headers']['total_time'] );
|
425 |
+
return false;
|
426 |
+
}
|
427 |
+
|
428 |
+
$this->last_error = 'Unknown error, call getLastResponse() to find out what happened.';
|
429 |
+
return false;
|
430 |
+
}
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Find the HTTP status code from the headers or API response body
|
434 |
+
* @param array $response The response from the curl request
|
435 |
+
* @param array|false $formattedResponse The response body payload from the curl request
|
436 |
+
* @return int HTTP status code
|
437 |
+
*/
|
438 |
+
private function findHTTPStatus($response, $formattedResponse)
|
439 |
+
{
|
440 |
+
if (!empty($response['headers']) && isset($response['headers']['http_code'])) {
|
441 |
+
return (int) $response['headers']['http_code'];
|
442 |
+
}
|
443 |
+
|
444 |
+
if (!empty($response['body']) && isset($formattedResponse['status'])) {
|
445 |
+
return (int) $formattedResponse['status'];
|
446 |
+
}
|
447 |
+
|
448 |
+
return 418;
|
449 |
+
}
|
450 |
+
}
|
modules/subscribe/classes/Webhook.php
CHANGED
@@ -1,82 +1,82 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* A MailChimp Webhook request.
|
4 |
-
* How to Set Up Webhooks: http://eepurl.com/bs-j_T
|
5 |
-
*
|
6 |
-
* @author Drew McLellan <drew.mclellan@gmail.com>
|
7 |
-
*/
|
8 |
-
class Webhook
|
9 |
-
{
|
10 |
-
private static $eventSubscriptions = array();
|
11 |
-
private static $receivedWebhook = null;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Subscribe to an incoming webhook request. The callback will be invoked when a matching webhook is received.
|
15 |
-
* @param string $event Name of the webhook event, e.g. subscribe, unsubscribe, campaign
|
16 |
-
* @param callable $callback A callable function to invoke with the data from the received webhook
|
17 |
-
* @return void
|
18 |
-
*/
|
19 |
-
public static function subscribe($event, $callback)
|
20 |
-
{
|
21 |
-
if (!isset(self::$eventSubscriptions[$event])) self::$eventSubscriptions[$event] = array();
|
22 |
-
self::$eventSubscriptions[$event][] = $callback;
|
23 |
-
|
24 |
-
self::receive();
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Retrieve the incoming webhook request as sent.
|
29 |
-
* @param string $input An optional raw POST body to use instead of php://input - mainly for unit testing.
|
30 |
-
* @return array|false An associative array containing the details of the received webhook
|
31 |
-
*/
|
32 |
-
public static function receive($input = null)
|
33 |
-
{
|
34 |
-
if (is_null($input)) {
|
35 |
-
if (self::$receivedWebhook !== null) {
|
36 |
-
$input = self::$receivedWebhook;
|
37 |
-
} else {
|
38 |
-
$input = file_get_contents("php://input");
|
39 |
-
}
|
40 |
-
}
|
41 |
-
|
42 |
-
if (!is_null($input) && $input != '') {
|
43 |
-
return self::processWebhook($input);
|
44 |
-
}
|
45 |
-
|
46 |
-
return false;
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Process the raw request into a PHP array and dispatch any matching subscription callbacks
|
51 |
-
* @param string $input The raw HTTP POST request
|
52 |
-
* @return array|false An associative array containing the details of the received webhook
|
53 |
-
*/
|
54 |
-
private static function processWebhook($input)
|
55 |
-
{
|
56 |
-
self::$receivedWebhook = $input;
|
57 |
-
parse_str($input, $result);
|
58 |
-
if ($result && isset($result['type'])) {
|
59 |
-
self::dispatchWebhookEvent($result['type'], $result['data']);
|
60 |
-
return $result;
|
61 |
-
}
|
62 |
-
|
63 |
-
return false;
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Call any subscribed callbacks for this event
|
68 |
-
* @param string $event The name of the callback event
|
69 |
-
* @param array $data An associative array of the webhook data
|
70 |
-
* @return void
|
71 |
-
*/
|
72 |
-
private static function dispatchWebhookEvent($event, $data)
|
73 |
-
{
|
74 |
-
if (isset(self::$eventSubscriptions[$event])) {
|
75 |
-
foreach(self::$eventSubscriptions[$event] as $callback) {
|
76 |
-
$callback($data);
|
77 |
-
}
|
78 |
-
// reset subscriptions
|
79 |
-
self::$eventSubscriptions[$event] = array();
|
80 |
-
}
|
81 |
-
}
|
82 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* A MailChimp Webhook request.
|
4 |
+
* How to Set Up Webhooks: http://eepurl.com/bs-j_T
|
5 |
+
*
|
6 |
+
* @author Drew McLellan <drew.mclellan@gmail.com>
|
7 |
+
*/
|
8 |
+
class Webhook
|
9 |
+
{
|
10 |
+
private static $eventSubscriptions = array();
|
11 |
+
private static $receivedWebhook = null;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Subscribe to an incoming webhook request. The callback will be invoked when a matching webhook is received.
|
15 |
+
* @param string $event Name of the webhook event, e.g. subscribe, unsubscribe, campaign
|
16 |
+
* @param callable $callback A callable function to invoke with the data from the received webhook
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
+
public static function subscribe($event, $callback)
|
20 |
+
{
|
21 |
+
if (!isset(self::$eventSubscriptions[$event])) self::$eventSubscriptions[$event] = array();
|
22 |
+
self::$eventSubscriptions[$event][] = $callback;
|
23 |
+
|
24 |
+
self::receive();
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Retrieve the incoming webhook request as sent.
|
29 |
+
* @param string $input An optional raw POST body to use instead of php://input - mainly for unit testing.
|
30 |
+
* @return array|false An associative array containing the details of the received webhook
|
31 |
+
*/
|
32 |
+
public static function receive($input = null)
|
33 |
+
{
|
34 |
+
if (is_null($input)) {
|
35 |
+
if (self::$receivedWebhook !== null) {
|
36 |
+
$input = self::$receivedWebhook;
|
37 |
+
} else {
|
38 |
+
$input = file_get_contents("php://input");
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
if (!is_null($input) && $input != '') {
|
43 |
+
return self::processWebhook($input);
|
44 |
+
}
|
45 |
+
|
46 |
+
return false;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Process the raw request into a PHP array and dispatch any matching subscription callbacks
|
51 |
+
* @param string $input The raw HTTP POST request
|
52 |
+
* @return array|false An associative array containing the details of the received webhook
|
53 |
+
*/
|
54 |
+
private static function processWebhook($input)
|
55 |
+
{
|
56 |
+
self::$receivedWebhook = $input;
|
57 |
+
parse_str($input, $result);
|
58 |
+
if ($result && isset($result['type'])) {
|
59 |
+
self::dispatchWebhookEvent($result['type'], $result['data']);
|
60 |
+
return $result;
|
61 |
+
}
|
62 |
+
|
63 |
+
return false;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Call any subscribed callbacks for this event
|
68 |
+
* @param string $event The name of the callback event
|
69 |
+
* @param array $data An associative array of the webhook data
|
70 |
+
* @return void
|
71 |
+
*/
|
72 |
+
private static function dispatchWebhookEvent($event, $data)
|
73 |
+
{
|
74 |
+
if (isset(self::$eventSubscriptions[$event])) {
|
75 |
+
foreach(self::$eventSubscriptions[$event] as $callback) {
|
76 |
+
$callback($data);
|
77 |
+
}
|
78 |
+
// reset subscriptions
|
79 |
+
self::$eventSubscriptions[$event] = array();
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
modules/subscribe/classes/mailPoetV3.php
CHANGED
@@ -1,14 +1,14 @@
|
|
1 |
-
<?php
|
2 |
-
class mailPoetV3Pps {
|
3 |
-
public function getLists() {
|
4 |
-
return \MailPoet\API\API::MP('v1')->getLists();
|
5 |
-
}
|
6 |
-
|
7 |
-
public function signupConfirm() {
|
8 |
-
return \MailPoet\Models\Setting::getValue('signup_confirmation');
|
9 |
-
}
|
10 |
-
|
11 |
-
public function subscribe($userData, $lists, $options) {
|
12 |
-
return \MailPoet\API\API::MP('v1')->addSubscriber($userData, $lists, $options);
|
13 |
-
}
|
14 |
}
|
1 |
+
<?php
|
2 |
+
class mailPoetV3Pps {
|
3 |
+
public function getLists() {
|
4 |
+
return \MailPoet\API\API::MP('v1')->getLists();
|
5 |
+
}
|
6 |
+
|
7 |
+
public function signupConfirm() {
|
8 |
+
return \MailPoet\Models\Setting::getValue('signup_confirmation');
|
9 |
+
}
|
10 |
+
|
11 |
+
public function subscribe($userData, $lists, $options) {
|
12 |
+
return \MailPoet\API\API::MP('v1')->addSubscriber($userData, $lists, $options);
|
13 |
+
}
|
14 |
}
|
modules/subscribe/mod.php
CHANGED
@@ -148,6 +148,7 @@ class subscribePps extends modulePps {
|
|
148 |
$enbLogin = (isset($popup['params']['tpl']['enb_login']) && !empty($popup['params']['tpl']['enb_login']));
|
149 |
$enbReg = (isset($popup['params']['tpl']['enb_reg']) && !empty($popup['params']['tpl']['enb_reg']));
|
150 |
$enbSub = (isset($popup['params']['tpl']['enb_subscribe']) && !empty($popup['params']['tpl']['enb_subscribe']));
|
|
|
151 |
if(($enbLogin || $enbReg)
|
152 |
&& framePps::_()->getModule('login') && !$onlyForceSub
|
153 |
) {
|
@@ -233,6 +234,11 @@ class subscribePps extends modulePps {
|
|
233 |
}
|
234 |
}
|
235 |
}
|
|
|
|
|
|
|
|
|
|
|
236 |
return $resHtml;
|
237 |
}
|
238 |
}
|
148 |
$enbLogin = (isset($popup['params']['tpl']['enb_login']) && !empty($popup['params']['tpl']['enb_login']));
|
149 |
$enbReg = (isset($popup['params']['tpl']['enb_reg']) && !empty($popup['params']['tpl']['enb_reg']));
|
150 |
$enbSub = (isset($popup['params']['tpl']['enb_subscribe']) && !empty($popup['params']['tpl']['enb_subscribe']));
|
151 |
+
$enbRecaptcha = (isset($popup['params']['tpl']['enb_captcha']) && !empty($popup['params']['tpl']['enb_captcha']));
|
152 |
if(($enbLogin || $enbReg)
|
153 |
&& framePps::_()->getModule('login') && !$onlyForceSub
|
154 |
) {
|
234 |
}
|
235 |
}
|
236 |
}
|
237 |
+
if(!empty($resHtml) && $enbRecaptcha && framePps::_()->getModule('sub_fields')) {
|
238 |
+
$resHtml .= htmlPps::recaptcha('recap', array(
|
239 |
+
'sitekey' => $popup['params']['tpl']['capt_site_key'],
|
240 |
+
));
|
241 |
+
}
|
242 |
return $resHtml;
|
243 |
}
|
244 |
}
|
modules/subscribe/models/subscribe.php
CHANGED
@@ -189,6 +189,16 @@ class subscribeModelPps extends modelPps {
|
|
189 |
return false;
|
190 |
}
|
191 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
return true;
|
193 |
}
|
194 |
public function getDest() {
|
@@ -826,7 +836,11 @@ class subscribeModelPps extends modelPps {
|
|
826 |
$this->pushError ( $res['error'] );
|
827 |
return false;
|
828 |
} elseif($this->_useMailchimp3Version && isset($res['status']) && $res['status'] == 400) {
|
829 |
-
|
|
|
|
|
|
|
|
|
830 |
return false;
|
831 |
}
|
832 |
}
|
189 |
return false;
|
190 |
}
|
191 |
}
|
192 |
+
$enbRecaptcha = (isset($popup['params']['tpl']['enb_captcha']) && !empty($popup['params']['tpl']['enb_captcha']));
|
193 |
+
if($enbRecaptcha
|
194 |
+
&& framePps::_()->getModule('sub_fields')
|
195 |
+
&& method_exists(framePps::_()->getModule('sub_fields'), 'validateReCaptcha')
|
196 |
+
) {
|
197 |
+
if(!framePps::_()->getModule('sub_fields')->validateReCaptcha($popup['params']['tpl']['capt_secret_key'], $d['g-recaptcha-response'])) {
|
198 |
+
$this->pushError(framePps::_()->getModule('sub_fields')->getErrors());
|
199 |
+
return false;
|
200 |
+
}
|
201 |
+
}
|
202 |
return true;
|
203 |
}
|
204 |
public function getDest() {
|
836 |
$this->pushError ( $res['error'] );
|
837 |
return false;
|
838 |
} elseif($this->_useMailchimp3Version && isset($res['status']) && $res['status'] == 400) {
|
839 |
+
if($res['title'] == 'Member Exists') {
|
840 |
+
$this->pushError($popup['params']['tpl']['sub_txt_exists_email'], 'email');
|
841 |
+
} else {
|
842 |
+
$this->pushError ( $res['detail'] );
|
843 |
+
}
|
844 |
return false;
|
845 |
}
|
846 |
}
|
modules/supsystic_promo/js/admin.tour.js
CHANGED
@@ -46,7 +46,7 @@ function _ppsOpenPointerAndPopupTab(tourId, pointId, tab) {
|
|
46 |
function _ppsOpenPointer(tourId, pointId) {
|
47 |
var pointer = ppsAdminTourData.tour[ tourId ].points[ pointId ];
|
48 |
var $content = ppsAdminTourData._$.find('#supsystic-'+ tourId+ '-'+ pointId);
|
49 |
-
if(!jQuery(pointer.target) || !jQuery(pointer.target).
|
50 |
return;
|
51 |
if(g_ppsCurrTour) {
|
52 |
_ppsTourSendNext(g_ppsCurrTour._tourId, g_ppsCurrTour._pointId);
|
46 |
function _ppsOpenPointer(tourId, pointId) {
|
47 |
var pointer = ppsAdminTourData.tour[ tourId ].points[ pointId ];
|
48 |
var $content = ppsAdminTourData._$.find('#supsystic-'+ tourId+ '-'+ pointId);
|
49 |
+
if(!jQuery(pointer.target) || !jQuery(pointer.target).length)
|
50 |
return;
|
51 |
if(g_ppsCurrTour) {
|
52 |
_ppsTourSendNext(g_ppsCurrTour._tourId, g_ppsCurrTour._pointId);
|
modules/supsystic_promo/mod.php
CHANGED
@@ -129,6 +129,7 @@ class supsystic_promoPps extends modulePps {
|
|
129 |
'ymlp' => array('label' => __('Your Mailing List Provider (Ymlp) - PRO', PPS_LANG_CODE), 'require_confirm' => false),
|
130 |
'fourdem' => array('label' => __('4Dem.it - PRO', PPS_LANG_CODE), 'require_confirm' => false),
|
131 |
'dotmailer' => array('label' => __('Dotmailer - PRO', PPS_LANG_CODE), 'require_confirm' => false),
|
|
|
132 |
));
|
133 |
}
|
134 |
return $subDestList;
|
129 |
'ymlp' => array('label' => __('Your Mailing List Provider (Ymlp) - PRO', PPS_LANG_CODE), 'require_confirm' => false),
|
130 |
'fourdem' => array('label' => __('4Dem.it - PRO', PPS_LANG_CODE), 'require_confirm' => false),
|
131 |
'dotmailer' => array('label' => __('Dotmailer - PRO', PPS_LANG_CODE), 'require_confirm' => false),
|
132 |
+
'madmimi' => array('label' => __('Mad Mimi - PRO', PPS_LANG_CODE), 'require_confirm' => false),
|
133 |
));
|
134 |
}
|
135 |
return $subDestList;
|
modules/supsystic_promo/models/classes/lib/Base/MixpanelBase.php
CHANGED
@@ -1,65 +1,65 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* This a Base class which all Mixpanel classes extend from to provide some very basic
|
5 |
-
* debugging and logging functionality. It also serves to persist $_options across the library.
|
6 |
-
*
|
7 |
-
*/
|
8 |
-
class Base_MixpanelBase {
|
9 |
-
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Default options that can be overridden via the $options constructor arg
|
13 |
-
* @var array
|
14 |
-
*/
|
15 |
-
private $_defaults = array(
|
16 |
-
"max_batch_size" => 50, // the max batch size Mixpanel will accept is 50,
|
17 |
-
"max_queue_size" => 1000, // the max num of items to hold in memory before flushing
|
18 |
-
"debug" => true, // enable/disable debug mode
|
19 |
-
"consumer" => "curl", // which consumer to use
|
20 |
-
"host" => "api.mixpanel.com", // the host name for api calls
|
21 |
-
"events_endpoint" => "/track", // host relative endpoint for events
|
22 |
-
"people_endpoint" => "/engage", // host relative endpoint for people updates
|
23 |
-
"use_ssl" => true, // use ssl when available
|
24 |
-
"error_callback" => null // callback to use on consumption failures
|
25 |
-
);
|
26 |
-
|
27 |
-
|
28 |
-
/**
|
29 |
-
* An array of options to be used by the Mixpanel library.
|
30 |
-
* @var array
|
31 |
-
*/
|
32 |
-
protected $_options = array();
|
33 |
-
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Construct a new MixpanelBase object and merge custom options with defaults
|
37 |
-
* @param array $options
|
38 |
-
*/
|
39 |
-
public function __construct($options = array()) {
|
40 |
-
$options = array_merge($this->_defaults, $options);
|
41 |
-
$this->_options = $options;
|
42 |
-
}
|
43 |
-
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Log a message to PHP's error log
|
47 |
-
* @param $msg
|
48 |
-
*/
|
49 |
-
protected function _log($msg) {
|
50 |
-
$arr = debug_backtrace();
|
51 |
-
$class = $arr[0]['class'];
|
52 |
-
$line = $arr[0]['line'];
|
53 |
-
error_log ( "[ $class - line $line ] : " . $msg );
|
54 |
-
}
|
55 |
-
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Returns true if in debug mode, false if in production mode
|
59 |
-
* @return bool
|
60 |
-
*/
|
61 |
-
protected function _debug() {
|
62 |
-
return array_key_exists("debug", $this->_options) && $this->_options["debug"] == true;
|
63 |
-
}
|
64 |
-
|
65 |
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* This a Base class which all Mixpanel classes extend from to provide some very basic
|
5 |
+
* debugging and logging functionality. It also serves to persist $_options across the library.
|
6 |
+
*
|
7 |
+
*/
|
8 |
+
class Base_MixpanelBase {
|
9 |
+
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Default options that can be overridden via the $options constructor arg
|
13 |
+
* @var array
|
14 |
+
*/
|
15 |
+
private $_defaults = array(
|
16 |
+
"max_batch_size" => 50, // the max batch size Mixpanel will accept is 50,
|
17 |
+
"max_queue_size" => 1000, // the max num of items to hold in memory before flushing
|
18 |
+
"debug" => true, // enable/disable debug mode
|
19 |
+
"consumer" => "curl", // which consumer to use
|
20 |
+
"host" => "api.mixpanel.com", // the host name for api calls
|
21 |
+
"events_endpoint" => "/track", // host relative endpoint for events
|
22 |
+
"people_endpoint" => "/engage", // host relative endpoint for people updates
|
23 |
+
"use_ssl" => true, // use ssl when available
|
24 |
+
"error_callback" => null // callback to use on consumption failures
|
25 |
+
);
|
26 |
+
|
27 |
+
|
28 |
+
/**
|
29 |
+
* An array of options to be used by the Mixpanel library.
|
30 |
+
* @var array
|
31 |
+
*/
|
32 |
+
protected $_options = array();
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Construct a new MixpanelBase object and merge custom options with defaults
|
37 |
+
* @param array $options
|
38 |
+
*/
|
39 |
+
public function __construct($options = array()) {
|
40 |
+
$options = array_merge($this->_defaults, $options);
|
41 |
+
$this->_options = $options;
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Log a message to PHP's error log
|
47 |
+
* @param $msg
|
48 |
+
*/
|
49 |
+
protected function _log($msg) {
|
50 |
+
$arr = debug_backtrace();
|
51 |
+
$class = $arr[0]['class'];
|
52 |
+
$line = $arr[0]['line'];
|
53 |
+
error_log ( "[ $class - line $line ] : " . $msg );
|
54 |
+
}
|
55 |
+
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Returns true if in debug mode, false if in production mode
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
+
protected function _debug() {
|
62 |
+
return array_key_exists("debug", $this->_options) && $this->_options["debug"] == true;
|
63 |
+
}
|
64 |
+
|
65 |
}
|
modules/supsystic_promo/models/classes/lib/ConsumerStrategies/AbstractConsumer.php
CHANGED
@@ -1,57 +1,57 @@
|
|
1 |
-
<?php
|
2 |
-
require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Provides some base methods for use by a Consumer implementation
|
6 |
-
*/
|
7 |
-
abstract class ConsumerStrategies_AbstractConsumer extends Base_MixpanelBase {
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Creates a new AbstractConsumer
|
11 |
-
* @param array $options
|
12 |
-
*/
|
13 |
-
function __construct($options = array()) {
|
14 |
-
|
15 |
-
parent::__construct($options);
|
16 |
-
|
17 |
-
if ($this->_debug()) {
|
18 |
-
$this->_log("Instantiated new Consumer");
|
19 |
-
}
|
20 |
-
|
21 |
-
}
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Encode an array to be persisted
|
25 |
-
* @param array $params
|
26 |
-
* @return string
|
27 |
-
*/
|
28 |
-
protected function _encode($params) {
|
29 |
-
return base64_encode(json_encode($params));
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Handles errors that occur in a consumer
|
34 |
-
* @param $code
|
35 |
-
* @param $msg
|
36 |
-
*/
|
37 |
-
protected function _handleError($code, $msg) {
|
38 |
-
if (isset($this->_options['error_callback'])) {
|
39 |
-
$handler = $this->_options['error_callback'];
|
40 |
-
call_user_func($handler, $code, $msg);
|
41 |
-
}
|
42 |
-
|
43 |
-
if ($this->_debug()) {
|
44 |
-
$arr = debug_backtrace();
|
45 |
-
$class = get_class($arr[0]['object']);
|
46 |
-
$line = $arr[0]['line'];
|
47 |
-
error_log ( "[ $class - line $line ] : " . print_r($msg, true) );
|
48 |
-
}
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Persist a batch of messages in whatever way the implementer sees fit
|
53 |
-
* @param array $batch an array of messages to consume
|
54 |
-
* @return boolean success or fail
|
55 |
-
*/
|
56 |
-
abstract function persist($batch);
|
57 |
}
|
1 |
+
<?php
|
2 |
+
require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Provides some base methods for use by a Consumer implementation
|
6 |
+
*/
|
7 |
+
abstract class ConsumerStrategies_AbstractConsumer extends Base_MixpanelBase {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Creates a new AbstractConsumer
|
11 |
+
* @param array $options
|
12 |
+
*/
|
13 |
+
function __construct($options = array()) {
|
14 |
+
|
15 |
+
parent::__construct($options);
|
16 |
+
|
17 |
+
if ($this->_debug()) {
|
18 |
+
$this->_log("Instantiated new Consumer");
|
19 |
+
}
|
20 |
+
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Encode an array to be persisted
|
25 |
+
* @param array $params
|
26 |
+
* @return string
|
27 |
+
*/
|
28 |
+
protected function _encode($params) {
|
29 |
+
return base64_encode(json_encode($params));
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Handles errors that occur in a consumer
|
34 |
+
* @param $code
|
35 |
+
* @param $msg
|
36 |
+
*/
|
37 |
+
protected function _handleError($code, $msg) {
|
38 |
+
if (isset($this->_options['error_callback'])) {
|
39 |
+
$handler = $this->_options['error_callback'];
|
40 |
+
call_user_func($handler, $code, $msg);
|
41 |
+
}
|
42 |
+
|
43 |
+
if ($this->_debug()) {
|
44 |
+
$arr = debug_backtrace();
|
45 |
+
$class = get_class($arr[0]['object']);
|
46 |
+
$line = $arr[0]['line'];
|
47 |
+
error_log ( "[ $class - line $line ] : " . print_r($msg, true) );
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Persist a batch of messages in whatever way the implementer sees fit
|
53 |
+
* @param array $batch an array of messages to consume
|
54 |
+
* @return boolean success or fail
|
55 |
+
*/
|
56 |
+
abstract function persist($batch);
|
57 |
}
|
modules/supsystic_promo/models/classes/lib/ConsumerStrategies/CurlConsumer.php
CHANGED
@@ -1,221 +1,221 @@
|
|
1 |
-
<?php
|
2 |
-
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Consumes messages and sends them to a host/endpoint using cURL
|
6 |
-
*/
|
7 |
-
class ConsumerStrategies_CurlConsumer extends ConsumerStrategies_AbstractConsumer {
|
8 |
-
|
9 |
-
/**
|
10 |
-
* @var string the host to connect to (e.g. api.mixpanel.com)
|
11 |
-
*/
|
12 |
-
protected $_host;
|
13 |
-
|
14 |
-
|
15 |
-
/**
|
16 |
-
* @var string the host-relative endpoint to write to (e.g. /engage)
|
17 |
-
*/
|
18 |
-
protected $_endpoint;
|
19 |
-
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @var int connect_timeout The number of seconds to wait while trying to connect. Default is 5 seconds.
|
23 |
-
*/
|
24 |
-
protected $_connect_timeout;
|
25 |
-
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var int timeout The maximum number of seconds to allow cURL call to execute. Default is 30 seconds.
|
29 |
-
*/
|
30 |
-
protected $_timeout;
|
31 |
-
|
32 |
-
|
33 |
-
/**
|
34 |
-
* @var string the protocol to use for the cURL connection
|
35 |
-
*/
|
36 |
-
protected $_protocol;
|
37 |
-
|
38 |
-
|
39 |
-
/**
|
40 |
-
* @var bool|null true to fork the cURL process (using exec) or false to use PHP's cURL extension. false by default
|
41 |
-
*/
|
42 |
-
protected $_fork = null;
|
43 |
-
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Creates a new CurlConsumer and assigns properties from the $options array
|
47 |
-
* @param array $options
|
48 |
-
* @throws Exception
|
49 |
-
*/
|
50 |
-
function __construct($options) {
|
51 |
-
parent::__construct($options);
|
52 |
-
|
53 |
-
$this->_host = $options['host'];
|
54 |
-
$this->_endpoint = $options['endpoint'];
|
55 |
-
$this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
|
56 |
-
$this->_timeout = array_key_exists('timeout', $options) ? $options['timeout'] : 30;
|
57 |
-
$this->_protocol = array_key_exists('use_ssl', $options) && $options['use_ssl'] == true ? "https" : "http";
|
58 |
-
$this->_fork = array_key_exists('fork', $options) ? ($options['fork'] == true) : false;
|
59 |
-
|
60 |
-
// ensure the environment is workable for the given settings
|
61 |
-
if ($this->_fork == true) {
|
62 |
-
$exists = function_exists('exec');
|
63 |
-
if (!$exists) {
|
64 |
-
throw new Exception('The "exec" function must exist to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
|
65 |
-
}
|
66 |
-
$disabled = explode(', ', ini_get('disable_functions'));
|
67 |
-
$enabled = !in_array('exec', $disabled);
|
68 |
-
if (!$enabled) {
|
69 |
-
throw new Exception('The "exec" function must be enabled to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
|
70 |
-
}
|
71 |
-
} else {
|
72 |
-
if (!function_exists('curl_init')) {
|
73 |
-
throw new Exception('The cURL PHP extension is required to use the cURL consumer with fork = false. Try setting fork = true or use another consumer.');
|
74 |
-
}
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Write to the given host/endpoint using either a forked cURL process or using PHP's cURL extension
|
81 |
-
* @param array $batch
|
82 |
-
* @return bool
|
83 |
-
*/
|
84 |
-
public function persist($batch) {
|
85 |
-
if (count($batch) > 0) {
|
86 |
-
$data = "data=" . $this->_encode($batch);
|
87 |
-
$url = $this->_protocol . "://" . $this->_host . $this->_endpoint;
|
88 |
-
if ($this->_fork) {
|
89 |
-
return $this->_execute_forked($url, $data);
|
90 |
-
} else {
|
91 |
-
return $this->_execute($url, $data);
|
92 |
-
}
|
93 |
-
} else {
|
94 |
-
return true;
|
95 |
-
}
|
96 |
-
}
|
97 |
-
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Write using the cURL php extension
|
101 |
-
* @param $url
|
102 |
-
* @param $data
|
103 |
-
* @return bool
|
104 |
-
*/
|
105 |
-
protected function _execute($url, $data) {
|
106 |
-
if ($this->_debug()) {
|
107 |
-
$this->_log("Making blocking cURL call to $url");
|
108 |
-
}
|
109 |
-
|
110 |
-
$ch = curl_init();
|
111 |
-
curl_setopt($ch, CURLOPT_URL, $url);
|
112 |
-
curl_setopt($ch, CURLOPT_HEADER, 0);
|
113 |
-
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_connect_timeout);
|
114 |
-
curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);
|
115 |
-
curl_setopt($ch, CURLOPT_POST, 1);
|
116 |
-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
117 |
-
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
118 |
-
$response = curl_exec($ch);
|
119 |
-
if (false === $response) {
|
120 |
-
$curl_error = curl_error($ch);
|
121 |
-
$curl_errno = curl_errno($ch);
|
122 |
-
curl_close($ch);
|
123 |
-
$this->_handleError($curl_errno, $curl_error);
|
124 |
-
return false;
|
125 |
-
} else {
|
126 |
-
curl_close($ch);
|
127 |
-
if (trim($response) == "1") {
|
128 |
-
return true;
|
129 |
-
} else {
|
130 |
-
$this->_handleError(0, $response);
|
131 |
-
return false;
|
132 |
-
}
|
133 |
-
}
|
134 |
-
}
|
135 |
-
|
136 |
-
|
137 |
-
/**
|
138 |
-
* Write using a forked cURL process
|
139 |
-
* @param $url
|
140 |
-
* @param $data
|
141 |
-
* @return bool
|
142 |
-
*/
|
143 |
-
protected function _execute_forked($url, $data) {
|
144 |
-
|
145 |
-
if ($this->_debug()) {
|
146 |
-
$this->_log("Making forked cURL call to $url");
|
147 |
-
}
|
148 |
-
|
149 |
-
$exec = 'curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d ' . $data . ' "' . $url . '"';
|
150 |
-
|
151 |
-
if(!$this->_debug()) {
|
152 |
-
$exec .= " >/dev/null 2>&1 &";
|
153 |
-
}
|
154 |
-
|
155 |
-
exec($exec, $output, $return_var);
|
156 |
-
|
157 |
-
if ($return_var != 0) {
|
158 |
-
$this->_handleError($return_var, $output);
|
159 |
-
}
|
160 |
-
|
161 |
-
return $return_var == 0;
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* @return int
|
166 |
-
*/
|
167 |
-
public function getConnectTimeout()
|
168 |
-
{
|
169 |
-
return $this->_connect_timeout;
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* @return string
|
174 |
-
*/
|
175 |
-
public function getEndpoint()
|
176 |
-
{
|
177 |
-
return $this->_endpoint;
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* @return bool|null
|
182 |
-
*/
|
183 |
-
public function getFork()
|
184 |
-
{
|
185 |
-
return $this->_fork;
|
186 |
-
}
|
187 |
-
|
188 |
-
/**
|
189 |
-
* @return string
|
190 |
-
*/
|
191 |
-
public function getHost()
|
192 |
-
{
|
193 |
-
return $this->_host;
|
194 |
-
}
|
195 |
-
|
196 |
-
/**
|
197 |
-
* @return array
|
198 |
-
*/
|
199 |
-
public function getOptions()
|
200 |
-
{
|
201 |
-
return $this->_options;
|
202 |
-
}
|
203 |
-
|
204 |
-
/**
|
205 |
-
* @return string
|
206 |
-
*/
|
207 |
-
public function getProtocol()
|
208 |
-
{
|
209 |
-
return $this->_protocol;
|
210 |
-
}
|
211 |
-
|
212 |
-
/**
|
213 |
-
* @return int
|
214 |
-
*/
|
215 |
-
public function getTimeout()
|
216 |
-
{
|
217 |
-
return $this->_timeout;
|
218 |
-
}
|
219 |
-
|
220 |
-
|
221 |
}
|
1 |
+
<?php
|
2 |
+
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Consumes messages and sends them to a host/endpoint using cURL
|
6 |
+
*/
|
7 |
+
class ConsumerStrategies_CurlConsumer extends ConsumerStrategies_AbstractConsumer {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @var string the host to connect to (e.g. api.mixpanel.com)
|
11 |
+
*/
|
12 |
+
protected $_host;
|
13 |
+
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var string the host-relative endpoint to write to (e.g. /engage)
|
17 |
+
*/
|
18 |
+
protected $_endpoint;
|
19 |
+
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var int connect_timeout The number of seconds to wait while trying to connect. Default is 5 seconds.
|
23 |
+
*/
|
24 |
+
protected $_connect_timeout;
|
25 |
+
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var int timeout The maximum number of seconds to allow cURL call to execute. Default is 30 seconds.
|
29 |
+
*/
|
30 |
+
protected $_timeout;
|
31 |
+
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string the protocol to use for the cURL connection
|
35 |
+
*/
|
36 |
+
protected $_protocol;
|
37 |
+
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var bool|null true to fork the cURL process (using exec) or false to use PHP's cURL extension. false by default
|
41 |
+
*/
|
42 |
+
protected $_fork = null;
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Creates a new CurlConsumer and assigns properties from the $options array
|
47 |
+
* @param array $options
|
48 |
+
* @throws Exception
|
49 |
+
*/
|
50 |
+
function __construct($options) {
|
51 |
+
parent::__construct($options);
|
52 |
+
|
53 |
+
$this->_host = $options['host'];
|
54 |
+
$this->_endpoint = $options['endpoint'];
|
55 |
+
$this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
|
56 |
+
$this->_timeout = array_key_exists('timeout', $options) ? $options['timeout'] : 30;
|
57 |
+
$this->_protocol = array_key_exists('use_ssl', $options) && $options['use_ssl'] == true ? "https" : "http";
|
58 |
+
$this->_fork = array_key_exists('fork', $options) ? ($options['fork'] == true) : false;
|
59 |
+
|
60 |
+
// ensure the environment is workable for the given settings
|
61 |
+
if ($this->_fork == true) {
|
62 |
+
$exists = function_exists('exec');
|
63 |
+
if (!$exists) {
|
64 |
+
throw new Exception('The "exec" function must exist to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
|
65 |
+
}
|
66 |
+
$disabled = explode(', ', ini_get('disable_functions'));
|
67 |
+
$enabled = !in_array('exec', $disabled);
|
68 |
+
if (!$enabled) {
|
69 |
+
throw new Exception('The "exec" function must be enabled to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
|
70 |
+
}
|
71 |
+
} else {
|
72 |
+
if (!function_exists('curl_init')) {
|
73 |
+
throw new Exception('The cURL PHP extension is required to use the cURL consumer with fork = false. Try setting fork = true or use another consumer.');
|
74 |
+
}
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Write to the given host/endpoint using either a forked cURL process or using PHP's cURL extension
|
81 |
+
* @param array $batch
|
82 |
+
* @return bool
|
83 |
+
*/
|
84 |
+
public function persist($batch) {
|
85 |
+
if (count($batch) > 0) {
|
86 |
+
$data = "data=" . $this->_encode($batch);
|
87 |
+
$url = $this->_protocol . "://" . $this->_host . $this->_endpoint;
|
88 |
+
if ($this->_fork) {
|
89 |
+
return $this->_execute_forked($url, $data);
|
90 |
+
} else {
|
91 |
+
return $this->_execute($url, $data);
|
92 |
+
}
|
93 |
+
} else {
|
94 |
+
return true;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Write using the cURL php extension
|
101 |
+
* @param $url
|
102 |
+
* @param $data
|
103 |
+
* @return bool
|
104 |
+
*/
|
105 |
+
protected function _execute($url, $data) {
|
106 |
+
if ($this->_debug()) {
|
107 |
+
$this->_log("Making blocking cURL call to $url");
|
108 |
+
}
|
109 |
+
|
110 |
+
$ch = curl_init();
|
111 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
112 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
113 |
+
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_connect_timeout);
|
114 |
+
curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);
|
115 |
+
curl_setopt($ch, CURLOPT_POST, 1);
|
116 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
117 |
+
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
118 |
+
$response = curl_exec($ch);
|
119 |
+
if (false === $response) {
|
120 |
+
$curl_error = curl_error($ch);
|
121 |
+
$curl_errno = curl_errno($ch);
|
122 |
+
curl_close($ch);
|
123 |
+
$this->_handleError($curl_errno, $curl_error);
|
124 |
+
return false;
|
125 |
+
} else {
|
126 |
+
curl_close($ch);
|
127 |
+
if (trim($response) == "1") {
|
128 |
+
return true;
|
129 |
+
} else {
|
130 |
+
$this->_handleError(0, $response);
|
131 |
+
return false;
|
132 |
+
}
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Write using a forked cURL process
|
139 |
+
* @param $url
|
140 |
+
* @param $data
|
141 |
+
* @return bool
|
142 |
+
*/
|
143 |
+
protected function _execute_forked($url, $data) {
|
144 |
+
|
145 |
+
if ($this->_debug()) {
|
146 |
+
$this->_log("Making forked cURL call to $url");
|
147 |
+
}
|
148 |
+
|
149 |
+
$exec = 'curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d ' . $data . ' "' . $url . '"';
|
150 |
+
|
151 |
+
if(!$this->_debug()) {
|
152 |
+
$exec .= " >/dev/null 2>&1 &";
|
153 |
+
}
|
154 |
+
|
155 |
+
exec($exec, $output, $return_var);
|
156 |
+
|
157 |
+
if ($return_var != 0) {
|
158 |
+
$this->_handleError($return_var, $output);
|
159 |
+
}
|
160 |
+
|
161 |
+
return $return_var == 0;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* @return int
|
166 |
+
*/
|
167 |
+
public function getConnectTimeout()
|
168 |
+
{
|
169 |
+
return $this->_connect_timeout;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* @return string
|
174 |
+
*/
|
175 |
+
public function getEndpoint()
|
176 |
+
{
|
177 |
+
return $this->_endpoint;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* @return bool|null
|
182 |
+
*/
|
183 |
+
public function getFork()
|
184 |
+
{
|
185 |
+
return $this->_fork;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* @return string
|
190 |
+
*/
|
191 |
+
public function getHost()
|
192 |
+
{
|
193 |
+
return $this->_host;
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* @return array
|
198 |
+
*/
|
199 |
+
public function getOptions()
|
200 |
+
{
|
201 |
+
return $this->_options;
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* @return string
|
206 |
+
*/
|
207 |
+
public function getProtocol()
|
208 |
+
{
|
209 |
+
return $this->_protocol;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* @return int
|
214 |
+
*/
|
215 |
+
public function getTimeout()
|
216 |
+
{
|
217 |
+
return $this->_timeout;
|
218 |
+
}
|
219 |
+
|
220 |
+
|
221 |
}
|
modules/supsystic_promo/models/classes/lib/ConsumerStrategies/FileConsumer.php
CHANGED
@@ -1,38 +1,38 @@
|
|
1 |
-
<?php
|
2 |
-
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
3 |
-
/**
|
4 |
-
* Consumes messages and writes them to a file
|
5 |
-
*/
|
6 |
-
class ConsumerStrategies_FileConsumer extends ConsumerStrategies_AbstractConsumer {
|
7 |
-
|
8 |
-
/**
|
9 |
-
* @var string path to a file that we want to write the messages to
|
10 |
-
*/
|
11 |
-
private $_file;
|
12 |
-
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Creates a new FileConsumer and assigns properties from the $options array
|
16 |
-
* @param array $options
|
17 |
-
*/
|
18 |
-
function __construct($options) {
|
19 |
-
parent::__construct($options);
|
20 |
-
|
21 |
-
// what file to write to?
|
22 |
-
$this->_file = array_key_exists("file", $options) ? $options['file'] : dirname(__FILE__)."/../../messages.txt";
|
23 |
-
}
|
24 |
-
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Append $batch to a file
|
28 |
-
* @param array $batch
|
29 |
-
* @return bool
|
30 |
-
*/
|
31 |
-
public function persist($batch) {
|
32 |
-
if (count($batch) > 0) {
|
33 |
-
return file_put_contents($this->_file, json_encode($batch)."\n", FILE_APPEND | LOCK_EX) !== false;
|
34 |
-
} else {
|
35 |
-
return true;
|
36 |
-
}
|
37 |
-
}
|
38 |
}
|
1 |
+
<?php
|
2 |
+
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
3 |
+
/**
|
4 |
+
* Consumes messages and writes them to a file
|
5 |
+
*/
|
6 |
+
class ConsumerStrategies_FileConsumer extends ConsumerStrategies_AbstractConsumer {
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @var string path to a file that we want to write the messages to
|
10 |
+
*/
|
11 |
+
private $_file;
|
12 |
+
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Creates a new FileConsumer and assigns properties from the $options array
|
16 |
+
* @param array $options
|
17 |
+
*/
|
18 |
+
function __construct($options) {
|
19 |
+
parent::__construct($options);
|
20 |
+
|
21 |
+
// what file to write to?
|
22 |
+
$this->_file = array_key_exists("file", $options) ? $options['file'] : dirname(__FILE__)."/../../messages.txt";
|
23 |
+
}
|
24 |
+
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Append $batch to a file
|
28 |
+
* @param array $batch
|
29 |
+
* @return bool
|
30 |
+
*/
|
31 |
+
public function persist($batch) {
|
32 |
+
if (count($batch) > 0) {
|
33 |
+
return file_put_contents($this->_file, json_encode($batch)."\n", FILE_APPEND | LOCK_EX) !== false;
|
34 |
+
} else {
|
35 |
+
return true;
|
36 |
+
}
|
37 |
+
}
|
38 |
}
|
modules/supsystic_promo/models/classes/lib/ConsumerStrategies/SocketConsumer.php
CHANGED
@@ -1,308 +1,308 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Portions of this class were borrowed from
|
4 |
-
* https://github.com/segmentio/analytics-php/blob/master/lib/Analytics/Consumer/Socket.php.
|
5 |
-
* Thanks for the work!
|
6 |
-
*
|
7 |
-
* WWWWWW||WWWWWW
|
8 |
-
* W W W||W W W
|
9 |
-
* ||
|
10 |
-
* ( OO )__________
|
11 |
-
* / | \
|
12 |
-
* /o o| MIT \
|
13 |
-
* \___/||_||__||_|| *
|
14 |
-
* || || || ||
|
15 |
-
* _||_|| _||_||
|
16 |
-
* (__|__|(__|__|
|
17 |
-
* (The MIT License)
|
18 |
-
*
|
19 |
-
* Copyright (c) 2013 Segment.io Inc. friends@segment.io
|
20 |
-
*
|
21 |
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
22 |
-
* documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
|
23 |
-
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
24 |
-
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
25 |
-
*
|
26 |
-
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
27 |
-
* Software.
|
28 |
-
*
|
29 |
-
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
30 |
-
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
31 |
-
* OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
32 |
-
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
33 |
-
*/
|
34 |
-
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Consumes messages and writes them to host/endpoint using a persistent socket
|
38 |
-
*/
|
39 |
-
class ConsumerStrategies_SocketConsumer extends ConsumerStrategies_AbstractConsumer {
|
40 |
-
|
41 |
-
/**
|
42 |
-
* @var string the host to connect to (e.g. api.mixpanel.com)
|
43 |
-
*/
|
44 |
-
private $_host;
|
45 |
-
|
46 |
-
|
47 |
-
/**
|
48 |
-
* @var string the host-relative endpoint to write to (e.g. /engage)
|
49 |
-
*/
|
50 |
-
private $_endpoint;
|
51 |
-
|
52 |
-
|
53 |
-
/**
|
54 |
-
* @var int connect_timeout the socket connection timeout in seconds
|
55 |
-
*/
|
56 |
-
private $_connect_timeout;
|
57 |
-
|
58 |
-
|
59 |
-
/**
|
60 |
-
* @var string the protocol to use for the socket connection
|
61 |
-
*/
|
62 |
-
private $_protocol;
|
63 |
-
|
64 |
-
|
65 |
-
/**
|
66 |
-
* @var resource holds the socket resource
|
67 |
-
*/
|
68 |
-
private $_socket;
|
69 |
-
|
70 |
-
/**
|
71 |
-
* @var bool whether or not to wait for a response
|
72 |
-
*/
|
73 |
-
private $_async;
|
74 |
-
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Creates a new SocketConsumer and assigns properties from the $options array
|
78 |
-
* @param array $options
|
79 |
-
*/
|
80 |
-
public function __construct($options = array()) {
|
81 |
-
parent::__construct($options);
|
82 |
-
|
83 |
-
|
84 |
-
$this->_host = $options['host'];
|
85 |
-
$this->_endpoint = $options['endpoint'];
|
86 |
-
$this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
|
87 |
-
$this->_async = array_key_exists('async', $options) && $options['async'] === false ? false : true;
|
88 |
-
|
89 |
-
if (array_key_exists('use_ssl', $options) && $options['use_ssl'] == true) {
|
90 |
-
$this->_protocol = "ssl";
|
91 |
-
$this->_port = 443;
|
92 |
-
} else {
|
93 |
-
$this->_protocol = "tcp";
|
94 |
-
$this->_port = 80;
|
95 |
-
}
|
96 |
-
}
|
97 |
-
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Write using a persistent socket connection.
|
101 |
-
* @param array $batch
|
102 |
-
* @return bool
|
103 |
-
*/
|
104 |
-
public function persist($batch) {
|
105 |
-
|
106 |
-
$socket = $this->_getSocket();
|
107 |
-
if (!is_resource($socket)) {
|
108 |
-
return false;
|
109 |
-
}
|
110 |
-
|
111 |
-
$data = "data=".$this->_encode($batch);
|
112 |
-
|
113 |
-
$body = "";
|
114 |
-
$body.= "POST ".$this->_endpoint." HTTP/1.1\r\n";
|
115 |
-
$body.= "Host: " . $this->_host . "\r\n";
|
116 |
-
$body.= "Content-Type: application/x-www-form-urlencoded\r\n";
|
117 |
-
$body.= "Accept: application/json\r\n";
|
118 |
-
$body.= "Content-length: " . strlen($data) . "\r\n";
|
119 |
-
$body.= "\r\n";
|
120 |
-
$body.= $data;
|
121 |
-
|
122 |
-
return $this->_write($socket, $body);
|
123 |
-
}
|
124 |
-
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Return cached socket if open or create a new persistent socket
|
128 |
-
* @return bool|resource
|
129 |
-
*/
|
130 |
-
private function _getSocket() {
|
131 |
-
if(is_resource($this->_socket)) {
|
132 |
-
|
133 |
-
if ($this->_debug()) {
|
134 |
-
$this->_log("Using existing socket");
|
135 |
-
}
|
136 |
-
|
137 |
-
return $this->_socket;
|
138 |
-
} else {
|
139 |
-
|
140 |
-
if ($this->_debug()) {
|
141 |
-
$this->_log("Creating new socket at ".time());
|
142 |
-
}
|
143 |
-
|
144 |
-
return $this->_createSocket();
|
145 |
-
}
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Attempt to open a new socket connection, cache it, and return the resource
|
150 |
-
* @param bool $retry
|
151 |
-
* @return bool|resource
|
152 |
-
*/
|
153 |
-
private function _createSocket($retry = true) {
|
154 |
-
try {
|
155 |
-
$socket = pfsockopen($this->_protocol . "://" . $this->_host, $this->_port, $err_no, $err_msg, $this->_connect_timeout);
|
156 |
-
|
157 |
-
if ($this->_debug()) {
|
158 |
-
$this->_log("Opening socket connection to " . $this->_protocol . "://" . $this->_host . ":" . $this->_port);
|
159 |
-
}
|
160 |
-
|
161 |
-
if ($err_no != 0) {
|
162 |
-
$this->_handleError($err_no, $err_msg);
|
163 |
-
return $retry == true ? $this->_createSocket(false) : false;
|
164 |
-
} else {
|
165 |
-
// cache the socket
|
166 |
-
$this->_socket = $socket;
|
167 |
-
return $socket;
|
168 |
-
}
|
169 |
-
|
170 |
-
} catch (Exception $e) {
|
171 |
-
$this->_handleError($e->getCode(), $e->getMessage());
|
172 |
-
return $retry == true ? $this->_createSocket(false) : false;
|
173 |
-
}
|
174 |
-
}
|
175 |
-
|
176 |
-
/**
|
177 |
-
* Attempt to close and dereference a socket resource
|
178 |
-
*/
|
179 |
-
private function _destroySocket() {
|
180 |
-
$socket = $this->_socket;
|
181 |
-
$this->_socket = null;
|
182 |
-
fclose($socket);
|
183 |
-
}
|
184 |
-
|
185 |
-
|
186 |
-
/**
|
187 |
-
* Write $data through the given $socket
|
188 |
-
* @param $socket
|
189 |
-
* @param $data
|
190 |
-
* @param bool $retry
|
191 |
-
* @return bool
|
192 |
-
*/
|
193 |
-
private function _write($socket, $data, $retry = true) {
|
194 |
-
|
195 |
-
$bytes_sent = 0;
|
196 |
-
$bytes_total = strlen($data);
|
197 |
-
$socket_closed = false;
|
198 |
-
$success = true;
|
199 |
-
$max_bytes_per_write = 8192;
|
200 |
-
|
201 |
-
// if we have no data to write just return true
|
202 |
-
if ($bytes_total == 0) {
|
203 |
-
return true;
|
204 |
-
}
|
205 |
-
|
206 |
-
// try to write the data
|
207 |
-
while (!$socket_closed && $bytes_sent < $bytes_total) {
|
208 |
-
|
209 |
-
try {
|
210 |
-
$bytes = fwrite($socket, $data, $max_bytes_per_write);
|
211 |
-
|
212 |
-
if ($this->_debug()) {
|
213 |
-
$this->_log("Socket wrote ".$bytes." bytes");
|
214 |
-
}
|
215 |
-
|
216 |
-
// if we actually wrote data, then remove the written portion from $data left to write
|
217 |
-
if ($bytes > 0) {
|
218 |
-
$data = substr($data, $max_bytes_per_write);
|
219 |
-
}
|
220 |
-
|
221 |
-
} catch (Exception $e) {
|
222 |
-
$this->_handleError($e->getCode(), $e->getMessage());
|
223 |
-
$socket_closed = true;
|
224 |
-
}
|
225 |
-
|
226 |
-
if (isset($bytes) && $bytes) {
|
227 |
-
$bytes_sent += $bytes;
|
228 |
-
} else {
|
229 |
-
$socket_closed = true;
|
230 |
-
}
|
231 |
-
}
|
232 |
-
|
233 |
-
// create a new socket if the current one is closed and retry the message
|
234 |
-
if ($socket_closed) {
|
235 |
-
|
236 |
-
$this->_destroySocket();
|
237 |
-
|
238 |
-
if ($retry) {
|
239 |
-
if ($this->_debug()) {
|
240 |
-
$this->_log("Retrying socket write...");
|
241 |
-
}
|
242 |
-
$socket = $this->_getSocket();
|
243 |
-
if ($socket) return $this->_write($socket, $data, false);
|
244 |
-
}
|
245 |
-
|
246 |
-
return false;
|
247 |
-
}
|
248 |
-
|
249 |
-
|
250 |
-
// only wait for the response in debug mode or if we explicitly want to be synchronous
|
251 |
-
if ($this->_debug() || !$this->_async) {
|
252 |
-
$res = $this->handleResponse(fread($socket, 2048));
|
253 |
-
if ($res["status"] != "200") {
|
254 |
-
$this->_handleError($res["status"], $res["body"]);
|
255 |
-
$success = false;
|
256 |
-
}
|
257 |
-
}
|
258 |
-
|
259 |
-
return $success;
|
260 |
-
}
|
261 |
-
|
262 |
-
|
263 |
-
/**
|
264 |
-
* Parse the response from a socket write (only used for debugging)
|
265 |
-
* @param $response
|
266 |
-
* @return array
|
267 |
-
*/
|
268 |
-
private function handleResponse($response) {
|
269 |
-
|
270 |
-
$lines = explode("\n", $response);
|
271 |
-
|
272 |
-
// extract headers
|
273 |
-
$headers = array();
|
274 |
-
foreach($lines as $line) {
|
275 |
-
$kvsplit = explode(":", $line);
|
276 |
-
if (count($kvsplit) == 2) {
|
277 |
-
$header = $kvsplit[0];
|
278 |
-
$value = $kvsplit[1];
|
279 |
-
$headers[$header] = trim($value);
|
280 |
-
}
|
281 |
-
|
282 |
-
}
|
283 |
-
|
284 |
-
// extract status
|
285 |
-
$line_one_exploded = explode(" ", $lines[0]);
|
286 |
-
$status = $line_one_exploded[1];
|
287 |
-
|
288 |
-
// extract body
|
289 |
-
$body = $lines[count($lines) - 1];
|
290 |
-
|
291 |
-
// if the connection has been closed lets kill the socket
|
292 |
-
if ($headers['Connection'] == "close") {
|
293 |
-
$this->_destroySocket();
|
294 |
-
if ($this->_debug()) {
|
295 |
-
$this->_log("Server told us connection closed so lets destroy the socket so it'll reconnect on next call");
|
296 |
-
}
|
297 |
-
}
|
298 |
-
|
299 |
-
$ret = array(
|
300 |
-
"status" => $status,
|
301 |
-
"body" => $body,
|
302 |
-
);
|
303 |
-
|
304 |
-
return $ret;
|
305 |
-
}
|
306 |
-
|
307 |
-
|
308 |
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Portions of this class were borrowed from
|
4 |
+
* https://github.com/segmentio/analytics-php/blob/master/lib/Analytics/Consumer/Socket.php.
|
5 |
+
* Thanks for the work!
|
6 |
+
*
|
7 |
+
* WWWWWW||WWWWWW
|
8 |
+
* W W W||W W W
|
9 |
+
* ||
|
10 |
+
* ( OO )__________
|
11 |
+
* / | \
|
12 |
+
* /o o| MIT \
|
13 |
+
* \___/||_||__||_|| *
|
14 |
+
* || || || ||
|
15 |
+
* _||_|| _||_||
|
16 |
+
* (__|__|(__|__|
|
17 |
+
* (The MIT License)
|
18 |
+
*
|
19 |
+
* Copyright (c) 2013 Segment.io Inc. friends@segment.io
|
20 |
+
*
|
21 |
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
22 |
+
* documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
|
23 |
+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
24 |
+
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
25 |
+
*
|
26 |
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
27 |
+
* Software.
|
28 |
+
*
|
29 |
+
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
30 |
+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
31 |
+
* OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
32 |
+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
33 |
+
*/
|
34 |
+
require_once(dirname(__FILE__) . "/AbstractConsumer.php");
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Consumes messages and writes them to host/endpoint using a persistent socket
|
38 |
+
*/
|
39 |
+
class ConsumerStrategies_SocketConsumer extends ConsumerStrategies_AbstractConsumer {
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @var string the host to connect to (e.g. api.mixpanel.com)
|
43 |
+
*/
|
44 |
+
private $_host;
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @var string the host-relative endpoint to write to (e.g. /engage)
|
49 |
+
*/
|
50 |
+
private $_endpoint;
|
51 |
+
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @var int connect_timeout the socket connection timeout in seconds
|
55 |
+
*/
|
56 |
+
private $_connect_timeout;
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @var string the protocol to use for the socket connection
|
61 |
+
*/
|
62 |
+
private $_protocol;
|
63 |
+
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @var resource holds the socket resource
|
67 |
+
*/
|
68 |
+
private $_socket;
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @var bool whether or not to wait for a response
|
72 |
+
*/
|
73 |
+
private $_async;
|
74 |
+
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Creates a new SocketConsumer and assigns properties from the $options array
|
78 |
+
* @param array $options
|
79 |
+
*/
|
80 |
+
public function __construct($options = array()) {
|
81 |
+
parent::__construct($options);
|
82 |
+
|
83 |
+
|
84 |
+
$this->_host = $options['host'];
|
85 |
+
$this->_endpoint = $options['endpoint'];
|
86 |
+
$this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
|
87 |
+
$this->_async = array_key_exists('async', $options) && $options['async'] === false ? false : true;
|
88 |
+
|
89 |
+
if (array_key_exists('use_ssl', $options) && $options['use_ssl'] == true) {
|
90 |
+
$this->_protocol = "ssl";
|
91 |
+
$this->_port = 443;
|
92 |
+
} else {
|
93 |
+
$this->_protocol = "tcp";
|
94 |
+
$this->_port = 80;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Write using a persistent socket connection.
|
101 |
+
* @param array $batch
|
102 |
+
* @return bool
|
103 |
+
*/
|
104 |
+
public function persist($batch) {
|
105 |
+
|
106 |
+
$socket = $this->_getSocket();
|
107 |
+
if (!is_resource($socket)) {
|
108 |
+
return false;
|
109 |
+
}
|
110 |
+
|
111 |
+
$data = "data=".$this->_encode($batch);
|
112 |
+
|
113 |
+
$body = "";
|
114 |
+
$body.= "POST ".$this->_endpoint." HTTP/1.1\r\n";
|
115 |
+
$body.= "Host: " . $this->_host . "\r\n";
|
116 |
+
$body.= "Content-Type: application/x-www-form-urlencoded\r\n";
|
117 |
+
$body.= "Accept: application/json\r\n";
|
118 |
+
$body.= "Content-length: " . strlen($data) . "\r\n";
|
119 |
+
$body.= "\r\n";
|
120 |
+
$body.= $data;
|
121 |
+
|
122 |
+
return $this->_write($socket, $body);
|
123 |
+
}
|
124 |
+
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Return cached socket if open or create a new persistent socket
|
128 |
+
* @return bool|resource
|
129 |
+
*/
|
130 |
+
private function _getSocket() {
|
131 |
+
if(is_resource($this->_socket)) {
|
132 |
+
|
133 |
+
if ($this->_debug()) {
|
134 |
+
$this->_log("Using existing socket");
|
135 |
+
}
|
136 |
+
|
137 |
+
return $this->_socket;
|
138 |
+
} else {
|
139 |
+
|
140 |
+
if ($this->_debug()) {
|
141 |
+
$this->_log("Creating new socket at ".time());
|
142 |
+
}
|
143 |
+
|
144 |
+
return $this->_createSocket();
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Attempt to open a new socket connection, cache it, and return the resource
|
150 |
+
* @param bool $retry
|
151 |
+
* @return bool|resource
|
152 |
+
*/
|
153 |
+
private function _createSocket($retry = true) {
|
154 |
+
try {
|
155 |
+
$socket = pfsockopen($this->_protocol . "://" . $this->_host, $this->_port, $err_no, $err_msg, $this->_connect_timeout);
|
156 |
+
|
157 |
+
if ($this->_debug()) {
|
158 |
+
$this->_log("Opening socket connection to " . $this->_protocol . "://" . $this->_host . ":" . $this->_port);
|
159 |
+
}
|
160 |
+
|
161 |
+
if ($err_no != 0) {
|
162 |
+
$this->_handleError($err_no, $err_msg);
|
163 |
+
return $retry == true ? $this->_createSocket(false) : false;
|
164 |
+
} else {
|
165 |
+
// cache the socket
|
166 |
+
$this->_socket = $socket;
|
167 |
+
return $socket;
|
168 |
+
}
|
169 |
+
|
170 |
+
} catch (Exception $e) {
|
171 |
+
$this->_handleError($e->getCode(), $e->getMessage());
|
172 |
+
return $retry == true ? $this->_createSocket(false) : false;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Attempt to close and dereference a socket resource
|
178 |
+
*/
|
179 |
+
private function _destroySocket() {
|
180 |
+
$socket = $this->_socket;
|
181 |
+
$this->_socket = null;
|
182 |
+
fclose($socket);
|
183 |
+
}
|
184 |
+
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Write $data through the given $socket
|
188 |
+
* @param $socket
|
189 |
+
* @param $data
|
190 |
+
* @param bool $retry
|
191 |
+
* @return bool
|
192 |
+
*/
|
193 |
+
private function _write($socket, $data, $retry = true) {
|
194 |
+
|
195 |
+
$bytes_sent = 0;
|
196 |
+
$bytes_total = strlen($data);
|
197 |
+
$socket_closed = false;
|
198 |
+
$success = true;
|
199 |
+
$max_bytes_per_write = 8192;
|
200 |
+
|
201 |
+
// if we have no data to write just return true
|
202 |
+
if ($bytes_total == 0) {
|
203 |
+
return true;
|
204 |
+
}
|
205 |
+
|
206 |
+
// try to write the data
|
207 |
+
while (!$socket_closed && $bytes_sent < $bytes_total) {
|
208 |
+
|
209 |
+
try {
|
210 |
+
$bytes = fwrite($socket, $data, $max_bytes_per_write);
|
211 |
+
|
212 |
+
if ($this->_debug()) {
|
213 |
+
$this->_log("Socket wrote ".$bytes." bytes");
|
214 |
+
}
|
215 |
+
|
216 |
+
// if we actually wrote data, then remove the written portion from $data left to write
|
217 |
+
if ($bytes > 0) {
|
218 |
+
$data = substr($data, $max_bytes_per_write);
|
219 |
+
}
|
220 |
+
|
221 |
+
} catch (Exception $e) {
|
222 |
+
$this->_handleError($e->getCode(), $e->getMessage());
|
223 |
+
$socket_closed = true;
|
224 |
+
}
|
225 |
+
|
226 |
+
if (isset($bytes) && $bytes) {
|
227 |
+
$bytes_sent += $bytes;
|
228 |
+
} else {
|
229 |
+
$socket_closed = true;
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
// create a new socket if the current one is closed and retry the message
|
234 |
+
if ($socket_closed) {
|
235 |
+
|
236 |
+
$this->_destroySocket();
|
237 |
+
|
238 |
+
if ($retry) {
|
239 |
+
if ($this->_debug()) {
|
240 |
+
$this->_log("Retrying socket write...");
|
241 |
+
}
|
242 |
+
$socket = $this->_getSocket();
|
243 |
+
if ($socket) return $this->_write($socket, $data, false);
|
244 |
+
}
|
245 |
+
|
246 |
+
return false;
|
247 |
+
}
|
248 |
+
|
249 |
+
|
250 |
+
// only wait for the response in debug mode or if we explicitly want to be synchronous
|
251 |
+
if ($this->_debug() || !$this->_async) {
|
252 |
+
$res = $this->handleResponse(fread($socket, 2048));
|
253 |
+
if ($res["status"] != "200") {
|
254 |
+
$this->_handleError($res["status"], $res["body"]);
|
255 |
+
$success = false;
|
256 |
+
}
|
257 |
+
}
|
258 |
+
|
259 |
+
return $success;
|
260 |
+
}
|
261 |
+
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Parse the response from a socket write (only used for debugging)
|
265 |
+
* @param $response
|
266 |
+
* @return array
|
267 |
+
*/
|
268 |
+
private function handleResponse($response) {
|
269 |
+
|
270 |
+
$lines = explode("\n", $response);
|
271 |
+
|
272 |
+
// extract headers
|
273 |
+
$headers = array();
|
274 |
+
foreach($lines as $line) {
|
275 |
+
$kvsplit = explode(":", $line);
|
276 |
+
if (count($kvsplit) == 2) {
|
277 |
+
$header = $kvsplit[0];
|
278 |
+
$value = $kvsplit[1];
|
279 |
+
$headers[$header] = trim($value);
|
280 |
+
}
|
281 |
+
|
282 |
+
}
|
283 |
+
|
284 |
+
// extract status
|
285 |
+
$line_one_exploded = explode(" ", $lines[0]);
|
286 |
+
$status = $line_one_exploded[1];
|
287 |
+
|
288 |
+
// extract body
|
289 |
+
$body = $lines[count($lines) - 1];
|
290 |
+
|
291 |
+
// if the connection has been closed lets kill the socket
|
292 |
+
if ($headers['Connection'] == "close") {
|
293 |
+
$this->_destroySocket();
|
294 |
+
if ($this->_debug()) {
|
295 |
+
$this->_log("Server told us connection closed so lets destroy the socket so it'll reconnect on next call");
|
296 |
+
}
|
297 |
+
}
|
298 |
+
|
299 |
+
$ret = array(
|
300 |
+
"status" => $status,
|
301 |
+
"body" => $body,
|
302 |
+
);
|
303 |
+
|
304 |
+
return $ret;
|
305 |
+
}
|
306 |
+
|
307 |
+
|
308 |
}
|
modules/supsystic_promo/models/classes/lib/Mixpanel.php
CHANGED
@@ -1,302 +1,302 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
require_once(dirname(__FILE__) . "/Base/MixpanelBase.php");
|
4 |
-
require_once(dirname(__FILE__) . "/Producers/MixpanelPeople.php");
|
5 |
-
require_once(dirname(__FILE__) . "/Producers/MixpanelEvents.php");
|
6 |
-
|
7 |
-
/**
|
8 |
-
* This is the main class for the Mixpanel PHP Library which provides all of the methods you need to track events and
|
9 |
-
* create/update profiles.
|
10 |
-
*
|
11 |
-
* Architecture
|
12 |
-
* -------------
|
13 |
-
*
|
14 |
-
* This library is built such that all messages are buffered in an in-memory "queue"
|
15 |
-
* The queue will be automatically flushed at the end of every request. Alternatively, you can call "flush()" manually
|
16 |
-
* at any time. Flushed messages will be passed to a Consumer's "persist" method. The library comes with a handful of
|
17 |
-
* Consumers. The "CurlConsumer" is used by default which will send the messages to Mixpanel using forked cURL processes.
|
18 |
-
* You can implement your own custom Consumer to customize how a message is sent to Mixpanel. This can be useful when
|
19 |
-
* you want to put messages onto a distributed queue (such as ActiveMQ or Kestrel) instead of writing to Mixpanel in
|
20 |
-
* the user thread.
|
21 |
-
*
|
22 |
-
* Options
|
23 |
-
* -------------
|
24 |
-
*
|
25 |
-
* <table width="100%" cellpadding="5">
|
26 |
-
* <tr>
|
27 |
-
* <th>Option</th>
|
28 |
-
* <th>Description</th>
|
29 |
-
* <th>Default</th>
|
30 |
-
* </tr>
|
31 |
-
* <tr>
|
32 |
-
* <td>max_queue_size</td>
|
33 |
-
* <td>The maximum number of items to buffer in memory before flushing</td>
|
34 |
-
* <td>1000</td>
|
35 |
-
* </tr>
|
36 |
-
* <tr>
|
37 |
-
* <td>debug</td>
|
38 |
-
* <td>Enable/disable debug mode</td>
|
39 |
-
* <td>false</td>
|
40 |
-
* </tr>
|
41 |
-
* <tr>
|
42 |
-
* <td>consumer</td>
|
43 |
-
* <td>The consumer to use for writing messages</td>
|
44 |
-
* <td>curl</td>
|
45 |
-
* </tr>
|
46 |
-
* <tr>
|
47 |
-
* <td>consumers</td>
|
48 |
-
* <td>An array of custom consumers in the format array(consumer_key => class_name)</td>
|
49 |
-
* <td>null</td>
|
50 |
-
* </tr>
|
51 |
-
* <tr>
|
52 |
-
* <td>host</td>
|
53 |
-
* <td>The host name for api calls (used by some consumers)</td>
|
54 |
-
* <td>api.mixpanel.com</td>
|
55 |
-
* </tr>
|
56 |
-
* <tr>
|
57 |
-
* <td>events_endpoint</td>
|
58 |
-
* <td>The endpoint for tracking events (relative to the host)</td>
|
59 |
-
* <td>/events</td>
|
60 |
-
* </tr>
|
61 |
-
* <tr>
|
62 |
-
* <td>people_endpoint</td>
|
63 |
-
* <td>The endpoint for making people updates (relative to the host)</td>
|
64 |
-
* <td>/engage</td>
|
65 |
-
* </tr>
|
66 |
-
* <tr>
|
67 |
-
* <td>use_ssl</td>
|
68 |
-
* <td>Tell the consumer whether or not to use ssl (when available)</td>
|
69 |
-
* <td>true</td>
|
70 |
-
* </tr>
|
71 |
-
* <tr>
|
72 |
-
* <td>error_callback</td>
|
73 |
-
* <td>The name of a function to be called on consumption failures</td>
|
74 |
-
* <td>null</td>
|
75 |
-
* </tr>
|
76 |
-
* <tr>
|
77 |
-
* <td>connect_timeout</td>
|
78 |
-
* <td>In both the SocketConsumer and CurlConsumer, this is used for the connection timeout (i.e. How long it has take to actually make a connection).
|
79 |
-
* <td>5</td>
|
80 |
-
* </tr>
|
81 |
-
* <tr>
|
82 |
-
* <td>timeout</td>
|
83 |
-
* <td>In the CurlConsumer (non-forked), it is used to determine how long the cURL call has to execute.
|
84 |
-
* <td>30</td>
|
85 |
-
* </tr>
|
86 |
-
* </table>
|
87 |
-
*
|
88 |
-
* Example: Tracking an Event
|
89 |
-
* -------------
|
90 |
-
*
|
91 |
-
* $mp = Mixpanel::getInstance("MY_TOKEN");
|
92 |
-
*
|
93 |
-
* $mp->track("My Event");
|
94 |
-
*
|
95 |
-
* Example: Setting Profile Properties
|
96 |
-
* -------------
|
97 |
-
*
|
98 |
-
* $mp = Mixpanel::getInstance("MY_TOKEN", array("use_ssl" => false));
|
99 |
-
*
|
100 |
-
* $mp->people->set(12345, array(
|
101 |
-
* '$first_name' => "John",
|
102 |
-
* '$last_name' => "Doe",
|
103 |
-
* '$email' => "john.doe@example.com",
|
104 |
-
* '$phone' => "5555555555",
|
105 |
-
* 'Favorite Color' => "red"
|
106 |
-
* ));
|
107 |
-
*
|
108 |
-
*/
|
109 |
-
class Mixpanel extends Base_MixpanelBase {
|
110 |
-
|
111 |
-
|
112 |
-
/**
|
113 |
-
* An instance of the MixpanelPeople class (used to create/update profiles)
|
114 |
-
* @var MixpanelPeople
|
115 |
-
*/
|
116 |
-
public $people;
|
117 |
-
|
118 |
-
|
119 |
-
/**
|
120 |
-
* An instance of the MixpanelEvents class
|
121 |
-
* @var Producers_MixpanelEvents
|
122 |
-
*/
|
123 |
-
private $_events;
|
124 |
-
|
125 |
-
|
126 |
-
/**
|
127 |
-
* An instance of the Mixpanel class (for singleton use)
|
128 |
-
* @var Mixpanel
|
129 |
-
*/
|
130 |
-
private static $_instance;
|
131 |
-
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Instantiates a new Mixpanel instance.
|
135 |
-
* @param $token
|
136 |
-
* @param array $options
|
137 |
-
*/
|
138 |
-
public function __construct($token, $options = array()) {
|
139 |
-
parent::__construct($options);
|
140 |
-
$this->people = new Producers_MixpanelPeople($token, $options);
|
141 |
-
$this->_events = new Producers_MixpanelEvents($token, $options);
|
142 |
-
}
|
143 |
-
|
144 |
-
|
145 |
-
/**
|
146 |
-
* Returns a singleton instance of Mixpanel
|
147 |
-
* @param $token
|
148 |
-
* @param array $options
|
149 |
-
* @return Mixpanel
|
150 |
-
*/
|
151 |
-
public static function getInstance($token, $options = array()) {
|
152 |
-
if(!isset(self::$_instance)) {
|
153 |
-
self::$_instance = new Mixpanel($token, $options);
|
154 |
-
}
|
155 |
-
return self::$_instance;
|
156 |
-
}
|
157 |
-
|
158 |
-
|
159 |
-
/**
|
160 |
-
* Add an array representing a message to be sent to Mixpanel to the in-memory queue.
|
161 |
-
* @param array $message
|
162 |
-
*/
|
163 |
-
public function enqueue($message = array()) {
|
164 |
-
$this->_events->enqueue($message);
|
165 |
-
}
|
166 |
-
|
167 |
-
|
168 |
-
/**
|
169 |
-
* Add an array representing a list of messages to be sent to Mixpanel to a queue.
|
170 |
-
* @param array $messages
|
171 |
-
*/
|
172 |
-
public function enqueueAll($messages = array()) {
|
173 |
-
$this->_events->enqueueAll($messages);
|
174 |
-
}
|
175 |
-
|
176 |
-
|
177 |
-
/**
|
178 |
-
* Flush the events queue
|
179 |
-
* @param int $desired_batch_size
|
180 |
-
*/
|
181 |
-
public function flush($desired_batch_size = 50) {
|
182 |
-
$this->_events->flush($desired_batch_size);
|
183 |
-
}
|
184 |
-
|
185 |
-
|
186 |
-
/**
|
187 |
-
* Empty the events queue
|
188 |
-
*/
|
189 |
-
public function reset() {
|
190 |
-
$this->_events->reset();
|
191 |
-
}
|
192 |
-
|
193 |
-
|
194 |
-
/**
|
195 |
-
* Identify the user you want to associate to tracked events
|
196 |
-
* @param string|int $user_id
|
197 |
-
*/
|
198 |
-
public function identify($user_id) {
|
199 |
-
$this->_events->identify($user_id);
|
200 |
-
}
|
201 |
-
|
202 |
-
/**
|
203 |
-
* Track an event defined by $event associated with metadata defined by $properties
|
204 |
-
* @param string $event
|
205 |
-
* @param array $properties
|
206 |
-
*/
|
207 |
-
public function track($event, $properties = array()) {
|
208 |
-
$this->_events->track($event, $properties);
|
209 |
-
}
|
210 |
-
|
211 |
-
|
212 |
-
/**
|
213 |
-
* Register a property to be sent with every event.
|
214 |
-
*
|
215 |
-
* If the property has already been registered, it will be
|
216 |
-
* overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
|
217 |
-
* @param string $property
|
218 |
-
* @param mixed $value
|
219 |
-
*/
|
220 |
-
public function register($property, $value) {
|
221 |
-
$this->_events->register($property, $value);
|
222 |
-
}
|
223 |
-
|
224 |
-
|
225 |
-
/**
|
226 |
-
* Register multiple properties to be sent with every event.
|
227 |
-
*
|
228 |
-
* If any of the properties have already been registered,
|
229 |
-
* they will be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
|
230 |
-
* instance.
|
231 |
-
* @param array $props_and_vals
|
232 |
-
*/
|
233 |
-
public function registerAll($props_and_vals = array()) {
|
234 |
-
$this->_events->registerAll($props_and_vals);
|
235 |
-
}
|
236 |
-
|
237 |
-
|
238 |
-
/**
|
239 |
-
* Register a property to be sent with every event.
|
240 |
-
*
|
241 |
-
* If the property has already been registered, it will NOT be
|
242 |
-
* overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
|
243 |
-
* @param $property
|
244 |
-
* @param $value
|
245 |
-
*/
|
246 |
-
public function registerOnce($property, $value) {
|
247 |
-
$this->_events->registerOnce($property, $value);
|
248 |
-
}
|
249 |
-
|
250 |
-
|
251 |
-
/**
|
252 |
-
* Register multiple properties to be sent with every event.
|
253 |
-
*
|
254 |
-
* If any of the properties have already been registered,
|
255 |
-
* they will NOT be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
|
256 |
-
* instance.
|
257 |
-
* @param array $props_and_vals
|
258 |
-
*/
|
259 |
-
public function registerAllOnce($props_and_vals = array()) {
|
260 |
-
$this->_events->registerAllOnce($props_and_vals);
|
261 |
-
}
|
262 |
-
|
263 |
-
|
264 |
-
/**
|
265 |
-
* Un-register an property to be sent with every event.
|
266 |
-
* @param string $property
|
267 |
-
*/
|
268 |
-
public function unregister($property) {
|
269 |
-
$this->_events->unregister($property);
|
270 |
-
}
|
271 |
-
|
272 |
-
|
273 |
-
/**
|
274 |
-
* Un-register a list of properties to be sent with every event.
|
275 |
-
* @param array $properties
|
276 |
-
*/
|
277 |
-
public function unregisterAll($properties) {
|
278 |
-
$this->_events->unregisterAll($properties);
|
279 |
-
}
|
280 |
-
|
281 |
-
|
282 |
-
/**
|
283 |
-
* Get a property that is set to be sent with every event
|
284 |
-
* @param string $property
|
285 |
-
* @return mixed
|
286 |
-
*/
|
287 |
-
public function getProperty($property)
|
288 |
-
{
|
289 |
-
return $this->_events->getProperty($property);
|
290 |
-
}
|
291 |
-
|
292 |
-
|
293 |
-
/**
|
294 |
-
* Alias an existing id with a different unique id. This is helpful when you want to associate a generated id
|
295 |
-
* (such as a session id) to a user id or username.
|
296 |
-
* @param string|int $original_id
|
297 |
-
* @param string|int $new_id
|
298 |
-
*/
|
299 |
-
public function createAlias($original_id, $new_id) {
|
300 |
-
$this->_events->createAlias($original_id, $new_id);
|
301 |
-
}
|
302 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once(dirname(__FILE__) . "/Base/MixpanelBase.php");
|
4 |
+
require_once(dirname(__FILE__) . "/Producers/MixpanelPeople.php");
|
5 |
+
require_once(dirname(__FILE__) . "/Producers/MixpanelEvents.php");
|
6 |
+
|
7 |
+
/**
|
8 |
+
* This is the main class for the Mixpanel PHP Library which provides all of the methods you need to track events and
|
9 |
+
* create/update profiles.
|
10 |
+
*
|
11 |
+
* Architecture
|
12 |
+
* -------------
|
13 |
+
*
|
14 |
+
* This library is built such that all messages are buffered in an in-memory "queue"
|
15 |
+
* The queue will be automatically flushed at the end of every request. Alternatively, you can call "flush()" manually
|
16 |
+
* at any time. Flushed messages will be passed to a Consumer's "persist" method. The library comes with a handful of
|
17 |
+
* Consumers. The "CurlConsumer" is used by default which will send the messages to Mixpanel using forked cURL processes.
|
18 |
+
* You can implement your own custom Consumer to customize how a message is sent to Mixpanel. This can be useful when
|
19 |
+
* you want to put messages onto a distributed queue (such as ActiveMQ or Kestrel) instead of writing to Mixpanel in
|
20 |
+
* the user thread.
|
21 |
+
*
|
22 |
+
* Options
|
23 |
+
* -------------
|
24 |
+
*
|
25 |
+
* <table width="100%" cellpadding="5">
|
26 |
+
* <tr>
|
27 |
+
* <th>Option</th>
|
28 |
+
* <th>Description</th>
|
29 |
+
* <th>Default</th>
|
30 |
+
* </tr>
|
31 |
+
* <tr>
|
32 |
+
* <td>max_queue_size</td>
|
33 |
+
* <td>The maximum number of items to buffer in memory before flushing</td>
|
34 |
+
* <td>1000</td>
|
35 |
+
* </tr>
|
36 |
+
* <tr>
|
37 |
+
* <td>debug</td>
|
38 |
+
* <td>Enable/disable debug mode</td>
|
39 |
+
* <td>false</td>
|
40 |
+
* </tr>
|
41 |
+
* <tr>
|
42 |
+
* <td>consumer</td>
|
43 |
+
* <td>The consumer to use for writing messages</td>
|
44 |
+
* <td>curl</td>
|
45 |
+
* </tr>
|
46 |
+
* <tr>
|
47 |
+
* <td>consumers</td>
|
48 |
+
* <td>An array of custom consumers in the format array(consumer_key => class_name)</td>
|
49 |
+
* <td>null</td>
|
50 |
+
* </tr>
|
51 |
+
* <tr>
|
52 |
+
* <td>host</td>
|
53 |
+
* <td>The host name for api calls (used by some consumers)</td>
|
54 |
+
* <td>api.mixpanel.com</td>
|
55 |
+
* </tr>
|
56 |
+
* <tr>
|
57 |
+
* <td>events_endpoint</td>
|
58 |
+
* <td>The endpoint for tracking events (relative to the host)</td>
|
59 |
+
* <td>/events</td>
|
60 |
+
* </tr>
|
61 |
+
* <tr>
|
62 |
+
* <td>people_endpoint</td>
|
63 |
+
* <td>The endpoint for making people updates (relative to the host)</td>
|
64 |
+
* <td>/engage</td>
|
65 |
+
* </tr>
|
66 |
+
* <tr>
|
67 |
+
* <td>use_ssl</td>
|
68 |
+
* <td>Tell the consumer whether or not to use ssl (when available)</td>
|
69 |
+
* <td>true</td>
|
70 |
+
* </tr>
|
71 |
+
* <tr>
|
72 |
+
* <td>error_callback</td>
|
73 |
+
* <td>The name of a function to be called on consumption failures</td>
|
74 |
+
* <td>null</td>
|
75 |
+
* </tr>
|
76 |
+
* <tr>
|
77 |
+
* <td>connect_timeout</td>
|
78 |
+
* <td>In both the SocketConsumer and CurlConsumer, this is used for the connection timeout (i.e. How long it has take to actually make a connection).
|
79 |
+
* <td>5</td>
|
80 |
+
* </tr>
|
81 |
+
* <tr>
|
82 |
+
* <td>timeout</td>
|
83 |
+
* <td>In the CurlConsumer (non-forked), it is used to determine how long the cURL call has to execute.
|
84 |
+
* <td>30</td>
|
85 |
+
* </tr>
|
86 |
+
* </table>
|
87 |
+
*
|
88 |
+
* Example: Tracking an Event
|
89 |
+
* -------------
|
90 |
+
*
|
91 |
+
* $mp = Mixpanel::getInstance("MY_TOKEN");
|
92 |
+
*
|
93 |
+
* $mp->track("My Event");
|
94 |
+
*
|
95 |
+
* Example: Setting Profile Properties
|
96 |
+
* -------------
|
97 |
+
*
|
98 |
+
* $mp = Mixpanel::getInstance("MY_TOKEN", array("use_ssl" => false));
|
99 |
+
*
|
100 |
+
* $mp->people->set(12345, array(
|
101 |
+
* '$first_name' => "John",
|
102 |
+
* '$last_name' => "Doe",
|
103 |
+
* '$email' => "john.doe@example.com",
|
104 |
+
* '$phone' => "5555555555",
|
105 |
+
* 'Favorite Color' => "red"
|
106 |
+
* ));
|
107 |
+
*
|
108 |
+
*/
|
109 |
+
class Mixpanel extends Base_MixpanelBase {
|
110 |
+
|
111 |
+
|
112 |
+
/**
|
113 |
+
* An instance of the MixpanelPeople class (used to create/update profiles)
|
114 |
+
* @var MixpanelPeople
|
115 |
+
*/
|
116 |
+
public $people;
|
117 |
+
|
118 |
+
|
119 |
+
/**
|
120 |
+
* An instance of the MixpanelEvents class
|
121 |
+
* @var Producers_MixpanelEvents
|
122 |
+
*/
|
123 |
+
private $_events;
|
124 |
+
|
125 |
+
|
126 |
+
/**
|
127 |
+
* An instance of the Mixpanel class (for singleton use)
|
128 |
+
* @var Mixpanel
|
129 |
+
*/
|
130 |
+
private static $_instance;
|
131 |
+
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Instantiates a new Mixpanel instance.
|
135 |
+
* @param $token
|
136 |
+
* @param array $options
|
137 |
+
*/
|
138 |
+
public function __construct($token, $options = array()) {
|
139 |
+
parent::__construct($options);
|
140 |
+
$this->people = new Producers_MixpanelPeople($token, $options);
|
141 |
+
$this->_events = new Producers_MixpanelEvents($token, $options);
|
142 |
+
}
|
143 |
+
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Returns a singleton instance of Mixpanel
|
147 |
+
* @param $token
|
148 |
+
* @param array $options
|
149 |
+
* @return Mixpanel
|
150 |
+
*/
|
151 |
+
public static function getInstance($token, $options = array()) {
|
152 |
+
if(!isset(self::$_instance)) {
|
153 |
+
self::$_instance = new Mixpanel($token, $options);
|
154 |
+
}
|
155 |
+
return self::$_instance;
|
156 |
+
}
|
157 |
+
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Add an array representing a message to be sent to Mixpanel to the in-memory queue.
|
161 |
+
* @param array $message
|
162 |
+
*/
|
163 |
+
public function enqueue($message = array()) {
|
164 |
+
$this->_events->enqueue($message);
|
165 |
+
}
|
166 |
+
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Add an array representing a list of messages to be sent to Mixpanel to a queue.
|
170 |
+
* @param array $messages
|
171 |
+
*/
|
172 |
+
public function enqueueAll($messages = array()) {
|
173 |
+
$this->_events->enqueueAll($messages);
|
174 |
+
}
|
175 |
+
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Flush the events queue
|
179 |
+
* @param int $desired_batch_size
|
180 |
+
*/
|
181 |
+
public function flush($desired_batch_size = 50) {
|
182 |
+
$this->_events->flush($desired_batch_size);
|
183 |
+
}
|
184 |
+
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Empty the events queue
|
188 |
+
*/
|
189 |
+
public function reset() {
|
190 |
+
$this->_events->reset();
|
191 |
+
}
|
192 |
+
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Identify the user you want to associate to tracked events
|
196 |
+
* @param string|int $user_id
|
197 |
+
*/
|
198 |
+
public function identify($user_id) {
|
199 |
+
$this->_events->identify($user_id);
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Track an event defined by $event associated with metadata defined by $properties
|
204 |
+
* @param string $event
|
205 |
+
* @param array $properties
|
206 |
+
*/
|
207 |
+
public function track($event, $properties = array()) {
|
208 |
+
$this->_events->track($event, $properties);
|
209 |
+
}
|
210 |
+
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Register a property to be sent with every event.
|
214 |
+
*
|
215 |
+
* If the property has already been registered, it will be
|
216 |
+
* overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
|
217 |
+
* @param string $property
|
218 |
+
* @param mixed $value
|
219 |
+
*/
|
220 |
+
public function register($property, $value) {
|
221 |
+
$this->_events->register($property, $value);
|
222 |
+
}
|
223 |
+
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Register multiple properties to be sent with every event.
|
227 |
+
*
|
228 |
+
* If any of the properties have already been registered,
|
229 |
+
* they will be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
|
230 |
+
* instance.
|
231 |
+
* @param array $props_and_vals
|
232 |
+
*/
|
233 |
+
public function registerAll($props_and_vals = array()) {
|
234 |
+
$this->_events->registerAll($props_and_vals);
|
235 |
+
}
|
236 |
+
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Register a property to be sent with every event.
|
240 |
+
*
|
241 |
+
* If the property has already been registered, it will NOT be
|
242 |
+
* overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
|
243 |
+
* @param $property
|
244 |
+
* @param $value
|
245 |
+
*/
|
246 |
+
public function registerOnce($property, $value) {
|
247 |
+
$this->_events->registerOnce($property, $value);
|
248 |
+
}
|
249 |
+
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Register multiple properties to be sent with every event.
|
253 |
+
*
|
254 |
+
* If any of the properties have already been registered,
|
255 |
+
* they will NOT be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
|
256 |
+
* instance.
|
257 |
+
* @param array $props_and_vals
|
258 |
+
*/
|
259 |
+
public function registerAllOnce($props_and_vals = array()) {
|
260 |
+
$this->_events->registerAllOnce($props_and_vals);
|
261 |
+
}
|
262 |
+
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Un-register an property to be sent with every event.
|
266 |
+
* @param string $property
|
267 |
+
*/
|
268 |
+
public function unregister($property) {
|
269 |
+
$this->_events->unregister($property);
|
270 |
+
}
|
271 |
+
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Un-register a list of properties to be sent with every event.
|
275 |
+
* @param array $properties
|
276 |
+
*/
|
277 |
+
public function unregisterAll($properties) {
|
278 |
+
$this->_events->unregisterAll($properties);
|
279 |
+
}
|
280 |
+
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Get a property that is set to be sent with every event
|
284 |
+
* @param string $property
|
285 |
+
* @return mixed
|
286 |
+
*/
|
287 |
+
public function getProperty($property)
|
288 |
+
{
|
289 |
+
return $this->_events->getProperty($property);
|
290 |
+
}
|
291 |
+
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Alias an existing id with a different unique id. This is helpful when you want to associate a generated id
|
295 |
+
* (such as a session id) to a user id or username.
|
296 |
+
* @param string|int $original_id
|
297 |
+
* @param string|int $new_id
|
298 |
+
*/
|
299 |
+
public function createAlias($original_id, $new_id) {
|
300 |
+
$this->_events->createAlias($original_id, $new_id);
|
301 |
+
}
|
302 |
+
}
|
modules/supsystic_promo/models/classes/lib/Producers/MixpanelBaseProducer.php
CHANGED
@@ -1,229 +1,229 @@
|
|
1 |
-
<?php
|
2 |
-
require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
|
3 |
-
require_once(dirname(__FILE__) . "/../ConsumerStrategies/FileConsumer.php");
|
4 |
-
require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
|
5 |
-
require_once(dirname(__FILE__) . "/../ConsumerStrategies/SocketConsumer.php");
|
6 |
-
|
7 |
-
if (!function_exists('json_encode')) {
|
8 |
-
throw new Exception('The JSON PHP extension is required.');
|
9 |
-
}
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Provides some base methods for use by a message Producer
|
13 |
-
*/
|
14 |
-
abstract class Producers_MixpanelBaseProducer extends Base_MixpanelBase {
|
15 |
-
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @var string a token associated to a Mixpanel project
|
19 |
-
*/
|
20 |
-
protected $_token;
|
21 |
-
|
22 |
-
|
23 |
-
/**
|
24 |
-
* @var array a queue to hold messages in memory before flushing in batches
|
25 |
-
*/
|
26 |
-
private $_queue = array();
|
27 |
-
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @var ConsumerStrategies_AbstractConsumer the consumer to use when flushing messages
|
31 |
-
*/
|
32 |
-
private $_consumer = null;
|
33 |
-
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @var array The list of available consumers
|
37 |
-
*/
|
38 |
-
private $_consumers = array(
|
39 |
-
"file" => "ConsumerStrategies_FileConsumer",
|
40 |
-
"curl" => "ConsumerStrategies_CurlConsumer",
|
41 |
-
"socket" => "ConsumerStrategies_SocketConsumer"
|
42 |
-
);
|
43 |
-
|
44 |
-
|
45 |
-
/**
|
46 |
-
* If the queue reaches this size we'll auto-flush to prevent out of memory errors
|
47 |
-
* @var int
|
48 |
-
*/
|
49 |
-
protected $_max_queue_size = 1000;
|
50 |
-
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Creates a new MixpanelBaseProducer, assings Mixpanel project token, registers custom Consumers, and instantiates
|
54 |
-
* the desired consumer
|
55 |
-
* @param $token
|
56 |
-
* @param array $options
|
57 |
-
*/
|
58 |
-
public function __construct($token, $options = array()) {
|
59 |
-
|
60 |
-
parent::__construct($options);
|
61 |
-
|
62 |
-
// register any customer consumers
|
63 |
-
if (array_key_exists("consumers", $options)) {
|
64 |
-
$this->_consumers = array_merge($this->_consumers, $options['consumers']);
|
65 |
-
}
|
66 |
-
|
67 |
-
// set max queue size
|
68 |
-
if (array_key_exists("max_queue_size", $options)) {
|
69 |
-
$this->_max_queue_size = $options['max_queue_size'];
|
70 |
-
}
|
71 |
-
|
72 |
-
// associate token
|
73 |
-
$this->_token = $token;
|
74 |
-
|
75 |
-
if ($this->_debug()) {
|
76 |
-
$this->_log("Using token: ".$this->_token);
|
77 |
-
}
|
78 |
-
|
79 |
-
// instantiate the chosen consumer
|
80 |
-
$this->_consumer = $this->_getConsumer();
|
81 |
-
|
82 |
-
}
|
83 |
-
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Flush the queue when we destruct the client with retries
|
87 |
-
*/
|
88 |
-
public function __destruct() {
|
89 |
-
$attempts = 0;
|
90 |
-
$max_attempts = 10;
|
91 |
-
$success = false;
|
92 |
-
while (!$success && $attempts < $max_attempts) {
|
93 |
-
if ($this->_debug()) {
|
94 |
-
$this->_log("destruct flush attempt #".($attempts+1));
|
95 |
-
}
|
96 |
-
$success = $this->flush();
|
97 |
-
$attempts++;
|
98 |
-
}
|
99 |
-
}
|
100 |
-
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Iterate the queue and write in batches using the instantiated Consumer Strategy
|
104 |
-
* @param int $desired_batch_size
|
105 |
-
* @return bool whether or not the flush was successful
|
106 |
-
*/
|
107 |
-
public function flush($desired_batch_size = 50) {
|
108 |
-
$queue_size = count($this->_queue);
|
109 |
-
$succeeded = true;
|
110 |
-
if ($this->_debug()) {
|
111 |
-
$this->_log("Flush called - queue size: ".$queue_size);
|
112 |
-
}
|
113 |
-
|
114 |
-
while($queue_size > 0 && $succeeded) {
|
115 |
-
$batch_size = min(array($queue_size, $desired_batch_size, $this->_options['max_batch_size']));
|
116 |
-
$batch = array_splice($this->_queue, 0, $batch_size);
|
117 |
-
$succeeded = $this->_persist($batch);
|
118 |
-
|
119 |
-
if (!$succeeded) {
|
120 |
-
if ($this->_debug()) {
|
121 |
-
$this->_log("Batch consumption failed!");
|
122 |
-
}
|
123 |
-
$this->_queue = array_merge($batch, $this->_queue);
|
124 |
-
|
125 |
-
if ($this->_debug()) {
|
126 |
-
$this->_log("added batch back to queue, queue size is now $queue_size");
|
127 |
-
}
|
128 |
-
}
|
129 |
-
|
130 |
-
$queue_size = count($this->_queue);
|
131 |
-
|
132 |
-
if ($this->_debug()) {
|
133 |
-
$this->_log("Batch of $batch_size consumed, queue size is now $queue_size");
|
134 |
-
}
|
135 |
-
}
|
136 |
-
return $succeeded;
|
137 |
-
}
|
138 |
-
|
139 |
-
|
140 |
-
/**
|
141 |
-
* Empties the queue without persisting any of the messages
|
142 |
-
*/
|
143 |
-
public function reset() {
|
144 |
-
$this->_queue = array();
|
145 |
-
}
|
146 |
-
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Returns the in-memory queue
|
150 |
-
* @return array
|
151 |
-
*/
|
152 |
-
public function getQueue() {
|
153 |
-
return $this->_queue;
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* Returns the current Mixpanel project token
|
158 |
-
* @return string
|
159 |
-
*/
|
160 |
-
public function getToken() {
|
161 |
-
return $this->_token;
|
162 |
-
}
|
163 |
-
|
164 |
-
|
165 |
-
/**
|
166 |
-
* Given a strategy type, return a new PersistenceStrategy object
|
167 |
-
* @return ConsumerStrategies_AbstractConsumer
|
168 |
-
*/
|
169 |
-
protected function _getConsumer() {
|
170 |
-
$key = $this->_options['consumer'];
|
171 |
-
$Strategy = $this->_consumers[$key];
|
172 |
-
if ($this->_debug()) {
|
173 |
-
$this->_log("Using consumer: " . $key . " -> " . $Strategy);
|
174 |
-
}
|
175 |
-
$this->_options['endpoint'] = $this->_getEndpoint();
|
176 |
-
|
177 |
-
return new $Strategy($this->_options);
|
178 |
-
}
|
179 |
-
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Add an array representing a message to be sent to Mixpanel to a queue.
|
183 |
-
* @param array $message
|
184 |
-
*/
|
185 |
-
public function enqueue($message = array()) {
|
186 |
-
array_push($this->_queue, $message);
|
187 |
-
|
188 |
-
// force a flush if we've reached our threshold
|
189 |
-
if (count($this->_queue) > $this->_max_queue_size) {
|
190 |
-
$this->flush();
|
191 |
-
}
|
192 |
-
|
193 |
-
if ($this->_debug()) {
|
194 |
-
$this->_log("Queued message: ".json_encode($message));
|
195 |
-
}
|
196 |
-
}
|
197 |
-
|
198 |
-
|
199 |
-
/**
|
200 |
-
* Add an array representing a list of messages to be sent to Mixpanel to a queue.
|
201 |
-
* @param array $messages
|
202 |
-
*/
|
203 |
-
public function enqueueAll($messages = array()) {
|
204 |
-
foreach($messages as $message) {
|
205 |
-
$this->enqueue($message);
|
206 |
-
}
|
207 |
-
|
208 |
-
}
|
209 |
-
|
210 |
-
|
211 |
-
/**
|
212 |
-
* Given an array of messages, persist it with the instantiated Persistence Strategy
|
213 |
-
* @param $message
|
214 |
-
* @return mixed
|
215 |
-
*/
|
216 |
-
protected function _persist($message) {
|
217 |
-
return $this->_consumer->persist($message);
|
218 |
-
}
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
/**
|
224 |
-
* Return the endpoint that should be used by a consumer that consumes messages produced by this producer.
|
225 |
-
* @return string
|
226 |
-
*/
|
227 |
-
abstract function _getEndpoint();
|
228 |
-
|
229 |
}
|
1 |
+
<?php
|
2 |
+
require_once(dirname(__FILE__) . "/../Base/MixpanelBase.php");
|
3 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/FileConsumer.php");
|
4 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
|
5 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/SocketConsumer.php");
|
6 |
+
|
7 |
+
if (!function_exists('json_encode')) {
|
8 |
+
throw new Exception('The JSON PHP extension is required.');
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Provides some base methods for use by a message Producer
|
13 |
+
*/
|
14 |
+
abstract class Producers_MixpanelBaseProducer extends Base_MixpanelBase {
|
15 |
+
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string a token associated to a Mixpanel project
|
19 |
+
*/
|
20 |
+
protected $_token;
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var array a queue to hold messages in memory before flushing in batches
|
25 |
+
*/
|
26 |
+
private $_queue = array();
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var ConsumerStrategies_AbstractConsumer the consumer to use when flushing messages
|
31 |
+
*/
|
32 |
+
private $_consumer = null;
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @var array The list of available consumers
|
37 |
+
*/
|
38 |
+
private $_consumers = array(
|
39 |
+
"file" => "ConsumerStrategies_FileConsumer",
|
40 |
+
"curl" => "ConsumerStrategies_CurlConsumer",
|
41 |
+
"socket" => "ConsumerStrategies_SocketConsumer"
|
42 |
+
);
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* If the queue reaches this size we'll auto-flush to prevent out of memory errors
|
47 |
+
* @var int
|
48 |
+
*/
|
49 |
+
protected $_max_queue_size = 1000;
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Creates a new MixpanelBaseProducer, assings Mixpanel project token, registers custom Consumers, and instantiates
|
54 |
+
* the desired consumer
|
55 |
+
* @param $token
|
56 |
+
* @param array $options
|
57 |
+
*/
|
58 |
+
public function __construct($token, $options = array()) {
|
59 |
+
|
60 |
+
parent::__construct($options);
|
61 |
+
|
62 |
+
// register any customer consumers
|
63 |
+
if (array_key_exists("consumers", $options)) {
|
64 |
+
$this->_consumers = array_merge($this->_consumers, $options['consumers']);
|
65 |
+
}
|
66 |
+
|
67 |
+
// set max queue size
|
68 |
+
if (array_key_exists("max_queue_size", $options)) {
|
69 |
+
$this->_max_queue_size = $options['max_queue_size'];
|
70 |
+
}
|
71 |
+
|
72 |
+
// associate token
|
73 |
+
$this->_token = $token;
|
74 |
+
|
75 |
+
if ($this->_debug()) {
|
76 |
+
$this->_log("Using token: ".$this->_token);
|
77 |
+
}
|
78 |
+
|
79 |
+
// instantiate the chosen consumer
|
80 |
+
$this->_consumer = $this->_getConsumer();
|
81 |
+
|
82 |
+
}
|
83 |
+
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Flush the queue when we destruct the client with retries
|
87 |
+
*/
|
88 |
+
public function __destruct() {
|
89 |
+
$attempts = 0;
|
90 |
+
$max_attempts = 10;
|
91 |
+
$success = false;
|
92 |
+
while (!$success && $attempts < $max_attempts) {
|
93 |
+
if ($this->_debug()) {
|
94 |
+
$this->_log("destruct flush attempt #".($attempts+1));
|
95 |
+
}
|
96 |
+
$success = $this->flush();
|
97 |
+
$attempts++;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Iterate the queue and write in batches using the instantiated Consumer Strategy
|
104 |
+
* @param int $desired_batch_size
|
105 |
+
* @return bool whether or not the flush was successful
|
106 |
+
*/
|
107 |
+
public function flush($desired_batch_size = 50) {
|
108 |
+
$queue_size = count($this->_queue);
|
109 |
+
$succeeded = true;
|
110 |
+
if ($this->_debug()) {
|
111 |
+
$this->_log("Flush called - queue size: ".$queue_size);
|
112 |
+
}
|
113 |
+
|
114 |
+
while($queue_size > 0 && $succeeded) {
|
115 |
+
$batch_size = min(array($queue_size, $desired_batch_size, $this->_options['max_batch_size']));
|
116 |
+
$batch = array_splice($this->_queue, 0, $batch_size);
|
117 |
+
$succeeded = $this->_persist($batch);
|
118 |
+
|
119 |
+
if (!$succeeded) {
|
120 |
+
if ($this->_debug()) {
|
121 |
+
$this->_log("Batch consumption failed!");
|
122 |
+
}
|
123 |
+
$this->_queue = array_merge($batch, $this->_queue);
|
124 |
+
|
125 |
+
if ($this->_debug()) {
|
126 |
+
$this->_log("added batch back to queue, queue size is now $queue_size");
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
$queue_size = count($this->_queue);
|
131 |
+
|
132 |
+
if ($this->_debug()) {
|
133 |
+
$this->_log("Batch of $batch_size consumed, queue size is now $queue_size");
|
134 |
+
}
|
135 |
+
}
|
136 |
+
return $succeeded;
|
137 |
+
}
|
138 |
+
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Empties the queue without persisting any of the messages
|
142 |
+
*/
|
143 |
+
public function reset() {
|
144 |
+
$this->_queue = array();
|
145 |
+
}
|
146 |
+
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Returns the in-memory queue
|
150 |
+
* @return array
|
151 |
+
*/
|
152 |
+
public function getQueue() {
|
153 |
+
return $this->_queue;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Returns the current Mixpanel project token
|
158 |
+
* @return string
|
159 |
+
*/
|
160 |
+
public function getToken() {
|
161 |
+
return $this->_token;
|
162 |
+
}
|
163 |
+
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Given a strategy type, return a new PersistenceStrategy object
|
167 |
+
* @return ConsumerStrategies_AbstractConsumer
|
168 |
+
*/
|
169 |
+
protected function _getConsumer() {
|
170 |
+
$key = $this->_options['consumer'];
|
171 |
+
$Strategy = $this->_consumers[$key];
|
172 |
+
if ($this->_debug()) {
|
173 |
+
$this->_log("Using consumer: " . $key . " -> " . $Strategy);
|
174 |
+
}
|
175 |
+
$this->_options['endpoint'] = $this->_getEndpoint();
|
176 |
+
|
177 |
+
return new $Strategy($this->_options);
|
178 |
+
}
|
179 |
+
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Add an array representing a message to be sent to Mixpanel to a queue.
|
183 |
+
* @param array $message
|
184 |
+
*/
|
185 |
+
public function enqueue($message = array()) {
|
186 |
+
array_push($this->_queue, $message);
|
187 |
+
|
188 |
+
// force a flush if we've reached our threshold
|
189 |
+
if (count($this->_queue) > $this->_max_queue_size) {
|
190 |
+
$this->flush();
|
191 |
+
}
|
192 |
+
|
193 |
+
if ($this->_debug()) {
|
194 |
+
$this->_log("Queued message: ".json_encode($message));
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Add an array representing a list of messages to be sent to Mixpanel to a queue.
|
201 |
+
* @param array $messages
|
202 |
+
*/
|
203 |
+
public function enqueueAll($messages = array()) {
|
204 |
+
foreach($messages as $message) {
|
205 |
+
$this->enqueue($message);
|
206 |
+
}
|
207 |
+
|
208 |
+
}
|
209 |
+
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Given an array of messages, persist it with the instantiated Persistence Strategy
|
213 |
+
* @param $message
|
214 |
+
* @return mixed
|
215 |
+
*/
|
216 |
+
protected function _persist($message) {
|
217 |
+
return $this->_consumer->persist($message);
|
218 |
+
}
|
219 |
+
|
220 |
+
|
221 |
+
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Return the endpoint that should be used by a consumer that consumes messages produced by this producer.
|
225 |
+
* @return string
|
226 |
+
*/
|
227 |
+
abstract function _getEndpoint();
|
228 |
+
|
229 |
}
|
modules/supsystic_promo/models/classes/lib/Producers/MixpanelEvents.php
CHANGED
@@ -1,164 +1,164 @@
|
|
1 |
-
<?php
|
2 |
-
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
3 |
-
require_once(dirname(__FILE__) . "/MixpanelPeople.php");
|
4 |
-
require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Provides an API to track events on Mixpanel
|
8 |
-
*/
|
9 |
-
class Producers_MixpanelEvents extends Producers_MixpanelBaseProducer {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* An array of properties to attach to every tracked event
|
13 |
-
* @var array
|
14 |
-
*/
|
15 |
-
private $_super_properties = array("mp_lib" => "php");
|
16 |
-
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Track an event defined by $event associated with metadata defined by $properties
|
20 |
-
* @param string $event
|
21 |
-
* @param array $properties
|
22 |
-
*/
|
23 |
-
public function track($event, $properties = array()) {
|
24 |
-
|
25 |
-
// if no token is passed in, use current token
|
26 |
-
if (!array_key_exists("token", $properties)) $properties['token'] = $this->_token;
|
27 |
-
|
28 |
-
// if no time is passed in, use the current time
|
29 |
-
if (!array_key_exists('time', $properties)) $properties['time'] = time();
|
30 |
-
|
31 |
-
$params['event'] = $event;
|
32 |
-
$params['properties'] = array_merge($this->_super_properties, $properties);
|
33 |
-
|
34 |
-
$this->enqueue($params);
|
35 |
-
}
|
36 |
-
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Register a property to be sent with every event. If the property has already been registered, it will be
|
40 |
-
* overwritten.
|
41 |
-
* @param string $property
|
42 |
-
* @param mixed $value
|
43 |
-
*/
|
44 |
-
public function register($property, $value) {
|
45 |
-
$this->_super_properties[$property] = $value;
|
46 |
-
}
|
47 |
-
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Register multiple properties to be sent with every event. If any of the properties have already been registered,
|
51 |
-
* they will be overwritten.
|
52 |
-
* @param array $props_and_vals
|
53 |
-
*/
|
54 |
-
public function registerAll($props_and_vals = array()) {
|
55 |
-
foreach($props_and_vals as $property => $value) {
|
56 |
-
$this->register($property, $value);
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Register a property to be sent with every event. If the property has already been registered, it will NOT be
|
63 |
-
* overwritten.
|
64 |
-
* @param $property
|
65 |
-
* @param $value
|
66 |
-
*/
|
67 |
-
public function registerOnce($property, $value) {
|
68 |
-
if (!isset($this->_super_properties[$property])) {
|
69 |
-
$this->register($property, $value);
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Register multiple properties to be sent with every event. If any of the properties have already been registered,
|
76 |
-
* they will NOT be overwritten.
|
77 |
-
* @param array $props_and_vals
|
78 |
-
*/
|
79 |
-
public function registerAllOnce($props_and_vals = array()) {
|
80 |
-
foreach($props_and_vals as $property => $value) {
|
81 |
-
if (!isset($this->_super_properties[$property])) {
|
82 |
-
$this->register($property, $value);
|
83 |
-
}
|
84 |
-
}
|
85 |
-
}
|
86 |
-
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Un-register an property to be sent with every event.
|
90 |
-
* @param string $property
|
91 |
-
*/
|
92 |
-
public function unregister($property) {
|
93 |
-
unset($this->_super_properties[$property]);
|
94 |
-
}
|
95 |
-
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Un-register a list of properties to be sent with every event.
|
99 |
-
* @param array $properties
|
100 |
-
*/
|
101 |
-
public function unregisterAll($properties) {
|
102 |
-
foreach($properties as $property) {
|
103 |
-
$this->unregister($property);
|
104 |
-
}
|
105 |
-
}
|
106 |
-
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Get a property that is set to be sent with every event
|
110 |
-
* @param string $property
|
111 |
-
* @return mixed
|
112 |
-
*/
|
113 |
-
public function getProperty($property) {
|
114 |
-
return $this->_super_properties[$property];
|
115 |
-
}
|
116 |
-
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Identify the user you want to associate to tracked events
|
120 |
-
* @param string|int $user_id
|
121 |
-
*/
|
122 |
-
public function identify($user_id) {
|
123 |
-
$this->register("distinct_id", $user_id);
|
124 |
-
}
|
125 |
-
|
126 |
-
|
127 |
-
/**
|
128 |
-
* Alias an existing id with a different unique id. This is helpful when you want to associate a generated id to
|
129 |
-
* a username or e-mail address.
|
130 |
-
*
|
131 |
-
* Because aliasing can be extremely vulnerable to race conditions and ordering issues, we'll make a synchronous
|
132 |
-
* call directly to Mixpanel when this method is called. If it fails we'll throw an Exception as subsequent
|
133 |
-
* events are likely to be incorrectly tracked.
|
134 |
-
* @param string|int $original_id
|
135 |
-
* @param string|int $new_id
|
136 |
-
* @return array $msg
|
137 |
-
* @throws Exception
|
138 |
-
*/
|
139 |
-
public function createAlias($original_id, $new_id) {
|
140 |
-
$msg = array(
|
141 |
-
"event" => '$create_alias',
|
142 |
-
"properties" => array("distinct_id" => $original_id, "alias" => $new_id, "token" => $this->_token)
|
143 |
-
);
|
144 |
-
|
145 |
-
$options = array_merge($this->_options, array("endpoint" => $this->_getEndpoint(), "fork" => false));
|
146 |
-
$curlConsumer = new ConsumerStrategies_CurlConsumer($options);
|
147 |
-
$success = $curlConsumer->persist(array($msg));
|
148 |
-
if (!$success) {
|
149 |
-
error_log("Creating Mixpanel Alias (original id: $original_id, new id: $new_id) failed");
|
150 |
-
throw new Exception("Tried to create an alias but the call was not successful");
|
151 |
-
} else {
|
152 |
-
return $msg;
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
|
157 |
-
/**
|
158 |
-
* Returns the "events" endpoint
|
159 |
-
* @return string
|
160 |
-
*/
|
161 |
-
function _getEndpoint() {
|
162 |
-
return $this->_options['events_endpoint'];
|
163 |
-
}
|
164 |
}
|
1 |
+
<?php
|
2 |
+
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
3 |
+
require_once(dirname(__FILE__) . "/MixpanelPeople.php");
|
4 |
+
require_once(dirname(__FILE__) . "/../ConsumerStrategies/CurlConsumer.php");
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Provides an API to track events on Mixpanel
|
8 |
+
*/
|
9 |
+
class Producers_MixpanelEvents extends Producers_MixpanelBaseProducer {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* An array of properties to attach to every tracked event
|
13 |
+
* @var array
|
14 |
+
*/
|
15 |
+
private $_super_properties = array("mp_lib" => "php");
|
16 |
+
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Track an event defined by $event associated with metadata defined by $properties
|
20 |
+
* @param string $event
|
21 |
+
* @param array $properties
|
22 |
+
*/
|
23 |
+
public function track($event, $properties = array()) {
|
24 |
+
|
25 |
+
// if no token is passed in, use current token
|
26 |
+
if (!array_key_exists("token", $properties)) $properties['token'] = $this->_token;
|
27 |
+
|
28 |
+
// if no time is passed in, use the current time
|
29 |
+
if (!array_key_exists('time', $properties)) $properties['time'] = time();
|
30 |
+
|
31 |
+
$params['event'] = $event;
|
32 |
+
$params['properties'] = array_merge($this->_super_properties, $properties);
|
33 |
+
|
34 |
+
$this->enqueue($params);
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Register a property to be sent with every event. If the property has already been registered, it will be
|
40 |
+
* overwritten.
|
41 |
+
* @param string $property
|
42 |
+
* @param mixed $value
|
43 |
+
*/
|
44 |
+
public function register($property, $value) {
|
45 |
+
$this->_super_properties[$property] = $value;
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Register multiple properties to be sent with every event. If any of the properties have already been registered,
|
51 |
+
* they will be overwritten.
|
52 |
+
* @param array $props_and_vals
|
53 |
+
*/
|
54 |
+
public function registerAll($props_and_vals = array()) {
|
55 |
+
foreach($props_and_vals as $property => $value) {
|
56 |
+
$this->register($property, $value);
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Register a property to be sent with every event. If the property has already been registered, it will NOT be
|
63 |
+
* overwritten.
|
64 |
+
* @param $property
|
65 |
+
* @param $value
|
66 |
+
*/
|
67 |
+
public function registerOnce($property, $value) {
|
68 |
+
if (!isset($this->_super_properties[$property])) {
|
69 |
+
$this->register($property, $value);
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Register multiple properties to be sent with every event. If any of the properties have already been registered,
|
76 |
+
* they will NOT be overwritten.
|
77 |
+
* @param array $props_and_vals
|
78 |
+
*/
|
79 |
+
public function registerAllOnce($props_and_vals = array()) {
|
80 |
+
foreach($props_and_vals as $property => $value) {
|
81 |
+
if (!isset($this->_super_properties[$property])) {
|
82 |
+
$this->register($property, $value);
|
83 |
+
}
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Un-register an property to be sent with every event.
|
90 |
+
* @param string $property
|
91 |
+
*/
|
92 |
+
public function unregister($property) {
|
93 |
+
unset($this->_super_properties[$property]);
|
94 |
+
}
|
95 |
+
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Un-register a list of properties to be sent with every event.
|
99 |
+
* @param array $properties
|
100 |
+
*/
|
101 |
+
public function unregisterAll($properties) {
|
102 |
+
foreach($properties as $property) {
|
103 |
+
$this->unregister($property);
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Get a property that is set to be sent with every event
|
110 |
+
* @param string $property
|
111 |
+
* @return mixed
|
112 |
+
*/
|
113 |
+
public function getProperty($property) {
|
114 |
+
return $this->_super_properties[$property];
|
115 |
+
}
|
116 |
+
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Identify the user you want to associate to tracked events
|
120 |
+
* @param string|int $user_id
|
121 |
+
*/
|
122 |
+
public function identify($user_id) {
|
123 |
+
$this->register("distinct_id", $user_id);
|
124 |
+
}
|
125 |
+
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Alias an existing id with a different unique id. This is helpful when you want to associate a generated id to
|
129 |
+
* a username or e-mail address.
|
130 |
+
*
|
131 |
+
* Because aliasing can be extremely vulnerable to race conditions and ordering issues, we'll make a synchronous
|
132 |
+
* call directly to Mixpanel when this method is called. If it fails we'll throw an Exception as subsequent
|
133 |
+
* events are likely to be incorrectly tracked.
|
134 |
+
* @param string|int $original_id
|
135 |
+
* @param string|int $new_id
|
136 |
+
* @return array $msg
|
137 |
+
* @throws Exception
|
138 |
+
*/
|
139 |
+
public function createAlias($original_id, $new_id) {
|
140 |
+
$msg = array(
|
141 |
+
"event" => '$create_alias',
|
142 |
+
"properties" => array("distinct_id" => $original_id, "alias" => $new_id, "token" => $this->_token)
|
143 |
+
);
|
144 |
+
|
145 |
+
$options = array_merge($this->_options, array("endpoint" => $this->_getEndpoint(), "fork" => false));
|
146 |
+
$curlConsumer = new ConsumerStrategies_CurlConsumer($options);
|
147 |
+
$success = $curlConsumer->persist(array($msg));
|
148 |
+
if (!$success) {
|
149 |
+
error_log("Creating Mixpanel Alias (original id: $original_id, new id: $new_id) failed");
|
150 |
+
throw new Exception("Tried to create an alias but the call was not successful");
|
151 |
+
} else {
|
152 |
+
return $msg;
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Returns the "events" endpoint
|
159 |
+
* @return string
|
160 |
+
*/
|
161 |
+
function _getEndpoint() {
|
162 |
+
return $this->_options['events_endpoint'];
|
163 |
+
}
|
164 |
}
|
modules/supsystic_promo/models/classes/lib/Producers/MixpanelPeople.php
CHANGED
@@ -1,147 +1,147 @@
|
|
1 |
-
<?php
|
2 |
-
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Provides an API to create/update profiles on Mixpanel
|
6 |
-
*/
|
7 |
-
class Producers_MixpanelPeople extends Producers_MixpanelBaseProducer {
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Internal method to prepare a message given the message data
|
11 |
-
* @param $distinct_id
|
12 |
-
* @param $operation
|
13 |
-
* @param $value
|
14 |
-
* @param null $ip
|
15 |
-
* @return array
|
16 |
-
*/
|
17 |
-
private function _constructPayload($distinct_id, $operation, $value, $ip = null, $ignore_time = false) {
|
18 |
-
$payload = array(
|
19 |
-
'$token' => $this->_token,
|
20 |
-
'$distinct_id' => $distinct_id,
|
21 |
-
$operation => $value
|
22 |
-
);
|
23 |
-
if ($ip !== null) $payload['$ip'] = $ip;
|
24 |
-
if ($ignore_time === true) $payload['$ignore_time'] = true;
|
25 |
-
return $payload;
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Set properties on a user record. If the profile does not exist, it creates it with these properties.
|
30 |
-
* If it does exist, it sets the properties to these values, overwriting existing values.
|
31 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
32 |
-
* @param array $props associative array of properties to set on the profile
|
33 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
34 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
35 |
-
*/
|
36 |
-
public function set($distinct_id, $props, $ip = null, $ignore_time = false) {
|
37 |
-
$payload = $this->_constructPayload($distinct_id, '$set', $props, $ip, $ignore_time);
|
38 |
-
$this->enqueue($payload);
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Set properties on a user record. If the profile does not exist, it creates it with these properties.
|
43 |
-
* If it does exist, it sets the properties to these values but WILL NOT overwrite existing values.
|
44 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
45 |
-
* @param array $props associative array of properties to set on the profile
|
46 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
47 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
48 |
-
*/
|
49 |
-
public function setOnce($distinct_id, $props, $ip = null, $ignore_time = false) {
|
50 |
-
$payload = $this->_constructPayload($distinct_id, '$set_once', $props, $ip, $ignore_time);
|
51 |
-
$this->enqueue($payload);
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Unset properties on a user record. If the profile does not exist, it creates it with no properties.
|
56 |
-
* If it does exist, it unsets these properties. NOTE: In other libraries we use 'unset' which is
|
57 |
-
* a reserved word in PHP.
|
58 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
59 |
-
* @param array $props associative array of properties to unset on the profile
|
60 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
61 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
62 |
-
*/
|
63 |
-
public function remove($distinct_id, $props, $ip = null, $ignore_time = false) {
|
64 |
-
$payload = $this->_constructPayload($distinct_id, '$unset', $props, $ip, $ignore_time);
|
65 |
-
$this->enqueue($payload);
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Increments the value of a property on a user record. If the profile does not exist, it creates it and sets the
|
70 |
-
* property to the increment value.
|
71 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
72 |
-
* @param $prop string the property to increment
|
73 |
-
* @param int $val the amount to increment the property by
|
74 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
75 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
76 |
-
*/
|
77 |
-
public function increment($distinct_id, $prop, $val, $ip = null, $ignore_time = false) {
|
78 |
-
$payload = $this->_constructPayload($distinct_id, '$add', array("$prop" => $val), $ip, $ignore_time);
|
79 |
-
$this->enqueue($payload);
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* Adds $val to a list located at $prop. If the property does not exist, it will be created. If $val is a string
|
84 |
-
* and the list is empty or does not exist, a new list with one value will be created.
|
85 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
86 |
-
* @param string $prop the property that holds the list
|
87 |
-
* @param string|array $val items to add to the list
|
88 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
89 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
90 |
-
*/
|
91 |
-
public function append($distinct_id, $prop, $val, $ip = null, $ignore_time = false) {
|
92 |
-
$operation = gettype($val) == "array" ? '$union' : '$append';
|
93 |
-
$payload = $this->_constructPayload($distinct_id, $operation, array("$prop" => $val), $ip, $ignore_time);
|
94 |
-
$this->enqueue($payload);
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Adds a transaction to the user's profile for revenue tracking
|
99 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
100 |
-
* @param string $amount the transaction amount e.g. "20.50"
|
101 |
-
* @param null $timestamp the timestamp of when the transaction occurred (default to current timestamp)
|
102 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
103 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
104 |
-
*/
|
105 |
-
public function trackCharge($distinct_id, $amount, $timestamp = null, $ip = null, $ignore_time = false) {
|
106 |
-
$timestamp = $timestamp == null ? time() : $timestamp;
|
107 |
-
$date_iso = date("c", $timestamp);
|
108 |
-
$transaction = array(
|
109 |
-
'$time' => $date_iso,
|
110 |
-
'$amount' => $amount
|
111 |
-
);
|
112 |
-
$val = array('$transactions' => $transaction);
|
113 |
-
$payload = $this->_constructPayload($distinct_id, '$append', $val, $ip, $ignore_time);
|
114 |
-
$this->enqueue($payload);
|
115 |
-
}
|
116 |
-
|
117 |
-
/**
|
118 |
-
* Clear all transactions stored on a user's profile
|
119 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
120 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
121 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
122 |
-
*/
|
123 |
-
public function clearCharges($distinct_id, $ip = null, $ignore_time = false) {
|
124 |
-
$payload = $this->_constructPayload($distinct_id, '$set', array('$transactions' => array()), $ip, $ignore_time);
|
125 |
-
$this->enqueue($payload);
|
126 |
-
}
|
127 |
-
|
128 |
-
/**
|
129 |
-
* Delete this profile from Mixpanel
|
130 |
-
* @param string|int $distinct_id the distinct_id or alias of a user
|
131 |
-
* @param string|null $ip the ip address of the client (used for geo-location)
|
132 |
-
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
133 |
-
*/
|
134 |
-
public function deleteUser($distinct_id, $ip = null, $ignore_time = false) {
|
135 |
-
$payload = $this->_constructPayload($distinct_id, '$delete', "", $ip, $ignore_time);
|
136 |
-
$this->enqueue($payload);
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Returns the "engage" endpoint
|
141 |
-
* @return string
|
142 |
-
*/
|
143 |
-
function _getEndpoint() {
|
144 |
-
return $this->_options['people_endpoint'];
|
145 |
-
}
|
146 |
-
|
147 |
-
}
|
1 |
+
<?php
|
2 |
+
require_once(dirname(__FILE__) . "/MixpanelBaseProducer.php");
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Provides an API to create/update profiles on Mixpanel
|
6 |
+
*/
|
7 |
+
class Producers_MixpanelPeople extends Producers_MixpanelBaseProducer {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal method to prepare a message given the message data
|
11 |
+
* @param $distinct_id
|
12 |
+
* @param $operation
|
13 |
+
* @param $value
|
14 |
+
* @param null $ip
|
15 |
+
* @return array
|
16 |
+
*/
|
17 |
+
private function _constructPayload($distinct_id, $operation, $value, $ip = null, $ignore_time = false) {
|
18 |
+
$payload = array(
|
19 |
+
'$token' => $this->_token,
|
20 |
+
'$distinct_id' => $distinct_id,
|
21 |
+
$operation => $value
|
22 |
+
);
|
23 |
+
if ($ip !== null) $payload['$ip'] = $ip;
|
24 |
+
if ($ignore_time === true) $payload['$ignore_time'] = true;
|
25 |
+
return $payload;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Set properties on a user record. If the profile does not exist, it creates it with these properties.
|
30 |
+
* If it does exist, it sets the properties to these values, overwriting existing values.
|
31 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
32 |
+
* @param array $props associative array of properties to set on the profile
|
33 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
34 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
35 |
+
*/
|
36 |
+
public function set($distinct_id, $props, $ip = null, $ignore_time = false) {
|
37 |
+
$payload = $this->_constructPayload($distinct_id, '$set', $props, $ip, $ignore_time);
|
38 |
+
$this->enqueue($payload);
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Set properties on a user record. If the profile does not exist, it creates it with these properties.
|
43 |
+
* If it does exist, it sets the properties to these values but WILL NOT overwrite existing values.
|
44 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
45 |
+
* @param array $props associative array of properties to set on the profile
|
46 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
47 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
48 |
+
*/
|
49 |
+
public function setOnce($distinct_id, $props, $ip = null, $ignore_time = false) {
|
50 |
+
$payload = $this->_constructPayload($distinct_id, '$set_once', $props, $ip, $ignore_time);
|
51 |
+
$this->enqueue($payload);
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Unset properties on a user record. If the profile does not exist, it creates it with no properties.
|
56 |
+
* If it does exist, it unsets these properties. NOTE: In other libraries we use 'unset' which is
|
57 |
+
* a reserved word in PHP.
|
58 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
59 |
+
* @param array $props associative array of properties to unset on the profile
|
60 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
61 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
62 |
+
*/
|
63 |
+
public function remove($distinct_id, $props, $ip = null, $ignore_time = false) {
|
64 |
+
$payload = $this->_constructPayload($distinct_id, '$unset', $props, $ip, $ignore_time);
|
65 |
+
$this->enqueue($payload);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Increments the value of a property on a user record. If the profile does not exist, it creates it and sets the
|
70 |
+
* property to the increment value.
|
71 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
72 |
+
* @param $prop string the property to increment
|
73 |
+
* @param int $val the amount to increment the property by
|
74 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
75 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
76 |
+
*/
|
77 |
+
public function increment($distinct_id, $prop, $val, $ip = null, $ignore_time = false) {
|
78 |
+
$payload = $this->_constructPayload($distinct_id, '$add', array("$prop" => $val), $ip, $ignore_time);
|
79 |
+
$this->enqueue($payload);
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Adds $val to a list located at $prop. If the property does not exist, it will be created. If $val is a string
|
84 |
+
* and the list is empty or does not exist, a new list with one value will be created.
|
85 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
86 |
+
* @param string $prop the property that holds the list
|
87 |
+
* @param string|array $val items to add to the list
|
88 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
89 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
90 |
+
*/
|
91 |
+
public function append($distinct_id, $prop, $val, $ip = null, $ignore_time = false) {
|
92 |
+
$operation = gettype($val) == "array" ? '$union' : '$append';
|
93 |
+
$payload = $this->_constructPayload($distinct_id, $operation, array("$prop" => $val), $ip, $ignore_time);
|
94 |
+
$this->enqueue($payload);
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Adds a transaction to the user's profile for revenue tracking
|
99 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
100 |
+
* @param string $amount the transaction amount e.g. "20.50"
|
101 |
+
* @param null $timestamp the timestamp of when the transaction occurred (default to current timestamp)
|
102 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
103 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
104 |
+
*/
|
105 |
+
public function trackCharge($distinct_id, $amount, $timestamp = null, $ip = null, $ignore_time = false) {
|
106 |
+
$timestamp = $timestamp == null ? time() : $timestamp;
|
107 |
+
$date_iso = date("c", $timestamp);
|
108 |
+
$transaction = array(
|
109 |
+
'$time' => $date_iso,
|
110 |
+
'$amount' => $amount
|
111 |
+
);
|
112 |
+
$val = array('$transactions' => $transaction);
|
113 |
+
$payload = $this->_constructPayload($distinct_id, '$append', $val, $ip, $ignore_time);
|
114 |
+
$this->enqueue($payload);
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Clear all transactions stored on a user's profile
|
119 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
120 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
121 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
122 |
+
*/
|
123 |
+
public function clearCharges($distinct_id, $ip = null, $ignore_time = false) {
|
124 |
+
$payload = $this->_constructPayload($distinct_id, '$set', array('$transactions' => array()), $ip, $ignore_time);
|
125 |
+
$this->enqueue($payload);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Delete this profile from Mixpanel
|
130 |
+
* @param string|int $distinct_id the distinct_id or alias of a user
|
131 |
+
* @param string|null $ip the ip address of the client (used for geo-location)
|
132 |
+
* @param boolean $ignore_time If the $ignore_time property is true, Mixpanel will not automatically update the "Last Seen" property of the profile. Otherwise, Mixpanel will add a "Last Seen" property associated with the current time
|
133 |
+
*/
|
134 |
+
public function deleteUser($distinct_id, $ip = null, $ignore_time = false) {
|
135 |
+
$payload = $this->_constructPayload($distinct_id, '$delete', "", $ip, $ignore_time);
|
136 |
+
$this->enqueue($payload);
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Returns the "engage" endpoint
|
141 |
+
* @return string
|
142 |
+
*/
|
143 |
+
function _getEndpoint() {
|
144 |
+
return $this->_options['people_endpoint'];
|
145 |
+
}
|
146 |
+
|
147 |
+
}
|
modules/supsystic_promo/views/tpl/adminTour.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<div id="supsystic-welcome-first_welcome">
|
3 |
<div class="supsystic-tour-content">
|
4 |
<h3><?php printf(__('Welcome to %s plugin!', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></h3>
|
5 |
-
<p><?php printf(__('Thank you for choosing our %s plugin. Just click here to start using it - and we will show you it\'s possibilities and
|
6 |
</div>
|
7 |
<div class="supsystic-tour-btns">
|
8 |
<a href="#" class="close"><?php _e('Close', PPS_LANG_CODE)?></a>
|
@@ -62,7 +62,7 @@
|
|
62 |
<div id="supsystic-first_edit-popup_design_opts">
|
63 |
<div class="supsystic-tour-content">
|
64 |
<h3><?php printf(__('Design Settings', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></h3>
|
65 |
-
<p><?php printf(__('One of our most
|
66 |
</div>
|
67 |
<div class="supsystic-tour-btns">
|
68 |
<a href="#" class="close"><?php _e('Close', PPS_LANG_CODE)?></a>
|
2 |
<div id="supsystic-welcome-first_welcome">
|
3 |
<div class="supsystic-tour-content">
|
4 |
<h3><?php printf(__('Welcome to %s plugin!', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></h3>
|
5 |
+
<p><?php printf(__('Thank you for choosing our %s plugin. Just click here to start using it - and we will show you it\'s possibilities and powerful features.', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></p>
|
6 |
</div>
|
7 |
<div class="supsystic-tour-btns">
|
8 |
<a href="#" class="close"><?php _e('Close', PPS_LANG_CODE)?></a>
|
62 |
<div id="supsystic-first_edit-popup_design_opts">
|
63 |
<div class="supsystic-tour-content">
|
64 |
<h3><?php printf(__('Design Settings', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></h3>
|
65 |
+
<p><?php printf(__('One of our most powerful features - possibility to <strong>customize</strong> design for each PopUp window for your needs. In this section you can select your PopUp colors and images, enter required texts that will describe your needs for your visitors, setup social settings (if required), select PopUp location, and in the end - select Animation style for your PopUp from list of more then 20 different animation styles!', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></p>
|
66 |
</div>
|
67 |
<div class="supsystic-tour-btns">
|
68 |
<a href="#" class="close"><?php _e('Close', PPS_LANG_CODE)?></a>
|
modules/supsystic_promo/views/tpl/pluginDeactivation.php
CHANGED
@@ -1,78 +1,78 @@
|
|
1 |
-
<style type="text/css">
|
2 |
-
.ppsDeactivateDescShell {
|
3 |
-
display: none;
|
4 |
-
margin-left: 25px;
|
5 |
-
margin-top: 5px;
|
6 |
-
}
|
7 |
-
.ppsDeactivateReasonShell {
|
8 |
-
display: block;
|
9 |
-
margin-bottom: 10px;
|
10 |
-
}
|
11 |
-
#ppsDeactivateWnd input[type="text"],
|
12 |
-
#ppsDeactivateWnd textarea {
|
13 |
-
width: 100%;
|
14 |
-
}
|
15 |
-
#ppsDeactivateWnd h4 {
|
16 |
-
line-height: 1.53em;
|
17 |
-
}
|
18 |
-
#ppsDeactivateWnd + .ui-dialog-buttonpane .ui-dialog-buttonset {
|
19 |
-
float: none;
|
20 |
-
}
|
21 |
-
.ppsDeactivateSkipDataBtn {
|
22 |
-
float: right;
|
23 |
-
margin-top: 15px;
|
24 |
-
text-decoration: none;
|
25 |
-
color: #777 !important;
|
26 |
-
}
|
27 |
-
</style>
|
28 |
-
<div id="ppsDeactivateWnd" style="display: none;" title="<?php _e('Your Feedback', PPS_LANG_CODE)?>">
|
29 |
-
<h4><?php printf(__('If you have a moment, please share why you are deactivating %s', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></h4>
|
30 |
-
<form id="ppsDeactivateForm">
|
31 |
-
<label class="ppsDeactivateReasonShell">
|
32 |
-
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
33 |
-
'value' => 'not_working',
|
34 |
-
))?>
|
35 |
-
<?php _e('Couldn\'t get the plugin to work', PPS_LANG_CODE)?>
|
36 |
-
<div class="ppsDeactivateDescShell">
|
37 |
-
<?php printf(__('If you have a question, <a href="%s" target="_blank">contact us</a> and will do our best to help you'), 'https://supsystic.com/contact-us/?utm_source=plugin&utm_medium=deactivated_contact&utm_campaign=popup')?>
|
38 |
-
</div>
|
39 |
-
</label>
|
40 |
-
<label class="ppsDeactivateReasonShell">
|
41 |
-
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
42 |
-
'value' => 'found_better',
|
43 |
-
))?>
|
44 |
-
<?php _e('I found a better plugin', PPS_LANG_CODE)?>
|
45 |
-
<div class="ppsDeactivateDescShell">
|
46 |
-
<?php echo htmlPps::text('better_plugin', array(
|
47 |
-
'placeholder' => __('If it\'s possible, specify plugin name', PPS_LANG_CODE),
|
48 |
-
))?>
|
49 |
-
</div>
|
50 |
-
</label>
|
51 |
-
<label class="ppsDeactivateReasonShell">
|
52 |
-
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
53 |
-
'value' => 'not_need',
|
54 |
-
))?>
|
55 |
-
<?php _e('I no longer need the plugin', PPS_LANG_CODE)?>
|
56 |
-
</label>
|
57 |
-
<label class="ppsDeactivateReasonShell">
|
58 |
-
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
59 |
-
'value' => 'temporary',
|
60 |
-
))?>
|
61 |
-
<?php _e('It\'s a temporary deactivation', PPS_LANG_CODE)?>
|
62 |
-
</label>
|
63 |
-
<label class="ppsDeactivateReasonShell">
|
64 |
-
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
65 |
-
'value' => 'other',
|
66 |
-
))?>
|
67 |
-
<?php _e('Other', PPS_LANG_CODE)?>
|
68 |
-
<div class="ppsDeactivateDescShell">
|
69 |
-
<?php echo htmlPps::text('other', array(
|
70 |
-
'placeholder' => __('What is the reason?', PPS_LANG_CODE),
|
71 |
-
))?>
|
72 |
-
</div>
|
73 |
-
</label>
|
74 |
-
<?php echo htmlPps::hidden('mod', array('value' => 'supsystic_promo'))?>
|
75 |
-
<?php echo htmlPps::hidden('action', array('value' => 'saveDeactivateData'))?>
|
76 |
-
</form>
|
77 |
-
<a href="" class="ppsDeactivateSkipDataBtn"><?php _e('Skip & Deactivate', PPS_LANG_CODE)?></a>
|
78 |
</div>
|
1 |
+
<style type="text/css">
|
2 |
+
.ppsDeactivateDescShell {
|
3 |
+
display: none;
|
4 |
+
margin-left: 25px;
|
5 |
+
margin-top: 5px;
|
6 |
+
}
|
7 |
+
.ppsDeactivateReasonShell {
|
8 |
+
display: block;
|
9 |
+
margin-bottom: 10px;
|
10 |
+
}
|
11 |
+
#ppsDeactivateWnd input[type="text"],
|
12 |
+
#ppsDeactivateWnd textarea {
|
13 |
+
width: 100%;
|
14 |
+
}
|
15 |
+
#ppsDeactivateWnd h4 {
|
16 |
+
line-height: 1.53em;
|
17 |
+
}
|
18 |
+
#ppsDeactivateWnd + .ui-dialog-buttonpane .ui-dialog-buttonset {
|
19 |
+
float: none;
|
20 |
+
}
|
21 |
+
.ppsDeactivateSkipDataBtn {
|
22 |
+
float: right;
|
23 |
+
margin-top: 15px;
|
24 |
+
text-decoration: none;
|
25 |
+
color: #777 !important;
|
26 |
+
}
|
27 |
+
</style>
|
28 |
+
<div id="ppsDeactivateWnd" style="display: none;" title="<?php _e('Your Feedback', PPS_LANG_CODE)?>">
|
29 |
+
<h4><?php printf(__('If you have a moment, please share why you are deactivating %s', PPS_LANG_CODE), PPS_WP_PLUGIN_NAME)?></h4>
|
30 |
+
<form id="ppsDeactivateForm">
|
31 |
+
<label class="ppsDeactivateReasonShell">
|
32 |
+
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
33 |
+
'value' => 'not_working',
|
34 |
+
))?>
|
35 |
+
<?php _e('Couldn\'t get the plugin to work', PPS_LANG_CODE)?>
|
36 |
+
<div class="ppsDeactivateDescShell">
|
37 |
+
<?php printf(__('If you have a question, <a href="%s" target="_blank">contact us</a> and will do our best to help you'), 'https://supsystic.com/contact-us/?utm_source=plugin&utm_medium=deactivated_contact&utm_campaign=popup')?>
|
38 |
+
</div>
|
39 |
+
</label>
|
40 |
+
<label class="ppsDeactivateReasonShell">
|
41 |
+
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
42 |
+
'value' => 'found_better',
|
43 |
+
))?>
|
44 |
+
<?php _e('I found a better plugin', PPS_LANG_CODE)?>
|
45 |
+
<div class="ppsDeactivateDescShell">
|
46 |
+
<?php echo htmlPps::text('better_plugin', array(
|
47 |
+
'placeholder' => __('If it\'s possible, specify plugin name', PPS_LANG_CODE),
|
48 |
+
))?>
|
49 |
+
</div>
|
50 |
+
</label>
|
51 |
+
<label class="ppsDeactivateReasonShell">
|
52 |
+
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
53 |
+
'value' => 'not_need',
|
54 |
+
))?>
|
55 |
+
<?php _e('I no longer need the plugin', PPS_LANG_CODE)?>
|
56 |
+
</label>
|
57 |
+
<label class="ppsDeactivateReasonShell">
|
58 |
+
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
59 |
+
'value' => 'temporary',
|
60 |
+
))?>
|
61 |
+
<?php _e('It\'s a temporary deactivation', PPS_LANG_CODE)?>
|
62 |
+
</label>
|
63 |
+
<label class="ppsDeactivateReasonShell">
|
64 |
+
<?php echo htmlPps::radiobutton('deactivate_reason', array(
|
65 |
+
'value' => 'other',
|
66 |
+
))?>
|
67 |
+
<?php _e('Other', PPS_LANG_CODE)?>
|
68 |
+
<div class="ppsDeactivateDescShell">
|
69 |
+
<?php echo htmlPps::text('other', array(
|
70 |
+
'placeholder' => __('What is the reason?', PPS_LANG_CODE),
|
71 |
+
))?>
|
72 |
+
</div>
|
73 |
+
</label>
|
74 |
+
<?php echo htmlPps::hidden('mod', array('value' => 'supsystic_promo'))?>
|
75 |
+
<?php echo htmlPps::hidden('action', array('value' => 'saveDeactivateData'))?>
|
76 |
+
</form>
|
77 |
+
<a href="" class="ppsDeactivateSkipDataBtn"><?php _e('Skip & Deactivate', PPS_LANG_CODE)?></a>
|
78 |
</div>
|
modules/templates/mod.php
CHANGED
@@ -66,9 +66,9 @@ class templatesPps extends modulePps {
|
|
66 |
static $loaded = false;
|
67 |
if(!$loaded) {
|
68 |
framePps::_()->addScript('jquery');
|
69 |
-
|
70 |
-
framePps::_()->addScript('commonPps', PPS_JS_PATH. 'common.js');
|
71 |
-
framePps::_()->addScript('corePps', PPS_JS_PATH. 'core.js');
|
72 |
|
73 |
$ajaxurl = admin_url('admin-ajax.php');
|
74 |
$jsData = array(
|
66 |
static $loaded = false;
|
67 |
if(!$loaded) {
|
68 |
framePps::_()->addScript('jquery');
|
69 |
+
$suf = PPS_MINIFY_ASSETS ? '.min' : '';
|
70 |
+
framePps::_()->addScript('commonPps', PPS_JS_PATH. 'common'. $suf. '.js');
|
71 |
+
framePps::_()->addScript('corePps', PPS_JS_PATH. 'core'. $suf. '.js');
|
72 |
|
73 |
$ajaxurl = admin_url('admin-ajax.php');
|
74 |
$jsData = array(
|
modules/tgm_promo/classes/class-tgm-plugin-activation.php
CHANGED
@@ -1,3853 +1,3853 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Plugin installation and activation for WordPress themes.
|
4 |
-
*
|
5 |
-
* Please note that this is a drop-in library for a theme or plugin.
|
6 |
-
* The authors of this library (Thomas, Gary and Juliette) are NOT responsible
|
7 |
-
* for the support of your plugin or theme. Please contact the plugin
|
8 |
-
* or theme author for support.
|
9 |
-
*
|
10 |
-
* @package TGM-Plugin-Activation
|
11 |
-
* @version 2.6.1
|
12 |
-
* @link http://tgmpluginactivation.com/
|
13 |
-
* @author Thomas Griffin, Gary Jones, Juliette Reinders Folmer
|
14 |
-
* @copyright Copyright (c) 2011, Thomas Griffin
|
15 |
-
* @license GPL-2.0+
|
16 |
-
*/
|
17 |
-
|
18 |
-
/*
|
19 |
-
Copyright 2011 Thomas Griffin (thomasgriffinmedia.com)
|
20 |
-
|
21 |
-
This program is free software; you can redistribute it and/or modify
|
22 |
-
it under the terms of the GNU General Public License, version 2, as
|
23 |
-
published by the Free Software Foundation.
|
24 |
-
|
25 |
-
This program is distributed in the hope that it will be useful,
|
26 |
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
27 |
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
28 |
-
GNU General Public License for more details.
|
29 |
-
|
30 |
-
You should have received a copy of the GNU General Public License
|
31 |
-
along with this program; if not, write to the Free Software
|
32 |
-
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
33 |
-
*/
|
34 |
-
|
35 |
-
if ( ! class_exists( 'TGM_Plugin_Activation' ) ) {
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Automatic plugin installation and activation library.
|
39 |
-
*
|
40 |
-
* Creates a way to automatically install and activate plugins from within themes.
|
41 |
-
* The plugins can be either bundled, downloaded from the WordPress
|
42 |
-
* Plugin Repository or downloaded from another external source.
|
43 |
-
*
|
44 |
-
* @since 1.0.0
|
45 |
-
*
|
46 |
-
* @package TGM-Plugin-Activation
|
47 |
-
* @author Thomas Griffin
|
48 |
-
* @author Gary Jones
|
49 |
-
*/
|
50 |
-
class TGM_Plugin_Activation {
|
51 |
-
/**
|
52 |
-
* TGMPA version number.
|
53 |
-
*
|
54 |
-
* @since 2.5.0
|
55 |
-
*
|
56 |
-
* @const string Version number.
|
57 |
-
*/
|
58 |
-
const TGMPA_VERSION = '2.6.1';
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Regular expression to test if a URL is a WP plugin repo URL.
|
62 |
-
*
|
63 |
-
* @const string Regex.
|
64 |
-
*
|
65 |
-
* @since 2.5.0
|
66 |
-
*/
|
67 |
-
const WP_REPO_REGEX = '|^http[s]?://wordpress\.org/(?:extend/)?plugins/|';
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Arbitrary regular expression to test if a string starts with a URL.
|
71 |
-
*
|
72 |
-
* @const string Regex.
|
73 |
-
*
|
74 |
-
* @since 2.5.0
|
75 |
-
*/
|
76 |
-
const IS_URL_REGEX = '|^http[s]?://|';
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Holds a copy of itself, so it can be referenced by the class name.
|
80 |
-
*
|
81 |
-
* @since 1.0.0
|
82 |
-
*
|
83 |
-
* @var TGM_Plugin_Activation
|
84 |
-
*/
|
85 |
-
public static $instance;
|
86 |
-
|
87 |
-
/**
|
88 |
-
* Holds arrays of plugin details.
|
89 |
-
*
|
90 |
-
* @since 1.0.0
|
91 |
-
* @since 2.5.0 the array has the plugin slug as an associative key.
|
92 |
-
*
|
93 |
-
* @var array
|
94 |
-
*/
|
95 |
-
public $plugins = array();
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Holds arrays of plugin names to use to sort the plugins array.
|
99 |
-
*
|
100 |
-
* @since 2.5.0
|
101 |
-
*
|
102 |
-
* @var array
|
103 |
-
*/
|
104 |
-
protected $sort_order = array();
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Whether any plugins have the 'force_activation' setting set to true.
|
108 |
-
*
|
109 |
-
* @since 2.5.0
|
110 |
-
*
|
111 |
-
* @var bool
|
112 |
-
*/
|
113 |
-
protected $has_forced_activation = false;
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Whether any plugins have the 'force_deactivation' setting set to true.
|
117 |
-
*
|
118 |
-
* @since 2.5.0
|
119 |
-
*
|
120 |
-
* @var bool
|
121 |
-
*/
|
122 |
-
protected $has_forced_deactivation = false;
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Name of the unique ID to hash notices.
|
126 |
-
*
|
127 |
-
* @since 2.4.0
|
128 |
-
*
|
129 |
-
* @var string
|
130 |
-
*/
|
131 |
-
public $id = 'tgmpa';
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Name of the query-string argument for the admin page.
|
135 |
-
*
|
136 |
-
* @since 1.0.0
|
137 |
-
*
|
138 |
-
* @var string
|
139 |
-
*/
|
140 |
-
protected $menu = 'tgmpa-install-plugins';
|
141 |
-
|
142 |
-
/**
|
143 |
-
* Parent menu file slug.
|
144 |
-
*
|
145 |
-
* @since 2.5.0
|
146 |
-
*
|
147 |
-
* @var string
|
148 |
-
*/
|
149 |
-
public $parent_slug = 'themes.php';
|
150 |
-
|
151 |
-
/**
|
152 |
-
* Capability needed to view the plugin installation menu item.
|
153 |
-
*
|
154 |
-
* @since 2.5.0
|
155 |
-
*
|
156 |
-
* @var string
|
157 |
-
*/
|
158 |
-
public $capability = 'edit_theme_options';
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Default absolute path to folder containing bundled plugin zip files.
|
162 |
-
*
|
163 |
-
* @since 2.0.0
|
164 |
-
*
|
165 |
-
* @var string Absolute path prefix to zip file location for bundled plugins. Default is empty string.
|
166 |
-
*/
|
167 |
-
public $default_path = '';
|
168 |
-
|
169 |
-
/**
|
170 |
-
* Flag to show admin notices or not.
|
171 |
-
*
|
172 |
-
* @since 2.1.0
|
173 |
-
*
|
174 |
-
* @var boolean
|
175 |
-
*/
|
176 |
-
public $has_notices = true;
|
177 |
-
|
178 |
-
/**
|
179 |
-
* Flag to determine if the user can dismiss the notice nag.
|
180 |
-
*
|
181 |
-
* @since 2.4.0
|
182 |
-
*
|
183 |
-
* @var boolean
|
184 |
-
*/
|
185 |
-
public $dismissable = true;
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Message to be output above nag notice if dismissable is false.
|
189 |
-
*
|
190 |
-
* @since 2.4.0
|
191 |
-
*
|
192 |
-
* @var string
|
193 |
-
*/
|
194 |
-
public $dismiss_msg = '';
|
195 |
-
|
196 |
-
/**
|
197 |
-
* Flag to set automatic activation of plugins. Off by default.
|
198 |
-
*
|
199 |
-
* @since 2.2.0
|
200 |
-
*
|
201 |
-
* @var boolean
|
202 |
-
*/
|
203 |
-
public $is_automatic = false;
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Optional message to display before the plugins table.
|
207 |
-
*
|
208 |
-
* @since 2.2.0
|
209 |
-
*
|
210 |
-
* @var string Message filtered by wp_kses_post(). Default is empty string.
|
211 |
-
*/
|
212 |
-
public $message = '';
|
213 |
-
|
214 |
-
/**
|
215 |
-
* Holds configurable array of strings.
|
216 |
-
*
|
217 |
-
* Default values are added in the constructor.
|
218 |
-
*
|
219 |
-
* @since 2.0.0
|
220 |
-
*
|
221 |
-
* @var array
|
222 |
-
*/
|
223 |
-
public $strings = array();
|
224 |
-
|
225 |
-
/**
|
226 |
-
* Holds the version of WordPress.
|
227 |
-
*
|
228 |
-
* @since 2.4.0
|
229 |
-
*
|
230 |
-
* @var int
|
231 |
-
*/
|
232 |
-
public $wp_version;
|
233 |
-
|
234 |
-
/**
|
235 |
-
* Holds the hook name for the admin page.
|
236 |
-
*
|
237 |
-
* @since 2.5.0
|
238 |
-
*
|
239 |
-
* @var string
|
240 |
-
*/
|
241 |
-
public $page_hook;
|
242 |
-
|
243 |
-
/**
|
244 |
-
* Adds a reference of this object to $instance, populates default strings,
|
245 |
-
* does the tgmpa_init action hook, and hooks in the interactions to init.
|
246 |
-
*
|
247 |
-
* {@internal This method should be `protected`, but as too many TGMPA implementations
|
248 |
-
* haven't upgraded beyond v2.3.6 yet, this gives backward compatibility issues.
|
249 |
-
* Reverted back to public for the time being.}}
|
250 |
-
*
|
251 |
-
* @since 1.0.0
|
252 |
-
*
|
253 |
-
* @see TGM_Plugin_Activation::init()
|
254 |
-
*/
|
255 |
-
public function __construct() {
|
256 |
-
// Set the current WordPress version.
|
257 |
-
$this->wp_version = $GLOBALS['wp_version'];
|
258 |
-
|
259 |
-
// Announce that the class is ready, and pass the object (for advanced use).
|
260 |
-
do_action_ref_array( 'tgmpa_init', array( $this ) );
|
261 |
-
|
262 |
-
/*
|
263 |
-
* Load our text domain and allow for overloading the fall-back file.
|
264 |
-
*
|
265 |
-
* {@internal IMPORTANT! If this code changes, review the regex in the custom TGMPA
|
266 |
-
* generator on the website.}}
|
267 |
-
*/
|
268 |
-
add_action( 'init', array( $this, 'load_textdomain' ), 5 );
|
269 |
-
add_filter( 'load_textdomain_mofile', array( $this, 'overload_textdomain_mofile' ), 10, 2 );
|
270 |
-
|
271 |
-
// When the rest of WP has loaded, kick-start the rest of the class.
|
272 |
-
add_action( 'init', array( $this, 'init' ) );
|
273 |
-
}
|
274 |
-
|
275 |
-
/**
|
276 |
-
* Magic method to (not) set protected properties from outside of this class.
|
277 |
-
*
|
278 |
-
* {@internal hackedihack... There is a serious bug in v2.3.2 - 2.3.6 where the `menu` property
|
279 |
-
* is being assigned rather than tested in a conditional, effectively rendering it useless.
|
280 |
-
* This 'hack' prevents this from happening.}}
|
281 |
-
*
|
282 |
-
* @see https://github.com/TGMPA/TGM-Plugin-Activation/blob/2.3.6/tgm-plugin-activation/class-tgm-plugin-activation.php#L1593
|
283 |
-
*
|
284 |
-
* @since 2.5.2
|
285 |
-
*
|
286 |
-
* @param string $name Name of an inaccessible property.
|
287 |
-
* @param mixed $value Value to assign to the property.
|
288 |
-
* @return void Silently fail to set the property when this is tried from outside of this class context.
|
289 |
-
* (Inside this class context, the __set() method if not used as there is direct access.)
|
290 |
-
*/
|
291 |
-
public function __set( $name, $value ) {
|
292 |
-
return;
|
293 |
-
}
|
294 |
-
|
295 |
-
/**
|
296 |
-
* Magic method to get the value of a protected property outside of this class context.
|
297 |
-
*
|
298 |
-
* @since 2.5.2
|
299 |
-
*
|
300 |
-
* @param string $name Name of an inaccessible property.
|
301 |
-
* @return mixed The property value.
|
302 |
-
*/
|
303 |
-
public function __get( $name ) {
|
304 |
-
return $this->{$name};
|
305 |
-
}
|
306 |
-
|
307 |
-
/**
|
308 |
-
* Initialise the interactions between this class and WordPress.
|
309 |
-
*
|
310 |
-
* Hooks in three new methods for the class: admin_menu, notices and styles.
|
311 |
-
*
|
312 |
-
* @since 2.0.0
|
313 |
-
*
|
314 |
-
* @see TGM_Plugin_Activation::admin_menu()
|
315 |
-
* @see TGM_Plugin_Activation::notices()
|
316 |
-
* @see TGM_Plugin_Activation::styles()
|
317 |
-
*/
|
318 |
-
public function init() {
|
319 |
-
/**
|
320 |
-
* By default TGMPA only loads on the WP back-end and not in an Ajax call. Using this filter
|
321 |
-
* you can overrule that behaviour.
|
322 |
-
*
|
323 |
-
* @since 2.5.0
|
324 |
-
*
|
325 |
-
* @param bool $load Whether or not TGMPA should load.
|
326 |
-
* Defaults to the return of `is_admin() && ! defined( 'DOING_AJAX' )`.
|
327 |
-
*/
|
328 |
-
if ( true !== apply_filters( 'tgmpa_load', ( is_admin() && ! defined( 'DOING_AJAX' ) ) ) ) {
|
329 |
-
return;
|
330 |
-
}
|
331 |
-
|
332 |
-
// Load class strings.
|
333 |
-
$this->strings = array(
|
334 |
-
'page_title' => __( 'Install Required Plugins', 'tgmpa' ),
|
335 |
-
'menu_title' => __( 'Install Plugins', 'tgmpa' ),
|
336 |
-
/* translators: %s: plugin name. */
|
337 |
-
'installing' => __( 'Installing Plugin: %s', 'tgmpa' ),
|
338 |
-
/* translators: %s: plugin name. */
|
339 |
-
'updating' => __( 'Updating Plugin: %s', 'tgmpa' ),
|
340 |
-
'oops' => __( 'Something went wrong with the plugin API.', 'tgmpa' ),
|
341 |
-
'notice_can_install_required' => _n_noop(
|
342 |
-
/* translators: 1: plugin name(s). */
|
343 |
-
'This theme requires the following plugin: %1$s.',
|
344 |
-
'This theme requires the following plugins: %1$s.',
|
345 |
-
'tgmpa'
|
346 |
-
),
|
347 |
-
'notice_can_install_recommended' => _n_noop(
|
348 |
-
/* translators: 1: plugin name(s). */
|
349 |
-
'This theme recommends the following plugin: %1$s.',
|
350 |
-
'This theme recommends the following plugins: %1$s.',
|
351 |
-
'tgmpa'
|
352 |
-
),
|
353 |
-
'notice_ask_to_update' => _n_noop(
|
354 |
-
/* translators: 1: plugin name(s). */
|
355 |
-
'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.',
|
356 |
-
'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.',
|
357 |
-
'tgmpa'
|
358 |
-
),
|
359 |
-
'notice_ask_to_update_maybe' => _n_noop(
|
360 |
-
/* translators: 1: plugin name(s). */
|
361 |
-
'There is an update available for: %1$s.',
|
362 |
-
'There are updates available for the following plugins: %1$s.',
|
363 |
-
'tgmpa'
|
364 |
-
),
|
365 |
-
'notice_can_activate_required' => _n_noop(
|
366 |
-
/* translators: 1: plugin name(s). */
|
367 |
-
'The following required plugin is currently inactive: %1$s.',
|
368 |
-
'The following required plugins are currently inactive: %1$s.',
|
369 |
-
'tgmpa'
|
370 |
-
),
|
371 |
-
'notice_can_activate_recommended' => _n_noop(
|
372 |
-
/* translators: 1: plugin name(s). */
|
373 |
-
'The following recommended plugin is currently inactive: %1$s.',
|
374 |
-
'The following recommended plugins are currently inactive: %1$s.',
|
375 |
-
'tgmpa'
|
376 |
-
),
|
377 |
-
'install_link' => _n_noop(
|
378 |
-
'Begin installing plugin',
|
379 |
-
'Begin installing plugins',
|
380 |
-
'tgmpa'
|
381 |
-
),
|
382 |
-
'update_link' => _n_noop(
|
383 |
-
'Begin updating plugin',
|
384 |
-
'Begin updating plugins',
|
385 |
-
'tgmpa'
|
386 |
-
),
|
387 |
-
'activate_link' => _n_noop(
|
388 |
-
'Begin activating plugin',
|
389 |
-
'Begin activating plugins',
|
390 |
-
'tgmpa'
|
391 |
-
),
|
392 |
-
'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ),
|
393 |
-
'dashboard' => __( 'Return to the Dashboard', 'tgmpa' ),
|
394 |
-
'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ),
|
395 |
-
'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ),
|
396 |
-
/* translators: 1: plugin name. */
|
397 |
-
'plugin_already_active' => __( 'No action taken. Plugin %1$s was already active.', 'tgmpa' ),
|
398 |
-
/* translators: 1: plugin name. */
|
399 |
-
'plugin_needs_higher_version' => __( 'Plugin not activated. A higher version of %s is needed for this theme. Please update the plugin.', 'tgmpa' ),
|
400 |
-
/* translators: 1: dashboard link. */
|
401 |
-
'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ),
|
402 |
-
'dismiss' => __( 'Dismiss this notice', 'tgmpa' ),
|
403 |
-
'notice_cannot_install_activate' => __( 'There are one or more required or recommended plugins to install, update or activate.', 'tgmpa' ),
|
404 |
-
'contact_admin' => __( 'Please contact the administrator of this site for help.', 'tgmpa' ),
|
405 |
-
);
|
406 |
-
|
407 |
-
do_action( 'tgmpa_register' );
|
408 |
-
|
409 |
-
/* After this point, the plugins should be registered and the configuration set. */
|
410 |
-
|
411 |
-
// Proceed only if we have plugins to handle.
|
412 |
-
if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) {
|
413 |
-
return;
|
414 |
-
}
|
415 |
-
|
416 |
-
// Set up the menu and notices if we still have outstanding actions.
|
417 |
-
if ( true !== $this->is_tgmpa_complete() ) {
|
418 |
-
// Sort the plugins.
|
419 |
-
array_multisort( $this->sort_order, SORT_ASC, $this->plugins );
|
420 |
-
|
421 |
-
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
422 |
-
add_action( 'admin_head', array( $this, 'dismiss' ) );
|
423 |
-
|
424 |
-
// Prevent the normal links from showing underneath a single install/update page.
|
425 |
-
add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) );
|
426 |
-
add_filter( 'update_plugin_complete_actions', array( $this, 'actions' ) );
|
427 |
-
|
428 |
-
if ( $this->has_notices ) {
|
429 |
-
add_action( 'admin_notices', array( $this, 'notices' ) );
|
430 |
-
add_action( 'admin_init', array( $this, 'admin_init' ), 1 );
|
431 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) );
|
432 |
-
}
|
433 |
-
}
|
434 |
-
|
435 |
-
// If needed, filter plugin action links.
|
436 |
-
add_action( 'load-plugins.php', array( $this, 'add_plugin_action_link_filters' ), 1 );
|
437 |
-
|
438 |
-
// Make sure things get reset on switch theme.
|
439 |
-
add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) );
|
440 |
-
|
441 |
-
if ( $this->has_notices ) {
|
442 |
-
add_action( 'switch_theme', array( $this, 'update_dismiss' ) );
|
443 |
-
}
|
444 |
-
|
445 |
-
// Setup the force activation hook.
|
446 |
-
if ( true === $this->has_forced_activation ) {
|
447 |
-
add_action( 'admin_init', array( $this, 'force_activation' ) );
|
448 |
-
}
|
449 |
-
|
450 |
-
// Setup the force deactivation hook.
|
451 |
-
if ( true === $this->has_forced_deactivation ) {
|
452 |
-
add_action( 'switch_theme', array( $this, 'force_deactivation' ) );
|
453 |
-
}
|
454 |
-
}
|
455 |
-
|
456 |
-
/**
|
457 |
-
* Load translations.
|
458 |
-
*
|
459 |
-
* @since 2.6.0
|
460 |
-
*
|
461 |
-
* (@internal Uses `load_theme_textdomain()` rather than `load_plugin_textdomain()` to
|
462 |
-
* get round the different ways of handling the path and deprecated notices being thrown
|
463 |
-
* and such. For plugins, the actual file name will be corrected by a filter.}}
|
464 |
-
*
|
465 |
-
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
466 |
-
* generator on the website.}}
|
467 |
-
*/
|
468 |
-
public function load_textdomain() {
|
469 |
-
if ( is_textdomain_loaded( 'tgmpa' ) ) {
|
470 |
-
return;
|
471 |
-
}
|
472 |
-
|
473 |
-
if ( false !== strpos( __FILE__, WP_PLUGIN_DIR ) || false !== strpos( __FILE__, WPMU_PLUGIN_DIR ) ) {
|
474 |
-
// Plugin, we'll need to adjust the file name.
|
475 |
-
add_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10, 2 );
|
476 |
-
load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' );
|
477 |
-
remove_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10 );
|
478 |
-
} else {
|
479 |
-
load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' );
|
480 |
-
}
|
481 |
-
}
|
482 |
-
|
483 |
-
/**
|
484 |
-
* Correct the .mo file name for (must-use) plugins.
|
485 |
-
*
|
486 |
-
* Themese use `/path/{locale}.mo` while plugins use `/path/{text-domain}-{locale}.mo`.
|
487 |
-
*
|
488 |
-
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
489 |
-
* generator on the website.}}
|
490 |
-
*
|
491 |
-
* @since 2.6.0
|
492 |
-
*
|
493 |
-
* @param string $mofile Full path to the target mofile.
|
494 |
-
* @param string $domain The domain for which a language file is being loaded.
|
495 |
-
* @return string $mofile
|
496 |
-
*/
|
497 |
-
public function correct_plugin_mofile( $mofile, $domain ) {
|
498 |
-
// Exit early if not our domain (just in case).
|
499 |
-
if ( 'tgmpa' !== $domain ) {
|
500 |
-
return $mofile;
|
501 |
-
}
|
502 |
-
return preg_replace( '`/([a-z]{2}_[A-Z]{2}.mo)$`', '/tgmpa-$1', $mofile );
|
503 |
-
}
|
504 |
-
|
505 |
-
/**
|
506 |
-
* Potentially overload the fall-back translation file for the current language.
|
507 |
-
*
|
508 |
-
* WP, by default since WP 3.7, will load a local translation first and if none
|
509 |
-
* can be found, will try and find a translation in the /wp-content/languages/ directory.
|
510 |
-
* As this library is theme/plugin agnostic, translation files for TGMPA can exist both
|
511 |
-
* in the WP_LANG_DIR /plugins/ subdirectory as well as in the /themes/ subdirectory.
|
512 |
-
*
|
513 |
-
* This method makes sure both directories are checked.
|
514 |
-
*
|
515 |
-
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
516 |
-
* generator on the website.}}
|
517 |
-
*
|
518 |
-
* @since 2.6.0
|
519 |
-
*
|
520 |
-
* @param string $mofile Full path to the target mofile.
|
521 |
-
* @param string $domain The domain for which a language file is being loaded.
|
522 |
-
* @return string $mofile
|
523 |
-
*/
|
524 |
-
public function overload_textdomain_mofile( $mofile, $domain ) {
|
525 |
-
// Exit early if not our domain, not a WP_LANG_DIR load or if the file exists and is readable.
|
526 |
-
if ( 'tgmpa' !== $domain || false === strpos( $mofile, WP_LANG_DIR ) || @is_readable( $mofile ) ) {
|
527 |
-
return $mofile;
|
528 |
-
}
|
529 |
-
|
530 |
-
// Current fallback file is not valid, let's try the alternative option.
|
531 |
-
if ( false !== strpos( $mofile, '/themes/' ) ) {
|
532 |
-
return str_replace( '/themes/', '/plugins/', $mofile );
|
533 |
-
} elseif ( false !== strpos( $mofile, '/plugins/' ) ) {
|
534 |
-
return str_replace( '/plugins/', '/themes/', $mofile );
|
535 |
-
} else {
|
536 |
-
return $mofile;
|
537 |
-
}
|
538 |
-
}
|
539 |
-
|
540 |
-
/**
|
541 |
-
* Hook in plugin action link filters for the WP native plugins page.
|
542 |
-
*
|
543 |
-
* - Prevent activation of plugins which don't meet the minimum version requirements.
|
544 |
-
* - Prevent deactivation of force-activated plugins.
|
545 |
-
* - Add update notice if update available.
|
546 |
-
*
|
547 |
-
* @since 2.5.0
|
548 |
-
*/
|
549 |
-
public function add_plugin_action_link_filters() {
|
550 |
-
foreach ( $this->plugins as $slug => $plugin ) {
|
551 |
-
if ( false === $this->can_plugin_activate( $slug ) ) {
|
552 |
-
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_activate' ), 20 );
|
553 |
-
}
|
554 |
-
|
555 |
-
if ( true === $plugin['force_activation'] ) {
|
556 |
-
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_deactivate' ), 20 );
|
557 |
-
}
|
558 |
-
|
559 |
-
if ( false !== $this->does_plugin_require_update( $slug ) ) {
|
560 |
-
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_update' ), 20 );
|
561 |
-
}
|
562 |
-
}
|
563 |
-
}
|
564 |
-
|
565 |
-
/**
|
566 |
-
* Remove the 'Activate' link on the WP native plugins page if the plugin does not meet the
|
567 |
-
* minimum version requirements.
|
568 |
-
*
|
569 |
-
* @since 2.5.0
|
570 |
-
*
|
571 |
-
* @param array $actions Action links.
|
572 |
-
* @return array
|
573 |
-
*/
|
574 |
-
public function filter_plugin_action_links_activate( $actions ) {
|
575 |
-
unset( $actions['activate'] );
|
576 |
-
|
577 |
-
return $actions;
|
578 |
-
}
|
579 |
-
|
580 |
-
/**
|
581 |
-
* Remove the 'Deactivate' link on the WP native plugins page if the plugin has been set to force activate.
|
582 |
-
*
|
583 |
-
* @since 2.5.0
|
584 |
-
*
|
585 |
-
* @param array $actions Action links.
|
586 |
-
* @return array
|
587 |
-
*/
|
588 |
-
public function filter_plugin_action_links_deactivate( $actions ) {
|
589 |
-
unset( $actions['deactivate'] );
|
590 |
-
|
591 |
-
return $actions;
|
592 |
-
}
|
593 |
-
|
594 |
-
/**
|
595 |
-
* Add a 'Requires update' link on the WP native plugins page if the plugin does not meet the
|
596 |
-
* minimum version requirements.
|
597 |
-
*
|
598 |
-
* @since 2.5.0
|
599 |
-
*
|
600 |
-
* @param array $actions Action links.
|
601 |
-
* @return array
|
602 |
-
*/
|
603 |
-
public function filter_plugin_action_links_update( $actions ) {
|
604 |
-
$actions['update'] = sprintf(
|
605 |
-
'<a href="%1$s" title="%2$s" class="edit">%3$s</a>',
|
606 |
-
esc_url( $this->get_tgmpa_status_url( 'update' ) ),
|
607 |
-
esc_attr__( 'This plugin needs to be updated to be compatible with your theme.', 'tgmpa' ),
|
608 |
-
esc_html__( 'Update Required', 'tgmpa' )
|
609 |
-
);
|
610 |
-
|
611 |
-
return $actions;
|
612 |
-
}
|
613 |
-
|
614 |
-
/**
|
615 |
-
* Handles calls to show plugin information via links in the notices.
|
616 |
-
*
|
617 |
-
* We get the links in the admin notices to point to the TGMPA page, rather
|
618 |
-
* than the typical plugin-install.php file, so we can prepare everything
|
619 |
-
* beforehand.
|
620 |
-
*
|
621 |
-
* WP does not make it easy to show the plugin information in the thickbox -
|
622 |
-
* here we have to require a file that includes a function that does the
|
623 |
-
* main work of displaying it, enqueue some styles, set up some globals and
|
624 |
-
* finally call that function before exiting.
|
625 |
-
*
|
626 |
-
* Down right easy once you know how...
|
627 |
-
*
|
628 |
-
* Returns early if not the TGMPA page.
|
629 |
-
*
|
630 |
-
* @since 2.1.0
|
631 |
-
*
|
632 |
-
* @global string $tab Used as iframe div class names, helps with styling
|
633 |
-
* @global string $body_id Used as the iframe body ID, helps with styling
|
634 |
-
*
|
635 |
-
* @return null Returns early if not the TGMPA page.
|
636 |
-
*/
|
637 |
-
public function admin_init() {
|
638 |
-
if ( ! $this->is_tgmpa_page() ) {
|
639 |
-
return;
|
640 |
-
}
|
641 |
-
|
642 |
-
if ( isset( $_REQUEST['tab'] ) && 'plugin-information' === $_REQUEST['tab'] ) {
|
643 |
-
// Needed for install_plugin_information().
|
644 |
-
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
|
645 |
-
|
646 |
-
wp_enqueue_style( 'plugin-install' );
|
647 |
-
|
648 |
-
global $tab, $body_id;
|
649 |
-
$body_id = 'plugin-information';
|
650 |
-
// @codingStandardsIgnoreStart
|
651 |
-
$tab = 'plugin-information';
|
652 |
-
// @codingStandardsIgnoreEnd
|
653 |
-
|
654 |
-
install_plugin_information();
|
655 |
-
|
656 |
-
exit;
|
657 |
-
}
|
658 |
-
}
|
659 |
-
|
660 |
-
/**
|
661 |
-
* Enqueue thickbox scripts/styles for plugin info.
|
662 |
-
*
|
663 |
-
* Thickbox is not automatically included on all admin pages, so we must
|
664 |
-
* manually enqueue it for those pages.
|
665 |
-
*
|
666 |
-
* Thickbox is only loaded if the user has not dismissed the admin
|
667 |
-
* notice or if there are any plugins left to install and activate.
|
668 |
-
*
|
669 |
-
* @since 2.1.0
|
670 |
-
*/
|
671 |
-
public function thickbox() {
|
672 |
-
if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) {
|
673 |
-
add_thickbox();
|
674 |
-
}
|
675 |
-
}
|
676 |
-
|
677 |
-
/**
|
678 |
-
* Adds submenu page if there are plugin actions to take.
|
679 |
-
*
|
680 |
-
* This method adds the submenu page letting users know that a required
|
681 |
-
* plugin needs to be installed.
|
682 |
-
*
|
683 |
-
* This page disappears once the plugin has been installed and activated.
|
684 |
-
*
|
685 |
-
* @since 1.0.0
|
686 |
-
*
|
687 |
-
* @see TGM_Plugin_Activation::init()
|
688 |
-
* @see TGM_Plugin_Activation::install_plugins_page()
|
689 |
-
*
|
690 |
-
* @return null Return early if user lacks capability to install a plugin.
|
691 |
-
*/
|
692 |
-
public function admin_menu() {
|
693 |
-
// Make sure privileges are correct to see the page.
|
694 |
-
if ( ! current_user_can( 'install_plugins' ) ) {
|
695 |
-
return;
|
696 |
-
}
|
697 |
-
|
698 |
-
$args = apply_filters(
|
699 |
-
'tgmpa_admin_menu_args',
|
700 |
-
array(
|
701 |
-
'parent_slug' => $this->parent_slug, // Parent Menu slug.
|
702 |
-
'page_title' => $this->strings['page_title'], // Page title.
|
703 |
-
'menu_title' => $this->strings['menu_title'], // Menu title.
|
704 |
-
'capability' => $this->capability, // Capability.
|
705 |
-
'menu_slug' => $this->menu, // Menu slug.
|
706 |
-
'function' => array( $this, 'install_plugins_page' ), // Callback.
|
707 |
-
)
|
708 |
-
);
|
709 |
-
|
710 |
-
$this->add_admin_menu( $args );
|
711 |
-
}
|
712 |
-
|
713 |
-
/**
|
714 |
-
* Add the menu item.
|
715 |
-
*
|
716 |
-
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
717 |
-
* generator on the website.}}
|
718 |
-
*
|
719 |
-
* @since 2.5.0
|
720 |
-
*
|
721 |
-
* @param array $args Menu item configuration.
|
722 |
-
*/
|
723 |
-
protected function add_admin_menu( array $args ) {
|
724 |
-
if ( has_filter( 'tgmpa_admin_menu_use_add_theme_page' ) ) {
|
725 |
-
_deprecated_function( 'The "tgmpa_admin_menu_use_add_theme_page" filter', '2.5.0', esc_html__( 'Set the parent_slug config variable instead.', 'tgmpa' ) );
|
726 |
-
}
|
727 |
-
|
728 |
-
if ( 'themes.php' === $this->parent_slug ) {
|
729 |
-
$this->page_hook = call_user_func( 'add_theme_page', $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
|
730 |
-
} else {
|
731 |
-
$this->page_hook = call_user_func( 'add_submenu_page', $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
|
732 |
-
}
|
733 |
-
}
|
734 |
-
|
735 |
-
/**
|
736 |
-
* Echoes plugin installation form.
|
737 |
-
*
|
738 |
-
* This method is the callback for the admin_menu method function.
|
739 |
-
* This displays the admin page and form area where the user can select to install and activate the plugin.
|
740 |
-
* Aborts early if we're processing a plugin installation action.
|
741 |
-
*
|
742 |
-
* @since 1.0.0
|
743 |
-
*
|
744 |
-
* @return null Aborts early if we're processing a plugin installation action.
|
745 |
-
*/
|
746 |
-
public function install_plugins_page() {
|
747 |
-
// Store new instance of plugin table in object.
|
748 |
-
$plugin_table = new TGMPA_List_Table;
|
749 |
-
|
750 |
-
// Return early if processing a plugin installation action.
|
751 |
-
if ( ( ( 'tgmpa-bulk-install' === $plugin_table->current_action() || 'tgmpa-bulk-update' === $plugin_table->current_action() ) && $plugin_table->process_bulk_actions() ) || $this->do_plugin_install() ) {
|
752 |
-
return;
|
753 |
-
}
|
754 |
-
|
755 |
-
// Force refresh of available plugin information so we'll know about manual updates/deletes.
|
756 |
-
wp_clean_plugins_cache( false );
|
757 |
-
|
758 |
-
?>
|
759 |
-
<div class="tgmpa wrap">
|
760 |
-
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
761 |
-
<?php $plugin_table->prepare_items(); ?>
|
762 |
-
|
763 |
-
<?php
|
764 |
-
if ( ! empty( $this->message ) && is_string( $this->message ) ) {
|
765 |
-
echo wp_kses_post( $this->message );
|
766 |
-
}
|
767 |
-
?>
|
768 |
-
<?php $plugin_table->views(); ?>
|
769 |
-
|
770 |
-
<form id="tgmpa-plugins" action="" method="post">
|
771 |
-
<input type="hidden" name="tgmpa-page" value="<?php echo esc_attr( $this->menu ); ?>" />
|
772 |
-
<input type="hidden" name="plugin_status" value="<?php echo esc_attr( $plugin_table->view_context ); ?>" />
|
773 |
-
<?php $plugin_table->display(); ?>
|
774 |
-
</form>
|
775 |
-
</div>
|
776 |
-
<?php
|
777 |
-
}
|
778 |
-
|
779 |
-
/**
|
780 |
-
* Installs, updates or activates a plugin depending on the action link clicked by the user.
|
781 |
-
*
|
782 |
-
* Checks the $_GET variable to see which actions have been
|
783 |
-
* passed and responds with the appropriate method.
|
784 |
-
*
|
785 |
-
* Uses WP_Filesystem to process and handle the plugin installation
|
786 |
-
* method.
|
787 |
-
*
|
788 |
-
* @since 1.0.0
|
789 |
-
*
|
790 |
-
* @uses WP_Filesystem
|
791 |
-
* @uses WP_Error
|
792 |
-
* @uses WP_Upgrader
|
793 |
-
* @uses Plugin_Upgrader
|
794 |
-
* @uses Plugin_Installer_Skin
|
795 |
-
* @uses Plugin_Upgrader_Skin
|
796 |
-
*
|
797 |
-
* @return boolean True on success, false on failure.
|
798 |
-
*/
|
799 |
-
protected function do_plugin_install() {
|
800 |
-
if ( empty( $_GET['plugin'] ) ) {
|
801 |
-
return false;
|
802 |
-
}
|
803 |
-
|
804 |
-
// All plugin information will be stored in an array for processing.
|
805 |
-
$slug = $this->sanitize_key( urldecode( $_GET['plugin'] ) );
|
806 |
-
|
807 |
-
if ( ! isset( $this->plugins[ $slug ] ) ) {
|
808 |
-
return false;
|
809 |
-
}
|
810 |
-
|
811 |
-
// Was an install or upgrade action link clicked?
|
812 |
-
if ( ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' === $_GET['tgmpa-install'] ) || ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) ) {
|
813 |
-
|
814 |
-
$install_type = 'install';
|
815 |
-
if ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) {
|
816 |
-
$install_type = 'update';
|
817 |
-
}
|
818 |
-
|
819 |
-
check_admin_referer( 'tgmpa-' . $install_type, 'tgmpa-nonce' );
|
820 |
-
|
821 |
-
// Pass necessary information via URL if WP_Filesystem is needed.
|
822 |
-
$url = wp_nonce_url(
|
823 |
-
add_query_arg(
|
824 |
-
array(
|
825 |
-
'plugin' => urlencode( $slug ),
|
826 |
-
'tgmpa-' . $install_type => $install_type . '-plugin',
|
827 |
-
),
|
828 |
-
$this->get_tgmpa_url()
|
829 |
-
),
|
830 |
-
'tgmpa-' . $install_type,
|
831 |
-
'tgmpa-nonce'
|
832 |
-
);
|
833 |
-
|
834 |
-
$method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
|
835 |
-
|
836 |
-
if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, array() ) ) ) {
|
837 |
-
return true;
|
838 |
-
}
|
839 |
-
|
840 |
-
if ( ! WP_Filesystem( $creds ) ) {
|
841 |
-
request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, array() ); // Setup WP_Filesystem.
|
842 |
-
return true;
|
843 |
-
}
|
844 |
-
|
845 |
-
/* If we arrive here, we have the filesystem. */
|
846 |
-
|
847 |
-
// Prep variables for Plugin_Installer_Skin class.
|
848 |
-
$extra = array();
|
849 |
-
$extra['slug'] = $slug; // Needed for potentially renaming of directory name.
|
850 |
-
$source = $this->get_download_url( $slug );
|
851 |
-
$api = ( 'repo' === $this->plugins[ $slug ]['source_type'] ) ? $this->get_plugins_api( $slug ) : null;
|
852 |
-
$api = ( false !== $api ) ? $api : null;
|
853 |
-
|
854 |
-
$url = add_query_arg(
|
855 |
-
array(
|
856 |
-
'action' => $install_type . '-plugin',
|
857 |
-
'plugin' => urlencode( $slug ),
|
858 |
-
),
|
859 |
-
'update.php'
|
860 |
-
);
|
861 |
-
|
862 |
-
if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
|
863 |
-
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
864 |
-
}
|
865 |
-
|
866 |
-
$title = ( 'update' === $install_type ) ? $this->strings['updating'] : $this->strings['installing'];
|
867 |
-
$skin_args = array(
|
868 |
-
'type' => ( 'bundled' !== $this->plugins[ $slug ]['source_type'] ) ? 'web' : 'upload',
|
869 |
-
'title' => sprintf( $title, $this->plugins[ $slug ]['name'] ),
|
870 |
-
'url' => esc_url_raw( $url ),
|
871 |
-
'nonce' => $install_type . '-plugin_' . $slug,
|
872 |
-
'plugin' => '',
|
873 |
-
'api' => $api,
|
874 |
-
'extra' => $extra,
|
875 |
-
);
|
876 |
-
unset( $title );
|
877 |
-
|
878 |
-
if ( 'update' === $install_type ) {
|
879 |
-
$skin_args['plugin'] = $this->plugins[ $slug ]['file_path'];
|
880 |
-
$skin = new Plugin_Upgrader_Skin( $skin_args );
|
881 |
-
} else {
|
882 |
-
$skin = new Plugin_Installer_Skin( $skin_args );
|
883 |
-
}
|
884 |
-
|
885 |
-
// Create a new instance of Plugin_Upgrader.
|
886 |
-
$upgrader = new Plugin_Upgrader( $skin );
|
887 |
-
|
888 |
-
// Perform the action and install the plugin from the $source urldecode().
|
889 |
-
add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
|
890 |
-
|
891 |
-
if ( 'update' === $install_type ) {
|
892 |
-
// Inject our info into the update transient.
|
893 |
-
$to_inject = array( $slug => $this->plugins[ $slug ] );
|
894 |
-
$to_inject[ $slug ]['source'] = $source;
|
895 |
-
$this->inject_update_info( $to_inject );
|
896 |
-
|
897 |
-
$upgrader->upgrade( $this->plugins[ $slug ]['file_path'] );
|
898 |
-
} else {
|
899 |
-
$upgrader->install( $source );
|
900 |
-
}
|
901 |
-
|
902 |
-
remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1 );
|
903 |
-
|
904 |
-
// Make sure we have the correct file path now the plugin is installed/updated.
|
905 |
-
$this->populate_file_path( $slug );
|
906 |
-
|
907 |
-
// Only activate plugins if the config option is set to true and the plugin isn't
|
908 |
-
// already active (upgrade).
|
909 |
-
if ( $this->is_automatic && ! $this->is_plugin_active( $slug ) ) {
|
910 |
-
$plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method.
|
911 |
-
if ( false === $this->activate_single_plugin( $plugin_activate, $slug, true ) ) {
|
912 |
-
return true; // Finish execution of the function early as we encountered an error.
|
913 |
-
}
|
914 |
-
}
|
915 |
-
|
916 |
-
$this->show_tgmpa_version();
|
917 |
-
|
918 |
-
// Display message based on if all plugins are now active or not.
|
919 |
-
if ( $this->is_tgmpa_complete() ) {
|
920 |
-
echo '<p>', sprintf( esc_html( $this->strings['complete'] ), '<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>' ), '</p>';
|
921 |
-
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
|
922 |
-
} else {
|
923 |
-
echo '<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
|
924 |
-
}
|
925 |
-
|
926 |
-
return true;
|
927 |
-
} elseif ( isset( $this->plugins[ $slug ]['file_path'], $_GET['tgmpa-activate'] ) && 'activate-plugin' === $_GET['tgmpa-activate'] ) {
|
928 |
-
// Activate action link was clicked.
|
929 |
-
check_admin_referer( 'tgmpa-activate', 'tgmpa-nonce' );
|
930 |
-
|
931 |
-
if ( false === $this->activate_single_plugin( $this->plugins[ $slug ]['file_path'], $slug ) ) {
|
932 |
-
return true; // Finish execution of the function early as we encountered an error.
|
933 |
-
}
|
934 |
-
}
|
935 |
-
|
936 |
-
return false;
|
937 |
-
}
|
938 |
-
|
939 |
-
/**
|
940 |
-
* Inject information into the 'update_plugins' site transient as WP checks that before running an update.
|
941 |
-
*
|
942 |
-
* @since 2.5.0
|
943 |
-
*
|
944 |
-
* @param array $plugins The plugin information for the plugins which are to be updated.
|
945 |
-
*/
|
946 |
-
public function inject_update_info( $plugins ) {
|
947 |
-
$repo_updates = get_site_transient( 'update_plugins' );
|
948 |
-
|
949 |
-
if ( ! is_object( $repo_updates ) ) {
|
950 |
-
$repo_updates = new stdClass;
|
951 |
-
}
|
952 |
-
|
953 |
-
foreach ( $plugins as $slug => $plugin ) {
|
954 |
-
$file_path = $plugin['file_path'];
|
955 |
-
|
956 |
-
if ( empty( $repo_updates->response[ $file_path ] ) ) {
|
957 |
-
$repo_updates->response[ $file_path ] = new stdClass;
|
958 |
-
}
|
959 |
-
|
960 |
-
// We only really need to set package, but let's do all we can in case WP changes something.
|
961 |
-
$repo_updates->response[ $file_path ]->slug = $slug;
|
962 |
-
$repo_updates->response[ $file_path ]->plugin = $file_path;
|
963 |
-
$repo_updates->response[ $file_path ]->new_version = $plugin['version'];
|
964 |
-
$repo_updates->response[ $file_path ]->package = $plugin['source'];
|
965 |
-
if ( empty( $repo_updates->response[ $file_path ]->url ) && ! empty( $plugin['external_url'] ) ) {
|
966 |
-
$repo_updates->response[ $file_path ]->url = $plugin['external_url'];
|
967 |
-
}
|
968 |
-
}
|
969 |
-
|
970 |
-
set_site_transient( 'update_plugins', $repo_updates );
|
971 |
-
}
|
972 |
-
|
973 |
-
/**
|
974 |
-
* Adjust the plugin directory name if necessary.
|
975 |
-
*
|
976 |
-
* The final destination directory of a plugin is based on the subdirectory name found in the
|
977 |
-
* (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this
|
978 |
-
* subdirectory name is not the same as the expected slug and the plugin will not be recognized
|
979 |
-
* as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to
|
980 |
-
* the expected plugin slug.
|
981 |
-
*
|
982 |
-
* @since 2.5.0
|
983 |
-
*
|
984 |
-
* @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/.
|
985 |
-
* @param string $remote_source Path to upgrade/zip-file-name.tmp.
|
986 |
-
* @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin.
|
987 |
-
* @return string $source
|
988 |
-
*/
|
989 |
-
public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) {
|
990 |
-
if ( ! $this->is_tgmpa_page() || ! is_object( $GLOBALS['wp_filesystem'] ) ) {
|
991 |
-
return $source;
|
992 |
-
}
|
993 |
-
|
994 |
-
// Check for single file plugins.
|
995 |
-
$source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) );
|
996 |
-
if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) {
|
997 |
-
return $source;
|
998 |
-
}
|
999 |
-
|
1000 |
-
// Multi-file plugin, let's see if the directory is correctly named.
|
1001 |
-
$desired_slug = '';
|
1002 |
-
|
1003 |
-
// Figure out what the slug is supposed to be.
|
1004 |
-
if ( false === $upgrader->bulk && ! empty( $upgrader->skin->options['extra']['slug'] ) ) {
|
1005 |
-
$desired_slug = $upgrader->skin->options['extra']['slug'];
|
1006 |
-
} else {
|
1007 |
-
// Bulk installer contains less info, so fall back on the info registered here.
|
1008 |
-
foreach ( $this->plugins as $slug => $plugin ) {
|
1009 |
-
if ( ! empty( $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) && $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) {
|
1010 |
-
$desired_slug = $slug;
|
1011 |
-
break;
|
1012 |
-
}
|
1013 |
-
}
|
1014 |
-
unset( $slug, $plugin );
|
1015 |
-
}
|
1016 |
-
|
1017 |
-
if ( ! empty( $desired_slug ) ) {
|
1018 |
-
$subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) );
|
1019 |
-
|
1020 |
-
if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) {
|
1021 |
-
$from_path = untrailingslashit( $source );
|
1022 |
-
$to_path = trailingslashit( $remote_source ) . $desired_slug;
|
1023 |
-
|
1024 |
-
if ( true === $GLOBALS['wp_filesystem']->move( $from_path, $to_path ) ) {
|
1025 |
-
return trailingslashit( $to_path );
|
1026 |
-
} else {
|
1027 |
-
return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
|
1028 |
-
}
|
1029 |
-
} elseif ( empty( $subdir_name ) ) {
|
1030 |
-
return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
|
1031 |
-
}
|
1032 |
-
}
|
1033 |
-
|
1034 |
-
return $source;
|
1035 |
-
}
|
1036 |
-
|
1037 |
-
/**
|
1038 |
-
* Activate a single plugin and send feedback about the result to the screen.
|
1039 |
-
*
|
1040 |
-
* @since 2.5.0
|
1041 |
-
*
|
1042 |
-
* @param string $file_path Path within wp-plugins/ to main plugin file.
|
1043 |
-
* @param string $slug Plugin slug.
|
1044 |
-
* @param bool $automatic Whether this is an automatic activation after an install. Defaults to false.
|
1045 |
-
* This determines the styling of the output messages.
|
1046 |
-
* @return bool False if an error was encountered, true otherwise.
|
1047 |
-
*/
|
1048 |
-
protected function activate_single_plugin( $file_path, $slug, $automatic = false ) {
|
1049 |
-
if ( $this->can_plugin_activate( $slug ) ) {
|
1050 |
-
$activate = activate_plugin( $file_path );
|
1051 |
-
|
1052 |
-
if ( is_wp_error( $activate ) ) {
|
1053 |
-
echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>',
|
1054 |
-
'<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
|
1055 |
-
|
1056 |
-
return false; // End it here if there is an error with activation.
|
1057 |
-
} else {
|
1058 |
-
if ( ! $automatic ) {
|
1059 |
-
// Make sure message doesn't display again if bulk activation is performed
|
1060 |
-
// immediately after a single activation.
|
1061 |
-
if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
|
1062 |
-
echo '<div id="message" class="updated"><p>', esc_html( $this->strings['activated_successfully'] ), ' <strong>', esc_html( $this->plugins[ $slug ]['name'] ), '.</strong></p></div>';
|
1063 |
-
}
|
1064 |
-
} else {
|
1065 |
-
// Simpler message layout for use on the plugin install page.
|
1066 |
-
echo '<p>', esc_html( $this->strings['plugin_activated'] ), '</p>';
|
1067 |
-
}
|
1068 |
-
}
|
1069 |
-
} elseif ( $this->is_plugin_active( $slug ) ) {
|
1070 |
-
// No simpler message format provided as this message should never be encountered
|
1071 |
-
// on the plugin install page.
|
1072 |
-
echo '<div id="message" class="error"><p>',
|
1073 |
-
sprintf(
|
1074 |
-
esc_html( $this->strings['plugin_already_active'] ),
|
1075 |
-
'<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
|
1076 |
-
),
|
1077 |
-
'</p></div>';
|
1078 |
-
} elseif ( $this->does_plugin_require_update( $slug ) ) {
|
1079 |
-
if ( ! $automatic ) {
|
1080 |
-
// Make sure message doesn't display again if bulk activation is performed
|
1081 |
-
// immediately after a single activation.
|
1082 |
-
if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
|
1083 |
-
echo '<div id="message" class="error"><p>',
|
1084 |
-
sprintf(
|
1085 |
-
esc_html( $this->strings['plugin_needs_higher_version'] ),
|
1086 |
-
'<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
|
1087 |
-
),
|
1088 |
-
'</p></div>';
|
1089 |
-
}
|
1090 |
-
} else {
|
1091 |
-
// Simpler message layout for use on the plugin install page.
|
1092 |
-
echo '<p>', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), esc_html( $this->plugins[ $slug ]['name'] ) ), '</p>';
|
1093 |
-
}
|
1094 |
-
}
|
1095 |
-
|
1096 |
-
return true;
|
1097 |
-
}
|
1098 |
-
|
1099 |
-
/**
|
1100 |
-
* Echoes required plugin notice.
|
1101 |
-
*
|
1102 |
-
* Outputs a message telling users that a specific plugin is required for
|
1103 |
-
* their theme. If appropriate, it includes a link to the form page where
|
1104 |
-
* users can install and activate the plugin.
|
1105 |
-
*
|
1106 |
-
* Returns early if we're on the Install page.
|
1107 |
-
*
|
1108 |
-
* @since 1.0.0
|
1109 |
-
*
|
1110 |
-
* @global object $current_screen
|
1111 |
-
*
|
1112 |
-
* @return null Returns early if we're on the Install page.
|
1113 |
-
*/
|
1114 |
-
public function notices() {
|
1115 |
-
// Remove nag on the install page / Return early if the nag message has been dismissed or user < author.
|
1116 |
-
if ( ( $this->is_tgmpa_page() || $this->is_core_update_page() ) || get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) || ! current_user_can( apply_filters( 'tgmpa_show_admin_notice_capability', 'publish_posts' ) ) ) {
|
1117 |
-
return;
|
1118 |
-
}
|
1119 |
-
|
1120 |
-
// Store for the plugin slugs by message type.
|
1121 |
-
$message = array();
|
1122 |
-
|
1123 |
-
// Initialize counters used to determine plurality of action link texts.
|
1124 |
-
$install_link_count = 0;
|
1125 |
-
$update_link_count = 0;
|
1126 |
-
$activate_link_count = 0;
|
1127 |
-
$total_required_action_count = 0;
|
1128 |
-
|
1129 |
-
foreach ( $this->plugins as $slug => $plugin ) {
|
1130 |
-
if ( $this->is_plugin_active( $slug ) && false === $this->does_plugin_have_update( $slug ) ) {
|
1131 |
-
continue;
|
1132 |
-
}
|
1133 |
-
|
1134 |
-
if ( ! $this->is_plugin_installed( $slug ) ) {
|
1135 |
-
if ( current_user_can( 'install_plugins' ) ) {
|
1136 |
-
$install_link_count++;
|
1137 |
-
|
1138 |
-
if ( true === $plugin['required'] ) {
|
1139 |
-
$message['notice_can_install_required'][] = $slug;
|
1140 |
-
} else {
|
1141 |
-
$message['notice_can_install_recommended'][] = $slug;
|
1142 |
-
}
|
1143 |
-
}
|
1144 |
-
if ( true === $plugin['required'] ) {
|
1145 |
-
$total_required_action_count++;
|
1146 |
-
}
|
1147 |
-
} else {
|
1148 |
-
if ( ! $this->is_plugin_active( $slug ) && $this->can_plugin_activate( $slug ) ) {
|
1149 |
-
if ( current_user_can( 'activate_plugins' ) ) {
|
1150 |
-
$activate_link_count++;
|
1151 |
-
|
1152 |
-
if ( true === $plugin['required'] ) {
|
1153 |
-
$message['notice_can_activate_required'][] = $slug;
|
1154 |
-
} else {
|
1155 |
-
$message['notice_can_activate_recommended'][] = $slug;
|
1156 |
-
}
|
1157 |
-
}
|
1158 |
-
if ( true === $plugin['required'] ) {
|
1159 |
-
$total_required_action_count++;
|
1160 |
-
}
|
1161 |
-
}
|
1162 |
-
|
1163 |
-
if ( $this->does_plugin_require_update( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
|
1164 |
-
|
1165 |
-
if ( current_user_can( 'update_plugins' ) ) {
|
1166 |
-
$update_link_count++;
|
1167 |
-
|
1168 |
-
if ( $this->does_plugin_require_update( $slug ) ) {
|
1169 |
-
$message['notice_ask_to_update'][] = $slug;
|
1170 |
-
} elseif ( false !== $this->does_plugin_have_update( $slug ) ) {
|
1171 |
-
$message['notice_ask_to_update_maybe'][] = $slug;
|
1172 |
-
}
|
1173 |
-
}
|
1174 |
-
if ( true === $plugin['required'] ) {
|
1175 |
-
$total_required_action_count++;
|
1176 |
-
}
|
1177 |
-
}
|
1178 |
-
}
|
1179 |
-
}
|
1180 |
-
unset( $slug, $plugin );
|
1181 |
-
|
1182 |
-
// If we have notices to display, we move forward.
|
1183 |
-
if ( ! empty( $message ) || $total_required_action_count > 0 ) {
|
1184 |
-
krsort( $message ); // Sort messages.
|
1185 |
-
$rendered = '';
|
1186 |
-
|
1187 |
-
// As add_settings_error() wraps the final message in a <p> and as the final message can't be
|
1188 |
-
// filtered, using <p>'s in our html would render invalid html output.
|
1189 |
-
$line_template = '<span style="display: block; margin: 0.5em 0.5em 0 0; clear: both;">%s</span>' . "\n";
|
1190 |
-
|
1191 |
-
if ( ! current_user_can( 'activate_plugins' ) && ! current_user_can( 'install_plugins' ) && ! current_user_can( 'update_plugins' ) ) {
|
1192 |
-
$rendered = esc_html( $this->strings['notice_cannot_install_activate'] ) . ' ' . esc_html( $this->strings['contact_admin'] );
|
1193 |
-
$rendered .= $this->create_user_action_links_for_notice( 0, 0, 0, $line_template );
|
1194 |
-
} else {
|
1195 |
-
|
1196 |
-
// If dismissable is false and a message is set, output it now.
|
1197 |
-
if ( ! $this->dismissable && ! empty( $this->dismiss_msg ) ) {
|
1198 |
-
$rendered .= sprintf( $line_template, wp_kses_post( $this->dismiss_msg ) );
|
1199 |
-
}
|
1200 |
-
|
1201 |
-
// Render the individual message lines for the notice.
|
1202 |
-
foreach ( $message as $type => $plugin_group ) {
|
1203 |
-
$linked_plugins = array();
|
1204 |
-
|
1205 |
-
// Get the external info link for a plugin if one is available.
|
1206 |
-
foreach ( $plugin_group as $plugin_slug ) {
|
1207 |
-
$linked_plugins[] = $this->get_info_link( $plugin_slug );
|
1208 |
-
}
|
1209 |
-
unset( $plugin_slug );
|
1210 |
-
|
1211 |
-
$count = count( $plugin_group );
|
1212 |
-
$linked_plugins = array_map( array( 'TGMPA_Utils', 'wrap_in_em' ), $linked_plugins );
|
1213 |
-
$last_plugin = array_pop( $linked_plugins ); // Pop off last name to prep for readability.
|
1214 |
-
$imploded = empty( $linked_plugins ) ? $last_plugin : ( implode( ', ', $linked_plugins ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
|
1215 |
-
|
1216 |
-
$rendered .= sprintf(
|
1217 |
-
$line_template,
|
1218 |
-
sprintf(
|
1219 |
-
translate_nooped_plural( $this->strings[ $type ], $count, 'tgmpa' ),
|
1220 |
-
$imploded,
|
1221 |
-
$count
|
1222 |
-
)
|
1223 |
-
);
|
1224 |
-
|
1225 |
-
}
|
1226 |
-
unset( $type, $plugin_group, $linked_plugins, $count, $last_plugin, $imploded );
|
1227 |
-
|
1228 |
-
$rendered .= $this->create_user_action_links_for_notice( $install_link_count, $update_link_count, $activate_link_count, $line_template );
|
1229 |
-
}
|
1230 |
-
|
1231 |
-
// Register the nag messages and prepare them to be processed.
|
1232 |
-
add_settings_error( 'tgmpa', 'tgmpa', $rendered, $this->get_admin_notice_class() );
|
1233 |
-
}
|
1234 |
-
|
1235 |
-
// Admin options pages already output settings_errors, so this is to avoid duplication.
|
1236 |
-
if ( 'options-general' !== $GLOBALS['current_screen']->parent_base ) {
|
1237 |
-
$this->display_settings_errors();
|
1238 |
-
}
|
1239 |
-
}
|
1240 |
-
|
1241 |
-
/**
|
1242 |
-
* Generate the user action links for the admin notice.
|
1243 |
-
*
|
1244 |
-
* @since 2.6.0
|
1245 |
-
*
|
1246 |
-
* @param int $install_count Number of plugins to install.
|
1247 |
-
* @param int $update_count Number of plugins to update.
|
1248 |
-
* @param int $activate_count Number of plugins to activate.
|
1249 |
-
* @param int $line_template Template for the HTML tag to output a line.
|
1250 |
-
* @return string Action links.
|
1251 |
-
*/
|
1252 |
-
protected function create_user_action_links_for_notice( $install_count, $update_count, $activate_count, $line_template ) {
|
1253 |
-
// Setup action links.
|
1254 |
-
$action_links = array(
|
1255 |
-
'install' => '',
|
1256 |
-
'update' => '',
|
1257 |
-
'activate' => '',
|
1258 |
-
'dismiss' => $this->dismissable ? '<a href="' . esc_url( wp_nonce_url( add_query_arg( 'tgmpa-dismiss', 'dismiss_admin_notices' ), 'tgmpa-dismiss-' . get_current_user_id() ) ) . '" class="dismiss-notice" target="_parent">' . esc_html( $this->strings['dismiss'] ) . '</a>' : '',
|
1259 |
-
);
|
1260 |
-
|
1261 |
-
$link_template = '<a href="%2$s">%1$s</a>';
|
1262 |
-
|
1263 |
-
if ( current_user_can( 'install_plugins' ) ) {
|
1264 |
-
if ( $install_count > 0 ) {
|
1265 |
-
$action_links['install'] = sprintf(
|
1266 |
-
$link_template,
|
1267 |
-
translate_nooped_plural( $this->strings['install_link'], $install_count, 'tgmpa' ),
|
1268 |
-
esc_url( $this->get_tgmpa_status_url( 'install' ) )
|
1269 |
-
);
|
1270 |
-
}
|
1271 |
-
if ( $update_count > 0 ) {
|
1272 |
-
$action_links['update'] = sprintf(
|
1273 |
-
$link_template,
|
1274 |
-
translate_nooped_plural( $this->strings['update_link'], $update_count, 'tgmpa' ),
|
1275 |
-
esc_url( $this->get_tgmpa_status_url( 'update' ) )
|
1276 |
-
);
|
1277 |
-
}
|
1278 |
-
}
|
1279 |
-
|
1280 |
-
if ( current_user_can( 'activate_plugins' ) && $activate_count > 0 ) {
|
1281 |
-
$action_links['activate'] = sprintf(
|
1282 |
-
$link_template,
|
1283 |
-
translate_nooped_plural( $this->strings['activate_link'], $activate_count, 'tgmpa' ),
|
1284 |
-
esc_url( $this->get_tgmpa_status_url( 'activate' ) )
|
1285 |
-
);
|
1286 |
-
}
|
1287 |
-
|
1288 |
-
$action_links = apply_filters( 'tgmpa_notice_action_links', $action_links );
|
1289 |
-
|
1290 |
-
$action_links = array_filter( (array) $action_links ); // Remove any empty array items.
|
1291 |
-
|
1292 |
-
if ( ! empty( $action_links ) ) {
|
1293 |
-
$action_links = sprintf( $line_template, implode( ' | ', $action_links ) );
|
1294 |
-
return apply_filters( 'tgmpa_notice_rendered_action_links', $action_links );
|
1295 |
-
} else {
|
1296 |
-
return '';
|
1297 |
-
}
|
1298 |
-
}
|
1299 |
-
|
1300 |
-
/**
|
1301 |
-
* Get admin notice class.
|
1302 |
-
*
|
1303 |
-
* Work around all the changes to the various admin notice classes between WP 4.4 and 3.7
|
1304 |
-
* (lowest supported version by TGMPA).
|
1305 |
-
*
|
1306 |
-
* @since 2.6.0
|
1307 |
-
*
|
1308 |
-
* @return string
|
1309 |
-
*/
|
1310 |
-
protected function get_admin_notice_class() {
|
1311 |
-
if ( ! empty( $this->strings['nag_type'] ) ) {
|
1312 |
-
return sanitize_html_class( strtolower( $this->strings['nag_type'] ) );
|
1313 |
-
} else {
|
1314 |
-
if ( version_compare( $this->wp_version, '4.2', '>=' ) ) {
|
1315 |
-
return 'notice-warning';
|
1316 |
-
} elseif ( version_compare( $this->wp_version, '4.1', '>=' ) ) {
|
1317 |
-
return 'notice';
|
1318 |
-
} else {
|
1319 |
-
return 'updated';
|
1320 |
-
}
|
1321 |
-
}
|
1322 |
-
}
|
1323 |
-
|
1324 |
-
/**
|
1325 |
-
* Display settings errors and remove those which have been displayed to avoid duplicate messages showing
|
1326 |
-
*
|
1327 |
-
* @since 2.5.0
|
1328 |
-
*/
|
1329 |
-
protected function display_settings_errors() {
|
1330 |
-
global $wp_settings_errors;
|
1331 |
-
|
1332 |
-
settings_errors( 'tgmpa' );
|
1333 |
-
|
1334 |
-
foreach ( (array) $wp_settings_errors as $key => $details ) {
|
1335 |
-
if ( 'tgmpa' === $details['setting'] ) {
|
1336 |
-
unset( $wp_settings_errors[ $key ] );
|
1337 |
-
break;
|
1338 |
-
}
|
1339 |
-
}
|
1340 |
-
}
|
1341 |
-
|
1342 |
-
/**
|
1343 |
-
* Register dismissal of admin notices.
|
1344 |
-
*
|
1345 |
-
* Acts on the dismiss link in the admin nag messages.
|
1346 |
-
* If clicked, the admin notice disappears and will no longer be visible to this user.
|
1347 |
-
*
|
1348 |
-
* @since 2.1.0
|
1349 |
-
*/
|
1350 |
-
public function dismiss() {
|
1351 |
-
if ( isset( $_GET['tgmpa-dismiss'] ) && check_admin_referer( 'tgmpa-dismiss-' . get_current_user_id() ) ) {
|
1352 |
-
update_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, 1 );
|
1353 |
-
}
|
1354 |
-
}
|
1355 |
-
|
1356 |
-
/**
|
1357 |
-
* Add individual plugin to our collection of plugins.
|
1358 |
-
*
|
1359 |
-
* If the required keys are not set or the plugin has already
|
1360 |
-
* been registered, the plugin is not added.
|
1361 |
-
*
|
1362 |
-
* @since 2.0.0
|
1363 |
-
*
|
1364 |
-
* @param array|null $plugin Array of plugin arguments or null if invalid argument.
|
1365 |
-
* @return null Return early if incorrect argument.
|
1366 |
-
*/
|
1367 |
-
public function register( $plugin ) {
|
1368 |
-
if ( empty( $plugin['slug'] ) || empty( $plugin['name'] ) ) {
|
1369 |
-
return;
|
1370 |
-
}
|
1371 |
-
|
1372 |
-
if ( empty( $plugin['slug'] ) || ! is_string( $plugin['slug'] ) || isset( $this->plugins[ $plugin['slug'] ] ) ) {
|
1373 |
-
return;
|
1374 |
-
}
|
1375 |
-
|
1376 |
-
$defaults = array(
|
1377 |
-
'name' => '', // String
|
1378 |
-
'slug' => '', // String
|
1379 |
-
'source' => 'repo', // String
|
1380 |
-
'required' => false, // Boolean
|
1381 |
-
'version' => '', // String
|
1382 |
-
'force_activation' => false, // Boolean
|
1383 |
-
'force_deactivation' => false, // Boolean
|
1384 |
-
'external_url' => '', // String
|
1385 |
-
'is_callable' => '', // String|Array.
|
1386 |
-
);
|
1387 |
-
|
1388 |
-
// Prepare the received data.
|
1389 |
-
$plugin = wp_parse_args( $plugin, $defaults );
|
1390 |
-
|
1391 |
-
// Standardize the received slug.
|
1392 |
-
$plugin['slug'] = $this->sanitize_key( $plugin['slug'] );
|
1393 |
-
|
1394 |
-
// Forgive users for using string versions of booleans or floats for version number.
|
1395 |
-
$plugin['version'] = (string) $plugin['version'];
|
1396 |
-
$plugin['source'] = empty( $plugin['source'] ) ? 'repo' : $plugin['source'];
|
1397 |
-
$plugin['required'] = TGMPA_Utils::validate_bool( $plugin['required'] );
|
1398 |
-
$plugin['force_activation'] = TGMPA_Utils::validate_bool( $plugin['force_activation'] );
|
1399 |
-
$plugin['force_deactivation'] = TGMPA_Utils::validate_bool( $plugin['force_deactivation'] );
|
1400 |
-
|
1401 |
-
// Enrich the received data.
|
1402 |
-
$plugin['file_path'] = $this->_get_plugin_basename_from_slug( $plugin['slug'] );
|
1403 |
-
$plugin['source_type'] = $this->get_plugin_source_type( $plugin['source'] );
|
1404 |
-
|
1405 |
-
// Set the class properties.
|
1406 |
-
$this->plugins[ $plugin['slug'] ] = $plugin;
|
1407 |
-
$this->sort_order[ $plugin['slug'] ] = $plugin['name'];
|
1408 |
-
|
1409 |
-
// Should we add the force activation hook ?
|
1410 |
-
if ( true === $plugin['force_activation'] ) {
|
1411 |
-
$this->has_forced_activation = true;
|
1412 |
-
}
|
1413 |
-
|
1414 |
-
// Should we add the force deactivation hook ?
|
1415 |
-
if ( true === $plugin['force_deactivation'] ) {
|
1416 |
-
$this->has_forced_deactivation = true;
|
1417 |
-
}
|
1418 |
-
}
|
1419 |
-
|
1420 |
-
/**
|
1421 |
-
* Determine what type of source the plugin comes from.
|
1422 |
-
*
|
1423 |
-
* @since 2.5.0
|
1424 |
-
*
|
1425 |
-
* @param string $source The source of the plugin as provided, either empty (= WP repo), a file path
|
1426 |
-
* (= bundled) or an external URL.
|
1427 |
-
* @return string 'repo', 'external', or 'bundled'
|
1428 |
-
*/
|
1429 |
-
protected function get_plugin_source_type( $source ) {
|
1430 |
-
if ( 'repo' === $source || preg_match( self::WP_REPO_REGEX, $source ) ) {
|
1431 |
-
return 'repo';
|
1432 |
-
} elseif ( preg_match( self::IS_URL_REGEX, $source ) ) {
|
1433 |
-
return 'external';
|
1434 |
-
} else {
|
1435 |
-
return 'bundled';
|
1436 |
-
}
|
1437 |
-
}
|
1438 |
-
|
1439 |
-
/**
|
1440 |
-
* Sanitizes a string key.
|
1441 |
-
*
|
1442 |
-
* Near duplicate of WP Core `sanitize_key()`. The difference is that uppercase characters *are*
|
1443 |
-
* allowed, so as not to break upgrade paths from non-standard bundled plugins using uppercase
|
1444 |
-
* characters in the plugin directory path/slug. Silly them.
|
1445 |
-
*
|
1446 |
-
* @see https://developer.wordpress.org/reference/hooks/sanitize_key/
|
1447 |
-
*
|
1448 |
-
* @since 2.5.0
|
1449 |
-
*
|
1450 |
-
* @param string $key String key.
|
1451 |
-
* @return string Sanitized key
|
1452 |
-
*/
|
1453 |
-
public function sanitize_key( $key ) {
|
1454 |
-
$raw_key = $key;
|
1455 |
-
$key = preg_replace( '`[^A-Za-z0-9_-]`', '', $key );
|
1456 |
-
|
1457 |
-
/**
|
1458 |
-
* Filter a sanitized key string.
|
1459 |
-
*
|
1460 |
-
* @since 2.5.0
|
1461 |
-
*
|
1462 |
-
* @param string $key Sanitized key.
|
1463 |
-
* @param string $raw_key The key prior to sanitization.
|
1464 |
-
*/
|
1465 |
-
return apply_filters( 'tgmpa_sanitize_key', $key, $raw_key );
|
1466 |
-
}
|
1467 |
-
|
1468 |
-
/**
|
1469 |
-
* Amend default configuration settings.
|
1470 |
-
*
|
1471 |
-
* @since 2.0.0
|
1472 |
-
*
|
1473 |
-
* @param array $config Array of config options to pass as class properties.
|
1474 |
-
*/
|
1475 |
-
public function config( $config ) {
|
1476 |
-
$keys = array(
|
1477 |
-
'id',
|
1478 |
-
'default_path',
|
1479 |
-
'has_notices',
|
1480 |
-
'dismissable',
|
1481 |
-
'dismiss_msg',
|
1482 |
-
'menu',
|
1483 |
-
'parent_slug',
|
1484 |
-
'capability',
|
1485 |
-
'is_automatic',
|
1486 |
-
'message',
|
1487 |
-
'strings',
|
1488 |
-
);
|
1489 |
-
|
1490 |
-
foreach ( $keys as $key ) {
|
1491 |
-
if ( isset( $config[ $key ] ) ) {
|
1492 |
-
if ( is_array( $config[ $key ] ) ) {
|
1493 |
-
$this->$key = array_merge( $this->$key, $config[ $key ] );
|
1494 |
-
} else {
|
1495 |
-
$this->$key = $config[ $key ];
|
1496 |
-
}
|
1497 |
-
}
|
1498 |
-
}
|
1499 |
-
}
|
1500 |
-
|
1501 |
-
/**
|
1502 |
-
* Amend action link after plugin installation.
|
1503 |
-
*
|
1504 |
-
* @since 2.0.0
|
1505 |
-
*
|
1506 |
-
* @param array $install_actions Existing array of actions.
|
1507 |
-
* @return false|array Amended array of actions.
|
1508 |
-
*/
|
1509 |
-
public function actions( $install_actions ) {
|
1510 |
-
// Remove action links on the TGMPA install page.
|
1511 |
-
if ( $this->is_tgmpa_page() ) {
|
1512 |
-
return false;
|
1513 |
-
}
|
1514 |
-
|
1515 |
-
return $install_actions;
|
1516 |
-
}
|
1517 |
-
|
1518 |
-
/**
|
1519 |
-
* Flushes the plugins cache on theme switch to prevent stale entries
|
1520 |
-
* from remaining in the plugin table.
|
1521 |
-
*
|
1522 |
-
* @since 2.4.0
|
1523 |
-
*
|
1524 |
-
* @param bool $clear_update_cache Optional. Whether to clear the Plugin updates cache.
|
1525 |
-
* Parameter added in v2.5.0.
|
1526 |
-
*/
|
1527 |
-
public function flush_plugins_cache( $clear_update_cache = true ) {
|
1528 |
-
wp_clean_plugins_cache( $clear_update_cache );
|
1529 |
-
}
|
1530 |
-
|
1531 |
-
/**
|
1532 |
-
* Set file_path key for each installed plugin.
|
1533 |
-
*
|
1534 |
-
* @since 2.1.0
|
1535 |
-
*
|
1536 |
-
* @param string $plugin_slug Optional. If set, only (re-)populates the file path for that specific plugin.
|
1537 |
-
* Parameter added in v2.5.0.
|
1538 |
-
*/
|
1539 |
-
public function populate_file_path( $plugin_slug = '' ) {
|
1540 |
-
if ( ! empty( $plugin_slug ) && is_string( $plugin_slug ) && isset( $this->plugins[ $plugin_slug ] ) ) {
|
1541 |
-
$this->plugins[ $plugin_slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $plugin_slug );
|
1542 |
-
} else {
|
1543 |
-
// Add file_path key for all plugins.
|
1544 |
-
foreach ( $this->plugins as $slug => $values ) {
|
1545 |
-
$this->plugins[ $slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $slug );
|
1546 |
-
}
|
1547 |
-
}
|
1548 |
-
}
|
1549 |
-
|
1550 |
-
/**
|
1551 |
-
* Helper function to extract the file path of the plugin file from the
|
1552 |
-
* plugin slug, if the plugin is installed.
|
1553 |
-
*
|
1554 |
-
* @since 2.0.0
|
1555 |
-
*
|
1556 |
-
* @param string $slug Plugin slug (typically folder name) as provided by the developer.
|
1557 |
-
* @return string Either file path for plugin if installed, or just the plugin slug.
|
1558 |
-
*/
|
1559 |
-
protected function _get_plugin_basename_from_slug( $slug ) {
|
1560 |
-
$keys = array_keys( $this->get_plugins() );
|
1561 |
-
|
1562 |
-
foreach ( $keys as $key ) {
|
1563 |
-
if ( preg_match( '|^' . $slug . '/|', $key ) ) {
|
1564 |
-
return $key;
|
1565 |
-
}
|
1566 |
-
}
|
1567 |
-
|
1568 |
-
return $slug;
|
1569 |
-
}
|
1570 |
-
|
1571 |
-
/**
|
1572 |
-
* Retrieve plugin data, given the plugin name.
|
1573 |
-
*
|
1574 |
-
* Loops through the registered plugins looking for $name. If it finds it,
|
1575 |
-
* it returns the $data from that plugin. Otherwise, returns false.
|
1576 |
-
*
|
1577 |
-
* @since 2.1.0
|
1578 |
-
*
|
1579 |
-
* @param string $name Name of the plugin, as it was registered.
|
1580 |
-
* @param string $data Optional. Array key of plugin data to return. Default is slug.
|
1581 |
-
* @return string|boolean Plugin slug if found, false otherwise.
|
1582 |
-
*/
|
1583 |
-
public function _get_plugin_data_from_name( $name, $data = 'slug' ) {
|
1584 |
-
foreach ( $this->plugins as $values ) {
|
1585 |
-
if ( $name === $values['name'] && isset( $values[ $data ] ) ) {
|
1586 |
-
return $values[ $data ];
|
1587 |
-
}
|
1588 |
-
}
|
1589 |
-
|
1590 |
-
return false;
|
1591 |
-
}
|
1592 |
-
|
1593 |
-
/**
|
1594 |
-
* Retrieve the download URL for a package.
|
1595 |
-
*
|
1596 |
-
* @since 2.5.0
|
1597 |
-
*
|
1598 |
-
* @param string $slug Plugin slug.
|
1599 |
-
* @return string Plugin download URL or path to local file or empty string if undetermined.
|
1600 |
-
*/
|
1601 |
-
public function get_download_url( $slug ) {
|
1602 |
-
$dl_source = '';
|
1603 |
-
|
1604 |
-
switch ( $this->plugins[ $slug ]['source_type'] ) {
|
1605 |
-
case 'repo':
|
1606 |
-
return $this->get_wp_repo_download_url( $slug );
|
1607 |
-
case 'external':
|
1608 |
-
return $this->plugins[ $slug ]['source'];
|
1609 |
-
case 'bundled':
|
1610 |
-
return $this->default_path . $this->plugins[ $slug ]['source'];
|
1611 |
-
}
|
1612 |
-
|
1613 |
-
return $dl_source; // Should never happen.
|
1614 |
-
}
|
1615 |
-
|
1616 |
-
/**
|
1617 |
-
* Retrieve the download URL for a WP repo package.
|
1618 |
-
*
|
1619 |
-
* @since 2.5.0
|
1620 |
-
*
|
1621 |
-
* @param string $slug Plugin slug.
|
1622 |
-
* @return string Plugin download URL.
|
1623 |
-
*/
|
1624 |
-
protected function get_wp_repo_download_url( $slug ) {
|
1625 |
-
$source = '';
|
1626 |
-
$api = $this->get_plugins_api( $slug );
|
1627 |
-
|
1628 |
-
if ( false !== $api && isset( $api->download_link ) ) {
|
1629 |
-
$source = $api->download_link;
|
1630 |
-
}
|
1631 |
-
|
1632 |
-
return $source;
|
1633 |
-
}
|
1634 |
-
|
1635 |
-
/**
|
1636 |
-
* Try to grab information from WordPress API.
|
1637 |
-
*
|
1638 |
-
* @since 2.5.0
|
1639 |
-
*
|
1640 |
-
* @param string $slug Plugin slug.
|
1641 |
-
* @return object Plugins_api response object on success, WP_Error on failure.
|
1642 |
-
*/
|
1643 |
-
protected function get_plugins_api( $slug ) {
|
1644 |
-
static $api = array(); // Cache received responses.
|
1645 |
-
|
1646 |
-
if ( ! isset( $api[ $slug ] ) ) {
|
1647 |
-
if ( ! function_exists( 'plugins_api' ) ) {
|
1648 |
-
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
|
1649 |
-
}
|
1650 |
-
|
1651 |
-
$response = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
|
1652 |
-
|
1653 |
-
$api[ $slug ] = false;
|
1654 |
-
|
1655 |
-
if ( is_wp_error( $response ) ) {
|
1656 |
-
wp_die( esc_html( $this->strings['oops'] ) );
|
1657 |
-
} else {
|
1658 |
-
$api[ $slug ] = $response;
|
1659 |
-
}
|
1660 |
-
}
|
1661 |
-
|
1662 |
-
return $api[ $slug ];
|
1663 |
-
}
|
1664 |
-
|
1665 |
-
/**
|
1666 |
-
* Retrieve a link to a plugin information page.
|
1667 |
-
*
|
1668 |
-
* @since 2.5.0
|
1669 |
-
*
|
1670 |
-
* @param string $slug Plugin slug.
|
1671 |
-
* @return string Fully formed html link to a plugin information page if available
|
1672 |
-
* or the plugin name if not.
|
1673 |
-
*/
|
1674 |
-
public function get_info_link( $slug ) {
|
1675 |
-
if ( ! empty( $this->plugins[ $slug ]['external_url'] ) && preg_match( self::IS_URL_REGEX, $this->plugins[ $slug ]['external_url'] ) ) {
|
1676 |
-
$link = sprintf(
|
1677 |
-
'<a href="%1$s" target="_blank">%2$s</a>',
|
1678 |
-
esc_url( $this->plugins[ $slug ]['external_url'] ),
|
1679 |
-
esc_html( $this->plugins[ $slug ]['name'] )
|
1680 |
-
);
|
1681 |
-
} elseif ( 'repo' === $this->plugins[ $slug ]['source_type'] ) {
|
1682 |
-
$url = add_query_arg(
|
1683 |
-
array(
|
1684 |
-
'tab' => 'plugin-information',
|
1685 |
-
'plugin' => urlencode( $slug ),
|
1686 |
-
'TB_iframe' => 'true',
|
1687 |
-
'width' => '640',
|
1688 |
-
'height' => '500',
|
1689 |
-
),
|
1690 |
-
self_admin_url( 'plugin-install.php' )
|
1691 |
-
);
|
1692 |
-
|
1693 |
-
$link = sprintf(
|
1694 |
-
'<a href="%1$s" class="thickbox">%2$s</a>',
|
1695 |
-
esc_url( $url ),
|
1696 |
-
esc_html( $this->plugins[ $slug ]['name'] )
|
1697 |
-
);
|
1698 |
-
} else {
|
1699 |
-
$link = esc_html( $this->plugins[ $slug ]['name'] ); // No hyperlink.
|
1700 |
-
}
|
1701 |
-
|
1702 |
-
return $link;
|
1703 |
-
}
|
1704 |
-
|
1705 |
-
/**
|
1706 |
-
* Determine if we're on the TGMPA Install page.
|
1707 |
-
*
|
1708 |
-
* @since 2.1.0
|
1709 |
-
*
|
1710 |
-
* @return boolean True when on the TGMPA page, false otherwise.
|
1711 |
-
*/
|
1712 |
-
protected function is_tgmpa_page() {
|
1713 |
-
return isset( $_GET['page'] ) && $this->menu === $_GET['page'];
|
1714 |
-
}
|
1715 |
-
|
1716 |
-
/**
|
1717 |
-
* Determine if we're on a WP Core installation/upgrade page.
|
1718 |
-
*
|
1719 |
-
* @since 2.6.0
|
1720 |
-
*
|
1721 |
-
* @return boolean True when on a WP Core installation/upgrade page, false otherwise.
|
1722 |
-
*/
|
1723 |
-
protected function is_core_update_page() {
|
1724 |
-
// Current screen is not always available, most notably on the customizer screen.
|
1725 |
-
if ( ! function_exists( 'get_current_screen' ) ) {
|
1726 |
-
return false;
|
1727 |
-
}
|
1728 |
-
|
1729 |
-
$screen = get_current_screen();
|
1730 |
-
|
1731 |
-
if ( 'update-core' === $screen->base ) {
|
1732 |
-
// Core update screen.
|
1733 |
-
return true;
|
1734 |
-
} elseif ( 'plugins' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok.
|
1735 |
-
// Plugins bulk update screen.
|
1736 |
-
return true;
|
1737 |
-
} elseif ( 'update' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok.
|
1738 |
-
// Individual updates (ajax call).
|
1739 |
-
return true;
|
1740 |
-
}
|
1741 |
-
|
1742 |
-
return false;
|
1743 |
-
}
|
1744 |
-
|
1745 |
-
/**
|
1746 |
-
* Retrieve the URL to the TGMPA Install page.
|
1747 |
-
*
|
1748 |
-
* I.e. depending on the config settings passed something along the lines of:
|
1749 |
-
* http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins
|
1750 |
-
*
|
1751 |
-
* @since 2.5.0
|
1752 |
-
*
|
1753 |
-
* @return string Properly encoded URL (not escaped).
|
1754 |
-
*/
|
1755 |
-
public function get_tgmpa_url() {
|
1756 |
-
static $url;
|
1757 |
-
|
1758 |
-
if ( ! isset( $url ) ) {
|
1759 |
-
$parent = $this->parent_slug;
|
1760 |
-
if ( false === strpos( $parent, '.php' ) ) {
|
1761 |
-
$parent = 'admin.php';
|
1762 |
-
}
|
1763 |
-
$url = add_query_arg(
|
1764 |
-
array(
|
1765 |
-
'page' => urlencode( $this->menu ),
|
1766 |
-
),
|
1767 |
-
self_admin_url( $parent )
|
1768 |
-
);
|
1769 |
-
}
|
1770 |
-
|
1771 |
-
return $url;
|
1772 |
-
}
|
1773 |
-
|
1774 |
-
/**
|
1775 |
-
* Retrieve the URL to the TGMPA Install page for a specific plugin status (view).
|
1776 |
-
*
|
1777 |
-
* I.e. depending on the config settings passed something along the lines of:
|
1778 |
-
* http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins&plugin_status=install
|
1779 |
-
*
|
1780 |
-
* @since 2.5.0
|
1781 |
-
*
|
1782 |
-
* @param string $status Plugin status - either 'install', 'update' or 'activate'.
|
1783 |
-
* @return string Properly encoded URL (not escaped).
|
1784 |
-
*/
|
1785 |
-
public function get_tgmpa_status_url( $status ) {
|
1786 |
-
return add_query_arg(
|
1787 |
-
array(
|
1788 |
-
'plugin_status' => urlencode( $status ),
|
1789 |
-
),
|
1790 |
-
$this->get_tgmpa_url()
|
1791 |
-
);
|
1792 |
-
}
|
1793 |
-
|
1794 |
-
/**
|
1795 |
-
* Determine whether there are open actions for plugins registered with TGMPA.
|
1796 |
-
*
|
1797 |
-
* @since 2.5.0
|
1798 |
-
*
|
1799 |
-
* @return bool True if complete, i.e. no outstanding actions. False otherwise.
|
1800 |
-
*/
|
1801 |
-
public function is_tgmpa_complete() {
|
1802 |
-
$complete = true;
|
1803 |
-
foreach ( $this->plugins as $slug => $plugin ) {
|
1804 |
-
if ( ! $this->is_plugin_active( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
|
1805 |
-
$complete = false;
|
1806 |
-
break;
|
1807 |
-
}
|
1808 |
-
}
|
1809 |
-
|
1810 |
-
return $complete;
|
1811 |
-
}
|
1812 |
-
|
1813 |
-
/**
|
1814 |
-
* Check if a plugin is installed. Does not take must-use plugins into account.
|
1815 |
-
*
|
1816 |
-
* @since 2.5.0
|
1817 |
-
*
|
1818 |
-
* @param string $slug Plugin slug.
|
1819 |
-
* @return bool True if installed, false otherwise.
|
1820 |
-
*/
|
1821 |
-
public function is_plugin_installed( $slug ) {
|
1822 |
-
$installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
|
1823 |
-
|
1824 |
-
return ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ] ) );
|
1825 |
-
}
|
1826 |
-
|
1827 |
-
/**
|
1828 |
-
* Check if a plugin is active.
|
1829 |
-
*
|
1830 |
-
* @since 2.5.0
|
1831 |
-
*
|
1832 |
-
* @param string $slug Plugin slug.
|
1833 |
-
* @return bool True if active, false otherwise.
|
1834 |
-
*/
|
1835 |
-
public function is_plugin_active( $slug ) {
|
1836 |
-
return ( ( ! empty( $this->plugins[ $slug ]['is_callable'] ) && is_callable( $this->plugins[ $slug ]['is_callable'] ) ) || is_plugin_active( $this->plugins[ $slug ]['file_path'] ) );
|
1837 |
-
}
|
1838 |
-
|
1839 |
-
/**
|
1840 |
-
* Check if a plugin can be updated, i.e. if we have information on the minimum WP version required
|
1841 |
-
* available, check whether the current install meets them.
|
1842 |
-
*
|
1843 |
-
* @since 2.5.0
|
1844 |
-
*
|
1845 |
-
* @param string $slug Plugin slug.
|
1846 |
-
* @return bool True if OK to update, false otherwise.
|
1847 |
-
*/
|
1848 |
-
public function can_plugin_update( $slug ) {
|
1849 |
-
// We currently can't get reliable info on non-WP-repo plugins - issue #380.
|
1850 |
-
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
|
1851 |
-
return true;
|
1852 |
-
}
|
1853 |
-
|
1854 |
-
$api = $this->get_plugins_api( $slug );
|
1855 |
-
|
1856 |
-
if ( false !== $api && isset( $api->requires ) ) {
|
1857 |
-
return version_compare( $this->wp_version, $api->requires, '>=' );
|
1858 |
-
}
|
1859 |
-
|
1860 |
-
// No usable info received from the plugins API, presume we can update.
|
1861 |
-
return true;
|
1862 |
-
}
|
1863 |
-
|
1864 |
-
/**
|
1865 |
-
* Check to see if the plugin is 'updatetable', i.e. installed, with an update available
|
1866 |
-
* and no WP version requirements blocking it.
|
1867 |
-
*
|
1868 |
-
* @since 2.6.0
|
1869 |
-
*
|
1870 |
-
* @param string $slug Plugin slug.
|
1871 |
-
* @return bool True if OK to proceed with update, false otherwise.
|
1872 |
-
*/
|
1873 |
-
public function is_plugin_updatetable( $slug ) {
|
1874 |
-
if ( ! $this->is_plugin_installed( $slug ) ) {
|
1875 |
-
return false;
|
1876 |
-
} else {
|
1877 |
-
return ( false !== $this->does_plugin_have_update( $slug ) && $this->can_plugin_update( $slug ) );
|
1878 |
-
}
|
1879 |
-
}
|
1880 |
-
|
1881 |
-
/**
|
1882 |
-
* Check if a plugin can be activated, i.e. is not currently active and meets the minimum
|
1883 |
-
* plugin version requirements set in TGMPA (if any).
|
1884 |
-
*
|
1885 |
-
* @since 2.5.0
|
1886 |
-
*
|
1887 |
-
* @param string $slug Plugin slug.
|
1888 |
-
* @return bool True if OK to activate, false otherwise.
|
1889 |
-
*/
|
1890 |
-
public function can_plugin_activate( $slug ) {
|
1891 |
-
return ( ! $this->is_plugin_active( $slug ) && ! $this->does_plugin_require_update( $slug ) );
|
1892 |
-
}
|
1893 |
-
|
1894 |
-
/**
|
1895 |
-
* Retrieve the version number of an installed plugin.
|
1896 |
-
*
|
1897 |
-
* @since 2.5.0
|
1898 |
-
*
|
1899 |
-
* @param string $slug Plugin slug.
|
1900 |
-
* @return string Version number as string or an empty string if the plugin is not installed
|
1901 |
-
* or version unknown (plugins which don't comply with the plugin header standard).
|
1902 |
-
*/
|
1903 |
-
public function get_installed_version( $slug ) {
|
1904 |
-
$installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
|
1905 |
-
|
1906 |
-
if ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'] ) ) {
|
1907 |
-
return $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'];
|
1908 |
-
}
|
1909 |
-
|
1910 |
-
return '';
|
1911 |
-
}
|
1912 |
-
|
1913 |
-
/**
|
1914 |
-
* Check whether a plugin complies with the minimum version requirements.
|
1915 |
-
*
|
1916 |
-
* @since 2.5.0
|
1917 |
-
*
|
1918 |
-
* @param string $slug Plugin slug.
|
1919 |
-
* @return bool True when a plugin needs to be updated, otherwise false.
|
1920 |
-
*/
|
1921 |
-
public function does_plugin_require_update( $slug ) {
|
1922 |
-
$installed_version = $this->get_installed_version( $slug );
|
1923 |
-
$minimum_version = $this->plugins[ $slug ]['version'];
|
1924 |
-
|
1925 |
-
return version_compare( $minimum_version, $installed_version, '>' );
|
1926 |
-
}
|
1927 |
-
|
1928 |
-
/**
|
1929 |
-
* Check whether there is an update available for a plugin.
|
1930 |
-
*
|
1931 |
-
* @since 2.5.0
|
1932 |
-
*
|
1933 |
-
* @param string $slug Plugin slug.
|
1934 |
-
* @return false|string Version number string of the available update or false if no update available.
|
1935 |
-
*/
|
1936 |
-
public function does_plugin_have_update( $slug ) {
|
1937 |
-
// Presume bundled and external plugins will point to a package which meets the minimum required version.
|
1938 |
-
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
|
1939 |
-
if ( $this->does_plugin_require_update( $slug ) ) {
|
1940 |
-
return $this->plugins[ $slug ]['version'];
|
1941 |
-
}
|
1942 |
-
|
1943 |
-
return false;
|
1944 |
-
}
|
1945 |
-
|
1946 |
-
$repo_updates = get_site_transient( 'update_plugins' );
|
1947 |
-
|
1948 |
-
if ( isset( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version ) ) {
|
1949 |
-
return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version;
|
1950 |
-
}
|
1951 |
-
|
1952 |
-
return false;
|
1953 |
-
}
|
1954 |
-
|
1955 |
-
/**
|
1956 |
-
* Retrieve potential upgrade notice for a plugin.
|
1957 |
-
*
|
1958 |
-
* @since 2.5.0
|
1959 |
-
*
|
1960 |
-
* @param string $slug Plugin slug.
|
1961 |
-
* @return string The upgrade notice or an empty string if no message was available or provided.
|
1962 |
-
*/
|
1963 |
-
public function get_upgrade_notice( $slug ) {
|
1964 |
-
// We currently can't get reliable info on non-WP-repo plugins - issue #380.
|
1965 |
-
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
|
1966 |
-
return '';
|
1967 |
-
}
|
1968 |
-
|
1969 |
-
$repo_updates = get_site_transient( 'update_plugins' );
|
1970 |
-
|
1971 |
-
if ( ! empty( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice ) ) {
|
1972 |
-
return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice;
|
1973 |
-
}
|
1974 |
-
|
1975 |
-
return '';
|
1976 |
-
}
|
1977 |
-
|
1978 |
-
/**
|
1979 |
-
* Wrapper around the core WP get_plugins function, making sure it's actually available.
|
1980 |
-
*
|
1981 |
-
* @since 2.5.0
|
1982 |
-
*
|
1983 |
-
* @param string $plugin_folder Optional. Relative path to single plugin folder.
|
1984 |
-
* @return array Array of installed plugins with plugin information.
|
1985 |
-
*/
|
1986 |
-
public function get_plugins( $plugin_folder = '' ) {
|
1987 |
-
if ( ! function_exists( 'get_plugins' ) ) {
|
1988 |
-
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
1989 |
-
}
|
1990 |
-
|
1991 |
-
return get_plugins( $plugin_folder );
|
1992 |
-
}
|
1993 |
-
|
1994 |
-
/**
|
1995 |
-
* Delete dismissable nag option when theme is switched.
|
1996 |
-
*
|
1997 |
-
* This ensures that the user(s) is/are again reminded via nag of required
|
1998 |
-
* and/or recommended plugins if they re-activate the theme.
|
1999 |
-
*
|
2000 |
-
* @since 2.1.1
|
2001 |
-
*/
|
2002 |
-
public function update_dismiss() {
|
2003 |
-
delete_metadata( 'user', null, 'tgmpa_dismissed_notice_' . $this->id, null, true );
|
2004 |
-
}
|
2005 |
-
|
2006 |
-
/**
|
2007 |
-
* Forces plugin activation if the parameter 'force_activation' is
|
2008 |
-
* set to true.
|
2009 |
-
*
|
2010 |
-
* This allows theme authors to specify certain plugins that must be
|
2011 |
-
* active at all times while using the current theme.
|
2012 |
-
*
|
2013 |
-
* Please take special care when using this parameter as it has the
|
2014 |
-
* potential to be harmful if not used correctly. Setting this parameter
|
2015 |
-
* to true will not allow the specified plugin to be deactivated unless
|
2016 |
-
* the user switches themes.
|
2017 |
-
*
|
2018 |
-
* @since 2.2.0
|
2019 |
-
*/
|
2020 |
-
public function force_activation() {
|
2021 |
-
foreach ( $this->plugins as $slug => $plugin ) {
|
2022 |
-
if ( true === $plugin['force_activation'] ) {
|
2023 |
-
if ( ! $this->is_plugin_installed( $slug ) ) {
|
2024 |
-
// Oops, plugin isn't there so iterate to next condition.
|
2025 |
-
continue;
|
2026 |
-
} elseif ( $this->can_plugin_activate( $slug ) ) {
|
2027 |
-
// There we go, activate the plugin.
|
2028 |
-
activate_plugin( $plugin['file_path'] );
|
2029 |
-
}
|
2030 |
-
}
|
2031 |
-
}
|
2032 |
-
}
|
2033 |
-
|
2034 |
-
/**
|
2035 |
-
* Forces plugin deactivation if the parameter 'force_deactivation'
|
2036 |
-
* is set to true and adds the plugin to the 'recently active' plugins list.
|
2037 |
-
*
|
2038 |
-
* This allows theme authors to specify certain plugins that must be
|
2039 |
-
* deactivated upon switching from the current theme to another.
|
2040 |
-
*
|
2041 |
-
* Please take special care when using this parameter as it has the
|
2042 |
-
* potential to be harmful if not used correctly.
|
2043 |
-
*
|
2044 |
-
* @since 2.2.0
|
2045 |
-
*/
|
2046 |
-
public function force_deactivation() {
|
2047 |
-
$deactivated = array();
|
2048 |
-
|
2049 |
-
foreach ( $this->plugins as $slug => $plugin ) {
|
2050 |
-
/*
|
2051 |
-
* Only proceed forward if the parameter is set to true and plugin is active
|
2052 |
-
* as a 'normal' (not must-use) plugin.
|
2053 |
-
*/
|
2054 |
-
if ( true === $plugin['force_deactivation'] && is_plugin_active( $plugin['file_path'] ) ) {
|
2055 |
-
deactivate_plugins( $plugin['file_path'] );
|
2056 |
-
$deactivated[ $plugin['file_path'] ] = time();
|
2057 |
-
}
|
2058 |
-
}
|
2059 |
-
|
2060 |
-
if ( ! empty( $deactivated ) ) {
|
2061 |
-
update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ) );
|
2062 |
-
}
|
2063 |
-
}
|
2064 |
-
|
2065 |
-
/**
|
2066 |
-
* Echo the current TGMPA version number to the page.
|
2067 |
-
*
|
2068 |
-
* @since 2.5.0
|
2069 |
-
*/
|
2070 |
-
public function show_tgmpa_version() {
|
2071 |
-
echo '<p style="float: right; padding: 0em 1.5em 0.5em 0;"><strong><small>',
|
2072 |
-
esc_html(
|
2073 |
-
sprintf(
|
2074 |
-
/* translators: %s: version number */
|
2075 |
-
__( 'TGMPA v%s', 'tgmpa' ),
|
2076 |
-
self::TGMPA_VERSION
|
2077 |
-
)
|
2078 |
-
),
|
2079 |
-
'</small></strong></p>';
|
2080 |
-
}
|
2081 |
-
|
2082 |
-
/**
|
2083 |
-
* Returns the singleton instance of the class.
|
2084 |
-
*
|
2085 |
-
* @since 2.4.0
|
2086 |
-
*
|
2087 |
-
* @return \TGM_Plugin_Activation The TGM_Plugin_Activation object.
|
2088 |
-
*/
|
2089 |
-
public static function get_instance() {
|
2090 |
-
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
|
2091 |
-
self::$instance = new self();
|
2092 |
-
}
|
2093 |
-
|
2094 |
-
return self::$instance;
|
2095 |
-
}
|
2096 |
-
}
|
2097 |
-
|
2098 |
-
if ( ! function_exists( 'load_tgm_plugin_activation' ) ) {
|
2099 |
-
/**
|
2100 |
-
* Ensure only one instance of the class is ever invoked.
|
2101 |
-
*
|
2102 |
-
* @since 2.5.0
|
2103 |
-
*/
|
2104 |
-
function load_tgm_plugin_activation() {
|
2105 |
-
$GLOBALS['tgmpa'] = TGM_Plugin_Activation::get_instance();
|
2106 |
-
}
|
2107 |
-
}
|
2108 |
-
|
2109 |
-
if ( did_action( 'plugins_loaded' ) ) {
|
2110 |
-
load_tgm_plugin_activation();
|
2111 |
-
} else {
|
2112 |
-
add_action( 'plugins_loaded', 'load_tgm_plugin_activation' );
|
2113 |
-
}
|
2114 |
-
}
|
2115 |
-
|
2116 |
-
if ( ! function_exists( 'tgmpa' ) ) {
|
2117 |
-
/**
|
2118 |
-
* Helper function to register a collection of required plugins.
|
2119 |
-
*
|
2120 |
-
* @since 2.0.0
|
2121 |
-
* @api
|
2122 |
-
*
|
2123 |
-
* @param array $plugins An array of plugin arrays.
|
2124 |
-
* @param array $config Optional. An array of configuration values.
|
2125 |
-
*/
|
2126 |
-
function tgmpa( $plugins, $config = array() ) {
|
2127 |
-
$instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
2128 |
-
|
2129 |
-
foreach ( $plugins as $plugin ) {
|
2130 |
-
call_user_func( array( $instance, 'register' ), $plugin );
|
2131 |
-
}
|
2132 |
-
|
2133 |
-
if ( ! empty( $config ) && is_array( $config ) ) {
|
2134 |
-
// Send out notices for deprecated arguments passed.
|
2135 |
-
if ( isset( $config['notices'] ) ) {
|
2136 |
-
_deprecated_argument( __FUNCTION__, '2.2.0', 'The `notices` config parameter was renamed to `has_notices` in TGMPA 2.2.0. Please adjust your configuration.' );
|
2137 |
-
if ( ! isset( $config['has_notices'] ) ) {
|
2138 |
-
$config['has_notices'] = $config['notices'];
|
2139 |
-
}
|
2140 |
-
}
|
2141 |
-
|
2142 |
-
if ( isset( $config['parent_menu_slug'] ) ) {
|
2143 |
-
_deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_menu_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
|
2144 |
-
}
|
2145 |
-
if ( isset( $config['parent_url_slug'] ) ) {
|
2146 |
-
_deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_url_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
|
2147 |
-
}
|
2148 |
-
|
2149 |
-
call_user_func( array( $instance, 'config' ), $config );
|
2150 |
-
}
|
2151 |
-
}
|
2152 |
-
}
|
2153 |
-
|
2154 |
-
/**
|
2155 |
-
* WP_List_Table isn't always available. If it isn't available,
|
2156 |
-
* we load it here.
|
2157 |
-
*
|
2158 |
-
* @since 2.2.0
|
2159 |
-
*/
|
2160 |
-
if ( ! class_exists( 'WP_List_Table' ) ) {
|
2161 |
-
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
2162 |
-
}
|
2163 |
-
|
2164 |
-
if ( ! class_exists( 'TGMPA_List_Table' ) ) {
|
2165 |
-
|
2166 |
-
/**
|
2167 |
-
* List table class for handling plugins.
|
2168 |
-
*
|
2169 |
-
* Extends the WP_List_Table class to provide a future-compatible
|
2170 |
-
* way of listing out all required/recommended plugins.
|
2171 |
-
*
|
2172 |
-
* Gives users an interface similar to the Plugin Administration
|
2173 |
-
* area with similar (albeit stripped down) capabilities.
|
2174 |
-
*
|
2175 |
-
* This class also allows for the bulk install of plugins.
|
2176 |
-
*
|
2177 |
-
* @since 2.2.0
|
2178 |
-
*
|
2179 |
-
* @package TGM-Plugin-Activation
|
2180 |
-
* @author Thomas Griffin
|
2181 |
-
* @author Gary Jones
|
2182 |
-
*/
|
2183 |
-
class TGMPA_List_Table extends WP_List_Table {
|
2184 |
-
/**
|
2185 |
-
* TGMPA instance.
|
2186 |
-
*
|
2187 |
-
* @since 2.5.0
|
2188 |
-
*
|
2189 |
-
* @var object
|
2190 |
-
*/
|
2191 |
-
protected $tgmpa;
|
2192 |
-
|
2193 |
-
/**
|
2194 |
-
* The currently chosen view.
|
2195 |
-
*
|
2196 |
-
* @since 2.5.0
|
2197 |
-
*
|
2198 |
-
* @var string One of: 'all', 'install', 'update', 'activate'
|
2199 |
-
*/
|
2200 |
-
public $view_context = 'all';
|
2201 |
-
|
2202 |
-
/**
|
2203 |
-
* The plugin counts for the various views.
|
2204 |
-
*
|
2205 |
-
* @since 2.5.0
|
2206 |
-
*
|
2207 |
-
* @var array
|
2208 |
-
*/
|
2209 |
-
protected $view_totals = array(
|
2210 |
-
'all' => 0,
|
2211 |
-
'install' => 0,
|
2212 |
-
'update' => 0,
|
2213 |
-
'activate' => 0,
|
2214 |
-
);
|
2215 |
-
|
2216 |
-
/**
|
2217 |
-
* References parent constructor and sets defaults for class.
|
2218 |
-
*
|
2219 |
-
* @since 2.2.0
|
2220 |
-
*/
|
2221 |
-
public function __construct() {
|
2222 |
-
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
2223 |
-
|
2224 |
-
parent::__construct(
|
2225 |
-
array(
|
2226 |
-
'singular' => 'plugin',
|
2227 |
-
'plural' => 'plugins',
|
2228 |
-
'ajax' => false,
|
2229 |
-
)
|
2230 |
-
);
|
2231 |
-
|
2232 |
-
if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'install', 'update', 'activate' ), true ) ) {
|
2233 |
-
$this->view_context = sanitize_key( $_REQUEST['plugin_status'] );
|
2234 |
-
}
|
2235 |
-
|
2236 |
-
add_filter( 'tgmpa_table_data_items', array( $this, 'sort_table_items' ) );
|
2237 |
-
}
|
2238 |
-
|
2239 |
-
/**
|
2240 |
-
* Get a list of CSS classes for the <table> tag.
|
2241 |
-
*
|
2242 |
-
* Overruled to prevent the 'plural' argument from being added.
|
2243 |
-
*
|
2244 |
-
* @since 2.5.0
|
2245 |
-
*
|
2246 |
-
* @return array CSS classnames.
|
2247 |
-
*/
|
2248 |
-
public function get_table_classes() {
|
2249 |
-
return array( 'widefat', 'fixed' );
|
2250 |
-
}
|
2251 |
-
|
2252 |
-
/**
|
2253 |
-
* Gathers and renames all of our plugin information to be used by WP_List_Table to create our table.
|
2254 |
-
*
|
2255 |
-
* @since 2.2.0
|
2256 |
-
*
|
2257 |
-
* @return array $table_data Information for use in table.
|
2258 |
-
*/
|
2259 |
-
protected function _gather_plugin_data() {
|
2260 |
-
// Load thickbox for plugin links.
|
2261 |
-
$this->tgmpa->admin_init();
|
2262 |
-
$this->tgmpa->thickbox();
|
2263 |
-
|
2264 |
-
// Categorize the plugins which have open actions.
|
2265 |
-
$plugins = $this->categorize_plugins_to_views();
|
2266 |
-
|
2267 |
-
// Set the counts for the view links.
|
2268 |
-
$this->set_view_totals( $plugins );
|
2269 |
-
|
2270 |
-
// Prep variables for use and grab list of all installed plugins.
|
2271 |
-
$table_data = array();
|
2272 |
-
$i = 0;
|
2273 |
-
|
2274 |
-
// Redirect to the 'all' view if no plugins were found for the selected view context.
|
2275 |
-
if ( empty( $plugins[ $this->view_context ] ) ) {
|
2276 |
-
$this->view_context = 'all';
|
2277 |
-
}
|
2278 |
-
|
2279 |
-
foreach ( $plugins[ $this->view_context ] as $slug => $plugin ) {
|
2280 |
-
$table_data[ $i ]['sanitized_plugin'] = $plugin['name'];
|
2281 |
-
$table_data[ $i ]['slug'] = $slug;
|
2282 |
-
$table_data[ $i ]['plugin'] = '<strong>' . $this->tgmpa->get_info_link( $slug ) . '</strong>';
|
2283 |
-
$table_data[ $i ]['source'] = $this->get_plugin_source_type_text( $plugin['source_type'] );
|
2284 |
-
$table_data[ $i ]['type'] = $this->get_plugin_advise_type_text( $plugin['required'] );
|
2285 |
-
$table_data[ $i ]['status'] = $this->get_plugin_status_text( $slug );
|
2286 |
-
$table_data[ $i ]['installed_version'] = $this->tgmpa->get_installed_version( $slug );
|
2287 |
-
$table_data[ $i ]['minimum_version'] = $plugin['version'];
|
2288 |
-
$table_data[ $i ]['available_version'] = $this->tgmpa->does_plugin_have_update( $slug );
|
2289 |
-
|
2290 |
-
// Prep the upgrade notice info.
|
2291 |
-
$upgrade_notice = $this->tgmpa->get_upgrade_notice( $slug );
|
2292 |
-
if ( ! empty( $upgrade_notice ) ) {
|
2293 |
-
$table_data[ $i ]['upgrade_notice'] = $upgrade_notice;
|
2294 |
-
|
2295 |
-
add_action( "tgmpa_after_plugin_row_{$slug}", array( $this, 'wp_plugin_update_row' ), 10, 2 );
|
2296 |
-
}
|
2297 |
-
|
2298 |
-
$table_data[ $i ] = apply_filters( 'tgmpa_table_data_item', $table_data[ $i ], $plugin );
|
2299 |
-
|
2300 |
-
$i++;
|
2301 |
-
}
|
2302 |
-
|
2303 |
-
return $table_data;
|
2304 |
-
}
|
2305 |
-
|
2306 |
-
/**
|
2307 |
-
* Categorize the plugins which have open actions into views for the TGMPA page.
|
2308 |
-
*
|
2309 |
-
* @since 2.5.0
|
2310 |
-
*/
|
2311 |
-
protected function categorize_plugins_to_views() {
|
2312 |
-
$plugins = array(
|
2313 |
-
'all' => array(), // Meaning: all plugins which still have open actions.
|
2314 |
-
'install' => array(),
|
2315 |
-
'update' => array(),
|
2316 |
-
'activate' => array(),
|
2317 |
-
);
|
2318 |
-
|
2319 |
-
foreach ( $this->tgmpa->plugins as $slug => $plugin ) {
|
2320 |
-
if ( $this->tgmpa->is_plugin_active( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2321 |
-
// No need to display plugins if they are installed, up-to-date and active.
|
2322 |
-
continue;
|
2323 |
-
} else {
|
2324 |
-
$plugins['all'][ $slug ] = $plugin;
|
2325 |
-
|
2326 |
-
if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
|
2327 |
-
$plugins['install'][ $slug ] = $plugin;
|
2328 |
-
} else {
|
2329 |
-
if ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2330 |
-
$plugins['update'][ $slug ] = $plugin;
|
2331 |
-
}
|
2332 |
-
|
2333 |
-
if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
|
2334 |
-
$plugins['activate'][ $slug ] = $plugin;
|
2335 |
-
}
|
2336 |
-
}
|
2337 |
-
}
|
2338 |
-
}
|
2339 |
-
|
2340 |
-
return $plugins;
|
2341 |
-
}
|
2342 |
-
|
2343 |
-
/**
|
2344 |
-
* Set the counts for the view links.
|
2345 |
-
*
|
2346 |
-
* @since 2.5.0
|
2347 |
-
*
|
2348 |
-
* @param array $plugins Plugins order by view.
|
2349 |
-
*/
|
2350 |
-
protected function set_view_totals( $plugins ) {
|
2351 |
-
foreach ( $plugins as $type => $list ) {
|
2352 |
-
$this->view_totals[ $type ] = count( $list );
|
2353 |
-
}
|
2354 |
-
}
|
2355 |
-
|
2356 |
-
/**
|
2357 |
-
* Get the plugin required/recommended text string.
|
2358 |
-
*
|
2359 |
-
* @since 2.5.0
|
2360 |
-
*
|
2361 |
-
* @param string $required Plugin required setting.
|
2362 |
-
* @return string
|
2363 |
-
*/
|
2364 |
-
protected function get_plugin_advise_type_text( $required ) {
|
2365 |
-
if ( true === $required ) {
|
2366 |
-
return __( 'Required', 'tgmpa' );
|
2367 |
-
}
|
2368 |
-
|
2369 |
-
return __( 'Recommended', 'tgmpa' );
|
2370 |
-
}
|
2371 |
-
|
2372 |
-
/**
|
2373 |
-
* Get the plugin source type text string.
|
2374 |
-
*
|
2375 |
-
* @since 2.5.0
|
2376 |
-
*
|
2377 |
-
* @param string $type Plugin type.
|
2378 |
-
* @return string
|
2379 |
-
*/
|
2380 |
-
protected function get_plugin_source_type_text( $type ) {
|
2381 |
-
$string = '';
|
2382 |
-
|
2383 |
-
switch ( $type ) {
|
2384 |
-
case 'repo':
|
2385 |
-
$string = __( 'WordPress Repository', 'tgmpa' );
|
2386 |
-
break;
|
2387 |
-
case 'external':
|
2388 |
-
$string = __( 'External Source', 'tgmpa' );
|
2389 |
-
break;
|
2390 |
-
case 'bundled':
|
2391 |
-
$string = __( 'Pre-Packaged', 'tgmpa' );
|
2392 |
-
break;
|
2393 |
-
}
|
2394 |
-
|
2395 |
-
return $string;
|
2396 |
-
}
|
2397 |
-
|
2398 |
-
/**
|
2399 |
-
* Determine the plugin status message.
|
2400 |
-
*
|
2401 |
-
* @since 2.5.0
|
2402 |
-
*
|
2403 |
-
* @param string $slug Plugin slug.
|
2404 |
-
* @return string
|
2405 |
-
*/
|
2406 |
-
protected function get_plugin_status_text( $slug ) {
|
2407 |
-
if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
|
2408 |
-
return __( 'Not Installed', 'tgmpa' );
|
2409 |
-
}
|
2410 |
-
|
2411 |
-
if ( ! $this->tgmpa->is_plugin_active( $slug ) ) {
|
2412 |
-
$install_status = __( 'Installed But Not Activated', 'tgmpa' );
|
2413 |
-
} else {
|
2414 |
-
$install_status = __( 'Active', 'tgmpa' );
|
2415 |
-
}
|
2416 |
-
|
2417 |
-
$update_status = '';
|
2418 |
-
|
2419 |
-
if ( $this->tgmpa->does_plugin_require_update( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2420 |
-
$update_status = __( 'Required Update not Available', 'tgmpa' );
|
2421 |
-
|
2422 |
-
} elseif ( $this->tgmpa->does_plugin_require_update( $slug ) ) {
|
2423 |
-
$update_status = __( 'Requires Update', 'tgmpa' );
|
2424 |
-
|
2425 |
-
} elseif ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2426 |
-
$update_status = __( 'Update recommended', 'tgmpa' );
|
2427 |
-
}
|
2428 |
-
|
2429 |
-
if ( '' === $update_status ) {
|
2430 |
-
return $install_status;
|
2431 |
-
}
|
2432 |
-
|
2433 |
-
return sprintf(
|
2434 |
-
/* translators: 1: install status, 2: update status */
|
2435 |
-
_x( '%1$s, %2$s', 'Install/Update Status', 'tgmpa' ),
|
2436 |
-
$install_status,
|
2437 |
-
$update_status
|
2438 |
-
);
|
2439 |
-
}
|
2440 |
-
|
2441 |
-
/**
|
2442 |
-
* Sort plugins by Required/Recommended type and by alphabetical plugin name within each type.
|
2443 |
-
*
|
2444 |
-
* @since 2.5.0
|
2445 |
-
*
|
2446 |
-
* @param array $items Prepared table items.
|
2447 |
-
* @return array Sorted table items.
|
2448 |
-
*/
|
2449 |
-
public function sort_table_items( $items ) {
|
2450 |
-
$type = array();
|
2451 |
-
$name = array();
|
2452 |
-
|
2453 |
-
foreach ( $items as $i => $plugin ) {
|
2454 |
-
$type[ $i ] = $plugin['type']; // Required / recommended.
|
2455 |
-
$name[ $i ] = $plugin['sanitized_plugin'];
|
2456 |
-
}
|
2457 |
-
|
2458 |
-
array_multisort( $type, SORT_DESC, $name, SORT_ASC, $items );
|
2459 |
-
|
2460 |
-
return $items;
|
2461 |
-
}
|
2462 |
-
|
2463 |
-
/**
|
2464 |
-
* Get an associative array ( id => link ) of the views available on this table.
|
2465 |
-
*
|
2466 |
-
* @since 2.5.0
|
2467 |
-
*
|
2468 |
-
* @return array
|
2469 |
-
*/
|
2470 |
-
public function get_views() {
|
2471 |
-
$status_links = array();
|
2472 |
-
|
2473 |
-
foreach ( $this->view_totals as $type => $count ) {
|
2474 |
-
if ( $count < 1 ) {
|
2475 |
-
continue;
|
2476 |
-
}
|
2477 |
-
|
2478 |
-
switch ( $type ) {
|
2479 |
-
case 'all':
|
2480 |
-
/* translators: 1: number of plugins. */
|
2481 |
-
$text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'plugins', 'tgmpa' );
|
2482 |
-
break;
|
2483 |
-
case 'install':
|
2484 |
-
/* translators: 1: number of plugins. */
|
2485 |
-
$text = _n( 'To Install <span class="count">(%s)</span>', 'To Install <span class="count">(%s)</span>', $count, 'tgmpa' );
|
2486 |
-
break;
|
2487 |
-
case 'update':
|
2488 |
-
/* translators: 1: number of plugins. */
|
2489 |
-
$text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count, 'tgmpa' );
|
2490 |
-
break;
|
2491 |
-
case 'activate':
|
2492 |
-
/* translators: 1: number of plugins. */
|
2493 |
-
$text = _n( 'To Activate <span class="count">(%s)</span>', 'To Activate <span class="count">(%s)</span>', $count, 'tgmpa' );
|
2494 |
-
break;
|
2495 |
-
default:
|
2496 |
-
$text = '';
|
2497 |
-
break;
|
2498 |
-
}
|
2499 |
-
|
2500 |
-
if ( ! empty( $text ) ) {
|
2501 |
-
|
2502 |
-
$status_links[ $type ] = sprintf(
|
2503 |
-
'<a href="%s"%s>%s</a>',
|
2504 |
-
esc_url( $this->tgmpa->get_tgmpa_status_url( $type ) ),
|
2505 |
-
( $type === $this->view_context ) ? ' class="current"' : '',
|
2506 |
-
sprintf( $text, number_format_i18n( $count ) )
|
2507 |
-
);
|
2508 |
-
}
|
2509 |
-
}
|
2510 |
-
|
2511 |
-
return $status_links;
|
2512 |
-
}
|
2513 |
-
|
2514 |
-
/**
|
2515 |
-
* Create default columns to display important plugin information
|
2516 |
-
* like type, action and status.
|
2517 |
-
*
|
2518 |
-
* @since 2.2.0
|
2519 |
-
*
|
2520 |
-
* @param array $item Array of item data.
|
2521 |
-
* @param string $column_name The name of the column.
|
2522 |
-
* @return string
|
2523 |
-
*/
|
2524 |
-
public function column_default( $item, $column_name ) {
|
2525 |
-
return $item[ $column_name ];
|
2526 |
-
}
|
2527 |
-
|
2528 |
-
/**
|
2529 |
-
* Required for bulk installing.
|
2530 |
-
*
|
2531 |
-
* Adds a checkbox for each plugin.
|
2532 |
-
*
|
2533 |
-
* @since 2.2.0
|
2534 |
-
*
|
2535 |
-
* @param array $item Array of item data.
|
2536 |
-
* @return string The input checkbox with all necessary info.
|
2537 |
-
*/
|
2538 |
-
public function column_cb( $item ) {
|
2539 |
-
return sprintf(
|
2540 |
-
'<input type="checkbox" name="%1$s[]" value="%2$s" id="%3$s" />',
|
2541 |
-
esc_attr( $this->_args['singular'] ),
|
2542 |
-
esc_attr( $item['slug'] ),
|
2543 |
-
esc_attr( $item['sanitized_plugin'] )
|
2544 |
-
);
|
2545 |
-
}
|
2546 |
-
|
2547 |
-
/**
|
2548 |
-
* Create default title column along with the action links.
|
2549 |
-
*
|
2550 |
-
* @since 2.2.0
|
2551 |
-
*
|
2552 |
-
* @param array $item Array of item data.
|
2553 |
-
* @return string The plugin name and action links.
|
2554 |
-
*/
|
2555 |
-
public function column_plugin( $item ) {
|
2556 |
-
return sprintf(
|
2557 |
-
'%1$s %2$s',
|
2558 |
-
$item['plugin'],
|
2559 |
-
$this->row_actions( $this->get_row_actions( $item ), true )
|
2560 |
-
);
|
2561 |
-
}
|
2562 |
-
|
2563 |
-
/**
|
2564 |
-
* Create version information column.
|
2565 |
-
*
|
2566 |
-
* @since 2.5.0
|
2567 |
-
*
|
2568 |
-
* @param array $item Array of item data.
|
2569 |
-
* @return string HTML-formatted version information.
|
2570 |
-
*/
|
2571 |
-
public function column_version( $item ) {
|
2572 |
-
$output = array();
|
2573 |
-
|
2574 |
-
if ( $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
|
2575 |
-
$installed = ! empty( $item['installed_version'] ) ? $item['installed_version'] : _x( 'unknown', 'as in: "version nr unknown"', 'tgmpa' );
|
2576 |
-
|
2577 |
-
$color = '';
|
2578 |
-
if ( ! empty( $item['minimum_version'] ) && $this->tgmpa->does_plugin_require_update( $item['slug'] ) ) {
|
2579 |
-
$color = ' color: #ff0000; font-weight: bold;';
|
2580 |
-
}
|
2581 |
-
|
2582 |
-
$output[] = sprintf(
|
2583 |
-
'<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Installed version:', 'tgmpa' ) . '</p>',
|
2584 |
-
$color,
|
2585 |
-
$installed
|
2586 |
-
);
|
2587 |
-
}
|
2588 |
-
|
2589 |
-
if ( ! empty( $item['minimum_version'] ) ) {
|
2590 |
-
$output[] = sprintf(
|
2591 |
-
'<p><span style="min-width: 32px; text-align: right; float: right;">%1$s</span>' . __( 'Minimum required version:', 'tgmpa' ) . '</p>',
|
2592 |
-
$item['minimum_version']
|
2593 |
-
);
|
2594 |
-
}
|
2595 |
-
|
2596 |
-
if ( ! empty( $item['available_version'] ) ) {
|
2597 |
-
$color = '';
|
2598 |
-
if ( ! empty( $item['minimum_version'] ) && version_compare( $item['available_version'], $item['minimum_version'], '>=' ) ) {
|
2599 |
-
$color = ' color: #71C671; font-weight: bold;';
|
2600 |
-
}
|
2601 |
-
|
2602 |
-
$output[] = sprintf(
|
2603 |
-
'<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Available version:', 'tgmpa' ) . '</p>',
|
2604 |
-
$color,
|
2605 |
-
$item['available_version']
|
2606 |
-
);
|
2607 |
-
}
|
2608 |
-
|
2609 |
-
if ( empty( $output ) ) {
|
2610 |
-
return ' '; // Let's not break the table layout.
|
2611 |
-
} else {
|
2612 |
-
return implode( "\n", $output );
|
2613 |
-
}
|
2614 |
-
}
|
2615 |
-
|
2616 |
-
/**
|
2617 |
-
* Sets default message within the plugins table if no plugins
|
2618 |
-
* are left for interaction.
|
2619 |
-
*
|
2620 |
-
* Hides the menu item to prevent the user from clicking and
|
2621 |
-
* getting a permissions error.
|
2622 |
-
*
|
2623 |
-
* @since 2.2.0
|
2624 |
-
*/
|
2625 |
-
public function no_items() {
|
2626 |
-
echo esc_html__( 'No plugins to install, update or activate.', 'tgmpa' ) . ' <a href="' . esc_url( self_admin_url() ) . '"> ' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>';
|
2627 |
-
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
|
2628 |
-
}
|
2629 |
-
|
2630 |
-
/**
|
2631 |
-
* Output all the column information within the table.
|
2632 |
-
*
|
2633 |
-
* @since 2.2.0
|
2634 |
-
*
|
2635 |
-
* @return array $columns The column names.
|
2636 |
-
*/
|
2637 |
-
public function get_columns() {
|
2638 |
-
$columns = array(
|
2639 |
-
'cb' => '<input type="checkbox" />',
|
2640 |
-
'plugin' => __( 'Plugin', 'tgmpa' ),
|
2641 |
-
'source' => __( 'Source', 'tgmpa' ),
|
2642 |
-
'type' => __( 'Type', 'tgmpa' ),
|
2643 |
-
);
|
2644 |
-
|
2645 |
-
if ( 'all' === $this->view_context || 'update' === $this->view_context ) {
|
2646 |
-
$columns['version'] = __( 'Version', 'tgmpa' );
|
2647 |
-
$columns['status'] = __( 'Status', 'tgmpa' );
|
2648 |
-
}
|
2649 |
-
|
2650 |
-
return apply_filters( 'tgmpa_table_columns', $columns );
|
2651 |
-
}
|
2652 |
-
|
2653 |
-
/**
|
2654 |
-
* Get name of default primary column
|
2655 |
-
*
|
2656 |
-
* @since 2.5.0 / WP 4.3+ compatibility
|
2657 |
-
* @access protected
|
2658 |
-
*
|
2659 |
-
* @return string
|
2660 |
-
*/
|
2661 |
-
protected function get_default_primary_column_name() {
|
2662 |
-
return 'plugin';
|
2663 |
-
}
|
2664 |
-
|
2665 |
-
/**
|
2666 |
-
* Get the name of the primary column.
|
2667 |
-
*
|
2668 |
-
* @since 2.5.0 / WP 4.3+ compatibility
|
2669 |
-
* @access protected
|
2670 |
-
*
|
2671 |
-
* @return string The name of the primary column.
|
2672 |
-
*/
|
2673 |
-
protected function get_primary_column_name() {
|
2674 |
-
if ( method_exists( 'WP_List_Table', 'get_primary_column_name' ) ) {
|
2675 |
-
return parent::get_primary_column_name();
|
2676 |
-
} else {
|
2677 |
-
return $this->get_default_primary_column_name();
|
2678 |
-
}
|
2679 |
-
}
|
2680 |
-
|
2681 |
-
/**
|
2682 |
-
* Get the actions which are relevant for a specific plugin row.
|
2683 |
-
*
|
2684 |
-
* @since 2.5.0
|
2685 |
-
*
|
2686 |
-
* @param array $item Array of item data.
|
2687 |
-
* @return array Array with relevant action links.
|
2688 |
-
*/
|
2689 |
-
protected function get_row_actions( $item ) {
|
2690 |
-
$actions = array();
|
2691 |
-
$action_links = array();
|
2692 |
-
|
2693 |
-
// Display the 'Install' action link if the plugin is not yet available.
|
2694 |
-
if ( ! $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
|
2695 |
-
/* translators: %2$s: plugin name in screen reader markup */
|
2696 |
-
$actions['install'] = __( 'Install %2$s', 'tgmpa' );
|
2697 |
-
} else {
|
2698 |
-
// Display the 'Update' action link if an update is available and WP complies with plugin minimum.
|
2699 |
-
if ( false !== $this->tgmpa->does_plugin_have_update( $item['slug'] ) && $this->tgmpa->can_plugin_update( $item['slug'] ) ) {
|
2700 |
-
/* translators: %2$s: plugin name in screen reader markup */
|
2701 |
-
$actions['update'] = __( 'Update %2$s', 'tgmpa' );
|
2702 |
-
}
|
2703 |
-
|
2704 |
-
// Display the 'Activate' action link, but only if the plugin meets the minimum version.
|
2705 |
-
if ( $this->tgmpa->can_plugin_activate( $item['slug'] ) ) {
|
2706 |
-
/* translators: %2$s: plugin name in screen reader markup */
|
2707 |
-
$actions['activate'] = __( 'Activate %2$s', 'tgmpa' );
|
2708 |
-
}
|
2709 |
-
}
|
2710 |
-
|
2711 |
-
// Create the actual links.
|
2712 |
-
foreach ( $actions as $action => $text ) {
|
2713 |
-
$nonce_url = wp_nonce_url(
|
2714 |
-
add_query_arg(
|
2715 |
-
array(
|
2716 |
-
'plugin' => urlencode( $item['slug'] ),
|
2717 |
-
'tgmpa-' . $action => $action . '-plugin',
|
2718 |
-
),
|
2719 |
-
$this->tgmpa->get_tgmpa_url()
|
2720 |
-
),
|
2721 |
-
'tgmpa-' . $action,
|
2722 |
-
'tgmpa-nonce'
|
2723 |
-
);
|
2724 |
-
|
2725 |
-
$action_links[ $action ] = sprintf(
|
2726 |
-
'<a href="%1$s">' . esc_html( $text ) . '</a>', // $text contains the second placeholder.
|
2727 |
-
esc_url( $nonce_url ),
|
2728 |
-
'<span class="screen-reader-text">' . esc_html( $item['sanitized_plugin'] ) . '</span>'
|
2729 |
-
);
|
2730 |
-
}
|
2731 |
-
|
2732 |
-
$prefix = ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) ? 'network_admin_' : '';
|
2733 |
-
return apply_filters( "tgmpa_{$prefix}plugin_action_links", array_filter( $action_links ), $item['slug'], $item, $this->view_context );
|
2734 |
-
}
|
2735 |
-
|
2736 |
-
/**
|
2737 |
-
* Generates content for a single row of the table.
|
2738 |
-
*
|
2739 |
-
* @since 2.5.0
|
2740 |
-
*
|
2741 |
-
* @param object $item The current item.
|
2742 |
-
*/
|
2743 |
-
public function single_row( $item ) {
|
2744 |
-
parent::single_row( $item );
|
2745 |
-
|
2746 |
-
/**
|
2747 |
-
* Fires after each specific row in the TGMPA Plugins list table.
|
2748 |
-
*
|
2749 |
-
* The dynamic portion of the hook name, `$item['slug']`, refers to the slug
|
2750 |
-
* for the plugin.
|
2751 |
-
*
|
2752 |
-
* @since 2.5.0
|
2753 |
-
*/
|
2754 |
-
do_action( "tgmpa_after_plugin_row_{$item['slug']}", $item['slug'], $item, $this->view_context );
|
2755 |
-
}
|
2756 |
-
|
2757 |
-
/**
|
2758 |
-
* Show the upgrade notice below a plugin row if there is one.
|
2759 |
-
*
|
2760 |
-
* @since 2.5.0
|
2761 |
-
*
|
2762 |
-
* @see /wp-admin/includes/update.php
|
2763 |
-
*
|
2764 |
-
* @param string $slug Plugin slug.
|
2765 |
-
* @param array $item The information available in this table row.
|
2766 |
-
* @return null Return early if upgrade notice is empty.
|
2767 |
-
*/
|
2768 |
-
public function wp_plugin_update_row( $slug, $item ) {
|
2769 |
-
if ( empty( $item['upgrade_notice'] ) ) {
|
2770 |
-
return;
|
2771 |
-
}
|
2772 |
-
|
2773 |
-
echo '
|
2774 |
-
<tr class="plugin-update-tr">
|
2775 |
-
<td colspan="', absint( $this->get_column_count() ), '" class="plugin-update colspanchange">
|
2776 |
-
<div class="update-message">',
|
2777 |
-
esc_html__( 'Upgrade message from the plugin author:', 'tgmpa' ),
|
2778 |
-
' <strong>', wp_kses_data( $item['upgrade_notice'] ), '</strong>
|
2779 |
-
</div>
|
2780 |
-
</td>
|
2781 |
-
</tr>';
|
2782 |
-
}
|
2783 |
-
|
2784 |
-
/**
|
2785 |
-
* Extra controls to be displayed between bulk actions and pagination.
|
2786 |
-
*
|
2787 |
-
* @since 2.5.0
|
2788 |
-
*
|
2789 |
-
* @param string $which 'top' or 'bottom' table navigation.
|
2790 |
-
*/
|
2791 |
-
public function extra_tablenav( $which ) {
|
2792 |
-
if ( 'bottom' === $which ) {
|
2793 |
-
$this->tgmpa->show_tgmpa_version();
|
2794 |
-
}
|
2795 |
-
}
|
2796 |
-
|
2797 |
-
/**
|
2798 |
-
* Defines the bulk actions for handling registered plugins.
|
2799 |
-
*
|
2800 |
-
* @since 2.2.0
|
2801 |
-
*
|
2802 |
-
* @return array $actions The bulk actions for the plugin install table.
|
2803 |
-
*/
|
2804 |
-
public function get_bulk_actions() {
|
2805 |
-
|
2806 |
-
$actions = array();
|
2807 |
-
|
2808 |
-
if ( 'update' !== $this->view_context && 'activate' !== $this->view_context ) {
|
2809 |
-
if ( current_user_can( 'install_plugins' ) ) {
|
2810 |
-
$actions['tgmpa-bulk-install'] = __( 'Install', 'tgmpa' );
|
2811 |
-
}
|
2812 |
-
}
|
2813 |
-
|
2814 |
-
if ( 'install' !== $this->view_context ) {
|
2815 |
-
if ( current_user_can( 'update_plugins' ) ) {
|
2816 |
-
$actions['tgmpa-bulk-update'] = __( 'Update', 'tgmpa' );
|
2817 |
-
}
|
2818 |
-
if ( current_user_can( 'activate_plugins' ) ) {
|
2819 |
-
$actions['tgmpa-bulk-activate'] = __( 'Activate', 'tgmpa' );
|
2820 |
-
}
|
2821 |
-
}
|
2822 |
-
|
2823 |
-
return $actions;
|
2824 |
-
}
|
2825 |
-
|
2826 |
-
/**
|
2827 |
-
* Processes bulk installation and activation actions.
|
2828 |
-
*
|
2829 |
-
* The bulk installation process looks for the $_POST information and passes that
|
2830 |
-
* through if a user has to use WP_Filesystem to enter their credentials.
|
2831 |
-
*
|
2832 |
-
* @since 2.2.0
|
2833 |
-
*/
|
2834 |
-
public function process_bulk_actions() {
|
2835 |
-
// Bulk installation process.
|
2836 |
-
if ( 'tgmpa-bulk-install' === $this->current_action() || 'tgmpa-bulk-update' === $this->current_action() ) {
|
2837 |
-
|
2838 |
-
check_admin_referer( 'bulk-' . $this->_args['plural'] );
|
2839 |
-
|
2840 |
-
$install_type = 'install';
|
2841 |
-
if ( 'tgmpa-bulk-update' === $this->current_action() ) {
|
2842 |
-
$install_type = 'update';
|
2843 |
-
}
|
2844 |
-
|
2845 |
-
$plugins_to_install = array();
|
2846 |
-
|
2847 |
-
// Did user actually select any plugins to install/update ?
|
2848 |
-
if ( empty( $_POST['plugin'] ) ) {
|
2849 |
-
if ( 'install' === $install_type ) {
|
2850 |
-
$message = __( 'No plugins were selected to be installed. No action taken.', 'tgmpa' );
|
2851 |
-
} else {
|
2852 |
-
$message = __( 'No plugins were selected to be updated. No action taken.', 'tgmpa' );
|
2853 |
-
}
|
2854 |
-
|
2855 |
-
echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
|
2856 |
-
|
2857 |
-
return false;
|
2858 |
-
}
|
2859 |
-
|
2860 |
-
if ( is_array( $_POST['plugin'] ) ) {
|
2861 |
-
$plugins_to_install = (array) $_POST['plugin'];
|
2862 |
-
} elseif ( is_string( $_POST['plugin'] ) ) {
|
2863 |
-
// Received via Filesystem page - un-flatten array (WP bug #19643).
|
2864 |
-
$plugins_to_install = explode( ',', $_POST['plugin'] );
|
2865 |
-
}
|
2866 |
-
|
2867 |
-
// Sanitize the received input.
|
2868 |
-
$plugins_to_install = array_map( 'urldecode', $plugins_to_install );
|
2869 |
-
$plugins_to_install = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins_to_install );
|
2870 |
-
|
2871 |
-
// Validate the received input.
|
2872 |
-
foreach ( $plugins_to_install as $key => $slug ) {
|
2873 |
-
// Check if the plugin was registered with TGMPA and remove if not.
|
2874 |
-
if ( ! isset( $this->tgmpa->plugins[ $slug ] ) ) {
|
2875 |
-
unset( $plugins_to_install[ $key ] );
|
2876 |
-
continue;
|
2877 |
-
}
|
2878 |
-
|
2879 |
-
// For install: make sure this is a plugin we *can* install and not one already installed.
|
2880 |
-
if ( 'install' === $install_type && true === $this->tgmpa->is_plugin_installed( $slug ) ) {
|
2881 |
-
unset( $plugins_to_install[ $key ] );
|
2882 |
-
}
|
2883 |
-
|
2884 |
-
// For updates: make sure this is a plugin we *can* update (update available and WP version ok).
|
2885 |
-
if ( 'update' === $install_type && false === $this->tgmpa->is_plugin_updatetable( $slug ) ) {
|
2886 |
-
unset( $plugins_to_install[ $key ] );
|
2887 |
-
}
|
2888 |
-
}
|
2889 |
-
|
2890 |
-
// No need to proceed further if we have no plugins to handle.
|
2891 |
-
if ( empty( $plugins_to_install ) ) {
|
2892 |
-
if ( 'install' === $install_type ) {
|
2893 |
-
$message = __( 'No plugins are available to be installed at this time.', 'tgmpa' );
|
2894 |
-
} else {
|
2895 |
-
$message = __( 'No plugins are available to be updated at this time.', 'tgmpa' );
|
2896 |
-
}
|
2897 |
-
|
2898 |
-
echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
|
2899 |
-
|
2900 |
-
return false;
|
2901 |
-
}
|
2902 |
-
|
2903 |
-
// Pass all necessary information if WP_Filesystem is needed.
|
2904 |
-
$url = wp_nonce_url(
|
2905 |
-
$this->tgmpa->get_tgmpa_url(),
|
2906 |
-
'bulk-' . $this->_args['plural']
|
2907 |
-
);
|
2908 |
-
|
2909 |
-
// Give validated data back to $_POST which is the only place the filesystem looks for extra fields.
|
2910 |
-
$_POST['plugin'] = implode( ',', $plugins_to_install ); // Work around for WP bug #19643.
|
2911 |
-
|
2912 |
-
$method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
|
2913 |
-
$fields = array_keys( $_POST ); // Extra fields to pass to WP_Filesystem.
|
2914 |
-
|
2915 |
-
if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, $fields ) ) ) {
|
2916 |
-
return true; // Stop the normal page form from displaying, credential request form will be shown.
|
2917 |
-
}
|
2918 |
-
|
2919 |
-
// Now we have some credentials, setup WP_Filesystem.
|
2920 |
-
if ( ! WP_Filesystem( $creds ) ) {
|
2921 |
-
// Our credentials were no good, ask the user for them again.
|
2922 |
-
request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, $fields );
|
2923 |
-
|
2924 |
-
return true;
|
2925 |
-
}
|
2926 |
-
|
2927 |
-
/* If we arrive here, we have the filesystem */
|
2928 |
-
|
2929 |
-
// Store all information in arrays since we are processing a bulk installation.
|
2930 |
-
$names = array();
|
2931 |
-
$sources = array(); // Needed for installs.
|
2932 |
-
$file_paths = array(); // Needed for upgrades.
|
2933 |
-
$to_inject = array(); // Information to inject into the update_plugins transient.
|
2934 |
-
|
2935 |
-
// Prepare the data for validated plugins for the install/upgrade.
|
2936 |
-
foreach ( $plugins_to_install as $slug ) {
|
2937 |
-
$name = $this->tgmpa->plugins[ $slug ]['name'];
|
2938 |
-
$source = $this->tgmpa->get_download_url( $slug );
|
2939 |
-
|
2940 |
-
if ( ! empty( $name ) && ! empty( $source ) ) {
|
2941 |
-
$names[] = $name;
|
2942 |
-
|
2943 |
-
switch ( $install_type ) {
|
2944 |
-
|
2945 |
-
case 'install':
|
2946 |
-
$sources[] = $source;
|
2947 |
-
break;
|
2948 |
-
|
2949 |
-
case 'update':
|
2950 |
-
$file_paths[] = $this->tgmpa->plugins[ $slug ]['file_path'];
|
2951 |
-
$to_inject[ $slug ] = $this->tgmpa->plugins[ $slug ];
|
2952 |
-
$to_inject[ $slug ]['source'] = $source;
|
2953 |
-
break;
|
2954 |
-
}
|
2955 |
-
}
|
2956 |
-
}
|
2957 |
-
unset( $slug, $name, $source );
|
2958 |
-
|
2959 |
-
// Create a new instance of TGMPA_Bulk_Installer.
|
2960 |
-
$installer = new TGMPA_Bulk_Installer(
|
2961 |
-
new TGMPA_Bulk_Installer_Skin(
|
2962 |
-
array(
|
2963 |
-
'url' => esc_url_raw( $this->tgmpa->get_tgmpa_url() ),
|
2964 |
-
'nonce' => 'bulk-' . $this->_args['plural'],
|
2965 |
-
'names' => $names,
|
2966 |
-
'install_type' => $install_type,
|
2967 |
-
)
|
2968 |
-
)
|
2969 |
-
);
|
2970 |
-
|
2971 |
-
// Wrap the install process with the appropriate HTML.
|
2972 |
-
echo '<div class="tgmpa">',
|
2973 |
-
'<h2 style="font-size: 23px; font-weight: 400; line-height: 29px; margin: 0; padding: 9px 15px 4px 0;">', esc_html( get_admin_page_title() ), '</h2>
|
2974 |
-
<div class="update-php" style="width: 100%; height: 98%; min-height: 850px; padding-top: 1px;">';
|
2975 |
-
|
2976 |
-
// Process the bulk installation submissions.
|
2977 |
-
add_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
|
2978 |
-
|
2979 |
-
if ( 'tgmpa-bulk-update' === $this->current_action() ) {
|
2980 |
-
// Inject our info into the update transient.
|
2981 |
-
$this->tgmpa->inject_update_info( $to_inject );
|
2982 |
-
|
2983 |
-
$installer->bulk_upgrade( $file_paths );
|
2984 |
-
} else {
|
2985 |
-
$installer->bulk_install( $sources );
|
2986 |
-
}
|
2987 |
-
|
2988 |
-
remove_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1 );
|
2989 |
-
|
2990 |
-
echo '</div></div>';
|
2991 |
-
|
2992 |
-
return true;
|
2993 |
-
}
|
2994 |
-
|
2995 |
-
// Bulk activation process.
|
2996 |
-
if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
|
2997 |
-
check_admin_referer( 'bulk-' . $this->_args['plural'] );
|
2998 |
-
|
2999 |
-
// Did user actually select any plugins to activate ?
|
3000 |
-
if ( empty( $_POST['plugin'] ) ) {
|
3001 |
-
echo '<div id="message" class="error"><p>', esc_html__( 'No plugins were selected to be activated. No action taken.', 'tgmpa' ), '</p></div>';
|
3002 |
-
|
3003 |
-
return false;
|
3004 |
-
}
|
3005 |
-
|
3006 |
-
// Grab plugin data from $_POST.
|
3007 |
-
$plugins = array();
|
3008 |
-
if ( isset( $_POST['plugin'] ) ) {
|
3009 |
-
$plugins = array_map( 'urldecode', (array) $_POST['plugin'] );
|
3010 |
-
$plugins = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins );
|
3011 |
-
}
|
3012 |
-
|
3013 |
-
$plugins_to_activate = array();
|
3014 |
-
$plugin_names = array();
|
3015 |
-
|
3016 |
-
// Grab the file paths for the selected & inactive plugins from the registration array.
|
3017 |
-
foreach ( $plugins as $slug ) {
|
3018 |
-
if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
|
3019 |
-
$plugins_to_activate[] = $this->tgmpa->plugins[ $slug ]['file_path'];
|
3020 |
-
$plugin_names[] = $this->tgmpa->plugins[ $slug ]['name'];
|
3021 |
-
}
|
3022 |
-
}
|
3023 |
-
unset( $slug );
|
3024 |
-
|
3025 |
-
// Return early if there are no plugins to activate.
|
3026 |
-
if ( empty( $plugins_to_activate ) ) {
|
3027 |
-
echo '<div id="message" class="error"><p>', esc_html__( 'No plugins are available to be activated at this time.', 'tgmpa' ), '</p></div>';
|
3028 |
-
|
3029 |
-
return false;
|
3030 |
-
}
|
3031 |
-
|
3032 |
-
// Now we are good to go - let's start activating plugins.
|
3033 |
-
$activate = activate_plugins( $plugins_to_activate );
|
3034 |
-
|
3035 |
-
if ( is_wp_error( $activate ) ) {
|
3036 |
-
echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>';
|
3037 |
-
} else {
|
3038 |
-
$count = count( $plugin_names ); // Count so we can use _n function.
|
3039 |
-
$plugin_names = array_map( array( 'TGMPA_Utils', 'wrap_in_strong' ), $plugin_names );
|
3040 |
-
$last_plugin = array_pop( $plugin_names ); // Pop off last name to prep for readability.
|
3041 |
-
$imploded = empty( $plugin_names ) ? $last_plugin : ( implode( ', ', $plugin_names ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
|
3042 |
-
|
3043 |
-
printf( // WPCS: xss ok.
|
3044 |
-
'<div id="message" class="updated"><p>%1$s %2$s.</p></div>',
|
3045 |
-
esc_html( _n( 'The following plugin was activated successfully:', 'The following plugins were activated successfully:', $count, 'tgmpa' ) ),
|
3046 |
-
$imploded
|
3047 |
-
);
|
3048 |
-
|
3049 |
-
// Update recently activated plugins option.
|
3050 |
-
$recent = (array) get_option( 'recently_activated' );
|
3051 |
-
foreach ( $plugins_to_activate as $plugin => $time ) {
|
3052 |
-
if ( isset( $recent[ $plugin ] ) ) {
|
3053 |
-
unset( $recent[ $plugin ] );
|
3054 |
-
}
|
3055 |
-
}
|
3056 |
-
update_option( 'recently_activated', $recent );
|
3057 |
-
}
|
3058 |
-
|
3059 |
-
unset( $_POST ); // Reset the $_POST variable in case user wants to perform one action after another.
|
3060 |
-
|
3061 |
-
return true;
|
3062 |
-
}
|
3063 |
-
|
3064 |
-
return false;
|
3065 |
-
}
|
3066 |
-
|
3067 |
-
/**
|
3068 |
-
* Prepares all of our information to be outputted into a usable table.
|
3069 |
-
*
|
3070 |
-
* @since 2.2.0
|
3071 |
-
*/
|
3072 |
-
public function prepare_items() {
|
3073 |
-
$columns = $this->get_columns(); // Get all necessary column information.
|
3074 |
-
$hidden = array(); // No columns to hide, but we must set as an array.
|
3075 |
-
$sortable = array(); // No reason to make sortable columns.
|
3076 |
-
$primary = $this->get_primary_column_name(); // Column which has the row actions.
|
3077 |
-
$this->_column_headers = array( $columns, $hidden, $sortable, $primary ); // Get all necessary column headers.
|
3078 |
-
|
3079 |
-
// Process our bulk activations here.
|
3080 |
-
if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
|
3081 |
-
$this->process_bulk_actions();
|
3082 |
-
}
|
3083 |
-
|
3084 |
-
// Store all of our plugin data into $items array so WP_List_Table can use it.
|
3085 |
-
$this->items = apply_filters( 'tgmpa_table_data_items', $this->_gather_plugin_data() );
|
3086 |
-
}
|
3087 |
-
|
3088 |
-
/* *********** DEPRECATED METHODS *********** */
|
3089 |
-
|
3090 |
-
/**
|
3091 |
-
* Retrieve plugin data, given the plugin name.
|
3092 |
-
*
|
3093 |
-
* @since 2.2.0
|
3094 |
-
* @deprecated 2.5.0 use {@see TGM_Plugin_Activation::_get_plugin_data_from_name()} instead.
|
3095 |
-
* @see TGM_Plugin_Activation::_get_plugin_data_from_name()
|
3096 |
-
*
|
3097 |
-
* @param string $name Name of the plugin, as it was registered.
|
3098 |
-
* @param string $data Optional. Array key of plugin data to return. Default is slug.
|
3099 |
-
* @return string|boolean Plugin slug if found, false otherwise.
|
3100 |
-
*/
|
3101 |
-
protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
|
3102 |
-
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'TGM_Plugin_Activation::_get_plugin_data_from_name()' );
|
3103 |
-
|
3104 |
-
return $this->tgmpa->_get_plugin_data_from_name( $name, $data );
|
3105 |
-
}
|
3106 |
-
}
|
3107 |
-
}
|
3108 |
-
|
3109 |
-
|
3110 |
-
if ( ! class_exists( 'TGM_Bulk_Installer' ) ) {
|
3111 |
-
|
3112 |
-
/**
|
3113 |
-
* Hack: Prevent TGMPA v2.4.1- bulk installer class from being loaded if 2.4.1- is loaded after 2.5+.
|
3114 |
-
*
|
3115 |
-
* @since 2.5.2
|
3116 |
-
*
|
3117 |
-
* {@internal The TGMPA_Bulk_Installer class was originally called TGM_Bulk_Installer.
|
3118 |
-
* For more information, see that class.}}
|
3119 |
-
*/
|
3120 |
-
class TGM_Bulk_Installer {
|
3121 |
-
}
|
3122 |
-
}
|
3123 |
-
if ( ! class_exists( 'TGM_Bulk_Installer_Skin' ) ) {
|
3124 |
-
|
3125 |
-
/**
|
3126 |
-
* Hack: Prevent TGMPA v2.4.1- bulk installer skin class from being loaded if 2.4.1- is loaded after 2.5+.
|
3127 |
-
*
|
3128 |
-
* @since 2.5.2
|
3129 |
-
*
|
3130 |
-
* {@internal The TGMPA_Bulk_Installer_Skin class was originally called TGM_Bulk_Installer_Skin.
|
3131 |
-
* For more information, see that class.}}
|
3132 |
-
*/
|
3133 |
-
class TGM_Bulk_Installer_Skin {
|
3134 |
-
}
|
3135 |
-
}
|
3136 |
-
|
3137 |
-
/**
|
3138 |
-
* The WP_Upgrader file isn't always available. If it isn't available,
|
3139 |
-
* we load it here.
|
3140 |
-
*
|
3141 |
-
* We check to make sure no action or activation keys are set so that WordPress
|
3142 |
-
* does not try to re-include the class when processing upgrades or installs outside
|
3143 |
-
* of the class.
|
3144 |
-
*
|
3145 |
-
* @since 2.2.0
|
3146 |
-
*/
|
3147 |
-
add_action( 'admin_init', 'tgmpa_load_bulk_installer' );
|
3148 |
-
if ( ! function_exists( 'tgmpa_load_bulk_installer' ) ) {
|
3149 |
-
/**
|
3150 |
-
* Load bulk installer
|
3151 |
-
*/
|
3152 |
-
function tgmpa_load_bulk_installer() {
|
3153 |
-
// Silently fail if 2.5+ is loaded *after* an older version.
|
3154 |
-
if ( ! isset( $GLOBALS['tgmpa'] ) ) {
|
3155 |
-
return;
|
3156 |
-
}
|
3157 |
-
|
3158 |
-
// Get TGMPA class instance.
|
3159 |
-
$tgmpa_instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
3160 |
-
|
3161 |
-
if ( isset( $_GET['page'] ) && $tgmpa_instance->menu === $_GET['page'] ) {
|
3162 |
-
if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
|
3163 |
-
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
3164 |
-
}
|
3165 |
-
|
3166 |
-
if ( ! class_exists( 'TGMPA_Bulk_Installer' ) ) {
|
3167 |
-
|
3168 |
-
/**
|
3169 |
-
* Installer class to handle bulk plugin installations.
|
3170 |
-
*
|
3171 |
-
* Extends WP_Upgrader and customizes to suit the installation of multiple
|
3172 |
-
* plugins.
|
3173 |
-
*
|
3174 |
-
* @since 2.2.0
|
3175 |
-
*
|
3176 |
-
* {@internal Since 2.5.0 the class is an extension of Plugin_Upgrader rather than WP_Upgrader.}}
|
3177 |
-
* {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer to TGMPA_Bulk_Installer.
|
3178 |
-
* This was done to prevent backward compatibility issues with v2.3.6.}}
|
3179 |
-
*
|
3180 |
-
* @package TGM-Plugin-Activation
|
3181 |
-
* @author Thomas Griffin
|
3182 |
-
* @author Gary Jones
|
3183 |
-
*/
|
3184 |
-
class TGMPA_Bulk_Installer extends Plugin_Upgrader {
|
3185 |
-
/**
|
3186 |
-
* Holds result of bulk plugin installation.
|
3187 |
-
*
|
3188 |
-
* @since 2.2.0
|
3189 |
-
*
|
3190 |
-
* @var string
|
3191 |
-
*/
|
3192 |
-
public $result;
|
3193 |
-
|
3194 |
-
/**
|
3195 |
-
* Flag to check if bulk installation is occurring or not.
|
3196 |
-
*
|
3197 |
-
* @since 2.2.0
|
3198 |
-
*
|
3199 |
-
* @var boolean
|
3200 |
-
*/
|
3201 |
-
public $bulk = false;
|
3202 |
-
|
3203 |
-
/**
|
3204 |
-
* TGMPA instance
|
3205 |
-
*
|
3206 |
-
* @since 2.5.0
|
3207 |
-
*
|
3208 |
-
* @var object
|
3209 |
-
*/
|
3210 |
-
protected $tgmpa;
|
3211 |
-
|
3212 |
-
/**
|
3213 |
-
* Whether or not the destination directory needs to be cleared ( = on update).
|
3214 |
-
*
|
3215 |
-
* @since 2.5.0
|
3216 |
-
*
|
3217 |
-
* @var bool
|
3218 |
-
*/
|
3219 |
-
protected $clear_destination = false;
|
3220 |
-
|
3221 |
-
/**
|
3222 |
-
* References parent constructor and sets defaults for class.
|
3223 |
-
*
|
3224 |
-
* @since 2.2.0
|
3225 |
-
*
|
3226 |
-
* @param \Bulk_Upgrader_Skin|null $skin Installer skin.
|
3227 |
-
*/
|
3228 |
-
public function __construct( $skin = null ) {
|
3229 |
-
// Get TGMPA class instance.
|
3230 |
-
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
3231 |
-
|
3232 |
-
parent::__construct( $skin );
|
3233 |
-
|
3234 |
-
if ( isset( $this->skin->options['install_type'] ) && 'update' === $this->skin->options['install_type'] ) {
|
3235 |
-
$this->clear_destination = true;
|
3236 |
-
}
|
3237 |
-
|
3238 |
-
if ( $this->tgmpa->is_automatic ) {
|
3239 |
-
$this->activate_strings();
|
3240 |
-
}
|
3241 |
-
|
3242 |
-
add_action( 'upgrader_process_complete', array( $this->tgmpa, 'populate_file_path' ) );
|
3243 |
-
}
|
3244 |
-
|
3245 |
-
/**
|
3246 |
-
* Sets the correct activation strings for the installer skin to use.
|
3247 |
-
*
|
3248 |
-
* @since 2.2.0
|
3249 |
-
*/
|
3250 |
-
public function activate_strings() {
|
3251 |
-
$this->strings['activation_failed'] = __( 'Plugin activation failed.', 'tgmpa' );
|
3252 |
-
$this->strings['activation_success'] = __( 'Plugin activated successfully.', 'tgmpa' );
|
3253 |
-
}
|
3254 |
-
|
3255 |
-
/**
|
3256 |
-
* Performs the actual installation of each plugin.
|
3257 |
-
*
|
3258 |
-
* @since 2.2.0
|
3259 |
-
*
|
3260 |
-
* @see WP_Upgrader::run()
|
3261 |
-
*
|
3262 |
-
* @param array $options The installation config options.
|
3263 |
-
* @return null|array Return early if error, array of installation data on success.
|
3264 |
-
*/
|
3265 |
-
public function run( $options ) {
|
3266 |
-
$result = parent::run( $options );
|
3267 |
-
|
3268 |
-
// Reset the strings in case we changed one during automatic activation.
|
3269 |
-
if ( $this->tgmpa->is_automatic ) {
|
3270 |
-
if ( 'update' === $this->skin->options['install_type'] ) {
|
3271 |
-
$this->upgrade_strings();
|
3272 |
-
} else {
|
3273 |
-
$this->install_strings();
|
3274 |
-
}
|
3275 |
-
}
|
3276 |
-
|
3277 |
-
return $result;
|
3278 |
-
}
|
3279 |
-
|
3280 |
-
/**
|
3281 |
-
* Processes the bulk installation of plugins.
|
3282 |
-
*
|
3283 |
-
* @since 2.2.0
|
3284 |
-
*
|
3285 |
-
* {@internal This is basically a near identical copy of the WP Core
|
3286 |
-
* Plugin_Upgrader::bulk_upgrade() method, with minor adjustments to deal with
|
3287 |
-
* new installs instead of upgrades.
|
3288 |
-
* For ease of future synchronizations, the adjustments are clearly commented, but no other
|
3289 |
-
* comments are added. Code style has been made to comply.}}
|
3290 |
-
*
|
3291 |
-
* @see Plugin_Upgrader::bulk_upgrade()
|
3292 |
-
* @see https://core.trac.wordpress.org/browser/tags/4.2.1/src/wp-admin/includes/class-wp-upgrader.php#L838
|
3293 |
-
* (@internal Last synced: Dec 31st 2015 against https://core.trac.wordpress.org/browser/trunk?rev=36134}}
|
3294 |
-
*
|
3295 |
-
* @param array $plugins The plugin sources needed for installation.
|
3296 |
-
* @param array $args Arbitrary passed extra arguments.
|
3297 |
-
* @return array|false Install confirmation messages on success, false on failure.
|
3298 |
-
*/
|
3299 |
-
public function bulk_install( $plugins, $args = array() ) {
|
3300 |
-
// [TGMPA + ] Hook auto-activation in.
|
3301 |
-
add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3302 |
-
|
3303 |
-
$defaults = array(
|
3304 |
-
'clear_update_cache' => true,
|
3305 |
-
);
|
3306 |
-
$parsed_args = wp_parse_args( $args, $defaults );
|
3307 |
-
|
3308 |
-
$this->init();
|
3309 |
-
$this->bulk = true;
|
3310 |
-
|
3311 |
-
$this->install_strings(); // [TGMPA + ] adjusted.
|
3312 |
-
|
3313 |
-
/* [TGMPA - ] $current = get_site_transient( 'update_plugins' ); */
|
3314 |
-
|
3315 |
-
/* [TGMPA - ] add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); */
|
3316 |
-
|
3317 |
-
$this->skin->header();
|
3318 |
-
|
3319 |
-
// Connect to the Filesystem first.
|
3320 |
-
$res = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
|
3321 |
-
if ( ! $res ) {
|
3322 |
-
$this->skin->footer();
|
3323 |
-
return false;
|
3324 |
-
}
|
3325 |
-
|
3326 |
-
$this->skin->bulk_header();
|
3327 |
-
|
3328 |
-
/*
|
3329 |
-
* Only start maintenance mode if:
|
3330 |
-
* - running Multisite and there are one or more plugins specified, OR
|
3331 |
-
* - a plugin with an update available is currently active.
|
3332 |
-
* @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
|
3333 |
-
*/
|
3334 |
-
$maintenance = ( is_multisite() && ! empty( $plugins ) );
|
3335 |
-
|
3336 |
-
/*
|
3337 |
-
[TGMPA - ]
|
3338 |
-
foreach ( $plugins as $plugin )
|
3339 |
-
$maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );
|
3340 |
-
*/
|
3341 |
-
if ( $maintenance ) {
|
3342 |
-
$this->maintenance_mode( true );
|
3343 |
-
}
|
3344 |
-
|
3345 |
-
$results = array();
|
3346 |
-
|
3347 |
-
$this->update_count = count( $plugins );
|
3348 |
-
$this->update_current = 0;
|
3349 |
-
foreach ( $plugins as $plugin ) {
|
3350 |
-
$this->update_current++;
|
3351 |
-
|
3352 |
-
/*
|
3353 |
-
[TGMPA - ]
|
3354 |
-
$this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
|
3355 |
-
|
3356 |
-
if ( !isset( $current->response[ $plugin ] ) ) {
|
3357 |
-
$this->skin->set_result('up_to_date');
|
3358 |
-
$this->skin->before();
|
3359 |
-
$this->skin->feedback('up_to_date');
|
3360 |
-
$this->skin->after();
|
3361 |
-
$results[$plugin] = true;
|
3362 |
-
continue;
|
3363 |
-
}
|
3364 |
-
|
3365 |
-
// Get the URL to the zip file.
|
3366 |
-
$r = $current->response[ $plugin ];
|
3367 |
-
|
3368 |
-
$this->skin->plugin_active = is_plugin_active($plugin);
|
3369 |
-
*/
|
3370 |
-
|
3371 |
-
$result = $this->run(
|
3372 |
-
array(
|
3373 |
-
'package' => $plugin, // [TGMPA + ] adjusted.
|
3374 |
-
'destination' => WP_PLUGIN_DIR,
|
3375 |
-
'clear_destination' => false, // [TGMPA + ] adjusted.
|
3376 |
-
'clear_working' => true,
|
3377 |
-
'is_multi' => true,
|
3378 |
-
'hook_extra' => array(
|
3379 |
-
'plugin' => $plugin,
|
3380 |
-
),
|
3381 |
-
)
|
3382 |
-
);
|
3383 |
-
|
3384 |
-
$results[ $plugin ] = $this->result;
|
3385 |
-
|
3386 |
-
// Prevent credentials auth screen from displaying multiple times.
|
3387 |
-
if ( false === $result ) {
|
3388 |
-
break;
|
3389 |
-
}
|
3390 |
-
} //end foreach $plugins
|
3391 |
-
|
3392 |
-
$this->maintenance_mode( false );
|
3393 |
-
|
3394 |
-
/**
|
3395 |
-
* Fires when the bulk upgrader process is complete.
|
3396 |
-
*
|
3397 |
-
* @since WP 3.6.0 / TGMPA 2.5.0
|
3398 |
-
*
|
3399 |
-
* @param Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might
|
3400 |
-
* be a Theme_Upgrader or Core_Upgrade instance.
|
3401 |
-
* @param array $data {
|
3402 |
-
* Array of bulk item update data.
|
3403 |
-
*
|
3404 |
-
* @type string $action Type of action. Default 'update'.
|
3405 |
-
* @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
|
3406 |
-
* @type bool $bulk Whether the update process is a bulk update. Default true.
|
3407 |
-
* @type array $packages Array of plugin, theme, or core packages to update.
|
3408 |
-
* }
|
3409 |
-
*/
|
3410 |
-
do_action( 'upgrader_process_complete', $this, array(
|
3411 |
-
'action' => 'install', // [TGMPA + ] adjusted.
|
3412 |
-
'type' => 'plugin',
|
3413 |
-
'bulk' => true,
|
3414 |
-
'plugins' => $plugins,
|
3415 |
-
) );
|
3416 |
-
|
3417 |
-
$this->skin->bulk_footer();
|
3418 |
-
|
3419 |
-
$this->skin->footer();
|
3420 |
-
|
3421 |
-
// Cleanup our hooks, in case something else does a upgrade on this connection.
|
3422 |
-
/* [TGMPA - ] remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); */
|
3423 |
-
|
3424 |
-
// [TGMPA + ] Remove our auto-activation hook.
|
3425 |
-
remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3426 |
-
|
3427 |
-
// Force refresh of plugin update information.
|
3428 |
-
wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
|
3429 |
-
|
3430 |
-
return $results;
|
3431 |
-
}
|
3432 |
-
|
3433 |
-
/**
|
3434 |
-
* Handle a bulk upgrade request.
|
3435 |
-
*
|
3436 |
-
* @since 2.5.0
|
3437 |
-
*
|
3438 |
-
* @see Plugin_Upgrader::bulk_upgrade()
|
3439 |
-
*
|
3440 |
-
* @param array $plugins The local WP file_path's of the plugins which should be upgraded.
|
3441 |
-
* @param array $args Arbitrary passed extra arguments.
|
3442 |
-
* @return string|bool Install confirmation messages on success, false on failure.
|
3443 |
-
*/
|
3444 |
-
public function bulk_upgrade( $plugins, $args = array() ) {
|
3445 |
-
|
3446 |
-
add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3447 |
-
|
3448 |
-
$result = parent::bulk_upgrade( $plugins, $args );
|
3449 |
-
|
3450 |
-
remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3451 |
-
|
3452 |
-
return $result;
|
3453 |
-
}
|
3454 |
-
|
3455 |
-
/**
|
3456 |
-
* Abuse a filter to auto-activate plugins after installation.
|
3457 |
-
*
|
3458 |
-
* Hooked into the 'upgrader_post_install' filter hook.
|
3459 |
-
*
|
3460 |
-
* @since 2.5.0
|
3461 |
-
*
|
3462 |
-
* @param bool $bool The value we need to give back (true).
|
3463 |
-
* @return bool
|
3464 |
-
*/
|
3465 |
-
public function auto_activate( $bool ) {
|
3466 |
-
// Only process the activation of installed plugins if the automatic flag is set to true.
|
3467 |
-
if ( $this->tgmpa->is_automatic ) {
|
3468 |
-
// Flush plugins cache so the headers of the newly installed plugins will be read correctly.
|
3469 |
-
wp_clean_plugins_cache();
|
3470 |
-
|
3471 |
-
// Get the installed plugin file.
|
3472 |
-
$plugin_info = $this->plugin_info();
|
3473 |
-
|
3474 |
-
// Don't try to activate on upgrade of active plugin as WP will do this already.
|
3475 |
-
if ( ! is_plugin_active( $plugin_info ) ) {
|
3476 |
-
$activate = activate_plugin( $plugin_info );
|
3477 |
-
|
3478 |
-
// Adjust the success string based on the activation result.
|
3479 |
-
$this->strings['process_success'] = $this->strings['process_success'] . "<br />\n";
|
3480 |
-
|
3481 |
-
if ( is_wp_error( $activate ) ) {
|
3482 |
-
$this->skin->error( $activate );
|
3483 |
-
$this->strings['process_success'] .= $this->strings['activation_failed'];
|
3484 |
-
} else {
|
3485 |
-
$this->strings['process_success'] .= $this->strings['activation_success'];
|
3486 |
-
}
|
3487 |
-
}
|
3488 |
-
}
|
3489 |
-
|
3490 |
-
return $bool;
|
3491 |
-
}
|
3492 |
-
}
|
3493 |
-
}
|
3494 |
-
|
3495 |
-
if ( ! class_exists( 'TGMPA_Bulk_Installer_Skin' ) ) {
|
3496 |
-
|
3497 |
-
/**
|
3498 |
-
* Installer skin to set strings for the bulk plugin installations..
|
3499 |
-
*
|
3500 |
-
* Extends Bulk_Upgrader_Skin and customizes to suit the installation of multiple
|
3501 |
-
* plugins.
|
3502 |
-
*
|
3503 |
-
* @since 2.2.0
|
3504 |
-
*
|
3505 |
-
* {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer_Skin to
|
3506 |
-
* TGMPA_Bulk_Installer_Skin.
|
3507 |
-
* This was done to prevent backward compatibility issues with v2.3.6.}}
|
3508 |
-
*
|
3509 |
-
* @see https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/class-wp-upgrader-skins.php
|
3510 |
-
*
|
3511 |
-
* @package TGM-Plugin-Activation
|
3512 |
-
* @author Thomas Griffin
|
3513 |
-
* @author Gary Jones
|
3514 |
-
*/
|
3515 |
-
class TGMPA_Bulk_Installer_Skin extends Bulk_Upgrader_Skin {
|
3516 |
-
/**
|
3517 |
-
* Holds plugin info for each individual plugin installation.
|
3518 |
-
*
|
3519 |
-
* @since 2.2.0
|
3520 |
-
*
|
3521 |
-
* @var array
|
3522 |
-
*/
|
3523 |
-
public $plugin_info = array();
|
3524 |
-
|
3525 |
-
/**
|
3526 |
-
* Holds names of plugins that are undergoing bulk installations.
|
3527 |
-
*
|
3528 |
-
* @since 2.2.0
|
3529 |
-
*
|
3530 |
-
* @var array
|
3531 |
-
*/
|
3532 |
-
public $plugin_names = array();
|
3533 |
-
|
3534 |
-
/**
|
3535 |
-
* Integer to use for iteration through each plugin installation.
|
3536 |
-
*
|
3537 |
-
* @since 2.2.0
|
3538 |
-
*
|
3539 |
-
* @var integer
|
3540 |
-
*/
|
3541 |
-
public $i = 0;
|
3542 |
-
|
3543 |
-
/**
|
3544 |
-
* TGMPA instance
|
3545 |
-
*
|
3546 |
-
* @since 2.5.0
|
3547 |
-
*
|
3548 |
-
* @var object
|
3549 |
-
*/
|
3550 |
-
protected $tgmpa;
|
3551 |
-
|
3552 |
-
/**
|
3553 |
-
* Constructor. Parses default args with new ones and extracts them for use.
|
3554 |
-
*
|
3555 |
-
* @since 2.2.0
|
3556 |
-
*
|
3557 |
-
* @param array $args Arguments to pass for use within the class.
|
3558 |
-
*/
|
3559 |
-
public function __construct( $args = array() ) {
|
3560 |
-
// Get TGMPA class instance.
|
3561 |
-
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
3562 |
-
|
3563 |
-
// Parse default and new args.
|
3564 |
-
$defaults = array(
|
3565 |
-
'url' => '',
|
3566 |
-
'nonce' => '',
|
3567 |
-
'names' => array(),
|
3568 |
-
'install_type' => 'install',
|
3569 |
-
);
|
3570 |
-
$args = wp_parse_args( $args, $defaults );
|
3571 |
-
|
3572 |
-
// Set plugin names to $this->plugin_names property.
|
3573 |
-
$this->plugin_names = $args['names'];
|
3574 |
-
|
3575 |
-
// Extract the new args.
|
3576 |
-
parent::__construct( $args );
|
3577 |
-
}
|
3578 |
-
|
3579 |
-
/**
|
3580 |
-
* Sets install skin strings for each individual plugin.
|
3581 |
-
*
|
3582 |
-
* Checks to see if the automatic activation flag is set and uses the
|
3583 |
-
* the proper strings accordingly.
|
3584 |
-
*
|
3585 |
-
* @since 2.2.0
|
3586 |
-
*/
|
3587 |
-
public function add_strings() {
|
3588 |
-
if ( 'update' === $this->options['install_type'] ) {
|
3589 |
-
parent::add_strings();
|
3590 |
-
/* translators: 1: plugin name, 2: action number 3: total number of actions. */
|
3591 |
-
$this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
|
3592 |
-
} else {
|
3593 |
-
/* translators: 1: plugin name, 2: error message. */
|
3594 |
-
$this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while installing %1$s: <strong>%2$s</strong>.', 'tgmpa' );
|
3595 |
-
/* translators: 1: plugin name. */
|
3596 |
-
$this->upgrader->strings['skin_update_failed'] = __( 'The installation of %1$s failed.', 'tgmpa' );
|
3597 |
-
|
3598 |
-
if ( $this->tgmpa->is_automatic ) {
|
3599 |
-
// Automatic activation strings.
|
3600 |
-
$this->upgrader->strings['skin_upgrade_start'] = __( 'The installation and activation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
|
3601 |
-
/* translators: 1: plugin name. */
|
3602 |
-
$this->upgrader->strings['skin_update_successful'] = __( '%1$s installed and activated successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
|
3603 |
-
$this->upgrader->strings['skin_upgrade_end'] = __( 'All installations and activations have been completed.', 'tgmpa' );
|
3604 |
-
/* translators: 1: plugin name, 2: action number 3: total number of actions. */
|
3605 |
-
$this->upgrader->strings['skin_before_update_header'] = __( 'Installing and Activating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
|
3606 |
-
} else {
|
3607 |
-
// Default installation strings.
|
3608 |
-
$this->upgrader->strings['skin_upgrade_start'] = __( 'The installation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
|
3609 |
-
/* translators: 1: plugin name. */
|
3610 |
-
$this->upgrader->strings['skin_update_successful'] = esc_html__( '%1$s installed successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
|
3611 |
-
$this->upgrader->strings['skin_upgrade_end'] = __( 'All installations have been completed.', 'tgmpa' );
|
3612 |
-
/* translators: 1: plugin name, 2: action number 3: total number of actions. */
|
3613 |
-
$this->upgrader->strings['skin_before_update_header'] = __( 'Installing Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
|
3614 |
-
}
|
3615 |
-
}
|
3616 |
-
}
|
3617 |
-
|
3618 |
-
/**
|
3619 |
-
* Outputs the header strings and necessary JS before each plugin installation.
|
3620 |
-
*
|
3621 |
-
* @since 2.2.0
|
3622 |
-
*
|
3623 |
-
* @param string $title Unused in this implementation.
|
3624 |
-
*/
|
3625 |
-
public function before( $title = '' ) {
|
3626 |
-
if ( empty( $title ) ) {
|
3627 |
-
$title = esc_html( $this->plugin_names[ $this->i ] );
|
3628 |
-
}
|
3629 |
-
parent::before( $title );
|
3630 |
-
}
|
3631 |
-
|
3632 |
-
/**
|
3633 |
-
* Outputs the footer strings and necessary JS after each plugin installation.
|
3634 |
-
*
|
3635 |
-
* Checks for any errors and outputs them if they exist, else output
|
3636 |
-
* success strings.
|
3637 |
-
*
|
3638 |
-
* @since 2.2.0
|
3639 |
-
*
|
3640 |
-
* @param string $title Unused in this implementation.
|
3641 |
-
*/
|
3642 |
-
public function after( $title = '' ) {
|
3643 |
-
if ( empty( $title ) ) {
|
3644 |
-
$title = esc_html( $this->plugin_names[ $this->i ] );
|
3645 |
-
}
|
3646 |
-
parent::after( $title );
|
3647 |
-
|
3648 |
-
$this->i++;
|
3649 |
-
}
|
3650 |
-
|
3651 |
-
/**
|
3652 |
-
* Outputs links after bulk plugin installation is complete.
|
3653 |
-
*
|
3654 |
-
* @since 2.2.0
|
3655 |
-
*/
|
3656 |
-
public function bulk_footer() {
|
3657 |
-
// Serve up the string to say installations (and possibly activations) are complete.
|
3658 |
-
parent::bulk_footer();
|
3659 |
-
|
3660 |
-
// Flush plugins cache so we can make sure that the installed plugins list is always up to date.
|
3661 |
-
wp_clean_plugins_cache();
|
3662 |
-
|
3663 |
-
$this->tgmpa->show_tgmpa_version();
|
3664 |
-
|
3665 |
-
// Display message based on if all plugins are now active or not.
|
3666 |
-
$update_actions = array();
|
3667 |
-
|
3668 |
-
if ( $this->tgmpa->is_tgmpa_complete() ) {
|
3669 |
-
// All plugins are active, so we display the complete string and hide the menu to protect users.
|
3670 |
-
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
|
3671 |
-
$update_actions['dashboard'] = sprintf(
|
3672 |
-
esc_html( $this->tgmpa->strings['complete'] ),
|
3673 |
-
'<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>'
|
3674 |
-
);
|
3675 |
-
} else {
|
3676 |
-
$update_actions['tgmpa_page'] = '<a href="' . esc_url( $this->tgmpa->get_tgmpa_url() ) . '" target="_parent">' . esc_html( $this->tgmpa->strings['return'] ) . '</a>';
|
3677 |
-
}
|
3678 |
-
|
3679 |
-
/**
|
3680 |
-
* Filter the list of action links available following bulk plugin installs/updates.
|
3681 |
-
*
|
3682 |
-
* @since 2.5.0
|
3683 |
-
*
|
3684 |
-
* @param array $update_actions Array of plugin action links.
|
3685 |
-
* @param array $plugin_info Array of information for the last-handled plugin.
|
3686 |
-
*/
|
3687 |
-
$update_actions = apply_filters( 'tgmpa_update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );
|
3688 |
-
|
3689 |
-
if ( ! empty( $update_actions ) ) {
|
3690 |
-
$this->feedback( implode( ' | ', (array) $update_actions ) );
|
3691 |
-
}
|
3692 |
-
}
|
3693 |
-
|
3694 |
-
/* *********** DEPRECATED METHODS *********** */
|
3695 |
-
|
3696 |
-
/**
|
3697 |
-
* Flush header output buffer.
|
3698 |
-
*
|
3699 |
-
* @since 2.2.0
|
3700 |
-
* @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
|
3701 |
-
* @see Bulk_Upgrader_Skin::flush_output()
|
3702 |
-
*/
|
3703 |
-
public function before_flush_output() {
|
3704 |
-
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
|
3705 |
-
$this->flush_output();
|
3706 |
-
}
|
3707 |
-
|
3708 |
-
/**
|
3709 |
-
* Flush footer output buffer and iterate $this->i to make sure the
|
3710 |
-
* installation strings reference the correct plugin.
|
3711 |
-
*
|
3712 |
-
* @since 2.2.0
|
3713 |
-
* @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
|
3714 |
-
* @see Bulk_Upgrader_Skin::flush_output()
|
3715 |
-
*/
|
3716 |
-
public function after_flush_output() {
|
3717 |
-
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
|
3718 |
-
$this->flush_output();
|
3719 |
-
$this->i++;
|
3720 |
-
}
|
3721 |
-
}
|
3722 |
-
}
|
3723 |
-
}
|
3724 |
-
}
|
3725 |
-
}
|
3726 |
-
|
3727 |
-
if ( ! class_exists( 'TGMPA_Utils' ) ) {
|
3728 |
-
|
3729 |
-
/**
|
3730 |
-
* Generic utilities for TGMPA.
|
3731 |
-
*
|
3732 |
-
* All methods are static, poor-dev name-spacing class wrapper.
|
3733 |
-
*
|
3734 |
-
* Class was called TGM_Utils in 2.5.0 but renamed TGMPA_Utils in 2.5.1 as this was conflicting with Soliloquy.
|
3735 |
-
*
|
3736 |
-
* @since 2.5.0
|
3737 |
-
*
|
3738 |
-
* @package TGM-Plugin-Activation
|
3739 |
-
* @author Juliette Reinders Folmer
|
3740 |
-
*/
|
3741 |
-
class TGMPA_Utils {
|
3742 |
-
/**
|
3743 |
-
* Whether the PHP filter extension is enabled.
|
3744 |
-
*
|
3745 |
-
* @see http://php.net/book.filter
|
3746 |
-
*
|
3747 |
-
* @since 2.5.0
|
3748 |
-
*
|
3749 |
-
* @static
|
3750 |
-
*
|
3751 |
-
* @var bool $has_filters True is the extension is enabled.
|
3752 |
-
*/
|
3753 |
-
public static $has_filters;
|
3754 |
-
|
3755 |
-
/**
|
3756 |
-
* Wrap an arbitrary string in <em> tags. Meant to be used in combination with array_map().
|
3757 |
-
*
|
3758 |
-
* @since 2.5.0
|
3759 |
-
*
|
3760 |
-
* @static
|
3761 |
-
*
|
3762 |
-
* @param string $string Text to be wrapped.
|
3763 |
-
* @return string
|
3764 |
-
*/
|
3765 |
-
public static function wrap_in_em( $string ) {
|
3766 |
-
return '<em>' . wp_kses_post( $string ) . '</em>';
|
3767 |
-
}
|
3768 |
-
|
3769 |
-
/**
|
3770 |
-
* Wrap an arbitrary string in <strong> tags. Meant to be used in combination with array_map().
|
3771 |
-
*
|
3772 |
-
* @since 2.5.0
|
3773 |
-
*
|
3774 |
-
* @static
|
3775 |
-
*
|
3776 |
-
* @param string $string Text to be wrapped.
|
3777 |
-
* @return string
|
3778 |
-
*/
|
3779 |
-
public static function wrap_in_strong( $string ) {
|
3780 |
-
return '<strong>' . wp_kses_post( $string ) . '</strong>';
|
3781 |
-
}
|
3782 |
-
|
3783 |
-
/**
|
3784 |
-
* Helper function: Validate a value as boolean
|
3785 |
-
*
|
3786 |
-
* @since 2.5.0
|
3787 |
-
*
|
3788 |
-
* @static
|
3789 |
-
*
|
3790 |
-
* @param mixed $value Arbitrary value.
|
3791 |
-
* @return bool
|
3792 |
-
*/
|
3793 |
-
public static function validate_bool( $value ) {
|
3794 |
-
if ( ! isset( self::$has_filters ) ) {
|
3795 |
-
self::$has_filters = extension_loaded( 'filter' );
|
3796 |
-
}
|
3797 |
-
|
3798 |
-
if ( self::$has_filters ) {
|
3799 |
-
return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
|
3800 |
-
} else {
|
3801 |
-
return self::emulate_filter_bool( $value );
|
3802 |
-
}
|
3803 |
-
}
|
3804 |
-
|
3805 |
-
/**
|
3806 |
-
* Helper function: Cast a value to bool
|
3807 |
-
*
|
3808 |
-
* @since 2.5.0
|
3809 |
-
*
|
3810 |
-
* @static
|
3811 |
-
*
|
3812 |
-
* @param mixed $value Value to cast.
|
3813 |
-
* @return bool
|
3814 |
-
*/
|
3815 |
-
protected static function emulate_filter_bool( $value ) {
|
3816 |
-
// @codingStandardsIgnoreStart
|
3817 |
-
static $true = array(
|
3818 |
-
'1',
|
3819 |
-
'true', 'True', 'TRUE',
|
3820 |
-
'y', 'Y',
|
3821 |
-
'yes', 'Yes', 'YES',
|
3822 |
-
'on', 'On', 'ON',
|
3823 |
-
);
|
3824 |
-
static $false = array(
|
3825 |
-
'0',
|
3826 |
-
'false', 'False', 'FALSE',
|
3827 |
-
'n', 'N',
|
3828 |
-
'no', 'No', 'NO',
|
3829 |
-
'off', 'Off', 'OFF',
|
3830 |
-
);
|
3831 |
-
// @codingStandardsIgnoreEnd
|
3832 |
-
|
3833 |
-
if ( is_bool( $value ) ) {
|
3834 |
-
return $value;
|
3835 |
-
} elseif ( is_int( $value ) && ( 0 === $value || 1 === $value ) ) {
|
3836 |
-
return (bool) $value;
|
3837 |
-
} elseif ( ( is_float( $value ) && ! is_nan( $value ) ) && ( (float) 0 === $value || (float) 1 === $value ) ) {
|
3838 |
-
return (bool) $value;
|
3839 |
-
} elseif ( is_string( $value ) ) {
|
3840 |
-
$value = trim( $value );
|
3841 |
-
if ( in_array( $value, $true, true ) ) {
|
3842 |
-
return true;
|
3843 |
-
} elseif ( in_array( $value, $false, true ) ) {
|
3844 |
-
return false;
|
3845 |
-
} else {
|
3846 |
-
return false;
|
3847 |
-
}
|
3848 |
-
}
|
3849 |
-
|
3850 |
-
return false;
|
3851 |
-
}
|
3852 |
-
} // End of class TGMPA_Utils
|
3853 |
-
} // End of class_exists wrapper
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Plugin installation and activation for WordPress themes.
|
4 |
+
*
|
5 |
+
* Please note that this is a drop-in library for a theme or plugin.
|
6 |
+
* The authors of this library (Thomas, Gary and Juliette) are NOT responsible
|
7 |
+
* for the support of your plugin or theme. Please contact the plugin
|
8 |
+
* or theme author for support.
|
9 |
+
*
|
10 |
+
* @package TGM-Plugin-Activation
|
11 |
+
* @version 2.6.1
|
12 |
+
* @link http://tgmpluginactivation.com/
|
13 |
+
* @author Thomas Griffin, Gary Jones, Juliette Reinders Folmer
|
14 |
+
* @copyright Copyright (c) 2011, Thomas Griffin
|
15 |
+
* @license GPL-2.0+
|
16 |
+
*/
|
17 |
+
|
18 |
+
/*
|
19 |
+
Copyright 2011 Thomas Griffin (thomasgriffinmedia.com)
|
20 |
+
|
21 |
+
This program is free software; you can redistribute it and/or modify
|
22 |
+
it under the terms of the GNU General Public License, version 2, as
|
23 |
+
published by the Free Software Foundation.
|
24 |
+
|
25 |
+
This program is distributed in the hope that it will be useful,
|
26 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
27 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
28 |
+
GNU General Public License for more details.
|
29 |
+
|
30 |
+
You should have received a copy of the GNU General Public License
|
31 |
+
along with this program; if not, write to the Free Software
|
32 |
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
33 |
+
*/
|
34 |
+
|
35 |
+
if ( ! class_exists( 'TGM_Plugin_Activation' ) ) {
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Automatic plugin installation and activation library.
|
39 |
+
*
|
40 |
+
* Creates a way to automatically install and activate plugins from within themes.
|
41 |
+
* The plugins can be either bundled, downloaded from the WordPress
|
42 |
+
* Plugin Repository or downloaded from another external source.
|
43 |
+
*
|
44 |
+
* @since 1.0.0
|
45 |
+
*
|
46 |
+
* @package TGM-Plugin-Activation
|
47 |
+
* @author Thomas Griffin
|
48 |
+
* @author Gary Jones
|
49 |
+
*/
|
50 |
+
class TGM_Plugin_Activation {
|
51 |
+
/**
|
52 |
+
* TGMPA version number.
|
53 |
+
*
|
54 |
+
* @since 2.5.0
|
55 |
+
*
|
56 |
+
* @const string Version number.
|
57 |
+
*/
|
58 |
+
const TGMPA_VERSION = '2.6.1';
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Regular expression to test if a URL is a WP plugin repo URL.
|
62 |
+
*
|
63 |
+
* @const string Regex.
|
64 |
+
*
|
65 |
+
* @since 2.5.0
|
66 |
+
*/
|
67 |
+
const WP_REPO_REGEX = '|^http[s]?://wordpress\.org/(?:extend/)?plugins/|';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Arbitrary regular expression to test if a string starts with a URL.
|
71 |
+
*
|
72 |
+
* @const string Regex.
|
73 |
+
*
|
74 |
+
* @since 2.5.0
|
75 |
+
*/
|
76 |
+
const IS_URL_REGEX = '|^http[s]?://|';
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Holds a copy of itself, so it can be referenced by the class name.
|
80 |
+
*
|
81 |
+
* @since 1.0.0
|
82 |
+
*
|
83 |
+
* @var TGM_Plugin_Activation
|
84 |
+
*/
|
85 |
+
public static $instance;
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Holds arrays of plugin details.
|
89 |
+
*
|
90 |
+
* @since 1.0.0
|
91 |
+
* @since 2.5.0 the array has the plugin slug as an associative key.
|
92 |
+
*
|
93 |
+
* @var array
|
94 |
+
*/
|
95 |
+
public $plugins = array();
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Holds arrays of plugin names to use to sort the plugins array.
|
99 |
+
*
|
100 |
+
* @since 2.5.0
|
101 |
+
*
|
102 |
+
* @var array
|
103 |
+
*/
|
104 |
+
protected $sort_order = array();
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Whether any plugins have the 'force_activation' setting set to true.
|
108 |
+
*
|
109 |
+
* @since 2.5.0
|
110 |
+
*
|
111 |
+
* @var bool
|
112 |
+
*/
|
113 |
+
protected $has_forced_activation = false;
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Whether any plugins have the 'force_deactivation' setting set to true.
|
117 |
+
*
|
118 |
+
* @since 2.5.0
|
119 |
+
*
|
120 |
+
* @var bool
|
121 |
+
*/
|
122 |
+
protected $has_forced_deactivation = false;
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Name of the unique ID to hash notices.
|
126 |
+
*
|
127 |
+
* @since 2.4.0
|
128 |
+
*
|
129 |
+
* @var string
|
130 |
+
*/
|
131 |
+
public $id = 'tgmpa';
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Name of the query-string argument for the admin page.
|
135 |
+
*
|
136 |
+
* @since 1.0.0
|
137 |
+
*
|
138 |
+
* @var string
|
139 |
+
*/
|
140 |
+
protected $menu = 'tgmpa-install-plugins';
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Parent menu file slug.
|
144 |
+
*
|
145 |
+
* @since 2.5.0
|
146 |
+
*
|
147 |
+
* @var string
|
148 |
+
*/
|
149 |
+
public $parent_slug = 'themes.php';
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Capability needed to view the plugin installation menu item.
|
153 |
+
*
|
154 |
+
* @since 2.5.0
|
155 |
+
*
|
156 |
+
* @var string
|
157 |
+
*/
|
158 |
+
public $capability = 'edit_theme_options';
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Default absolute path to folder containing bundled plugin zip files.
|
162 |
+
*
|
163 |
+
* @since 2.0.0
|
164 |
+
*
|
165 |
+
* @var string Absolute path prefix to zip file location for bundled plugins. Default is empty string.
|
166 |
+
*/
|
167 |
+
public $default_path = '';
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Flag to show admin notices or not.
|
171 |
+
*
|
172 |
+
* @since 2.1.0
|
173 |
+
*
|
174 |
+
* @var boolean
|
175 |
+
*/
|
176 |
+
public $has_notices = true;
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Flag to determine if the user can dismiss the notice nag.
|
180 |
+
*
|
181 |
+
* @since 2.4.0
|
182 |
+
*
|
183 |
+
* @var boolean
|
184 |
+
*/
|
185 |
+
public $dismissable = true;
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Message to be output above nag notice if dismissable is false.
|
189 |
+
*
|
190 |
+
* @since 2.4.0
|
191 |
+
*
|
192 |
+
* @var string
|
193 |
+
*/
|
194 |
+
public $dismiss_msg = '';
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Flag to set automatic activation of plugins. Off by default.
|
198 |
+
*
|
199 |
+
* @since 2.2.0
|
200 |
+
*
|
201 |
+
* @var boolean
|
202 |
+
*/
|
203 |
+
public $is_automatic = false;
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Optional message to display before the plugins table.
|
207 |
+
*
|
208 |
+
* @since 2.2.0
|
209 |
+
*
|
210 |
+
* @var string Message filtered by wp_kses_post(). Default is empty string.
|
211 |
+
*/
|
212 |
+
public $message = '';
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Holds configurable array of strings.
|
216 |
+
*
|
217 |
+
* Default values are added in the constructor.
|
218 |
+
*
|
219 |
+
* @since 2.0.0
|
220 |
+
*
|
221 |
+
* @var array
|
222 |
+
*/
|
223 |
+
public $strings = array();
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Holds the version of WordPress.
|
227 |
+
*
|
228 |
+
* @since 2.4.0
|
229 |
+
*
|
230 |
+
* @var int
|
231 |
+
*/
|
232 |
+
public $wp_version;
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Holds the hook name for the admin page.
|
236 |
+
*
|
237 |
+
* @since 2.5.0
|
238 |
+
*
|
239 |
+
* @var string
|
240 |
+
*/
|
241 |
+
public $page_hook;
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Adds a reference of this object to $instance, populates default strings,
|
245 |
+
* does the tgmpa_init action hook, and hooks in the interactions to init.
|
246 |
+
*
|
247 |
+
* {@internal This method should be `protected`, but as too many TGMPA implementations
|
248 |
+
* haven't upgraded beyond v2.3.6 yet, this gives backward compatibility issues.
|
249 |
+
* Reverted back to public for the time being.}}
|
250 |
+
*
|
251 |
+
* @since 1.0.0
|
252 |
+
*
|
253 |
+
* @see TGM_Plugin_Activation::init()
|
254 |
+
*/
|
255 |
+
public function __construct() {
|
256 |
+
// Set the current WordPress version.
|
257 |
+
$this->wp_version = $GLOBALS['wp_version'];
|
258 |
+
|
259 |
+
// Announce that the class is ready, and pass the object (for advanced use).
|
260 |
+
do_action_ref_array( 'tgmpa_init', array( $this ) );
|
261 |
+
|
262 |
+
/*
|
263 |
+
* Load our text domain and allow for overloading the fall-back file.
|
264 |
+
*
|
265 |
+
* {@internal IMPORTANT! If this code changes, review the regex in the custom TGMPA
|
266 |
+
* generator on the website.}}
|
267 |
+
*/
|
268 |
+
add_action( 'init', array( $this, 'load_textdomain' ), 5 );
|
269 |
+
add_filter( 'load_textdomain_mofile', array( $this, 'overload_textdomain_mofile' ), 10, 2 );
|
270 |
+
|
271 |
+
// When the rest of WP has loaded, kick-start the rest of the class.
|
272 |
+
add_action( 'init', array( $this, 'init' ) );
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Magic method to (not) set protected properties from outside of this class.
|
277 |
+
*
|
278 |
+
* {@internal hackedihack... There is a serious bug in v2.3.2 - 2.3.6 where the `menu` property
|
279 |
+
* is being assigned rather than tested in a conditional, effectively rendering it useless.
|
280 |
+
* This 'hack' prevents this from happening.}}
|
281 |
+
*
|
282 |
+
* @see https://github.com/TGMPA/TGM-Plugin-Activation/blob/2.3.6/tgm-plugin-activation/class-tgm-plugin-activation.php#L1593
|
283 |
+
*
|
284 |
+
* @since 2.5.2
|
285 |
+
*
|
286 |
+
* @param string $name Name of an inaccessible property.
|
287 |
+
* @param mixed $value Value to assign to the property.
|
288 |
+
* @return void Silently fail to set the property when this is tried from outside of this class context.
|
289 |
+
* (Inside this class context, the __set() method if not used as there is direct access.)
|
290 |
+
*/
|
291 |
+
public function __set( $name, $value ) {
|
292 |
+
return;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Magic method to get the value of a protected property outside of this class context.
|
297 |
+
*
|
298 |
+
* @since 2.5.2
|
299 |
+
*
|
300 |
+
* @param string $name Name of an inaccessible property.
|
301 |
+
* @return mixed The property value.
|
302 |
+
*/
|
303 |
+
public function __get( $name ) {
|
304 |
+
return $this->{$name};
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Initialise the interactions between this class and WordPress.
|
309 |
+
*
|
310 |
+
* Hooks in three new methods for the class: admin_menu, notices and styles.
|
311 |
+
*
|
312 |
+
* @since 2.0.0
|
313 |
+
*
|
314 |
+
* @see TGM_Plugin_Activation::admin_menu()
|
315 |
+
* @see TGM_Plugin_Activation::notices()
|
316 |
+
* @see TGM_Plugin_Activation::styles()
|
317 |
+
*/
|
318 |
+
public function init() {
|
319 |
+
/**
|
320 |
+
* By default TGMPA only loads on the WP back-end and not in an Ajax call. Using this filter
|
321 |
+
* you can overrule that behaviour.
|
322 |
+
*
|
323 |
+
* @since 2.5.0
|
324 |
+
*
|
325 |
+
* @param bool $load Whether or not TGMPA should load.
|
326 |
+
* Defaults to the return of `is_admin() && ! defined( 'DOING_AJAX' )`.
|
327 |
+
*/
|
328 |
+
if ( true !== apply_filters( 'tgmpa_load', ( is_admin() && ! defined( 'DOING_AJAX' ) ) ) ) {
|
329 |
+
return;
|
330 |
+
}
|
331 |
+
|
332 |
+
// Load class strings.
|
333 |
+
$this->strings = array(
|
334 |
+
'page_title' => __( 'Install Required Plugins', 'tgmpa' ),
|
335 |
+
'menu_title' => __( 'Install Plugins', 'tgmpa' ),
|
336 |
+
/* translators: %s: plugin name. */
|
337 |
+
'installing' => __( 'Installing Plugin: %s', 'tgmpa' ),
|
338 |
+
/* translators: %s: plugin name. */
|
339 |
+
'updating' => __( 'Updating Plugin: %s', 'tgmpa' ),
|
340 |
+
'oops' => __( 'Something went wrong with the plugin API.', 'tgmpa' ),
|
341 |
+
'notice_can_install_required' => _n_noop(
|
342 |
+
/* translators: 1: plugin name(s). */
|
343 |
+
'This theme requires the following plugin: %1$s.',
|
344 |
+
'This theme requires the following plugins: %1$s.',
|
345 |
+
'tgmpa'
|
346 |
+
),
|
347 |
+
'notice_can_install_recommended' => _n_noop(
|
348 |
+
/* translators: 1: plugin name(s). */
|
349 |
+
'This theme recommends the following plugin: %1$s.',
|
350 |
+
'This theme recommends the following plugins: %1$s.',
|
351 |
+
'tgmpa'
|
352 |
+
),
|
353 |
+
'notice_ask_to_update' => _n_noop(
|
354 |
+
/* translators: 1: plugin name(s). */
|
355 |
+
'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.',
|
356 |
+
'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.',
|
357 |
+
'tgmpa'
|
358 |
+
),
|
359 |
+
'notice_ask_to_update_maybe' => _n_noop(
|
360 |
+
/* translators: 1: plugin name(s). */
|
361 |
+
'There is an update available for: %1$s.',
|
362 |
+
'There are updates available for the following plugins: %1$s.',
|
363 |
+
'tgmpa'
|
364 |
+
),
|
365 |
+
'notice_can_activate_required' => _n_noop(
|
366 |
+
/* translators: 1: plugin name(s). */
|
367 |
+
'The following required plugin is currently inactive: %1$s.',
|
368 |
+
'The following required plugins are currently inactive: %1$s.',
|
369 |
+
'tgmpa'
|
370 |
+
),
|
371 |
+
'notice_can_activate_recommended' => _n_noop(
|
372 |
+
/* translators: 1: plugin name(s). */
|
373 |
+
'The following recommended plugin is currently inactive: %1$s.',
|
374 |
+
'The following recommended plugins are currently inactive: %1$s.',
|
375 |
+
'tgmpa'
|
376 |
+
),
|
377 |
+
'install_link' => _n_noop(
|
378 |
+
'Begin installing plugin',
|
379 |
+
'Begin installing plugins',
|
380 |
+
'tgmpa'
|
381 |
+
),
|
382 |
+
'update_link' => _n_noop(
|
383 |
+
'Begin updating plugin',
|
384 |
+
'Begin updating plugins',
|
385 |
+
'tgmpa'
|
386 |
+
),
|
387 |
+
'activate_link' => _n_noop(
|
388 |
+
'Begin activating plugin',
|
389 |
+
'Begin activating plugins',
|
390 |
+
'tgmpa'
|
391 |
+
),
|
392 |
+
'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ),
|
393 |
+
'dashboard' => __( 'Return to the Dashboard', 'tgmpa' ),
|
394 |
+
'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ),
|
395 |
+
'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ),
|
396 |
+
/* translators: 1: plugin name. */
|
397 |
+
'plugin_already_active' => __( 'No action taken. Plugin %1$s was already active.', 'tgmpa' ),
|
398 |
+
/* translators: 1: plugin name. */
|
399 |
+
'plugin_needs_higher_version' => __( 'Plugin not activated. A higher version of %s is needed for this theme. Please update the plugin.', 'tgmpa' ),
|
400 |
+
/* translators: 1: dashboard link. */
|
401 |
+
'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ),
|
402 |
+
'dismiss' => __( 'Dismiss this notice', 'tgmpa' ),
|
403 |
+
'notice_cannot_install_activate' => __( 'There are one or more required or recommended plugins to install, update or activate.', 'tgmpa' ),
|
404 |
+
'contact_admin' => __( 'Please contact the administrator of this site for help.', 'tgmpa' ),
|
405 |
+
);
|
406 |
+
|
407 |
+
do_action( 'tgmpa_register' );
|
408 |
+
|
409 |
+
/* After this point, the plugins should be registered and the configuration set. */
|
410 |
+
|
411 |
+
// Proceed only if we have plugins to handle.
|
412 |
+
if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) {
|
413 |
+
return;
|
414 |
+
}
|
415 |
+
|
416 |
+
// Set up the menu and notices if we still have outstanding actions.
|
417 |
+
if ( true !== $this->is_tgmpa_complete() ) {
|
418 |
+
// Sort the plugins.
|
419 |
+
array_multisort( $this->sort_order, SORT_ASC, $this->plugins );
|
420 |
+
|
421 |
+
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
422 |
+
add_action( 'admin_head', array( $this, 'dismiss' ) );
|
423 |
+
|
424 |
+
// Prevent the normal links from showing underneath a single install/update page.
|
425 |
+
add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) );
|
426 |
+
add_filter( 'update_plugin_complete_actions', array( $this, 'actions' ) );
|
427 |
+
|
428 |
+
if ( $this->has_notices ) {
|
429 |
+
add_action( 'admin_notices', array( $this, 'notices' ) );
|
430 |
+
add_action( 'admin_init', array( $this, 'admin_init' ), 1 );
|
431 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) );
|
432 |
+
}
|
433 |
+
}
|
434 |
+
|
435 |
+
// If needed, filter plugin action links.
|
436 |
+
add_action( 'load-plugins.php', array( $this, 'add_plugin_action_link_filters' ), 1 );
|
437 |
+
|
438 |
+
// Make sure things get reset on switch theme.
|
439 |
+
add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) );
|
440 |
+
|
441 |
+
if ( $this->has_notices ) {
|
442 |
+
add_action( 'switch_theme', array( $this, 'update_dismiss' ) );
|
443 |
+
}
|
444 |
+
|
445 |
+
// Setup the force activation hook.
|
446 |
+
if ( true === $this->has_forced_activation ) {
|
447 |
+
add_action( 'admin_init', array( $this, 'force_activation' ) );
|
448 |
+
}
|
449 |
+
|
450 |
+
// Setup the force deactivation hook.
|
451 |
+
if ( true === $this->has_forced_deactivation ) {
|
452 |
+
add_action( 'switch_theme', array( $this, 'force_deactivation' ) );
|
453 |
+
}
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Load translations.
|
458 |
+
*
|
459 |
+
* @since 2.6.0
|
460 |
+
*
|
461 |
+
* (@internal Uses `load_theme_textdomain()` rather than `load_plugin_textdomain()` to
|
462 |
+
* get round the different ways of handling the path and deprecated notices being thrown
|
463 |
+
* and such. For plugins, the actual file name will be corrected by a filter.}}
|
464 |
+
*
|
465 |
+
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
466 |
+
* generator on the website.}}
|
467 |
+
*/
|
468 |
+
public function load_textdomain() {
|
469 |
+
if ( is_textdomain_loaded( 'tgmpa' ) ) {
|
470 |
+
return;
|
471 |
+
}
|
472 |
+
|
473 |
+
if ( false !== strpos( __FILE__, WP_PLUGIN_DIR ) || false !== strpos( __FILE__, WPMU_PLUGIN_DIR ) ) {
|
474 |
+
// Plugin, we'll need to adjust the file name.
|
475 |
+
add_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10, 2 );
|
476 |
+
load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' );
|
477 |
+
remove_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10 );
|
478 |
+
} else {
|
479 |
+
load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' );
|
480 |
+
}
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* Correct the .mo file name for (must-use) plugins.
|
485 |
+
*
|
486 |
+
* Themese use `/path/{locale}.mo` while plugins use `/path/{text-domain}-{locale}.mo`.
|
487 |
+
*
|
488 |
+
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
489 |
+
* generator on the website.}}
|
490 |
+
*
|
491 |
+
* @since 2.6.0
|
492 |
+
*
|
493 |
+
* @param string $mofile Full path to the target mofile.
|
494 |
+
* @param string $domain The domain for which a language file is being loaded.
|
495 |
+
* @return string $mofile
|
496 |
+
*/
|
497 |
+
public function correct_plugin_mofile( $mofile, $domain ) {
|
498 |
+
// Exit early if not our domain (just in case).
|
499 |
+
if ( 'tgmpa' !== $domain ) {
|
500 |
+
return $mofile;
|
501 |
+
}
|
502 |
+
return preg_replace( '`/([a-z]{2}_[A-Z]{2}.mo)$`', '/tgmpa-$1', $mofile );
|
503 |
+
}
|
504 |
+
|
505 |
+
/**
|
506 |
+
* Potentially overload the fall-back translation file for the current language.
|
507 |
+
*
|
508 |
+
* WP, by default since WP 3.7, will load a local translation first and if none
|
509 |
+
* can be found, will try and find a translation in the /wp-content/languages/ directory.
|
510 |
+
* As this library is theme/plugin agnostic, translation files for TGMPA can exist both
|
511 |
+
* in the WP_LANG_DIR /plugins/ subdirectory as well as in the /themes/ subdirectory.
|
512 |
+
*
|
513 |
+
* This method makes sure both directories are checked.
|
514 |
+
*
|
515 |
+
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
516 |
+
* generator on the website.}}
|
517 |
+
*
|
518 |
+
* @since 2.6.0
|
519 |
+
*
|
520 |
+
* @param string $mofile Full path to the target mofile.
|
521 |
+
* @param string $domain The domain for which a language file is being loaded.
|
522 |
+
* @return string $mofile
|
523 |
+
*/
|
524 |
+
public function overload_textdomain_mofile( $mofile, $domain ) {
|
525 |
+
// Exit early if not our domain, not a WP_LANG_DIR load or if the file exists and is readable.
|
526 |
+
if ( 'tgmpa' !== $domain || false === strpos( $mofile, WP_LANG_DIR ) || @is_readable( $mofile ) ) {
|
527 |
+
return $mofile;
|
528 |
+
}
|
529 |
+
|
530 |
+
// Current fallback file is not valid, let's try the alternative option.
|
531 |
+
if ( false !== strpos( $mofile, '/themes/' ) ) {
|
532 |
+
return str_replace( '/themes/', '/plugins/', $mofile );
|
533 |
+
} elseif ( false !== strpos( $mofile, '/plugins/' ) ) {
|
534 |
+
return str_replace( '/plugins/', '/themes/', $mofile );
|
535 |
+
} else {
|
536 |
+
return $mofile;
|
537 |
+
}
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Hook in plugin action link filters for the WP native plugins page.
|
542 |
+
*
|
543 |
+
* - Prevent activation of plugins which don't meet the minimum version requirements.
|
544 |
+
* - Prevent deactivation of force-activated plugins.
|
545 |
+
* - Add update notice if update available.
|
546 |
+
*
|
547 |
+
* @since 2.5.0
|
548 |
+
*/
|
549 |
+
public function add_plugin_action_link_filters() {
|
550 |
+
foreach ( $this->plugins as $slug => $plugin ) {
|
551 |
+
if ( false === $this->can_plugin_activate( $slug ) ) {
|
552 |
+
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_activate' ), 20 );
|
553 |
+
}
|
554 |
+
|
555 |
+
if ( true === $plugin['force_activation'] ) {
|
556 |
+
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_deactivate' ), 20 );
|
557 |
+
}
|
558 |
+
|
559 |
+
if ( false !== $this->does_plugin_require_update( $slug ) ) {
|
560 |
+
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_update' ), 20 );
|
561 |
+
}
|
562 |
+
}
|
563 |
+
}
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Remove the 'Activate' link on the WP native plugins page if the plugin does not meet the
|
567 |
+
* minimum version requirements.
|
568 |
+
*
|
569 |
+
* @since 2.5.0
|
570 |
+
*
|
571 |
+
* @param array $actions Action links.
|
572 |
+
* @return array
|
573 |
+
*/
|
574 |
+
public function filter_plugin_action_links_activate( $actions ) {
|
575 |
+
unset( $actions['activate'] );
|
576 |
+
|
577 |
+
return $actions;
|
578 |
+
}
|
579 |
+
|
580 |
+
/**
|
581 |
+
* Remove the 'Deactivate' link on the WP native plugins page if the plugin has been set to force activate.
|
582 |
+
*
|
583 |
+
* @since 2.5.0
|
584 |
+
*
|
585 |
+
* @param array $actions Action links.
|
586 |
+
* @return array
|
587 |
+
*/
|
588 |
+
public function filter_plugin_action_links_deactivate( $actions ) {
|
589 |
+
unset( $actions['deactivate'] );
|
590 |
+
|
591 |
+
return $actions;
|
592 |
+
}
|
593 |
+
|
594 |
+
/**
|
595 |
+
* Add a 'Requires update' link on the WP native plugins page if the plugin does not meet the
|
596 |
+
* minimum version requirements.
|
597 |
+
*
|
598 |
+
* @since 2.5.0
|
599 |
+
*
|
600 |
+
* @param array $actions Action links.
|
601 |
+
* @return array
|
602 |
+
*/
|
603 |
+
public function filter_plugin_action_links_update( $actions ) {
|
604 |
+
$actions['update'] = sprintf(
|
605 |
+
'<a href="%1$s" title="%2$s" class="edit">%3$s</a>',
|
606 |
+
esc_url( $this->get_tgmpa_status_url( 'update' ) ),
|
607 |
+
esc_attr__( 'This plugin needs to be updated to be compatible with your theme.', 'tgmpa' ),
|
608 |
+
esc_html__( 'Update Required', 'tgmpa' )
|
609 |
+
);
|
610 |
+
|
611 |
+
return $actions;
|
612 |
+
}
|
613 |
+
|
614 |
+
/**
|
615 |
+
* Handles calls to show plugin information via links in the notices.
|
616 |
+
*
|
617 |
+
* We get the links in the admin notices to point to the TGMPA page, rather
|
618 |
+
* than the typical plugin-install.php file, so we can prepare everything
|
619 |
+
* beforehand.
|
620 |
+
*
|
621 |
+
* WP does not make it easy to show the plugin information in the thickbox -
|
622 |
+
* here we have to require a file that includes a function that does the
|
623 |
+
* main work of displaying it, enqueue some styles, set up some globals and
|
624 |
+
* finally call that function before exiting.
|
625 |
+
*
|
626 |
+
* Down right easy once you know how...
|
627 |
+
*
|
628 |
+
* Returns early if not the TGMPA page.
|
629 |
+
*
|
630 |
+
* @since 2.1.0
|
631 |
+
*
|
632 |
+
* @global string $tab Used as iframe div class names, helps with styling
|
633 |
+
* @global string $body_id Used as the iframe body ID, helps with styling
|
634 |
+
*
|
635 |
+
* @return null Returns early if not the TGMPA page.
|
636 |
+
*/
|
637 |
+
public function admin_init() {
|
638 |
+
if ( ! $this->is_tgmpa_page() ) {
|
639 |
+
return;
|
640 |
+
}
|
641 |
+
|
642 |
+
if ( isset( $_REQUEST['tab'] ) && 'plugin-information' === $_REQUEST['tab'] ) {
|
643 |
+
// Needed for install_plugin_information().
|
644 |
+
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
|
645 |
+
|
646 |
+
wp_enqueue_style( 'plugin-install' );
|
647 |
+
|
648 |
+
global $tab, $body_id;
|
649 |
+
$body_id = 'plugin-information';
|
650 |
+
// @codingStandardsIgnoreStart
|
651 |
+
$tab = 'plugin-information';
|
652 |
+
// @codingStandardsIgnoreEnd
|
653 |
+
|
654 |
+
install_plugin_information();
|
655 |
+
|
656 |
+
exit;
|
657 |
+
}
|
658 |
+
}
|
659 |
+
|
660 |
+
/**
|
661 |
+
* Enqueue thickbox scripts/styles for plugin info.
|
662 |
+
*
|
663 |
+
* Thickbox is not automatically included on all admin pages, so we must
|
664 |
+
* manually enqueue it for those pages.
|
665 |
+
*
|
666 |
+
* Thickbox is only loaded if the user has not dismissed the admin
|
667 |
+
* notice or if there are any plugins left to install and activate.
|
668 |
+
*
|
669 |
+
* @since 2.1.0
|
670 |
+
*/
|
671 |
+
public function thickbox() {
|
672 |
+
if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) {
|
673 |
+
add_thickbox();
|
674 |
+
}
|
675 |
+
}
|
676 |
+
|
677 |
+
/**
|
678 |
+
* Adds submenu page if there are plugin actions to take.
|
679 |
+
*
|
680 |
+
* This method adds the submenu page letting users know that a required
|
681 |
+
* plugin needs to be installed.
|
682 |
+
*
|
683 |
+
* This page disappears once the plugin has been installed and activated.
|
684 |
+
*
|
685 |
+
* @since 1.0.0
|
686 |
+
*
|
687 |
+
* @see TGM_Plugin_Activation::init()
|
688 |
+
* @see TGM_Plugin_Activation::install_plugins_page()
|
689 |
+
*
|
690 |
+
* @return null Return early if user lacks capability to install a plugin.
|
691 |
+
*/
|
692 |
+
public function admin_menu() {
|
693 |
+
// Make sure privileges are correct to see the page.
|
694 |
+
if ( ! current_user_can( 'install_plugins' ) ) {
|
695 |
+
return;
|
696 |
+
}
|
697 |
+
|
698 |
+
$args = apply_filters(
|
699 |
+
'tgmpa_admin_menu_args',
|
700 |
+
array(
|
701 |
+
'parent_slug' => $this->parent_slug, // Parent Menu slug.
|
702 |
+
'page_title' => $this->strings['page_title'], // Page title.
|
703 |
+
'menu_title' => $this->strings['menu_title'], // Menu title.
|
704 |
+
'capability' => $this->capability, // Capability.
|
705 |
+
'menu_slug' => $this->menu, // Menu slug.
|
706 |
+
'function' => array( $this, 'install_plugins_page' ), // Callback.
|
707 |
+
)
|
708 |
+
);
|
709 |
+
|
710 |
+
$this->add_admin_menu( $args );
|
711 |
+
}
|
712 |
+
|
713 |
+
/**
|
714 |
+
* Add the menu item.
|
715 |
+
*
|
716 |
+
* {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
|
717 |
+
* generator on the website.}}
|
718 |
+
*
|
719 |
+
* @since 2.5.0
|
720 |
+
*
|
721 |
+
* @param array $args Menu item configuration.
|
722 |
+
*/
|
723 |
+
protected function add_admin_menu( array $args ) {
|
724 |
+
if ( has_filter( 'tgmpa_admin_menu_use_add_theme_page' ) ) {
|
725 |
+
_deprecated_function( 'The "tgmpa_admin_menu_use_add_theme_page" filter', '2.5.0', esc_html__( 'Set the parent_slug config variable instead.', 'tgmpa' ) );
|
726 |
+
}
|
727 |
+
|
728 |
+
if ( 'themes.php' === $this->parent_slug ) {
|
729 |
+
$this->page_hook = call_user_func( 'add_theme_page', $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
|
730 |
+
} else {
|
731 |
+
$this->page_hook = call_user_func( 'add_submenu_page', $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
|
732 |
+
}
|
733 |
+
}
|
734 |
+
|
735 |
+
/**
|
736 |
+
* Echoes plugin installation form.
|
737 |
+
*
|
738 |
+
* This method is the callback for the admin_menu method function.
|
739 |
+
* This displays the admin page and form area where the user can select to install and activate the plugin.
|
740 |
+
* Aborts early if we're processing a plugin installation action.
|
741 |
+
*
|
742 |
+
* @since 1.0.0
|
743 |
+
*
|
744 |
+
* @return null Aborts early if we're processing a plugin installation action.
|
745 |
+
*/
|
746 |
+
public function install_plugins_page() {
|
747 |
+
// Store new instance of plugin table in object.
|
748 |
+
$plugin_table = new TGMPA_List_Table;
|
749 |
+
|
750 |
+
// Return early if processing a plugin installation action.
|
751 |
+
if ( ( ( 'tgmpa-bulk-install' === $plugin_table->current_action() || 'tgmpa-bulk-update' === $plugin_table->current_action() ) && $plugin_table->process_bulk_actions() ) || $this->do_plugin_install() ) {
|
752 |
+
return;
|
753 |
+
}
|
754 |
+
|
755 |
+
// Force refresh of available plugin information so we'll know about manual updates/deletes.
|
756 |
+
wp_clean_plugins_cache( false );
|
757 |
+
|
758 |
+
?>
|
759 |
+
<div class="tgmpa wrap">
|
760 |
+
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
761 |
+
<?php $plugin_table->prepare_items(); ?>
|
762 |
+
|
763 |
+
<?php
|
764 |
+
if ( ! empty( $this->message ) && is_string( $this->message ) ) {
|
765 |
+
echo wp_kses_post( $this->message );
|
766 |
+
}
|
767 |
+
?>
|
768 |
+
<?php $plugin_table->views(); ?>
|
769 |
+
|
770 |
+
<form id="tgmpa-plugins" action="" method="post">
|
771 |
+
<input type="hidden" name="tgmpa-page" value="<?php echo esc_attr( $this->menu ); ?>" />
|
772 |
+
<input type="hidden" name="plugin_status" value="<?php echo esc_attr( $plugin_table->view_context ); ?>" />
|
773 |
+
<?php $plugin_table->display(); ?>
|
774 |
+
</form>
|
775 |
+
</div>
|
776 |
+
<?php
|
777 |
+
}
|
778 |
+
|
779 |
+
/**
|
780 |
+
* Installs, updates or activates a plugin depending on the action link clicked by the user.
|
781 |
+
*
|
782 |
+
* Checks the $_GET variable to see which actions have been
|
783 |
+
* passed and responds with the appropriate method.
|
784 |
+
*
|
785 |
+
* Uses WP_Filesystem to process and handle the plugin installation
|
786 |
+
* method.
|
787 |
+
*
|
788 |
+
* @since 1.0.0
|
789 |
+
*
|
790 |
+
* @uses WP_Filesystem
|
791 |
+
* @uses WP_Error
|
792 |
+
* @uses WP_Upgrader
|
793 |
+
* @uses Plugin_Upgrader
|
794 |
+
* @uses Plugin_Installer_Skin
|
795 |
+
* @uses Plugin_Upgrader_Skin
|
796 |
+
*
|
797 |
+
* @return boolean True on success, false on failure.
|
798 |
+
*/
|
799 |
+
protected function do_plugin_install() {
|
800 |
+
if ( empty( $_GET['plugin'] ) ) {
|
801 |
+
return false;
|
802 |
+
}
|
803 |
+
|
804 |
+
// All plugin information will be stored in an array for processing.
|
805 |
+
$slug = $this->sanitize_key( urldecode( $_GET['plugin'] ) );
|
806 |
+
|
807 |
+
if ( ! isset( $this->plugins[ $slug ] ) ) {
|
808 |
+
return false;
|
809 |
+
}
|
810 |
+
|
811 |
+
// Was an install or upgrade action link clicked?
|
812 |
+
if ( ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' === $_GET['tgmpa-install'] ) || ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) ) {
|
813 |
+
|
814 |
+
$install_type = 'install';
|
815 |
+
if ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) {
|
816 |
+
$install_type = 'update';
|
817 |
+
}
|
818 |
+
|
819 |
+
check_admin_referer( 'tgmpa-' . $install_type, 'tgmpa-nonce' );
|
820 |
+
|
821 |
+
// Pass necessary information via URL if WP_Filesystem is needed.
|
822 |
+
$url = wp_nonce_url(
|
823 |
+
add_query_arg(
|
824 |
+
array(
|
825 |
+
'plugin' => urlencode( $slug ),
|
826 |
+
'tgmpa-' . $install_type => $install_type . '-plugin',
|
827 |
+
),
|
828 |
+
$this->get_tgmpa_url()
|
829 |
+
),
|
830 |
+
'tgmpa-' . $install_type,
|
831 |
+
'tgmpa-nonce'
|
832 |
+
);
|
833 |
+
|
834 |
+
$method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
|
835 |
+
|
836 |
+
if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, array() ) ) ) {
|
837 |
+
return true;
|
838 |
+
}
|
839 |
+
|
840 |
+
if ( ! WP_Filesystem( $creds ) ) {
|
841 |
+
request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, array() ); // Setup WP_Filesystem.
|
842 |
+
return true;
|
843 |
+
}
|
844 |
+
|
845 |
+
/* If we arrive here, we have the filesystem. */
|
846 |
+
|
847 |
+
// Prep variables for Plugin_Installer_Skin class.
|
848 |
+
$extra = array();
|
849 |
+
$extra['slug'] = $slug; // Needed for potentially renaming of directory name.
|
850 |
+
$source = $this->get_download_url( $slug );
|
851 |
+
$api = ( 'repo' === $this->plugins[ $slug ]['source_type'] ) ? $this->get_plugins_api( $slug ) : null;
|
852 |
+
$api = ( false !== $api ) ? $api : null;
|
853 |
+
|
854 |
+
$url = add_query_arg(
|
855 |
+
array(
|
856 |
+
'action' => $install_type . '-plugin',
|
857 |
+
'plugin' => urlencode( $slug ),
|
858 |
+
),
|
859 |
+
'update.php'
|
860 |
+
);
|
861 |
+
|
862 |
+
if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
|
863 |
+
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
864 |
+
}
|
865 |
+
|
866 |
+
$title = ( 'update' === $install_type ) ? $this->strings['updating'] : $this->strings['installing'];
|
867 |
+
$skin_args = array(
|
868 |
+
'type' => ( 'bundled' !== $this->plugins[ $slug ]['source_type'] ) ? 'web' : 'upload',
|
869 |
+
'title' => sprintf( $title, $this->plugins[ $slug ]['name'] ),
|
870 |
+
'url' => esc_url_raw( $url ),
|
871 |
+
'nonce' => $install_type . '-plugin_' . $slug,
|
872 |
+
'plugin' => '',
|
873 |
+
'api' => $api,
|
874 |
+
'extra' => $extra,
|
875 |
+
);
|
876 |
+
unset( $title );
|
877 |
+
|
878 |
+
if ( 'update' === $install_type ) {
|
879 |
+
$skin_args['plugin'] = $this->plugins[ $slug ]['file_path'];
|
880 |
+
$skin = new Plugin_Upgrader_Skin( $skin_args );
|
881 |
+
} else {
|
882 |
+
$skin = new Plugin_Installer_Skin( $skin_args );
|
883 |
+
}
|
884 |
+
|
885 |
+
// Create a new instance of Plugin_Upgrader.
|
886 |
+
$upgrader = new Plugin_Upgrader( $skin );
|
887 |
+
|
888 |
+
// Perform the action and install the plugin from the $source urldecode().
|
889 |
+
add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
|
890 |
+
|
891 |
+
if ( 'update' === $install_type ) {
|
892 |
+
// Inject our info into the update transient.
|
893 |
+
$to_inject = array( $slug => $this->plugins[ $slug ] );
|
894 |
+
$to_inject[ $slug ]['source'] = $source;
|
895 |
+
$this->inject_update_info( $to_inject );
|
896 |
+
|
897 |
+
$upgrader->upgrade( $this->plugins[ $slug ]['file_path'] );
|
898 |
+
} else {
|
899 |
+
$upgrader->install( $source );
|
900 |
+
}
|
901 |
+
|
902 |
+
remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1 );
|
903 |
+
|
904 |
+
// Make sure we have the correct file path now the plugin is installed/updated.
|
905 |
+
$this->populate_file_path( $slug );
|
906 |
+
|
907 |
+
// Only activate plugins if the config option is set to true and the plugin isn't
|
908 |
+
// already active (upgrade).
|
909 |
+
if ( $this->is_automatic && ! $this->is_plugin_active( $slug ) ) {
|
910 |
+
$plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method.
|
911 |
+
if ( false === $this->activate_single_plugin( $plugin_activate, $slug, true ) ) {
|
912 |
+
return true; // Finish execution of the function early as we encountered an error.
|
913 |
+
}
|
914 |
+
}
|
915 |
+
|
916 |
+
$this->show_tgmpa_version();
|
917 |
+
|
918 |
+
// Display message based on if all plugins are now active or not.
|
919 |
+
if ( $this->is_tgmpa_complete() ) {
|
920 |
+
echo '<p>', sprintf( esc_html( $this->strings['complete'] ), '<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>' ), '</p>';
|
921 |
+
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
|
922 |
+
} else {
|
923 |
+
echo '<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
|
924 |
+
}
|
925 |
+
|
926 |
+
return true;
|
927 |
+
} elseif ( isset( $this->plugins[ $slug ]['file_path'], $_GET['tgmpa-activate'] ) && 'activate-plugin' === $_GET['tgmpa-activate'] ) {
|
928 |
+
// Activate action link was clicked.
|
929 |
+
check_admin_referer( 'tgmpa-activate', 'tgmpa-nonce' );
|
930 |
+
|
931 |
+
if ( false === $this->activate_single_plugin( $this->plugins[ $slug ]['file_path'], $slug ) ) {
|
932 |
+
return true; // Finish execution of the function early as we encountered an error.
|
933 |
+
}
|
934 |
+
}
|
935 |
+
|
936 |
+
return false;
|
937 |
+
}
|
938 |
+
|
939 |
+
/**
|
940 |
+
* Inject information into the 'update_plugins' site transient as WP checks that before running an update.
|
941 |
+
*
|
942 |
+
* @since 2.5.0
|
943 |
+
*
|
944 |
+
* @param array $plugins The plugin information for the plugins which are to be updated.
|
945 |
+
*/
|
946 |
+
public function inject_update_info( $plugins ) {
|
947 |
+
$repo_updates = get_site_transient( 'update_plugins' );
|
948 |
+
|
949 |
+
if ( ! is_object( $repo_updates ) ) {
|
950 |
+
$repo_updates = new stdClass;
|
951 |
+
}
|
952 |
+
|
953 |
+
foreach ( $plugins as $slug => $plugin ) {
|
954 |
+
$file_path = $plugin['file_path'];
|
955 |
+
|
956 |
+
if ( empty( $repo_updates->response[ $file_path ] ) ) {
|
957 |
+
$repo_updates->response[ $file_path ] = new stdClass;
|
958 |
+
}
|
959 |
+
|
960 |
+
// We only really need to set package, but let's do all we can in case WP changes something.
|
961 |
+
$repo_updates->response[ $file_path ]->slug = $slug;
|
962 |
+
$repo_updates->response[ $file_path ]->plugin = $file_path;
|
963 |
+
$repo_updates->response[ $file_path ]->new_version = $plugin['version'];
|
964 |
+
$repo_updates->response[ $file_path ]->package = $plugin['source'];
|
965 |
+
if ( empty( $repo_updates->response[ $file_path ]->url ) && ! empty( $plugin['external_url'] ) ) {
|
966 |
+
$repo_updates->response[ $file_path ]->url = $plugin['external_url'];
|
967 |
+
}
|
968 |
+
}
|
969 |
+
|
970 |
+
set_site_transient( 'update_plugins', $repo_updates );
|
971 |
+
}
|
972 |
+
|
973 |
+
/**
|
974 |
+
* Adjust the plugin directory name if necessary.
|
975 |
+
*
|
976 |
+
* The final destination directory of a plugin is based on the subdirectory name found in the
|
977 |
+
* (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this
|
978 |
+
* subdirectory name is not the same as the expected slug and the plugin will not be recognized
|
979 |
+
* as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to
|
980 |
+
* the expected plugin slug.
|
981 |
+
*
|
982 |
+
* @since 2.5.0
|
983 |
+
*
|
984 |
+
* @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/.
|
985 |
+
* @param string $remote_source Path to upgrade/zip-file-name.tmp.
|
986 |
+
* @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin.
|
987 |
+
* @return string $source
|
988 |
+
*/
|
989 |
+
public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) {
|
990 |
+
if ( ! $this->is_tgmpa_page() || ! is_object( $GLOBALS['wp_filesystem'] ) ) {
|
991 |
+
return $source;
|
992 |
+
}
|
993 |
+
|
994 |
+
// Check for single file plugins.
|
995 |
+
$source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) );
|
996 |
+
if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) {
|
997 |
+
return $source;
|
998 |
+
}
|
999 |
+
|
1000 |
+
// Multi-file plugin, let's see if the directory is correctly named.
|
1001 |
+
$desired_slug = '';
|
1002 |
+
|
1003 |
+
// Figure out what the slug is supposed to be.
|
1004 |
+
if ( false === $upgrader->bulk && ! empty( $upgrader->skin->options['extra']['slug'] ) ) {
|
1005 |
+
$desired_slug = $upgrader->skin->options['extra']['slug'];
|
1006 |
+
} else {
|
1007 |
+
// Bulk installer contains less info, so fall back on the info registered here.
|
1008 |
+
foreach ( $this->plugins as $slug => $plugin ) {
|
1009 |
+
if ( ! empty( $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) && $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) {
|
1010 |
+
$desired_slug = $slug;
|
1011 |
+
break;
|
1012 |
+
}
|
1013 |
+
}
|
1014 |
+
unset( $slug, $plugin );
|
1015 |
+
}
|
1016 |
+
|
1017 |
+
if ( ! empty( $desired_slug ) ) {
|
1018 |
+
$subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) );
|
1019 |
+
|
1020 |
+
if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) {
|
1021 |
+
$from_path = untrailingslashit( $source );
|
1022 |
+
$to_path = trailingslashit( $remote_source ) . $desired_slug;
|
1023 |
+
|
1024 |
+
if ( true === $GLOBALS['wp_filesystem']->move( $from_path, $to_path ) ) {
|
1025 |
+
return trailingslashit( $to_path );
|
1026 |
+
} else {
|
1027 |
+
return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
|
1028 |
+
}
|
1029 |
+
} elseif ( empty( $subdir_name ) ) {
|
1030 |
+
return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
|
1031 |
+
}
|
1032 |
+
}
|
1033 |
+
|
1034 |
+
return $source;
|
1035 |
+
}
|
1036 |
+
|
1037 |
+
/**
|
1038 |
+
* Activate a single plugin and send feedback about the result to the screen.
|
1039 |
+
*
|
1040 |
+
* @since 2.5.0
|
1041 |
+
*
|
1042 |
+
* @param string $file_path Path within wp-plugins/ to main plugin file.
|
1043 |
+
* @param string $slug Plugin slug.
|
1044 |
+
* @param bool $automatic Whether this is an automatic activation after an install. Defaults to false.
|
1045 |
+
* This determines the styling of the output messages.
|
1046 |
+
* @return bool False if an error was encountered, true otherwise.
|
1047 |
+
*/
|
1048 |
+
protected function activate_single_plugin( $file_path, $slug, $automatic = false ) {
|
1049 |
+
if ( $this->can_plugin_activate( $slug ) ) {
|
1050 |
+
$activate = activate_plugin( $file_path );
|
1051 |
+
|
1052 |
+
if ( is_wp_error( $activate ) ) {
|
1053 |
+
echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>',
|
1054 |
+
'<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
|
1055 |
+
|
1056 |
+
return false; // End it here if there is an error with activation.
|
1057 |
+
} else {
|
1058 |
+
if ( ! $automatic ) {
|
1059 |
+
// Make sure message doesn't display again if bulk activation is performed
|
1060 |
+
// immediately after a single activation.
|
1061 |
+
if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
|
1062 |
+
echo '<div id="message" class="updated"><p>', esc_html( $this->strings['activated_successfully'] ), ' <strong>', esc_html( $this->plugins[ $slug ]['name'] ), '.</strong></p></div>';
|
1063 |
+
}
|
1064 |
+
} else {
|
1065 |
+
// Simpler message layout for use on the plugin install page.
|
1066 |
+
echo '<p>', esc_html( $this->strings['plugin_activated'] ), '</p>';
|
1067 |
+
}
|
1068 |
+
}
|
1069 |
+
} elseif ( $this->is_plugin_active( $slug ) ) {
|
1070 |
+
// No simpler message format provided as this message should never be encountered
|
1071 |
+
// on the plugin install page.
|
1072 |
+
echo '<div id="message" class="error"><p>',
|
1073 |
+
sprintf(
|
1074 |
+
esc_html( $this->strings['plugin_already_active'] ),
|
1075 |
+
'<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
|
1076 |
+
),
|
1077 |
+
'</p></div>';
|
1078 |
+
} elseif ( $this->does_plugin_require_update( $slug ) ) {
|
1079 |
+
if ( ! $automatic ) {
|
1080 |
+
// Make sure message doesn't display again if bulk activation is performed
|
1081 |
+
// immediately after a single activation.
|
1082 |
+
if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
|
1083 |
+
echo '<div id="message" class="error"><p>',
|
1084 |
+
sprintf(
|
1085 |
+
esc_html( $this->strings['plugin_needs_higher_version'] ),
|
1086 |
+
'<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
|
1087 |
+
),
|
1088 |
+
'</p></div>';
|
1089 |
+
}
|
1090 |
+
} else {
|
1091 |
+
// Simpler message layout for use on the plugin install page.
|
1092 |
+
echo '<p>', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), esc_html( $this->plugins[ $slug ]['name'] ) ), '</p>';
|
1093 |
+
}
|
1094 |
+
}
|
1095 |
+
|
1096 |
+
return true;
|
1097 |
+
}
|
1098 |
+
|
1099 |
+
/**
|
1100 |
+
* Echoes required plugin notice.
|
1101 |
+
*
|
1102 |
+
* Outputs a message telling users that a specific plugin is required for
|
1103 |
+
* their theme. If appropriate, it includes a link to the form page where
|
1104 |
+
* users can install and activate the plugin.
|
1105 |
+
*
|
1106 |
+
* Returns early if we're on the Install page.
|
1107 |
+
*
|
1108 |
+
* @since 1.0.0
|
1109 |
+
*
|
1110 |
+
* @global object $current_screen
|
1111 |
+
*
|
1112 |
+
* @return null Returns early if we're on the Install page.
|
1113 |
+
*/
|
1114 |
+
public function notices() {
|
1115 |
+
// Remove nag on the install page / Return early if the nag message has been dismissed or user < author.
|
1116 |
+
if ( ( $this->is_tgmpa_page() || $this->is_core_update_page() ) || get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) || ! current_user_can( apply_filters( 'tgmpa_show_admin_notice_capability', 'publish_posts' ) ) ) {
|
1117 |
+
return;
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
// Store for the plugin slugs by message type.
|
1121 |
+
$message = array();
|
1122 |
+
|
1123 |
+
// Initialize counters used to determine plurality of action link texts.
|
1124 |
+
$install_link_count = 0;
|
1125 |
+
$update_link_count = 0;
|
1126 |
+
$activate_link_count = 0;
|
1127 |
+
$total_required_action_count = 0;
|
1128 |
+
|
1129 |
+
foreach ( $this->plugins as $slug => $plugin ) {
|
1130 |
+
if ( $this->is_plugin_active( $slug ) && false === $this->does_plugin_have_update( $slug ) ) {
|
1131 |
+
continue;
|
1132 |
+
}
|
1133 |
+
|
1134 |
+
if ( ! $this->is_plugin_installed( $slug ) ) {
|
1135 |
+
if ( current_user_can( 'install_plugins' ) ) {
|
1136 |
+
$install_link_count++;
|
1137 |
+
|
1138 |
+
if ( true === $plugin['required'] ) {
|
1139 |
+
$message['notice_can_install_required'][] = $slug;
|
1140 |
+
} else {
|
1141 |
+
$message['notice_can_install_recommended'][] = $slug;
|
1142 |
+
}
|
1143 |
+
}
|
1144 |
+
if ( true === $plugin['required'] ) {
|
1145 |
+
$total_required_action_count++;
|
1146 |
+
}
|
1147 |
+
} else {
|
1148 |
+
if ( ! $this->is_plugin_active( $slug ) && $this->can_plugin_activate( $slug ) ) {
|
1149 |
+
if ( current_user_can( 'activate_plugins' ) ) {
|
1150 |
+
$activate_link_count++;
|
1151 |
+
|
1152 |
+
if ( true === $plugin['required'] ) {
|
1153 |
+
$message['notice_can_activate_required'][] = $slug;
|
1154 |
+
} else {
|
1155 |
+
$message['notice_can_activate_recommended'][] = $slug;
|
1156 |
+
}
|
1157 |
+
}
|
1158 |
+
if ( true === $plugin['required'] ) {
|
1159 |
+
$total_required_action_count++;
|
1160 |
+
}
|
1161 |
+
}
|
1162 |
+
|
1163 |
+
if ( $this->does_plugin_require_update( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
|
1164 |
+
|
1165 |
+
if ( current_user_can( 'update_plugins' ) ) {
|
1166 |
+
$update_link_count++;
|
1167 |
+
|
1168 |
+
if ( $this->does_plugin_require_update( $slug ) ) {
|
1169 |
+
$message['notice_ask_to_update'][] = $slug;
|
1170 |
+
} elseif ( false !== $this->does_plugin_have_update( $slug ) ) {
|
1171 |
+
$message['notice_ask_to_update_maybe'][] = $slug;
|
1172 |
+
}
|
1173 |
+
}
|
1174 |
+
if ( true === $plugin['required'] ) {
|
1175 |
+
$total_required_action_count++;
|
1176 |
+
}
|
1177 |
+
}
|
1178 |
+
}
|
1179 |
+
}
|
1180 |
+
unset( $slug, $plugin );
|
1181 |
+
|
1182 |
+
// If we have notices to display, we move forward.
|
1183 |
+
if ( ! empty( $message ) || $total_required_action_count > 0 ) {
|
1184 |
+
krsort( $message ); // Sort messages.
|
1185 |
+
$rendered = '';
|
1186 |
+
|
1187 |
+
// As add_settings_error() wraps the final message in a <p> and as the final message can't be
|
1188 |
+
// filtered, using <p>'s in our html would render invalid html output.
|
1189 |
+
$line_template = '<span style="display: block; margin: 0.5em 0.5em 0 0; clear: both;">%s</span>' . "\n";
|
1190 |
+
|
1191 |
+
if ( ! current_user_can( 'activate_plugins' ) && ! current_user_can( 'install_plugins' ) && ! current_user_can( 'update_plugins' ) ) {
|
1192 |
+
$rendered = esc_html( $this->strings['notice_cannot_install_activate'] ) . ' ' . esc_html( $this->strings['contact_admin'] );
|
1193 |
+
$rendered .= $this->create_user_action_links_for_notice( 0, 0, 0, $line_template );
|
1194 |
+
} else {
|
1195 |
+
|
1196 |
+
// If dismissable is false and a message is set, output it now.
|
1197 |
+
if ( ! $this->dismissable && ! empty( $this->dismiss_msg ) ) {
|
1198 |
+
$rendered .= sprintf( $line_template, wp_kses_post( $this->dismiss_msg ) );
|
1199 |
+
}
|
1200 |
+
|
1201 |
+
// Render the individual message lines for the notice.
|
1202 |
+
foreach ( $message as $type => $plugin_group ) {
|
1203 |
+
$linked_plugins = array();
|
1204 |
+
|
1205 |
+
// Get the external info link for a plugin if one is available.
|
1206 |
+
foreach ( $plugin_group as $plugin_slug ) {
|
1207 |
+
$linked_plugins[] = $this->get_info_link( $plugin_slug );
|
1208 |
+
}
|
1209 |
+
unset( $plugin_slug );
|
1210 |
+
|
1211 |
+
$count = count( $plugin_group );
|
1212 |
+
$linked_plugins = array_map( array( 'TGMPA_Utils', 'wrap_in_em' ), $linked_plugins );
|
1213 |
+
$last_plugin = array_pop( $linked_plugins ); // Pop off last name to prep for readability.
|
1214 |
+
$imploded = empty( $linked_plugins ) ? $last_plugin : ( implode( ', ', $linked_plugins ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
|
1215 |
+
|
1216 |
+
$rendered .= sprintf(
|
1217 |
+
$line_template,
|
1218 |
+
sprintf(
|
1219 |
+
translate_nooped_plural( $this->strings[ $type ], $count, 'tgmpa' ),
|
1220 |
+
$imploded,
|
1221 |
+
$count
|
1222 |
+
)
|
1223 |
+
);
|
1224 |
+
|
1225 |
+
}
|
1226 |
+
unset( $type, $plugin_group, $linked_plugins, $count, $last_plugin, $imploded );
|
1227 |
+
|
1228 |
+
$rendered .= $this->create_user_action_links_for_notice( $install_link_count, $update_link_count, $activate_link_count, $line_template );
|
1229 |
+
}
|
1230 |
+
|
1231 |
+
// Register the nag messages and prepare them to be processed.
|
1232 |
+
add_settings_error( 'tgmpa', 'tgmpa', $rendered, $this->get_admin_notice_class() );
|
1233 |
+
}
|
1234 |
+
|
1235 |
+
// Admin options pages already output settings_errors, so this is to avoid duplication.
|
1236 |
+
if ( 'options-general' !== $GLOBALS['current_screen']->parent_base ) {
|
1237 |
+
$this->display_settings_errors();
|
1238 |
+
}
|
1239 |
+
}
|
1240 |
+
|
1241 |
+
/**
|
1242 |
+
* Generate the user action links for the admin notice.
|
1243 |
+
*
|
1244 |
+
* @since 2.6.0
|
1245 |
+
*
|
1246 |
+
* @param int $install_count Number of plugins to install.
|
1247 |
+
* @param int $update_count Number of plugins to update.
|
1248 |
+
* @param int $activate_count Number of plugins to activate.
|
1249 |
+
* @param int $line_template Template for the HTML tag to output a line.
|
1250 |
+
* @return string Action links.
|
1251 |
+
*/
|
1252 |
+
protected function create_user_action_links_for_notice( $install_count, $update_count, $activate_count, $line_template ) {
|
1253 |
+
// Setup action links.
|
1254 |
+
$action_links = array(
|
1255 |
+
'install' => '',
|
1256 |
+
'update' => '',
|
1257 |
+
'activate' => '',
|
1258 |
+
'dismiss' => $this->dismissable ? '<a href="' . esc_url( wp_nonce_url( add_query_arg( 'tgmpa-dismiss', 'dismiss_admin_notices' ), 'tgmpa-dismiss-' . get_current_user_id() ) ) . '" class="dismiss-notice" target="_parent">' . esc_html( $this->strings['dismiss'] ) . '</a>' : '',
|
1259 |
+
);
|
1260 |
+
|
1261 |
+
$link_template = '<a href="%2$s">%1$s</a>';
|
1262 |
+
|
1263 |
+
if ( current_user_can( 'install_plugins' ) ) {
|
1264 |
+
if ( $install_count > 0 ) {
|
1265 |
+
$action_links['install'] = sprintf(
|
1266 |
+
$link_template,
|
1267 |
+
translate_nooped_plural( $this->strings['install_link'], $install_count, 'tgmpa' ),
|
1268 |
+
esc_url( $this->get_tgmpa_status_url( 'install' ) )
|
1269 |
+
);
|
1270 |
+
}
|
1271 |
+
if ( $update_count > 0 ) {
|
1272 |
+
$action_links['update'] = sprintf(
|
1273 |
+
$link_template,
|
1274 |
+
translate_nooped_plural( $this->strings['update_link'], $update_count, 'tgmpa' ),
|
1275 |
+
esc_url( $this->get_tgmpa_status_url( 'update' ) )
|
1276 |
+
);
|
1277 |
+
}
|
1278 |
+
}
|
1279 |
+
|
1280 |
+
if ( current_user_can( 'activate_plugins' ) && $activate_count > 0 ) {
|
1281 |
+
$action_links['activate'] = sprintf(
|
1282 |
+
$link_template,
|
1283 |
+
translate_nooped_plural( $this->strings['activate_link'], $activate_count, 'tgmpa' ),
|
1284 |
+
esc_url( $this->get_tgmpa_status_url( 'activate' ) )
|
1285 |
+
);
|
1286 |
+
}
|
1287 |
+
|
1288 |
+
$action_links = apply_filters( 'tgmpa_notice_action_links', $action_links );
|
1289 |
+
|
1290 |
+
$action_links = array_filter( (array) $action_links ); // Remove any empty array items.
|
1291 |
+
|
1292 |
+
if ( ! empty( $action_links ) ) {
|
1293 |
+
$action_links = sprintf( $line_template, implode( ' | ', $action_links ) );
|
1294 |
+
return apply_filters( 'tgmpa_notice_rendered_action_links', $action_links );
|
1295 |
+
} else {
|
1296 |
+
return '';
|
1297 |
+
}
|
1298 |
+
}
|
1299 |
+
|
1300 |
+
/**
|
1301 |
+
* Get admin notice class.
|
1302 |
+
*
|
1303 |
+
* Work around all the changes to the various admin notice classes between WP 4.4 and 3.7
|
1304 |
+
* (lowest supported version by TGMPA).
|
1305 |
+
*
|
1306 |
+
* @since 2.6.0
|
1307 |
+
*
|
1308 |
+
* @return string
|
1309 |
+
*/
|
1310 |
+
protected function get_admin_notice_class() {
|
1311 |
+
if ( ! empty( $this->strings['nag_type'] ) ) {
|
1312 |
+
return sanitize_html_class( strtolower( $this->strings['nag_type'] ) );
|
1313 |
+
} else {
|
1314 |
+
if ( version_compare( $this->wp_version, '4.2', '>=' ) ) {
|
1315 |
+
return 'notice-warning';
|
1316 |
+
} elseif ( version_compare( $this->wp_version, '4.1', '>=' ) ) {
|
1317 |
+
return 'notice';
|
1318 |
+
} else {
|
1319 |
+
return 'updated';
|
1320 |
+
}
|
1321 |
+
}
|
1322 |
+
}
|
1323 |
+
|
1324 |
+
/**
|
1325 |
+
* Display settings errors and remove those which have been displayed to avoid duplicate messages showing
|
1326 |
+
*
|
1327 |
+
* @since 2.5.0
|
1328 |
+
*/
|
1329 |
+
protected function display_settings_errors() {
|
1330 |
+
global $wp_settings_errors;
|
1331 |
+
|
1332 |
+
settings_errors( 'tgmpa' );
|
1333 |
+
|
1334 |
+
foreach ( (array) $wp_settings_errors as $key => $details ) {
|
1335 |
+
if ( 'tgmpa' === $details['setting'] ) {
|
1336 |
+
unset( $wp_settings_errors[ $key ] );
|
1337 |
+
break;
|
1338 |
+
}
|
1339 |
+
}
|
1340 |
+
}
|
1341 |
+
|
1342 |
+
/**
|
1343 |
+
* Register dismissal of admin notices.
|
1344 |
+
*
|
1345 |
+
* Acts on the dismiss link in the admin nag messages.
|
1346 |
+
* If clicked, the admin notice disappears and will no longer be visible to this user.
|
1347 |
+
*
|
1348 |
+
* @since 2.1.0
|
1349 |
+
*/
|
1350 |
+
public function dismiss() {
|
1351 |
+
if ( isset( $_GET['tgmpa-dismiss'] ) && check_admin_referer( 'tgmpa-dismiss-' . get_current_user_id() ) ) {
|
1352 |
+
update_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, 1 );
|
1353 |
+
}
|
1354 |
+
}
|
1355 |
+
|
1356 |
+
/**
|
1357 |
+
* Add individual plugin to our collection of plugins.
|
1358 |
+
*
|
1359 |
+
* If the required keys are not set or the plugin has already
|
1360 |
+
* been registered, the plugin is not added.
|
1361 |
+
*
|
1362 |
+
* @since 2.0.0
|
1363 |
+
*
|
1364 |
+
* @param array|null $plugin Array of plugin arguments or null if invalid argument.
|
1365 |
+
* @return null Return early if incorrect argument.
|
1366 |
+
*/
|
1367 |
+
public function register( $plugin ) {
|
1368 |
+
if ( empty( $plugin['slug'] ) || empty( $plugin['name'] ) ) {
|
1369 |
+
return;
|
1370 |
+
}
|
1371 |
+
|
1372 |
+
if ( empty( $plugin['slug'] ) || ! is_string( $plugin['slug'] ) || isset( $this->plugins[ $plugin['slug'] ] ) ) {
|
1373 |
+
return;
|
1374 |
+
}
|
1375 |
+
|
1376 |
+
$defaults = array(
|
1377 |
+
'name' => '', // String
|
1378 |
+
'slug' => '', // String
|
1379 |
+
'source' => 'repo', // String
|
1380 |
+
'required' => false, // Boolean
|
1381 |
+
'version' => '', // String
|
1382 |
+
'force_activation' => false, // Boolean
|
1383 |
+
'force_deactivation' => false, // Boolean
|
1384 |
+
'external_url' => '', // String
|
1385 |
+
'is_callable' => '', // String|Array.
|
1386 |
+
);
|
1387 |
+
|
1388 |
+
// Prepare the received data.
|
1389 |
+
$plugin = wp_parse_args( $plugin, $defaults );
|
1390 |
+
|
1391 |
+
// Standardize the received slug.
|
1392 |
+
$plugin['slug'] = $this->sanitize_key( $plugin['slug'] );
|
1393 |
+
|
1394 |
+
// Forgive users for using string versions of booleans or floats for version number.
|
1395 |
+
$plugin['version'] = (string) $plugin['version'];
|
1396 |
+
$plugin['source'] = empty( $plugin['source'] ) ? 'repo' : $plugin['source'];
|
1397 |
+
$plugin['required'] = TGMPA_Utils::validate_bool( $plugin['required'] );
|
1398 |
+
$plugin['force_activation'] = TGMPA_Utils::validate_bool( $plugin['force_activation'] );
|
1399 |
+
$plugin['force_deactivation'] = TGMPA_Utils::validate_bool( $plugin['force_deactivation'] );
|
1400 |
+
|
1401 |
+
// Enrich the received data.
|
1402 |
+
$plugin['file_path'] = $this->_get_plugin_basename_from_slug( $plugin['slug'] );
|
1403 |
+
$plugin['source_type'] = $this->get_plugin_source_type( $plugin['source'] );
|
1404 |
+
|
1405 |
+
// Set the class properties.
|
1406 |
+
$this->plugins[ $plugin['slug'] ] = $plugin;
|
1407 |
+
$this->sort_order[ $plugin['slug'] ] = $plugin['name'];
|
1408 |
+
|
1409 |
+
// Should we add the force activation hook ?
|
1410 |
+
if ( true === $plugin['force_activation'] ) {
|
1411 |
+
$this->has_forced_activation = true;
|
1412 |
+
}
|
1413 |
+
|
1414 |
+
// Should we add the force deactivation hook ?
|
1415 |
+
if ( true === $plugin['force_deactivation'] ) {
|
1416 |
+
$this->has_forced_deactivation = true;
|
1417 |
+
}
|
1418 |
+
}
|
1419 |
+
|
1420 |
+
/**
|
1421 |
+
* Determine what type of source the plugin comes from.
|
1422 |
+
*
|
1423 |
+
* @since 2.5.0
|
1424 |
+
*
|
1425 |
+
* @param string $source The source of the plugin as provided, either empty (= WP repo), a file path
|
1426 |
+
* (= bundled) or an external URL.
|
1427 |
+
* @return string 'repo', 'external', or 'bundled'
|
1428 |
+
*/
|
1429 |
+
protected function get_plugin_source_type( $source ) {
|
1430 |
+
if ( 'repo' === $source || preg_match( self::WP_REPO_REGEX, $source ) ) {
|
1431 |
+
return 'repo';
|
1432 |
+
} elseif ( preg_match( self::IS_URL_REGEX, $source ) ) {
|
1433 |
+
return 'external';
|
1434 |
+
} else {
|
1435 |
+
return 'bundled';
|
1436 |
+
}
|
1437 |
+
}
|
1438 |
+
|
1439 |
+
/**
|
1440 |
+
* Sanitizes a string key.
|
1441 |
+
*
|
1442 |
+
* Near duplicate of WP Core `sanitize_key()`. The difference is that uppercase characters *are*
|
1443 |
+
* allowed, so as not to break upgrade paths from non-standard bundled plugins using uppercase
|
1444 |
+
* characters in the plugin directory path/slug. Silly them.
|
1445 |
+
*
|
1446 |
+
* @see https://developer.wordpress.org/reference/hooks/sanitize_key/
|
1447 |
+
*
|
1448 |
+
* @since 2.5.0
|
1449 |
+
*
|
1450 |
+
* @param string $key String key.
|
1451 |
+
* @return string Sanitized key
|
1452 |
+
*/
|
1453 |
+
public function sanitize_key( $key ) {
|
1454 |
+
$raw_key = $key;
|
1455 |
+
$key = preg_replace( '`[^A-Za-z0-9_-]`', '', $key );
|
1456 |
+
|
1457 |
+
/**
|
1458 |
+
* Filter a sanitized key string.
|
1459 |
+
*
|
1460 |
+
* @since 2.5.0
|
1461 |
+
*
|
1462 |
+
* @param string $key Sanitized key.
|
1463 |
+
* @param string $raw_key The key prior to sanitization.
|
1464 |
+
*/
|
1465 |
+
return apply_filters( 'tgmpa_sanitize_key', $key, $raw_key );
|
1466 |
+
}
|
1467 |
+
|
1468 |
+
/**
|
1469 |
+
* Amend default configuration settings.
|
1470 |
+
*
|
1471 |
+
* @since 2.0.0
|
1472 |
+
*
|
1473 |
+
* @param array $config Array of config options to pass as class properties.
|
1474 |
+
*/
|
1475 |
+
public function config( $config ) {
|
1476 |
+
$keys = array(
|
1477 |
+
'id',
|
1478 |
+
'default_path',
|
1479 |
+
'has_notices',
|
1480 |
+
'dismissable',
|
1481 |
+
'dismiss_msg',
|
1482 |
+
'menu',
|
1483 |
+
'parent_slug',
|
1484 |
+
'capability',
|
1485 |
+
'is_automatic',
|
1486 |
+
'message',
|
1487 |
+
'strings',
|
1488 |
+
);
|
1489 |
+
|
1490 |
+
foreach ( $keys as $key ) {
|
1491 |
+
if ( isset( $config[ $key ] ) ) {
|
1492 |
+
if ( is_array( $config[ $key ] ) ) {
|
1493 |
+
$this->$key = array_merge( $this->$key, $config[ $key ] );
|
1494 |
+
} else {
|
1495 |
+
$this->$key = $config[ $key ];
|
1496 |
+
}
|
1497 |
+
}
|
1498 |
+
}
|
1499 |
+
}
|
1500 |
+
|
1501 |
+
/**
|
1502 |
+
* Amend action link after plugin installation.
|
1503 |
+
*
|
1504 |
+
* @since 2.0.0
|
1505 |
+
*
|
1506 |
+
* @param array $install_actions Existing array of actions.
|
1507 |
+
* @return false|array Amended array of actions.
|
1508 |
+
*/
|
1509 |
+
public function actions( $install_actions ) {
|
1510 |
+
// Remove action links on the TGMPA install page.
|
1511 |
+
if ( $this->is_tgmpa_page() ) {
|
1512 |
+
return false;
|
1513 |
+
}
|
1514 |
+
|
1515 |
+
return $install_actions;
|
1516 |
+
}
|
1517 |
+
|
1518 |
+
/**
|
1519 |
+
* Flushes the plugins cache on theme switch to prevent stale entries
|
1520 |
+
* from remaining in the plugin table.
|
1521 |
+
*
|
1522 |
+
* @since 2.4.0
|
1523 |
+
*
|
1524 |
+
* @param bool $clear_update_cache Optional. Whether to clear the Plugin updates cache.
|
1525 |
+
* Parameter added in v2.5.0.
|
1526 |
+
*/
|
1527 |
+
public function flush_plugins_cache( $clear_update_cache = true ) {
|
1528 |
+
wp_clean_plugins_cache( $clear_update_cache );
|
1529 |
+
}
|
1530 |
+
|
1531 |
+
/**
|
1532 |
+
* Set file_path key for each installed plugin.
|
1533 |
+
*
|
1534 |
+
* @since 2.1.0
|
1535 |
+
*
|
1536 |
+
* @param string $plugin_slug Optional. If set, only (re-)populates the file path for that specific plugin.
|
1537 |
+
* Parameter added in v2.5.0.
|
1538 |
+
*/
|
1539 |
+
public function populate_file_path( $plugin_slug = '' ) {
|
1540 |
+
if ( ! empty( $plugin_slug ) && is_string( $plugin_slug ) && isset( $this->plugins[ $plugin_slug ] ) ) {
|
1541 |
+
$this->plugins[ $plugin_slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $plugin_slug );
|
1542 |
+
} else {
|
1543 |
+
// Add file_path key for all plugins.
|
1544 |
+
foreach ( $this->plugins as $slug => $values ) {
|
1545 |
+
$this->plugins[ $slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $slug );
|
1546 |
+
}
|
1547 |
+
}
|
1548 |
+
}
|
1549 |
+
|
1550 |
+
/**
|
1551 |
+
* Helper function to extract the file path of the plugin file from the
|
1552 |
+
* plugin slug, if the plugin is installed.
|
1553 |
+
*
|
1554 |
+
* @since 2.0.0
|
1555 |
+
*
|
1556 |
+
* @param string $slug Plugin slug (typically folder name) as provided by the developer.
|
1557 |
+
* @return string Either file path for plugin if installed, or just the plugin slug.
|
1558 |
+
*/
|
1559 |
+
protected function _get_plugin_basename_from_slug( $slug ) {
|
1560 |
+
$keys = array_keys( $this->get_plugins() );
|
1561 |
+
|
1562 |
+
foreach ( $keys as $key ) {
|
1563 |
+
if ( preg_match( '|^' . $slug . '/|', $key ) ) {
|
1564 |
+
return $key;
|
1565 |
+
}
|
1566 |
+
}
|
1567 |
+
|
1568 |
+
return $slug;
|
1569 |
+
}
|
1570 |
+
|
1571 |
+
/**
|
1572 |
+
* Retrieve plugin data, given the plugin name.
|
1573 |
+
*
|
1574 |
+
* Loops through the registered plugins looking for $name. If it finds it,
|
1575 |
+
* it returns the $data from that plugin. Otherwise, returns false.
|
1576 |
+
*
|
1577 |
+
* @since 2.1.0
|
1578 |
+
*
|
1579 |
+
* @param string $name Name of the plugin, as it was registered.
|
1580 |
+
* @param string $data Optional. Array key of plugin data to return. Default is slug.
|
1581 |
+
* @return string|boolean Plugin slug if found, false otherwise.
|
1582 |
+
*/
|
1583 |
+
public function _get_plugin_data_from_name( $name, $data = 'slug' ) {
|
1584 |
+
foreach ( $this->plugins as $values ) {
|
1585 |
+
if ( $name === $values['name'] && isset( $values[ $data ] ) ) {
|
1586 |
+
return $values[ $data ];
|
1587 |
+
}
|
1588 |
+
}
|
1589 |
+
|
1590 |
+
return false;
|
1591 |
+
}
|
1592 |
+
|
1593 |
+
/**
|
1594 |
+
* Retrieve the download URL for a package.
|
1595 |
+
*
|
1596 |
+
* @since 2.5.0
|
1597 |
+
*
|
1598 |
+
* @param string $slug Plugin slug.
|
1599 |
+
* @return string Plugin download URL or path to local file or empty string if undetermined.
|
1600 |
+
*/
|
1601 |
+
public function get_download_url( $slug ) {
|
1602 |
+
$dl_source = '';
|
1603 |
+
|
1604 |
+
switch ( $this->plugins[ $slug ]['source_type'] ) {
|
1605 |
+
case 'repo':
|
1606 |
+
return $this->get_wp_repo_download_url( $slug );
|
1607 |
+
case 'external':
|
1608 |
+
return $this->plugins[ $slug ]['source'];
|
1609 |
+
case 'bundled':
|
1610 |
+
return $this->default_path . $this->plugins[ $slug ]['source'];
|
1611 |
+
}
|
1612 |
+
|
1613 |
+
return $dl_source; // Should never happen.
|
1614 |
+
}
|
1615 |
+
|
1616 |
+
/**
|
1617 |
+
* Retrieve the download URL for a WP repo package.
|
1618 |
+
*
|
1619 |
+
* @since 2.5.0
|
1620 |
+
*
|
1621 |
+
* @param string $slug Plugin slug.
|
1622 |
+
* @return string Plugin download URL.
|
1623 |
+
*/
|
1624 |
+
protected function get_wp_repo_download_url( $slug ) {
|
1625 |
+
$source = '';
|
1626 |
+
$api = $this->get_plugins_api( $slug );
|
1627 |
+
|
1628 |
+
if ( false !== $api && isset( $api->download_link ) ) {
|
1629 |
+
$source = $api->download_link;
|
1630 |
+
}
|
1631 |
+
|
1632 |
+
return $source;
|
1633 |
+
}
|
1634 |
+
|
1635 |
+
/**
|
1636 |
+
* Try to grab information from WordPress API.
|
1637 |
+
*
|
1638 |
+
* @since 2.5.0
|
1639 |
+
*
|
1640 |
+
* @param string $slug Plugin slug.
|
1641 |
+
* @return object Plugins_api response object on success, WP_Error on failure.
|
1642 |
+
*/
|
1643 |
+
protected function get_plugins_api( $slug ) {
|
1644 |
+
static $api = array(); // Cache received responses.
|
1645 |
+
|
1646 |
+
if ( ! isset( $api[ $slug ] ) ) {
|
1647 |
+
if ( ! function_exists( 'plugins_api' ) ) {
|
1648 |
+
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
|
1649 |
+
}
|
1650 |
+
|
1651 |
+
$response = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
|
1652 |
+
|
1653 |
+
$api[ $slug ] = false;
|
1654 |
+
|
1655 |
+
if ( is_wp_error( $response ) ) {
|
1656 |
+
wp_die( esc_html( $this->strings['oops'] ) );
|
1657 |
+
} else {
|
1658 |
+
$api[ $slug ] = $response;
|
1659 |
+
}
|
1660 |
+
}
|
1661 |
+
|
1662 |
+
return $api[ $slug ];
|
1663 |
+
}
|
1664 |
+
|
1665 |
+
/**
|
1666 |
+
* Retrieve a link to a plugin information page.
|
1667 |
+
*
|
1668 |
+
* @since 2.5.0
|
1669 |
+
*
|
1670 |
+
* @param string $slug Plugin slug.
|
1671 |
+
* @return string Fully formed html link to a plugin information page if available
|
1672 |
+
* or the plugin name if not.
|
1673 |
+
*/
|
1674 |
+
public function get_info_link( $slug ) {
|
1675 |
+
if ( ! empty( $this->plugins[ $slug ]['external_url'] ) && preg_match( self::IS_URL_REGEX, $this->plugins[ $slug ]['external_url'] ) ) {
|
1676 |
+
$link = sprintf(
|
1677 |
+
'<a href="%1$s" target="_blank">%2$s</a>',
|
1678 |
+
esc_url( $this->plugins[ $slug ]['external_url'] ),
|
1679 |
+
esc_html( $this->plugins[ $slug ]['name'] )
|
1680 |
+
);
|
1681 |
+
} elseif ( 'repo' === $this->plugins[ $slug ]['source_type'] ) {
|
1682 |
+
$url = add_query_arg(
|
1683 |
+
array(
|
1684 |
+
'tab' => 'plugin-information',
|
1685 |
+
'plugin' => urlencode( $slug ),
|
1686 |
+
'TB_iframe' => 'true',
|
1687 |
+
'width' => '640',
|
1688 |
+
'height' => '500',
|
1689 |
+
),
|
1690 |
+
self_admin_url( 'plugin-install.php' )
|
1691 |
+
);
|
1692 |
+
|
1693 |
+
$link = sprintf(
|
1694 |
+
'<a href="%1$s" class="thickbox">%2$s</a>',
|
1695 |
+
esc_url( $url ),
|
1696 |
+
esc_html( $this->plugins[ $slug ]['name'] )
|
1697 |
+
);
|
1698 |
+
} else {
|
1699 |
+
$link = esc_html( $this->plugins[ $slug ]['name'] ); // No hyperlink.
|
1700 |
+
}
|
1701 |
+
|
1702 |
+
return $link;
|
1703 |
+
}
|
1704 |
+
|
1705 |
+
/**
|
1706 |
+
* Determine if we're on the TGMPA Install page.
|
1707 |
+
*
|
1708 |
+
* @since 2.1.0
|
1709 |
+
*
|
1710 |
+
* @return boolean True when on the TGMPA page, false otherwise.
|
1711 |
+
*/
|
1712 |
+
protected function is_tgmpa_page() {
|
1713 |
+
return isset( $_GET['page'] ) && $this->menu === $_GET['page'];
|
1714 |
+
}
|
1715 |
+
|
1716 |
+
/**
|
1717 |
+
* Determine if we're on a WP Core installation/upgrade page.
|
1718 |
+
*
|
1719 |
+
* @since 2.6.0
|
1720 |
+
*
|
1721 |
+
* @return boolean True when on a WP Core installation/upgrade page, false otherwise.
|
1722 |
+
*/
|
1723 |
+
protected function is_core_update_page() {
|
1724 |
+
// Current screen is not always available, most notably on the customizer screen.
|
1725 |
+
if ( ! function_exists( 'get_current_screen' ) ) {
|
1726 |
+
return false;
|
1727 |
+
}
|
1728 |
+
|
1729 |
+
$screen = get_current_screen();
|
1730 |
+
|
1731 |
+
if ( 'update-core' === $screen->base ) {
|
1732 |
+
// Core update screen.
|
1733 |
+
return true;
|
1734 |
+
} elseif ( 'plugins' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok.
|
1735 |
+
// Plugins bulk update screen.
|
1736 |
+
return true;
|
1737 |
+
} elseif ( 'update' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok.
|
1738 |
+
// Individual updates (ajax call).
|
1739 |
+
return true;
|
1740 |
+
}
|
1741 |
+
|
1742 |
+
return false;
|
1743 |
+
}
|
1744 |
+
|
1745 |
+
/**
|
1746 |
+
* Retrieve the URL to the TGMPA Install page.
|
1747 |
+
*
|
1748 |
+
* I.e. depending on the config settings passed something along the lines of:
|
1749 |
+
* http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins
|
1750 |
+
*
|
1751 |
+
* @since 2.5.0
|
1752 |
+
*
|
1753 |
+
* @return string Properly encoded URL (not escaped).
|
1754 |
+
*/
|
1755 |
+
public function get_tgmpa_url() {
|
1756 |
+
static $url;
|
1757 |
+
|
1758 |
+
if ( ! isset( $url ) ) {
|
1759 |
+
$parent = $this->parent_slug;
|
1760 |
+
if ( false === strpos( $parent, '.php' ) ) {
|
1761 |
+
$parent = 'admin.php';
|
1762 |
+
}
|
1763 |
+
$url = add_query_arg(
|
1764 |
+
array(
|
1765 |
+
'page' => urlencode( $this->menu ),
|
1766 |
+
),
|
1767 |
+
self_admin_url( $parent )
|
1768 |
+
);
|
1769 |
+
}
|
1770 |
+
|
1771 |
+
return $url;
|
1772 |
+
}
|
1773 |
+
|
1774 |
+
/**
|
1775 |
+
* Retrieve the URL to the TGMPA Install page for a specific plugin status (view).
|
1776 |
+
*
|
1777 |
+
* I.e. depending on the config settings passed something along the lines of:
|
1778 |
+
* http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins&plugin_status=install
|
1779 |
+
*
|
1780 |
+
* @since 2.5.0
|
1781 |
+
*
|
1782 |
+
* @param string $status Plugin status - either 'install', 'update' or 'activate'.
|
1783 |
+
* @return string Properly encoded URL (not escaped).
|
1784 |
+
*/
|
1785 |
+
public function get_tgmpa_status_url( $status ) {
|
1786 |
+
return add_query_arg(
|
1787 |
+
array(
|
1788 |
+
'plugin_status' => urlencode( $status ),
|
1789 |
+
),
|
1790 |
+
$this->get_tgmpa_url()
|
1791 |
+
);
|
1792 |
+
}
|
1793 |
+
|
1794 |
+
/**
|
1795 |
+
* Determine whether there are open actions for plugins registered with TGMPA.
|
1796 |
+
*
|
1797 |
+
* @since 2.5.0
|
1798 |
+
*
|
1799 |
+
* @return bool True if complete, i.e. no outstanding actions. False otherwise.
|
1800 |
+
*/
|
1801 |
+
public function is_tgmpa_complete() {
|
1802 |
+
$complete = true;
|
1803 |
+
foreach ( $this->plugins as $slug => $plugin ) {
|
1804 |
+
if ( ! $this->is_plugin_active( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
|
1805 |
+
$complete = false;
|
1806 |
+
break;
|
1807 |
+
}
|
1808 |
+
}
|
1809 |
+
|
1810 |
+
return $complete;
|
1811 |
+
}
|
1812 |
+
|
1813 |
+
/**
|
1814 |
+
* Check if a plugin is installed. Does not take must-use plugins into account.
|
1815 |
+
*
|
1816 |
+
* @since 2.5.0
|
1817 |
+
*
|
1818 |
+
* @param string $slug Plugin slug.
|
1819 |
+
* @return bool True if installed, false otherwise.
|
1820 |
+
*/
|
1821 |
+
public function is_plugin_installed( $slug ) {
|
1822 |
+
$installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
|
1823 |
+
|
1824 |
+
return ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ] ) );
|
1825 |
+
}
|
1826 |
+
|
1827 |
+
/**
|
1828 |
+
* Check if a plugin is active.
|
1829 |
+
*
|
1830 |
+
* @since 2.5.0
|
1831 |
+
*
|
1832 |
+
* @param string $slug Plugin slug.
|
1833 |
+
* @return bool True if active, false otherwise.
|
1834 |
+
*/
|
1835 |
+
public function is_plugin_active( $slug ) {
|
1836 |
+
return ( ( ! empty( $this->plugins[ $slug ]['is_callable'] ) && is_callable( $this->plugins[ $slug ]['is_callable'] ) ) || is_plugin_active( $this->plugins[ $slug ]['file_path'] ) );
|
1837 |
+
}
|
1838 |
+
|
1839 |
+
/**
|
1840 |
+
* Check if a plugin can be updated, i.e. if we have information on the minimum WP version required
|
1841 |
+
* available, check whether the current install meets them.
|
1842 |
+
*
|
1843 |
+
* @since 2.5.0
|
1844 |
+
*
|
1845 |
+
* @param string $slug Plugin slug.
|
1846 |
+
* @return bool True if OK to update, false otherwise.
|
1847 |
+
*/
|
1848 |
+
public function can_plugin_update( $slug ) {
|
1849 |
+
// We currently can't get reliable info on non-WP-repo plugins - issue #380.
|
1850 |
+
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
|
1851 |
+
return true;
|
1852 |
+
}
|
1853 |
+
|
1854 |
+
$api = $this->get_plugins_api( $slug );
|
1855 |
+
|
1856 |
+
if ( false !== $api && isset( $api->requires ) ) {
|
1857 |
+
return version_compare( $this->wp_version, $api->requires, '>=' );
|
1858 |
+
}
|
1859 |
+
|
1860 |
+
// No usable info received from the plugins API, presume we can update.
|
1861 |
+
return true;
|
1862 |
+
}
|
1863 |
+
|
1864 |
+
/**
|
1865 |
+
* Check to see if the plugin is 'updatetable', i.e. installed, with an update available
|
1866 |
+
* and no WP version requirements blocking it.
|
1867 |
+
*
|
1868 |
+
* @since 2.6.0
|
1869 |
+
*
|
1870 |
+
* @param string $slug Plugin slug.
|
1871 |
+
* @return bool True if OK to proceed with update, false otherwise.
|
1872 |
+
*/
|
1873 |
+
public function is_plugin_updatetable( $slug ) {
|
1874 |
+
if ( ! $this->is_plugin_installed( $slug ) ) {
|
1875 |
+
return false;
|
1876 |
+
} else {
|
1877 |
+
return ( false !== $this->does_plugin_have_update( $slug ) && $this->can_plugin_update( $slug ) );
|
1878 |
+
}
|
1879 |
+
}
|
1880 |
+
|
1881 |
+
/**
|
1882 |
+
* Check if a plugin can be activated, i.e. is not currently active and meets the minimum
|
1883 |
+
* plugin version requirements set in TGMPA (if any).
|
1884 |
+
*
|
1885 |
+
* @since 2.5.0
|
1886 |
+
*
|
1887 |
+
* @param string $slug Plugin slug.
|
1888 |
+
* @return bool True if OK to activate, false otherwise.
|
1889 |
+
*/
|
1890 |
+
public function can_plugin_activate( $slug ) {
|
1891 |
+
return ( ! $this->is_plugin_active( $slug ) && ! $this->does_plugin_require_update( $slug ) );
|
1892 |
+
}
|
1893 |
+
|
1894 |
+
/**
|
1895 |
+
* Retrieve the version number of an installed plugin.
|
1896 |
+
*
|
1897 |
+
* @since 2.5.0
|
1898 |
+
*
|
1899 |
+
* @param string $slug Plugin slug.
|
1900 |
+
* @return string Version number as string or an empty string if the plugin is not installed
|
1901 |
+
* or version unknown (plugins which don't comply with the plugin header standard).
|
1902 |
+
*/
|
1903 |
+
public function get_installed_version( $slug ) {
|
1904 |
+
$installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
|
1905 |
+
|
1906 |
+
if ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'] ) ) {
|
1907 |
+
return $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'];
|
1908 |
+
}
|
1909 |
+
|
1910 |
+
return '';
|
1911 |
+
}
|
1912 |
+
|
1913 |
+
/**
|
1914 |
+
* Check whether a plugin complies with the minimum version requirements.
|
1915 |
+
*
|
1916 |
+
* @since 2.5.0
|
1917 |
+
*
|
1918 |
+
* @param string $slug Plugin slug.
|
1919 |
+
* @return bool True when a plugin needs to be updated, otherwise false.
|
1920 |
+
*/
|
1921 |
+
public function does_plugin_require_update( $slug ) {
|
1922 |
+
$installed_version = $this->get_installed_version( $slug );
|
1923 |
+
$minimum_version = $this->plugins[ $slug ]['version'];
|
1924 |
+
|
1925 |
+
return version_compare( $minimum_version, $installed_version, '>' );
|
1926 |
+
}
|
1927 |
+
|
1928 |
+
/**
|
1929 |
+
* Check whether there is an update available for a plugin.
|
1930 |
+
*
|
1931 |
+
* @since 2.5.0
|
1932 |
+
*
|
1933 |
+
* @param string $slug Plugin slug.
|
1934 |
+
* @return false|string Version number string of the available update or false if no update available.
|
1935 |
+
*/
|
1936 |
+
public function does_plugin_have_update( $slug ) {
|
1937 |
+
// Presume bundled and external plugins will point to a package which meets the minimum required version.
|
1938 |
+
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
|
1939 |
+
if ( $this->does_plugin_require_update( $slug ) ) {
|
1940 |
+
return $this->plugins[ $slug ]['version'];
|
1941 |
+
}
|
1942 |
+
|
1943 |
+
return false;
|
1944 |
+
}
|
1945 |
+
|
1946 |
+
$repo_updates = get_site_transient( 'update_plugins' );
|
1947 |
+
|
1948 |
+
if ( isset( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version ) ) {
|
1949 |
+
return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version;
|
1950 |
+
}
|
1951 |
+
|
1952 |
+
return false;
|
1953 |
+
}
|
1954 |
+
|
1955 |
+
/**
|
1956 |
+
* Retrieve potential upgrade notice for a plugin.
|
1957 |
+
*
|
1958 |
+
* @since 2.5.0
|
1959 |
+
*
|
1960 |
+
* @param string $slug Plugin slug.
|
1961 |
+
* @return string The upgrade notice or an empty string if no message was available or provided.
|
1962 |
+
*/
|
1963 |
+
public function get_upgrade_notice( $slug ) {
|
1964 |
+
// We currently can't get reliable info on non-WP-repo plugins - issue #380.
|
1965 |
+
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
|
1966 |
+
return '';
|
1967 |
+
}
|
1968 |
+
|
1969 |
+
$repo_updates = get_site_transient( 'update_plugins' );
|
1970 |
+
|
1971 |
+
if ( ! empty( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice ) ) {
|
1972 |
+
return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice;
|
1973 |
+
}
|
1974 |
+
|
1975 |
+
return '';
|
1976 |
+
}
|
1977 |
+
|
1978 |
+
/**
|
1979 |
+
* Wrapper around the core WP get_plugins function, making sure it's actually available.
|
1980 |
+
*
|
1981 |
+
* @since 2.5.0
|
1982 |
+
*
|
1983 |
+
* @param string $plugin_folder Optional. Relative path to single plugin folder.
|
1984 |
+
* @return array Array of installed plugins with plugin information.
|
1985 |
+
*/
|
1986 |
+
public function get_plugins( $plugin_folder = '' ) {
|
1987 |
+
if ( ! function_exists( 'get_plugins' ) ) {
|
1988 |
+
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
1989 |
+
}
|
1990 |
+
|
1991 |
+
return get_plugins( $plugin_folder );
|
1992 |
+
}
|
1993 |
+
|
1994 |
+
/**
|
1995 |
+
* Delete dismissable nag option when theme is switched.
|
1996 |
+
*
|
1997 |
+
* This ensures that the user(s) is/are again reminded via nag of required
|
1998 |
+
* and/or recommended plugins if they re-activate the theme.
|
1999 |
+
*
|
2000 |
+
* @since 2.1.1
|
2001 |
+
*/
|
2002 |
+
public function update_dismiss() {
|
2003 |
+
delete_metadata( 'user', null, 'tgmpa_dismissed_notice_' . $this->id, null, true );
|
2004 |
+
}
|
2005 |
+
|
2006 |
+
/**
|
2007 |
+
* Forces plugin activation if the parameter 'force_activation' is
|
2008 |
+
* set to true.
|
2009 |
+
*
|
2010 |
+
* This allows theme authors to specify certain plugins that must be
|
2011 |
+
* active at all times while using the current theme.
|
2012 |
+
*
|
2013 |
+
* Please take special care when using this parameter as it has the
|
2014 |
+
* potential to be harmful if not used correctly. Setting this parameter
|
2015 |
+
* to true will not allow the specified plugin to be deactivated unless
|
2016 |
+
* the user switches themes.
|
2017 |
+
*
|
2018 |
+
* @since 2.2.0
|
2019 |
+
*/
|
2020 |
+
public function force_activation() {
|
2021 |
+
foreach ( $this->plugins as $slug => $plugin ) {
|
2022 |
+
if ( true === $plugin['force_activation'] ) {
|
2023 |
+
if ( ! $this->is_plugin_installed( $slug ) ) {
|
2024 |
+
// Oops, plugin isn't there so iterate to next condition.
|
2025 |
+
continue;
|
2026 |
+
} elseif ( $this->can_plugin_activate( $slug ) ) {
|
2027 |
+
// There we go, activate the plugin.
|
2028 |
+
activate_plugin( $plugin['file_path'] );
|
2029 |
+
}
|
2030 |
+
}
|
2031 |
+
}
|
2032 |
+
}
|
2033 |
+
|
2034 |
+
/**
|
2035 |
+
* Forces plugin deactivation if the parameter 'force_deactivation'
|
2036 |
+
* is set to true and adds the plugin to the 'recently active' plugins list.
|
2037 |
+
*
|
2038 |
+
* This allows theme authors to specify certain plugins that must be
|
2039 |
+
* deactivated upon switching from the current theme to another.
|
2040 |
+
*
|
2041 |
+
* Please take special care when using this parameter as it has the
|
2042 |
+
* potential to be harmful if not used correctly.
|
2043 |
+
*
|
2044 |
+
* @since 2.2.0
|
2045 |
+
*/
|
2046 |
+
public function force_deactivation() {
|
2047 |
+
$deactivated = array();
|
2048 |
+
|
2049 |
+
foreach ( $this->plugins as $slug => $plugin ) {
|
2050 |
+
/*
|
2051 |
+
* Only proceed forward if the parameter is set to true and plugin is active
|
2052 |
+
* as a 'normal' (not must-use) plugin.
|
2053 |
+
*/
|
2054 |
+
if ( true === $plugin['force_deactivation'] && is_plugin_active( $plugin['file_path'] ) ) {
|
2055 |
+
deactivate_plugins( $plugin['file_path'] );
|
2056 |
+
$deactivated[ $plugin['file_path'] ] = time();
|
2057 |
+
}
|
2058 |
+
}
|
2059 |
+
|
2060 |
+
if ( ! empty( $deactivated ) ) {
|
2061 |
+
update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ) );
|
2062 |
+
}
|
2063 |
+
}
|
2064 |
+
|
2065 |
+
/**
|
2066 |
+
* Echo the current TGMPA version number to the page.
|
2067 |
+
*
|
2068 |
+
* @since 2.5.0
|
2069 |
+
*/
|
2070 |
+
public function show_tgmpa_version() {
|
2071 |
+
echo '<p style="float: right; padding: 0em 1.5em 0.5em 0;"><strong><small>',
|
2072 |
+
esc_html(
|
2073 |
+
sprintf(
|
2074 |
+
/* translators: %s: version number */
|
2075 |
+
__( 'TGMPA v%s', 'tgmpa' ),
|
2076 |
+
self::TGMPA_VERSION
|
2077 |
+
)
|
2078 |
+
),
|
2079 |
+
'</small></strong></p>';
|
2080 |
+
}
|
2081 |
+
|
2082 |
+
/**
|
2083 |
+
* Returns the singleton instance of the class.
|
2084 |
+
*
|
2085 |
+
* @since 2.4.0
|
2086 |
+
*
|
2087 |
+
* @return \TGM_Plugin_Activation The TGM_Plugin_Activation object.
|
2088 |
+
*/
|
2089 |
+
public static function get_instance() {
|
2090 |
+
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
|
2091 |
+
self::$instance = new self();
|
2092 |
+
}
|
2093 |
+
|
2094 |
+
return self::$instance;
|
2095 |
+
}
|
2096 |
+
}
|
2097 |
+
|
2098 |
+
if ( ! function_exists( 'load_tgm_plugin_activation' ) ) {
|
2099 |
+
/**
|
2100 |
+
* Ensure only one instance of the class is ever invoked.
|
2101 |
+
*
|
2102 |
+
* @since 2.5.0
|
2103 |
+
*/
|
2104 |
+
function load_tgm_plugin_activation() {
|
2105 |
+
$GLOBALS['tgmpa'] = TGM_Plugin_Activation::get_instance();
|
2106 |
+
}
|
2107 |
+
}
|
2108 |
+
|
2109 |
+
if ( did_action( 'plugins_loaded' ) ) {
|
2110 |
+
load_tgm_plugin_activation();
|
2111 |
+
} else {
|
2112 |
+
add_action( 'plugins_loaded', 'load_tgm_plugin_activation' );
|
2113 |
+
}
|
2114 |
+
}
|
2115 |
+
|
2116 |
+
if ( ! function_exists( 'tgmpa' ) ) {
|
2117 |
+
/**
|
2118 |
+
* Helper function to register a collection of required plugins.
|
2119 |
+
*
|
2120 |
+
* @since 2.0.0
|
2121 |
+
* @api
|
2122 |
+
*
|
2123 |
+
* @param array $plugins An array of plugin arrays.
|
2124 |
+
* @param array $config Optional. An array of configuration values.
|
2125 |
+
*/
|
2126 |
+
function tgmpa( $plugins, $config = array() ) {
|
2127 |
+
$instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
2128 |
+
|
2129 |
+
foreach ( $plugins as $plugin ) {
|
2130 |
+
call_user_func( array( $instance, 'register' ), $plugin );
|
2131 |
+
}
|
2132 |
+
|
2133 |
+
if ( ! empty( $config ) && is_array( $config ) ) {
|
2134 |
+
// Send out notices for deprecated arguments passed.
|
2135 |
+
if ( isset( $config['notices'] ) ) {
|
2136 |
+
_deprecated_argument( __FUNCTION__, '2.2.0', 'The `notices` config parameter was renamed to `has_notices` in TGMPA 2.2.0. Please adjust your configuration.' );
|
2137 |
+
if ( ! isset( $config['has_notices'] ) ) {
|
2138 |
+
$config['has_notices'] = $config['notices'];
|
2139 |
+
}
|
2140 |
+
}
|
2141 |
+
|
2142 |
+
if ( isset( $config['parent_menu_slug'] ) ) {
|
2143 |
+
_deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_menu_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
|
2144 |
+
}
|
2145 |
+
if ( isset( $config['parent_url_slug'] ) ) {
|
2146 |
+
_deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_url_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
|
2147 |
+
}
|
2148 |
+
|
2149 |
+
call_user_func( array( $instance, 'config' ), $config );
|
2150 |
+
}
|
2151 |
+
}
|
2152 |
+
}
|
2153 |
+
|
2154 |
+
/**
|
2155 |
+
* WP_List_Table isn't always available. If it isn't available,
|
2156 |
+
* we load it here.
|
2157 |
+
*
|
2158 |
+
* @since 2.2.0
|
2159 |
+
*/
|
2160 |
+
if ( ! class_exists( 'WP_List_Table' ) ) {
|
2161 |
+
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
2162 |
+
}
|
2163 |
+
|
2164 |
+
if ( ! class_exists( 'TGMPA_List_Table' ) ) {
|
2165 |
+
|
2166 |
+
/**
|
2167 |
+
* List table class for handling plugins.
|
2168 |
+
*
|
2169 |
+
* Extends the WP_List_Table class to provide a future-compatible
|
2170 |
+
* way of listing out all required/recommended plugins.
|
2171 |
+
*
|
2172 |
+
* Gives users an interface similar to the Plugin Administration
|
2173 |
+
* area with similar (albeit stripped down) capabilities.
|
2174 |
+
*
|
2175 |
+
* This class also allows for the bulk install of plugins.
|
2176 |
+
*
|
2177 |
+
* @since 2.2.0
|
2178 |
+
*
|
2179 |
+
* @package TGM-Plugin-Activation
|
2180 |
+
* @author Thomas Griffin
|
2181 |
+
* @author Gary Jones
|
2182 |
+
*/
|
2183 |
+
class TGMPA_List_Table extends WP_List_Table {
|
2184 |
+
/**
|
2185 |
+
* TGMPA instance.
|
2186 |
+
*
|
2187 |
+
* @since 2.5.0
|
2188 |
+
*
|
2189 |
+
* @var object
|
2190 |
+
*/
|
2191 |
+
protected $tgmpa;
|
2192 |
+
|
2193 |
+
/**
|
2194 |
+
* The currently chosen view.
|
2195 |
+
*
|
2196 |
+
* @since 2.5.0
|
2197 |
+
*
|
2198 |
+
* @var string One of: 'all', 'install', 'update', 'activate'
|
2199 |
+
*/
|
2200 |
+
public $view_context = 'all';
|
2201 |
+
|
2202 |
+
/**
|
2203 |
+
* The plugin counts for the various views.
|
2204 |
+
*
|
2205 |
+
* @since 2.5.0
|
2206 |
+
*
|
2207 |
+
* @var array
|
2208 |
+
*/
|
2209 |
+
protected $view_totals = array(
|
2210 |
+
'all' => 0,
|
2211 |
+
'install' => 0,
|
2212 |
+
'update' => 0,
|
2213 |
+
'activate' => 0,
|
2214 |
+
);
|
2215 |
+
|
2216 |
+
/**
|
2217 |
+
* References parent constructor and sets defaults for class.
|
2218 |
+
*
|
2219 |
+
* @since 2.2.0
|
2220 |
+
*/
|
2221 |
+
public function __construct() {
|
2222 |
+
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
2223 |
+
|
2224 |
+
parent::__construct(
|
2225 |
+
array(
|
2226 |
+
'singular' => 'plugin',
|
2227 |
+
'plural' => 'plugins',
|
2228 |
+
'ajax' => false,
|
2229 |
+
)
|
2230 |
+
);
|
2231 |
+
|
2232 |
+
if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'install', 'update', 'activate' ), true ) ) {
|
2233 |
+
$this->view_context = sanitize_key( $_REQUEST['plugin_status'] );
|
2234 |
+
}
|
2235 |
+
|
2236 |
+
add_filter( 'tgmpa_table_data_items', array( $this, 'sort_table_items' ) );
|
2237 |
+
}
|
2238 |
+
|
2239 |
+
/**
|
2240 |
+
* Get a list of CSS classes for the <table> tag.
|
2241 |
+
*
|
2242 |
+
* Overruled to prevent the 'plural' argument from being added.
|
2243 |
+
*
|
2244 |
+
* @since 2.5.0
|
2245 |
+
*
|
2246 |
+
* @return array CSS classnames.
|
2247 |
+
*/
|
2248 |
+
public function get_table_classes() {
|
2249 |
+
return array( 'widefat', 'fixed' );
|
2250 |
+
}
|
2251 |
+
|
2252 |
+
/**
|
2253 |
+
* Gathers and renames all of our plugin information to be used by WP_List_Table to create our table.
|
2254 |
+
*
|
2255 |
+
* @since 2.2.0
|
2256 |
+
*
|
2257 |
+
* @return array $table_data Information for use in table.
|
2258 |
+
*/
|
2259 |
+
protected function _gather_plugin_data() {
|
2260 |
+
// Load thickbox for plugin links.
|
2261 |
+
$this->tgmpa->admin_init();
|
2262 |
+
$this->tgmpa->thickbox();
|
2263 |
+
|
2264 |
+
// Categorize the plugins which have open actions.
|
2265 |
+
$plugins = $this->categorize_plugins_to_views();
|
2266 |
+
|
2267 |
+
// Set the counts for the view links.
|
2268 |
+
$this->set_view_totals( $plugins );
|
2269 |
+
|
2270 |
+
// Prep variables for use and grab list of all installed plugins.
|
2271 |
+
$table_data = array();
|
2272 |
+
$i = 0;
|
2273 |
+
|
2274 |
+
// Redirect to the 'all' view if no plugins were found for the selected view context.
|
2275 |
+
if ( empty( $plugins[ $this->view_context ] ) ) {
|
2276 |
+
$this->view_context = 'all';
|
2277 |
+
}
|
2278 |
+
|
2279 |
+
foreach ( $plugins[ $this->view_context ] as $slug => $plugin ) {
|
2280 |
+
$table_data[ $i ]['sanitized_plugin'] = $plugin['name'];
|
2281 |
+
$table_data[ $i ]['slug'] = $slug;
|
2282 |
+
$table_data[ $i ]['plugin'] = '<strong>' . $this->tgmpa->get_info_link( $slug ) . '</strong>';
|
2283 |
+
$table_data[ $i ]['source'] = $this->get_plugin_source_type_text( $plugin['source_type'] );
|
2284 |
+
$table_data[ $i ]['type'] = $this->get_plugin_advise_type_text( $plugin['required'] );
|
2285 |
+
$table_data[ $i ]['status'] = $this->get_plugin_status_text( $slug );
|
2286 |
+
$table_data[ $i ]['installed_version'] = $this->tgmpa->get_installed_version( $slug );
|
2287 |
+
$table_data[ $i ]['minimum_version'] = $plugin['version'];
|
2288 |
+
$table_data[ $i ]['available_version'] = $this->tgmpa->does_plugin_have_update( $slug );
|
2289 |
+
|
2290 |
+
// Prep the upgrade notice info.
|
2291 |
+
$upgrade_notice = $this->tgmpa->get_upgrade_notice( $slug );
|
2292 |
+
if ( ! empty( $upgrade_notice ) ) {
|
2293 |
+
$table_data[ $i ]['upgrade_notice'] = $upgrade_notice;
|
2294 |
+
|
2295 |
+
add_action( "tgmpa_after_plugin_row_{$slug}", array( $this, 'wp_plugin_update_row' ), 10, 2 );
|
2296 |
+
}
|
2297 |
+
|
2298 |
+
$table_data[ $i ] = apply_filters( 'tgmpa_table_data_item', $table_data[ $i ], $plugin );
|
2299 |
+
|
2300 |
+
$i++;
|
2301 |
+
}
|
2302 |
+
|
2303 |
+
return $table_data;
|
2304 |
+
}
|
2305 |
+
|
2306 |
+
/**
|
2307 |
+
* Categorize the plugins which have open actions into views for the TGMPA page.
|
2308 |
+
*
|
2309 |
+
* @since 2.5.0
|
2310 |
+
*/
|
2311 |
+
protected function categorize_plugins_to_views() {
|
2312 |
+
$plugins = array(
|
2313 |
+
'all' => array(), // Meaning: all plugins which still have open actions.
|
2314 |
+
'install' => array(),
|
2315 |
+
'update' => array(),
|
2316 |
+
'activate' => array(),
|
2317 |
+
);
|
2318 |
+
|
2319 |
+
foreach ( $this->tgmpa->plugins as $slug => $plugin ) {
|
2320 |
+
if ( $this->tgmpa->is_plugin_active( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2321 |
+
// No need to display plugins if they are installed, up-to-date and active.
|
2322 |
+
continue;
|
2323 |
+
} else {
|
2324 |
+
$plugins['all'][ $slug ] = $plugin;
|
2325 |
+
|
2326 |
+
if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
|
2327 |
+
$plugins['install'][ $slug ] = $plugin;
|
2328 |
+
} else {
|
2329 |
+
if ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2330 |
+
$plugins['update'][ $slug ] = $plugin;
|
2331 |
+
}
|
2332 |
+
|
2333 |
+
if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
|
2334 |
+
$plugins['activate'][ $slug ] = $plugin;
|
2335 |
+
}
|
2336 |
+
}
|
2337 |
+
}
|
2338 |
+
}
|
2339 |
+
|
2340 |
+
return $plugins;
|
2341 |
+
}
|
2342 |
+
|
2343 |
+
/**
|
2344 |
+
* Set the counts for the view links.
|
2345 |
+
*
|
2346 |
+
* @since 2.5.0
|
2347 |
+
*
|
2348 |
+
* @param array $plugins Plugins order by view.
|
2349 |
+
*/
|
2350 |
+
protected function set_view_totals( $plugins ) {
|
2351 |
+
foreach ( $plugins as $type => $list ) {
|
2352 |
+
$this->view_totals[ $type ] = count( $list );
|
2353 |
+
}
|
2354 |
+
}
|
2355 |
+
|
2356 |
+
/**
|
2357 |
+
* Get the plugin required/recommended text string.
|
2358 |
+
*
|
2359 |
+
* @since 2.5.0
|
2360 |
+
*
|
2361 |
+
* @param string $required Plugin required setting.
|
2362 |
+
* @return string
|
2363 |
+
*/
|
2364 |
+
protected function get_plugin_advise_type_text( $required ) {
|
2365 |
+
if ( true === $required ) {
|
2366 |
+
return __( 'Required', 'tgmpa' );
|
2367 |
+
}
|
2368 |
+
|
2369 |
+
return __( 'Recommended', 'tgmpa' );
|
2370 |
+
}
|
2371 |
+
|
2372 |
+
/**
|
2373 |
+
* Get the plugin source type text string.
|
2374 |
+
*
|
2375 |
+
* @since 2.5.0
|
2376 |
+
*
|
2377 |
+
* @param string $type Plugin type.
|
2378 |
+
* @return string
|
2379 |
+
*/
|
2380 |
+
protected function get_plugin_source_type_text( $type ) {
|
2381 |
+
$string = '';
|
2382 |
+
|
2383 |
+
switch ( $type ) {
|
2384 |
+
case 'repo':
|
2385 |
+
$string = __( 'WordPress Repository', 'tgmpa' );
|
2386 |
+
break;
|
2387 |
+
case 'external':
|
2388 |
+
$string = __( 'External Source', 'tgmpa' );
|
2389 |
+
break;
|
2390 |
+
case 'bundled':
|
2391 |
+
$string = __( 'Pre-Packaged', 'tgmpa' );
|
2392 |
+
break;
|
2393 |
+
}
|
2394 |
+
|
2395 |
+
return $string;
|
2396 |
+
}
|
2397 |
+
|
2398 |
+
/**
|
2399 |
+
* Determine the plugin status message.
|
2400 |
+
*
|
2401 |
+
* @since 2.5.0
|
2402 |
+
*
|
2403 |
+
* @param string $slug Plugin slug.
|
2404 |
+
* @return string
|
2405 |
+
*/
|
2406 |
+
protected function get_plugin_status_text( $slug ) {
|
2407 |
+
if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
|
2408 |
+
return __( 'Not Installed', 'tgmpa' );
|
2409 |
+
}
|
2410 |
+
|
2411 |
+
if ( ! $this->tgmpa->is_plugin_active( $slug ) ) {
|
2412 |
+
$install_status = __( 'Installed But Not Activated', 'tgmpa' );
|
2413 |
+
} else {
|
2414 |
+
$install_status = __( 'Active', 'tgmpa' );
|
2415 |
+
}
|
2416 |
+
|
2417 |
+
$update_status = '';
|
2418 |
+
|
2419 |
+
if ( $this->tgmpa->does_plugin_require_update( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2420 |
+
$update_status = __( 'Required Update not Available', 'tgmpa' );
|
2421 |
+
|
2422 |
+
} elseif ( $this->tgmpa->does_plugin_require_update( $slug ) ) {
|
2423 |
+
$update_status = __( 'Requires Update', 'tgmpa' );
|
2424 |
+
|
2425 |
+
} elseif ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
|
2426 |
+
$update_status = __( 'Update recommended', 'tgmpa' );
|
2427 |
+
}
|
2428 |
+
|
2429 |
+
if ( '' === $update_status ) {
|
2430 |
+
return $install_status;
|
2431 |
+
}
|
2432 |
+
|
2433 |
+
return sprintf(
|
2434 |
+
/* translators: 1: install status, 2: update status */
|
2435 |
+
_x( '%1$s, %2$s', 'Install/Update Status', 'tgmpa' ),
|
2436 |
+
$install_status,
|
2437 |
+
$update_status
|
2438 |
+
);
|
2439 |
+
}
|
2440 |
+
|
2441 |
+
/**
|
2442 |
+
* Sort plugins by Required/Recommended type and by alphabetical plugin name within each type.
|
2443 |
+
*
|
2444 |
+
* @since 2.5.0
|
2445 |
+
*
|
2446 |
+
* @param array $items Prepared table items.
|
2447 |
+
* @return array Sorted table items.
|
2448 |
+
*/
|
2449 |
+
public function sort_table_items( $items ) {
|
2450 |
+
$type = array();
|
2451 |
+
$name = array();
|
2452 |
+
|
2453 |
+
foreach ( $items as $i => $plugin ) {
|
2454 |
+
$type[ $i ] = $plugin['type']; // Required / recommended.
|
2455 |
+
$name[ $i ] = $plugin['sanitized_plugin'];
|
2456 |
+
}
|
2457 |
+
|
2458 |
+
array_multisort( $type, SORT_DESC, $name, SORT_ASC, $items );
|
2459 |
+
|
2460 |
+
return $items;
|
2461 |
+
}
|
2462 |
+
|
2463 |
+
/**
|
2464 |
+
* Get an associative array ( id => link ) of the views available on this table.
|
2465 |
+
*
|
2466 |
+
* @since 2.5.0
|
2467 |
+
*
|
2468 |
+
* @return array
|
2469 |
+
*/
|
2470 |
+
public function get_views() {
|
2471 |
+
$status_links = array();
|
2472 |
+
|
2473 |
+
foreach ( $this->view_totals as $type => $count ) {
|
2474 |
+
if ( $count < 1 ) {
|
2475 |
+
continue;
|
2476 |
+
}
|
2477 |
+
|
2478 |
+
switch ( $type ) {
|
2479 |
+
case 'all':
|
2480 |
+
/* translators: 1: number of plugins. */
|
2481 |
+
$text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'plugins', 'tgmpa' );
|
2482 |
+
break;
|
2483 |
+
case 'install':
|
2484 |
+
/* translators: 1: number of plugins. */
|
2485 |
+
$text = _n( 'To Install <span class="count">(%s)</span>', 'To Install <span class="count">(%s)</span>', $count, 'tgmpa' );
|
2486 |
+
break;
|
2487 |
+
case 'update':
|
2488 |
+
/* translators: 1: number of plugins. */
|
2489 |
+
$text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count, 'tgmpa' );
|
2490 |
+
break;
|
2491 |
+
case 'activate':
|
2492 |
+
/* translators: 1: number of plugins. */
|
2493 |
+
$text = _n( 'To Activate <span class="count">(%s)</span>', 'To Activate <span class="count">(%s)</span>', $count, 'tgmpa' );
|
2494 |
+
break;
|
2495 |
+
default:
|
2496 |
+
$text = '';
|
2497 |
+
break;
|
2498 |
+
}
|
2499 |
+
|
2500 |
+
if ( ! empty( $text ) ) {
|
2501 |
+
|
2502 |
+
$status_links[ $type ] = sprintf(
|
2503 |
+
'<a href="%s"%s>%s</a>',
|
2504 |
+
esc_url( $this->tgmpa->get_tgmpa_status_url( $type ) ),
|
2505 |
+
( $type === $this->view_context ) ? ' class="current"' : '',
|
2506 |
+
sprintf( $text, number_format_i18n( $count ) )
|
2507 |
+
);
|
2508 |
+
}
|
2509 |
+
}
|
2510 |
+
|
2511 |
+
return $status_links;
|
2512 |
+
}
|
2513 |
+
|
2514 |
+
/**
|
2515 |
+
* Create default columns to display important plugin information
|
2516 |
+
* like type, action and status.
|
2517 |
+
*
|
2518 |
+
* @since 2.2.0
|
2519 |
+
*
|
2520 |
+
* @param array $item Array of item data.
|
2521 |
+
* @param string $column_name The name of the column.
|
2522 |
+
* @return string
|
2523 |
+
*/
|
2524 |
+
public function column_default( $item, $column_name ) {
|
2525 |
+
return $item[ $column_name ];
|
2526 |
+
}
|
2527 |
+
|
2528 |
+
/**
|
2529 |
+
* Required for bulk installing.
|
2530 |
+
*
|
2531 |
+
* Adds a checkbox for each plugin.
|
2532 |
+
*
|
2533 |
+
* @since 2.2.0
|
2534 |
+
*
|
2535 |
+
* @param array $item Array of item data.
|
2536 |
+
* @return string The input checkbox with all necessary info.
|
2537 |
+
*/
|
2538 |
+
public function column_cb( $item ) {
|
2539 |
+
return sprintf(
|
2540 |
+
'<input type="checkbox" name="%1$s[]" value="%2$s" id="%3$s" />',
|
2541 |
+
esc_attr( $this->_args['singular'] ),
|
2542 |
+
esc_attr( $item['slug'] ),
|
2543 |
+
esc_attr( $item['sanitized_plugin'] )
|
2544 |
+
);
|
2545 |
+
}
|
2546 |
+
|
2547 |
+
/**
|
2548 |
+
* Create default title column along with the action links.
|
2549 |
+
*
|
2550 |
+
* @since 2.2.0
|
2551 |
+
*
|
2552 |
+
* @param array $item Array of item data.
|
2553 |
+
* @return string The plugin name and action links.
|
2554 |
+
*/
|
2555 |
+
public function column_plugin( $item ) {
|
2556 |
+
return sprintf(
|
2557 |
+
'%1$s %2$s',
|
2558 |
+
$item['plugin'],
|
2559 |
+
$this->row_actions( $this->get_row_actions( $item ), true )
|
2560 |
+
);
|
2561 |
+
}
|
2562 |
+
|
2563 |
+
/**
|
2564 |
+
* Create version information column.
|
2565 |
+
*
|
2566 |
+
* @since 2.5.0
|
2567 |
+
*
|
2568 |
+
* @param array $item Array of item data.
|
2569 |
+
* @return string HTML-formatted version information.
|
2570 |
+
*/
|
2571 |
+
public function column_version( $item ) {
|
2572 |
+
$output = array();
|
2573 |
+
|
2574 |
+
if ( $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
|
2575 |
+
$installed = ! empty( $item['installed_version'] ) ? $item['installed_version'] : _x( 'unknown', 'as in: "version nr unknown"', 'tgmpa' );
|
2576 |
+
|
2577 |
+
$color = '';
|
2578 |
+
if ( ! empty( $item['minimum_version'] ) && $this->tgmpa->does_plugin_require_update( $item['slug'] ) ) {
|
2579 |
+
$color = ' color: #ff0000; font-weight: bold;';
|
2580 |
+
}
|
2581 |
+
|
2582 |
+
$output[] = sprintf(
|
2583 |
+
'<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Installed version:', 'tgmpa' ) . '</p>',
|
2584 |
+
$color,
|
2585 |
+
$installed
|
2586 |
+
);
|
2587 |
+
}
|
2588 |
+
|
2589 |
+
if ( ! empty( $item['minimum_version'] ) ) {
|
2590 |
+
$output[] = sprintf(
|
2591 |
+
'<p><span style="min-width: 32px; text-align: right; float: right;">%1$s</span>' . __( 'Minimum required version:', 'tgmpa' ) . '</p>',
|
2592 |
+
$item['minimum_version']
|
2593 |
+
);
|
2594 |
+
}
|
2595 |
+
|
2596 |
+
if ( ! empty( $item['available_version'] ) ) {
|
2597 |
+
$color = '';
|
2598 |
+
if ( ! empty( $item['minimum_version'] ) && version_compare( $item['available_version'], $item['minimum_version'], '>=' ) ) {
|
2599 |
+
$color = ' color: #71C671; font-weight: bold;';
|
2600 |
+
}
|
2601 |
+
|
2602 |
+
$output[] = sprintf(
|
2603 |
+
'<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Available version:', 'tgmpa' ) . '</p>',
|
2604 |
+
$color,
|
2605 |
+
$item['available_version']
|
2606 |
+
);
|
2607 |
+
}
|
2608 |
+
|
2609 |
+
if ( empty( $output ) ) {
|
2610 |
+
return ' '; // Let's not break the table layout.
|
2611 |
+
} else {
|
2612 |
+
return implode( "\n", $output );
|
2613 |
+
}
|
2614 |
+
}
|
2615 |
+
|
2616 |
+
/**
|
2617 |
+
* Sets default message within the plugins table if no plugins
|
2618 |
+
* are left for interaction.
|
2619 |
+
*
|
2620 |
+
* Hides the menu item to prevent the user from clicking and
|
2621 |
+
* getting a permissions error.
|
2622 |
+
*
|
2623 |
+
* @since 2.2.0
|
2624 |
+
*/
|
2625 |
+
public function no_items() {
|
2626 |
+
echo esc_html__( 'No plugins to install, update or activate.', 'tgmpa' ) . ' <a href="' . esc_url( self_admin_url() ) . '"> ' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>';
|
2627 |
+
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
|
2628 |
+
}
|
2629 |
+
|
2630 |
+
/**
|
2631 |
+
* Output all the column information within the table.
|
2632 |
+
*
|
2633 |
+
* @since 2.2.0
|
2634 |
+
*
|
2635 |
+
* @return array $columns The column names.
|
2636 |
+
*/
|
2637 |
+
public function get_columns() {
|
2638 |
+
$columns = array(
|
2639 |
+
'cb' => '<input type="checkbox" />',
|
2640 |
+
'plugin' => __( 'Plugin', 'tgmpa' ),
|
2641 |
+
'source' => __( 'Source', 'tgmpa' ),
|
2642 |
+
'type' => __( 'Type', 'tgmpa' ),
|
2643 |
+
);
|
2644 |
+
|
2645 |
+
if ( 'all' === $this->view_context || 'update' === $this->view_context ) {
|
2646 |
+
$columns['version'] = __( 'Version', 'tgmpa' );
|
2647 |
+
$columns['status'] = __( 'Status', 'tgmpa' );
|
2648 |
+
}
|
2649 |
+
|
2650 |
+
return apply_filters( 'tgmpa_table_columns', $columns );
|
2651 |
+
}
|
2652 |
+
|
2653 |
+
/**
|
2654 |
+
* Get name of default primary column
|
2655 |
+
*
|
2656 |
+
* @since 2.5.0 / WP 4.3+ compatibility
|
2657 |
+
* @access protected
|
2658 |
+
*
|
2659 |
+
* @return string
|
2660 |
+
*/
|
2661 |
+
protected function get_default_primary_column_name() {
|
2662 |
+
return 'plugin';
|
2663 |
+
}
|
2664 |
+
|
2665 |
+
/**
|
2666 |
+
* Get the name of the primary column.
|
2667 |
+
*
|
2668 |
+
* @since 2.5.0 / WP 4.3+ compatibility
|
2669 |
+
* @access protected
|
2670 |
+
*
|
2671 |
+
* @return string The name of the primary column.
|
2672 |
+
*/
|
2673 |
+
protected function get_primary_column_name() {
|
2674 |
+
if ( method_exists( 'WP_List_Table', 'get_primary_column_name' ) ) {
|
2675 |
+
return parent::get_primary_column_name();
|
2676 |
+
} else {
|
2677 |
+
return $this->get_default_primary_column_name();
|
2678 |
+
}
|
2679 |
+
}
|
2680 |
+
|
2681 |
+
/**
|
2682 |
+
* Get the actions which are relevant for a specific plugin row.
|
2683 |
+
*
|
2684 |
+
* @since 2.5.0
|
2685 |
+
*
|
2686 |
+
* @param array $item Array of item data.
|
2687 |
+
* @return array Array with relevant action links.
|
2688 |
+
*/
|
2689 |
+
protected function get_row_actions( $item ) {
|
2690 |
+
$actions = array();
|
2691 |
+
$action_links = array();
|
2692 |
+
|
2693 |
+
// Display the 'Install' action link if the plugin is not yet available.
|
2694 |
+
if ( ! $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
|
2695 |
+
/* translators: %2$s: plugin name in screen reader markup */
|
2696 |
+
$actions['install'] = __( 'Install %2$s', 'tgmpa' );
|
2697 |
+
} else {
|
2698 |
+
// Display the 'Update' action link if an update is available and WP complies with plugin minimum.
|
2699 |
+
if ( false !== $this->tgmpa->does_plugin_have_update( $item['slug'] ) && $this->tgmpa->can_plugin_update( $item['slug'] ) ) {
|
2700 |
+
/* translators: %2$s: plugin name in screen reader markup */
|
2701 |
+
$actions['update'] = __( 'Update %2$s', 'tgmpa' );
|
2702 |
+
}
|
2703 |
+
|
2704 |
+
// Display the 'Activate' action link, but only if the plugin meets the minimum version.
|
2705 |
+
if ( $this->tgmpa->can_plugin_activate( $item['slug'] ) ) {
|
2706 |
+
/* translators: %2$s: plugin name in screen reader markup */
|
2707 |
+
$actions['activate'] = __( 'Activate %2$s', 'tgmpa' );
|
2708 |
+
}
|
2709 |
+
}
|
2710 |
+
|
2711 |
+
// Create the actual links.
|
2712 |
+
foreach ( $actions as $action => $text ) {
|
2713 |
+
$nonce_url = wp_nonce_url(
|
2714 |
+
add_query_arg(
|
2715 |
+
array(
|
2716 |
+
'plugin' => urlencode( $item['slug'] ),
|
2717 |
+
'tgmpa-' . $action => $action . '-plugin',
|
2718 |
+
),
|
2719 |
+
$this->tgmpa->get_tgmpa_url()
|
2720 |
+
),
|
2721 |
+
'tgmpa-' . $action,
|
2722 |
+
'tgmpa-nonce'
|
2723 |
+
);
|
2724 |
+
|
2725 |
+
$action_links[ $action ] = sprintf(
|
2726 |
+
'<a href="%1$s">' . esc_html( $text ) . '</a>', // $text contains the second placeholder.
|
2727 |
+
esc_url( $nonce_url ),
|
2728 |
+
'<span class="screen-reader-text">' . esc_html( $item['sanitized_plugin'] ) . '</span>'
|
2729 |
+
);
|
2730 |
+
}
|
2731 |
+
|
2732 |
+
$prefix = ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) ? 'network_admin_' : '';
|
2733 |
+
return apply_filters( "tgmpa_{$prefix}plugin_action_links", array_filter( $action_links ), $item['slug'], $item, $this->view_context );
|
2734 |
+
}
|
2735 |
+
|
2736 |
+
/**
|
2737 |
+
* Generates content for a single row of the table.
|
2738 |
+
*
|
2739 |
+
* @since 2.5.0
|
2740 |
+
*
|
2741 |
+
* @param object $item The current item.
|
2742 |
+
*/
|
2743 |
+
public function single_row( $item ) {
|
2744 |
+
parent::single_row( $item );
|
2745 |
+
|
2746 |
+
/**
|
2747 |
+
* Fires after each specific row in the TGMPA Plugins list table.
|
2748 |
+
*
|
2749 |
+
* The dynamic portion of the hook name, `$item['slug']`, refers to the slug
|
2750 |
+
* for the plugin.
|
2751 |
+
*
|
2752 |
+
* @since 2.5.0
|
2753 |
+
*/
|
2754 |
+
do_action( "tgmpa_after_plugin_row_{$item['slug']}", $item['slug'], $item, $this->view_context );
|
2755 |
+
}
|
2756 |
+
|
2757 |
+
/**
|
2758 |
+
* Show the upgrade notice below a plugin row if there is one.
|
2759 |
+
*
|
2760 |
+
* @since 2.5.0
|
2761 |
+
*
|
2762 |
+
* @see /wp-admin/includes/update.php
|
2763 |
+
*
|
2764 |
+
* @param string $slug Plugin slug.
|
2765 |
+
* @param array $item The information available in this table row.
|
2766 |
+
* @return null Return early if upgrade notice is empty.
|
2767 |
+
*/
|
2768 |
+
public function wp_plugin_update_row( $slug, $item ) {
|
2769 |
+
if ( empty( $item['upgrade_notice'] ) ) {
|
2770 |
+
return;
|
2771 |
+
}
|
2772 |
+
|
2773 |
+
echo '
|
2774 |
+
<tr class="plugin-update-tr">
|
2775 |
+
<td colspan="', absint( $this->get_column_count() ), '" class="plugin-update colspanchange">
|
2776 |
+
<div class="update-message">',
|
2777 |
+
esc_html__( 'Upgrade message from the plugin author:', 'tgmpa' ),
|
2778 |
+
' <strong>', wp_kses_data( $item['upgrade_notice'] ), '</strong>
|
2779 |
+
</div>
|
2780 |
+
</td>
|
2781 |
+
</tr>';
|
2782 |
+
}
|
2783 |
+
|
2784 |
+
/**
|
2785 |
+
* Extra controls to be displayed between bulk actions and pagination.
|
2786 |
+
*
|
2787 |
+
* @since 2.5.0
|
2788 |
+
*
|
2789 |
+
* @param string $which 'top' or 'bottom' table navigation.
|
2790 |
+
*/
|
2791 |
+
public function extra_tablenav( $which ) {
|
2792 |
+
if ( 'bottom' === $which ) {
|
2793 |
+
$this->tgmpa->show_tgmpa_version();
|
2794 |
+
}
|
2795 |
+
}
|
2796 |
+
|
2797 |
+
/**
|
2798 |
+
* Defines the bulk actions for handling registered plugins.
|
2799 |
+
*
|
2800 |
+
* @since 2.2.0
|
2801 |
+
*
|
2802 |
+
* @return array $actions The bulk actions for the plugin install table.
|
2803 |
+
*/
|
2804 |
+
public function get_bulk_actions() {
|
2805 |
+
|
2806 |
+
$actions = array();
|
2807 |
+
|
2808 |
+
if ( 'update' !== $this->view_context && 'activate' !== $this->view_context ) {
|
2809 |
+
if ( current_user_can( 'install_plugins' ) ) {
|
2810 |
+
$actions['tgmpa-bulk-install'] = __( 'Install', 'tgmpa' );
|
2811 |
+
}
|
2812 |
+
}
|
2813 |
+
|
2814 |
+
if ( 'install' !== $this->view_context ) {
|
2815 |
+
if ( current_user_can( 'update_plugins' ) ) {
|
2816 |
+
$actions['tgmpa-bulk-update'] = __( 'Update', 'tgmpa' );
|
2817 |
+
}
|
2818 |
+
if ( current_user_can( 'activate_plugins' ) ) {
|
2819 |
+
$actions['tgmpa-bulk-activate'] = __( 'Activate', 'tgmpa' );
|
2820 |
+
}
|
2821 |
+
}
|
2822 |
+
|
2823 |
+
return $actions;
|
2824 |
+
}
|
2825 |
+
|
2826 |
+
/**
|
2827 |
+
* Processes bulk installation and activation actions.
|
2828 |
+
*
|
2829 |
+
* The bulk installation process looks for the $_POST information and passes that
|
2830 |
+
* through if a user has to use WP_Filesystem to enter their credentials.
|
2831 |
+
*
|
2832 |
+
* @since 2.2.0
|
2833 |
+
*/
|
2834 |
+
public function process_bulk_actions() {
|
2835 |
+
// Bulk installation process.
|
2836 |
+
if ( 'tgmpa-bulk-install' === $this->current_action() || 'tgmpa-bulk-update' === $this->current_action() ) {
|
2837 |
+
|
2838 |
+
check_admin_referer( 'bulk-' . $this->_args['plural'] );
|
2839 |
+
|
2840 |
+
$install_type = 'install';
|
2841 |
+
if ( 'tgmpa-bulk-update' === $this->current_action() ) {
|
2842 |
+
$install_type = 'update';
|
2843 |
+
}
|
2844 |
+
|
2845 |
+
$plugins_to_install = array();
|
2846 |
+
|
2847 |
+
// Did user actually select any plugins to install/update ?
|
2848 |
+
if ( empty( $_POST['plugin'] ) ) {
|
2849 |
+
if ( 'install' === $install_type ) {
|
2850 |
+
$message = __( 'No plugins were selected to be installed. No action taken.', 'tgmpa' );
|
2851 |
+
} else {
|
2852 |
+
$message = __( 'No plugins were selected to be updated. No action taken.', 'tgmpa' );
|
2853 |
+
}
|
2854 |
+
|
2855 |
+
echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
|
2856 |
+
|
2857 |
+
return false;
|
2858 |
+
}
|
2859 |
+
|
2860 |
+
if ( is_array( $_POST['plugin'] ) ) {
|
2861 |
+
$plugins_to_install = (array) $_POST['plugin'];
|
2862 |
+
} elseif ( is_string( $_POST['plugin'] ) ) {
|
2863 |
+
// Received via Filesystem page - un-flatten array (WP bug #19643).
|
2864 |
+
$plugins_to_install = explode( ',', $_POST['plugin'] );
|
2865 |
+
}
|
2866 |
+
|
2867 |
+
// Sanitize the received input.
|
2868 |
+
$plugins_to_install = array_map( 'urldecode', $plugins_to_install );
|
2869 |
+
$plugins_to_install = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins_to_install );
|
2870 |
+
|
2871 |
+
// Validate the received input.
|
2872 |
+
foreach ( $plugins_to_install as $key => $slug ) {
|
2873 |
+
// Check if the plugin was registered with TGMPA and remove if not.
|
2874 |
+
if ( ! isset( $this->tgmpa->plugins[ $slug ] ) ) {
|
2875 |
+
unset( $plugins_to_install[ $key ] );
|
2876 |
+
continue;
|
2877 |
+
}
|
2878 |
+
|
2879 |
+
// For install: make sure this is a plugin we *can* install and not one already installed.
|
2880 |
+
if ( 'install' === $install_type && true === $this->tgmpa->is_plugin_installed( $slug ) ) {
|
2881 |
+
unset( $plugins_to_install[ $key ] );
|
2882 |
+
}
|
2883 |
+
|
2884 |
+
// For updates: make sure this is a plugin we *can* update (update available and WP version ok).
|
2885 |
+
if ( 'update' === $install_type && false === $this->tgmpa->is_plugin_updatetable( $slug ) ) {
|
2886 |
+
unset( $plugins_to_install[ $key ] );
|
2887 |
+
}
|
2888 |
+
}
|
2889 |
+
|
2890 |
+
// No need to proceed further if we have no plugins to handle.
|
2891 |
+
if ( empty( $plugins_to_install ) ) {
|
2892 |
+
if ( 'install' === $install_type ) {
|
2893 |
+
$message = __( 'No plugins are available to be installed at this time.', 'tgmpa' );
|
2894 |
+
} else {
|
2895 |
+
$message = __( 'No plugins are available to be updated at this time.', 'tgmpa' );
|
2896 |
+
}
|
2897 |
+
|
2898 |
+
echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
|
2899 |
+
|
2900 |
+
return false;
|
2901 |
+
}
|
2902 |
+
|
2903 |
+
// Pass all necessary information if WP_Filesystem is needed.
|
2904 |
+
$url = wp_nonce_url(
|
2905 |
+
$this->tgmpa->get_tgmpa_url(),
|
2906 |
+
'bulk-' . $this->_args['plural']
|
2907 |
+
);
|
2908 |
+
|
2909 |
+
// Give validated data back to $_POST which is the only place the filesystem looks for extra fields.
|
2910 |
+
$_POST['plugin'] = implode( ',', $plugins_to_install ); // Work around for WP bug #19643.
|
2911 |
+
|
2912 |
+
$method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
|
2913 |
+
$fields = array_keys( $_POST ); // Extra fields to pass to WP_Filesystem.
|
2914 |
+
|
2915 |
+
if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, $fields ) ) ) {
|
2916 |
+
return true; // Stop the normal page form from displaying, credential request form will be shown.
|
2917 |
+
}
|
2918 |
+
|
2919 |
+
// Now we have some credentials, setup WP_Filesystem.
|
2920 |
+
if ( ! WP_Filesystem( $creds ) ) {
|
2921 |
+
// Our credentials were no good, ask the user for them again.
|
2922 |
+
request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, $fields );
|
2923 |
+
|
2924 |
+
return true;
|
2925 |
+
}
|
2926 |
+
|
2927 |
+
/* If we arrive here, we have the filesystem */
|
2928 |
+
|
2929 |
+
// Store all information in arrays since we are processing a bulk installation.
|
2930 |
+
$names = array();
|
2931 |
+
$sources = array(); // Needed for installs.
|
2932 |
+
$file_paths = array(); // Needed for upgrades.
|
2933 |
+
$to_inject = array(); // Information to inject into the update_plugins transient.
|
2934 |
+
|
2935 |
+
// Prepare the data for validated plugins for the install/upgrade.
|
2936 |
+
foreach ( $plugins_to_install as $slug ) {
|
2937 |
+
$name = $this->tgmpa->plugins[ $slug ]['name'];
|
2938 |
+
$source = $this->tgmpa->get_download_url( $slug );
|
2939 |
+
|
2940 |
+
if ( ! empty( $name ) && ! empty( $source ) ) {
|
2941 |
+
$names[] = $name;
|
2942 |
+
|
2943 |
+
switch ( $install_type ) {
|
2944 |
+
|
2945 |
+
case 'install':
|
2946 |
+
$sources[] = $source;
|
2947 |
+
break;
|
2948 |
+
|
2949 |
+
case 'update':
|
2950 |
+
$file_paths[] = $this->tgmpa->plugins[ $slug ]['file_path'];
|
2951 |
+
$to_inject[ $slug ] = $this->tgmpa->plugins[ $slug ];
|
2952 |
+
$to_inject[ $slug ]['source'] = $source;
|
2953 |
+
break;
|
2954 |
+
}
|
2955 |
+
}
|
2956 |
+
}
|
2957 |
+
unset( $slug, $name, $source );
|
2958 |
+
|
2959 |
+
// Create a new instance of TGMPA_Bulk_Installer.
|
2960 |
+
$installer = new TGMPA_Bulk_Installer(
|
2961 |
+
new TGMPA_Bulk_Installer_Skin(
|
2962 |
+
array(
|
2963 |
+
'url' => esc_url_raw( $this->tgmpa->get_tgmpa_url() ),
|
2964 |
+
'nonce' => 'bulk-' . $this->_args['plural'],
|
2965 |
+
'names' => $names,
|
2966 |
+
'install_type' => $install_type,
|
2967 |
+
)
|
2968 |
+
)
|
2969 |
+
);
|
2970 |
+
|
2971 |
+
// Wrap the install process with the appropriate HTML.
|
2972 |
+
echo '<div class="tgmpa">',
|
2973 |
+
'<h2 style="font-size: 23px; font-weight: 400; line-height: 29px; margin: 0; padding: 9px 15px 4px 0;">', esc_html( get_admin_page_title() ), '</h2>
|
2974 |
+
<div class="update-php" style="width: 100%; height: 98%; min-height: 850px; padding-top: 1px;">';
|
2975 |
+
|
2976 |
+
// Process the bulk installation submissions.
|
2977 |
+
add_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
|
2978 |
+
|
2979 |
+
if ( 'tgmpa-bulk-update' === $this->current_action() ) {
|
2980 |
+
// Inject our info into the update transient.
|
2981 |
+
$this->tgmpa->inject_update_info( $to_inject );
|
2982 |
+
|
2983 |
+
$installer->bulk_upgrade( $file_paths );
|
2984 |
+
} else {
|
2985 |
+
$installer->bulk_install( $sources );
|
2986 |
+
}
|
2987 |
+
|
2988 |
+
remove_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1 );
|
2989 |
+
|
2990 |
+
echo '</div></div>';
|
2991 |
+
|
2992 |
+
return true;
|
2993 |
+
}
|
2994 |
+
|
2995 |
+
// Bulk activation process.
|
2996 |
+
if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
|
2997 |
+
check_admin_referer( 'bulk-' . $this->_args['plural'] );
|
2998 |
+
|
2999 |
+
// Did user actually select any plugins to activate ?
|
3000 |
+
if ( empty( $_POST['plugin'] ) ) {
|
3001 |
+
echo '<div id="message" class="error"><p>', esc_html__( 'No plugins were selected to be activated. No action taken.', 'tgmpa' ), '</p></div>';
|
3002 |
+
|
3003 |
+
return false;
|
3004 |
+
}
|
3005 |
+
|
3006 |
+
// Grab plugin data from $_POST.
|
3007 |
+
$plugins = array();
|
3008 |
+
if ( isset( $_POST['plugin'] ) ) {
|
3009 |
+
$plugins = array_map( 'urldecode', (array) $_POST['plugin'] );
|
3010 |
+
$plugins = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins );
|
3011 |
+
}
|
3012 |
+
|
3013 |
+
$plugins_to_activate = array();
|
3014 |
+
$plugin_names = array();
|
3015 |
+
|
3016 |
+
// Grab the file paths for the selected & inactive plugins from the registration array.
|
3017 |
+
foreach ( $plugins as $slug ) {
|
3018 |
+
if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
|
3019 |
+
$plugins_to_activate[] = $this->tgmpa->plugins[ $slug ]['file_path'];
|
3020 |
+
$plugin_names[] = $this->tgmpa->plugins[ $slug ]['name'];
|
3021 |
+
}
|
3022 |
+
}
|
3023 |
+
unset( $slug );
|
3024 |
+
|
3025 |
+
// Return early if there are no plugins to activate.
|
3026 |
+
if ( empty( $plugins_to_activate ) ) {
|
3027 |
+
echo '<div id="message" class="error"><p>', esc_html__( 'No plugins are available to be activated at this time.', 'tgmpa' ), '</p></div>';
|
3028 |
+
|
3029 |
+
return false;
|
3030 |
+
}
|
3031 |
+
|
3032 |
+
// Now we are good to go - let's start activating plugins.
|
3033 |
+
$activate = activate_plugins( $plugins_to_activate );
|
3034 |
+
|
3035 |
+
if ( is_wp_error( $activate ) ) {
|
3036 |
+
echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>';
|
3037 |
+
} else {
|
3038 |
+
$count = count( $plugin_names ); // Count so we can use _n function.
|
3039 |
+
$plugin_names = array_map( array( 'TGMPA_Utils', 'wrap_in_strong' ), $plugin_names );
|
3040 |
+
$last_plugin = array_pop( $plugin_names ); // Pop off last name to prep for readability.
|
3041 |
+
$imploded = empty( $plugin_names ) ? $last_plugin : ( implode( ', ', $plugin_names ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
|
3042 |
+
|
3043 |
+
printf( // WPCS: xss ok.
|
3044 |
+
'<div id="message" class="updated"><p>%1$s %2$s.</p></div>',
|
3045 |
+
esc_html( _n( 'The following plugin was activated successfully:', 'The following plugins were activated successfully:', $count, 'tgmpa' ) ),
|
3046 |
+
$imploded
|
3047 |
+
);
|
3048 |
+
|
3049 |
+
// Update recently activated plugins option.
|
3050 |
+
$recent = (array) get_option( 'recently_activated' );
|
3051 |
+
foreach ( $plugins_to_activate as $plugin => $time ) {
|
3052 |
+
if ( isset( $recent[ $plugin ] ) ) {
|
3053 |
+
unset( $recent[ $plugin ] );
|
3054 |
+
}
|
3055 |
+
}
|
3056 |
+
update_option( 'recently_activated', $recent );
|
3057 |
+
}
|
3058 |
+
|
3059 |
+
unset( $_POST ); // Reset the $_POST variable in case user wants to perform one action after another.
|
3060 |
+
|
3061 |
+
return true;
|
3062 |
+
}
|
3063 |
+
|
3064 |
+
return false;
|
3065 |
+
}
|
3066 |
+
|
3067 |
+
/**
|
3068 |
+
* Prepares all of our information to be outputted into a usable table.
|
3069 |
+
*
|
3070 |
+
* @since 2.2.0
|
3071 |
+
*/
|
3072 |
+
public function prepare_items() {
|
3073 |
+
$columns = $this->get_columns(); // Get all necessary column information.
|
3074 |
+
$hidden = array(); // No columns to hide, but we must set as an array.
|
3075 |
+
$sortable = array(); // No reason to make sortable columns.
|
3076 |
+
$primary = $this->get_primary_column_name(); // Column which has the row actions.
|
3077 |
+
$this->_column_headers = array( $columns, $hidden, $sortable, $primary ); // Get all necessary column headers.
|
3078 |
+
|
3079 |
+
// Process our bulk activations here.
|
3080 |
+
if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
|
3081 |
+
$this->process_bulk_actions();
|
3082 |
+
}
|
3083 |
+
|
3084 |
+
// Store all of our plugin data into $items array so WP_List_Table can use it.
|
3085 |
+
$this->items = apply_filters( 'tgmpa_table_data_items', $this->_gather_plugin_data() );
|
3086 |
+
}
|
3087 |
+
|
3088 |
+
/* *********** DEPRECATED METHODS *********** */
|
3089 |
+
|
3090 |
+
/**
|
3091 |
+
* Retrieve plugin data, given the plugin name.
|
3092 |
+
*
|
3093 |
+
* @since 2.2.0
|
3094 |
+
* @deprecated 2.5.0 use {@see TGM_Plugin_Activation::_get_plugin_data_from_name()} instead.
|
3095 |
+
* @see TGM_Plugin_Activation::_get_plugin_data_from_name()
|
3096 |
+
*
|
3097 |
+
* @param string $name Name of the plugin, as it was registered.
|
3098 |
+
* @param string $data Optional. Array key of plugin data to return. Default is slug.
|
3099 |
+
* @return string|boolean Plugin slug if found, false otherwise.
|
3100 |
+
*/
|
3101 |
+
protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
|
3102 |
+
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'TGM_Plugin_Activation::_get_plugin_data_from_name()' );
|
3103 |
+
|
3104 |
+
return $this->tgmpa->_get_plugin_data_from_name( $name, $data );
|
3105 |
+
}
|
3106 |
+
}
|
3107 |
+
}
|
3108 |
+
|
3109 |
+
|
3110 |
+
if ( ! class_exists( 'TGM_Bulk_Installer' ) ) {
|
3111 |
+
|
3112 |
+
/**
|
3113 |
+
* Hack: Prevent TGMPA v2.4.1- bulk installer class from being loaded if 2.4.1- is loaded after 2.5+.
|
3114 |
+
*
|
3115 |
+
* @since 2.5.2
|
3116 |
+
*
|
3117 |
+
* {@internal The TGMPA_Bulk_Installer class was originally called TGM_Bulk_Installer.
|
3118 |
+
* For more information, see that class.}}
|
3119 |
+
*/
|
3120 |
+
class TGM_Bulk_Installer {
|
3121 |
+
}
|
3122 |
+
}
|
3123 |
+
if ( ! class_exists( 'TGM_Bulk_Installer_Skin' ) ) {
|
3124 |
+
|
3125 |
+
/**
|
3126 |
+
* Hack: Prevent TGMPA v2.4.1- bulk installer skin class from being loaded if 2.4.1- is loaded after 2.5+.
|
3127 |
+
*
|
3128 |
+
* @since 2.5.2
|
3129 |
+
*
|
3130 |
+
* {@internal The TGMPA_Bulk_Installer_Skin class was originally called TGM_Bulk_Installer_Skin.
|
3131 |
+
* For more information, see that class.}}
|
3132 |
+
*/
|
3133 |
+
class TGM_Bulk_Installer_Skin {
|
3134 |
+
}
|
3135 |
+
}
|
3136 |
+
|
3137 |
+
/**
|
3138 |
+
* The WP_Upgrader file isn't always available. If it isn't available,
|
3139 |
+
* we load it here.
|
3140 |
+
*
|
3141 |
+
* We check to make sure no action or activation keys are set so that WordPress
|
3142 |
+
* does not try to re-include the class when processing upgrades or installs outside
|
3143 |
+
* of the class.
|
3144 |
+
*
|
3145 |
+
* @since 2.2.0
|
3146 |
+
*/
|
3147 |
+
add_action( 'admin_init', 'tgmpa_load_bulk_installer' );
|
3148 |
+
if ( ! function_exists( 'tgmpa_load_bulk_installer' ) ) {
|
3149 |
+
/**
|
3150 |
+
* Load bulk installer
|
3151 |
+
*/
|
3152 |
+
function tgmpa_load_bulk_installer() {
|
3153 |
+
// Silently fail if 2.5+ is loaded *after* an older version.
|
3154 |
+
if ( ! isset( $GLOBALS['tgmpa'] ) ) {
|
3155 |
+
return;
|
3156 |
+
}
|
3157 |
+
|
3158 |
+
// Get TGMPA class instance.
|
3159 |
+
$tgmpa_instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
3160 |
+
|
3161 |
+
if ( isset( $_GET['page'] ) && $tgmpa_instance->menu === $_GET['page'] ) {
|
3162 |
+
if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
|
3163 |
+
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
3164 |
+
}
|
3165 |
+
|
3166 |
+
if ( ! class_exists( 'TGMPA_Bulk_Installer' ) ) {
|
3167 |
+
|
3168 |
+
/**
|
3169 |
+
* Installer class to handle bulk plugin installations.
|
3170 |
+
*
|
3171 |
+
* Extends WP_Upgrader and customizes to suit the installation of multiple
|
3172 |
+
* plugins.
|
3173 |
+
*
|
3174 |
+
* @since 2.2.0
|
3175 |
+
*
|
3176 |
+
* {@internal Since 2.5.0 the class is an extension of Plugin_Upgrader rather than WP_Upgrader.}}
|
3177 |
+
* {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer to TGMPA_Bulk_Installer.
|
3178 |
+
* This was done to prevent backward compatibility issues with v2.3.6.}}
|
3179 |
+
*
|
3180 |
+
* @package TGM-Plugin-Activation
|
3181 |
+
* @author Thomas Griffin
|
3182 |
+
* @author Gary Jones
|
3183 |
+
*/
|
3184 |
+
class TGMPA_Bulk_Installer extends Plugin_Upgrader {
|
3185 |
+
/**
|
3186 |
+
* Holds result of bulk plugin installation.
|
3187 |
+
*
|
3188 |
+
* @since 2.2.0
|
3189 |
+
*
|
3190 |
+
* @var string
|
3191 |
+
*/
|
3192 |
+
public $result;
|
3193 |
+
|
3194 |
+
/**
|
3195 |
+
* Flag to check if bulk installation is occurring or not.
|
3196 |
+
*
|
3197 |
+
* @since 2.2.0
|
3198 |
+
*
|
3199 |
+
* @var boolean
|
3200 |
+
*/
|
3201 |
+
public $bulk = false;
|
3202 |
+
|
3203 |
+
/**
|
3204 |
+
* TGMPA instance
|
3205 |
+
*
|
3206 |
+
* @since 2.5.0
|
3207 |
+
*
|
3208 |
+
* @var object
|
3209 |
+
*/
|
3210 |
+
protected $tgmpa;
|
3211 |
+
|
3212 |
+
/**
|
3213 |
+
* Whether or not the destination directory needs to be cleared ( = on update).
|
3214 |
+
*
|
3215 |
+
* @since 2.5.0
|
3216 |
+
*
|
3217 |
+
* @var bool
|
3218 |
+
*/
|
3219 |
+
protected $clear_destination = false;
|
3220 |
+
|
3221 |
+
/**
|
3222 |
+
* References parent constructor and sets defaults for class.
|
3223 |
+
*
|
3224 |
+
* @since 2.2.0
|
3225 |
+
*
|
3226 |
+
* @param \Bulk_Upgrader_Skin|null $skin Installer skin.
|
3227 |
+
*/
|
3228 |
+
public function __construct( $skin = null ) {
|
3229 |
+
// Get TGMPA class instance.
|
3230 |
+
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
3231 |
+
|
3232 |
+
parent::__construct( $skin );
|
3233 |
+
|
3234 |
+
if ( isset( $this->skin->options['install_type'] ) && 'update' === $this->skin->options['install_type'] ) {
|
3235 |
+
$this->clear_destination = true;
|
3236 |
+
}
|
3237 |
+
|
3238 |
+
if ( $this->tgmpa->is_automatic ) {
|
3239 |
+
$this->activate_strings();
|
3240 |
+
}
|
3241 |
+
|
3242 |
+
add_action( 'upgrader_process_complete', array( $this->tgmpa, 'populate_file_path' ) );
|
3243 |
+
}
|
3244 |
+
|
3245 |
+
/**
|
3246 |
+
* Sets the correct activation strings for the installer skin to use.
|
3247 |
+
*
|
3248 |
+
* @since 2.2.0
|
3249 |
+
*/
|
3250 |
+
public function activate_strings() {
|
3251 |
+
$this->strings['activation_failed'] = __( 'Plugin activation failed.', 'tgmpa' );
|
3252 |
+
$this->strings['activation_success'] = __( 'Plugin activated successfully.', 'tgmpa' );
|
3253 |
+
}
|
3254 |
+
|
3255 |
+
/**
|
3256 |
+
* Performs the actual installation of each plugin.
|
3257 |
+
*
|
3258 |
+
* @since 2.2.0
|
3259 |
+
*
|
3260 |
+
* @see WP_Upgrader::run()
|
3261 |
+
*
|
3262 |
+
* @param array $options The installation config options.
|
3263 |
+
* @return null|array Return early if error, array of installation data on success.
|
3264 |
+
*/
|
3265 |
+
public function run( $options ) {
|
3266 |
+
$result = parent::run( $options );
|
3267 |
+
|
3268 |
+
// Reset the strings in case we changed one during automatic activation.
|
3269 |
+
if ( $this->tgmpa->is_automatic ) {
|
3270 |
+
if ( 'update' === $this->skin->options['install_type'] ) {
|
3271 |
+
$this->upgrade_strings();
|
3272 |
+
} else {
|
3273 |
+
$this->install_strings();
|
3274 |
+
}
|
3275 |
+
}
|
3276 |
+
|
3277 |
+
return $result;
|
3278 |
+
}
|
3279 |
+
|
3280 |
+
/**
|
3281 |
+
* Processes the bulk installation of plugins.
|
3282 |
+
*
|
3283 |
+
* @since 2.2.0
|
3284 |
+
*
|
3285 |
+
* {@internal This is basically a near identical copy of the WP Core
|
3286 |
+
* Plugin_Upgrader::bulk_upgrade() method, with minor adjustments to deal with
|
3287 |
+
* new installs instead of upgrades.
|
3288 |
+
* For ease of future synchronizations, the adjustments are clearly commented, but no other
|
3289 |
+
* comments are added. Code style has been made to comply.}}
|
3290 |
+
*
|
3291 |
+
* @see Plugin_Upgrader::bulk_upgrade()
|
3292 |
+
* @see https://core.trac.wordpress.org/browser/tags/4.2.1/src/wp-admin/includes/class-wp-upgrader.php#L838
|
3293 |
+
* (@internal Last synced: Dec 31st 2015 against https://core.trac.wordpress.org/browser/trunk?rev=36134}}
|
3294 |
+
*
|
3295 |
+
* @param array $plugins The plugin sources needed for installation.
|
3296 |
+
* @param array $args Arbitrary passed extra arguments.
|
3297 |
+
* @return array|false Install confirmation messages on success, false on failure.
|
3298 |
+
*/
|
3299 |
+
public function bulk_install( $plugins, $args = array() ) {
|
3300 |
+
// [TGMPA + ] Hook auto-activation in.
|
3301 |
+
add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3302 |
+
|
3303 |
+
$defaults = array(
|
3304 |
+
'clear_update_cache' => true,
|
3305 |
+
);
|
3306 |
+
$parsed_args = wp_parse_args( $args, $defaults );
|
3307 |
+
|
3308 |
+
$this->init();
|
3309 |
+
$this->bulk = true;
|
3310 |
+
|
3311 |
+
$this->install_strings(); // [TGMPA + ] adjusted.
|
3312 |
+
|
3313 |
+
/* [TGMPA - ] $current = get_site_transient( 'update_plugins' ); */
|
3314 |
+
|
3315 |
+
/* [TGMPA - ] add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); */
|
3316 |
+
|
3317 |
+
$this->skin->header();
|
3318 |
+
|
3319 |
+
// Connect to the Filesystem first.
|
3320 |
+
$res = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
|
3321 |
+
if ( ! $res ) {
|
3322 |
+
$this->skin->footer();
|
3323 |
+
return false;
|
3324 |
+
}
|
3325 |
+
|
3326 |
+
$this->skin->bulk_header();
|
3327 |
+
|
3328 |
+
/*
|
3329 |
+
* Only start maintenance mode if:
|
3330 |
+
* - running Multisite and there are one or more plugins specified, OR
|
3331 |
+
* - a plugin with an update available is currently active.
|
3332 |
+
* @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
|
3333 |
+
*/
|
3334 |
+
$maintenance = ( is_multisite() && ! empty( $plugins ) );
|
3335 |
+
|
3336 |
+
/*
|
3337 |
+
[TGMPA - ]
|
3338 |
+
foreach ( $plugins as $plugin )
|
3339 |
+
$maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );
|
3340 |
+
*/
|
3341 |
+
if ( $maintenance ) {
|
3342 |
+
$this->maintenance_mode( true );
|
3343 |
+
}
|
3344 |
+
|
3345 |
+
$results = array();
|
3346 |
+
|
3347 |
+
$this->update_count = count( $plugins );
|
3348 |
+
$this->update_current = 0;
|
3349 |
+
foreach ( $plugins as $plugin ) {
|
3350 |
+
$this->update_current++;
|
3351 |
+
|
3352 |
+
/*
|
3353 |
+
[TGMPA - ]
|
3354 |
+
$this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
|
3355 |
+
|
3356 |
+
if ( !isset( $current->response[ $plugin ] ) ) {
|
3357 |
+
$this->skin->set_result('up_to_date');
|
3358 |
+
$this->skin->before();
|
3359 |
+
$this->skin->feedback('up_to_date');
|
3360 |
+
$this->skin->after();
|
3361 |
+
$results[$plugin] = true;
|
3362 |
+
continue;
|
3363 |
+
}
|
3364 |
+
|
3365 |
+
// Get the URL to the zip file.
|
3366 |
+
$r = $current->response[ $plugin ];
|
3367 |
+
|
3368 |
+
$this->skin->plugin_active = is_plugin_active($plugin);
|
3369 |
+
*/
|
3370 |
+
|
3371 |
+
$result = $this->run(
|
3372 |
+
array(
|
3373 |
+
'package' => $plugin, // [TGMPA + ] adjusted.
|
3374 |
+
'destination' => WP_PLUGIN_DIR,
|
3375 |
+
'clear_destination' => false, // [TGMPA + ] adjusted.
|
3376 |
+
'clear_working' => true,
|
3377 |
+
'is_multi' => true,
|
3378 |
+
'hook_extra' => array(
|
3379 |
+
'plugin' => $plugin,
|
3380 |
+
),
|
3381 |
+
)
|
3382 |
+
);
|
3383 |
+
|
3384 |
+
$results[ $plugin ] = $this->result;
|
3385 |
+
|
3386 |
+
// Prevent credentials auth screen from displaying multiple times.
|
3387 |
+
if ( false === $result ) {
|
3388 |
+
break;
|
3389 |
+
}
|
3390 |
+
} //end foreach $plugins
|
3391 |
+
|
3392 |
+
$this->maintenance_mode( false );
|
3393 |
+
|
3394 |
+
/**
|
3395 |
+
* Fires when the bulk upgrader process is complete.
|
3396 |
+
*
|
3397 |
+
* @since WP 3.6.0 / TGMPA 2.5.0
|
3398 |
+
*
|
3399 |
+
* @param Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might
|
3400 |
+
* be a Theme_Upgrader or Core_Upgrade instance.
|
3401 |
+
* @param array $data {
|
3402 |
+
* Array of bulk item update data.
|
3403 |
+
*
|
3404 |
+
* @type string $action Type of action. Default 'update'.
|
3405 |
+
* @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
|
3406 |
+
* @type bool $bulk Whether the update process is a bulk update. Default true.
|
3407 |
+
* @type array $packages Array of plugin, theme, or core packages to update.
|
3408 |
+
* }
|
3409 |
+
*/
|
3410 |
+
do_action( 'upgrader_process_complete', $this, array(
|
3411 |
+
'action' => 'install', // [TGMPA + ] adjusted.
|
3412 |
+
'type' => 'plugin',
|
3413 |
+
'bulk' => true,
|
3414 |
+
'plugins' => $plugins,
|
3415 |
+
) );
|
3416 |
+
|
3417 |
+
$this->skin->bulk_footer();
|
3418 |
+
|
3419 |
+
$this->skin->footer();
|
3420 |
+
|
3421 |
+
// Cleanup our hooks, in case something else does a upgrade on this connection.
|
3422 |
+
/* [TGMPA - ] remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); */
|
3423 |
+
|
3424 |
+
// [TGMPA + ] Remove our auto-activation hook.
|
3425 |
+
remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3426 |
+
|
3427 |
+
// Force refresh of plugin update information.
|
3428 |
+
wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
|
3429 |
+
|
3430 |
+
return $results;
|
3431 |
+
}
|
3432 |
+
|
3433 |
+
/**
|
3434 |
+
* Handle a bulk upgrade request.
|
3435 |
+
*
|
3436 |
+
* @since 2.5.0
|
3437 |
+
*
|
3438 |
+
* @see Plugin_Upgrader::bulk_upgrade()
|
3439 |
+
*
|
3440 |
+
* @param array $plugins The local WP file_path's of the plugins which should be upgraded.
|
3441 |
+
* @param array $args Arbitrary passed extra arguments.
|
3442 |
+
* @return string|bool Install confirmation messages on success, false on failure.
|
3443 |
+
*/
|
3444 |
+
public function bulk_upgrade( $plugins, $args = array() ) {
|
3445 |
+
|
3446 |
+
add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3447 |
+
|
3448 |
+
$result = parent::bulk_upgrade( $plugins, $args );
|
3449 |
+
|
3450 |
+
remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
|
3451 |
+
|
3452 |
+
return $result;
|
3453 |
+
}
|
3454 |
+
|
3455 |
+
/**
|
3456 |
+
* Abuse a filter to auto-activate plugins after installation.
|
3457 |
+
*
|
3458 |
+
* Hooked into the 'upgrader_post_install' filter hook.
|
3459 |
+
*
|
3460 |
+
* @since 2.5.0
|
3461 |
+
*
|
3462 |
+
* @param bool $bool The value we need to give back (true).
|
3463 |
+
* @return bool
|
3464 |
+
*/
|
3465 |
+
public function auto_activate( $bool ) {
|
3466 |
+
// Only process the activation of installed plugins if the automatic flag is set to true.
|
3467 |
+
if ( $this->tgmpa->is_automatic ) {
|
3468 |
+
// Flush plugins cache so the headers of the newly installed plugins will be read correctly.
|
3469 |
+
wp_clean_plugins_cache();
|
3470 |
+
|
3471 |
+
// Get the installed plugin file.
|
3472 |
+
$plugin_info = $this->plugin_info();
|
3473 |
+
|
3474 |
+
// Don't try to activate on upgrade of active plugin as WP will do this already.
|
3475 |
+
if ( ! is_plugin_active( $plugin_info ) ) {
|
3476 |
+
$activate = activate_plugin( $plugin_info );
|
3477 |
+
|
3478 |
+
// Adjust the success string based on the activation result.
|
3479 |
+
$this->strings['process_success'] = $this->strings['process_success'] . "<br />\n";
|
3480 |
+
|
3481 |
+
if ( is_wp_error( $activate ) ) {
|
3482 |
+
$this->skin->error( $activate );
|
3483 |
+
$this->strings['process_success'] .= $this->strings['activation_failed'];
|
3484 |
+
} else {
|
3485 |
+
$this->strings['process_success'] .= $this->strings['activation_success'];
|
3486 |
+
}
|
3487 |
+
}
|
3488 |
+
}
|
3489 |
+
|
3490 |
+
return $bool;
|
3491 |
+
}
|
3492 |
+
}
|
3493 |
+
}
|
3494 |
+
|
3495 |
+
if ( ! class_exists( 'TGMPA_Bulk_Installer_Skin' ) ) {
|
3496 |
+
|
3497 |
+
/**
|
3498 |
+
* Installer skin to set strings for the bulk plugin installations..
|
3499 |
+
*
|
3500 |
+
* Extends Bulk_Upgrader_Skin and customizes to suit the installation of multiple
|
3501 |
+
* plugins.
|
3502 |
+
*
|
3503 |
+
* @since 2.2.0
|
3504 |
+
*
|
3505 |
+
* {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer_Skin to
|
3506 |
+
* TGMPA_Bulk_Installer_Skin.
|
3507 |
+
* This was done to prevent backward compatibility issues with v2.3.6.}}
|
3508 |
+
*
|
3509 |
+
* @see https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/class-wp-upgrader-skins.php
|
3510 |
+
*
|
3511 |
+
* @package TGM-Plugin-Activation
|
3512 |
+
* @author Thomas Griffin
|
3513 |
+
* @author Gary Jones
|
3514 |
+
*/
|
3515 |
+
class TGMPA_Bulk_Installer_Skin extends Bulk_Upgrader_Skin {
|
3516 |
+
/**
|
3517 |
+
* Holds plugin info for each individual plugin installation.
|
3518 |
+
*
|
3519 |
+
* @since 2.2.0
|
3520 |
+
*
|
3521 |
+
* @var array
|
3522 |
+
*/
|
3523 |
+
public $plugin_info = array();
|
3524 |
+
|
3525 |
+
/**
|
3526 |
+
* Holds names of plugins that are undergoing bulk installations.
|
3527 |
+
*
|
3528 |
+
* @since 2.2.0
|
3529 |
+
*
|
3530 |
+
* @var array
|
3531 |
+
*/
|
3532 |
+
public $plugin_names = array();
|
3533 |
+
|
3534 |
+
/**
|
3535 |
+
* Integer to use for iteration through each plugin installation.
|
3536 |
+
*
|
3537 |
+
* @since 2.2.0
|
3538 |
+
*
|
3539 |
+
* @var integer
|
3540 |
+
*/
|
3541 |
+
public $i = 0;
|
3542 |
+
|
3543 |
+
/**
|
3544 |
+
* TGMPA instance
|
3545 |
+
*
|
3546 |
+
* @since 2.5.0
|
3547 |
+
*
|
3548 |
+
* @var object
|
3549 |
+
*/
|
3550 |
+
protected $tgmpa;
|
3551 |
+
|
3552 |
+
/**
|
3553 |
+
* Constructor. Parses default args with new ones and extracts them for use.
|
3554 |
+
*
|
3555 |
+
* @since 2.2.0
|
3556 |
+
*
|
3557 |
+
* @param array $args Arguments to pass for use within the class.
|
3558 |
+
*/
|
3559 |
+
public function __construct( $args = array() ) {
|
3560 |
+
// Get TGMPA class instance.
|
3561 |
+
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
|
3562 |
+
|
3563 |
+
// Parse default and new args.
|
3564 |
+
$defaults = array(
|
3565 |
+
'url' => '',
|
3566 |
+
'nonce' => '',
|
3567 |
+
'names' => array(),
|
3568 |
+
'install_type' => 'install',
|
3569 |
+
);
|
3570 |
+
$args = wp_parse_args( $args, $defaults );
|
3571 |
+
|
3572 |
+
// Set plugin names to $this->plugin_names property.
|
3573 |
+
$this->plugin_names = $args['names'];
|
3574 |
+
|
3575 |
+
// Extract the new args.
|
3576 |
+
parent::__construct( $args );
|
3577 |
+
}
|
3578 |
+
|
3579 |
+
/**
|
3580 |
+
* Sets install skin strings for each individual plugin.
|
3581 |
+
*
|
3582 |
+
* Checks to see if the automatic activation flag is set and uses the
|
3583 |
+
* the proper strings accordingly.
|
3584 |
+
*
|
3585 |
+
* @since 2.2.0
|
3586 |
+
*/
|
3587 |
+
public function add_strings() {
|
3588 |
+
if ( 'update' === $this->options['install_type'] ) {
|
3589 |
+
parent::add_strings();
|
3590 |
+
/* translators: 1: plugin name, 2: action number 3: total number of actions. */
|
3591 |
+
$this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
|
3592 |
+
} else {
|
3593 |
+
/* translators: 1: plugin name, 2: error message. */
|
3594 |
+
$this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while installing %1$s: <strong>%2$s</strong>.', 'tgmpa' );
|
3595 |
+
/* translators: 1: plugin name. */
|
3596 |
+
$this->upgrader->strings['skin_update_failed'] = __( 'The installation of %1$s failed.', 'tgmpa' );
|
3597 |
+
|
3598 |
+
if ( $this->tgmpa->is_automatic ) {
|
3599 |
+
// Automatic activation strings.
|
3600 |
+
$this->upgrader->strings['skin_upgrade_start'] = __( 'The installation and activation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
|
3601 |
+
/* translators: 1: plugin name. */
|
3602 |
+
$this->upgrader->strings['skin_update_successful'] = __( '%1$s installed and activated successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
|
3603 |
+
$this->upgrader->strings['skin_upgrade_end'] = __( 'All installations and activations have been completed.', 'tgmpa' );
|
3604 |
+
/* translators: 1: plugin name, 2: action number 3: total number of actions. */
|
3605 |
+
$this->upgrader->strings['skin_before_update_header'] = __( 'Installing and Activating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
|
3606 |
+
} else {
|
3607 |
+
// Default installation strings.
|
3608 |
+
$this->upgrader->strings['skin_upgrade_start'] = __( 'The installation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
|
3609 |
+
/* translators: 1: plugin name. */
|
3610 |
+
$this->upgrader->strings['skin_update_successful'] = esc_html__( '%1$s installed successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
|
3611 |
+
$this->upgrader->strings['skin_upgrade_end'] = __( 'All installations have been completed.', 'tgmpa' );
|
3612 |
+
/* translators: 1: plugin name, 2: action number 3: total number of actions. */
|
3613 |
+
$this->upgrader->strings['skin_before_update_header'] = __( 'Installing Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
|
3614 |
+
}
|
3615 |
+
}
|
3616 |
+
}
|
3617 |
+
|
3618 |
+
/**
|
3619 |
+
* Outputs the header strings and necessary JS before each plugin installation.
|
3620 |
+
*
|
3621 |
+
* @since 2.2.0
|
3622 |
+
*
|
3623 |
+
* @param string $title Unused in this implementation.
|
3624 |
+
*/
|
3625 |
+
public function before( $title = '' ) {
|
3626 |
+
if ( empty( $title ) ) {
|
3627 |
+
$title = esc_html( $this->plugin_names[ $this->i ] );
|
3628 |
+
}
|
3629 |
+
parent::before( $title );
|
3630 |
+
}
|
3631 |
+
|
3632 |
+
/**
|
3633 |
+
* Outputs the footer strings and necessary JS after each plugin installation.
|
3634 |
+
*
|
3635 |
+
* Checks for any errors and outputs them if they exist, else output
|
3636 |
+
* success strings.
|
3637 |
+
*
|
3638 |
+
* @since 2.2.0
|
3639 |
+
*
|
3640 |
+
* @param string $title Unused in this implementation.
|
3641 |
+
*/
|
3642 |
+
public function after( $title = '' ) {
|
3643 |
+
if ( empty( $title ) ) {
|
3644 |
+
$title = esc_html( $this->plugin_names[ $this->i ] );
|
3645 |
+
}
|
3646 |
+
parent::after( $title );
|
3647 |
+
|
3648 |
+
$this->i++;
|
3649 |
+
}
|
3650 |
+
|
3651 |
+
/**
|
3652 |
+
* Outputs links after bulk plugin installation is complete.
|
3653 |
+
*
|
3654 |
+
* @since 2.2.0
|
3655 |
+
*/
|
3656 |
+
public function bulk_footer() {
|
3657 |
+
// Serve up the string to say installations (and possibly activations) are complete.
|
3658 |
+
parent::bulk_footer();
|
3659 |
+
|
3660 |
+
// Flush plugins cache so we can make sure that the installed plugins list is always up to date.
|
3661 |
+
wp_clean_plugins_cache();
|
3662 |
+
|
3663 |
+
$this->tgmpa->show_tgmpa_version();
|
3664 |
+
|
3665 |
+
// Display message based on if all plugins are now active or not.
|
3666 |
+
$update_actions = array();
|
3667 |
+
|
3668 |
+
if ( $this->tgmpa->is_tgmpa_complete() ) {
|
3669 |
+
// All plugins are active, so we display the complete string and hide the menu to protect users.
|
3670 |
+
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
|
3671 |
+
$update_actions['dashboard'] = sprintf(
|
3672 |
+
esc_html( $this->tgmpa->strings['complete'] ),
|
3673 |
+
'<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>'
|
3674 |
+
);
|
3675 |
+
} else {
|
3676 |
+
$update_actions['tgmpa_page'] = '<a href="' . esc_url( $this->tgmpa->get_tgmpa_url() ) . '" target="_parent">' . esc_html( $this->tgmpa->strings['return'] ) . '</a>';
|
3677 |
+
}
|
3678 |
+
|
3679 |
+
/**
|
3680 |
+
* Filter the list of action links available following bulk plugin installs/updates.
|
3681 |
+
*
|
3682 |
+
* @since 2.5.0
|
3683 |
+
*
|
3684 |
+
* @param array $update_actions Array of plugin action links.
|
3685 |
+
* @param array $plugin_info Array of information for the last-handled plugin.
|
3686 |
+
*/
|
3687 |
+
$update_actions = apply_filters( 'tgmpa_update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );
|
3688 |
+
|
3689 |
+
if ( ! empty( $update_actions ) ) {
|
3690 |
+
$this->feedback( implode( ' | ', (array) $update_actions ) );
|
3691 |
+
}
|
3692 |
+
}
|
3693 |
+
|
3694 |
+
/* *********** DEPRECATED METHODS *********** */
|
3695 |
+
|
3696 |
+
/**
|
3697 |
+
* Flush header output buffer.
|
3698 |
+
*
|
3699 |
+
* @since 2.2.0
|
3700 |
+
* @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
|
3701 |
+
* @see Bulk_Upgrader_Skin::flush_output()
|
3702 |
+
*/
|
3703 |
+
public function before_flush_output() {
|
3704 |
+
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
|
3705 |
+
$this->flush_output();
|
3706 |
+
}
|
3707 |
+
|
3708 |
+
/**
|
3709 |
+
* Flush footer output buffer and iterate $this->i to make sure the
|
3710 |
+
* installation strings reference the correct plugin.
|
3711 |
+
*
|
3712 |
+
* @since 2.2.0
|
3713 |
+
* @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
|
3714 |
+
* @see Bulk_Upgrader_Skin::flush_output()
|
3715 |
+
*/
|
3716 |
+
public function after_flush_output() {
|
3717 |
+
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
|
3718 |
+
$this->flush_output();
|
3719 |
+
$this->i++;
|
3720 |
+
}
|
3721 |
+
}
|
3722 |
+
}
|
3723 |
+
}
|
3724 |
+
}
|
3725 |
+
}
|
3726 |
+
|
3727 |
+
if ( ! class_exists( 'TGMPA_Utils' ) ) {
|
3728 |
+
|
3729 |
+
/**
|
3730 |
+
* Generic utilities for TGMPA.
|
3731 |
+
*
|
3732 |
+
* All methods are static, poor-dev name-spacing class wrapper.
|
3733 |
+
*
|
3734 |
+
* Class was called TGM_Utils in 2.5.0 but renamed TGMPA_Utils in 2.5.1 as this was conflicting with Soliloquy.
|
3735 |
+
*
|
3736 |
+
* @since 2.5.0
|
3737 |
+
*
|
3738 |
+
* @package TGM-Plugin-Activation
|
3739 |
+
* @author Juliette Reinders Folmer
|
3740 |
+
*/
|
3741 |
+
class TGMPA_Utils {
|
3742 |
+
/**
|
3743 |
+
* Whether the PHP filter extension is enabled.
|
3744 |
+
*
|
3745 |
+
* @see http://php.net/book.filter
|
3746 |
+
*
|
3747 |
+
* @since 2.5.0
|
3748 |
+
*
|
3749 |
+
* @static
|
3750 |
+
*
|
3751 |
+
* @var bool $has_filters True is the extension is enabled.
|
3752 |
+
*/
|
3753 |
+
public static $has_filters;
|
3754 |
+
|
3755 |
+
/**
|
3756 |
+
* Wrap an arbitrary string in <em> tags. Meant to be used in combination with array_map().
|
3757 |
+
*
|
3758 |
+
* @since 2.5.0
|
3759 |
+
*
|
3760 |
+
* @static
|
3761 |
+
*
|
3762 |
+
* @param string $string Text to be wrapped.
|
3763 |
+
* @return string
|
3764 |
+
*/
|
3765 |
+
public static function wrap_in_em( $string ) {
|
3766 |
+
return '<em>' . wp_kses_post( $string ) . '</em>';
|
3767 |
+
}
|
3768 |
+
|
3769 |
+
/**
|
3770 |
+
* Wrap an arbitrary string in <strong> tags. Meant to be used in combination with array_map().
|
3771 |
+
*
|
3772 |
+
* @since 2.5.0
|
3773 |
+
*
|
3774 |
+
* @static
|
3775 |
+
*
|
3776 |
+
* @param string $string Text to be wrapped.
|
3777 |
+
* @return string
|
3778 |
+
*/
|
3779 |
+
public static function wrap_in_strong( $string ) {
|
3780 |
+
return '<strong>' . wp_kses_post( $string ) . '</strong>';
|
3781 |
+
}
|
3782 |
+
|
3783 |
+
/**
|
3784 |
+
* Helper function: Validate a value as boolean
|
3785 |
+
*
|
3786 |
+
* @since 2.5.0
|
3787 |
+
*
|
3788 |
+
* @static
|
3789 |
+
*
|
3790 |
+
* @param mixed $value Arbitrary value.
|
3791 |
+
* @return bool
|
3792 |
+
*/
|
3793 |
+
public static function validate_bool( $value ) {
|
3794 |
+
if ( ! isset( self::$has_filters ) ) {
|
3795 |
+
self::$has_filters = extension_loaded( 'filter' );
|
3796 |
+
}
|
3797 |
+
|
3798 |
+
if ( self::$has_filters ) {
|
3799 |
+
return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
|
3800 |
+
} else {
|
3801 |
+
return self::emulate_filter_bool( $value );
|
3802 |
+
}
|
3803 |
+
}
|
3804 |
+
|
3805 |
+
/**
|
3806 |
+
* Helper function: Cast a value to bool
|
3807 |
+
*
|
3808 |
+
* @since 2.5.0
|
3809 |
+
*
|
3810 |
+
* @static
|
3811 |
+
*
|
3812 |
+
* @param mixed $value Value to cast.
|
3813 |
+
* @return bool
|
3814 |
+
*/
|
3815 |
+
protected static function emulate_filter_bool( $value ) {
|
3816 |
+
// @codingStandardsIgnoreStart
|
3817 |
+
static $true = array(
|
3818 |
+
'1',
|
3819 |
+
'true', 'True', 'TRUE',
|
3820 |
+
'y', 'Y',
|
3821 |
+
'yes', 'Yes', 'YES',
|
3822 |
+
'on', 'On', 'ON',
|
3823 |
+
);
|
3824 |
+
static $false = array(
|
3825 |
+
'0',
|
3826 |
+
'false', 'False', 'FALSE',
|
3827 |
+
'n', 'N',
|
3828 |
+
'no', 'No', 'NO',
|
3829 |
+
'off', 'Off', 'OFF',
|
3830 |
+
);
|
3831 |
+
// @codingStandardsIgnoreEnd
|
3832 |
+
|
3833 |
+
if ( is_bool( $value ) ) {
|
3834 |
+
return $value;
|
3835 |
+
} elseif ( is_int( $value ) && ( 0 === $value || 1 === $value ) ) {
|
3836 |
+
return (bool) $value;
|
3837 |
+
} elseif ( ( is_float( $value ) && ! is_nan( $value ) ) && ( (float) 0 === $value || (float) 1 === $value ) ) {
|
3838 |
+
return (bool) $value;
|
3839 |
+
} elseif ( is_string( $value ) ) {
|
3840 |
+
$value = trim( $value );
|
3841 |
+
if ( in_array( $value, $true, true ) ) {
|
3842 |
+
return true;
|
3843 |
+
} elseif ( in_array( $value, $false, true ) ) {
|
3844 |
+
return false;
|
3845 |
+
} else {
|
3846 |
+
return false;
|
3847 |
+
}
|
3848 |
+
}
|
3849 |
+
|
3850 |
+
return false;
|
3851 |
+
}
|
3852 |
+
} // End of class TGMPA_Utils
|
3853 |
+
} // End of class_exists wrapper
|
modules/tgm_promo/mod.php
CHANGED
@@ -1,47 +1,47 @@
|
|
1 |
-
<?php
|
2 |
-
class tgm_promoPps extends modulePps {
|
3 |
-
public function init() {
|
4 |
-
parent::init();
|
5 |
-
// Closed for now
|
6 |
-
if(is_admin()) {
|
7 |
-
require_once($this->getModDir(). 'classes'. DS. 'class-tgm-plugin-activation.php');
|
8 |
-
add_action('tgmpa_register', array($this, 'registerPromo'));
|
9 |
-
}
|
10 |
-
}
|
11 |
-
|
12 |
-
public function registerPromo() {
|
13 |
-
// For new users only
|
14 |
-
if(!installerPps::isNewUser())
|
15 |
-
return;
|
16 |
-
if(function_exists('addplus_fs')) {
|
17 |
-
if(framePps::_()->getModule('options')->get('addendio_promo')) {
|
18 |
-
framePps::_()->getModule('options')->getModel()->save('addendio_promo', 0);
|
19 |
-
framePps::_()->getModule('supsystic_promo')->getModel()->bigStatAdd('addendio_promo');
|
20 |
-
}
|
21 |
-
return;
|
22 |
-
}
|
23 |
-
if(!framePps::_()->getModule('options')->get('addendio_promo'))
|
24 |
-
framePps::_()->getModule('options')->getModel()->save('addendio_promo', 1);
|
25 |
-
$plugins = array(
|
26 |
-
array(
|
27 |
-
'name' => 'Addendio PLUS',
|
28 |
-
'slug' => 'addendio-plus',
|
29 |
-
'source' => 'https://assets.addendio.com/addendio-plus/assets/addendio-plus.zip',
|
30 |
-
),
|
31 |
-
);
|
32 |
-
$config = array(
|
33 |
-
'id' => 'pps_lng', // Unique ID for hashing notices for multiple instances of TGMPA.
|
34 |
-
'default_path' => '', // Default absolute path to bundled plugins.
|
35 |
-
'menu' => 'tgmpa-install-plugins', // Menu slug.
|
36 |
-
'parent_slug' => 'plugins.php', // Parent menu slug.
|
37 |
-
'capability' => 'manage_options', // Capability needed to view plugin install page, should be a capability associated with the parent menu used.
|
38 |
-
'has_notices' => true, // Show admin notices or not.
|
39 |
-
'dismissable' => true, // If false, a user cannot dismiss the nag message.
|
40 |
-
'dismiss_msg' => '', // If 'dismissable' is false, this message will be output at top of nag.
|
41 |
-
'is_automatic' => false, // Automatically activate plugins after installation or not.
|
42 |
-
'message' => '', // Message to output right before the plugins table.
|
43 |
-
);
|
44 |
-
|
45 |
-
tgmpa( $plugins, $config );
|
46 |
-
}
|
47 |
}
|
1 |
+
<?php
|
2 |
+
class tgm_promoPps extends modulePps {
|
3 |
+
public function init() {
|
4 |
+
parent::init();
|
5 |
+
// Closed for now
|
6 |
+
/*if(is_admin()) {
|
7 |
+
require_once($this->getModDir(). 'classes'. DS. 'class-tgm-plugin-activation.php');
|
8 |
+
add_action('tgmpa_register', array($this, 'registerPromo'));
|
9 |
+
}*/
|
10 |
+
}
|
11 |
+
|
12 |
+
/*public function registerPromo() {
|
13 |
+
// For new users only
|
14 |
+
if(!installerPps::isNewUser())
|
15 |
+
return;
|
16 |
+
if(function_exists('addplus_fs')) {
|
17 |
+
if(framePps::_()->getModule('options')->get('addendio_promo')) {
|
18 |
+
framePps::_()->getModule('options')->getModel()->save('addendio_promo', 0);
|
19 |
+
framePps::_()->getModule('supsystic_promo')->getModel()->bigStatAdd('addendio_promo');
|
20 |
+
}
|
21 |
+
return;
|
22 |
+
}
|
23 |
+
if(!framePps::_()->getModule('options')->get('addendio_promo'))
|
24 |
+
framePps::_()->getModule('options')->getModel()->save('addendio_promo', 1);
|
25 |
+
$plugins = array(
|
26 |
+
array(
|
27 |
+
'name' => 'Addendio PLUS',
|
28 |
+
'slug' => 'addendio-plus',
|
29 |
+
'source' => 'https://assets.addendio.com/addendio-plus/assets/addendio-plus.zip',
|
30 |
+
),
|
31 |
+
);
|
32 |
+
$config = array(
|
33 |
+
'id' => 'pps_lng', // Unique ID for hashing notices for multiple instances of TGMPA.
|
34 |
+
'default_path' => '', // Default absolute path to bundled plugins.
|
35 |
+
'menu' => 'tgmpa-install-plugins', // Menu slug.
|
36 |
+
'parent_slug' => 'plugins.php', // Parent menu slug.
|
37 |
+
'capability' => 'manage_options', // Capability needed to view plugin install page, should be a capability associated with the parent menu used.
|
38 |
+
'has_notices' => true, // Show admin notices or not.
|
39 |
+
'dismissable' => true, // If false, a user cannot dismiss the nag message.
|
40 |
+
'dismiss_msg' => '', // If 'dismissable' is false, this message will be output at top of nag.
|
41 |
+
'is_automatic' => false, // Automatically activate plugins after installation or not.
|
42 |
+
'message' => '', // Message to output right before the plugins table.
|
43 |
+
);
|
44 |
+
|
45 |
+
tgmpa( $plugins, $config );
|
46 |
+
}*/
|
47 |
}
|
pps.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Popup by Supsystic
|
4 |
* Plugin URI: https://supsystic.com/plugins/popup-plugin/
|
5 |
* Description: The Best WordPress popup plugin to help you gain more subscribers, social followers or advertisement. Responsive popups with friendly options
|
6 |
-
* Version: 1.9.
|
7 |
* Author: supsystic.com
|
8 |
* Author URI: https://supsystic.com
|
9 |
**/
|
@@ -55,3 +55,5 @@
|
|
55 |
framePps::_()->exec();
|
56 |
|
57 |
//var_dump(framePps::_()->getActivationErrors()); exit();
|
|
|
|
3 |
* Plugin Name: Popup by Supsystic
|
4 |
* Plugin URI: https://supsystic.com/plugins/popup-plugin/
|
5 |
* Description: The Best WordPress popup plugin to help you gain more subscribers, social followers or advertisement. Responsive popups with friendly options
|
6 |
+
* Version: 1.9.38
|
7 |
* Author: supsystic.com
|
8 |
* Author URI: https://supsystic.com
|
9 |
**/
|
55 |
framePps::_()->exec();
|
56 |
|
57 |
//var_dump(framePps::_()->getActivationErrors()); exit();
|
58 |
+
|
59 |
+
// Aaaaaaaaand another test for update:)
|
readme.txt
CHANGED
@@ -1,315 +1,173 @@
|
|
1 |
=== Popup by Supsystic ===
|
2 |
Contributors: supsystic.com
|
3 |
Donate link: https://supsystic.com/plugins/popup-plugin
|
4 |
-
Tags: popup,
|
5 |
-
Tested up to: 4.9.
|
6 |
-
Stable tag: 1.9.
|
7 |
|
8 |
-
|
9 |
|
10 |
== Description ==
|
11 |
|
12 |
-
[Popup by Supsystic](https://supsystic.com/plugins/popup-plugin?utm_source=wordpress&utm_medium=description&utm_campaign=popup "Popup WordPress Plugin") with Popup Builder
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
* [Popup Triggers](https://supsystic.com/displaying-popup-configuration/ "Popup Triggers"). When to show / close popup, whom to show, show on next pages, time to display
|
18 |
-
* Different Popup types
|
19 |
-
* [Popup Placement](https://supsystic.com/popup-placement/ "Popup Placement"). Modal Popup, Fullscreen Popup, Info Bar, Fly-in, Slide In Popup
|
20 |
-
|
21 |
-
= More Popup Options =
|
22 |
-
|
23 |
-
* [Optin, Social and Link Locks](https://supsystic.com/lock-content/ "Content Lock")
|
24 |
-
* Subscription Services Integration (WordPress, MailChimp, Aweber and more)
|
25 |
-
* [A/B Split Tests](https://supsystic.com/what-is-ab-testing/ "A / B Split Test")
|
26 |
-
* [Real Time Statistic](https://supsystic.com/statistics/ "Real Time Popup Statistic")
|
27 |
-
* [20+ Popup Opening Animations](https://supsystic.com/popup-opening-animations/ "Popup Openin Animation")
|
28 |
-
* [HTML/CSS editing}(https://supsystic.com/documentation/popup-html-css-code/ "HTML CSS code")
|
29 |
-
* [Contact Form integration](https://supsystic.com/documentation/popup-with-contact-form/ "[Contact Form integration")
|
30 |
|
31 |
-
Popup types:
|
32 |
|
33 |
-
|
34 |
-
* [Contact Form](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_206 "Contact Form Popup")
|
35 |
-
* [Facebook](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_104 "Facebook Popup")
|
36 |
-
* [Video](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_103 "Video Popup")
|
37 |
-
* [Social Buttons](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_186 "Social Buttons Popup")
|
38 |
-
* [Full Screen](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_157 "Full Screen Popup")
|
39 |
-
* [HTML](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_208 "HTML Popup")
|
40 |
-
* [Notification Bar](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_157 "Notification Bar")
|
41 |
-
* [Age Verivication](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_158 "Age Verification Popup")
|
42 |
-
|
43 |
-
= Popup Builder =
|
44 |
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
46 |
|
|
|
47 |
[youtube http://www.youtube.com/watch?v=-Q9-tWi-lQE]
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
In order to make visitors feel comfortable with popup on the site, in our [Popup plugin](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") we produced [more settings to adjust popup appearance unobtrusively](https://supsystic.com/docs/popup-triggers/ "Popup triggers") and display only most needed information with popup. In Pop Up settings you can establish how many times show popup for one guest, concrete day or night time to use popup, which pages you want popup can be seen, moment of popup closing and many others of these popup setting variants.
|
52 |
-
|
53 |
-
= Layered Popup Style =
|
54 |
-
|
55 |
-
Lots of first time popup users think where to place popup or at least how to place popuping popup as they want, because everybody understand that popup must be both gentle and appropriate. New technologies of popup builders and methodologies of popup masters inspired us to provide [Layered PopUp Style]( https://supsystic.com/popup-placement/
|
56 |
-
"Layered PopUp Style").
|
57 |
-
|
58 |
-
You can find this popup option following the pass: Popup plugin> Create new popup> Design> Popup Location. Here you see gratified Popup Layout with name of the site places for popup to appear.
|
59 |
-
|
60 |
-
Just choose a best spot for your popup and place. Thus your popup will be bonded to popup on the established popup cell.
|
61 |
-
|
62 |
-
= Popup Build-in Page =
|
63 |
-
|
64 |
-
In the case when Layered Popup Style doesn’t suit you, we have made another popup feature to satisfy your popup needs. This popup option right for people who always know what popup they want and how it must popuping on the page. So here comes Build-in page Popup. There is Main Tab Settings in the “Add New Popup” or “Open old Popup”. There, in the “When to Show Popup section” Build-in Page are waiting for your Popup adjustments.
|
65 |
-
|
66 |
-
By Build-in Page Popup shortcode you can explore it pasting Popup into the any place of your site for popup to stay there constantly. Ergo, site visitors will see popup information and will be delighted with the beauty of Your Popup Art.
|
67 |
-
|
68 |
-
= Popup Opening Animations =
|
69 |
-
|
70 |
-
Simple popuping window now hardly ever can impress at least somebody even popup owner. To untie the popup knot we offer you to taste our backed feature of modern popups - Opening and closing Popup Animation. [Supsystic Popup plugin](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") accounts twenty-eight different elated, amused and cheerful Popup animations!
|
71 |
-
To find and add euphoric popup to your site follow the instructions:
|
72 |
-
|
73 |
-
* “Add New Popup” or “Open old Popup”
|
74 |
-
* "Design" Popup Tab Settings
|
75 |
-
* Popup "Opening/ Closing Animation"
|
76 |
-
|
77 |
-
Splendid! Put your cursor on the one or just carry through of Popup animation squares and feel overflowing willy-willy of esthetic pleasure of popup aniart.
|
78 |
-
|
79 |
-
= Lock Content =
|
80 |
-
|
81 |
-
Some of sites are made only for adult or any other limited users auditory. If you are looking for feature to meet your requirements, come as you are to Popup Builder by Supsistic and Popup Your Life Simplicity!
|
82 |
-
|
83 |
-
We thought about popup for you and will tell how to Lock your site Content with Popup advantages. For this kind of popup follow the next:
|
84 |
-
|
85 |
-
1. “Add New Popup” or “Open old Popup”
|
86 |
-
2. “Main” Tab Settings of Popup
|
87 |
-
3. [“When to show”](https://supsystic.com/documentation/when-to-show-popup/ "When to show") PopUp
|
88 |
-
4. “When page loads”
|
89 |
-
5. [“When to close PopUp”](https://supsystic.com/documentation/when-to-close-popup/ "When to close PopUp")
|
90 |
-
6. “Only after action (Subscribe / Share / Like)”
|
91 |
-
7. [“Whom to show”](https://supsystic.com/documentation/whom-to-show-popup/ "Whom to show") PopUp
|
92 |
-
8. “Until user makes an action” on the Popup. One site user will need to subscribe on Popup only one time for a specified period. To make Popup remember only for one browser session – use 0 here, to make Popup remember forever – try to set big number.
|
93 |
-
9. Don’t forget to save changes in Popup Builder.
|
94 |
-
|
95 |
-
Now on site pages with [Popup](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") the users will see the Popup message stating that they need to share this page or login to unlock content. To set popup closing after login, make popup with login or contact form.
|
96 |
-
|
97 |
-
Locking content with popup builder can be also successfully practised for shops or blogs to connect emails with popup and then use Newsletter mailing to popup purchases by attractive proposition.
|
98 |
-
|
99 |
-
= Popup Plugin Support =
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
* Dutch
|
110 |
-
* French
|
111 |
-
* German
|
112 |
-
* Indonesian
|
113 |
-
* Italian
|
114 |
-
* Persian
|
115 |
-
* Polish
|
116 |
-
* Portuguese (Brazil)
|
117 |
-
* Romanian
|
118 |
-
* Russian
|
119 |
-
* Spanish
|
120 |
-
* Spanish (Colombia)
|
121 |
-
* Spanish (Mexico)
|
122 |
-
* Spanish (Venezuela)
|
123 |
-
* Turkish
|
124 |
-
|
125 |
-
Popup is the tool of professionals and people who are thirsty to new highs of success. Involve visitors with popup to show them better life of popup information and popup usage benefit.
|
126 |
-
At all corners of WWW Popup opens new possibility level for every popup user!
|
127 |
-
|
128 |
-
== Installation ==
|
129 |
-
|
130 |
-
= First Level Popup Supsystic user =
|
131 |
-
|
132 |
-
Welcome to the Popup World! To begin with Supsystic popup armor open plug-in admin WordPress panel to try popup on. Here you can “Add new” popup or customise one of “All Popups”.
|
133 |
-
|
134 |
-
To begin “Add new” popup in popup left menu. Choose popup template (you can change it later) accordingly to your popup requirements. Give the name to your Popup armor and save. As soon as Popup Builder prototype loaded set the options for your popup. Here you can establish when to show popup, whom to popup, on what pages popup info, add your content to popup. Design Popup with Popup Builder one and only and choose appropriate appearing / vanishing popup animation to shine bright like a diamond, note down popup description and social buttons. Additionally you can tool up with css and html Popup code editors.
|
135 |
-
Don't forget to "Save" Pop Up! After all last popup configurations you can see below in the popup previewer.
|
136 |
-
|
137 |
-
= To install a plugin via FTP, follow next popup instructions =
|
138 |
-
|
139 |
-
1. Download the Popup plugin
|
140 |
-
2. Unarchive the Popup plugin
|
141 |
-
3. Copy the folder with Popup plugin
|
142 |
-
4. Open ftp \wp-content\plugins\
|
143 |
-
5. Paste the plug-ins folder in the folder
|
144 |
-
6. Go to admin panel => open item "Plugins" => activate the Popup by Supsytic plugin
|
145 |
|
146 |
== Frequently Asked Questions ==
|
147 |
|
148 |
-
=
|
149 |
-
|
150 |
-
Often the goal for a website is to generate sales, increase subscription rates and develop loyal readership. If your site has a good traffic, but no conversion it’s frustrating for both you and your advertisers.
|
151 |
-
|
152 |
-
Professional internet marketers innovated Popup Builder for this needs. To fix the situation try on our Popup builder by Supsystic! Popup marketing research shows a huge potential of Popup for every site.
|
153 |
-
Best Popup effectivity can be reached due to this Popup features:
|
154 |
-
|
155 |
-
* Unlimited Popup Content Customization
|
156 |
-
* Auto Open Popups
|
157 |
-
* Contact Form with popup
|
158 |
-
* Popup Opening Animations
|
159 |
-
* Customizable Popup Themes
|
160 |
-
* Subscription popup window (WordPress, MailChimp and Aweber integration)
|
161 |
-
* Theme Popup Builder
|
162 |
-
* Responsive Popups
|
163 |
-
* Exit-intent popups that allow to capture lost visitors
|
164 |
-
|
165 |
-
= How to create Subscribe Custom Fields in Popup? =
|
166 |
-
|
167 |
-
Every demanding customer deserves to be satisfied with popup builder requirements. When you want more Pop Up features, Popup by Supsystic gives you more, just ask for popup clearly and be surprised popuply.
|
168 |
-
|
169 |
-
To get more popup custom fields in new popup:
|
170 |
-
|
171 |
-
* Popup Subscribe Tab
|
172 |
-
* Popup Subscription Fields block.
|
173 |
-
* Click “Add” button
|
174 |
-
* Enter the Name for your Popup field.
|
175 |
-
* Enter Label for Popup field – visible for subscribers.
|
176 |
-
* Enter default Popup field Value.
|
177 |
-
* Choose HTML type of Popup field – text, email, popup text area, popup select box, popup checkbox or hidden Popup field.
|
178 |
-
* Also here you can make Popup field mandatory to fill-in. Simply check Mandatory option and then users will not be able to continue without filling-in this Popup field.
|
179 |
-
* To finish the creation of new popup field – click “OK”.
|
180 |
-
* The default Popup fields (Name and Email) is stable. New Popup fields created independently in Popup – you can edit or delete in any moment.
|
181 |
-
|
182 |
-
Save your New Popup changes to popup purchases.
|
183 |
-
To know more detail of popup fields builder go [here](https://supsystic.com/subscribe-custom-fields-builder/ "here").
|
184 |
-
|
185 |
-
= How to add Contact Form into Popup? =
|
186 |
-
|
187 |
-
Supsystic [PopUp](https://supsystic.com/plugins/popup-plugin/ "PopUp") and [Contact Form](https://supsystic.com/plugins/contact-form-plugin/ "Contact Form") are lightly customizable. Beginners and Seniors will find advantages like user-friendly interface and a great number of functionality.
|
188 |
-
|
189 |
-
Contact Form can be integrated in Popup by several clicks, while this popup builder mix will give you a great popuping result. With Popup plugin Contact Form will fascinate your eyes focus to make you rich popup site owner. Such Popup mutation can be inserted in anywhere on your site. Note, that all Popup functions of will be accessible in your Contact Form. It’s an ideal way for those clients who want to gather the emails of the users, but not popup subscribers.
|
190 |
|
191 |
-
|
192 |
|
193 |
-
|
194 |
-
* “Add new Popup”
|
195 |
-
* Go to Popup Design
|
196 |
-
* Open Popup Text Window
|
197 |
-
* Insert Contact Form shortcode into Popup text builder
|
198 |
-
* Copy the Popup shortcode and insert it into the page text for popup to appear.
|
199 |
|
200 |
-
|
|
|
201 |
|
202 |
-
|
203 |
|
204 |
-
|
205 |
|
206 |
-
|
207 |
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
|
210 |
-
|
211 |
|
212 |
-
=
|
213 |
|
214 |
-
|
215 |
|
216 |
-
|
217 |
|
218 |
-
|
219 |
-
|
220 |
-
= Can I close PopUp after certain time? =
|
221 |
-
|
222 |
-
Yes. Light compliant Popup plugin backup can close the Popup window, just set the time in seconds by clicking on “After time passed” in "When to close PopUp" of Main Top Popup Settings.
|
223 |
-
|
224 |
-
== Screenshots ==
|
225 |
-
|
226 |
-
1. Login PopUp
|
227 |
-
|
228 |
-
2. Facebook like popup
|
229 |
-
|
230 |
-
3. Popup with YouTube video
|
231 |
-
|
232 |
-
4. PopUp Login / Registration Style
|
233 |
-
|
234 |
-
5. PopUp with google map and contact form
|
235 |
-
|
236 |
-
6. Social Buttons and contact form with popup
|
237 |
-
|
238 |
-
7. Popup WordPress plugin
|
239 |
-
|
240 |
-
8. Subscription popup templates. All [Popup Examples](https://supsystic.com/popup-examples?utm_source=wordpress&utm_medium=second_screenshot&utm_campaign=popup "Popup Examples")
|
241 |
-
|
242 |
-
|
243 |
-
== Other Notes ==
|
244 |
-
|
245 |
-
[Supsystic Popup plugin](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") has the lightest kids intuitive installation ever created. You can explore lots of different features of Popup Builder, like watching “YouTube” and “Vimeo” videos in the same popup window and appreciate the concrete animation of the Plugin by clicking on the thumbnails. Or creating contact form in Popup to collect user's emails and even make Popup work with [Newsletter Subscribe Form of Supsystic plugin](https://supsystic.com/plugins/newsletter-plugin "Newsletter plugin")! Thus not only gather user's emails, but also attach to different Subscriber Lists of mailing automatically.
|
246 |
-
|
247 |
-
Some of the main merits of Popup to instal right now:
|
248 |
-
|
249 |
-
1. Immediate operation after activation, no need for additional image/video configurations or short coding
|
250 |
|
251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
|
253 |
-
=
|
|
|
|
|
254 |
|
255 |
-
=
|
|
|
|
|
256 |
|
257 |
-
|
|
|
|
|
258 |
|
259 |
-
=
|
|
|
|
|
|
|
|
|
260 |
|
261 |
-
|
|
|
|
|
|
|
262 |
|
263 |
-
|
|
|
|
|
264 |
|
265 |
-
=
|
|
|
|
|
|
|
266 |
|
267 |
-
|
|
|
|
|
268 |
|
269 |
-
|
|
|
|
|
270 |
|
271 |
-
=
|
|
|
|
|
|
|
272 |
|
273 |
-
|
274 |
-
|
|
|
275 |
|
276 |
-
=
|
|
|
|
|
277 |
|
278 |
-
|
|
|
|
|
279 |
|
280 |
-
=
|
|
|
|
|
|
|
281 |
|
282 |
-
|
283 |
-
*
|
284 |
-
*
|
285 |
-
* [Data Tables Generator by Supsystic](https://wordpress.org/plugins/data-tables-generator-by-supsystic/ "Data Tables Generator by Supsystic")
|
286 |
-
* [Slider by Supsystic](https://wordpress.org/plugins/slider-by-supsystic/ "Slider by Supsystic")
|
287 |
-
* [Social Share Buttons by Supsystic](https://wordpress.org/plugins/social-share-buttons-by-supsystic/ "Social Share Buttons by Supsystic")
|
288 |
-
* [Coming Soon by Supsystic](https://wordpress.org/plugins/coming-soon-by-supsystic/ "Coming Soon by Supsystic")
|
289 |
-
* [Digital Publications by Supsystic](https://wordpress.org/plugins/digital-publications-by-supsystic/ "Digital Publications by Supsystic")
|
290 |
-
* [Backup by Supsystic](https://wordpress.org/plugins/backup-by-supsystic/ "Backup by Supsystic")
|
291 |
-
* [Membership by Supsystic](https://wordpress.org/plugins/membership-by-supsystic/ "Membership by Supsystic")
|
292 |
-
* [Newsletter by Supsystic](https://wordpress.org/plugins/newsletter-by-supsystic/ "Newsletter by Supsystic")
|
293 |
-
* [Live Chat by Supsystic](https://wordpress.org/plugins/live-chat-by-supsystic/ "Live Chat by Supsystic")
|
294 |
-
* [Google Maps Easy](https://wordpress.org/plugins/google-maps-easy/ "Google Maps Easy")
|
295 |
-
* [Translate by Supsystic](https://wordpress.org/plugins/translate-by-supsystic/ "Translate by Supsystic")
|
296 |
|
297 |
-
|
|
|
|
|
298 |
|
299 |
= 1.9.20 / 14.02.2018 =
|
300 |
* Minor issues fix
|
301 |
* Code review and improvements
|
302 |
|
303 |
= 1.9.19 / 07.02.2018 =
|
304 |
-
* Fix Facebook Like
|
305 |
|
306 |
= 1.9.18 / 06.02.2018 =
|
307 |
-
* Adapt Facebook Like
|
308 |
* Additional core code improvements
|
309 |
* Minor issues fixed
|
310 |
|
311 |
= 1.9.17 / 31.01.2018 =
|
312 |
-
* Possibility to create Primary buttons for actions in Age Verify
|
313 |
* Added full compatibility with older PHP versions (5.2)
|
314 |
* Fix issue with latest MailChimp API (V3) and it's Groups
|
315 |
* Campaign Monitor library fix
|
@@ -319,7 +177,7 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
319 |
|
320 |
= 1.9.15 / 28.12.2017
|
321 |
* Dotmailer subscription system integration
|
322 |
-
* Possibility to display only required data from iFrame
|
323 |
* Core code improvement (make it little faster)
|
324 |
|
325 |
= 1.9.14 / 27.11.2017
|
@@ -329,13 +187,13 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
329 |
|
330 |
= 1.9.13 / 21.11.2017
|
331 |
* Minor code issue fix
|
332 |
-
* Disable
|
333 |
* Possibility to insert images - from remove URLs too
|
334 |
* Core code improvements
|
335 |
|
336 |
= 1.9.12 / 14.11.2017
|
337 |
* Added options Create subscriber Disabled and Send Confirm email for Newsletters by Supsystic plugin subscriptions
|
338 |
-
* Additional fix for existing YouTube autoplay
|
339 |
* Minor Core code improvements
|
340 |
|
341 |
= 1.9.11 / 23.10.2017
|
@@ -349,13 +207,13 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
349 |
* Minor issues fix
|
350 |
|
351 |
= 1.9.9 / 11.10.2017
|
352 |
-
* Added "Documentation" as additional Post Type for
|
353 |
* Minor issues fix and improvements
|
354 |
|
355 |
= 1.9.8 / 05.10.2017
|
356 |
* Compatibility with MailPoet 3rd version
|
357 |
* Fixed issue when subscribing to already subscribed list with existing email to MailChimp
|
358 |
-
* Fix issue with Videos auto-play when
|
359 |
* Minor Core code improvements
|
360 |
|
361 |
= 1.9.7 / 07.09.2017
|
@@ -365,7 +223,7 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
365 |
|
366 |
= 1.9.6 / 10.08.2017
|
367 |
* Fix issue with Font Stiles and Colors for texts, that have inner html elements
|
368 |
-
* Fix small issue with
|
369 |
* Minor issues fix and improvements
|
370 |
|
371 |
= 1.9.5 / 22.06.2017
|
@@ -379,12 +237,12 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
379 |
|
380 |
= 1.9.3 / 24.04.2017
|
381 |
* Additional feedback improvements
|
382 |
-
* Fix issue with some non-latin characters in
|
383 |
* Additional core improvements
|
384 |
|
385 |
= 1.9.2 / 19.04.2017
|
386 |
* Added Age Verification templates detailed statistics
|
387 |
-
* Fixed issue with propagandizing cached stats for AB Test
|
388 |
* Fix small issue with ConstantContact subscribe service
|
389 |
* Core code improvements and minor issues fix
|
390 |
|
@@ -394,17 +252,17 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
394 |
* Code improvements
|
395 |
|
396 |
= 1.9.0 / 23.03.2017
|
397 |
-
* Possibility to show
|
398 |
* Small code improvements
|
399 |
* Access module improvements
|
400 |
* Compatibility with other WordPress plugins, that modify/remove iCheck library
|
401 |
* Compatibility with plugins/themes/WordPress setup when WP_USE_THEMES is not defined, or defined as "false"
|
402 |
-
|
403 |
-
= 1.8.9 / 14.03.2017
|
404 |
* Updated PHP Mailer library to latest version
|
405 |
-
* Fix issues with some Facebook
|
406 |
-
* Possibility to disable
|
407 |
-
* Fix possible issue with iframe without src in
|
408 |
* Minor fix for SendGrid updated API integration
|
409 |
|
410 |
= 1.8.8 / 21.02.2017
|
@@ -413,38 +271,38 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
413 |
|
414 |
= 1.8.7 / 16.02.2017
|
415 |
* WooCommerce categories added to Categories select list
|
416 |
-
* Facebook Like
|
417 |
* Fix HTTP images protocol for christmas snow effect
|
418 |
-
* Possibility to select week days when you need to show
|
419 |
* SMTP servers integration
|
420 |
* Send Mail service integration
|
421 |
-
* Possibility to just close
|
422 |
* Fix possible conflict if someone add html tag with name "ajaxurl"
|
423 |
* Setting images for backgrounds only with selected in WordPress library size
|
424 |
* Possibility to show Close button for Close mode - "Only after action (Subscribe / Share / Like)"
|
425 |
|
426 |
= 1.8.6 / 26.01.2017
|
427 |
-
* Possibility to manually create Passwords on Frontend
|
428 |
-
* Additional re-position and resize
|
429 |
-
* Do not use
|
430 |
* Blacklist error message editing
|
431 |
-
* Make correct work Layered
|
432 |
-
* Fix issue with displaying
|
433 |
|
434 |
= 1.8.5 / 12.01.2017
|
435 |
* Fix MailChimp Groups List sending value in email
|
436 |
* Fixed old code for php 7 compatibility
|
437 |
* SendGrid API update
|
438 |
-
* Added
|
439 |
-
* Added
|
440 |
-
* Added
|
441 |
-
* Added
|
442 |
* Minor code review
|
443 |
|
444 |
= 1.8.4 / 19.12.2016 =
|
445 |
-
* Redesign
|
446 |
-
* Redesign
|
447 |
-
* Added
|
448 |
* Added possibility to add emails / email templates into Blacklist - PRO
|
449 |
* Admin area design minor improvements
|
450 |
* Code optimizations
|
@@ -453,20 +311,20 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
453 |
= 1.8.3 / 07.12.2016 =
|
454 |
* Background Overlay settings added: Color, Image and Snow
|
455 |
* Paralax Page Builder compatibility
|
456 |
-
* Fix
|
457 |
-
* Added
|
458 |
-
* Added
|
459 |
-
* Added
|
460 |
-
* Added
|
461 |
-
* Forgot Password link for Login
|
462 |
|
463 |
= 1.8.2 / 29.11.2016 =
|
464 |
-
* Added [Christmas
|
465 |
* Minor issues fix
|
466 |
|
467 |
= 1.8.1 / 23.11.2016 =
|
468 |
* Added possibility to use HTML tags in Subscribe / Registration fields Labels
|
469 |
-
* Possibility to show
|
470 |
* Mobile detection library update - new devices detection
|
471 |
* SG Autorepondeur API updated
|
472 |
* Minor admin area design improvements
|
@@ -474,10 +332,10 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
474 |
* Language pack updated
|
475 |
|
476 |
= 1.8.0 / 02.11.2016 =
|
477 |
-
* New
|
478 |
* Update mobile detection library
|
479 |
-
* Possibility to integrate
|
480 |
-
* Added new Statistic Event Types -
|
481 |
* 4Dem.it Subscription service integration - PRO
|
482 |
* Your Mailing List Provider (Ymlp) Subscription service integration - PRO
|
483 |
* Vtiger CRM Subscription service integration - PRO
|
@@ -490,14 +348,14 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
490 |
* Fix minor HTML coding issues in admin area (correct build-in tables formatting)
|
491 |
* Improve option "Disable window scroll"
|
492 |
* Additional compatibility check for Campaign Monitor library in other plugins installed
|
493 |
-
* Added users inactivity logout
|
494 |
-
* Admin area
|
495 |
* Minor issues fix and improvements
|
496 |
|
497 |
= 1.7.10 / 21.09.2016 =
|
498 |
* Integration with [Digital Publication plugin](https://wordpress.org/plugins/digital-publications-by-supsystic/ "Digital Publication WordPress Plugin")
|
499 |
* Integration with [Newsletter by Supsystic plugin] (https://wordpress.org/plugins/newsletter-by-supsystic/ "Newsletter by Supsystic WordPress plugin")
|
500 |
-
* Re-posite
|
501 |
* Minor bugs fixed
|
502 |
|
503 |
= 1.7.9 / 07.09.2016 =
|
@@ -519,47 +377,47 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
519 |
|
520 |
= 1.7.6 / 21.07.2016 =
|
521 |
* Fix issue with conflict of Font and Text Color styles and styles of users custom themes (theme styles often override our styles, now it will not occur anymore)
|
522 |
-
* Fixed issue for showing
|
523 |
* Integration with Contact Form plugin (step 1 - correct show shortcodes)
|
524 |
* Options with Disabling CDN usage description link added
|
525 |
-
* Correct update iFrames after
|
526 |
-
* Fixed issue with multiple shortcodes compilation from
|
527 |
-
* Fixed issue with multiple "
|
528 |
* Added Spanish (Venezuela), Dutch languages and updated Spanish translation
|
529 |
* Minor spelling issues fix
|
530 |
|
531 |
= 1.7.5 / 21.06.2016 =
|
532 |
* Small fixes of welcome page and step-by step tutorial
|
533 |
* Fix small issue with Facebook Subscription
|
534 |
-
* Possibility to export all subscribers from all
|
535 |
-
* Possibility to redirect to link URL after subscribe if On Click link was used to show
|
536 |
* Fix issue with detecting required user roles for Show / Hide for user role functionality for cases when user have several roles
|
537 |
|
538 |
= 1.7.4 / 07.06.2016 =
|
539 |
-
* Possibility to disable CDN server usage - and move all assets to own
|
540 |
-
* Fix issue with showing
|
541 |
* Code review and re-factor
|
542 |
* Minor improvements
|
543 |
|
544 |
= 1.7.2 / 17.05.2016 =
|
545 |
-
* Possibility to enable Label at the top of the Facebook Widget
|
546 |
-
* Option to show
|
547 |
* Possibility to send any user data - to email with user confirm link, and in email to new user subscribers
|
548 |
* Added New Subscribers notification email Subject option
|
549 |
-
* Show / Hide
|
550 |
-
* Small fixes and improvements for
|
551 |
-
* Possibility to select categories for
|
552 |
-
* Possibility to insert shortcodes in Subscribe fields values
|
553 |
-
* Possibility to insert scripts - inside
|
554 |
-
* Show
|
555 |
* Fixed conflicts with WordPress plugins, that make URLs relative
|
556 |
* Fixed conflicts with other themes and plugins, that using zoom jQuery method with same method name
|
557 |
* Code review and improvements
|
558 |
|
559 |
= 1.7.1 / 28.04.2016 =
|
560 |
-
* New
|
561 |
* MailChimp API key - ignore space symbols in beginning or ending of it in case they was inserted accidentally
|
562 |
-
* Fix issue with Social Share by Supsystic project sharing re-selecting from
|
563 |
* Updated Italian translation
|
564 |
* Additional TinyMCE check in admin area - to make sure we will not call errors in case it's absent on user WP configuration
|
565 |
* Sending mail functionality improvements
|
@@ -568,16 +426,16 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
568 |
* Added new subscribe form field type - MailChimp Groups List
|
569 |
* Minor admin area design improvements
|
570 |
* InfusionSoft - set all subscribers Marketable after subscribe
|
571 |
-
* Background fix for PDF
|
572 |
-
* Age Verification
|
573 |
|
574 |
= 1.6.9 / 13.04.2016 =
|
575 |
-
* Hot fix for WordPress 4.5 and On Click
|
576 |
-
* Fix On Click
|
577 |
|
578 |
= 1.6.8 / 12.04.2016 =
|
579 |
* Aweber - change subscribe URL to SSL protocol
|
580 |
-
* "Pink"
|
581 |
* Small subscribe messages success conflict fix
|
582 |
* Minor issue fixes and code improvements
|
583 |
|
@@ -585,13 +443,13 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
585 |
* Fix Facebook Widget - Share functionality: adapt it to new Facebook API usage
|
586 |
|
587 |
= 1.6.6 / 06.04.2016 =
|
588 |
-
*
|
589 |
* Small spelling issues fix
|
590 |
|
591 |
= 1.6.5 / 05.04.2016 =
|
592 |
-
* Possibility to use Subscribe, Login and Registration forms - in one
|
593 |
-
* Small fix for "Photodoto"
|
594 |
-
* Added option "Redirect after close" - you can now redirect your users after they will close
|
595 |
* Emma email subscription service integration - PRO
|
596 |
* Correct subscriber, registration and login form work with enable cache plugins (W3 Total Cache or Super Cache)
|
597 |
* Don't send standard WordPress new users notifications if all messages fields was cleared by user
|
@@ -603,34 +461,34 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
603 |
* InfusionSoft - Tags added
|
604 |
* Fix issue with redirect after authorization on InfusionSoft system
|
605 |
* Correct Whom to show -> Number times in a day option in admin are for RTL languages
|
606 |
-
* Fix issue with new Registered user through
|
607 |
* iContact - added "prefix" additional default field support
|
608 |
* BenchmarkEmail, MailRelay, SendGrid - small fix for encoding / decoding internal API data
|
609 |
-
* Small fix for "List Building Layered"
|
610 |
|
611 |
= 1.6.3 / 22.03.2016 =
|
612 |
-
* Fix issue with showing
|
613 |
* Added another supported video hosting service
|
614 |
-
* Small fix for build-in content popup - do not load them in standard
|
615 |
* Minor debug issues fix
|
616 |
|
617 |
= 1.6.2 / 17.03.2016 =
|
618 |
* SGautorepondeur - small issue with server response fix
|
619 |
* Subscribe additional fields - selectbox field type - fix option adding process
|
620 |
-
* Added option to show
|
621 |
-
* Small fix for PDF
|
622 |
-
* Make correct open/close Video
|
623 |
|
624 |
= 1.6.1 / 14.03.2016 =
|
625 |
* Full RTL (Right-to-Left) languages support
|
626 |
* Possibility to disable HTML emails content type - for servers, that doesn't allow to send such emails
|
627 |
-
* Fix issue with iFrames reloading after
|
628 |
* ConvertKit subscription method integration - PRO
|
629 |
-
*
|
630 |
* Disable block IP for multiple subscriptions by default
|
631 |
-
* Improve On Exit
|
632 |
* Fixed minor conflicts in admin area with other javascript codes of other themes and plugins
|
633 |
-
* Added possibility to use Registration and Login form - in one
|
634 |
* Count time from first site load option added
|
635 |
* jQuery UI admin area CSS - small compatibility with other plugins fix
|
636 |
* Added possibility to add fields with type = email
|
@@ -640,37 +498,37 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
640 |
= 1.6.0 / 02.03.2016 =
|
641 |
* Remove unused error message parts from MailChimp errors
|
642 |
* SalesForce - Web-to-Lead integration - PRO
|
643 |
-
* Close video
|
644 |
* Constant Contact - add contact even if it exist in some other subscription lists
|
645 |
* InfusionSoft subscription method added - PRO
|
646 |
* Additional compatibility with Google Maps Easy plugin https://wordpress.org/plugins/google-maps-easy/
|
647 |
* Language files update and minor spelling issues fix
|
648 |
|
649 |
= 1.5.9 / 25.02.2016 =
|
650 |
-
* Quick fix for Date Picker library in admin area ->
|
651 |
* Small spelling issue fix in admin area
|
652 |
* MailChimp - replace tags into variables names if error from MailChimp server about variable is returned
|
653 |
|
654 |
= 1.5.8 / 23.02.2016 =
|
655 |
-
* Jetpack subscription engine added - now you can subscribe
|
656 |
-
* Added Date display range
|
657 |
* Count already subscribed user as subscriber on client side if email already exists and "Redirect if email already exists" option is enabled
|
658 |
* iContact Subscribe method integration
|
659 |
* GetResponse Subscribe method improvements
|
660 |
* Always send form on Enter press in Subscribe form
|
661 |
* Fix issue with HTTPS loading fonts in Fonts PRO module
|
662 |
* GetResponse - added new field - "Cycle Day"
|
663 |
-
* Don't pass unused
|
664 |
* MailChimp - fix issue with limit of Subscribe lists, shown in admin area (there was standard limit in 25 lists)
|
665 |
* Core code improve (minor "strict standards" php notice fix)
|
666 |
-
* Facebook Subscribe - fix result messages (or errors) - now they will be visible in
|
667 |
-
* When to close
|
668 |
* Update Spanish translation
|
669 |
* Code review
|
670 |
|
671 |
= 1.5.7 / 16.02.2016 =
|
672 |
-
* Added Search Engines and Social Media sites detection - to show/hide
|
673 |
-
* Possibility to insert
|
674 |
* Added names for Backgrounds - now they will show for what exactly each other is corresponding for
|
675 |
* MailRelay Subscribe method fix
|
676 |
* Spelling issues fix
|
@@ -680,83 +538,83 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
680 |
= 1.5.6 / 02.02.2016 =
|
681 |
* Added subscribe from URL variable to subscribers emails - [subscribe_url]
|
682 |
* If user is already subscribed to MailChimp - count this as done subscribe action, and not error
|
683 |
-
* "Email exists" error message option
|
684 |
-
* Reduce user browser memory usage to work
|
685 |
* Functionality to show only for first time visitors popup even if they are shown "On Click"
|
686 |
-
* Fix issue with opening Media Library on Enter key press in
|
687 |
-
* Small fix for
|
688 |
-
* "Add
|
689 |
|
690 |
= 1.5.5 / 26.01.2016 =
|
691 |
* MailChimp Groups functionality added
|
692 |
-
* Do not send CSS and HTML data when editing
|
693 |
-
* Possibility to force show
|
694 |
-
* Minor fix for Business
|
695 |
* Improve IP detection algorithm
|
696 |
-
* Small correct for TinyMce buttons colors on
|
697 |
-
* Minor fixes for
|
698 |
-
* Added option "Disable window scroll" to disable browser window scrolling while
|
699 |
-
* Show
|
700 |
|
701 |
= 1.5.4 / 13.01.2016 =
|
702 |
* Possibility to create WordPress Subscribers with different then WordPress subscribers mail engine
|
703 |
* Added option to load all plugin assets - in site footer - to increase page speed load
|
704 |
* Correct detecting mobile device with On Exit functionality
|
705 |
-
* Possibility to add attachments to email from
|
706 |
-
* Fix positioning for Responsive mode
|
707 |
* Update English and Russian languages
|
708 |
* Minor translation issues fix
|
709 |
|
710 |
= 1.5.3 / 21.12.2015 =
|
711 |
-
* Fix possibility to show
|
712 |
* Increase popup z-index - to make sure that it is located above other elements
|
713 |
* New pretty loader
|
714 |
* Correct Overview page for case if mysql_get_server_info() function are missing
|
715 |
* Video popup - added self-hosted video support
|
716 |
-
* Additional Responsive mode - "Width only", with possibility to select most suitable mode in
|
717 |
-
* Added "Ignore related videos" option for Video type
|
718 |
* Plugin server-side core improvements
|
719 |
-
* On Exit
|
720 |
* Checkbox additional fields type improvements
|
721 |
* Minor issue fix in Mailrelay modules
|
722 |
|
723 |
= 1.5.2 / 14.12.2015 =
|
724 |
-
* Change
|
725 |
-
* Correct shortcodes display in admin area on small
|
726 |
* Benchmark email service integration - PRO
|
727 |
* Added additional subscribe fields - to CSV Subscribers export file
|
728 |
* Subscribe checkbox additional field display improvements
|
729 |
-
* Disable autosave on
|
730 |
-
* Fix for "On Link Follow"
|
731 |
-
* Improve "START
|
732 |
|
733 |
= 1.5.1 / 08.12.2015 =
|
734 |
* Required fields Subscribe validation for Safary browser on client side
|
735 |
-
* Templates "Simple iFrame", "Simple HTML", "HTML 2 Columns", "PDF
|
736 |
* Step by step tour for first time users
|
737 |
-
* Added option for Time Delay for
|
738 |
* Fixed build-in Contact Form Support email address
|
739 |
* Minor AB testing issue fix (when have many original popup with tested popup)
|
740 |
* Mailrelay - minor issue fix
|
741 |
|
742 |
= 1.5.0 / 03.12.2015 =
|
743 |
-
* Added "Time display settings" to add possibility show
|
744 |
-
* Minor issue fixed for
|
745 |
-
*
|
746 |
-
* Notification Bar
|
747 |
-
* Login / Registration
|
748 |
-
* A lot of new
|
749 |
|
750 |
= 1.4.6 / 17.11.2015 =
|
751 |
* Small code improvements
|
752 |
-
* "Map style"
|
753 |
* Minor spelling issues fix
|
754 |
* Small fix for "List Building Layered" PRO template
|
755 |
* Added Spanish (Colombia) language
|
756 |
|
757 |
= 1.4.5 / 10.11.2015 =
|
758 |
* Fixed issue with PRO for multi-sites
|
759 |
-
* Changed sort orders of
|
760 |
* PRO - Updated Facebook API usage
|
761 |
* Minor core code improvements
|
762 |
|
@@ -768,17 +626,17 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
768 |
= 1.4.3 / 03.11.2015 =
|
769 |
* New Animation library added - more animations with better performance!
|
770 |
* Small issue fix with WordPress Subscribers export
|
771 |
-
* Small admin area
|
772 |
* Corrections for responsiveness - now will correct display on all devices
|
773 |
* Added Polish language
|
774 |
-
* Small fix for Calm
|
775 |
-
* AB Testing - added possibility to select Main (Display) settings for tested
|
776 |
* MailRelay module - minor code improvements
|
777 |
* ConstantContact - added compatibility with other plugins, that can use same ConstantContact API SDK
|
778 |
-
* Small fix for Video Classy
|
779 |
|
780 |
= 1.4.2 / 27.10.2015 =
|
781 |
-
* Minor issues fix for "List Building", "Bonus" and "Smart"
|
782 |
* Remove admin tooltips animation - just to check now it will be look like
|
783 |
* Small fixes for preview templates Pink and Discount
|
784 |
* Export subscribers to WordPress users list as CSV file (all subscribers - confirmed and unconfirmed too)
|
@@ -786,27 +644,27 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
786 |
* Make custom selects in admin area - responsive
|
787 |
* Fix List Green and Green Dots bullets
|
788 |
* Change version for js and css files each time new version is release - to avoid using browser cache
|
789 |
-
* Small fixes for Business and Map style
|
790 |
|
791 |
= 1.4.1 / 21.10.2015 =
|
792 |
* Added HTML5 Subscribe fields validation on client side - fast and light!
|
793 |
-
* Small fix to make proper work responsiveness + animation feature when need to reduce size after
|
794 |
* Fix issue for compatibility with styles output on some mobile devices
|
795 |
* Admin WordPress more pretty menu icon
|
796 |
* Additional clarification link to documentation about MailChimp usage
|
797 |
* Improve usability - move to Design tab after template was changed
|
798 |
* Backgrounds images preview in admin area - max width to 300px
|
799 |
* Admin area -> Make Background opacity slider - smaller
|
800 |
-
* Small fix for Find Us and Map style
|
801 |
* Admin area - fixes for small devices
|
802 |
|
803 |
= 1.4.0 / 13.10.2015 =
|
804 |
* Compatibility with Minification functionality (provided by other plugins, for example - W3 Total Cache)
|
805 |
-
* Make
|
806 |
* Small spelling issues fix
|
807 |
* Fixed optin template Map style
|
808 |
* Fix issue with displaying popup and Google Maps in it (when Maps didn't load it's scripts correctly on some themes)
|
809 |
-
* Admin lead generator interface design small improvements - make it more
|
810 |
* More interactions with our users - just trying improve software for your needs!
|
811 |
* Small fix for SendGrid admin js issue
|
812 |
|
@@ -814,7 +672,7 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
814 |
* Fix small issue for servers, that make auto translate "&" sign to "&" in http_build_query() function
|
815 |
* Fixed small issue with MailRelay and SendGrid modules (encryption/decryption saved tokens length)
|
816 |
* Fix issue with pre-load images algorithm: for cases when type background selected as Image, but actually no image was selected
|
817 |
-
* "Link Follow" show
|
818 |
|
819 |
= 1.3.8 / 28.09.2015 =
|
820 |
* Notification about new subscribers for all Subscription services functionality added
|
@@ -838,39 +696,39 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
838 |
|
839 |
= 1.3.5 / 17.09.2015 =
|
840 |
* Welcome page added to plugin admin area
|
841 |
-
*
|
842 |
* Active Campaign Subscription service integration - PRO
|
843 |
* Plugin core code improvements
|
844 |
|
845 |
= 1.3.4 / 12.09.2015 =
|
846 |
* Added compatibility with WordPress 3.4.2
|
847 |
-
* Fixed issue with "displacements" of content in
|
848 |
* Code review and core code improvements
|
849 |
* Minor issues fix
|
850 |
|
851 |
= 1.3.3 / 08.09.2015 =
|
852 |
-
* More flexible way to pre-load images
|
853 |
* Make Admin area preview load faster
|
854 |
* Additional integrations with Google Maps - https://wordpress.org/plugins/google-maps-easy/
|
855 |
* Small code review and improvements
|
856 |
|
857 |
= 1.3.2 / 01.09.2015 =
|
858 |
* GetResponse Subscribe integration - PRO
|
859 |
-
* Added sort order to base
|
860 |
* Minor issues fix
|
861 |
* Small code review and improvements
|
862 |
|
863 |
= 1.3.1 / 25.08.2015 =
|
864 |
* Additional Subscribe fields - new field type - Hidden
|
865 |
* Added Spanish (MEXICO) language
|
866 |
-
* Simple images preload
|
867 |
* Compatibility for themes where jquery library added more then 1 time
|
868 |
|
869 |
= 1.3.0 / 13.08.2015 =
|
870 |
* Added 4 new templates with Google Maps and Contact Form!
|
871 |
* New text list bullet type
|
872 |
* Added fix for servers without ctype_alpha standard PHP function
|
873 |
-
* Admin
|
874 |
* Fix minor issues in templates
|
875 |
|
876 |
= 1.2.9 / 04.08.2015 =
|
@@ -882,8 +740,8 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
882 |
= 1.2.8 / 31.07.2015 =
|
883 |
* Added new template with map
|
884 |
* Fix issue for servers, that doesn't have "hash" php function
|
885 |
-
* Fix problem with viewing lists of posts/pages where need to show/hide
|
886 |
-
* Possibility to edit
|
887 |
* Redirect link option for case if email is already subscribed
|
888 |
|
889 |
= 1.2.7 / 24.07.2015 =
|
@@ -892,7 +750,7 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
892 |
* Layered style - fix displaying saved setting in admin area
|
893 |
* Minor admin area design improvements
|
894 |
* Integration with Social Share Buttons plugin - https://wordpress.org/plugins/social-share-buttons-by-supsystic/
|
895 |
-
* Additional improvements for "On Click"
|
896 |
* Constant Contact Subscribe Engine integration - PRO
|
897 |
* Campaign Monitor Subscribe Engine integration - PRO
|
898 |
* Vertical Response Subscribe Engine integration - PRO
|
@@ -900,7 +758,7 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
900 |
* SendGrid Subscribe Engine integration - PRO
|
901 |
* SG Autorepondeur Engine integration - PRO
|
902 |
* Added "Show Only" option in addition for options Hide for Devices, Hide for Post Types, Hide for for IP, Hide for Countries and Hide for Languages
|
903 |
-
* Functionality to show
|
904 |
|
905 |
= 1.2.6 / 16.07.2015 =
|
906 |
* Added new template "Discount"
|
@@ -918,7 +776,7 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
918 |
* Reduce plugin size - move static images to our server
|
919 |
|
920 |
= 1.2.5 / 01.07.2015 =
|
921 |
-
* Added new template - "
|
922 |
* Minor PHP warnings fix
|
923 |
* Adding PRO options to change font color in popup fields
|
924 |
* Minor issues fix
|
@@ -937,105 +795,105 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
937 |
* Responsive Overview admin page
|
938 |
* Admin area small design improvements
|
939 |
* Remove some old code - to make plugin lighter
|
940 |
-
* Fix color for Success Subscribe message for all
|
941 |
|
942 |
= 1.2.2 / 04.06.2015 =
|
943 |
-
* Possibility to insert "embed" shortcodes to text fields
|
944 |
* Small fix for "Best Of Collection" template
|
945 |
* Minor issues fix and code improvements
|
946 |
|
947 |
= 1.2.1 / 29.05.2015 =
|
948 |
* Added new template "Best Of Collection"
|
949 |
-
* START
|
950 |
-
* Fixed close button position in Exclusive template and
|
951 |
* Minor issues fixes and improvements
|
952 |
|
953 |
= 1.2.0 / 19.05.2015 =
|
954 |
-
* Fixed
|
955 |
-
* Added Russian
|
956 |
-
* Subscribe
|
957 |
-
* Small
|
958 |
-
* Language
|
959 |
-
* Aweber
|
960 |
-
* Some
|
961 |
-
* Small
|
962 |
-
* Admin
|
963 |
-
* Correct
|
964 |
|
965 |
= 1.1.9 / 07.05.2015 =
|
966 |
-
* Code
|
967 |
-
* Minor
|
968 |
|
969 |
= 1.1.8 / 30.04.2015 =
|
970 |
-
* Added
|
971 |
-
* Fix for
|
972 |
-
* Added new
|
973 |
-
* Close
|
974 |
-
* Small
|
975 |
-
* Small
|
976 |
-
* Check your server
|
977 |
-
* Fixed
|
978 |
|
979 |
= 1.1.7 / 23.04.2015 =
|
980 |
-
* Admin
|
981 |
-
* Fix
|
982 |
-
* Hide popup for Logged-in
|
983 |
-
*
|
984 |
|
985 |
= 1.1.6 / 14.04.2015 =
|
986 |
* Correction for cookie lifetime in recording user actions
|
987 |
-
* Fix
|
988 |
-
* Some
|
989 |
-
* Fix
|
990 |
-
* Minor
|
991 |
-
* Small
|
992 |
* Popup MailChimp - disable double opt-in option
|
993 |
-
* Improve
|
994 |
-
* Social
|
995 |
-
* Minor
|
996 |
|
997 |
= 1.1.5 / 07.04.2015 =
|
998 |
-
*
|
999 |
-
*
|
1000 |
* Shortcode popup output in admin area - make it more comfortable to copy and move to content
|
1001 |
-
* Fixed
|
1002 |
-
* Facebook
|
1003 |
-
* Correct displaying usual embed iframes with Google Maps
|
1004 |
-
* PRO
|
1005 |
-
* PRO
|
1006 |
-
* PRO
|
1007 |
-
* PRO
|
1008 |
-
* Some
|
1009 |
-
* Core
|
1010 |
|
1011 |
= 1.1.4 / 01.04.2015 =
|
1012 |
* MailPoet popup Subscribe integration
|
1013 |
* Possibility to select Home page of whole site - to show or not popup
|
1014 |
-
* New
|
1015 |
* Option to edit popup From field in emails to subscriber
|
1016 |
-
* Small
|
1017 |
-
* Added German
|
1018 |
-
* PRO
|
1019 |
-
* Correction for Video
|
1020 |
-
* Minor
|
1021 |
|
1022 |
= 1.1.3 / 24.03.2015 =
|
1023 |
-
* Play/Stop
|
1024 |
-
* Fix
|
1025 |
-
* Added French
|
1026 |
-
* Added Spanish
|
1027 |
-
* Correction for
|
1028 |
-
* Overview - FAQ
|
1029 |
|
1030 |
= 1.1.2 / 20.03.2015 =
|
1031 |
-
* Added
|
1032 |
-
* Special
|
1033 |
-
* Small
|
1034 |
-
* Compile
|
1035 |
-
* Some
|
1036 |
-
* Overview
|
1037 |
-
* Statistics
|
1038 |
-
* Correct
|
1039 |
|
1040 |
= 1.1.1 / 10.03.2015 =
|
1041 |
* Subscription - possibility to modify subscribe messages - browser notifications, email subject and content
|
@@ -1043,103 +901,103 @@ Working with adult site content, sometimes is needed to be sure kids not watchin
|
|
1043 |
* Statistics - show data if week / month is selected with date range that is in current week / month
|
1044 |
* Mailchimp popup API class - minor correct for DEBUG mode
|
1045 |
* Correct popup saving "&" sign - in text fields
|
1046 |
-
* Fix
|
1047 |
-
* Correct
|
1048 |
* Added popup link to documentation about usage code - HTML and CSS - editor
|
1049 |
-
* Correct
|
1050 |
* Minor fixes for base templates
|
1051 |
* PRO - On Exit functionality integration - https://supsystic.com/plugins/popup-plugin/
|
1052 |
* Fix issue - with multiple time showing when "On Click" mode is enabled and animation is added
|
1053 |
-
* Added usual posts to list where show or not
|
1054 |
|
1055 |
= 1.1.0 / 05.03.2015 =
|
1056 |
-
* Added 5 new
|
1057 |
-
*
|
1058 |
-
*
|
1059 |
-
*
|
1060 |
-
*
|
1061 |
* Possibility to disable popup (not delete, but just disable)
|
1062 |
-
* Clone
|
1063 |
* Admin UI style improvements - make it more pretty and comfortable for usage
|
1064 |
* After change measure type for With - from px to % - make sure that width value - is not more then 100
|
1065 |
-
* Additional
|
1066 |
-
* AB
|
1067 |
-
*
|
1068 |
|
1069 |
= 1.0.9 / 24.02.2015 =
|
1070 |
* Allow to assign new subscribers - special roles
|
1071 |
-
* Option to disable
|
1072 |
* Additional fix for mobile devices
|
1073 |
-
* Small fix for latest added
|
1074 |
-
* Main
|
1075 |
-
* Show
|
1076 |
-
* Option to show
|
1077 |
-
* Layered
|
1078 |
-
* Additional
|
1079 |
-
* A/B
|
1080 |
-
* Admin
|
1081 |
-
* Correct show
|
1082 |
-
* Fix sticky edit
|
1083 |
|
1084 |
= 1.0.8 =
|
1085 |
-
* Added
|
1086 |
* Video popup - Hide Controls option
|
1087 |
-
* New
|
1088 |
* Fix php notice for enabled debug mode for some php versions on activation
|
1089 |
-
* Added localization
|
1090 |
-
* Change Aweber
|
1091 |
-
* Fix issue for "Click on certain link / button / other element" - when there are more
|
1092 |
-
* Make
|
1093 |
* Make popup Animation selection - more obviously
|
1094 |
-
* Admin
|
1095 |
-
* Animation
|
1096 |
-
* Helper
|
1097 |
-
* PRO
|
1098 |
-
* Core
|
1099 |
-
* Minor
|
1100 |
|
1101 |
= 1.0.7 =
|
1102 |
-
* Accept shortcodes in
|
1103 |
-
* Possibility to show
|
1104 |
* Popup Fix for case when no template was selected during PopUp creation
|
1105 |
-
* Additional
|
1106 |
-
* Minor
|
1107 |
|
1108 |
= 1.0.6 =
|
1109 |
* MailChimp integration with popup
|
1110 |
* Video popup - Autoplay option added
|
1111 |
-
* Correct position set for Facebook Like
|
1112 |
-
* Re-calculate position for each
|
1113 |
-
* Fix
|
1114 |
* Disable popup clicking and submitting forms inside preview iFrame in admin area
|
1115 |
* Fix images load as background - added load WordPress media gallery
|
1116 |
-
* List
|
1117 |
-
* Fastest and Easiest
|
1118 |
* Fix Popup for smaller window size - responsive from now!
|
1119 |
-
* Correct "none"
|
1120 |
-
* Rename
|
1121 |
-
* Fix
|
1122 |
-
* Tooltip
|
1123 |
-
* Some
|
1124 |
-
* Compress some
|
1125 |
* Admin popup UI design minor optimizations - make it's usage more comfortable for You
|
1126 |
|
1127 |
= 1.0.5 =
|
1128 |
-
* Fixed
|
1129 |
|
1130 |
= 1.0.4 =
|
1131 |
* Fixes Popup for DEBUG mode enabled
|
1132 |
|
1133 |
= 1.0.3 =
|
1134 |
-
* Remove some unused
|
1135 |
-
* New
|
1136 |
-
*
|
1137 |
-
* Correct
|
1138 |
|
1139 |
= 1.0.2 =
|
1140 |
-
*
|
1141 |
-
*
|
1142 |
-
*
|
1143 |
|
1144 |
= 1.0.1 =
|
1145 |
* Popup plugin submit to WordPress.org
|
1 |
=== Popup by Supsystic ===
|
2 |
Contributors: supsystic.com
|
3 |
Donate link: https://supsystic.com/plugins/popup-plugin
|
4 |
+
Tags: popup, popup WordPress plugin, marketing, popover, pop-up, popup builder, social popup, facebook popup, popup builder, popup maker
|
5 |
+
Tested up to: 4.9.8
|
6 |
+
Stable tag: 1.9.38
|
7 |
|
8 |
+
Create elegant popup easily with Popup Builder by Supsystic. Popup with Subscription Forms, Facebook popup, Optin and Social locks, Contact Forms etc.
|
9 |
|
10 |
== Description ==
|
11 |
|
12 |
+
[Popup plugin by Supsystic](https://supsystic.com/plugins/popup-plugin?utm_source=wordpress&utm_medium=description&utm_campaign=popup "Popup WordPress Plugin") with Popup Builder helps you get newsletter subscribers, promote new products, make special offers and attract more social followers.
|
13 |
|
14 |
+
Create a lightbox easily with any type of information you want to show to your visitors. You can simply choose the most appropriate popup type and template that fit the design of your website and make a popup in the shortest time. Add a shortcode to any post, where you want to show a popup. It is possible to make unlimited number of popups with unique configurations.
|
15 |
+
The intuitive admin panel interface was developed to let you easily customize popup location, sizes, set loading and closing options, etc.
|
16 |
+
According to your needs, show popup only to first time users, or for everybody. It can be loaded automatically with time delay or by clicking on a specific location. There are many options helping to adapt the popup to the individual needs.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
|
|
18 |
|
19 |
+
= Main Features =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
+
* Choose one of 69 mobile-friendly [Popup Templates](https://supsystic.com/popup-examples?utm_source=wordpress&utm_medium=features&utm_campaign=popup) for your website. It is possible to create and manage an unlimited number of popups, or set [Popup Triggers](https://supsystic.com/docs/popup-triggers?utm_source=wordpress&utm_medium=featurestriggers&utm_campaign=popup). It's easy to choose whom, where, when and how to show your pop up, conditions to close it (we assume that you wouldn’t like annoy your customers with non-closing windows).
|
22 |
+
* [Over 18 Popup types](https://supsystic.com/popup-examples?utm_source=wordpress&utm_medium=featurestypes&utm_campaign=popup), so even the pickiest user will find the one which fits their needs perfectly. And if you`d like to make our perfect preset more adorable, you can customize it with usual builder and HTML/СSS editor.
|
23 |
+
* Different [Popup Location](https://supsystic.com/documentation/popup-location?utm_source=wordpress&utm_medium=featureslocation&utm_campaign=popup) on the page in one click. Pop-up can be shown at any place on your page – bottom, top, center, left, right, in the corner of the page etc.
|
24 |
+
* [20+ Opening Animations](https://supsystic.com/documentation/popup-animations?utm_source=wordpress&utm_medium=featuresanimation&utm_campaign=popup). Feel like you are a wizard for a moment - try the full range of animation effects one by one to finish the look on the most suitable popup for your website.
|
25 |
+
* Make [A/B Split Tests](https://supsystic.com/what-is-ab-testing?utm_source=wordpress&utm_medium=optionstests&utm_campaign=popup "A / B Split Test") for choosing the best way of showing your Pop-up. See [Real Time Stats](https://supsystic.com/statistics?utm_source=wordpress&utm_medium=optionsstatistic&utm_campaign=popup "Real Time Popup Stats") for analytics.
|
26 |
+
* There are many different popular popup types, such as Subsсription, video, iFrame, Facebook, PDF, Age Verification, Full Screen, Login and Registration, Google Maps, Notification Bar, etc.
|
27 |
|
28 |
+
Video tutorial to show you how to make a pop-up easily with our plugin.
|
29 |
[youtube http://www.youtube.com/watch?v=-Q9-tWi-lQE]
|
30 |
|
31 |
+
== Screenshots ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
+
1. Subscription templates
|
34 |
+
2. Facebook like popup
|
35 |
+
3. Popup with YouTube video and more
|
36 |
+
4. PopUp Login / Registration Style
|
37 |
+
5. Popup with google map and contact form
|
38 |
+
6. Social Buttons and contact form with popup
|
39 |
+
7. Age verification
|
40 |
+
8. Simple HTML popups
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
== Frequently Asked Questions ==
|
43 |
|
44 |
+
= For fist-time users =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
+
Our plugin is overloaded by different features and abilities, so you can look at [tutorial](https://supsystic.com/documentation/popup-getting-started/) to learn to create PopUps in a couple of minutes. If something is still unclear, [contact us](https://supsystic.com/contact-us/) and we will be glad to help you.
|
47 |
|
48 |
+
= When and Whom to Show Popup =
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
+
You can choose when and whom to show Popup in the Main tab of the plugin’s admin panel. It can be shown when the page loads, when the user clicks on the page or scrolls the window, by click on certain link / button / other element, on the bottom of the page, in case of user inactivity, on exit from your site, etc.
|
51 |
+
You can show Popup for everyone, only for first-time visitors, until user makes an action or you can set the fixed number of times a day (an hour, a week, a month) for showing it. There is also a possibility to hide/show only for mobile devices, for defined countries, user roles, specific post types etc.
|
52 |
|
53 |
+
= When Popup can be Closed =
|
54 |
|
55 |
+
You may choose different variants for closing pop up window: after user close it, by clicking anywhere outside the pop-up, only after action (Subscribe / Share / Like), when the curtain time passed.
|
56 |
|
57 |
+
= How to Create a Facebook Like Popup =
|
58 |
|
59 |
+
In order to add facebook like popup for WordPress with Popup by Supsystic you need to:
|
60 |
+
* Create popup and enable Social Buttons – go to Design tab -> Social -> activate “Enable Social Buttons” checkbox -> activate only Facebook social network.
|
61 |
+
* Enable Facebook button in WordPress Popup plugin
|
62 |
+
* Go to this page – https://developers.facebook.com/docs/plugins/like-button and follow the step-by-step instruction.
|
63 |
+
* Choose URL or Page of a website or Facebook Page you want to use with the like button and put it to the “URL to Like” field.
|
64 |
+
* Adjust settings like the width of the facebook like button, layout – you can choose different styles of button, and action type – like or recommend.
|
65 |
+
* Click the “Get Code” button to generate facebook like button code.
|
66 |
+
* Copy and paste the snippet into the HTML editor of WordPress Popup plugin on CSS/HTML Code tab.
|
67 |
+
* Save the settings and check popup.
|
68 |
|
69 |
+
For more information check an article [Add Facebook Like Popup](https://supsystic.com/documentation/add-facebook-like-button/ "How to Create a Facebook Like Box Popup")
|
70 |
|
71 |
+
= Opening popup with link =
|
72 |
|
73 |
+
With WordPress Popup plugin by Supsystic you can show popup in different ways – when page loads, after user scrolls page, on exit from site, after user comment. Besides you can show popup by clicking on certain link, button, image or even show it by clicking the Menu item. Just add required code and everything is done!
|
74 |
|
75 |
+
For more information see the article [How to open popup with link](https://supsystic.com/documentation/open-popup-click/ "Opening popup with link")
|
76 |
|
77 |
+
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
+
= 1.9.38 / 18.09.2018 =
|
80 |
+
* Additional code improvements
|
81 |
+
* Minor issues fix
|
82 |
+
|
83 |
+
= 1.9.37 / 12.09.2018 =
|
84 |
+
* Minor issues fix
|
85 |
+
* Code review
|
86 |
|
87 |
+
= 1.9.36 / 04.09.2018 =
|
88 |
+
* Mad Mimi Subscription service integration
|
89 |
+
* Minor issues fix
|
90 |
|
91 |
+
= 1.9.35 / 21.08.2018 =
|
92 |
+
* Minor issues fix
|
93 |
+
* Fix issue with saving Mail Settings (SMTP)
|
94 |
|
95 |
+
= 1.9.34 / 08.08.2018 =
|
96 |
+
* ReCaptcha added
|
97 |
+
* Minor issues fix
|
98 |
|
99 |
+
= 1.9.33 / 25.07.2018 =
|
100 |
+
* Fixed export popup. Fixed 48 popup login button
|
101 |
+
* Fix issue with several PopUps on page but with different font settings for each of them
|
102 |
+
* Fix design issues with Facebook Subscribe button
|
103 |
+
* Minor issues fix
|
104 |
|
105 |
+
= 1.9.32 / 10.07.2018 =
|
106 |
+
* Minor issues fix
|
107 |
+
* Code review and improvements
|
108 |
+
* Fixed christmas mood №48 login text
|
109 |
|
110 |
+
= 1.9.31 / 26.06.2018 =
|
111 |
+
* Code review
|
112 |
+
* Minor issues fixed
|
113 |
|
114 |
+
= 1.9.30 / 19.06.2018 =
|
115 |
+
* Fix option URL Match for some redirect functionalities.
|
116 |
+
* Possibility to show PopUp after user will visit several pages on the site.
|
117 |
+
* Minor issues fixed
|
118 |
|
119 |
+
= 1.9.29 / 05.06.2018 =
|
120 |
+
* Possibility to redirect to button link that was clicked after PopUp closed
|
121 |
+
* Code improvements
|
122 |
|
123 |
+
= 1.9.28 / 15.05.2018 =
|
124 |
+
* Possibility to edit standard Registration fields
|
125 |
+
* Fixed plugin activation on multisite
|
126 |
|
127 |
+
= 1.9.27 / 25.04.2018 =
|
128 |
+
* Updated readme and screenshots
|
129 |
+
* Code review and improvements
|
130 |
+
* Minor issues fixed
|
131 |
|
132 |
+
= 1.9.26 / 17.04.2018 =
|
133 |
+
* Fix minor conflict with Contact Forms plugin
|
134 |
+
* Minor issues fixed
|
135 |
|
136 |
+
= 1.9.25 / 11.04.2018 =
|
137 |
+
* JavaScript Core Code improvements - remove deprecated functions
|
138 |
+
* Minor issues fixed
|
139 |
|
140 |
+
= 1.9.24 / 28.03.2018 =
|
141 |
+
* Improvements for Google PageSpeed Insights with images pre-loader
|
142 |
+
* Minor issues fixed
|
143 |
|
144 |
+
= 1.9.23 / 20.03.2018 =
|
145 |
+
* Fix issue with re-adding emails to MailChimp lists error
|
146 |
+
* Minify frontend assets - JS scripts and CSS styles - to make it lighter
|
147 |
+
* Minor issues fixed
|
148 |
|
149 |
+
= 1.9.22 / 01.03.2018 =
|
150 |
+
* Additional core code improvements
|
151 |
+
* Minor issues fixed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
|
153 |
+
= 1.9.21 / 20.02.2018 =
|
154 |
+
* Possibility to deselect all Tabs in Facebook Like Popup
|
155 |
+
* Minor issues fix
|
156 |
|
157 |
= 1.9.20 / 14.02.2018 =
|
158 |
* Minor issues fix
|
159 |
* Code review and improvements
|
160 |
|
161 |
= 1.9.19 / 07.02.2018 =
|
162 |
+
* Fix Facebook Like Pop up positioning
|
163 |
|
164 |
= 1.9.18 / 06.02.2018 =
|
165 |
+
* Adapt Facebook Like Popup to latest Facebook API changes
|
166 |
* Additional core code improvements
|
167 |
* Minor issues fixed
|
168 |
|
169 |
= 1.9.17 / 31.01.2018 =
|
170 |
+
* Possibility to create Primary buttons for actions in Age Verify Popups
|
171 |
* Added full compatibility with older PHP versions (5.2)
|
172 |
* Fix issue with latest MailChimp API (V3) and it's Groups
|
173 |
* Campaign Monitor library fix
|
177 |
|
178 |
= 1.9.15 / 28.12.2017
|
179 |
* Dotmailer subscription system integration
|
180 |
+
* Possibility to display only required data from iFrame Popup using "Display only selector"
|
181 |
* Core code improvement (make it little faster)
|
182 |
|
183 |
= 1.9.14 / 27.11.2017
|
187 |
|
188 |
= 1.9.13 / 21.11.2017
|
189 |
* Minor code issue fix
|
190 |
+
* Disable build-in MailChimp Welcome email functionality - it was disabled by MailChimp for API, and can be enabled in MailChimp account
|
191 |
* Possibility to insert images - from remove URLs too
|
192 |
* Core code improvements
|
193 |
|
194 |
= 1.9.12 / 14.11.2017
|
195 |
* Added options Create subscriber Disabled and Send Confirm email for Newsletters by Supsystic plugin subscriptions
|
196 |
+
* Additional fix for existing YouTube autoplay Popups
|
197 |
* Minor Core code improvements
|
198 |
|
199 |
= 1.9.11 / 23.10.2017
|
207 |
* Minor issues fix
|
208 |
|
209 |
= 1.9.9 / 11.10.2017
|
210 |
+
* Added "Documentation" as additional Post Type for plugin interaction
|
211 |
* Minor issues fix and improvements
|
212 |
|
213 |
= 1.9.8 / 05.10.2017
|
214 |
* Compatibility with MailPoet 3rd version
|
215 |
* Fixed issue when subscribing to already subscribed list with existing email to MailChimp
|
216 |
+
* Fix issue with Videos auto-play when Popup is not visible right after page load (show after click or on exit from site for example)
|
217 |
* Minor Core code improvements
|
218 |
|
219 |
= 1.9.7 / 07.09.2017
|
223 |
|
224 |
= 1.9.6 / 10.08.2017
|
225 |
* Fix issue with Font Stiles and Colors for texts, that have inner html elements
|
226 |
+
* Fix small issue with template "Best Of Collection"
|
227 |
* Minor issues fix and improvements
|
228 |
|
229 |
= 1.9.5 / 22.06.2017
|
237 |
|
238 |
= 1.9.3 / 24.04.2017
|
239 |
* Additional feedback improvements
|
240 |
+
* Fix issue with some non-latin characters in Labels
|
241 |
* Additional core improvements
|
242 |
|
243 |
= 1.9.2 / 19.04.2017
|
244 |
* Added Age Verification templates detailed statistics
|
245 |
+
* Fixed issue with propagandizing cached stats for AB Test Popups
|
246 |
* Fix small issue with ConstantContact subscribe service
|
247 |
* Core code improvements and minor issues fix
|
248 |
|
252 |
* Code improvements
|
253 |
|
254 |
= 1.9.0 / 23.03.2017
|
255 |
+
* Possibility to show Popup right near clicked element (or any other element on page)
|
256 |
* Small code improvements
|
257 |
* Access module improvements
|
258 |
* Compatibility with other WordPress plugins, that modify/remove iCheck library
|
259 |
* Compatibility with plugins/themes/WordPress setup when WP_USE_THEMES is not defined, or defined as "false"
|
260 |
+
|
261 |
+
= 1.8.9 / 14.03.2017
|
262 |
* Updated PHP Mailer library to latest version
|
263 |
+
* Fix issues with some Facebook plugin’s settings output
|
264 |
+
* Possibility to disable Statistics
|
265 |
+
* Fix possible issue with iframe without src in Popup
|
266 |
* Minor fix for SendGrid updated API integration
|
267 |
|
268 |
= 1.8.8 / 21.02.2017
|
271 |
|
272 |
= 1.8.7 / 16.02.2017
|
273 |
* WooCommerce categories added to Categories select list
|
274 |
+
* Facebook Like Pop up fix - to make it work according latest Facebook changes
|
275 |
* Fix HTTP images protocol for christmas snow effect
|
276 |
+
* Possibility to select week days when you need to show Popups
|
277 |
* SMTP servers integration
|
278 |
* Send Mail service integration
|
279 |
+
* Possibility to just close window if email already exists during Registration process
|
280 |
* Fix possible conflict if someone add html tag with name "ajaxurl"
|
281 |
* Setting images for backgrounds only with selected in WordPress library size
|
282 |
* Possibility to show Close button for Close mode - "Only after action (Subscribe / Share / Like)"
|
283 |
|
284 |
= 1.8.6 / 26.01.2017
|
285 |
+
* Possibility to manually create Passwords on Frontend Registration
|
286 |
+
* Additional re-position and resize Popup after all images inside was loaded
|
287 |
+
* Do not use Pop up close and subscribe errors actions - when calculating conversions
|
288 |
* Blacklist error message editing
|
289 |
+
* Make correct work Layered Popup with Click outside option
|
290 |
+
* Fix issue with displaying Popup on Posts page listing
|
291 |
|
292 |
= 1.8.5 / 12.01.2017
|
293 |
* Fix MailChimp Groups List sending value in email
|
294 |
* Fixed old code for php 7 compatibility
|
295 |
* SendGrid API update
|
296 |
+
* Added Template "Lavender Mood"
|
297 |
+
* Added Template "Winter Subscribe"
|
298 |
+
* Added Template "Get Discount"
|
299 |
+
* Added Template "Pretty"
|
300 |
* Minor code review
|
301 |
|
302 |
= 1.8.4 / 19.12.2016 =
|
303 |
+
* Redesign Theme "New York"
|
304 |
+
* Redesign Theme "Video List"
|
305 |
+
* Added template "Exclusive Subscription"
|
306 |
* Added possibility to add emails / email templates into Blacklist - PRO
|
307 |
* Admin area design minor improvements
|
308 |
* Code optimizations
|
311 |
= 1.8.3 / 07.12.2016 =
|
312 |
* Background Overlay settings added: Color, Image and Snow
|
313 |
* Paralax Page Builder compatibility
|
314 |
+
* Fix template bugs for additional subscribe elements
|
315 |
+
* Added template "Winter Sale"
|
316 |
+
* Added template "Christmas Tree"
|
317 |
+
* Added template "Christmas Candies"
|
318 |
+
* Added template "Xmas Discount"
|
319 |
+
* Forgot Password link for Login functionality added
|
320 |
|
321 |
= 1.8.2 / 29.11.2016 =
|
322 |
+
* Added [Christmas templates pack](https://supsystic.com/blog/christmas-popup-templates-pack "Christmas templates")
|
323 |
* Minor issues fix
|
324 |
|
325 |
= 1.8.1 / 23.11.2016 =
|
326 |
* Added possibility to use HTML tags in Subscribe / Registration fields Labels
|
327 |
+
* Possibility to show Pop-Up - in Admin Area
|
328 |
* Mobile detection library update - new devices detection
|
329 |
* SG Autorepondeur API updated
|
330 |
* Minor admin area design improvements
|
332 |
* Language pack updated
|
333 |
|
334 |
= 1.8.0 / 02.11.2016 =
|
335 |
+
* New Themes - List Building Neo, Bright Girl and Sign Up Classic!
|
336 |
* Update mobile detection library
|
337 |
+
* Possibility to integrate plugin with Google Analytic - PRO
|
338 |
+
* Added new Statistic Event Types - Close and Subscribe Failure
|
339 |
* 4Dem.it Subscription service integration - PRO
|
340 |
* Your Mailing List Provider (Ymlp) Subscription service integration - PRO
|
341 |
* Vtiger CRM Subscription service integration - PRO
|
348 |
* Fix minor HTML coding issues in admin area (correct build-in tables formatting)
|
349 |
* Improve option "Disable window scroll"
|
350 |
* Additional compatibility check for Campaign Monitor library in other plugins installed
|
351 |
+
* Added users inactivity logout Pop-up - PRO
|
352 |
+
* Admin area listing design improvements
|
353 |
* Minor issues fix and improvements
|
354 |
|
355 |
= 1.7.10 / 21.09.2016 =
|
356 |
* Integration with [Digital Publication plugin](https://wordpress.org/plugins/digital-publications-by-supsystic/ "Digital Publication WordPress Plugin")
|
357 |
* Integration with [Newsletter by Supsystic plugin] (https://wordpress.org/plugins/newsletter-by-supsystic/ "Newsletter by Supsystic WordPress plugin")
|
358 |
+
* Re-posite popup after Subscribe form was successfully submitted
|
359 |
* Minor bugs fixed
|
360 |
|
361 |
= 1.7.9 / 07.09.2016 =
|
377 |
|
378 |
= 1.7.6 / 21.07.2016 =
|
379 |
* Fix issue with conflict of Font and Text Color styles and styles of users custom themes (theme styles often override our styles, now it will not occur anymore)
|
380 |
+
* Fixed issue for showing Popup on Homepage with posts listing and multiple pages of listings
|
381 |
* Integration with Contact Form plugin (step 1 - correct show shortcodes)
|
382 |
* Options with Disabling CDN usage description link added
|
383 |
+
* Correct update iFrames after Pop-up was displayed
|
384 |
+
* Fixed issue with multiple shortcodes compilation from Popups text data
|
385 |
+
* Fixed issue with multiple "onclick" binding attempts
|
386 |
* Added Spanish (Venezuela), Dutch languages and updated Spanish translation
|
387 |
* Minor spelling issues fix
|
388 |
|
389 |
= 1.7.5 / 21.06.2016 =
|
390 |
* Small fixes of welcome page and step-by step tutorial
|
391 |
* Fix small issue with Facebook Subscription
|
392 |
+
* Possibility to export all subscribers from all Popups - in one click from Settings page
|
393 |
+
* Possibility to redirect to link URL after subscribe if On Click link was used to show Pop up
|
394 |
* Fix issue with detecting required user roles for Show / Hide for user role functionality for cases when user have several roles
|
395 |
|
396 |
= 1.7.4 / 07.06.2016 =
|
397 |
+
* Possibility to disable CDN server usage - and move all assets to own website
|
398 |
+
* Fix issue with showing Pop-up on main Home Page if Home Page - is from WooCommerce plugin
|
399 |
* Code review and re-factor
|
400 |
* Minor improvements
|
401 |
|
402 |
= 1.7.2 / 17.05.2016 =
|
403 |
+
* Possibility to enable Label at the top of the Facebook Widget Popup
|
404 |
+
* Option to show Pop-up if AdBlock is enabled - PRO
|
405 |
* Possibility to send any user data - to email with user confirm link, and in email to new user subscribers
|
406 |
* Added New Subscribers notification email Subject option
|
407 |
+
* Show / Hide for selected User Roles option - PRO
|
408 |
+
* Small fixes and improvements for Themes. #170 add 0.2h
|
409 |
+
* Possibility to select categories for showing
|
410 |
+
* Possibility to insert shortcodes in Subscribe fields values
|
411 |
+
* Possibility to insert scripts - inside content (in text editors)
|
412 |
+
* Show Popup "On Click" - add additional check - after all scripts, that was triggered, will done their work - check it one more time - to make sure we didn't miss anyone
|
413 |
* Fixed conflicts with WordPress plugins, that make URLs relative
|
414 |
* Fixed conflicts with other themes and plugins, that using zoom jQuery method with same method name
|
415 |
* Code review and improvements
|
416 |
|
417 |
= 1.7.1 / 28.04.2016 =
|
418 |
+
* New Template added - "Video List Flat"
|
419 |
* MailChimp API key - ignore space symbols in beginning or ending of it in case they was inserted accidentally
|
420 |
+
* Fix issue with Social Share by Supsystic project sharing re-selecting from Pop-up
|
421 |
* Updated Italian translation
|
422 |
* Additional TinyMCE check in admin area - to make sure we will not call errors in case it's absent on user WP configuration
|
423 |
* Sending mail functionality improvements
|
426 |
* Added new subscribe form field type - MailChimp Groups List
|
427 |
* Minor admin area design improvements
|
428 |
* InfusionSoft - set all subscribers Marketable after subscribe
|
429 |
+
* Background fix for PDF template
|
430 |
+
* Age Verification - added statistics for verification actions too
|
431 |
|
432 |
= 1.6.9 / 13.04.2016 =
|
433 |
+
* Hot fix for WordPress 4.5 and On Click pop-up
|
434 |
+
* Fix On Click Popup show for latest jQuery library
|
435 |
|
436 |
= 1.6.8 / 12.04.2016 =
|
437 |
* Aweber - change subscribe URL to SSL protocol
|
438 |
+
* "Pink" Template mobile version fix
|
439 |
* Small subscribe messages success conflict fix
|
440 |
* Minor issue fixes and code improvements
|
441 |
|
443 |
* Fix Facebook Widget - Share functionality: adapt it to new Facebook API usage
|
444 |
|
445 |
= 1.6.6 / 06.04.2016 =
|
446 |
+
* Hotfix for page cache check (hot fix version 1.6.5)
|
447 |
* Small spelling issues fix
|
448 |
|
449 |
= 1.6.5 / 05.04.2016 =
|
450 |
+
* Possibility to use Subscribe, Login and Registration forms - in one Pop up, at one and same time - all 3 forms together
|
451 |
+
* Small fix for "Photodoto" Template
|
452 |
+
* Added option "Redirect after close" - you can now redirect your users after they will close Popup
|
453 |
* Emma email subscription service integration - PRO
|
454 |
* Correct subscriber, registration and login form work with enable cache plugins (W3 Total Cache or Super Cache)
|
455 |
* Don't send standard WordPress new users notifications if all messages fields was cleared by user
|
461 |
* InfusionSoft - Tags added
|
462 |
* Fix issue with redirect after authorization on InfusionSoft system
|
463 |
* Correct Whom to show -> Number times in a day option in admin are for RTL languages
|
464 |
+
* Fix issue with new Registered user through admin notifications
|
465 |
* iContact - added "prefix" additional default field support
|
466 |
* BenchmarkEmail, MailRelay, SendGrid - small fix for encoding / decoding internal API data
|
467 |
+
* Small fix for "List Building Layered" template
|
468 |
|
469 |
= 1.6.3 / 22.03.2016 =
|
470 |
+
* Fix issue with showing Popup on WooCommerce "Shop" page only
|
471 |
* Added another supported video hosting service
|
472 |
+
* Small fix for build-in content popup - do not load them in standard load query (they will be loaded from shortcodes)
|
473 |
* Minor debug issues fix
|
474 |
|
475 |
= 1.6.2 / 17.03.2016 =
|
476 |
* SGautorepondeur - small issue with server response fix
|
477 |
* Subscribe additional fields - selectbox field type - fix option adding process
|
478 |
+
* Added option to show Pop-up specific times in a hour, day, week or month - for each visitor
|
479 |
+
* Small fix for PDF template
|
480 |
+
* Make correct open/close Video Pop-up with self-hosted videos
|
481 |
|
482 |
= 1.6.1 / 14.03.2016 =
|
483 |
* Full RTL (Right-to-Left) languages support
|
484 |
* Possibility to disable HTML emails content type - for servers, that doesn't allow to send such emails
|
485 |
+
* Fix issue with iFrames reloading after Popup was shown (PDF, iFrame PopUp types)
|
486 |
* ConvertKit subscription method integration - PRO
|
487 |
+
* Login - login by Username by default
|
488 |
* Disable block IP for multiple subscriptions by default
|
489 |
+
* Improve On Exit initialization (to avoid conflict with some modificated jquery libraries)
|
490 |
* Fixed minor conflicts in admin area with other javascript codes of other themes and plugins
|
491 |
+
* Added possibility to use Registration and Login form - in one Popup at one and same time
|
492 |
* Count time from first site load option added
|
493 |
* jQuery UI admin area CSS - small compatibility with other plugins fix
|
494 |
* Added possibility to add fields with type = email
|
498 |
= 1.6.0 / 02.03.2016 =
|
499 |
* Remove unused error message parts from MailChimp errors
|
500 |
* SalesForce - Web-to-Lead integration - PRO
|
501 |
+
* Close video after Popup was closed even if template was not with video type
|
502 |
* Constant Contact - add contact even if it exist in some other subscription lists
|
503 |
* InfusionSoft subscription method added - PRO
|
504 |
* Additional compatibility with Google Maps Easy plugin https://wordpress.org/plugins/google-maps-easy/
|
505 |
* Language files update and minor spelling issues fix
|
506 |
|
507 |
= 1.5.9 / 25.02.2016 =
|
508 |
+
* Quick fix for Date Picker library in admin area -> Edit screen
|
509 |
* Small spelling issue fix in admin area
|
510 |
* MailChimp - replace tags into variables names if error from MailChimp server about variable is returned
|
511 |
|
512 |
= 1.5.8 / 23.02.2016 =
|
513 |
+
* Jetpack subscription engine added - now you can subscribe to Jetpack!
|
514 |
+
* Added Date display range
|
515 |
* Count already subscribed user as subscriber on client side if email already exists and "Redirect if email already exists" option is enabled
|
516 |
* iContact Subscribe method integration
|
517 |
* GetResponse Subscribe method improvements
|
518 |
* Always send form on Enter press in Subscribe form
|
519 |
* Fix issue with HTTPS loading fonts in Fonts PRO module
|
520 |
* GetResponse - added new field - "Cycle Day"
|
521 |
+
* Don't pass unused data - to fronted JavaScript: make code lighter
|
522 |
* MailChimp - fix issue with limit of Subscribe lists, shown in admin area (there was standard limit in 25 lists)
|
523 |
* Core code improve (minor "strict standards" php notice fix)
|
524 |
+
* Facebook Subscribe - fix result messages (or errors) - now they will be visible in Pop-up itself
|
525 |
+
* When to close -> Only after action -> Added possibility to select time after action that should pass before close
|
526 |
* Update Spanish translation
|
527 |
* Code review
|
528 |
|
529 |
= 1.5.7 / 16.02.2016 =
|
530 |
+
* Added Search Engines and Social Media sites detection - to show/hide Pop-up only for specific Search Engines and Social Media sites
|
531 |
+
* Possibility to insert Popup into site content - PRO
|
532 |
* Added names for Backgrounds - now they will show for what exactly each other is corresponding for
|
533 |
* MailRelay Subscribe method fix
|
534 |
* Spelling issues fix
|
538 |
= 1.5.6 / 02.02.2016 =
|
539 |
* Added subscribe from URL variable to subscribers emails - [subscribe_url]
|
540 |
* If user is already subscribed to MailChimp - count this as done subscribe action, and not error
|
541 |
+
* "Email exists" error message option in admin area
|
542 |
+
* Reduce user browser memory usage to work correctly - make it faster and lighter!
|
543 |
* Functionality to show only for first time visitors popup even if they are shown "On Click"
|
544 |
+
* Fix issue with opening Media Library on Enter key press in admin area edit screen
|
545 |
+
* Small fix for Pop-up Template
|
546 |
+
* "Add Popup" button - in admin top bar: create your pop up more faster!
|
547 |
|
548 |
= 1.5.5 / 26.01.2016 =
|
549 |
* MailChimp Groups functionality added
|
550 |
+
* Do not send CSS and HTML data when editing plugin if they were not changed
|
551 |
+
* Possibility to force show Popup right after page loaded using hash parameters
|
552 |
+
* Minor fix for Business Template
|
553 |
* Improve IP detection algorithm
|
554 |
+
* Small correct for TinyMce buttons colors on Edit screen
|
555 |
+
* Minor fixes for templates Video Classy, Layered Popup, Ready and Business
|
556 |
+
* Added option "Disable window scroll" to disable browser window scrolling while Pop-up is opened
|
557 |
+
* Show for cases when user selected invalid image as of the Backgrounds
|
558 |
|
559 |
= 1.5.4 / 13.01.2016 =
|
560 |
* Possibility to create WordPress Subscribers with different then WordPress subscribers mail engine
|
561 |
* Added option to load all plugin assets - in site footer - to increase page speed load
|
562 |
* Correct detecting mobile device with On Exit functionality
|
563 |
+
* Possibility to add attachments to email from plugin
|
564 |
+
* Fix positioning for Responsive mode with "Full resize" responsive mode
|
565 |
* Update English and Russian languages
|
566 |
* Minor translation issues fix
|
567 |
|
568 |
= 1.5.3 / 21.12.2015 =
|
569 |
+
* Fix possibility to show Pop-up on menu click for WordPress 4.4 (after field Title for menu items was removed)
|
570 |
* Increase popup z-index - to make sure that it is located above other elements
|
571 |
* New pretty loader
|
572 |
* Correct Overview page for case if mysql_get_server_info() function are missing
|
573 |
* Video popup - added self-hosted video support
|
574 |
+
* Additional Responsive mode - "Width only", with possibility to select most suitable mode in settings!
|
575 |
+
* Added "Ignore related videos" option for Video type
|
576 |
* Plugin server-side core improvements
|
577 |
+
* On Exit Popup - make Exit detection more correct
|
578 |
* Checkbox additional fields type improvements
|
579 |
* Minor issue fix in Mailrelay modules
|
580 |
|
581 |
= 1.5.2 / 14.12.2015 =
|
582 |
+
* Change Template functionality - don't flush Main settings after Template change
|
583 |
+
* Correct shortcodes display in admin area on small screen devices
|
584 |
* Benchmark email service integration - PRO
|
585 |
* Added additional subscribe fields - to CSV Subscribers export file
|
586 |
* Subscribe checkbox additional field display improvements
|
587 |
+
* Disable autosave on edit screen option
|
588 |
+
* Fix for "On Link Follow" mode
|
589 |
+
* Improve "START" template
|
590 |
|
591 |
= 1.5.1 / 08.12.2015 =
|
592 |
* Required fields Subscribe validation for Safary browser on client side
|
593 |
+
* Templates "Simple iFrame", "Simple HTML", "HTML 2 Columns", "PDF Popup" - minor issues fixed
|
594 |
* Step by step tour for first time users
|
595 |
+
* Added option for Time Delay for Pop-up Click on certain link and On Link Follow settings
|
596 |
* Fixed build-in Contact Form Support email address
|
597 |
* Minor AB testing issue fix (when have many original popup with tested popup)
|
598 |
* Mailrelay - minor issue fix
|
599 |
|
600 |
= 1.5.0 / 03.12.2015 =
|
601 |
+
* Added "Time display settings" to add possibility show Pop-up at specific time range
|
602 |
+
* Minor issue fixed for lists bullets
|
603 |
+
* Subscription additional fields - Checkbox field type added
|
604 |
+
* Notification Bar type added
|
605 |
+
* Login / Registration types added
|
606 |
+
* A lot of new templates
|
607 |
|
608 |
= 1.4.6 / 17.11.2015 =
|
609 |
* Small code improvements
|
610 |
+
* "Map style" template small fix
|
611 |
* Minor spelling issues fix
|
612 |
* Small fix for "List Building Layered" PRO template
|
613 |
* Added Spanish (Colombia) language
|
614 |
|
615 |
= 1.4.5 / 10.11.2015 =
|
616 |
* Fixed issue with PRO for multi-sites
|
617 |
+
* Changed sort orders of Templates in admin area
|
618 |
* PRO - Updated Facebook API usage
|
619 |
* Minor core code improvements
|
620 |
|
626 |
= 1.4.3 / 03.11.2015 =
|
627 |
* New Animation library added - more animations with better performance!
|
628 |
* Small issue fix with WordPress Subscribers export
|
629 |
+
* Small admin area user friendly improvements
|
630 |
* Corrections for responsiveness - now will correct display on all devices
|
631 |
* Added Polish language
|
632 |
+
* Small fix for Calm template
|
633 |
+
* AB Testing - added possibility to select Main (Display) settings for tested Popup
|
634 |
* MailRelay module - minor code improvements
|
635 |
* ConstantContact - added compatibility with other plugins, that can use same ConstantContact API SDK
|
636 |
+
* Small fix for Video Classy template
|
637 |
|
638 |
= 1.4.2 / 27.10.2015 =
|
639 |
+
* Minor issues fix for "List Building", "Bonus" and "Smart" templates
|
640 |
* Remove admin tooltips animation - just to check now it will be look like
|
641 |
* Small fixes for preview templates Pink and Discount
|
642 |
* Export subscribers to WordPress users list as CSV file (all subscribers - confirmed and unconfirmed too)
|
644 |
* Make custom selects in admin area - responsive
|
645 |
* Fix List Green and Green Dots bullets
|
646 |
* Change version for js and css files each time new version is release - to avoid using browser cache
|
647 |
+
* Small fixes for Business and Map style templates
|
648 |
|
649 |
= 1.4.1 / 21.10.2015 =
|
650 |
* Added HTML5 Subscribe fields validation on client side - fast and light!
|
651 |
+
* Small fix to make proper work responsiveness + animation feature when need to reduce size after Pop-up will be shown
|
652 |
* Fix issue for compatibility with styles output on some mobile devices
|
653 |
* Admin WordPress more pretty menu icon
|
654 |
* Additional clarification link to documentation about MailChimp usage
|
655 |
* Improve usability - move to Design tab after template was changed
|
656 |
* Backgrounds images preview in admin area - max width to 300px
|
657 |
* Admin area -> Make Background opacity slider - smaller
|
658 |
+
* Small fix for Find Us and Map style templates
|
659 |
* Admin area - fixes for small devices
|
660 |
|
661 |
= 1.4.0 / 13.10.2015 =
|
662 |
* Compatibility with Minification functionality (provided by other plugins, for example - W3 Total Cache)
|
663 |
+
* Make data for frontend - lighter by removing unused on frontend variables
|
664 |
* Small spelling issues fix
|
665 |
* Fixed optin template Map style
|
666 |
* Fix issue with displaying popup and Google Maps in it (when Maps didn't load it's scripts correctly on some themes)
|
667 |
+
* Admin lead generator interface design small improvements - make it more user friendly
|
668 |
* More interactions with our users - just trying improve software for your needs!
|
669 |
* Small fix for SendGrid admin js issue
|
670 |
|
672 |
* Fix small issue for servers, that make auto translate "&" sign to "&" in http_build_query() function
|
673 |
* Fixed small issue with MailRelay and SendGrid modules (encryption/decryption saved tokens length)
|
674 |
* Fix issue with pre-load images algorithm: for cases when type background selected as Image, but actually no image was selected
|
675 |
+
* "Link Follow" show Popup options - PRO
|
676 |
|
677 |
= 1.3.8 / 28.09.2015 =
|
678 |
* Notification about new subscribers for all Subscription services functionality added
|
696 |
|
697 |
= 1.3.5 / 17.09.2015 =
|
698 |
* Welcome page added to plugin admin area
|
699 |
+
* Installation and Activation process included
|
700 |
* Active Campaign Subscription service integration - PRO
|
701 |
* Plugin core code improvements
|
702 |
|
703 |
= 1.3.4 / 12.09.2015 =
|
704 |
* Added compatibility with WordPress 3.4.2
|
705 |
+
* Fixed issue with "displacements" of content in templates
|
706 |
* Code review and core code improvements
|
707 |
* Minor issues fix
|
708 |
|
709 |
= 1.3.3 / 08.09.2015 =
|
710 |
+
* More flexible way to pre-load images
|
711 |
* Make Admin area preview load faster
|
712 |
* Additional integrations with Google Maps - https://wordpress.org/plugins/google-maps-easy/
|
713 |
* Small code review and improvements
|
714 |
|
715 |
= 1.3.2 / 01.09.2015 =
|
716 |
* GetResponse Subscribe integration - PRO
|
717 |
+
* Added sort order to base Templates
|
718 |
* Minor issues fix
|
719 |
* Small code review and improvements
|
720 |
|
721 |
= 1.3.1 / 25.08.2015 =
|
722 |
* Additional Subscribe fields - new field type - Hidden
|
723 |
* Added Spanish (MEXICO) language
|
724 |
+
* Simple images preload - show images without delay
|
725 |
* Compatibility for themes where jquery library added more then 1 time
|
726 |
|
727 |
= 1.3.0 / 13.08.2015 =
|
728 |
* Added 4 new templates with Google Maps and Contact Form!
|
729 |
* New text list bullet type
|
730 |
* Added fix for servers without ctype_alpha standard PHP function
|
731 |
+
* Admin Popup preview - load all frontend styles and scripts - to make it's view more like on frontend
|
732 |
* Fix minor issues in templates
|
733 |
|
734 |
= 1.2.9 / 04.08.2015 =
|
740 |
= 1.2.8 / 31.07.2015 =
|
741 |
* Added new template with map
|
742 |
* Fix issue for servers, that doesn't have "hash" php function
|
743 |
+
* Fix problem with viewing lists of posts/pages where need to show/hide Pop-up
|
744 |
+
* Possibility to edit Name after creation
|
745 |
* Redirect link option for case if email is already subscribed
|
746 |
|
747 |
= 1.2.7 / 24.07.2015 =
|
750 |
* Layered style - fix displaying saved setting in admin area
|
751 |
* Minor admin area design improvements
|
752 |
* Integration with Social Share Buttons plugin - https://wordpress.org/plugins/social-share-buttons-by-supsystic/
|
753 |
+
* Additional improvements for "On Click" show - now link can contain shortcode in any href attr place
|
754 |
* Constant Contact Subscribe Engine integration - PRO
|
755 |
* Campaign Monitor Subscribe Engine integration - PRO
|
756 |
* Vertical Response Subscribe Engine integration - PRO
|
758 |
* SendGrid Subscribe Engine integration - PRO
|
759 |
* SG Autorepondeur Engine integration - PRO
|
760 |
* Added "Show Only" option in addition for options Hide for Devices, Hide for Post Types, Hide for for IP, Hide for Countries and Hide for Languages
|
761 |
+
* Functionality to show - on Menu Item click
|
762 |
|
763 |
= 1.2.6 / 16.07.2015 =
|
764 |
* Added new template "Discount"
|
776 |
* Reduce plugin size - move static images to our server
|
777 |
|
778 |
= 1.2.5 / 01.07.2015 =
|
779 |
+
* Added new template - "Business"
|
780 |
* Minor PHP warnings fix
|
781 |
* Adding PRO options to change font color in popup fields
|
782 |
* Minor issues fix
|
795 |
* Responsive Overview admin page
|
796 |
* Admin area small design improvements
|
797 |
* Remove some old code - to make plugin lighter
|
798 |
+
* Fix color for Success Subscribe message for all pop-up
|
799 |
|
800 |
= 1.2.2 / 04.06.2015 =
|
801 |
+
* Possibility to insert "embed" shortcodes to text fields - to show video in any place
|
802 |
* Small fix for "Best Of Collection" template
|
803 |
* Minor issues fix and code improvements
|
804 |
|
805 |
= 1.2.1 / 29.05.2015 =
|
806 |
* Added new template "Best Of Collection"
|
807 |
+
* START template additional subscribe fields integration
|
808 |
+
* Fixed close button position in Exclusive template and remove errorMsg border
|
809 |
* Minor issues fixes and improvements
|
810 |
|
811 |
= 1.2.0 / 19.05.2015 =
|
812 |
+
* Fixed bug with Mozilla browser in Exclusive template
|
813 |
+
* Added Russian language and fixed some spelling issues
|
814 |
+
* Subscribe custom fields builder - PRO
|
815 |
+
* Small fix for Classy template
|
816 |
+
* Language translation files update
|
817 |
+
* Aweber AD Tracking feature added
|
818 |
+
* Some unused files remove
|
819 |
+
* Small re-design on Layered style feature
|
820 |
+
* Admin area design improvements
|
821 |
+
* Correct message for subscribe success when MailPoet is used as Subscribe engine
|
822 |
|
823 |
= 1.1.9 / 07.05.2015 =
|
824 |
+
* Code review
|
825 |
+
* Minor issues fix
|
826 |
|
827 |
= 1.1.8 / 30.04.2015 =
|
828 |
+
* Added translation
|
829 |
+
* Fix for cookie days set - for case when it is set to 0
|
830 |
+
* Added new global option - "Disable blocking Subscription from same IP"
|
831 |
+
* Close after outside click option
|
832 |
+
* Small main settings tab tooltips fix
|
833 |
+
* Small fix for "Sign Up" template
|
834 |
+
* Check your server email functionality option
|
835 |
+
* Fixed minor bugs
|
836 |
|
837 |
= 1.1.7 / 23.04.2015 =
|
838 |
+
* Admin area User Interface improvements - make it more comfortable and attractive for our Users
|
839 |
+
* Fix conflict with some WordPress plugins in our Code editor tool (conflict with "codemirror" library)
|
840 |
+
* Hide popup for Logged-in option
|
841 |
+
* Option to set period of time for hide for already viewed users, or already made an action
|
842 |
|
843 |
= 1.1.6 / 14.04.2015 =
|
844 |
* Correction for cookie lifetime in recording user actions
|
845 |
+
* Fix template width for template "Informed"
|
846 |
+
* Some spelling issues fix
|
847 |
+
* Fix charset for admin Pop-up preview
|
848 |
+
* Minor admin design issues fix
|
849 |
+
* Small fix for "Informed" template
|
850 |
* Popup MailChimp - disable double opt-in option
|
851 |
+
* Improve design of admin area -> Edit PopUp -> Subscribe section
|
852 |
+
* Social links - additional fix to avoid styles conflict
|
853 |
+
* Minor issues code fix
|
854 |
|
855 |
= 1.1.5 / 07.04.2015 =
|
856 |
+
* Aweber - Added option to redirect on Subscribe success
|
857 |
+
* Option - to Show on required % scroll
|
858 |
* Shortcode popup output in admin area - make it more comfortable to copy and move to content
|
859 |
+
* Fixed conflict with Twig autoloaded re-defining in other plugins or themes
|
860 |
+
* Facebook Pop-up - correct language detection
|
861 |
+
* Correct displaying usual embed iframes with Google Maps
|
862 |
+
* PRO - added options: Close only after action, after time passed - https://supsystic.com/plugins/popup-plugin/
|
863 |
+
* PRO - added options: Show at the bottom of the page, after Inactivity, after User Comment option, after Purchasing (Checkout) - https://supsystic.com/plugins/popup-plugin/
|
864 |
+
* PRO - Possibility to subscribe with Facebook - https://supsystic.com/plugins/popup-plugin/
|
865 |
+
* PRO - Possibility to set user role for plugin usage (not just admin) - https://supsystic.com/plugins/popup-plugin/
|
866 |
+
* Some minor spelling issues fix
|
867 |
+
* Core code improvements
|
868 |
|
869 |
= 1.1.4 / 01.04.2015 =
|
870 |
* MailPoet popup Subscribe integration
|
871 |
* Possibility to select Home page of whole site - to show or not popup
|
872 |
+
* New Subscriber email edit options
|
873 |
* Option to edit popup From field in emails to subscriber
|
874 |
+
* Small issue fix - for servers with old version of pcre package (preg_match_all php warning)
|
875 |
+
* Added German translation
|
876 |
+
* PRO - Possibility to set font family
|
877 |
+
* Correction for Video Popup - correct stop/play video after close/open Pop-up
|
878 |
+
* Minor issue with empty statistics fix
|
879 |
|
880 |
= 1.1.3 / 24.03.2015 =
|
881 |
+
* Play/Stop Youtube video on client side - make it correct work for hidden elements
|
882 |
+
* Fix conflict with other plugins that use modified CodeMirror library
|
883 |
+
* Added French translation
|
884 |
+
* Added Spanish translation
|
885 |
+
* Correction for loading translation files for plugin - make it fully multi language
|
886 |
+
* Overview - FAQ info changed
|
887 |
|
888 |
= 1.1.2 / 20.03.2015 =
|
889 |
+
* Added option - "Create Subscriber without confirmation"
|
890 |
+
* Special page - to show when confirm subscription for WordPress
|
891 |
+
* Small Fix for Template ID 7 - inputs text color
|
892 |
+
* Compile shortcodes - even in preview in admin area edit screen
|
893 |
+
* Some spelling issues fix
|
894 |
+
* Overview tab added
|
895 |
+
* Statistics date format for Hour change
|
896 |
+
* Correct condition - for showing / hiding for specific post / page - don't show on posts listing, only on single post / page
|
897 |
|
898 |
= 1.1.1 / 10.03.2015 =
|
899 |
* Subscription - possibility to modify subscribe messages - browser notifications, email subject and content
|
901 |
* Statistics - show data if week / month is selected with date range that is in current week / month
|
902 |
* Mailchimp popup API class - minor correct for DEBUG mode
|
903 |
* Correct popup saving "&" sign - in text fields
|
904 |
+
* Fix animations tab in admin area
|
905 |
+
* Correct animation for Facebook Like Popup - animate it only after whole content will be loaded from Facebook
|
906 |
* Added popup link to documentation about usage code - HTML and CSS - editor
|
907 |
+
* Correct process shortcode from any place (not only from post/page content) - sidebars, external themes/plugins, etc.
|
908 |
* Minor fixes for base templates
|
909 |
* PRO - On Exit functionality integration - https://supsystic.com/plugins/popup-plugin/
|
910 |
* Fix issue - with multiple time showing when "On Click" mode is enabled and animation is added
|
911 |
+
* Added usual posts to list where show or not
|
912 |
|
913 |
= 1.1.0 / 05.03.2015 =
|
914 |
+
* Added 5 new templates
|
915 |
+
* Statistics - added table view in admin area
|
916 |
+
* Statistics - added CSV export in admin area
|
917 |
+
* Statistics - added date range selection in admin area
|
918 |
+
* Statistics - added Unique views parameters and Conversion calculation
|
919 |
* Possibility to disable popup (not delete, but just disable)
|
920 |
+
* Clone Popup functionality added
|
921 |
* Admin UI style improvements - make it more pretty and comfortable for usage
|
922 |
* After change measure type for With - from px to % - make sure that width value - is not more then 100
|
923 |
+
* Additional core improvements
|
924 |
+
* AB testing - test list modification according to main popup list
|
925 |
+
* Pop-up Installer improve
|
926 |
|
927 |
= 1.0.9 / 24.02.2015 =
|
928 |
* Allow to assign new subscribers - special roles
|
929 |
+
* Option to disable Popup for: Mobile, Tablet or Desktop PC
|
930 |
* Additional fix for mobile devices
|
931 |
+
* Small fix for latest added new templates
|
932 |
+
* Main edit tabs sticky functionality - make it work with some standard notifications
|
933 |
+
* Show Popup label always on top of edit tabs on edit screen - more user-friendly
|
934 |
+
* Option to show Pop-up - after scroll window - right after scroll or with delay
|
935 |
+
* Layered integration - https://supsystic.com/plugins/popup-plugin/
|
936 |
+
* Additional modification for "Click On" show mode - to make sure it work with more content editor systems
|
937 |
+
* A/B testing - tests should stay tests even after whole design change - fixed - https://supsystic.com/plugins/popup-plugin/
|
938 |
+
* Admin list table - do not stick header line (call too much problems and don't need this)
|
939 |
+
* Correct show on mobile devices - every size, every type
|
940 |
+
* Fix sticky edit tabs scroll position
|
941 |
|
942 |
= 1.0.8 =
|
943 |
+
* Added Statistics - now you can view charts in admin area
|
944 |
* Video popup - Hide Controls option
|
945 |
+
* New Templates - 4 additional templates
|
946 |
* Fix php notice for enabled debug mode for some php versions on activation
|
947 |
+
* Added localization .pot file - in plugin folder lang/pps_lng.po
|
948 |
+
* Change Aweber list name - "Unique List ID" field label - to make it more clearer
|
949 |
+
* Fix issue for "Click on certain link / button / other element" - when there are more than one Popup in post/page inserted
|
950 |
+
* Make Popup admin tabs edit - responsive (usability)
|
951 |
* Make popup Animation selection - more obviously
|
952 |
+
* Admin system messages - make it design according to main admin design
|
953 |
+
* Animation duration - now in milliseconds (instead of seconds)
|
954 |
+
* Helper screen - for option
|
955 |
+
* PRO version integration
|
956 |
+
* Core code API improvements
|
957 |
+
* Minor issues fix
|
958 |
|
959 |
= 1.0.7 =
|
960 |
+
* Accept shortcodes in text areas, footer note and even label
|
961 |
+
* Possibility to show Popup on Click on any element of the page
|
962 |
* Popup Fix for case when no template was selected during PopUp creation
|
963 |
+
* Additional fixes for DEBUG mode
|
964 |
+
* Minor issue fixes on core code
|
965 |
|
966 |
= 1.0.6 =
|
967 |
* MailChimp integration with popup
|
968 |
* Video popup - Autoplay option added
|
969 |
+
* Correct position set for Facebook Like Popup - depend position on widget size after it will be loaded
|
970 |
+
* Re-calculate position for each Pop up - after window was resized
|
971 |
+
* Fix issue with Facebook Like Popup array options
|
972 |
* Disable popup clicking and submitting forms inside preview iFrame in admin area
|
973 |
* Fix images load as background - added load WordPress media gallery
|
974 |
+
* List Building and Video List templates - fix subscribe Submit button name option
|
975 |
+
* Fastest and Easiest template - fix subscribe enable/disabler name option
|
976 |
* Fix Popup for smaller window size - responsive from now!
|
977 |
+
* Correct "none" animation selection
|
978 |
+
* Rename admin area menu items - make it more intuitive and user-friendly
|
979 |
+
* Fix preview iFrame issue in admin area - when for some cases scripts with "ppsHidePreviewUpdating" was not loaded when iFrame was already loaded
|
980 |
+
* Tooltip functionality in admin area optimization
|
981 |
+
* Some wording changes in admin area
|
982 |
+
* Compress some javascript libraries and remove unused files to make plugin lighter
|
983 |
* Admin popup UI design minor optimizations - make it's usage more comfortable for You
|
984 |
|
985 |
= 1.0.5 =
|
986 |
+
* Fixed activation warning with DEBUG mode enabled
|
987 |
|
988 |
= 1.0.4 =
|
989 |
* Fixes Popup for DEBUG mode enabled
|
990 |
|
991 |
= 1.0.3 =
|
992 |
+
* Remove some unused code parts
|
993 |
+
* New template preview images - more comfortable popup creation process
|
994 |
+
* Label edit - moved to Texts section
|
995 |
+
* Correct internal links to wordpress.org
|
996 |
|
997 |
= 1.0.2 =
|
998 |
+
* Plugin installation optimization
|
999 |
+
* Color picker - add color picker styles
|
1000 |
+
* Plugin core improvements - make it lighter
|
1001 |
|
1002 |
= 1.0.1 =
|
1003 |
* Popup plugin submit to WordPress.org
|