Popup by Supsystic - Version 1.9.38

Version Description

/ 18.09.2018 = * Additional code improvements * Minor issues fix

Download this release

Release Info

Developer supsystic.com
Plugin Icon 128x128 Popup by Supsystic
Version 1.9.38
Comparing to
See all releases

Code changes from version 1.9.20 to 1.9.38

Files changed (49) hide show
  1. classes/html.php +12 -0
  2. classes/installer.php +2 -2
  3. classes/utils.php +12 -6
  4. config.php +5 -1
  5. js/admin.options.js +15 -15
  6. js/common.js +2 -2
  7. js/common.min.js +2 -0
  8. js/core.js +3 -3
  9. js/core.min.js +2 -0
  10. js/google.recaptcha.js +32 -0
  11. js/wp.tabs.js +3 -3
  12. modules/options/models/options.php +2 -2
  13. modules/popup/controller.php +3 -1
  14. modules/popup/css/admin.popup.css +5 -2
  15. modules/popup/css/frontend.popup.css +4 -2
  16. modules/popup/css/frontend.popup.min.css +2 -0
  17. modules/popup/js/admin.popup.edit.js +1 -0
  18. modules/popup/js/admin.popup.js +1 -1
  19. modules/popup/js/frontend.popup.js +36 -12
  20. modules/popup/js/frontend.popup.min.js +2 -0
  21. modules/popup/mod.php +6 -3
  22. modules/popup/views/popup.php +9 -2
  23. modules/popup/views/tpl/popupEditAdminDesignOpts.php +9 -0
  24. modules/popup/views/tpl/popupEditAdminMainOpts.php +20 -2
  25. modules/popup/views/tpl/popupEditAdminSubOpts.php +43 -1
  26. modules/subscribe/classes/Batch.php +150 -150
  27. modules/subscribe/classes/MailChimp.php +450 -450
  28. modules/subscribe/classes/Webhook.php +82 -82
  29. modules/subscribe/classes/mailPoetV3.php +13 -13
  30. modules/subscribe/mod.php +6 -0
  31. modules/subscribe/models/subscribe.php +15 -1
  32. modules/supsystic_promo/js/admin.tour.js +1 -1
  33. modules/supsystic_promo/mod.php +1 -0
  34. modules/supsystic_promo/models/classes/lib/Base/MixpanelBase.php +64 -64
  35. modules/supsystic_promo/models/classes/lib/ConsumerStrategies/AbstractConsumer.php +56 -56
  36. modules/supsystic_promo/models/classes/lib/ConsumerStrategies/CurlConsumer.php +220 -220
  37. modules/supsystic_promo/models/classes/lib/ConsumerStrategies/FileConsumer.php +37 -37
  38. modules/supsystic_promo/models/classes/lib/ConsumerStrategies/SocketConsumer.php +307 -307
  39. modules/supsystic_promo/models/classes/lib/Mixpanel.php +302 -302
  40. modules/supsystic_promo/models/classes/lib/Producers/MixpanelBaseProducer.php +228 -228
  41. modules/supsystic_promo/models/classes/lib/Producers/MixpanelEvents.php +163 -163
  42. modules/supsystic_promo/models/classes/lib/Producers/MixpanelPeople.php +147 -147
  43. modules/supsystic_promo/views/tpl/adminTour.php +2 -2
  44. modules/supsystic_promo/views/tpl/pluginDeactivation.php +77 -77
  45. modules/templates/mod.php +3 -3
  46. modules/tgm_promo/classes/class-tgm-plugin-activation.php +3853 -3853
  47. modules/tgm_promo/mod.php +46 -46
  48. pps.php +3 -1
  49. 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
- $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
  }
346
  }
347
- switch_to_blog($orig_id);
 
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
- $orig_id = $wpdb->blogid;
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
- switch_to_blog($orig_id);
 
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
- $orig_id = $wpdb->blogid;
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
- switch_to_blog($orig_id);
 
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.20');
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+ '"]').size()) {
13
  jQuery(this).addClass('current');
14
  }
15
  });
@@ -34,7 +34,7 @@ jQuery(document).ready(function(){
34
  }
35
  }, 1000);
36
 
37
- if(jQuery('.ppsInputsWithDescrForm').size()) {
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').size()) {
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').size()) {
93
  tooltipsterSettings.position = 'top-left';
94
  jQuery('.supsystic-tooltip').tooltipster( tooltipsterSettings );
95
  }
96
- if(jQuery('.supsystic-tooltip-bottom').size()) {
97
  tooltipsterSettings.position = 'bottom-left';
98
  jQuery('.supsystic-tooltip-bottom').tooltipster( tooltipsterSettings );
99
  }
100
- if(jQuery('.supsystic-tooltip-left').size()) {
101
  tooltipsterSettings.position = 'left';
102
  jQuery('.supsystic-tooltip-left').tooltipster( tooltipsterSettings );
103
  }
104
- if(jQuery('.supsystic-tooltip-right').size()) {
105
  tooltipsterSettings.position = 'right';
106
  jQuery('.supsystic-tooltip-right').tooltipster( tooltipsterSettings );
107
  }*/
108
  ppsInitTooltips();
109
- if(jQuery('.ppsCopyTextCode').size()) {
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').size()) { // Not used for now
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').size())
296
  jQuery('#ppsPopupGoToTop').show();
297
  } else if(wasUnSticking) {
298
- if(jQuery('#ppsPopupGoToTop').size())
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).size()) {
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').size()) {
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').size()) {
521
  parent = jQuery(this).parents('label:first');
522
- } else if(jQuery(this).parents('.ppsPopupOptRow:first').size()) {
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).size() > 0 ? true : false);
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).size() > 0) {
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').size() ? jQuery(params.btn).find('.fa') : jQuery(params.btn);
89
- if(jQuery(params.btn).find('.fa').size()) {
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').size()) {
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).size()) {
21
  $this.wpTabs('activate', locationHash);
22
- if(jQuery(locationHash).size()) {
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).size()) {
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'] != $val) {
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 = 0;
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
- $arr[] = '"'. $wpdb->_real_escape($v). '"';
 
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: 1px !important;
43
- height: 1px !important;
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').size()) { // If on creation page
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.reidrect_on_close && popup.params.tpl.reidrect_on_close != '') {
 
 
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').size()) {
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').size()) {
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').size()) {
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').size()) {
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
- , href = $btn && $btn.size() ? $btn.attr('href') : false;
1295
- if(href && href != '') {
1296
- ppsPopups[ i ].params.sub_redirect_to_btn_url_href = href;
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
- framePps::_()->addScript('frontend.popup', $this->getModPath(). 'js/frontend.popup.js');
 
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="ppsShowPopup('. $this->popup['id'] .'); 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,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
- $this->pushError ( $res['detail'] );
 
 
 
 
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).size())
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 powerfull 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,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 powerfull 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 neds 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>
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 '&nbsp;'; // 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 '&nbsp;'; // 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.20
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, marketing, optin, advertising, popover, pop-up, pop over, lightbox, contact form, builder, modal, video, youtube, social, facebook
5
- Tested up to: 4.9.4
6
- Stable tag: 1.9.19
7
 
8
- Popup by Supsystic is the best way to convert visitors into subscribers, followers & customers. Create any type of popup with popup builder templates
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 help you to get newsletter subscribers, promote new products, deliver special offers and get more social followers. Popup maker loaded with full range of features:
13
 
14
- = Main Features =
15
-
16
- * 30+ Mobile-ready [Popup Templates](https://supsystic.com/popup-examples/ "WordPress Plugin Popup Templates")
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
- * [Subscription / Mail List Building](https://supsystic.com/plugins/popup-plugin/#ppsShowPopUp_127 "Mail List Building Popup")
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
- What makes people buy up? Firstly emotions. Use Popup builder to popup people's emotions and up your purchases. By Supsystic team Popup you can easily customize any popup window to your site design attracting users popuply. Popup plugin allows to create magnetizing popup by customizing sizes, attracting visitors attention to bonuses and discounts with popups. Many other various promotion offers becomes more effective by popouping them on the site.
 
 
 
 
 
46
 
 
47
  [youtube http://www.youtube.com/watch?v=-Q9-tWi-lQE]
48
 
49
- = Popup Triggers =
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
- Popup Customers Support is the only one tool to help you survive in Popup Plugins World. [Contact us](https://supsystic.com/plugins/popup-plugin?utm_source=wordpress&utm_medium=contactus&utm_campaign=popup "Contact Us"), if your Popup Lifes come down or you need a Powerful Popup Advice from experienced Popup Backing Masters and your dreams come true!
102
-
103
- = Popup Translations =
104
-
105
- Wanna feel outfitted and equipped enough? Get Pop Up Pro version for free! Just write about your intention to popup support and translate Popup to the one of new languages. Let’s Popup the WordPress beginners!
106
- Available translations for [PopUp by Supsystic](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic"):
107
-
108
- * English
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
- = Why Popup by Supsystic is “must have” for your website? =
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
- To put Contact form into Popup:
192
 
193
- * Create Contact Form and copy it’s short code
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
- = Can we show popup only when user is scrolling? =
 
201
 
202
- Supsystic Popup Builder in Main Top Settings has section “When To Show PopUp” that includes an option Scroll Window. In this builder you can choose the delay and percentage of total scroll of the page for Popup to occur. This Popup Builder option of Supsystic Popup Plugin is such workable and suitable that it can be applied to every Popup on every WordPress site.
203
 
204
- = Can Popup been shown only per visitors? =
205
 
206
- Surely, in order to achieve this kind of showing Popup follow the pass: Popup plugin> “Add new PopUp”> Main Top Settings> “Whom To Show PopUp”. Here it is the place to force Popup be shown only per visitors in time and status dimensions of Popup settings. Don’t forget to choose the time period, for which Popup Builder should remember your task.
207
 
208
- = Can we show popup only on mobile devices? =
 
 
 
 
 
 
 
 
209
 
210
- Yes, we can. There is “Show/Hide on devices” option in “Whom To Show PopUp” of Main Tab Popup Builder Settings. Choose the device of Popup showcase – tablet, phone etc.
211
 
212
- = Is autoclose of Popup avalaible? =
213
 
214
- Yes.To establish this performance for the Popup, please, follow the pass: Popup plugin> “Add new PopUp”> Main Top Settings>"When to close PopUp"> “After time passed” and set the closing time that your Popup need.
215
 
216
- = Disable Popup without action - how to do it? =
217
 
218
- Popuping the window in front of the user and waiting for some guests reaction - is a perfect Popup for you, but you don’t know how to bring this Popup idea to Life? Supsystic team and Popup builder know how to let your Popup dreams come true! Open Popup Plugin in WordPress area, Create new Popup in Popup Builder and wait fr new page to popup. In the main Tab Popup Builder Settings pay attention at “When to close PopUp”. In this place of Popup builder find an option “Only after action (Subscribe/Share/Like)” or don’t forget to chose the time, after which Popup will be closed to make your popup users feel nice.
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
- 2. Wide range of settings to configure the optin plugin and make it work for different tasks.
 
 
 
 
 
 
252
 
253
- = Popup Types =
 
 
254
 
255
- = Common Popup =
 
 
256
 
257
- It is a type of [Popup](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") that comes first for creating New one Popup. Twenty-nine popup common templates are made for your simplifying work with popup. To Common Popup Builder you can easily add map, popup background pictures and social share buttons for unique design of your popup. Minimize your time for popup production with ready popup common temples.
 
 
258
 
259
- = Contact Form Popup =
 
 
 
 
260
 
261
- To pump your [Popup](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") Builder with contact form requires several easiest actions: make a contact form and insert it to popup with shortcode. Furthermore, you can edit popup and contact form in popup in the same time.
 
 
 
262
 
263
- This theme of contact form popup allows user to model and manage the popup contact forms easily on the WordPress website and product popup with contact form inside. There is a popup wonderful possibility to add the image or text button link in all popups with contact forms. That popup contact form permits to send emails to the popup administration page and permits to change the site admin email address.
 
 
264
 
265
- = Video Popup =
 
 
 
266
 
267
- When you are on the start level of the online shop owner you may see that only a little part of your site visitors buy the something. To improve the situation explore the [Popup](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") to collect emails with popup contact form and aware your potential clients in last sales, bonus programs or others. Also you may try login/registration popups to bond your guests with special proposals on popups. Or, for example, try Social Share Buttons in the PopUp Builder.
 
 
268
 
269
- Perform your site in candy attraction resource with Video Popup Builder features! Enterprise Popup Elegant Box with tutorials, advertising, reviews and your team achievements now is possible with Pop Uping Video on WordPress sites.
 
 
270
 
271
- = Facebook Like Popup =
 
 
 
272
 
273
- More then 50% of population of the Earth is addicted to the internet and social share resources. Make them involved in your products/ services with Popup plugin. Or just become popular offering to share your site along the FB, Twitter, Linkedin etc. by Facebook Like Popup. Installing of the Popup Builder doesn’t take much time or effort than to drink coffee or tea.
274
- Facebook Like Popup is the most gentle way to welcome your visitors for website interaction. Try simple Facebook Like Popup by Supsystic in the box to show your social sites profile.
 
275
 
276
- = Age Verification Popup =
 
 
277
 
278
- Working with adult site content, sometimes is needed to be sure kids not watching. Use simple [Popup](https://supsystic.com/plugins/popup-plugin "PopUp by Supsytic") builder to provide Popup Age Verification and prevent problems. Popup Age Verification works easily in psychological aspect and give maximum result with little expenses. Minimalistic design of the popup can be fairly edited in Popup Age Verification template.
 
 
279
 
280
- = Our plugins =
 
 
 
281
 
282
- * [Photo Gallery by Supsystic](https://wordpress.org/plugins/gallery-by-supsystic/ "Photo Gallery by Supsystic")
283
- * [Pricing Table by Supsystic](https://wordpress.org/plugins/pricing-table-by-supsystic/ "Pricing Table by Supsystic")
284
- * [Contact Form by Supsystic](https://wordpress.org/plugins/contact-form-by-supsystic/ "Contact Form by Supsystic")
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
- == Changelog ==
 
 
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 PopUp positioning
305
 
306
  = 1.9.18 / 06.02.2018 =
307
- * Adapt Facebook Like PopUp to latest Facebook API changes
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 PopUps
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 PopUp using "Display only selector"
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 bild-in MailChimp Welcome email functionality - it was disabled by MailChimp for API, and can be enabled in MailChimp account
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 PopUps
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 PopUp interaction
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 PopUp is not visible right after page load (show after click or on exit from site for example)
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 PopUp template "Best Of Collection"
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 PopUp Labels
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 PopUps
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 PopUp right near clicked element (or any other element on page)
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 PopUp settings output
406
- * Possibility to disable PopUp Statistics
407
- * Fix possible issue with iframe without src in PopUp
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 PopUp fix - to make it work according latest Facebook changes
417
  * Fix HTTP images protocol for christmas snow effect
418
- * Possibility to select week days when you need to show PopUps
419
  * SMTP servers integration
420
  * Send Mail service integration
421
- * Possibility to just close PopUp if email already exists during Registration process
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 PopUp Registration
428
- * Additional re-position and resize PopUp after all images inside was loaded
429
- * Do not use PopUp close and subscribe errors actions - when calculating conversions
430
  * Blacklist error message editing
431
- * Make correct work Layered PopUp with Click outside PopUp option
432
- * Fix issue with displaying PopUp on Posts page listing
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 PopUp Template "Lavender Mood"
439
- * Added PopUp Template "Winter Subscribe"
440
- * Added PopUp Template "Get Discount"
441
- * Added PopUp Template "Pretty"
442
  * Minor code review
443
 
444
  = 1.8.4 / 19.12.2016 =
445
- * Redesign PopUp Theme "New York"
446
- * Redesign PopUp Theme "Video List"
447
- * Added PopUp template "Exclusive Subscription"
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 pop-up template bugs for additional subscribe elements
457
- * Added PopUp template "Winter Sale"
458
- * Added PopUp template "Christmas Tree"
459
- * Added PopUp template "Christmas Candies"
460
- * Added PopUp template "Xmas Discount"
461
- * Forgot Password link for Login PopUps functionality added
462
 
463
  = 1.8.2 / 29.11.2016 =
464
- * Added [Christmas popup templates pack](https://supsystic.com/blog/christmas-popup-templates-pack "Christmas popup templates")
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 PopUp - in Admin Area
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 PopUp Themes - List Building Neo, Bright Girl and Sign Up Classic!
478
  * Update mobile detection library
479
- * Possibility to integrate PopUp with Google Analytic - PRO
480
- * Added new Statistic Event Types - PopUp Close and Subscribe Failure
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 PopUp - PRO
494
- * Admin area PopUps listing design improvements
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 Popup after Subscribe form was successfully submitted
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 PopUp on Home page with posts listing and multiple pages of listings
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 PopUp was displayed
526
- * Fixed issue with multiple shortcodes compilation from PopUps text data
527
- * Fixed issue with multiple "on click" binding attempts
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 PopUps - in one click from Settings page
535
- * Possibility to redirect to link URL after subscribe if On Click link was used to show PopUp
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 web-site
540
- * Fix issue with showing PopUp on main Home Page if Home Page - is from WooCommerce plugin
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 PopUp
546
- * Option to show PopUp if AdBlock is enabled - PRO
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 PopUp for selected User Roles option - PRO
550
- * Small fixes and improvements for PopUp Themes. #170 add 0.2h
551
- * Possibility to select categories for show PopUp
552
- * Possibility to insert shortcodes in Subscribe fields values in PopUp
553
- * Possibility to insert scripts - inside PopUp content (in text editors)
554
- * 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
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 PopUp Template added - "Video List Flat"
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 PopUp
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 PopUp template
572
- * Age Verification PopUp - added statistics for verification actions too
573
 
574
  = 1.6.9 / 13.04.2016 =
575
- * Hot fix for WordPress 4.5 and On Click popup
576
- * Fix On Click PopUp show for latest jQuery library
577
 
578
  = 1.6.8 / 12.04.2016 =
579
  * Aweber - change subscribe URL to SSL protocol
580
- * "Pink" PopUp Template mobile version fix
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
- * Hot fix for page cache check (hot fix version 1.6.5)
589
  * Small spelling issues fix
590
 
591
  = 1.6.5 / 05.04.2016 =
592
- * Possibility to use Subscribe, Login and Registration forms - in one PopUp, at one and same time - all 3 forms together
593
- * Small fix for "Photodoto" PopUp Template
594
- * Added option "Redirect after close" - you can now redirect your users after they will close PopUp
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 PopUp admin notifications
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" PopUp template
610
 
611
  = 1.6.3 / 22.03.2016 =
612
- * Fix issue with showing PopUp on WooCommerce "Shop" page only
613
  * Added another supported video hosting service
614
- * Small fix for build-in content popup - do not load them in standard PopUp load query (they will be loaded from shortcodes)
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 PopUp specific times in a hour, day, week or month - for each visitor
621
- * Small fix for PDF PopUp template
622
- * Make correct open/close Video PopUp with self-hosted videos
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 PopUp was shown (PDF, iFrame PopUp types)
628
  * ConvertKit subscription method integration - PRO
629
- * PopUp Login - login by Username by default
630
  * Disable block IP for multiple subscriptions by default
631
- * Improve On Exit PopUp initialization (to avoid conflict with some modificated jquery libraries)
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 PopUp at one and same time
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 in PopUp after PopUp was closed even if template was not with video type
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 -> PopUp edit screen
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 from PopUp to Jetpack!
656
- * Added Date display range for PopUp
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 PopUp data - to fronted JavaScript: make code lighter
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 PopUp itself
667
- * When to close PopUp -> Only after action -> Added possibility to select time after action that should pass before 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 PopUp only for specific Search Engines and Social Media sites
673
- * Possibility to insert PopUp into site content - PRO
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 for popup in admin area
684
- * Reduce user browser memory usage to work PopUp correctly - make it faster and lighter!
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 PopUp admin area edit screen
687
- * Small fix for PopUp Template
688
- * "Add PopUp" button - in admin top bar: create your popup more faster!
689
 
690
  = 1.5.5 / 26.01.2016 =
691
  * MailChimp Groups functionality added
692
- * Do not send CSS and HTML data when editing PopUp if they was not changed
693
- * Possibility to force show PopUp right after page loaded using hash parameters
694
- * Minor fix for Business PopUp Template
695
  * Improve IP detection algorithm
696
- * Small correct for TinyMce buttons colors on PopUp Edit screen
697
- * Minor fixes for PopUp templates Video Classy, Layered Popup, Ready and Business
698
- * Added option "Disable window scroll" to disable browser window scrolling while PopUp is opened
699
- * Show PopUp for cases when user selected invalid image as on of the Backgrounds
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 PopUp plugin
706
- * Fix positioning for Responsive mode of the PopUp with "Full resize" 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 PopUp on menu click for WordPress 4.4 (after field Title for menu items was removed)
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 PopUp settings!
717
- * Added "Ignore related videos" option for Video type popup
718
  * Plugin server-side core improvements
719
- * On Exit PopUp - make Exit detection more correct
720
  * Checkbox additional fields type improvements
721
  * Minor issue fix in Mailrelay modules
722
 
723
  = 1.5.2 / 14.12.2015 =
724
- * Change PopUp Template functionality - don't flush Main settings after Template change
725
- * Correct shortcodes display in admin area on small scree devices
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 PopUp edit screen option
730
- * Fix for "On Link Follow" PopUp mode
731
- * Improve "START popup" template
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 PopUp" - minor issues fixed
736
  * Step by step tour for first time users
737
- * Added option for Time Delay for PopUp Click on certain link and On Link Follow settings
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 PopUp at specific time range
744
- * Minor issue fixed for popup lists bullets
745
- * Popup subscription additional fields - Checkbox field type added
746
- * Notification Bar popup type added
747
- * Login / Registration popup types added
748
- * A lot of new popup templates
749
 
750
  = 1.4.6 / 17.11.2015 =
751
  * Small code improvements
752
- * "Map style" PopUp template small fix
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 PopUp Templates in admin area
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 userfriendly improvements
772
  * Corrections for responsiveness - now will correct display on all devices
773
  * Added Polish language
774
- * Small fix for Calm PopUp template
775
- * AB Testing - added possibility to select Main (Display) settings for tested PopUp
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 PopUp template
779
 
780
  = 1.4.2 / 27.10.2015 =
781
- * Minor issues fix for "List Building", "Bonus" and "Smart" PopUp templates
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 PopUp templates
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 PopUp will be shown
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 PopUp templates
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 PopUp data for frontend - lighter by removing unused on frontend variables
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 userfriendly
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 "&amp;" 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 PopUp options - PRO
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
- * Instalation and Activation process included
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 PopUp templates
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 in PopUp
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 PopUp Templates
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 for popup - show images in PopUp without delay
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 PopUp preview - load all frontend styles and scripts - to make it's view more like on frontend
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 PopUp
886
- * Possibility to edit PopUp Name after creation
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" POpUp show - now link can contain shortcode in any href attr place
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 PopUp - on Menu Item click
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 - "Bussiness"
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 popup
941
 
942
  = 1.2.2 / 04.06.2015 =
943
- * Possibility to insert "embed" shortcodes to text fields in PopUp - to show video in any place
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 popup template additional subscribe fields integration
950
- * Fixed close button position in Exclusive template and romove errorMsg border
951
  * Minor issues fixes and improvements
952
 
953
  = 1.2.0 / 19.05.2015 =
954
- * Fixed popup bug with Mozilla browser in Exclusive template
955
- * Added Russian popup language and fixed some spelling issues
956
- * Subscribe popup custom fields builder - PRO
957
- * Small popup fix for Classy template
958
- * Language popup translation files update
959
- * Aweber popup AD Tracking feature added
960
- * Some popup unused files remove
961
- * Small popup re-design on Layered PopUp style feature
962
- * Admin popup area design improvements
963
- * Correct popup message for subscribe success when MailPoet is used as Subscribe engine
964
 
965
  = 1.1.9 / 07.05.2015 =
966
- * Code popup review
967
- * Minor popup issues fix
968
 
969
  = 1.1.8 / 30.04.2015 =
970
- * Added popup translation
971
- * Fix for popup cookie days set - for case when it is set to 0
972
- * Added new popup global option - "Disable blocking Subscription from same IP"
973
- * Close PopUp after outside click option
974
- * Small PopUp main settings tab tooltips fix
975
- * Small popup fix for "Sign Up" template
976
- * Check your server popup email functionality option
977
- * Fixed popup minor bugs
978
 
979
  = 1.1.7 / 23.04.2015 =
980
- * Admin popup area User Interface improvements - make it more comfortable and attractive for our Users
981
- * Fix popup conflict with some WordPress plugins in our Code editor tool (conflict with "codemirror" library)
982
- * Hide popup for Logged-in PopUp option
983
- * Popup Option to set period of time for hide PopUp for already viewed users, or already made an action
984
 
985
  = 1.1.6 / 14.04.2015 =
986
  * Correction for cookie lifetime in recording user actions
987
- * Fix popup template width for template "Informed" template
988
- * Some popup spelling issues fix
989
- * Fix popup charset for admin PopUp preview
990
- * Minor popup admin design issues fix
991
- * Small popup fix for "Informed" template
992
  * Popup MailChimp - disable double opt-in option
993
- * Improve popup design of admin area -> Edit PopUp -> Subscribe section
994
- * Social popup links - additional fix to avoid styles conflict
995
- * Minor popup issues code fix
996
 
997
  = 1.1.5 / 07.04.2015 =
998
- * Popup Aweber - Added option to redirect on Subscribe success
999
- * Popup Option - to Show on required % scroll
1000
  * Shortcode popup output in admin area - make it more comfortable to copy and move to content
1001
- * Fixed popup conflict with Twig autoloaded re-defining in other plugins or themes
1002
- * Facebook PopUp - correct language detection
1003
- * Correct displaying usual embed iframes with Google Maps in PopUp
1004
- * PRO popup - added options: Close only after action, after time passed - https://supsystic.com/plugins/popup-plugin/
1005
- * PRO popup - added options: Show at the bottom of the page, after Inactivity, after User Comment option, after Purchasing (Checkout) - https://supsystic.com/plugins/popup-plugin/
1006
- * PRO popup - Possibility to subscribe with Facebook - https://supsystic.com/plugins/popup-plugin/
1007
- * PRO popup - Possibility to set user role for plugin usage (not just admin) - https://supsystic.com/plugins/popup-plugin/
1008
- * Some popup minor spelling issues fix
1009
- * Core popup code improvements
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 popup Subscriber email edit options
1015
  * Option to edit popup From field in emails to subscriber
1016
- * Small popup issue fix - for servers with old version of pcre package (preg_match_all php warning)
1017
- * Added German popup translation
1018
- * PRO popup - Possibility to set font family for PopUp
1019
- * Correction for Video PopUp - correct stop/play video after close/open PopUp
1020
- * Minor popup issue with empty statistics fix
1021
 
1022
  = 1.1.3 / 24.03.2015 =
1023
- * Play/Stop popup Youtube video on client side - make it correct work for hidden elements
1024
- * Fix popup conflict with other plugins that use modified CodeMirror library
1025
- * Added French popup translation
1026
- * Added Spanish popup translation
1027
- * Correction for popup loading translation files for plugin - make it fully multi language
1028
- * Overview - FAQ popup info changed
1029
 
1030
  = 1.1.2 / 20.03.2015 =
1031
- * Added popup option - "Create popup Subscriber without confirmation"
1032
- * Special popup page - to show when confirm subscription for WordPress
1033
- * Small popup Fix for Template ID 7 - inputs text color
1034
- * Compile popup shortcodes - even in preview in admin area PopUp edit screen
1035
- * Some popup spelling issues fix
1036
- * Overview popup tab added
1037
- * Statistics popup date format for Hour change
1038
- * Correct popup condition - for showing / hiding for specific post / page - don't show on posts listing, only on single post / page
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 popup animations tab in admin area
1047
- * Correct popup animation for Facebook Like PopUp - animate it only after whole content will be loaded from Facebook
1048
  * Added popup link to documentation about usage code - HTML and CSS - editor
1049
- * Correct popup process shortcode from any place (not only from post/page content) - sidebars, external themes/plugins, etc.
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 popup
1054
 
1055
  = 1.1.0 / 05.03.2015 =
1056
- * Added 5 new popup templates
1057
- * Popup Statistics - added table view in admin area
1058
- * Popup Statistics - added CSV export in admin area
1059
- * Popup Statistics - added date range selection in admin area
1060
- * Popup Statistics - added Unique views parameters and Conversion calculation
1061
  * Possibility to disable popup (not delete, but just disable)
1062
- * Clone PopUp functionality added
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 popup core improvements
1066
- * AB popup testing - test list modification according to main popup list
1067
- * Popup Installer improve
1068
 
1069
  = 1.0.9 / 24.02.2015 =
1070
  * Allow to assign new subscribers - special roles
1071
- * Option to disable PopUp for: Mobile, Tablet or Desktop PC
1072
  * Additional fix for mobile devices
1073
- * Small fix for latest added popup new templates
1074
- * Main PopUp edit tabs sticky functionality - make it work with some standard notifications
1075
- * Show PopUp label always on top of edit tabs on PopUp edit screen - more user-friendly
1076
- * Option to show PopUp - after scroll window - right after scroll or with delay
1077
- * Layered popup integration - https://supsystic.com/plugins/popup-plugin/
1078
- * Additional popup modification for "Click On" show mode - to make sure it work with more content editor systems
1079
- * A/B popup testing - tests should stay tests even after whole design change - fixed - https://supsystic.com/plugins/popup-plugin/
1080
- * Admin popup list table - do not stick header line (call too much problems and don't need this)
1081
- * Correct show popup on mobile devices - every size, every type
1082
- * Fix sticky edit PopUp tabs scroll position
1083
 
1084
  = 1.0.8 =
1085
- * Added PopuUp Statistics - now you can view charts for your popup in admin area
1086
  * Video popup - Hide Controls option
1087
- * New PopUp Templates - 4 additional templates
1088
  * Fix php notice for enabled debug mode for some php versions on activation
1089
- * Added localization popup .pot file - in plugin folder lang/pps_lng.po
1090
- * Change Aweber popup listname - "Unique List ID" field label - to make it more clearer
1091
- * Fix issue for "Click on certain link / button / other element" - when there are more then one PopUp in post/page inserted
1092
- * Make PopUp admin tabs edit - responsive (usability)
1093
  * Make popup Animation selection - more obviously
1094
- * Admin popup system messages - make it design according to main admin design
1095
- * Animation popup duration - now in milliseconds (instead of seconds)
1096
- * Helper popup screen - for option
1097
- * PRO popup version integration
1098
- * Core popup code API improvements
1099
- * Minor popup issues fix
1100
 
1101
  = 1.0.7 =
1102
- * Accept shortcodes in PopUp text areas, footer note and even label
1103
- * Possibility to show PopUp on Click on any element of the page
1104
  * Popup Fix for case when no template was selected during PopUp creation
1105
- * Additional popup fixes for DEBUG mode
1106
- * Minor popup issue fixes on core code
1107
 
1108
  = 1.0.6 =
1109
  * MailChimp integration with popup
1110
  * Video popup - Autoplay option added
1111
- * Correct position set for Facebook Like PopUp - depend position on widget size after it will be loaded
1112
- * Re-calculate position for each PopUp - after window was resized
1113
- * Fix popup issue with popup Facebook Like PopUp array options
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 popup Building and popup Video List templates - fix subscribe Submit button name option
1117
- * Fastest and Easiest popup template - fix subscribe enable/disabler name option
1118
  * Fix Popup for smaller window size - responsive from now!
1119
- * Correct "none" popup animation selection
1120
- * Rename popup admin area menu items - make it more intuitive and user-friendly
1121
- * Fix popup preview iFrame issue in admin area - when for some cases scripts with "ppsHidePreviewUpdating" was not loaded when iFrame was already loaded
1122
- * Tooltip popup functionality in admin area optimization
1123
- * Some popup wording changes in admin area
1124
- * Compress some popup javascript libraries and remove unused files to make plugin lighter
1125
  * Admin popup UI design minor optimizations - make it's usage more comfortable for You
1126
 
1127
  = 1.0.5 =
1128
- * Fixed Popup activation warning with DEBUG mode enabled
1129
 
1130
  = 1.0.4 =
1131
  * Fixes Popup for DEBUG mode enabled
1132
 
1133
  = 1.0.3 =
1134
- * Remove some unused popup code parts
1135
- * New popup template preview images - more comfortable popup creation process
1136
- * Popup Label edit - moved to Texts section
1137
- * Correct popup internal links to wordpress.org
1138
 
1139
  = 1.0.2 =
1140
- * Popup installation optimization
1141
- * Popup Color picker - add color picker styles
1142
- * Popup plugin core improvements - make it lighter
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 "&amp;" 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