MailPoet Newsletters (Previous) - Version 2.7.15

Version Description

Download this release

Release Info

Developer wysija
Plugin Icon 128x128 MailPoet Newsletters (Previous)
Version 2.7.15
Comparing to
See all releases

Code changes from version 2.7.14 to 2.7.15

Files changed (322) hide show
  1. controllers/ajax/subscribers.php +3 -1
  2. controllers/front/subscribers.php +3 -1
  3. core/base.php +1 -1
  4. helpers/update.php +22 -1
  5. helpers/user.php +43 -11
  6. index.php +1 -1
  7. readme.txt +4 -1
  8. sql/install.sql +9 -0
  9. trunk/add-ons/add-ons-list.php +359 -0
  10. trunk/add-ons/add-ons.php +263 -0
  11. trunk/add-ons/index.html +0 -0
  12. trunk/classes/WJ_Analytics.php +899 -0
  13. trunk/classes/WJ_Bridge.php +91 -0
  14. trunk/classes/WJ_Export.php +236 -0
  15. trunk/classes/WJ_Field.php +307 -0
  16. trunk/classes/WJ_FieldHandler.php +59 -0
  17. trunk/classes/WJ_FieldRender.php +268 -0
  18. trunk/classes/WJ_FieldUser.php +130 -0
  19. trunk/classes/WJ_Import.php +853 -0
  20. trunk/classes/WJ_Settings.php +29 -0
  21. trunk/classes/WJ_Sparkpost.php +86 -0
  22. trunk/classes/WJ_Stats.php +491 -0
  23. trunk/classes/WJ_StatsSessionManager.php +100 -0
  24. trunk/classes/WJ_Upgrade.php +408 -0
  25. trunk/classes/WJ_Utils.php +88 -0
  26. trunk/classes/index.html +0 -0
  27. trunk/controllers/ajax/campaigns.php +978 -0
  28. trunk/controllers/ajax/config.php +470 -0
  29. trunk/controllers/ajax/index.html +0 -0
  30. trunk/controllers/ajax/statistics.php +115 -0
  31. trunk/controllers/ajax/subscribers.php +127 -0
  32. trunk/controllers/ajax/tmce.php +17 -0
  33. trunk/controllers/back.php +779 -0
  34. trunk/controllers/back/campaigns.php +2665 -0
  35. trunk/controllers/back/config.php +377 -0
  36. trunk/controllers/back/index.html +0 -0
  37. trunk/controllers/back/mp3.php +26 -0
  38. trunk/controllers/back/premium.php +26 -0
  39. trunk/controllers/back/statistics.php +204 -0
  40. trunk/controllers/back/subscribers.php +1043 -0
  41. trunk/controllers/front.php +59 -0
  42. trunk/controllers/front/confirm.php +295 -0
  43. trunk/controllers/front/email.php +83 -0
  44. trunk/controllers/front/index.html +0 -0
  45. trunk/controllers/front/stats.php +72 -0
  46. trunk/controllers/front/subscribers.php +144 -0
  47. trunk/controllers/index.html +0 -0
  48. trunk/core/autoloader.php +23 -0
  49. trunk/core/base.php +1632 -0
  50. trunk/core/constants.php +44 -0
  51. trunk/core/controller.php +117 -0
  52. trunk/core/index.html +0 -0
  53. trunk/core/model.php +1040 -0
  54. trunk/core/module/module.php +244 -0
  55. trunk/core/module/statistics.php +33 -0
  56. trunk/core/module/statistics_model.php +140 -0
  57. trunk/core/module/statisticschart.php +11 -0
  58. trunk/core/module/statisticstable.php +5 -0
  59. trunk/core/view.php +318 -0
  60. trunk/css/add-ons.css +1 -0
  61. trunk/css/admin-campaigns-articles.css +1 -0
  62. trunk/css/admin-campaigns-autopost.css +1 -0
  63. trunk/css/admin-campaigns-bookmarks.css +1 -0
  64. trunk/css/admin-campaigns-dividers.css +1 -0
  65. trunk/css/admin-campaigns-editDetails.css +1 -0
  66. trunk/css/admin-campaigns-editTemplate.css +1 -0
  67. trunk/css/admin-campaigns-medias.css +1 -0
  68. trunk/css/admin-campaigns-themes.css +1 -0
  69. trunk/css/admin-campaigns-viewstats.css +1 -0
  70. trunk/css/admin-campaigns-welcome_new.css +1 -0
  71. trunk/css/admin-campaigns.css +1 -0
  72. trunk/css/admin-config-form_widget_settings.css +1 -0
  73. trunk/css/admin-config.css +1 -0
  74. trunk/css/admin-global.css +1 -0
  75. trunk/css/admin-premium.css +1 -0
  76. trunk/css/admin-statistics.css +1 -0
  77. trunk/css/admin-subscribers-addlist.css +1 -0
  78. trunk/css/admin-subscribers-edit.css +1 -0
  79. trunk/css/admin-subscribers-export.css +1 -0
  80. trunk/css/admin-subscribers-exportlist.css +1 -0
  81. trunk/css/admin-subscribers-import.css +1 -0
  82. trunk/css/admin-subscribers-importmatch.css +1 -0
  83. trunk/css/admin-subscribers-lists.css +0 -0
  84. trunk/css/admin-subscribers.css +1 -0
  85. trunk/css/admin-widget.css +1 -0
  86. trunk/css/admin.css +1 -0
  87. trunk/css/adminPopup.css +1 -0
  88. trunk/css/index.html +0 -0
  89. trunk/css/jquery/ui/themes/base/images/animated-overlay.gif +0 -0
  90. trunk/css/jquery/ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  91. trunk/css/jquery/ui/themes/base/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  92. trunk/css/jquery/ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  93. trunk/css/jquery/ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  94. trunk/css/jquery/ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  95. trunk/css/jquery/ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  96. trunk/css/jquery/ui/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  97. trunk/css/jquery/ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  98. trunk/css/jquery/ui/themes/base/images/ui-icons_222222_256x240.png +0 -0
  99. trunk/css/jquery/ui/themes/base/images/ui-icons_2e83ff_256x240.png +0 -0
  100. trunk/css/jquery/ui/themes/base/images/ui-icons_454545_256x240.png +0 -0
  101. trunk/css/jquery/ui/themes/base/images/ui-icons_888888_256x240.png +0 -0
  102. trunk/css/jquery/ui/themes/base/images/ui-icons_cd0a0a_256x240.png +0 -0
  103. trunk/css/jquery/ui/themes/base/jquery.ui.core.min.css +5 -0
  104. trunk/css/jquery/ui/themes/base/jquery.ui.datepicker.min.css +5 -0
  105. trunk/css/rtl.css +1 -0
  106. trunk/css/select2/select2.css +615 -0
  107. trunk/css/smoothness/images/calendar.gif +0 -0
  108. trunk/css/smoothness/images/index.html +0 -0
  109. trunk/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  110. trunk/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  111. trunk/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  112. trunk/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  113. trunk/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  114. trunk/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  115. trunk/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  116. trunk/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  117. trunk/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  118. trunk/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  119. trunk/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  120. trunk/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  121. trunk/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  122. trunk/css/smoothness/index.html +0 -0
  123. trunk/css/smoothness/jquery-ui-1.8.20.custom.css +565 -0
  124. trunk/css/tmce/editor.css +2317 -0
  125. trunk/css/tmce/index.html +0 -0
  126. trunk/css/tmce/panelbtns.css +23 -0
  127. trunk/css/tmce/style.css +7 -0
  128. trunk/css/tmce/subscribers_count.css +37 -0
  129. trunk/css/tmce/widget.css +44 -0
  130. trunk/css/validationEngine.jquery.css +1 -0
  131. trunk/css/vendor/bootstrap.tooltip.css +101 -0
  132. trunk/css/wysija-editor.css +1 -0
  133. trunk/css/wysija-form-editor.css +1 -0
  134. trunk/data/bookmarks/index.html +0 -0
  135. trunk/data/bookmarks/medium/01/credit.txt +3 -0
  136. trunk/data/bookmarks/medium/01/facebook.png +0 -0
  137. trunk/data/bookmarks/medium/01/google.png +0 -0
  138. trunk/data/bookmarks/medium/01/linkedin.png +0 -0
  139. trunk/data/bookmarks/medium/01/twitter.png +0 -0
  140. trunk/data/bookmarks/medium/02/credit.txt +3 -0
  141. trunk/data/bookmarks/medium/02/facebook.png +0 -0
  142. trunk/data/bookmarks/medium/02/google.png +0 -0
  143. trunk/data/bookmarks/medium/02/linkedin.png +0 -0
  144. trunk/data/bookmarks/medium/02/twitter.png +0 -0
  145. trunk/data/bookmarks/medium/03/credit.txt +5 -0
  146. trunk/data/bookmarks/medium/03/facebook.png +0 -0
  147. trunk/data/bookmarks/medium/03/google.png +0 -0
  148. trunk/data/bookmarks/medium/03/linkedin.png +0 -0
  149. trunk/data/bookmarks/medium/03/twitter.png +0 -0
  150. trunk/data/bookmarks/medium/04/credit.txt +5 -0
  151. trunk/data/bookmarks/medium/04/facebook.png +0 -0
  152. trunk/data/bookmarks/medium/04/google.png +0 -0
  153. trunk/data/bookmarks/medium/04/linkedin.png +0 -0
  154. trunk/data/bookmarks/medium/04/twitter.png +0 -0
  155. trunk/data/bookmarks/medium/06/credit.txt +5 -0
  156. trunk/data/bookmarks/medium/06/facebook.png +0 -0
  157. trunk/data/bookmarks/medium/06/google.png +0 -0
  158. trunk/data/bookmarks/medium/06/linkedin.png +0 -0
  159. trunk/data/bookmarks/medium/06/twitter.png +0 -0
  160. trunk/data/bookmarks/medium/07/credit.txt +5 -0
  161. trunk/data/bookmarks/medium/07/facebook.png +0 -0
  162. trunk/data/bookmarks/medium/07/google.png +0 -0
  163. trunk/data/bookmarks/medium/07/linkedin.png +0 -0
  164. trunk/data/bookmarks/medium/07/twitter.png +0 -0
  165. trunk/data/bookmarks/medium/08/credit.txt +5 -0
  166. trunk/data/bookmarks/medium/08/facebook.png +0 -0
  167. trunk/data/bookmarks/medium/08/google.png +0 -0
  168. trunk/data/bookmarks/medium/08/linkedin.png +0 -0
  169. trunk/data/bookmarks/medium/08/twitter.png +0 -0
  170. trunk/data/bookmarks/medium/09/credit.txt +5 -0
  171. trunk/data/bookmarks/medium/09/facebook.png +0 -0
  172. trunk/data/bookmarks/medium/09/google.png +0 -0
  173. trunk/data/bookmarks/medium/09/linkedin.png +0 -0
  174. trunk/data/bookmarks/medium/09/twitter.png +0 -0
  175. trunk/data/bookmarks/medium/10/credit.txt +3 -0
  176. trunk/data/bookmarks/medium/10/facebook.png +0 -0
  177. trunk/data/bookmarks/medium/10/google.png +0 -0
  178. trunk/data/bookmarks/medium/10/linkedin.png +0 -0
  179. trunk/data/bookmarks/medium/10/twitter.png +0 -0
  180. trunk/data/bookmarks/medium/11/credit.txt +5 -0
  181. trunk/data/bookmarks/medium/11/facebook.png +0 -0
  182. trunk/data/bookmarks/medium/11/google.png +0 -0
  183. trunk/data/bookmarks/medium/11/linkedin.png +0 -0
  184. trunk/data/bookmarks/medium/11/twitter.png +0 -0
  185. trunk/data/bookmarks/medium/12/credit.txt +5 -0
  186. trunk/data/bookmarks/medium/12/facebook.png +0 -0
  187. trunk/data/bookmarks/medium/12/google.png +0 -0
  188. trunk/data/bookmarks/medium/12/linkedin.png +0 -0
  189. trunk/data/bookmarks/medium/12/twitter.png +0 -0
  190. trunk/data/bookmarks/medium/13/credit.txt +5 -0
  191. trunk/data/bookmarks/medium/13/facebook.png +0 -0
  192. trunk/data/bookmarks/medium/13/google.png +0 -0
  193. trunk/data/bookmarks/medium/13/linkedin.png +0 -0
  194. trunk/data/bookmarks/medium/13/twitter.png +0 -0
  195. trunk/data/bookmarks/medium/14/credit.txt +3 -0
  196. trunk/data/bookmarks/medium/14/facebook.png +0 -0
  197. trunk/data/bookmarks/medium/14/google.png +0 -0
  198. trunk/data/bookmarks/medium/14/linkedin.png +0 -0
  199. trunk/data/bookmarks/medium/14/twitter.png +0 -0
  200. trunk/data/bookmarks/medium/15/credit.txt +3 -0
  201. trunk/data/bookmarks/medium/15/facebook.png +0 -0
  202. trunk/data/bookmarks/medium/15/google.png +0 -0
  203. trunk/data/bookmarks/medium/15/linkedin.png +0 -0
  204. trunk/data/bookmarks/medium/15/twitter.png +0 -0
  205. trunk/data/bookmarks/medium/16/credit.txt +3 -0
  206. trunk/data/bookmarks/medium/16/facebook.png +0 -0
  207. trunk/data/bookmarks/medium/16/google.png +0 -0
  208. trunk/data/bookmarks/medium/16/linkedin.png +0 -0
  209. trunk/data/bookmarks/medium/16/twitter.png +0 -0
  210. trunk/data/bookmarks/medium/17/facebook.png +0 -0
  211. trunk/data/bookmarks/medium/17/google.png +0 -0
  212. trunk/data/bookmarks/medium/17/linkedin.png +0 -0
  213. trunk/data/bookmarks/medium/17/twitter.png +0 -0
  214. trunk/data/bookmarks/medium/18/credit.txt +3 -0
  215. trunk/data/bookmarks/medium/18/facebook.png +0 -0
  216. trunk/data/bookmarks/medium/18/google.png +0 -0
  217. trunk/data/bookmarks/medium/18/linkedin.png +0 -0
  218. trunk/data/bookmarks/medium/18/twitter.png +0 -0
  219. trunk/data/bookmarks/medium/19/credit.txt +3 -0
  220. trunk/data/bookmarks/medium/19/facebook.png +0 -0
  221. trunk/data/bookmarks/medium/19/google.png +0 -0
  222. trunk/data/bookmarks/medium/19/linkedin.png +0 -0
  223. trunk/data/bookmarks/medium/19/twitter.png +0 -0
  224. trunk/data/bookmarks/medium/20/credit.txt +3 -0
  225. trunk/data/bookmarks/medium/20/facebook.png +0 -0
  226. trunk/data/bookmarks/medium/20/google.png +0 -0
  227. trunk/data/bookmarks/medium/20/linkedin.png +0 -0
  228. trunk/data/bookmarks/medium/20/twitter.png +0 -0
  229. trunk/data/bookmarks/medium/21/credit.txt +3 -0
  230. trunk/data/bookmarks/medium/21/facebook.png +0 -0
  231. trunk/data/bookmarks/medium/21/google.png +0 -0
  232. trunk/data/bookmarks/medium/21/linkedin.png +0 -0
  233. trunk/data/bookmarks/medium/21/twitter.png +0 -0
  234. trunk/data/bookmarks/medium/22/credit.txt +3 -0
  235. trunk/data/bookmarks/medium/22/facebook.png +0 -0
  236. trunk/data/bookmarks/medium/22/google.png +0 -0
  237. trunk/data/bookmarks/medium/22/linkedin.png +0 -0
  238. trunk/data/bookmarks/medium/22/twitter.png +0 -0
  239. trunk/data/bookmarks/medium/23/facebook.png +0 -0
  240. trunk/data/bookmarks/medium/23/google.png +0 -0
  241. trunk/data/bookmarks/medium/23/linkedin.png +0 -0
  242. trunk/data/bookmarks/medium/23/twitter.png +0 -0
  243. trunk/data/bookmarks/medium/24/facebook.png +0 -0
  244. trunk/data/bookmarks/medium/24/google.png +0 -0
  245. trunk/data/bookmarks/medium/24/linkedin.png +0 -0
  246. trunk/data/bookmarks/medium/24/twitter.png +0 -0
  247. trunk/data/bookmarks/medium/index.html +0 -0
  248. trunk/data/bookmarks/small/01/credit.txt +3 -0
  249. trunk/data/bookmarks/small/01/facebook.gif +0 -0
  250. trunk/data/bookmarks/small/01/google.gif +0 -0
  251. trunk/data/bookmarks/small/01/linkedin.gif +0 -0
  252. trunk/data/bookmarks/small/01/twitter.gif +0 -0
  253. trunk/data/bookmarks/small/02/credit.txt +3 -0
  254. trunk/data/bookmarks/small/02/facebook.png +0 -0
  255. trunk/data/bookmarks/small/02/google.png +0 -0
  256. trunk/data/bookmarks/small/02/linkedin.png +0 -0
  257. trunk/data/bookmarks/small/02/twitter.png +0 -0
  258. trunk/data/bookmarks/small/03/credit.txt +5 -0
  259. trunk/data/bookmarks/small/03/facebook.png +0 -0
  260. trunk/data/bookmarks/small/03/google.png +0 -0
  261. trunk/data/bookmarks/small/03/linkedin.png +0 -0
  262. trunk/data/bookmarks/small/03/twitter.png +0 -0
  263. trunk/data/bookmarks/small/04/credit.txt +5 -0
  264. trunk/data/bookmarks/small/04/facebook.png +0 -0
  265. trunk/data/bookmarks/small/04/google.png +0 -0
  266. trunk/data/bookmarks/small/04/linkedin.png +0 -0
  267. trunk/data/bookmarks/small/04/twitter.png +0 -0
  268. trunk/data/bookmarks/small/05/credit.txt +3 -0
  269. trunk/data/bookmarks/small/05/facebook.png +0 -0
  270. trunk/data/bookmarks/small/05/google.png +0 -0
  271. trunk/data/bookmarks/small/05/linkedin.png +0 -0
  272. trunk/data/bookmarks/small/05/twitter.png +0 -0
  273. trunk/data/bookmarks/small/06/credit.txt +3 -0
  274. trunk/data/bookmarks/small/06/facebook.png +0 -0
  275. trunk/data/bookmarks/small/06/google.png +0 -0
  276. trunk/data/bookmarks/small/06/linkedin.png +0 -0
  277. trunk/data/bookmarks/small/06/twitter.png +0 -0
  278. trunk/data/bookmarks/small/index.html +0 -0
  279. trunk/data/dividers/artcore-white.png +0 -0
  280. trunk/data/dividers/artcore.png +0 -0
  281. trunk/data/dividers/bar.png +0 -0
  282. trunk/data/dividers/business.png +0 -0
  283. trunk/data/dividers/business2.png +0 -0
  284. trunk/data/dividers/cafe.png +0 -0
  285. trunk/data/dividers/drop1.png +0 -0
  286. trunk/data/dividers/drop2.png +0 -0
  287. trunk/data/dividers/drop3.png +0 -0
  288. trunk/data/dividers/flashback.png +0 -0
  289. trunk/data/dividers/index.html +0 -0
  290. trunk/data/dividers/juicy.png +0 -0
  291. trunk/data/dividers/plus.png +0 -0
  292. trunk/data/dividers/school.png +0 -0
  293. trunk/data/dividers/sketchy.png +0 -0
  294. trunk/data/dividers/solid.jpg +0 -0
  295. trunk/data/dividers/vintage.png +0 -0
  296. trunk/data/index.html +0 -0
  297. trunk/data/themes/default/index.html +0 -0
  298. trunk/data/themes/default/screenshot.jpg +0 -0
  299. trunk/data/themes/default/style.css +48 -0
  300. trunk/data/themes/default/thumbnail.jpg +0 -0
  301. trunk/data/themes/index.html +0 -0
  302. trunk/docs/german-disclaimer.md +4 -0
  303. trunk/font/icon-email.eot +0 -0
  304. trunk/font/icon-email.svg +11 -0
  305. trunk/font/icon-email.ttf +0 -0
  306. trunk/font/icon-email.woff +0 -0
  307. trunk/helpers/articles.php +416 -0
  308. trunk/helpers/autonews.php +413 -0
  309. trunk/helpers/back.php +625 -0
  310. trunk/helpers/backloader.php +419 -0
  311. trunk/helpers/bookmarks.php +117 -0
  312. trunk/helpers/bounce.php +1110 -0
  313. trunk/helpers/campaigns.php +53 -0
  314. trunk/helpers/charts.php +66 -0
  315. trunk/helpers/conflicts.php +107 -0
  316. trunk/helpers/cron.php +201 -0
  317. trunk/helpers/dividers.php +65 -0
  318. trunk/helpers/email.php +170 -0
  319. trunk/helpers/encoding.php +40 -0
  320. trunk/helpers/file.php +223 -0
  321. trunk/helpers/form_engine.php +843 -0
  322. trunk/helpers/forms.php +242 -0
controllers/ajax/subscribers.php CHANGED
@@ -37,7 +37,9 @@ class WYSIJA_control_back_subscribers extends WYSIJA_control_front{
37
  $helperUser=WYSIJA::get('user','helper');
38
  if(!$helperUser->checkData($data))return false;
39
  if(!$helperUser->throttleRepeatedSubscriptions($data))return false;
40
- $helperUser->addSubscriber($data);
 
 
41
 
42
  return true;
43
  }
37
  $helperUser=WYSIJA::get('user','helper');
38
  if(!$helperUser->checkData($data))return false;
39
  if(!$helperUser->throttleRepeatedSubscriptions($data))return false;
40
+ if($helperUser->addSubscriber($data)) {
41
+ $helperUser->storeSubscriberIP();
42
+ }
43
 
44
  return true;
45
  }
controllers/front/subscribers.php CHANGED
@@ -44,7 +44,9 @@ class WYSIJA_control_front_subscribers extends WYSIJA_control_front{
44
  if(!$helperUser->checkData($data))return false;
45
  if(!$helperUser->throttleRepeatedSubscriptions()) return false;
46
 
47
- $helperUser->addSubscriber($data);
 
 
48
 
49
  return true;
50
  }
44
  if(!$helperUser->checkData($data))return false;
45
  if(!$helperUser->throttleRepeatedSubscriptions()) return false;
46
 
47
+ if($helperUser->addSubscriber($data)) {
48
+ $helperUser->storeSubscriberIP();
49
+ }
50
 
51
  return true;
52
  }
core/base.php CHANGED
@@ -19,7 +19,7 @@ class WYSIJA_object{
19
  * Static variable holding core MailPoet's version
20
  * @var array
21
  */
22
- static $version = '2.7.14';
23
 
24
  function __construct(){}
25
 
19
  * Static variable holding core MailPoet's version
20
  * @var array
21
  */
22
+ static $version = '2.7.15';
23
 
24
  function __construct(){}
25
 
helpers/update.php CHANGED
@@ -14,7 +14,7 @@ class WYSIJA_help_update extends WYSIJA_object {
14
  '2.3.3','2.3.4',
15
  '2.4', '2.4.1', '2.4.3','2.4.4',
16
  '2.5','2.5.2','2.5.5','2.5.9.6', '2.5.9.7',
17
- '2.6', '2.6.0.8', '2.6.15'
18
  );
19
  }
20
 
@@ -498,6 +498,27 @@ class WYSIJA_help_update extends WYSIJA_object {
498
  return true;
499
  break;
500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
  default:
502
  return false;
503
  }
14
  '2.3.3','2.3.4',
15
  '2.4', '2.4.1', '2.4.3','2.4.4',
16
  '2.5','2.5.2','2.5.5','2.5.9.6', '2.5.9.7',
17
+ '2.6', '2.6.0.8', '2.6.15', '2.7.15'
18
  );
19
  }
20
 
498
  return true;
499
  break;
500
 
501
+ case '2.7.15':
502
+ $queries = array();
503
+
504
+ // Subscriber IPs table.
505
+ $queries[] = 'CREATE TABLE IF NOT EXISTS `[wysija]subscriber_ips` ('.
506
+ '`ip` varchar(45) NOT NULL,'.
507
+ '`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,'.
508
+ 'PRIMARY KEY (`created_at`, `ip`),'.
509
+ 'KEY ip (`ip`)'.
510
+ ') /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/';
511
+
512
+ $errors = $this->run_update_queries( $queries );
513
+
514
+ if ( $errors ) {
515
+ $this->error( implode( $errors, "\n" ) );
516
+ return false;
517
+ }
518
+
519
+ return true;
520
+ break;
521
+
522
  default:
523
  return false;
524
  }
helpers/user.php CHANGED
@@ -386,29 +386,30 @@ class WYSIJA_help_user extends WYSIJA_object {
386
  }
387
 
388
  function throttleRepeatedSubscriptions() {
389
- $model_user = WYSIJA::get('user', 'model');
390
 
391
  $subscription_limit_enabled = apply_filters('wysija_subscription_limit_enabled', true);
392
 
393
- if ($subscription_limit_enabled && !is_user_logged_in()) {
394
- $subscription_limit_window = apply_filters('wysija_subscription_limit_window', DAY_IN_SECONDS);
395
- $subscription_limit_base = apply_filters('wysija_subscription_limit_base', MINUTE_IN_SECONDS);
 
396
 
397
- $subscriber_ip = $this->getIP();
398
  if (!empty($subscriber_ip)) {
399
- $subscription_count = $model_user->query(
400
  'get_row',
401
- 'SELECT COUNT(*) as row_count FROM ' . $model_user->getSelectTableName() . '
402
- WHERE `ip` = "' . $subscriber_ip . '" AND `created_at` >= (UNIX_TIMESTAMP() - ' . (int) $subscription_limit_window . ')'
403
  );
404
 
405
  if (isset($subscription_count['row_count']) && $subscription_count['row_count'] > 0) {
406
  $timeout = $subscription_limit_base * pow(2, $subscription_count['row_count'] - 1);
407
- $existing_user = $model_user->query(
408
  'get_row',
409
  'SELECT COUNT(*) as row_count
410
- FROM ' . $model_user->getSelectTableName() . '
411
- WHERE `ip` = "' . $subscriber_ip . '" AND `created_at` >= (UNIX_TIMESTAMP() - ' . (int) $timeout . ') LIMIT 1'
412
  );
413
  if (!empty($existing_user['row_count'])) {
414
  $this->error( sprintf(__( 'You need to wait %s seconds before subscribing again.' , WYSIJA ), $timeout) , true);
@@ -418,9 +419,29 @@ class WYSIJA_help_user extends WYSIJA_object {
418
  }
419
  }
420
 
 
 
 
 
 
 
421
  return true;
422
  }
423
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
  /**
425
  * send auto nl based on the params passed
426
  * @staticvar type $emails
@@ -1074,6 +1095,17 @@ class WYSIJA_help_user extends WYSIJA_object {
1074
  return strip_tags($ip);
1075
  }
1076
 
 
 
 
 
 
 
 
 
 
 
 
1077
  /**
1078
  * verify that an email string is valid
1079
  * @param string $email
386
  }
387
 
388
  function throttleRepeatedSubscriptions() {
389
+ $model_subscriber_ip = WYSIJA::get('subscriber_ip', 'model');
390
 
391
  $subscription_limit_enabled = apply_filters('wysija_subscription_limit_enabled', true);
392
 
393
+ $subscription_limit_window = apply_filters('wysija_subscription_limit_window', DAY_IN_SECONDS);
394
+ $subscription_limit_base = apply_filters('wysija_subscription_limit_base', MINUTE_IN_SECONDS);
395
+
396
+ $subscriber_ip = $this->getIPForThrottling();
397
 
398
+ if ($subscription_limit_enabled && !is_user_logged_in()) {
399
  if (!empty($subscriber_ip)) {
400
+ $subscription_count = $model_subscriber_ip->query(
401
  'get_row',
402
+ 'SELECT COUNT(*) as row_count FROM ' . $model_subscriber_ip->getSelectTableName() . '
403
+ WHERE `ip` = "' . $subscriber_ip . '" AND `created_at` >= NOW() - INTERVAL ' . (int) $subscription_limit_window . ' SECOND'
404
  );
405
 
406
  if (isset($subscription_count['row_count']) && $subscription_count['row_count'] > 0) {
407
  $timeout = $subscription_limit_base * pow(2, $subscription_count['row_count'] - 1);
408
+ $existing_user = $model_subscriber_ip->query(
409
  'get_row',
410
  'SELECT COUNT(*) as row_count
411
+ FROM ' . $model_subscriber_ip->getSelectTableName() . '
412
+ WHERE `ip` = "' . $subscriber_ip . '" AND `created_at` >= NOW() - INTERVAL ' . (int) $timeout . ' SECOND LIMIT 1'
413
  );
414
  if (!empty($existing_user['row_count'])) {
415
  $this->error( sprintf(__( 'You need to wait %s seconds before subscribing again.' , WYSIJA ), $timeout) , true);
419
  }
420
  }
421
 
422
+ // Purge old IP addresses
423
+ $model_subscriber_ip->query(
424
+ 'DELETE FROM ' . $model_subscriber_ip->getSelectTableName() . '
425
+ WHERE `created_at` < NOW() - INTERVAL ' . (int) $subscription_limit_window . ' SECOND'
426
+ );
427
+
428
  return true;
429
  }
430
 
431
+ function storeSubscriberIP() {
432
+ global $wpdb;
433
+
434
+ $model_subscriber_ip = WYSIJA::get('subscriber_ip', 'model');
435
+ $subscriber_ip = $this->getIPForThrottling();
436
+
437
+ if (!empty($subscriber_ip)) {
438
+ $wpdb->insert(
439
+ $model_subscriber_ip->getSelectTableName(),
440
+ array('ip' => $subscriber_ip)
441
+ );
442
+ }
443
+ }
444
+
445
  /**
446
  * send auto nl based on the params passed
447
  * @staticvar type $emails
1095
  return strip_tags($ip);
1096
  }
1097
 
1098
+ // More secure IP check
1099
+ function getIPForThrottling() {
1100
+ $ip = '';
1101
+
1102
+ if (!empty($_SERVER['REMOTE_ADDR']) AND strlen($_SERVER['REMOTE_ADDR']) > 6) {
1103
+ $ip = strip_tags($_SERVER['REMOTE_ADDR']);
1104
+ }//endif
1105
+
1106
+ return $ip;
1107
+ }
1108
+
1109
  /**
1110
  * verify that an email string is valid
1111
  * @param string $email
index.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: MailPoet 2
4
  Plugin URI: http://www.mailpoet.com/
5
  Description: Create and send newsletters or automated emails. Capture subscribers with a widget. Import and manage your lists. This version is being replaced by MailPoet 3. Support offered to Premium customers only. Updates are limited to security issues.
6
- Version: 2.7.14
7
  Author: MailPoet
8
  Author URI: http://www.mailpoet.com/
9
  License: GPLv2 or later
3
  Plugin Name: MailPoet 2
4
  Plugin URI: http://www.mailpoet.com/
5
  Description: Create and send newsletters or automated emails. Capture subscribers with a widget. Import and manage your lists. This version is being replaced by MailPoet 3. Support offered to Premium customers only. Updates are limited to security issues.
6
+ Version: 2.7.15
7
  Author: MailPoet
8
  Author URI: http://www.mailpoet.com/
9
  License: GPLv2 or later
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: wysija
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, signup, subscription, SMTP
4
  Requires at least: 3.5
5
  Tested up to: 4.8
6
- Stable tag: 2.7.14
7
  Send newsletters post notifications or autoresponders from WordPress easily, and beautifully. Start to capture subscribers with our widget now.
8
 
9
  == Description ==
@@ -113,6 +113,9 @@ Our [support site](https://www.mailpoet.com/support) has plenty of articles and
113
 
114
  == Changelog ==
115
 
 
 
 
116
  = 2.7.14 - 2017-10-23 =
117
  * Removed SWFUpload support
118
  * Fixed path for TinyMCE styles
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, signup, subscription, SMTP
4
  Requires at least: 3.5
5
  Tested up to: 4.8
6
+ Stable tag: 2.7.15
7
  Send newsletters post notifications or autoresponders from WordPress easily, and beautifully. Start to capture subscribers with our widget now.
8
 
9
  == Description ==
113
 
114
  == Changelog ==
115
 
116
+ = 2.7.15 - 2017-11-02 =
117
+ * Improved IP throttling to work independently of subscribers table (for robustness)
118
+  
119
  = 2.7.14 - 2017-10-23 =
120
  * Removed SWFUpload support
121
  * Fixed path for TinyMCE styles
sql/install.sql CHANGED
@@ -194,3 +194,12 @@ CREATE TABLE IF NOT EXISTS `custom_field` (
194
  `settings` text DEFAULT NULL,
195
  PRIMARY KEY (`id`)
196
  ) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;
 
 
 
 
 
 
 
 
 
194
  `settings` text DEFAULT NULL,
195
  PRIMARY KEY (`id`)
196
  ) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;
197
+
198
+ -- QUERY ---
199
+
200
+ CREATE TABLE IF NOT EXISTS `subscriber_ips` (
201
+ `ip` varchar(45) NOT NULL,
202
+ `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
203
+ PRIMARY KEY (`created_at`, `ip`),
204
+ KEY ip (`ip`)
205
+ ) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;
trunk/add-ons/add-ons-list.php ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * List of all add-ons available for MailPoet
5
+ */
6
+ function add_ons_list(){
7
+ $available_add_ons = array(
8
+ array(
9
+ 'name' => 'WooCommerce: Subscribe on Checkout',
10
+ 'search' => 'MailPoet WooCommerce Add-on',
11
+ 'thumbnail' => 'woocommerce.png',
12
+ 'description' => __( 'Add a checkbox on checkout page for your customers to subscribe to your MailPoet newsletters.', WYSIJA ),
13
+ 'plugin_url' => 'mailpoet-woocommerce-addon/mailpoet-woocommerce-addon.php',
14
+ 'version' => '1.0.2',
15
+ 'config_url' => 'admin.php?page=woocommerce_settings&tab=mailpoet',
16
+ 'official' => true,
17
+ 'on_wordpress.org' => true,
18
+ 'free' => true,
19
+ 'service' => false,
20
+ 'requires' => 'woocommerce/woocommerce.php',
21
+ 'requires_name' => 'WooCommerce',
22
+ ),
23
+
24
+ array(
25
+ 'name' => 'Autoresponders for WooCommerce Products',
26
+ 'search' => 'Autoresponders for WooCommerce Products',
27
+ 'thumbnail' => 'woocommerce.png',
28
+ 'description' => __( 'Decide which emails a new customer gets automatically, based on the product he just purchased. This a Premium add-on for WooCommerce.', WYSIJA ),
29
+ 'review' => '',
30
+ 'plugin_url' => '',
31
+ 'author_url' => 'http://clicky.me/woocommerce-autoresponder',
32
+ 'purchase_url' => 'http://clicky.me/woocommerce-autoresponder',
33
+ 'version' => '1.0.1',
34
+ 'official' => true,
35
+ 'on_wordpress.org' => false,
36
+ 'free' => false,
37
+ 'service' => false,
38
+ ),
39
+
40
+ array(
41
+ 'name' => 'Jigoshop: Subscribe on Checkout',
42
+ 'search' => 'MailPoet Jigoshop Add-on',
43
+ 'thumbnail' => 'jigoshop.png',
44
+ 'description' => __( 'Add a checkbox on checkout page for your customers to subscribe to your MailPoet newsletters.', WYSIJA ),
45
+ 'plugin_url' => 'mailpoet-jigoshop-addon/mailpoet-jigoshop-addon.php',
46
+ 'version' => '1.0.3',
47
+ 'config_url' => 'admin.php?page=jigoshop_settings&tab=mailpoet',
48
+ 'official' => true,
49
+ 'on_wordpress.org' => true,
50
+ 'free' => true,
51
+ 'service' => false,
52
+ 'requires' => 'jigoshop/jigoshop.php',
53
+ 'requires_name' => 'Jigoshop',
54
+ ),
55
+
56
+ array(
57
+ 'name' => 'Gravity Forms: Subscribe Add-on',
58
+ 'search' => 'MailPoet Gravity Forms Add-on',
59
+ 'thumbnail' => 'gravity-forms.png',
60
+ 'description' => __( 'Add a new field to add to your forms so your visitors can subscribe to your MailPoet newsletters.', WYSIJA ),
61
+ 'plugin_url' => 'mailpoet-gravity-forms-addon/mailpoet-gravity-forms-addon.php',
62
+ 'version' => '1.0.0',
63
+ 'official' => true,
64
+ 'on_wordpress.org' => true,
65
+ 'free' => true,
66
+ 'service' => false,
67
+ 'requires' => 'gravityforms/gravityforms.php',
68
+ 'requires_name' => 'Gravity Forms',
69
+ ),
70
+
71
+ array(
72
+ 'name' => 'WP e-Commerce: Subscribe on Checkout',
73
+ 'search' => 'MailPoet WP e-Commerce Add-on',
74
+ 'thumbnail' => 'wp-e-commerce.png',
75
+ 'description' => __( 'Add a checkbox on checkout page for your customers to subscribe to your MailPoet newsletters.', WYSIJA ),
76
+ 'plugin_url' => 'mailpoet-wp-ecommerce-addon/mailpoet-wp-ecommerce-addon.php',
77
+ 'version' => '1.0.0',
78
+ 'config_url' => 'edit.php?post_type=wpsc-product&page=mailpoet',
79
+ 'official' => true,
80
+ 'on_wordpress.org' => true,
81
+ 'free' => true,
82
+ 'service' => false,
83
+ 'requires' => 'wp-e-commerce/wp-shopping-cart.php',
84
+ 'requires_name' => 'WP e-Commerce',
85
+ ),
86
+
87
+ array(
88
+ 'name' => 'Restrict Content Pro: Registration Add-on',
89
+ 'search' => 'Restrict Content Pro Wysija',
90
+ 'thumbnail' => 'pippins.png',
91
+ 'description' => __( 'Add a checkbox on the registration form of this plugin so your new users join a list of your choice.', WYSIJA ),
92
+ 'plugin_url' => 'restrict-content-pro-wysija/rcp-wysija.php',
93
+ 'version' => '1.0',
94
+ 'official' => true,
95
+ 'on_wordpress.org' => true,
96
+ 'free' => true,
97
+ 'service' => false,
98
+ 'requires' => 'restrict-content-pro/restrict-content-pro.php',
99
+ 'requires_name' => 'Restrict Content Pro',
100
+ ),
101
+
102
+ array(
103
+ 'name' => 'Contact Form 7: MailPoet Add-on',
104
+ 'search' => 'MailPoet Contact Form 7',
105
+ 'thumbnail' => 'cf7.png',
106
+ 'description' => __( 'Add a checkbox in your forms, and choose which lists the user gets added to.', WYSIJA ),
107
+ 'plugin_url' => 'mailpoet-contact-form-7/mailpoet-contact-form-7.php',
108
+ 'author_url' => '',
109
+ 'version' => '1.0.0',
110
+ 'official' => true,
111
+ 'on_wordpress.org' => true,
112
+ 'free' => true,
113
+ 'service' => false,
114
+ 'requires' => 'contact-form-7/wp-contact-form-7.php',
115
+ 'requires_name' => 'Contact Form 7',
116
+ ),
117
+
118
+ array(
119
+ 'name' => 'WangGuard: MailPoet Connector',
120
+ 'search' => 'WangGuard Wysija Newsletter Connector',
121
+ 'thumbnail' => 'wangguard.png',
122
+ 'description' => __( 'Stop fake signups by robots with WangGuard, a free white listing service, and plugin.', WYSIJA ),
123
+ 'review' => __( 'If you have this problem, then this is your solution. Totally free too.', WYSIJA ),
124
+ 'plugin_url' => 'wangguard-wysija-newsletter-connector/wangguard-wysija.php',
125
+ 'author_url' => 'http://clicky.me/wangguard',
126
+ 'version' => '1.0.0',
127
+ 'official' => true,
128
+ 'on_wordpress.org' => true,
129
+ 'free' => true,
130
+ 'service' => false,
131
+ 'requires' => '',
132
+ ),
133
+
134
+ array(
135
+ 'name' => 'Leaky Paywall: MailPoet Add-on',
136
+ 'search' => 'Leaky Paywall: MailPoet Add-on',
137
+ 'thumbnail' => 'leakypw.png',
138
+ 'description' => __( 'Leaky Paywall is a Premium plugin to put content behind a paywall. This add-on manages your customers\' customers subscriptions.', WYSIJA ),
139
+ 'plugin_url' => 'leaky-paywall-mail-poet/issuem-leaky-paywall-mailpoet.php',
140
+ 'author_url' => 'http://clicky.me/leakypw',
141
+ 'version' => '1.0.0',
142
+ 'official' => true,
143
+ 'on_wordpress.org' => true,
144
+ 'free' => true,
145
+ 'service' => false,
146
+ ),
147
+
148
+ array(
149
+ 'name' => 'GetConversion: Bar and Box Forms Add-on',
150
+ 'search' => 'GC MailPoet EX',
151
+ 'thumbnail' => 'getconversion.png',
152
+ 'description' => __( 'Put a form in a top or bottom bar of your site, or in a nice box within your posts with GetConversion\'s free plugins. Connect them to MailPoet with this add-on.<br/></br>Get 30% off the Premium version of their add-on by clicking <a href="http://getconversion.com/products/gc-mailpoet-ex-pro/?coupon=MAILPOET">here</a>.', WYSIJA ),
153
+ 'review' => __( 'Try it yourself, we were impressed by the free versions.', WYSIJA ),
154
+ 'plugin_url' => 'gc-message-bar/main.php',
155
+ 'author_url' => 'http://clicky.me/GC-add-on',
156
+ 'version' => '1.0.0',
157
+ 'official' => true,
158
+ 'on_wordpress.org' => true,
159
+ 'free' => true,
160
+ 'service' => false,
161
+ ),
162
+
163
+ /* Below is the list of services that work with MailPoet */
164
+
165
+ array(
166
+ 'name' => 'OptinMonster: Slick Forms',
167
+ 'search' => 'OptinMonster: slick forms',
168
+ 'thumbnail' => 'optinmonster.png',
169
+ 'description' => __( 'Put a subscription form in a popup, footer bar or slide-in to add subscribers with this Premium plugin.', WYSIJA ),
170
+ 'review' => __( 'The authors have done a pretty awesome job.', WYSIJA ),
171
+ 'plugin_url' => '',
172
+ 'author_url' => 'http://clicky.me/optinmonsteraddon',
173
+ 'purchase_url' => '',
174
+ 'version' => '',
175
+ 'official' => false,
176
+ 'on_wordpress.org' => false,
177
+ 'free' => false,
178
+ 'service' => true,
179
+ 'premium_offer' => __( 'Premium users save 20% with this coupon: MP20', WYSIJA ),
180
+ ),
181
+
182
+ array(
183
+ 'name' => 'Pippity: Form in a Popup',
184
+ 'search' => 'Pippity: form in a popup',
185
+ 'thumbnail' => 'pippity.png',
186
+ 'description' => __( 'This Premium plugin allows you to add a MailPoet form in a popup.', WYSIJA ),
187
+ 'review' => __( 'You\'ll need to know CSS to design it to your taste.', WYSIJA ),
188
+ 'plugin_url' => '',
189
+ 'author_url' => 'http://clicky.me/pippity',
190
+ 'purchase_url' => '',
191
+ 'version' => '',
192
+ 'official' => false,
193
+ 'on_wordpress.org' => false,
194
+ 'free' => false,
195
+ 'service' => true,
196
+ 'premium_offer' => __( 'Premium users save 25% with this coupon: mailpoet25', WYSIJA ),
197
+ ),
198
+
199
+
200
+ array(
201
+ 'name' => 'Hybrid Connect: Forms and Facebook',
202
+ 'search' => 'Hybrid Connect: forms and Facebook',
203
+ 'thumbnail' => 'hybrid-connect.png',
204
+ 'description' => __( 'This Premium plugin allows you to add MailPoet\'s forms in many places, and in Facebook.', WYSIJA ),
205
+ 'review' => __( 'Very powerful, if not a quirky user interface.', WYSIJA ),
206
+ 'plugin_url' => '',
207
+ 'author_url' => 'http://clicky.me/hybrid-connect',
208
+ 'purchase_url' => '',
209
+ 'version' => '',
210
+ 'official' => false,
211
+ 'on_wordpress.org' => false,
212
+ 'free' => false,
213
+ 'service' => true,
214
+ 'premium_offer' => '',
215
+ ),
216
+
217
+ array(
218
+ 'name' => 'Magic Action Box: Pretty forms in post',
219
+ 'search' => 'Magic Action Box: pretty forms in post',
220
+ 'thumbnail' => 'magic-action-box.png',
221
+ 'description' => __( 'This free plugin allows you to design and position a form at the beginning or bottom of a post.', WYSIJA ),
222
+ 'review' => __( 'It\'s free, and has proven popular with our users.', WYSIJA ),
223
+ 'plugin_url' => '',
224
+ 'author_url' => 'http://clicky.me/magic-action-box',
225
+ 'purchase_url' => '',
226
+ 'version' => '',
227
+ 'official' => false,
228
+ 'on_wordpress.org' => false,
229
+ 'free' => false,
230
+ 'service' => true,
231
+ 'premium_offer' => '',
232
+ ),
233
+
234
+ array(
235
+ 'name' => 'wBounce: Exit popup forms',
236
+ 'search' => 'wBounce',
237
+ 'thumbnail' => 'wbounce-forms.jpg',
238
+ 'description' => __( 'Exit popups are not only "in vogue", they are provably increasing conversions and therefore boost marketing, signups and sales. wBounce displays an inline popup before the user leaves your site.', WYSIJA ),
239
+ 'review' => __( 'Exit popup will appear when your cursor leaves the window.', WYSIJA ),
240
+ 'plugin_url' => 'wbounce/wbounce.php',
241
+ 'author_url' => 'http://clicky.me/wbounce',
242
+ 'version' => '1.4',
243
+ 'official' => true,
244
+ 'on_wordpress.org' => true,
245
+ 'free' => true,
246
+ 'service' => false,
247
+ 'requires' => '',
248
+ ),
249
+ array(
250
+ 'name' => 'Optin Revolution: Popup form',
251
+ 'search' => 'Optin Revolution: popup form',
252
+ 'thumbnail' => 'optin-revolution.png',
253
+ 'description' => __( 'This free plugin allows you to put a form in a popup, that\'s it.', WYSIJA ),
254
+ 'review' => __( 'This is the free version of a more powerful Premium version.', WYSIJA ),
255
+ 'plugin_url' => '',
256
+ 'author_url' => 'http://clicky.me/optin-revolution',
257
+ 'purchase_url' => '',
258
+ 'version' => '',
259
+ 'official' => false,
260
+ 'on_wordpress.org' => false,
261
+ 'free' => false,
262
+ 'service' => true,
263
+ 'premium_offer' => '',
264
+ ),
265
+
266
+ array(
267
+ 'name' => 'Ultimate Coming Soon Page',
268
+ 'search' => 'Ultimate Coming Soon Page',
269
+ 'thumbnail' => 'ultimate-coming-soon.png',
270
+ 'description' => __( 'Your new site is not yet launched? Put a coming soon page with a form to capture emails with this Premium plugin.', WYSIJA ),
271
+ 'review' => __( 'A well designed plugin for a simple idea.', WYSIJA ),
272
+ 'plugin_url' => '',
273
+ 'author_url' => 'http://clicky.me/coming-soon',
274
+ 'purchase_url' => '',
275
+ 'version' => '',
276
+ 'official' => false,
277
+ 'on_wordpress.org' => false,
278
+ 'free' => false,
279
+ 'service' => true,
280
+ 'premium_offer' => __( 'Premium users save 20% with this coupon: MAILPOET20', WYSIJA ),
281
+ ),
282
+
283
+ array(
284
+ 'name' => 'Plugmatter: form below your header',
285
+ 'search' => 'Plugmatter',
286
+ 'thumbnail' => 'plugmatter.png',
287
+ 'description' => __( 'This Premium plugin allows you to put a pretty form right below the header. Nothing more, nothing less.', WYSIJA ),
288
+ 'review' => '',
289
+ 'plugin_url' => '',
290
+ 'author_url' => 'http://clicky.me/plugmatter',
291
+ 'purchase_url' => '',
292
+ 'version' => '',
293
+ 'official' => false,
294
+ 'on_wordpress.org' => false,
295
+ 'free' => false,
296
+ 'service' => true,
297
+ 'premium_offer' => '',
298
+ ),
299
+
300
+ array(
301
+ 'name' => 'EDD: MailPoet: Subscribe on Checkout',
302
+ 'search' => 'Easy Digital Downloads - MailPoet',
303
+ 'thumbnail' => 'easy-digital-downloads.png',
304
+ 'description' => __( 'A checkbox is added as option for your customers to signup for your newsletter while purchasing from your digital store.', WYSIJA ),
305
+ 'review' => '',
306
+ 'plugin_url' => '',
307
+ 'author_url' => 'http://clicky.me/easy-digital-downloads',
308
+ 'purchase_url' => 'http://clicky.me/easy-digital-downloads',
309
+ 'version' => '1.1.2',
310
+ 'official' => false,
311
+ 'on_wordpress.org' => false,
312
+ 'free' => false,
313
+ 'service' => false,
314
+ 'requires' => 'easy-digital-downloads/easy-digital-downloads.php',
315
+ 'requires_name' => 'Easy Digital Downloads',
316
+ 'premium_offer' => '',
317
+ ),
318
+
319
+ array(
320
+ 'name' => 'Ninja Forms: Subscribe Add-on',
321
+ 'search' => 'Ninja Forms: Subscribe Add-on',
322
+ 'thumbnail' => 'ninja-forms.png',
323
+ 'description' => __( 'Quickly create newsletter signup forms for your MailPoet mailing lists using the power and flexibility that Ninja Forms provides.', WYSIJA ),
324
+ 'review' => '',
325
+ 'plugin_url' => 'ninja-forms-mailpoet/nf-mailpoet.php',
326
+ 'author_url' => 'http://clicky.me/ninja-forms',
327
+ 'purchase_url' => 'http://clicky.me/ninja-forms',
328
+ 'version' => '1.0.1',
329
+ 'official' => false,
330
+ 'on_wordpress.org' => false,
331
+ 'free' => true,
332
+ 'service' => false,
333
+ 'requires' => 'ninja-forms/ninja-forms.php',
334
+ 'requires_name' => 'Ninja Forms',
335
+ 'premium_offer' => '',
336
+ ),
337
+
338
+ array(
339
+ 'name' => 'Multilingual Press',
340
+ 'search' => 'Multilingual Press',
341
+ 'thumbnail' => 'multilingual-press.jpg',
342
+ 'description' => __( 'We recommend this plugin as the good alternative to WPML for multilingual sites. It\'s lean, straightforward, and leaves your site\'s core largely untouched. Each language has its own site in your WordPress Multisite install. Works great with MailPoet.', WYSIJA ),
343
+ 'review' => '',
344
+ 'plugin_url' => 'multilingual-press/multilingual-press.php',
345
+ 'author_url' => 'http://clicky.me/multilingual-press',
346
+ 'purchase_url' => 'http://clicky.me/multilingual-press',
347
+ 'version' => '2.0.3',
348
+ 'official' => true,
349
+ 'on_wordpress.org' => true,
350
+ 'free' => true,
351
+ 'service' => false,
352
+ 'requires' => 'multilingual-press/multilingual-press.php',
353
+ 'requires_name' => 'Multilingual Press',
354
+ 'premium_offer' => '',
355
+ ),
356
+ );
357
+
358
+ return $available_add_ons;
359
+ }
trunk/add-ons/add-ons.php ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ){
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ class MailPoet_Add_ons {
7
+ /**
8
+ * Constructor
9
+ */
10
+ public function __construct(){
11
+ $this->plugin_path = WYSIJA_DIR;
12
+ $this->wp_plugin_path = str_replace( 'wysija-newsletters', '', $this->plugin_path );
13
+ $this->plugin_url = WYSIJA_URL;
14
+ $this->image_url = '//ps.w.org/wysija-newsletters/assets/add-ons/';
15
+
16
+ $this->mailpoet_add_on_activated_notice();
17
+ $this->mailpoet_add_on_deactivated_notice();
18
+ }
19
+
20
+ /**
21
+ * Runs when the plugin is initialized.
22
+ */
23
+ public function init_mail_poet_add_ons(){
24
+ // Load JavaScript and stylesheets.
25
+ $this->register_scripts_and_styles();
26
+ }
27
+
28
+ /**
29
+ * Registers and enqueues stylesheets for the
30
+ * administration panel and the public facing site.
31
+ */
32
+ public function register_scripts_and_styles(){
33
+ if ( is_admin() ) {
34
+ wp_register_style( 'mail_poet_add_ons', WYSIJA_URL . 'css/add-ons.css' );
35
+ wp_enqueue_style( 'mail_poet_add_ons' );
36
+ } // end if
37
+ } // end register_scripts_and_styles
38
+
39
+ /**
40
+ * This notifies the user that the add-on plugin
41
+ * is now activated and returns them back to the
42
+ * add-ons page.
43
+ */
44
+ public function mailpoet_add_on_activated_notice(){
45
+ global $current_screen;
46
+
47
+ require_once(ABSPATH.'/wp-admin/includes/plugin.php');
48
+
49
+ if ( isset($_GET['action'] ) && $_GET['action'] == 'activate' && isset( $_GET['module'] ) ) {
50
+
51
+ $plugin = plugin_basename( $_GET['module'] );
52
+ $plugin_data = get_plugin_data( $this->wp_plugin_path . $plugin );
53
+
54
+ $plugin_name = esc_attr( str_replace( ' ', '_', $plugin_data['Name'] ) );
55
+ $plugin_name = esc_attr( str_replace( '&#039;', '_', $plugin_name ) );
56
+
57
+ if ( isset( $_GET['requires'] ) ) {
58
+ if ( file_exists( $this->wp_plugin_path . plugin_basename( $_GET['requires'] ) ) ) {
59
+ if ( ! WYSIJA::is_plugin_active( $_GET['requires'] ) ) {
60
+ $location = admin_url( 'admin.php?page=wysija_config&status=not-activated&add-on=' . $plugin_name . '&requires=' . esc_attr( str_replace( ' ', '_', $_GET['requires_name'] ) ) . '#tab-add-ons' );
61
+ wp_safe_redirect( $location );
62
+ exit;
63
+ }
64
+ } else {
65
+ $location = admin_url( 'admin.php?page=wysija_config&status=not-installed&add-on=' . $plugin_name . '&requires=' . esc_attr( str_replace( ' ', '_', $_GET['requires_name'] ) ) . '#tab-add-ons' );
66
+ wp_safe_redirect( $location );
67
+ exit;
68
+ }
69
+ }
70
+
71
+ // Activate the add-on plugin.
72
+ activate_plugin( $plugin );
73
+
74
+ // Return back to add-on page.
75
+ $location = admin_url( 'admin.php?page=wysija_config&status=activated&add-on=' . $plugin_name . '#tab-add-ons' );
76
+ wp_safe_redirect( $location );
77
+ exit;
78
+ }
79
+
80
+ /**
81
+ * Display message if the plugin was not able to activate due
82
+ * to a required plugin is not active first.
83
+ */
84
+ if ( $current_screen->parent_base == 'wysija_campaigns' && isset( $_GET['status'] ) && $_GET['status'] == 'not-activated' || isset( $_GET['status'] ) && $_GET['status'] == 'not-installed' ){
85
+ echo
86
+ '<div id="message" class="error fade" style="display:block !important;">' .
87
+ '<p>' .
88
+ '<strong>' . esc_attr( str_replace( '_', ' ', $_GET['add-on'] ) ) . '</strong> ' .
89
+ wp_kses( sprintf(
90
+ __( 'was not activated as it requires <strong><a href="%s">%s</a></strong> to be installed and active first.', WYSIJA ),
91
+ esc_url( admin_url( 'plugin-install.php?tab=search&type=term&s=' . esc_attr( strtolower( str_replace( ' ', '+', $_GET['requires'] ) ) ) ) ),
92
+ str_replace( '_', ' ', $_GET['requires'] )
93
+ ), array( 'a' => array( 'href' => array() ), 'strong' => array(), 'b' => array(), 'em' => array() ) ) .
94
+ ' <input type="button" class="button" value="' . esc_attr__( 'Hide this message', WYSIJA ) . '" onclick="document.location.href=\'' . esc_url( admin_url( 'admin.php?page=wysija_config#tab-add_ons' ) ) . '\';">' .
95
+ '</p>' .
96
+ '</div>';
97
+ }
98
+
99
+ // Display message once the add-on has been activated.
100
+ if ( $current_screen->parent_base == 'wysija_campaigns' && isset( $_GET['status'] ) && $_GET['status'] == 'activated' ){
101
+ echo '<div id="message" class="updated fade" style="display:block !important;"><p><strong>' . esc_attr( str_replace( '_', ' ', $_GET['add-on'] ) ) . '</strong> ' . esc_attr__( 'has been activated.', WYSIJA ) . '</p></div>';
102
+ }
103
+ }
104
+
105
+ /**
106
+ * This notifies the user that the add-on plugin
107
+ * is now deactivated and returns them back to the
108
+ * add-ons page.
109
+ */
110
+ public function mailpoet_add_on_deactivated_notice(){
111
+ global $current_screen;
112
+
113
+ require_once ABSPATH . '/wp-admin/includes/plugin.php';
114
+
115
+ if ( isset( $_GET['action'] ) && $_GET['action'] == 'deactivate' && isset( $_GET['module'] ) ) {
116
+ $plugin = plugin_basename( $_GET['module'] );
117
+ $plugin_data = get_plugin_data( $this->wp_plugin_path . $plugin );
118
+
119
+ // Deactivate the add-on plugin.
120
+ deactivate_plugins( $plugin );
121
+
122
+ // Return back to add-on page.
123
+ $location = admin_url( 'admin.php?page=wysija_config&status=deactivated&add-on=' . esc_html( str_replace( ' ', '_', $plugin_data['Name'] ) ) . '#tab-add-ons' );
124
+ wp_safe_redirect( $location );
125
+ exit;
126
+ }
127
+
128
+ // Display message once the add-on has been deactivated.
129
+ if ( $current_screen->parent_base == 'wysija_campaigns' && isset( $_GET['status'] ) && $_GET['status'] == 'deactivated' ) {
130
+ echo '<div id="message" class="updated fade" style="display:block !important;"><p><strong>' . esc_attr( str_replace( '_', ' ', $_GET['add-on'] ) ) . '</strong> ' . esc_attr__( 'has been de-activated.', WYSIJA ) . '</p></div>';
131
+ }
132
+
133
+ }
134
+
135
+ /**
136
+ * Displays the add ons page and lists
137
+ * the plugins and services available.
138
+ */
139
+ public function add_ons_page(){
140
+ require_once WYSIJA_DIR . '/add-ons/add-ons-list.php';
141
+
142
+ echo '<div class="module-container">';
143
+ foreach ( add_ons_list() as $plugin => $product ){
144
+ $status = ''; // Status class.
145
+
146
+ /**
147
+ * Queries if the plugin is installed,
148
+ * active and meets the requirements
149
+ * it requires if any.
150
+ */
151
+ if ( file_exists( $this->wp_plugin_path . plugin_basename( $product['plugin_url'] ) ) ) {
152
+ $status .= ' installed';
153
+ } else {
154
+ $status .= ' not-installed';
155
+ }
156
+
157
+ if ( WYSIJA::is_plugin_active( $product['plugin_url'] ) ) {
158
+ $status .= ' active';
159
+ } else {
160
+ $status .= ' inactive';
161
+ }
162
+
163
+ if ( empty( $product['requires'] ) ) {
164
+ $status .= ' ready';
165
+ } elseif ( ! empty( $product['requires'] ) && file_exists( $this->wp_plugin_path . plugin_basename( $product['requires'] ) ) ) {
166
+ $status .= ' ready';
167
+ if ( WYSIJA::is_plugin_active( $product['requires'] ) ) {
168
+ $status .= ' ready';
169
+ } else {
170
+ $status .= ' not-ready';
171
+ }
172
+ } elseif ( ! empty( $product['requires'] ) && ! file_exists( $this->wp_plugin_path . plugin_basename( $product['requires'] ) ) ) {
173
+ $status .= ' not-ready';
174
+ }
175
+
176
+ if ( WYSIJA::is_plugin_active( 'wysija-newsletters-premium/index.php' ) ) {
177
+ $status .= ' premium-active';
178
+ }
179
+
180
+ echo
181
+ '<div class="mailpoet-module' . esc_attr( $status ) . '" id="product">' .
182
+ '<h3>' . esc_attr( $product['name'] ) . '</h3>';
183
+
184
+ if ( ! empty( $product['thumbnail'] ) ) {
185
+ echo '<div class="mailpoet-module-image"><img src="' . esc_url( $this->image_url . $product['thumbnail'] ) . '" width="100%" title="' . esc_attr( $product['name'] ) . '" alt=""></div>';
186
+ }
187
+
188
+ echo
189
+ '<div class="mailpoet-module-content">' .
190
+ '<div class="mailpoet-module-description">' .
191
+ '<p>' . wp_kses( $product['description'], array() ) . '</p>';
192
+
193
+ if ( ! empty( $product['review'] ) ) {
194
+ echo '<p><strong>' . esc_attr__( 'MailPoet says: ', WYSIJA ) . '<em>' . esc_attr( $product['review'] ) . '</em>' . '</strong></p>';
195
+ }
196
+
197
+ if ( WYSIJA::is_plugin_active( 'wysija-newsletters-premium/index.php' ) && ! empty( $product['premium_offer'] ) ) {
198
+ echo '<p><strong>' . esc_attr( $product['premium_offer'] ) . '</strong></p>';
199
+ }
200
+ echo
201
+ '</div>' .
202
+ '</div>' .
203
+
204
+ '<div class="mailpoet-module-actions">';
205
+
206
+ if ( ! empty( $product['author_url'] ) ) {
207
+ echo '<a href="' . esc_url( $product['author_url'] ) . '" target="_blank" rel="external" class="button-primary website">' . esc_attr__( 'Website', WYSIJA ) . '</a>&nbsp;';
208
+ }
209
+
210
+ if ( $product['free'] == false && ! empty( $product['purchase_url'] ) ) {
211
+ if ( ! empty( $product['plugin_url'] ) && ! file_exists( $this->wp_plugin_path . plugin_basename( $product['plugin_url'] ) ) ) {
212
+ echo '<a href="' . esc_url( $product['purchase_url'] ) . '" target="_blank" rel="external" class="button-primary purchase">' . esc_attr__( 'Purchase', WYSIJA ) . '</a>&nbsp;';
213
+ } // end if plugin is installed, don't show purchase button.
214
+ } // end if product is not free.
215
+
216
+ if ( $product['service'] == false ){
217
+ if ( $product['on_wordpress.org'] == true ){
218
+ if ( ! file_exists( $this->wp_plugin_path . plugin_basename( $product['plugin_url'] ) ) ) {
219
+ echo '<a href="' . esc_url( admin_url( 'plugin-install.php?tab=search&type=term&s=' . strtolower( str_replace( ' ', '+', $product['search'] ) ) ) ) . '" class="button-primary install">' . esc_attr__( 'Install from WordPress.org', WYSIJA ) . '</a>&nbsp;';
220
+ }
221
+ } // end if $product['on_wordpress.org'];
222
+
223
+ if ( ! empty( $product['plugin_url'] ) && file_exists( $this->wp_plugin_path . plugin_basename( $product['plugin_url'] ) ) ) {
224
+ if ( ! WYSIJA::is_plugin_active( $product['plugin_url'] ) ) {
225
+ if ( ! empty( $product['requires'] ) ) {
226
+ $requires = '&amp;requires=' . $product['requires'] . '&amp;requires_name=' . $product['requires_name'];
227
+ } else {
228
+ $requires = '';
229
+ }
230
+ echo '<a href="' . esc_url( admin_url( 'admin.php?page=wysija_config&amp;action=activate&amp;module=' . $product['plugin_url'] . $requires ) ) . '" class="button-primary activate">' . esc_attr__( 'Activate', WYSIJA ) . '</a>&nbsp;';
231
+ } else {
232
+ if ( ! empty( $product['config_url'] ) ) {
233
+ echo '<a href="' . esc_url( $product['config_url'] ) . '" class="mailpoet-configure-button button-secondary">' . esc_attr__( 'Configure', WYSIJA ) . '</a>';
234
+ }
235
+ }
236
+ }
237
+ }
238
+
239
+ echo
240
+ '</div>' .
241
+ '</div>';
242
+ } // end if local is yes.
243
+
244
+ echo
245
+ '<div class="submit-idea">' .
246
+ '<p>' . wp_kses( sprintf( __( 'Don\'t see the add-on you\'re looking for? <a href="%s">Submit it</a> in our contact form.', WYSIJA ), 'http://www.mailpoet.com/contact/" target="blank' ), array( 'a' => array( 'href' => array() ) ) ) . '</p>' .
247
+ '</div>' .
248
+ '</div>';
249
+ }
250
+ } // end class
251
+
252
+ /**
253
+ * This loads the add ons class and displays the page.
254
+ *
255
+ * @init_mail_poet_add_ons();
256
+ * @add_ons_page();
257
+ */
258
+ function load_add_ons_manager(){
259
+ $mailpoet_add_ons = new MailPoet_Add_ons();
260
+ $mailpoet_add_ons->init_mail_poet_add_ons();
261
+ $mailpoet_add_ons->add_ons_page();
262
+ }
263
+ load_add_ons_manager();
trunk/add-ons/index.html ADDED
File without changes
trunk/classes/WJ_Analytics.php ADDED
@@ -0,0 +1,899 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /*
4
+ Class Analytics.
5
+ It's a sort of useful stats and numbers generator about MailPoet usage.
6
+ It also handles the MixPanel integration.
7
+ $analytics = new WJ_Analytics();
8
+ $analytics->generate_data();
9
+ $analytics->send();
10
+ */
11
+ class WJ_Analytics {
12
+
13
+ // All analytics data to be sent to JS.
14
+ private $analytics_data = array(
15
+ 'php_version' => array(
16
+ 'label' => 'PHP version',
17
+ 'value' => ''
18
+ ),
19
+ 'monthly_emails_sent' => array(
20
+ 'label' => 'Monthly emails sent',
21
+ 'value' => ''
22
+ ),
23
+ 'lists_with_more_than_25' => array(
24
+ 'label' => 'Lists with more than 25 subscribers',
25
+ 'value' => ''
26
+ ),
27
+ 'confirmed_subscribers' => array(
28
+ 'label' => 'Confirmed subscribers',
29
+ 'value' => ''
30
+ ),
31
+ 'range_confirmed_subscribers' => array(
32
+ 'label' => 'Range Confirmed subscribers',
33
+ 'value' => ''
34
+ ),
35
+ 'unconfirmed_subscribers' => array(
36
+ 'label' => 'Unconfirmed subscribers',
37
+ 'value' => ''
38
+ ),
39
+ 'standard_newsletters' => array(
40
+ 'label' => 'Standard newsletters',
41
+ 'value' => ''
42
+ ),
43
+ 'auto_newsletters' => array(
44
+ 'label' => 'Auto newsletters',
45
+ 'value' => ''
46
+ ),
47
+ 'wordpress_version' => array(
48
+ 'label' => 'WordPress Version',
49
+ 'value' => ''
50
+ ),
51
+ 'plugin_version' => array(
52
+ 'label' => 'Plugin Version',
53
+ 'value' => ''
54
+ ),
55
+ 'license_type' => array(
56
+ 'label' => 'License type',
57
+ 'value' => ''
58
+ ),
59
+ 'sending_method' => array(
60
+ 'label' => 'Sending method',
61
+ 'value' => ''
62
+ ),
63
+ 'smtp_hostname' => array(
64
+ 'label' => 'Smtp hostname',
65
+ 'value' => ''
66
+ ),
67
+ 'activation_email_status' => array(
68
+ 'label' => 'Activation Email',
69
+ 'value' => ''
70
+ ),
71
+ 'average_open_rate' => array(
72
+ 'label' => 'Open rate',
73
+ 'value' => ''
74
+ ),
75
+ 'average_click_rate' => array(
76
+ 'label' => 'Click rate',
77
+ 'value' => ''
78
+ ),
79
+ 'industry' => array(
80
+ 'label' => 'Industry',
81
+ 'value' => ''
82
+ ),
83
+ 'wordpress_language' => array(
84
+ 'label' => 'WordPress Language',
85
+ 'value' => ''
86
+ ),
87
+ 'rtl' => array(
88
+ 'label' => 'Rtl',
89
+ 'value' => ''
90
+ ),
91
+ 'beta' => array(
92
+ 'label' => 'Beta',
93
+ 'value' => ''
94
+ ),
95
+ 'archive_page' => array(
96
+ 'label' => 'Archive Page',
97
+ 'value' => ''
98
+ ),
99
+ 'dkim_status' => array(
100
+ 'label' => 'DKIM Active',
101
+ 'value' => ''
102
+ ),
103
+ 'subscribe_in_comments' => array(
104
+ 'label' => 'Subscribe in comments',
105
+ 'value' => ''
106
+ ),
107
+ 'subscribe_on_register' => array(
108
+ 'label' => 'Subscribe on registration',
109
+ 'value' => ''
110
+ ),
111
+ 'browser_link' => array(
112
+ 'label' => 'View in browser link',
113
+ 'value' => ''
114
+ ),
115
+ 'profile_edit'=> array(
116
+ 'label' => 'Subcsribers can edit profile',
117
+ 'value' => ''
118
+ ),
119
+ 'html_edit' => array(
120
+ 'label' => 'Allow HTML edit',
121
+ 'value' => ''
122
+ ),
123
+ 'mailpoet_cron' => array(
124
+ 'label' => 'MailPoet Cron Enabled',
125
+ 'value' => ''
126
+ ),
127
+ 'forms_number' => array(
128
+ 'label' => 'Total number of forms',
129
+ 'value' => ''
130
+ ),
131
+ 'using_custom_fields' => array(
132
+ 'label' => 'Using custom fields',
133
+ 'value' => ''
134
+ ),
135
+ 'custom_fields_input' => array(
136
+ 'label' => 'Custom Fields: Input field',
137
+ 'value' => ''
138
+ ),
139
+ 'custom_fields_textarea' => array(
140
+ 'label' => 'Custom Fields: Textarea',
141
+ 'value' => ''
142
+ ),
143
+ 'custom_fields_select' => array(
144
+ 'label' => 'Custom Fields: Select',
145
+ 'value' => ''
146
+ ),
147
+ 'custom_fields_checkbox' => array(
148
+ 'label' => 'Custom Fields: Checkbox',
149
+ 'value' => ''
150
+ ),
151
+ 'custom_fields_radio' => array(
152
+ 'label' => 'Custom Fields: Radio',
153
+ 'value' => ''
154
+ ),
155
+ 'active_last_week' => array(
156
+ 'label' => 'Active last week',
157
+ 'value' => ''
158
+ ),
159
+ 'is_multisite' => array(
160
+ 'label' => 'Using Multisite',
161
+ 'value' => ''
162
+ ),
163
+ 'bounce_enabled' => array(
164
+ 'label' => 'Using bounce',
165
+ 'value' => ''
166
+ )
167
+ );
168
+
169
+ function __construct() {
170
+ }
171
+
172
+ /**
173
+ * Send data to Mixpanel by enqueuing the analytics JS file.
174
+ * @return
175
+ */
176
+ public function send() {
177
+
178
+ // Enqueue analytics Javascript.
179
+ wp_enqueue_script('analytics', WYSIJA_URL . 'js/analytics.js', array(), WYSIJA::get_version());
180
+ // Make analytics data available in JS.
181
+ wp_localize_script('analytics', 'analytics_data', $this->analytics_data);
182
+ }
183
+
184
+ /**
185
+ * Generate fresh data and store it in the $analytics_data Class property.
186
+ * @return
187
+ */
188
+ public function generate_data() {
189
+
190
+ foreach ($this->analytics_data as $key => $data) {
191
+ $method = $key;
192
+ $this->analytics_data[$key]['value'] = call_user_func(array($this, $method));
193
+ }
194
+
195
+ }
196
+
197
+ /**
198
+ * Calculate Emails sent in the last 30 days.
199
+ * @return Int
200
+ */
201
+ private function monthly_emails_sent() {
202
+
203
+ $model_email_user_stat = WYSIJA::get('email_user_stat', 'model');
204
+ $query = 'SELECT COUNT(*) as total_emails
205
+ FROM ' . '[wysija]' . $model_email_user_stat->table_name . '
206
+ WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= sent_at';
207
+ $result = $model_email_user_stat->query('get_res', $query);
208
+
209
+ $total_emails = $result[0]['total_emails'];
210
+ switch (true) {
211
+ case ($total_emails <= 1000):
212
+ $track = 'Less than 1000';
213
+ break;
214
+ case ((1001 <= $total_emails) && ($total_emails <= 2500)):
215
+ $track = '1001 to 2500';
216
+ break;
217
+ case ((2501 <= $total_emails) && ($total_emails <= 5000)):
218
+ $track = '2501 to 5000';
219
+ break;
220
+ case ((5001 <= $total_emails) && ($total_emails <= 10000)):
221
+ $track = '5001 to 10000';
222
+ break;
223
+ case ((10001 <= $total_emails) && ($total_emails <= 25000)):
224
+ $track = '10001 to 25000';
225
+ break;
226
+ case ((25001 <= $total_emails) && ($total_emails <= 50000)):
227
+ $track = '25001 to 50000';
228
+ break;
229
+ case ((50001 <= $total_emails) && ($total_emails <= 100000)):
230
+ $track = '50001 to 100000';
231
+ break;
232
+ case (100001 <= $total_emails):
233
+ $track = 'More than 100001';
234
+ break;
235
+ default:
236
+ $track = 'No emails sent';
237
+ break;
238
+ }
239
+
240
+ return $track;
241
+
242
+ }
243
+
244
+ /*
245
+ Pass through the WordPress version.
246
+ */
247
+ private function wordpress_version() {
248
+ return get_bloginfo('version');
249
+ }
250
+
251
+ /*
252
+ Pass through the WordPress language.
253
+ */
254
+ private function wordpress_language() {
255
+ return get_bloginfo('language');
256
+ }
257
+
258
+ /*
259
+ The plugin version.
260
+ */
261
+ private function plugin_version() {
262
+ return WYSIJA::get_version();
263
+ }
264
+
265
+ /**
266
+ * Calculate lists with more than 25 subscribers.
267
+ * @return Int
268
+ */
269
+ private function lists_with_more_than_25() {
270
+
271
+ $model_user_list = WYSIJA::get('user_list', 'model');
272
+ $query = 'SELECT list_id, COUNT(*) as count
273
+ FROM ' . '[wysija]' . $model_user_list->table_name . '
274
+ GROUP BY list_id
275
+ HAVING COUNT(*) >= 25';
276
+ $result = $model_user_list->query('get_res', $query);
277
+ $lists_count = count($result);
278
+
279
+ return $lists_count;
280
+ }
281
+
282
+ /**
283
+ * Calculate total subscribers.
284
+ * @return Int
285
+ */
286
+ private function total_subcsribers() {
287
+
288
+ $model_user = WYSIJA::get('user', 'model');
289
+ $query = 'SELECT COUNT(*) as total_subscribers
290
+ FROM ' . '[wysija]' . $model_user->table_name;
291
+ $result = $model_user->query('get_res', $query);
292
+
293
+ return $result[0]['total_subscribers'];
294
+ }
295
+
296
+ /**
297
+ * Calculate confirmed subscribers.
298
+ * @return Int
299
+ */
300
+ private function confirmed_subscribers() {
301
+
302
+ $model_user = WYSIJA::get('user', 'model');
303
+ $query = 'SELECT COUNT(*) as confirmed_subscribers
304
+ FROM ' . '[wysija]' . $model_user->table_name . '
305
+ WHERE status = 1';
306
+ $result = $model_user->query('get_res', $query);
307
+
308
+ $confirmed_subscribers = $result[0]['confirmed_subscribers'];
309
+ $total_subscribers = $this->total_subcsribers();
310
+ $confirmed_percentage = round(($confirmed_subscribers * 100) / $total_subscribers);
311
+
312
+ return $confirmed_percentage;
313
+ }
314
+
315
+ /**
316
+ *
317
+ * @return string range eg: 0-100 101-200 2001-500
318
+ */
319
+ private function range_confirmed_subscribers(){
320
+ $model_user = WYSIJA::get('user', 'model');
321
+ $query = 'SELECT COUNT(*) as confirmed_subscribers
322
+ FROM ' . '[wysija]' . $model_user->table_name . '
323
+ WHERE status = 1';
324
+ $result = $model_user->query('get_res', $query);
325
+
326
+ $confirmed_subscribers = (int) $result[0]['confirmed_subscribers'];
327
+
328
+ $ranges_increment = array( 2000 => 100, 10000 => 500, 20000 => 1000, 40000 => 2000, 100000 => 5000, 200000 => 10000, 500000 => 25000, 1000000 => 50000);
329
+
330
+ $found_range = $this->range_finder( $confirmed_subscribers, $ranges_increment );
331
+
332
+ return $found_range['lower'].' - '.$found_range['upper'];
333
+ }
334
+
335
+ private function range_finder($value, $ranges_increment){
336
+
337
+ $limit_max = 0;
338
+ foreach( $ranges_increment as $limit => $range_increment ){
339
+ $small_limit = $limit_max + $range_increment;
340
+ $limit_max = $limit;
341
+
342
+ if( $value > $limit_max){
343
+ continue;
344
+ }
345
+
346
+ while( $value >= $small_limit && $small_limit <= $limit_max ){
347
+
348
+ if( $value > $small_limit ){
349
+ $min_value = $small_limit - $range_increment + 1;
350
+ }
351
+ if( $value == $small_limit ){
352
+ break;
353
+ }
354
+ $small_limit += $range_increment;
355
+ }
356
+
357
+ if( $value <= $small_limit){
358
+ break;
359
+ }
360
+ }
361
+
362
+ if( $value > $limit_max){
363
+ return array( 'lower' => $limit_max , 'upper' => 'above' );
364
+ }else{
365
+ if( $value < 1 ){
366
+ return array( 'lower' => 0 , 'upper' => 'or undefined' );
367
+ }else{
368
+ $min_value = $small_limit - $range_increment + 1;
369
+ return array( 'lower' => $min_value , 'upper' => $small_limit );
370
+ }
371
+ }
372
+
373
+ }
374
+
375
+ /**
376
+ * Calculate unconfirmed subscribers.
377
+ * @return Int
378
+ */
379
+ public function unconfirmed_subscribers() {
380
+
381
+ $model_user = WYSIJA::get('user', 'model');
382
+ $query = 'SELECT COUNT(*) as unconfirmed_subscribers
383
+ FROM ' . '[wysija]' . $model_user->table_name . '
384
+ WHERE status = 0';
385
+ $result = $model_user->query('get_res', $query);
386
+
387
+ return $result[0]['unconfirmed_subscribers'];
388
+ }
389
+
390
+ /**
391
+ * Calculate standard newsletters total.
392
+ * @return Int
393
+ */
394
+ private function standard_newsletters() {
395
+
396
+ $model_email = WYSIJA::get('email', 'model');
397
+ $query = 'SELECT COUNT(*) as standard_newsletters
398
+ FROM ' . '[wysija]' . $model_email->table_name . '
399
+ WHERE type = 1
400
+ AND status = 2';
401
+ $result = $model_email->query('get_res', $query);
402
+
403
+ return $result[0]['standard_newsletters'];
404
+ }
405
+
406
+ /**
407
+ * Calculate auto newsletters total.
408
+ * @return Int
409
+ */
410
+ private function auto_newsletters() {
411
+
412
+ $model_email = WYSIJA::get('email', 'model');
413
+ $query = 'SELECT COUNT(*) as auto_newsletters
414
+ FROM ' . '[wysija]' . $model_email->table_name . '
415
+ WHERE type = 2';
416
+ $result = $model_email->query('get_res', $query);
417
+
418
+ return $result[0]['auto_newsletters'];
419
+ }
420
+
421
+ /**
422
+ * Check license type in use.
423
+ * @return String Free | Premium
424
+ */
425
+ private function license_type() {
426
+
427
+ $model_config = WYSIJA::get('config', 'model');
428
+ $is_premium = $model_config->getValue('premium_key');
429
+
430
+ if ($is_premium) {
431
+ $license_type = 'Premium';
432
+ } else {
433
+ $license_type = 'Free';
434
+ }
435
+
436
+ return $license_type;
437
+ }
438
+
439
+ /**
440
+ * Get sending method in use.
441
+ * @return String
442
+ */
443
+ private function sending_method() {
444
+
445
+ $model_config = WYSIJA::get('config', 'model');
446
+ return $model_config->getValue('sending_method');
447
+ }
448
+
449
+ /**
450
+ * Get smtp hostname in use.
451
+ * @return String
452
+ */
453
+ private function smtp_hostname() {
454
+
455
+ $model_config = WYSIJA::get('config', 'model');
456
+ return $model_config->getValue('smtp_host');
457
+ }
458
+
459
+ /**
460
+ * Get activation email status.
461
+ * @return String On | Off
462
+ */
463
+ private function activation_email_status() {
464
+
465
+ $model_config = WYSIJA::get('config', 'model');
466
+ $activation_email_status = $model_config->getValue('confirm_dbleoptin');
467
+
468
+ if ($activation_email_status === 1) {
469
+ $result = 'On';
470
+ } else {
471
+ $result = 'Off';
472
+ }
473
+
474
+ return $result;
475
+ }
476
+
477
+ /**
478
+ * Get DKIM status.
479
+ * @return String Yes | No
480
+ */
481
+ private function dkim_status() {
482
+ $model_config = WYSIJA::get('config', 'model');
483
+ $dkim_status = $model_config->getValue('dkim_active');
484
+ if ($dkim_status === 1) {
485
+ $result = 'Yes';
486
+ } else {
487
+ $result = 'No';
488
+ }
489
+ return $result;
490
+ }
491
+
492
+ /**
493
+ * Get subscribe in comments.
494
+ * @return String Yes | No
495
+ */
496
+ private function subscribe_in_comments() {
497
+ $model_config = WYSIJA::get('config', 'model');
498
+ $subscribe_in_comments = $model_config->getValue('commentform');
499
+ if ($subscribe_in_comments == 1) {
500
+ $result = 'Yes';
501
+ } else {
502
+ $result = 'No';
503
+ }
504
+ return $result;
505
+ }
506
+
507
+ /**
508
+ * Get subscribe during registration option.
509
+ * @return String Yes | No
510
+ */
511
+ private function subscribe_on_register() {
512
+ $model_config = WYSIJA::get('config', 'model');
513
+ $subscribe_on_register = $model_config->getValue('registerform');
514
+ if ($subscribe_on_register == 1) {
515
+ $result = 'Yes';
516
+ } else {
517
+ $result = 'No';
518
+ }
519
+ return $result;
520
+ }
521
+
522
+ /**
523
+ * Get view in browser option.
524
+ * @return String Yes | No
525
+ */
526
+ private function browser_link() {
527
+ $model_config = WYSIJA::get('config', 'model');
528
+ $browser_link = $model_config->getValue('viewinbrowser');
529
+ if ($browser_link == 1) {
530
+ $result = 'Yes';
531
+ } else {
532
+ $result = 'No';
533
+ }
534
+ return $result;
535
+ }
536
+
537
+ /**
538
+ * Get profile edit option.
539
+ * @return String Yes | No
540
+ */
541
+ private function profile_edit() {
542
+ $model_config = WYSIJA::get('config', 'model');
543
+ $profile_edit = $model_config->getValue('manage_subscriptions');
544
+ if ($profile_edit == 1) {
545
+ $result = 'Yes';
546
+ } else {
547
+ $result = 'No';
548
+ }
549
+ return $result;
550
+ }
551
+
552
+ /**
553
+ * Get html edit in newsletter option.
554
+ * @return String Yes | No
555
+ */
556
+ private function html_edit() {
557
+ $model_config = WYSIJA::get('config', 'model');
558
+ $html_edit = $model_config->getValue('html_source');
559
+ if ($html_edit == 1) {
560
+ $result = 'Yes';
561
+ } else {
562
+ $result = 'No';
563
+ }
564
+ return $result;
565
+ }
566
+
567
+ /**
568
+ * Get mailpoet cron option.
569
+ * @return String Yes | No
570
+ */
571
+ private function mailpoet_cron() {
572
+ $model_config = WYSIJA::get('config', 'model');
573
+ $cron_option = $model_config->getValue('cron_manual');
574
+ if ($cron_option == 1) {
575
+ $result = 'Yes';
576
+ } else {
577
+ $result = 'No';
578
+ }
579
+ return $result;
580
+ }
581
+
582
+ /**
583
+ * Calculate average open rate.
584
+ * @return Int
585
+ */
586
+ private function average_open_rate() {
587
+
588
+ $model_email_user_stat = WYSIJA::get('email_user_stat', 'model');
589
+ $query = 'SELECT COUNT(*) as opened_emails
590
+ FROM ' . '[wysija]' . $model_email_user_stat->table_name . '
591
+ WHERE status = 1';
592
+ $result = $model_email_user_stat->query('get_res', $query);
593
+
594
+ $opened_emails = $result[0]['opened_emails'];
595
+ $total_emails = $this->total_emails_sent();
596
+
597
+ if ($total_emails == 0) {
598
+ $average_open_rate = 0;
599
+ } else {
600
+ $average_open_rate = round(($opened_emails * 100) / $total_emails);
601
+ }
602
+
603
+ return $average_open_rate;
604
+ }
605
+
606
+ /**
607
+ * Calculate average click rate.
608
+ * @return String opened/total
609
+ */
610
+ private function average_click_rate() {
611
+
612
+ $model_email_user_stat = WYSIJA::get('email_user_stat', 'model');
613
+ $query = 'SELECT COUNT(*) as clicked_emails
614
+ FROM ' . '[wysija]' . $model_email_user_stat->table_name . '
615
+ WHERE status = 2';
616
+ $result = $model_email_user_stat->query('get_res', $query);
617
+
618
+ $clicked_emails = $result[0]['clicked_emails'];
619
+ $total_emails = $this->total_emails_sent();
620
+
621
+ if ($total_emails == 0) {
622
+ $average_click_rate = 0;
623
+ } else {
624
+ $average_click_rate = round(($clicked_emails * 100) / $total_emails);
625
+ }
626
+
627
+ return $average_click_rate;
628
+ }
629
+
630
+ /**
631
+ * Get all emails sent.
632
+ * @return Int
633
+ */
634
+ private function total_emails_sent() {
635
+
636
+ $model_email_user_stat = WYSIJA::get('email_user_stat', 'model');
637
+ $query = 'SELECT COUNT(*) as all_emails
638
+ FROM ' . '[wysija]' . $model_email_user_stat->table_name . '';
639
+ $result = $model_email_user_stat->query('get_res', $query);
640
+
641
+ return $result[0]['all_emails'];
642
+ }
643
+
644
+ /**
645
+ * Get total number of forms.
646
+ * @return Int
647
+ */
648
+ private function forms_number() {
649
+
650
+ $model_form = WYSIJA::get('forms', 'model');
651
+ $query = 'SELECT COUNT(*) as forms_number
652
+ FROM ' . '[wysija]' . $model_form->table_name . '';
653
+ $result = $model_form->query('get_res', $query);
654
+
655
+ return $result[0]['forms_number'];
656
+ }
657
+
658
+ /**
659
+ * Get Industry specified in the settings page.
660
+ * @return String
661
+ */
662
+ public function industry() {
663
+ $model_config = WYSIJA::get('config', 'model');
664
+ return $model_config->getValue('industry');
665
+ }
666
+
667
+ /**
668
+ * Get if is using right to left language.
669
+ * @return String
670
+ */
671
+ private function rtl() {
672
+
673
+ if (is_rtl()) {
674
+ $is_rtl = 'Yes';
675
+ } else {
676
+ $is_rtl = 'No';
677
+ }
678
+
679
+ return $is_rtl;
680
+ }
681
+
682
+ /**
683
+ * Check if it's multisite.
684
+ * @return String
685
+ */
686
+ private function is_multisite() {
687
+
688
+ if (is_multisite()) {
689
+ $is_multisite = 'Yes';
690
+ } else {
691
+ $is_multisite = 'No';
692
+ }
693
+
694
+ return $is_multisite;
695
+ }
696
+
697
+ /**
698
+ * Get if is using beta mode
699
+ * @return String
700
+ */
701
+ private function beta() {
702
+
703
+ $model_config = WYSIJA::get('config', 'model');
704
+
705
+ if ($model_config->getValue('beta_mode')) {
706
+ $is_beta = 'Yes';
707
+ } else {
708
+ $is_beta = 'No';
709
+ }
710
+
711
+ return $is_beta;
712
+ }
713
+
714
+ /**
715
+ * Checks if user used the archive page feature.
716
+ * @return String true | false
717
+ */
718
+ private function archive_page() {
719
+
720
+ $model_config = WYSIJA::get('config', 'model');
721
+ $archive_lists = $model_config->getValue('archive_lists');
722
+
723
+ if (!empty($archive_lists)) {
724
+ $used_archive = 'true';
725
+ } else {
726
+ $used_archive = 'false';
727
+ }
728
+
729
+ return $used_archive;
730
+ }
731
+
732
+ /*
733
+ Check if user is using custom fields or not.
734
+ # => Yes | No
735
+ */
736
+ private function using_custom_fields() {
737
+ $fields = WJ_Field::get_all();
738
+ if ($fields != null) {
739
+ $result = 'Yes';
740
+ } else {
741
+ $result = 'No';
742
+ }
743
+ return $result;
744
+ }
745
+
746
+ /*
747
+ How many input custom fields are in use.
748
+ # => int | null
749
+ */
750
+ private function custom_fields_input() {
751
+ global $wpdb;
752
+ $field = new WJ_Field();
753
+ $table_name = $field->get_table_name();
754
+ $result = $wpdb->get_var(
755
+ "SELECT COUNT(*) as inputs
756
+ FROM $table_name
757
+ WHERE type = 'input'"
758
+ );
759
+ if ($result == null) {
760
+ $result = '0';
761
+ }
762
+ return $result;
763
+ }
764
+
765
+ /*
766
+ How many textarea custom fields are in use.
767
+ # => int | null
768
+ */
769
+ private function custom_fields_textarea() {
770
+ global $wpdb;
771
+ $field = new WJ_Field();
772
+ $table_name = $field->get_table_name();
773
+ $result = $wpdb->get_var(
774
+ "SELECT COUNT(*) as textareas
775
+ FROM $table_name
776
+ WHERE type = 'textarea'"
777
+ );
778
+ if ($result == null) {
779
+ $result = '0';
780
+ }
781
+ return $result;
782
+ }
783
+
784
+ /*
785
+ How many select custom fields are in use.
786
+ # => int | null
787
+ */
788
+ private function custom_fields_select() {
789
+ global $wpdb;
790
+ $field = new WJ_Field();
791
+ $table_name = $field->get_table_name();
792
+ $result = $wpdb->get_var(
793
+ "SELECT COUNT(*) as selects
794
+ FROM $table_name
795
+ WHERE type = 'select'"
796
+ );
797
+ if ($result == null) {
798
+ $result = '0';
799
+ }
800
+ return $result;
801
+ }
802
+
803
+ /*
804
+ How many checkbox custom fields are in use.
805
+ # => int | null
806
+ */
807
+ private function custom_fields_checkbox() {
808
+ global $wpdb;
809
+ $field = new WJ_Field();
810
+ $table_name = $field->get_table_name();
811
+ $result = $wpdb->get_var(
812
+ "SELECT COUNT(*) as checkboxes
813
+ FROM $table_name
814
+ WHERE type = 'checkbox'"
815
+ );
816
+ if ($result == null) {
817
+ $result = '0';
818
+ }
819
+ return $result;
820
+ }
821
+
822
+ /*
823
+ How many checkbox custom fields are in use.
824
+ # => int | null
825
+ */
826
+ private function custom_fields_radio() {
827
+ global $wpdb;
828
+ $field = new WJ_Field();
829
+ $table_name = $field->get_table_name();
830
+ $result = $wpdb->get_var(
831
+ "SELECT COUNT(*) as radios
832
+ FROM $table_name
833
+ WHERE type = 'radio'"
834
+ );
835
+ if ($result == null) {
836
+ $result = '0';
837
+ }
838
+ return $result;
839
+ }
840
+
841
+ /*
842
+ Check if user has been active in the last week.
843
+ This means he sent at least one email.
844
+ # => Yes | No
845
+ */
846
+ private function active_last_week() {
847
+ global $wpdb;
848
+ $model_stats = WYSIJA::get('email_user_stat', 'model');
849
+ $table_name = '[wysija]' . $model_stats->table_name;
850
+
851
+ $query = 'SELECT COUNT(*) as activities
852
+ FROM ' . $table_name .
853
+ ' WHERE sent_at > UNIX_TIMESTAMP(date_sub(now(), interval 1 week))';
854
+
855
+ $result = $model_stats->query('get_res', $query);
856
+ $result = $result[0]['activities'];
857
+
858
+ if ($result > 0) {
859
+ return 'Yes';
860
+ }
861
+ return 'No';
862
+ }
863
+
864
+ /**
865
+ * Check PHP versions
866
+ * @return string
867
+ */
868
+ private function php_version() {
869
+ $php_version_factors = explode('.', phpversion());
870
+ $main_version = (int)$php_version_factors[0];
871
+ $sub_version = isset($php_version_factors[1]) ? (int)$php_version_factors[1] : null;
872
+
873
+ $php_version = 'others';
874
+ if ($sub_version !== null) {
875
+ if ($main_version == 4) {
876
+ $php_version = '4.x';
877
+ } elseif ($main_version >= 5) {
878
+ $php_version = implode('.', array( $main_version, $sub_version ));
879
+ }
880
+ }
881
+ return $php_version;
882
+ }
883
+
884
+
885
+ /**
886
+ * Check if bounce is enabled
887
+ * @return string
888
+ */
889
+ private function bounce_enabled() {
890
+ $multisite_prefix = '';
891
+ if ( is_multisite() ) {
892
+ $multisite_prefix = 'ms_';
893
+ }
894
+ $model_config = WYSIJA::get('config', 'model');
895
+ return ($model_config->getValue(
896
+ $multisite_prefix . 'bounce_process_auto')
897
+ ) ? "Yes" : "No";
898
+ }
899
+ }
trunk/classes/WJ_Bridge.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WJ_Bridge {
5
+ public $error;
6
+ private $api_key = '';
7
+ public function __construct($api_key) {
8
+ $this->api_key = $api_key;
9
+ }
10
+
11
+ public function send_mail(& $object)
12
+ {
13
+ $replyToKey = key($object->ReplyTo);
14
+
15
+ $msg = array(
16
+ 'to' => array(
17
+ 'name' => '' ,
18
+ 'address' => $object->to[0][0] ),
19
+ 'reply_to'=> array(
20
+ 'name' => '' ,
21
+ 'address' => $object->ReplyTo[$replyToKey][0]
22
+ ),
23
+ 'from' => array(
24
+ 'name' => $object->FromName ,
25
+ 'address' => $object->From ),
26
+ );
27
+
28
+ // set the subject
29
+ if (!empty ($object->Subject)) $msg['subject']= $object->Subject;
30
+
31
+ // set the body
32
+ if (!empty ($object->sendHTML) || !empty($object->AltBody)){
33
+ $msg['html']= $object->Body;
34
+ if (!empty ($object->AltBody)) $msg['text']=$object->AltBody;
35
+ }else{
36
+ $msg['text']=$object->Body;
37
+ }
38
+
39
+ if(!empty($object->to[0][1])) $msg['to']['name'] = $object->to[0][1];
40
+
41
+ if(!empty($object->ReplyTo[0][1])) $msg['reply_to']['name']= $object->ReplyTo[0][1];
42
+
43
+ $url = 'https://bridge.mailpoet.com/api/messages';
44
+
45
+ $args = array( $msg );
46
+
47
+ return $this->run( $url, $args);
48
+
49
+ }
50
+
51
+ protected function run($url, $args)
52
+ {
53
+ $return = null;
54
+ $data = json_encode($args);
55
+
56
+ $params = array(
57
+ 'headers' => array(
58
+ 'Content-Type: application/json',
59
+ 'Authorization' => 'Basic ' . base64_encode('api:' . $this->api_key )
60
+ ),
61
+ 'body' => $data
62
+ );
63
+
64
+ $result = null;
65
+ $result = wp_remote_post($url, $params);
66
+ try {
67
+ if (!is_wp_error($result) && in_array( (int)$result['response']['code'], array( 201, 400, 401) ) )
68
+ {
69
+ switch( $result['response']['code'] ){
70
+ case 201:
71
+ $return = true;
72
+ break;
73
+ case 400:
74
+ $this->error = 'Bad input';
75
+ break;
76
+ case 401:
77
+ $this->error = 'Not Authorized';
78
+ break;
79
+ }
80
+ }
81
+ else if (is_wp_error($result)) {
82
+ $this->error = $result->get_error_messages();
83
+ }
84
+ } catch(Exception $e) {
85
+ $this->error = 'Unexpected error: '.$e->getMessage() . ' ['.var_export($result, true).']';// do nothing
86
+ }
87
+
88
+ return $return;
89
+ }
90
+
91
+ }
trunk/classes/WJ_Export.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * Class Export.
5
+ *
6
+ * Exporting subscribers
7
+ */
8
+ class WJ_Export extends WYSIJA_object {
9
+
10
+ private $_file_header = '';
11
+ private $_file_handle = null;
12
+ private $_user_ids_rows = 0;
13
+ private $_user_ids = array();
14
+ private $_fields = array();
15
+ private $_export_batch = 2000;
16
+ private $_filter_list = '';
17
+ private $_filter_confirmed = '';
18
+ private $_fields_separator = ';';
19
+ private $_lines_separator = "\n";
20
+ private $_base_encode = 'UTF-8';
21
+ /**
22
+ * Default encoding of exported files
23
+ * @var string
24
+ */
25
+ private $_output_encode = 'UTF-8//TRANSLIT//IGNORE';
26
+
27
+ //needed for tung's batch actions
28
+ public $batch_select = null;
29
+
30
+ function __construct() {
31
+ if ( ! empty( $_POST['wysija']['export']['fields'] ) ) {
32
+ $this->_fields = $_POST['wysija']['export']['fields'];
33
+ }
34
+
35
+ if ( ! empty( $_POST['wysija']['export']['user_ids'] ) ) {
36
+ $this->_user_ids = $this->_get_posted_user_ids();
37
+ }
38
+ if ( ! empty($_POST['wysija']['export']['filter']['list'] ) ) {
39
+ $this->_filter_list = $_POST['wysija']['export']['filter']['list'];
40
+ }
41
+
42
+ // how do we separate the values in the files commas or semy colons ?
43
+ if ( ! empty($_POST['wysija']['export']['format'] ) ) {
44
+ $this->_fields_separator = $_POST['wysija']['export']['format'];
45
+ }
46
+
47
+ if ( ! empty($_POST['wysija']['export']['filter']['confirmed'] ) ) {
48
+ $this->_filter_confirmed = $_POST['wysija']['export']['filter']['confirmed'];
49
+ }
50
+
51
+ $this->set_output_encode();
52
+ }
53
+
54
+ /**
55
+ * Set output encoding based on platform
56
+ */
57
+ protected function set_output_encode() {
58
+ $this->_output_encode = WYSIJA::is_windows() ? 'Windows-1252' : 'UTF-8//TRANSLIT//IGNORE';
59
+ }
60
+
61
+ /**
62
+ * get the number of rows exported
63
+ * @return type
64
+ */
65
+ public function get_user_ids_rows() {
66
+ return $this->_user_ids_rows;
67
+ }
68
+
69
+ /**
70
+ * get an array of user_ids from the global $_POST
71
+ * @return type
72
+ */
73
+ private function _get_posted_user_ids() {
74
+ return (array) json_decode( base64_decode( $_POST['wysija']['export']['user_ids'] ), true );
75
+ }
76
+
77
+ /**
78
+ * get the query used to select a bung of ids
79
+ * @return string
80
+ */
81
+ private function _get_query_users_ids() {
82
+
83
+ // based on filters prepare a query to get a list of user_ids
84
+ if ( ! empty( $this->batch_select ) ) { // batch select and export
85
+ $this->_user_ids_rows = $this->batch_select['count'];
86
+ $qry = $this->batch_select['original_query'];
87
+ } else { // export all list
88
+ // prepare the filters
89
+ $filters = array();
90
+ if ( ! empty( $this->_filter_list ) ) {
91
+ if ( ! is_array( $this->_filter_list ) ) {
92
+ $this->_filter_list = array( $this->_filter_list );
93
+ }
94
+ }
95
+ $filters['lists'] = $this->_filter_list;
96
+
97
+ // include also unsubscribed and unconfirmed
98
+ if ( ! empty( $this->_filter_confirmed ) ) {
99
+ $filters['status'] = 'subscribed';
100
+ }
101
+
102
+ $model_user = WYSIJA::get( 'user', 'model' );
103
+ $select = array( 'A.user_id' );
104
+ $qry = $model_user->get_subscribers( $select, $filters, '', $return_query = true );
105
+ }
106
+
107
+ return $qry;
108
+ }
109
+
110
+ /**
111
+ * get chunks of subscribers ids and push them step by step to the export file
112
+ */
113
+ private function _get_chunks_user_ids() {
114
+
115
+ $model_user = WYSIJA::get( 'user', 'model' );
116
+ $this->_user_ids = array();
117
+ $query_user_ids = $this->_get_query_users_ids();
118
+ $query_count = str_replace( array( 'DISTINCT(A.user_id)', 'DISTINCT(B.user_id)' ), 'COUNT(DISTINCT(A.user_id))', $query_user_ids );
119
+
120
+ if ( empty( $this->_user_ids_rows ) ) {
121
+ $useridsrows_result = $model_user->getResults( $query_count, ARRAY_N );
122
+ $this->_user_ids_rows = (int) $useridsrows_result[0][0];
123
+ }
124
+
125
+ if ( $this->_user_ids_rows <= $this->_export_batch ) {
126
+ $user_ids_db = $model_user->getResults( $query_user_ids, ARRAY_N );
127
+
128
+ foreach ( $user_ids_db as $uarr ) {
129
+ $this->_user_ids[] = $uarr[0];
130
+ }
131
+
132
+ $this->_push_data_to_export_file();
133
+ } else {
134
+ $pages = ceil( $this->_user_ids_rows / $this->_export_batch ); //pagination
135
+ for ( $i = 0; $i < $pages; $i++ ) {
136
+ $query_batch = $query_user_ids . ' ORDER BY user_id ASC LIMIT ' . ($i * $this->_export_batch) . ',' . $this->_export_batch;
137
+ $user_ids_db = $model_user->getResults( $query_batch, ARRAY_N );
138
+ foreach ( $user_ids_db as $uarr ) {
139
+ $this->_user_ids[] = $uarr[0];
140
+ }
141
+ $this->_push_data_to_export_file();
142
+
143
+ unset($user_ids_db); //free memory
144
+ }
145
+ }
146
+ }
147
+
148
+ /**
149
+ * split the user_ids array into chunks, load the fields of all the concerned
150
+ * users and push the data to the file
151
+ */
152
+ private function _push_data_to_export_file() {
153
+ $user_ids_chunks = array(); // chunk rows into separated batchs, limit by $this->_export_batch
154
+ $user_ids_chunks = array_chunk( $this->_user_ids, 200 );
155
+ $this->_user_ids = null; // free memory
156
+
157
+ $model_user = WYSIJA::get( 'user', 'model' );
158
+ $model_user->refresh_columns();
159
+ foreach ( $user_ids_chunks as $user_id_chunk ) {
160
+ // get the full data for that specific chunk of ids
161
+ $data = $model_user->get( $this->_fields, array( 'user_id' => $user_id_chunk ) );
162
+
163
+ if ( in_array( 'created_at', $this->_fields ) ) {
164
+ foreach ( $data as $key => $row ) {
165
+ $data[$key]['created_at'] = date_i18n( get_option( 'date_format' ), $row['created_at'] );
166
+ }
167
+ }
168
+
169
+ $rows_count = count( $data );
170
+
171
+ // As required in Wysija/plugin#798 removed BOM from file
172
+ // fwrite( $this->_file_handle, "\xEF\xBB\xBF" );
173
+
174
+ // append content to the file
175
+ foreach ( $data as $k => $row ) {
176
+ $row = array_map(function($value) {
177
+ $value = str_replace('"', '""', $value);
178
+ return (preg_match('/,/', $value)) ?
179
+ '"' . $value . '"' :
180
+ $value;
181
+ }, $row);
182
+ $row_string = implode( $this->_fields_separator, $row );
183
+ $encoded_string = iconv( $this->_base_encode, $this->_output_encode, $row_string );
184
+ fwrite( $this->_file_handle, $encoded_string . ( $rows_count !== $k ? $this->_lines_separator : '' ) );
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * simply prepare the header of the file based on the fields
191
+ */
192
+ private function _prepare_headers() {
193
+ $model_user = WYSIJA::get( 'user_field', 'model' );
194
+ $database_fields = $model_user->getFields();
195
+
196
+ $name_fields = array();
197
+ //prepare the columns that need to be exported
198
+ foreach ( $this->_fields as $key_field ) {
199
+ $name_fields[] = $database_fields[$key_field];
200
+ }
201
+
202
+ //create the export file step by step
203
+ $row_string = implode( $this->_fields_separator, $name_fields ) . $this->_lines_separator;
204
+ $encoded_string = iconv( $this->_base_encode, $this->_output_encode, $row_string );
205
+ $this->_file_header = $encoded_string;
206
+ }
207
+
208
+ /**
209
+ * export the subscribers
210
+ * @return type
211
+ */
212
+ public function export_subscribers() {
213
+
214
+ //generate temp file
215
+ $helper_file = WYSIJA::get( 'file', 'helper' );
216
+ $this->_prepare_headers();
217
+ $result_file = $helper_file->temp( $this->_file_header, 'export', '.csv' );
218
+
219
+ //open the created file in append mode
220
+ $this->_file_handle = fopen( $result_file['path'], 'a' );
221
+
222
+ //get a list of user_ids to export
223
+ if ( ! empty( $this->_user_ids ) && empty( $this->batch_select ) ) {
224
+
225
+ $this->_user_ids_rows = count( $this->_user_ids );
226
+ $this->_push_data_to_export_file();
227
+ } else {
228
+
229
+ $this->_get_chunks_user_ids();
230
+ }
231
+
232
+ fclose( $this->_file_handle );
233
+ return $result_file;
234
+ }
235
+
236
+ }
trunk/classes/WJ_Field.php ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /*
4
+ A custom field.
5
+ It represents a custom field that
6
+ can be added to a form.
7
+ Example:
8
+ $custom_field = new WJ_Field(
9
+ array(
10
+ 'name' => 'Fruits',
11
+ 'type' => 'select',
12
+ 'required' => false,
13
+ 'settings' => array(
14
+ 'label' => 'Select a fruit:',
15
+ 'values' => array(
16
+ 'Apple', 'Orange', 'Banana'
17
+ ),
18
+ 'default_value' => 'Orange'
19
+ )
20
+ )
21
+ );
22
+ $custom_field->save();
23
+ */
24
+
25
+ class WJ_Field {
26
+
27
+ // The custom fields DB table.
28
+ private $table;
29
+ // The Users table.
30
+ private $user_table;
31
+ // The ID of the custom field.
32
+ public $id;
33
+ // The name of the custom field.
34
+ public $name;
35
+ // input, textarea, checkbox, radio, select
36
+ public $type;
37
+ // true | false
38
+ public $required;
39
+ // Settings.
40
+ public $settings = array();
41
+
42
+ static $_table = 'custom_field';
43
+ static $_user_table = 'user';
44
+
45
+ static $defaults = array(
46
+ 'date' => array(
47
+ 'date_type' => 'year_month_day',
48
+ 'is_default_today' => 0,
49
+ 'date_order' => 'mm/dd/yyyy',
50
+ ),
51
+ 'radio' => array(
52
+ 'values' => array(),
53
+ ),
54
+ 'checkbox' => array(
55
+ 'values' => array(),
56
+ ),
57
+ 'select' => array(
58
+ 'values' => array(),
59
+ )
60
+ );
61
+
62
+ /*
63
+ Just set the correct tables on creation.
64
+ $custom_field = new WJ_Field();
65
+ */
66
+ function __construct( $args = null ) {
67
+ $this->table = WJ_Settings::db_prefix( self::$_table );
68
+ $this->user_table = WJ_Settings::db_prefix( self::$_user_table );
69
+
70
+ if ( ! is_null( $args ) ){
71
+ $this->set( $args );
72
+ }
73
+ }
74
+
75
+ /*
76
+ Get the table name.
77
+ Useful for statistics and counts on Custom Fields.
78
+ Generally when we want to run DB queries.
79
+ */
80
+ public function get_table_name() {
81
+ return $this->table;
82
+ }
83
+
84
+ /*
85
+ Static method to get a Custom field by id.
86
+ WJ_Field::get(id);
87
+ # => WJCustomField Object
88
+ */
89
+ public static function get( $id ) {
90
+ global $wpdb;
91
+ $result = $wpdb->get_row( $wpdb->prepare( 'SELECT * from ' . WJ_Settings::db_prefix( self::$_table ) . ' WHERE id = %d', $id ), ARRAY_A );
92
+ if ( $result != null ) {
93
+ return new self( $result );
94
+ } else {
95
+ return null;
96
+ }
97
+ }
98
+
99
+ /*
100
+ Get all custom fields.
101
+ WJ_Field::get_all();
102
+ # => Array of WJ_Field
103
+ */
104
+ public static function get_all( $options = array() ) {
105
+ global $wpdb;
106
+
107
+ // default order by
108
+ $order_by = 'id ASC';
109
+ if ( isset( $options['order_by'] ) ){
110
+ $order_by = $options['order_by'];
111
+ }
112
+
113
+ // fetch rows from db
114
+ $results = $wpdb->get_results( $wpdb->prepare( 'SELECT * from ' . WJ_Settings::db_prefix( self::$_table ) . ' ORDER BY %s', $order_by ), ARRAY_A );
115
+
116
+ if ( ! is_null( $results ) ) {
117
+ $collection = array();
118
+ foreach ( $results as $result ) {
119
+ $collection[] = new self( $result );
120
+ }
121
+ return $collection;
122
+ } else {
123
+ return null;
124
+ }
125
+ }
126
+
127
+
128
+ /*
129
+ Get a custom fields names list.
130
+ WJ_Field::get_names_list();
131
+ # => array(1 => 'Address', 2 => 'Gender')
132
+ */
133
+ public static function get_all_names() {
134
+ $fields = self::get_all();
135
+ $fields_list = array();
136
+ if ( isset( $fields ) ) {
137
+ foreach ( $fields as $field ) {
138
+ $fields_list[ $field->id ] = $field->name;
139
+ }
140
+ }
141
+ return $fields_list;
142
+ }
143
+
144
+ /*
145
+ Set all object properties.
146
+ $custom_field->set(array(
147
+ 'name' => 'First Name',
148
+ 'type' => 'text',
149
+ 'required' => true
150
+ ));
151
+ */
152
+ public function set( $args ) {
153
+ if ( isset( $args['id'] ) ) {
154
+ $this->id = $args['id'];
155
+ }
156
+ $this->name = $args['name'];
157
+ $this->type = $args['type'];
158
+ $this->required = WJ_Utils::to_bool( $args['required'] );
159
+ $this->settings = maybe_unserialize( $args['settings'] );
160
+
161
+ if ( ! is_array( $this->settings ) ){
162
+ $this->settings = array();
163
+ }
164
+
165
+ if ( isset( self::$defaults[ $this->type ] ) && is_array( self::$defaults[ $this->type ] ) ) {
166
+ $this->settings = wp_parse_args( (array) $this->settings, (array) self::$defaults[ $this->type ] );
167
+ }
168
+ }
169
+
170
+ /*
171
+ Store Custom Field in DB.
172
+ If already stored, updates it.
173
+ $custom_field->save();
174
+ */
175
+ public function save() {
176
+ // Check if it's a new object or an update.
177
+ if ( isset( $this->id ) ) {
178
+ $this->update();
179
+ } else {
180
+ $this->create();
181
+ }
182
+ }
183
+
184
+ // Delete custom field from DB.
185
+ public function delete() {
186
+ global $wpdb;
187
+ $result = $wpdb->delete( $this->table, array( 'id' => $this->id ), array( '%d' ) );
188
+ $this->delete_user_col( $this->id );
189
+ return $result;
190
+ }
191
+
192
+ /*
193
+ Generates user column name;
194
+ $custom_field->user_column_name();
195
+ # => 'cf_1'
196
+ */
197
+ public function user_column_name() {
198
+ $column_name = 'cf_' . $this->id;
199
+ return $column_name;
200
+ }
201
+
202
+ /*
203
+ Creates the Custom Field.
204
+ It also creates the user column, depending on type.
205
+ */
206
+ private function create() {
207
+ global $wpdb;
208
+ $required = WJ_Utils::to_int( $this->required );
209
+ $wpdb->insert(
210
+ $this->table,
211
+ array(
212
+ 'name' => $this->name,
213
+ 'type' => $this->type,
214
+ 'required' => $required,
215
+ 'settings' => serialize( $this->settings ),
216
+ ),
217
+ array( '%s', '%s', '%d', '%s', '%s' )
218
+ );
219
+ // ! No id in user col?
220
+ if ( $wpdb->insert_id ) {
221
+ $this->id = $wpdb->insert_id;
222
+ $this->create_user_col();
223
+ } else {
224
+ return false;
225
+ }
226
+ }
227
+
228
+ /*
229
+ Updates the value of the custom field.
230
+ $custom_field->update('New address');
231
+ */
232
+ private function update() {
233
+ global $wpdb;
234
+ $required = WJ_Utils::to_int( $this->required );
235
+ $result = $wpdb->update(
236
+ $this->table,
237
+ array(
238
+ 'name' => $this->name,
239
+ 'type' => $this->type,
240
+ 'required' => $required,
241
+ 'settings' => maybe_serialize( $this->settings ),
242
+ ),
243
+ array( 'id' => $this->id ),
244
+ array( '%s', '%s', '%d' ),
245
+ array( '%d' )
246
+ );
247
+ return $result;
248
+ }
249
+
250
+ /*
251
+ Creates the correct user columnn, named cf_x, in the
252
+ user table. x is the ID if the custom field.
253
+ */
254
+ private function create_user_col() {
255
+ global $wpdb;
256
+ $column_name = $this->user_column_name();
257
+ $column_type = $this->generate_column_type();
258
+ $result = $wpdb->query(
259
+ "ALTER TABLE $this->user_table ADD COLUMN $column_name $column_type"
260
+ );
261
+ return $result;
262
+ }
263
+
264
+ /*
265
+ Calculates the correct column type, based on custom field type.
266
+ $custom_field->generate_column_type();
267
+ # => 'VARCHAR(100)'
268
+ */
269
+ private function generate_column_type() {
270
+ switch ( $this->type ) {
271
+ case 'input':
272
+ $column_type = 'VARCHAR(100)';
273
+ break;
274
+ case 'textarea':
275
+ $column_type = 'VARCHAR(255)';
276
+ break;
277
+ case 'checkbox':
278
+ $column_type = 'TINYINT(1)';
279
+ break;
280
+ case 'radio':
281
+ $column_type = 'VARCHAR(255)';
282
+ break;
283
+ case 'select':
284
+ $column_type = 'VARCHAR(255)';
285
+ break;
286
+ case 'date':
287
+ $column_type = 'INT(20)';
288
+ break;
289
+ default:
290
+ $column_type = 'VARCHAR(255)';
291
+ break;
292
+ }
293
+ return $column_type;
294
+ }
295
+
296
+ /*
297
+ Deletes the user column in the user table.
298
+ Needed when we remove a custom field.
299
+ */
300
+ private function delete_user_col( $custom_field_id ) {
301
+ global $wpdb;
302
+ $cf_column = 'cf_' . $custom_field_id;
303
+ $result = $wpdb->query( "ALTER TABLE $this->user_table DROP COLUMN $cf_column" );
304
+ return $result;
305
+ }
306
+
307
+ }
trunk/classes/WJ_FieldHandler.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /*
4
+ Class WJ_FieldHandler
5
+ It handles the custom fields in a controller.
6
+ */
7
+ class WJ_FieldHandler {
8
+
9
+ public function __construct() {
10
+ }
11
+
12
+ /*
13
+ Handler to save all the fields, by giving an array
14
+ that specifies the custom fields columns names, and
15
+ the ID of the user.
16
+ WJ_FieldHandler::handle_all(array(
17
+ 'cf_1' => 'Value',
18
+ 'cf_2' => 'Value 2'
19
+ ), 1
20
+ );
21
+ */
22
+ public static function handle_all(array $fields_values, $user_id) {
23
+ $user_fields = WJ_FieldUser::get_all($user_id);
24
+
25
+ if(isset($user_fields) && !empty($user_fields)) {
26
+ foreach ($user_fields as $user_field) {
27
+ $key = $user_field->column_name();
28
+
29
+ // check if there is a value for this custom field
30
+ if(array_key_exists($key, $fields_values)) {
31
+
32
+ // set value
33
+ $new_value = $fields_values[$key];
34
+
35
+ // extra process for specific types
36
+ if($user_field->field->type === 'checkbox') {
37
+ // limit the value between [0,1]
38
+ $new_value = min(max(0, (int)$new_value), 1);
39
+
40
+ } else if($user_field->field->type === 'date') {
41
+ // get date parameters
42
+ $year = (isset($fields_values[$key]['year'])) ? (int)$fields_values[$key]['year'] : (int)strftime('%Y');
43
+ $month = (isset($fields_values[$key]['month'])) ? (int)$fields_values[$key]['month'] : 1;
44
+ $day = (isset($fields_values[$key]['day'])) ? (int)$fields_values[$key]['day'] : 1;
45
+
46
+ $new_value = null;
47
+ if($year !== 0 && $month !== 0 && $day !== 0) {
48
+ // make timestamp from date parameters
49
+ $new_value = mktime(0, 0, 0, $month, $day, $year);
50
+ }
51
+ }
52
+
53
+ // update value
54
+ $user_field->update($new_value);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
trunk/classes/WJ_FieldRender.php ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /*
4
+ Class WJ_FieldRender
5
+ It is able to render Custom Fields in a form.
6
+ */
7
+
8
+ class WJ_FieldRender {
9
+
10
+ // WJ_FieldUser Object.
11
+ private $field_user;
12
+ // The column, like 'cf_1'
13
+ private $identifier;
14
+ // Name of the field.
15
+ private $name;
16
+ // Value of the field.
17
+ private $value;
18
+
19
+ public function __construct( $field_user ) {
20
+ $this->field_user = $field_user;
21
+ $this->identifier = $field_user->column_name();
22
+ $this->name = esc_attr( $field_user->field->name );
23
+ $this->value = esc_attr( $field_user->value() );
24
+ }
25
+
26
+ public function validation() {
27
+ $rules = array();
28
+ $validation_class = '';
29
+
30
+ // If there are any validations, add correct class names.
31
+ if ( ! empty( $this->field_user->field->settings['validate'] ) ) {
32
+ $validation_value = $this->field_user->field->settings['validate'];
33
+ $rules[] = 'custom[' . $validation_value . ']';
34
+ }
35
+
36
+ // If there's any validation, join all classes.
37
+ if ( ! empty( $rules ) ) {
38
+ $validation_class = 'class="validate[' . join( ',', $rules ) . ']"';
39
+ }
40
+
41
+ return $validation_class;
42
+ }
43
+
44
+ /*
45
+ Returns the HTML label for this field, to be used
46
+ in a form.
47
+ $field_render->label();
48
+ # => '<label ...>Address</label>'
49
+ */
50
+ public function label() {
51
+ $form_field_name = $this->identifier;
52
+ $label =
53
+ '<label for="' . $form_field_name . '">' .
54
+ $this->name .
55
+ '</label>';
56
+ return $label;
57
+ }
58
+
59
+ /*
60
+ Returns the input related to the type of the field,
61
+ to be used in a form.
62
+ $field_render->input();
63
+ # => '<input type=..../>
64
+ */
65
+ public function input() {
66
+ $input = '';
67
+
68
+ switch ( $this->field_user->field->type ) {
69
+ case 'input':
70
+ $input =
71
+ '<input type="text" size="40" id="'. $this->identifier . '"' .
72
+ ' value="' . $this->value .
73
+ '" name="wysija[field][' . $this->identifier . ']" ' .
74
+ $this->validation() .
75
+ ' />';
76
+ break;
77
+ case 'textarea':
78
+ $input =
79
+ '<textarea id="'. $this->identifier . '"' .
80
+ 'name="wysija[field][' . $this->identifier . ']" ' .
81
+ $this->validation() .
82
+ ' />' .
83
+ $this->value .
84
+ '</textarea>';
85
+ break;
86
+ case 'checkbox':
87
+ if ( empty( $this->field_user->field->settings['values'] ) ){
88
+ $input = esc_attr__( 'This field contains no values', WYSIJA );
89
+ break;
90
+ }
91
+ $check_value = '';
92
+ $label = $this->field_user->field->settings['values'][0]['value'];
93
+ if ( $this->value == 1 ) {
94
+ $check_value = ' checked="checked"';
95
+ }
96
+ $input =
97
+ '<label for="' . $this->identifier . '">' .
98
+ '<input type="hidden" '.
99
+ $check_value .
100
+ ' name="wysija[field][' . $this->identifier . ']"' .
101
+ ' value="0" ' .
102
+ ' />' .
103
+ '<input type="checkbox" id="'. $this->identifier . '"' .
104
+ $check_value .
105
+ ' name="wysija[field][' . $this->identifier . ']"' .
106
+ ' value="1" ' .
107
+ $this->validation() .
108
+ ' />' . $label . '</label>';
109
+ break;
110
+ case 'radio':
111
+ $field = $this->field_user->field;
112
+ if ( empty( $this->field_user->field->settings['values'] ) ){
113
+ $input = esc_attr__( 'This field contains no values', WYSIJA );
114
+ break;
115
+ }
116
+ foreach ( $field->settings['values'] as $index => $content ) {
117
+ $check_value = '';
118
+ if ( $this->value == $content['value'] ) {
119
+ $check_value = 'checked="checked"';
120
+ }
121
+ $local_identifier = $this->identifier . '_' . $content['value'];
122
+ $input .=
123
+ '<label for="' . $local_identifier . '">' .
124
+ '<input type="radio" id="'. $local_identifier . '"' .
125
+ $check_value .
126
+ ' name="wysija[field][' . $this->identifier . ']"' .
127
+ ' value="' . $content['value'] . '" />' .
128
+ $content['value'] .
129
+ '</label>';
130
+ }
131
+ break;
132
+ case 'select':
133
+ if ( empty( $this->field_user->field->settings['values'] ) ){
134
+ $input = esc_attr__( 'This field contains no values', WYSIJA );
135
+ break;
136
+ }
137
+
138
+ $input = '<select id="' . $this->identifier . '"' .
139
+ ' name="wysija[field][' . $this->identifier . ']" ' .
140
+ $this->validation() .
141
+ ' />';
142
+ $field = $this->field_user->field;
143
+ foreach ( $field->settings['values'] as $index => $content ) {
144
+ $check_value = '';
145
+ if ( $this->value == $content['value'] ) {
146
+ $check_value = 'selected="selected"';
147
+ }
148
+ $input .=
149
+ '<option ' . $check_value .
150
+ ' value="' . $content['value'] . '" >' .
151
+ $content['value'] .
152
+ '</option>';
153
+ }
154
+ $input .= '</select>';
155
+ break;
156
+
157
+ case 'date':
158
+ // get date format from field settings
159
+ $field = $this->field_user->field;
160
+
161
+ // get timestamp value
162
+ $value = (int) $this->value;
163
+
164
+ // get date type (defaults to year + month + day)
165
+ $date_type = ( isset( $field->settings['date_type'] ) ) ? $field->settings['date_type'] : 'year_month_day';
166
+ // get an array of all required date components (year, month, day)
167
+ $display_date_fields = explode( '_', $date_type );
168
+ // form engine to get date data
169
+ $helper_form_engine = WYSIJA::get( 'form_engine', 'helper' );
170
+ $date_order = explode('/', $field->settings['date_order']);
171
+
172
+ foreach ($date_order as $date_element) {
173
+ if (strpos($date_element, 'yy') !== false) {
174
+ // year selection
175
+ if ( in_array( 'year', $display_date_fields ) ) {
176
+ $years = $helper_form_engine->get_years();
177
+
178
+ $selected_year = null;
179
+ if ( $value !== null ) {
180
+ $selected_year = (int) strftime( '%Y', $value );
181
+ }
182
+
183
+ // select
184
+ $input .= '<select name="wysija[field]['.$this->identifier.'][year]">';
185
+ $input .= '<option value="">' . __( 'Year' ) .'</option>';
186
+ foreach ( $years as $year ) {
187
+ $is_selected = ((int)$year['year'] === $selected_year) ? ' selected="selected"' : '';
188
+ $input .= '<option value="'.$year['year'].'"'.$is_selected.'>'.$year['year'].'</option>';
189
+ }
190
+ $input .= '</select>';
191
+ }
192
+ } elseif (strpos($date_element, 'mm') !== false) {
193
+ // month selection
194
+ if ( in_array( 'month', $display_date_fields ) ) {
195
+ $months = $helper_form_engine->get_months();
196
+
197
+ $selected_month = null;
198
+ if ( $value !== null ) {
199
+ $selected_month = (int) strftime( '%m', $value );
200
+ }
201
+
202
+ // select
203
+ $input .= '<select name="wysija[field]['.$this->identifier.'][month]">';
204
+ $input .= '<option value="">' . __( 'Month' ) . '</option>';
205
+ foreach ( $months as $month ) {
206
+ $is_selected = ((int)$month['month'] === $selected_month) ? ' selected="selected"' : '';
207
+ $input .= '<option value="'.$month['month'].'"'.$is_selected.'>'.$month['month_name'].'</option>';
208
+ }
209
+ $input .= '</select>';
210
+ }
211
+ } elseif (strpos($date_element, 'dd') !== false) {
212
+ // day selection
213
+ if ( in_array( 'day', $display_date_fields ) ) {
214
+ $days = $helper_form_engine->get_days();
215
+
216
+ $selected_day = null;
217
+ if ( $value !== null ) {
218
+ $selected_day = (int) strftime( '%d', $value );
219
+ }
220
+
221
+ // select
222
+ $input .= '<select name="wysija[field]['.$this->identifier.'][day]">';
223
+ $input .= '<option value="">' . __( 'Day' ) . '</option>';
224
+ foreach ( $days as $day ) {
225
+ $is_selected = ((int)$day['day'] === $selected_day) ? ' selected="selected"' : '';
226
+ $input .= '<option value="'.$day['day'].'"'.$is_selected.'>'.$day['day'].'</option>';
227
+ }
228
+ $input .= '</select>';
229
+ }
230
+ }
231
+ }
232
+
233
+ break;
234
+ default:
235
+ $input = '';
236
+ break;
237
+ }
238
+ return $input;
239
+ }
240
+
241
+ /*
242
+ Render all custom fields in a table, given the user id.
243
+ $field_render::render_all(1);
244
+ # => '<tr><th><label...<input...</td></tr>'
245
+ */
246
+ public static function render_all( $user_id ) {
247
+ $fields = WJ_FieldUser::get_all( $user_id );
248
+ if ( isset( $fields ) ) {
249
+ $output = '';
250
+ foreach ( $fields as $field ) {
251
+ $field_render = new self($field);
252
+ $output .=
253
+ '<tr>' .
254
+ '<th scope="row">' .
255
+ $field_render->label() .
256
+ '</th><td>' .
257
+ $field_render->input() .
258
+ '</td></tr>';
259
+ }
260
+ return $output;
261
+ } else {
262
+ return null;
263
+ }
264
+ }
265
+
266
+
267
+ }
268
+
trunk/classes/WJ_FieldUser.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /*
4
+ An user field is a custom field identified by ID,
5
+ linked to a particular user, identified by ID.
6
+ */
7
+
8
+ class WJ_FieldUser {
9
+
10
+ // User Table.
11
+ private $user_table;
12
+ // Custom fields table.
13
+ private $field_table;
14
+ // User ID.
15
+ public $user_id;
16
+ // The field object.
17
+ public $field;
18
+ // The field value.
19
+ public $value;
20
+
21
+ /*
22
+ $field_user = new WJ_FieldUser();
23
+ Just setup correct tables names.
24
+ */
25
+ function __construct() {
26
+ $this->user_table = WJ_Settings::db_prefix('user');
27
+ $this->field_table = WJ_Settings::db_prefix('custom_field');
28
+ }
29
+
30
+ /*
31
+ After object creation, you can set the user id,
32
+ and the field id. The object will now contain the right
33
+ custom field, and the user id.
34
+ $field_user->set(array(
35
+ 'user_id' => 1,
36
+ 'field_id' => 2
37
+ ));
38
+ */
39
+ public function set($args) {
40
+ $this->user_id = $args['user_id'];
41
+ $this->field = WJ_Field::get($args['field_id']);
42
+ }
43
+
44
+ /*
45
+ Updates the field user value.
46
+ $field_user->update('Main Street');
47
+ */
48
+ public function update($value) {
49
+ global $wpdb;
50
+ $column_name = $this->field->user_column_name();
51
+ // Cast value to the correct column type.
52
+ switch ($this->field->type) {
53
+ case 'checkbox':
54
+ $validation = '%d';
55
+ $value = (int)$value;
56
+ break;
57
+ default:
58
+ // We default to a string.
59
+ $validation = '%s';
60
+ $value = (string)$value;
61
+ break;
62
+ }
63
+ $result = $wpdb->update(
64
+ $this->user_table,
65
+ array(
66
+ $column_name => $value
67
+ ), array("user_id" => $this->user_id),
68
+ array($validation),
69
+ array("%d")
70
+ );
71
+ if ($result != false) {
72
+ $this->value = $value;
73
+ }
74
+ return $result;
75
+ }
76
+
77
+ /*
78
+ Get the user field value.
79
+ $field_user->value();
80
+ # => 'Main Street'
81
+ */
82
+ public function value() {
83
+ $value = '';
84
+ if (isset($this->value)) {
85
+ $value = $this->value;
86
+ } else {
87
+ $column_name = $this->field->user_column_name();
88
+ global $wpdb;
89
+ $result = $wpdb->get_row($wpdb->prepare(
90
+ "SELECT $column_name FROM $this->user_table
91
+ WHERE user_id = %d",
92
+ array($this->user_id)
93
+ ), ARRAY_A);
94
+ $this->value = $result[$column_name];
95
+ $value = $result[$column_name];
96
+ }
97
+ return $value;
98
+ }
99
+
100
+ /*
101
+ Get the user unique column name.
102
+ $field_user->column_name();
103
+ # => 'cf_1'
104
+ */
105
+ public function column_name() {
106
+ return $this->field->user_column_name();
107
+ }
108
+
109
+ /*
110
+ Get all UserFields by User ID.
111
+ $WJ_FieldUser::get_all();
112
+ # => Array of WJ_FieldUser
113
+ */
114
+ public static function get_all($user_id) {
115
+ $fields = WJ_Field::get_all();
116
+ if(isset($fields) && !empty($fields)) {
117
+ $collection = array();
118
+ foreach ($fields as $field) {
119
+ $user_field = new self();
120
+ $user_field->user_id = $user_id;
121
+ $user_field->field = $field;
122
+ $collection[] = $user_field;
123
+ }
124
+ return $collection;
125
+ } else {
126
+ return null;
127
+ }
128
+ }
129
+
130
+ }
trunk/classes/WJ_Import.php ADDED
@@ -0,0 +1,853 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * Class Import.
5
+ *
6
+ * Importing subscribers
7
+ */
8
+ class WJ_Import extends WYSIJA_object {
9
+
10
+ private $_header_row = array();
11
+ private $_csv_data = array();
12
+ private $_match = array();
13
+ private $_ignore_invalid_date = array(); // specific for date fields
14
+ private $_custom_fields = array();
15
+ private $_email_key = '';
16
+ private $_data_to_insert = array();
17
+ private $_number_list = 0;
18
+ private $_data_numbers = array();
19
+ private $_line_delimiter = "\n";
20
+ private $_duplicate_emails_count = array(); // detect the emails that are duplicates in the import file
21
+ private $_csv_array = array(); // containing the csv into an array
22
+ private $_ignored_row_count = 0; // the count of rows we ignore because there was no valid email present
23
+ private $_lines_count = 0; // count the number of valid lines inserted in the DB
24
+ private $_chunks_count = 0; // number of chunks we chopped from the csv
25
+ private $_first_row_is_data = false; // means that there is no header on that csv file
26
+ private $_emails_inserted_in_current_chunk = array(); // array of emails
27
+ private $_csv_file_string = '';
28
+ private $_data_result = array(); // used for importmatch refactor
29
+ private $_regex_new_field = "/^new_field\|([^\|]+)\|(.+)$/i";
30
+ private $_field_separators_to_test = array( ',', ';', "\t" );
31
+ private $_field_enclosers_to_test = array( '"', '' );
32
+
33
+ function __construct() {
34
+ if (!empty($_POST['wysija']['match']))
35
+ $this->_match = $_POST['wysija']['match'];
36
+ if (!empty($_POST['wysija']['ignore_invalid_date']))
37
+ $this->_ignore_invalid_date = $_POST['wysija']['ignore_invalid_date'];
38
+ if (!empty($_REQUEST['wysija']['user_list']['list']))
39
+ $this->_number_list = count($_REQUEST['wysija']['user_list']['list']);
40
+ if (!empty($_POST['firstrowisdata']))
41
+ $this->_first_row_is_data = true;
42
+ $this->_data_numbers = array('invalid' => array(), 'inserted' => 0, 'valid_email_processed' => 0, 'list_added' => 0, 'list_user_ids' => 0, 'list_list_ids' => $this->_number_list, 'emails_queued' => 0);
43
+ }
44
+
45
+ /**
46
+ * loading file data passed in a global variable
47
+ * @return type
48
+ */
49
+ private function _get_temp_file_info() {
50
+ if (!empty($_REQUEST['wysija']['dataImport'])){
51
+ return (array) json_decode(base64_decode($_REQUEST['wysija']['dataImport']),true);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * loading the file based on global parameters
57
+ * @return string
58
+ */
59
+ private function _loading_file_content() {
60
+ // try to access the temporary file created in the previous step
61
+ $this->_csv_data = $this->_get_temp_file_info();
62
+
63
+ if ( empty($this->_csv_data['csv']) || !is_string( $this->_csv_data['csv'] ) || preg_match('|[^a-z0-9#_.-]|i',$this->_csv_data['csv']) !== 0 ){
64
+ $this->error('Error with import file name');
65
+ return false;
66
+ }
67
+
68
+ $helper_file = WYSIJA::get('file', 'helper');
69
+
70
+ if (!is_string($this->_csv_data['csv']) OR preg_match('|[^a-z0-9#_.-]|i',$this->_csv_data['csv']) !== 0 ){
71
+ die('Import file error.');
72
+ }
73
+ $result_file = $helper_file->get($this->_csv_data['csv'], 'import');
74
+
75
+ if (!$result_file) {
76
+ $upload_dir = wp_upload_dir();
77
+ $this->error(sprintf(__('Cannot access CSV file. Verify access rights to this directory "%1$s"', WYSIJA), $upload_dir['basedir']), true);
78
+ return false;
79
+ }
80
+
81
+ // get the temp csv file
82
+ $this->_csv_file_string = file_get_contents($result_file);
83
+ }
84
+
85
+ private function _set_custom_fields(){
86
+ $WJ_Field = new WJ_Field();
87
+ $_custom_fields = $WJ_Field->get_all();
88
+
89
+ if(!empty($_custom_fields)){
90
+ foreach($_custom_fields as $key => &$row){
91
+ $this->_custom_fields['cf_'.$row->id] = $row;
92
+ }
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Validate if a column is already matched previously
98
+ * @param string $column_name
99
+ * @return boolean
100
+ */
101
+ private function _is_column_matched($column_name) {
102
+ if (empty($this->_data_to_insert)) {
103
+ return false;
104
+ }
105
+ $column_names = array_values($this->_data_to_insert);
106
+ return in_array(trim($column_name), $column_names);
107
+ }
108
+ /**
109
+ * match columns together with the csv data based on the data passed
110
+ */
111
+ private function _match_columns_to_insert() {
112
+
113
+ // we're going through all of the selected value in each dropdown when importing
114
+ foreach($this->_match as $csv_column_number => $column_in_user_table){
115
+
116
+ if (!is_string($column_in_user_table) OR preg_match('|[^a-z0-9#_\|.-]|i',$column_in_user_table) !== 0 ){
117
+ continue;
118
+ }
119
+ // Reduce matching twice the same column
120
+ if ($this->_is_column_matched($column_in_user_table))
121
+ continue;
122
+
123
+ // Ignore `nomatch` columns
124
+ if ($column_in_user_table == 'nomatch')
125
+ continue;
126
+
127
+ // Check if maybe it's a new field
128
+ preg_match($this->_regex_new_field, $column_in_user_table, $maybe_newfield);
129
+ if ( !empty($maybe_newfield) && in_array($maybe_newfield[1], array('date', 'input')) ){
130
+ // TODO need to change to WJ_Field I guess when Marco is done moving the files
131
+ // saving a new custom field
132
+ $custom_field = new WJ_Field();
133
+
134
+ $custom_field->set(array(
135
+ 'name' => $maybe_newfield[2],
136
+ 'type' => $maybe_newfield[1],
137
+ 'required' => false,
138
+ 'settings' => array(
139
+ 'label' => $maybe_newfield[2],
140
+ )
141
+ ));
142
+
143
+ $custom_field->save();
144
+
145
+ // this is the column name in the database so this is where we need to import that field
146
+ $column_in_user_table = $custom_field->user_column_name();
147
+ $this->_match[$csv_column_number] = $column_in_user_table;
148
+ }
149
+
150
+ // keep the match of CSV column number to column key in our database
151
+ // not sure why do we trim the column key ...
152
+ $this->_data_to_insert[$csv_column_number] = trim($column_in_user_table);
153
+
154
+ // this column is the email column, let's keep track of it for later validation etc..
155
+ if($column_in_user_table == 'email'){
156
+ $this->_email_key = $csv_column_number;
157
+ }
158
+ }
159
+
160
+ $this->_set_custom_fields();
161
+
162
+ // if the status column is not matched, we make sure that we have an entry for the status column so that we default it to some value on import
163
+ if(!in_array('status',$this->_data_to_insert)){
164
+ $this->_data_to_insert['status'] = 'status';
165
+ }
166
+ }
167
+
168
+ /**
169
+ * build the header of the import query
170
+ * @return type
171
+ */
172
+ private function _get_import_query_header() {
173
+ return 'INSERT INTO [wysija]user (`' . implode('` ,`', $this->_data_to_insert) . '`,`created_at`) VALUES ';
174
+ }
175
+
176
+ /**
177
+ *
178
+ * @param type $array_csv
179
+ */
180
+ private function _check_duplicate_emails($array_csv) {
181
+ // look for duplicate emails
182
+ foreach ($array_csv as $keyline => $csv_line) {
183
+ if (isset($csv_line[$this->_email_key])) {
184
+ if (isset($this->_duplicate_emails_count[$csv_line[$this->_email_key]])) {
185
+ $this->_duplicate_emails_count[$csv_line[$this->_email_key]]++;
186
+ //$arra[$keyline]
187
+ } else {
188
+ $this->_duplicate_emails_count[$csv_line[$this->_email_key]] = 1;
189
+ }
190
+ } else {
191
+ //if the record doesn't have the attribute email then we just ignore it
192
+ $this->_ignored_row_count++;
193
+ unset($array_csv[$keyline]);
194
+ }
195
+ }
196
+ }
197
+
198
+ /**
199
+ * save new column/field match to improve usability the next time our admin
200
+ * import a field with similar headers/columns names
201
+ * @return boolean
202
+ */
203
+ private function _smart_column_match_recording() {
204
+ if ($this->_first_row_is_data === false) {
205
+ //save the importing fields to be able to match them the next time
206
+ $import_fields = get_option('wysija_import_fields');
207
+
208
+ foreach($this->_match as $csv_column_number => $column_in_user_table){
209
+ if($column_in_user_table != 'nomatch') {
210
+
211
+ // make a column name key
212
+ $column_name_key = str_replace(array(' ','-','_'),'',strtolower($this->_header_row[$csv_column_number]));
213
+ // fill in the array of "csv column name" / "user table column" matches
214
+ $import_fields[$column_name_key] = $column_in_user_table;
215
+
216
+ }
217
+ }
218
+
219
+ WYSIJA::update_option('wysija_import_fields' , $import_fields);
220
+ return true;
221
+ }
222
+ return false;
223
+ }
224
+
225
+ /**
226
+ * import a csv type into wysija's subscribers' table
227
+ * @return type
228
+ */
229
+ public function import_subscribers() {
230
+
231
+ // import the contacts
232
+ // 1-check that a list is selected and that there is a csv file pasted
233
+ // 2-save the list if necessary
234
+ // 3-save the contacts and record them for each list selected
235
+ $this->_loading_file_content();
236
+ // convert the csv file to an array of lines
237
+ $this->_csv_array = $this->_csv_to_array( $this->_csv_file_string , 0 , $this->_csv_data['fsep'] , $this->_csv_data['fenc']);
238
+
239
+ // check what columns of the csv have been matched together with our subscribers' table
240
+ $this->_match_columns_to_insert();
241
+
242
+ $this->_header_row = array_map('trim', $this->_csv_array[0]);
243
+
244
+ // we process the sql insertion 200 by 200 so that we are safe with the server's memory and cpu
245
+ $csv_chunks = array_chunk($this->_csv_array, 200);
246
+ $this->_csv_array = null;
247
+ $this->_chunks_count = 0;
248
+ $this->_lines_count = 0;
249
+
250
+ // setting up a timeout value on the sql side to avoid timeout when importing a lot of data apparently.
251
+ global $wpdb;
252
+ $wpdb->query('set session wait_timeout=600');
253
+
254
+ // loop and insert the data chunks by chunks
255
+ foreach ($csv_chunks as $key_chunk => $csv_chunk) {
256
+
257
+ $this->_check_duplicate_emails($csv_chunk);
258
+
259
+ $result = $this->_import_rows($csv_chunk);
260
+
261
+ if ($result !== false)
262
+ $this->_chunks_count++;
263
+ else {
264
+ // there was an error we try 3 more times the same chunk and se how it goes
265
+ $try = 0;
266
+ while ($result === false && $try < 3) {
267
+ $result = $this->_import_rows($csv_chunk);
268
+ if ($result !== false) {
269
+ $this->_chunks_count++;
270
+ break;
271
+ }
272
+ $try++;
273
+ }
274
+
275
+ if ($result === false) {
276
+ $this->error(__('There seems to be an error with the list you\'re trying to import.', WYSIJA), true);
277
+ return false;
278
+ }
279
+ }
280
+ // increment the lines count
281
+ $this->_lines_count += $result;
282
+ // free up some memory
283
+ unset($csv_chunks[$key_chunk]);
284
+ }
285
+
286
+ // useful the next time we import a file with the same format
287
+ $this->_smart_column_match_recording();
288
+
289
+ // refresh the total count of users in wysija
290
+ $helper_user = WYSIJA::get('user','helper');
291
+ $helper_user->refreshUsers();
292
+
293
+ // keep only the real duplicate emails unset the unique ones
294
+ // TODO check that this email duplicate function could be a memory sink hole
295
+ // especially that right now we don't use its value
296
+ foreach ($this->_duplicate_emails_count as $email_address => $times_email_in_csv) {
297
+ if ($times_email_in_csv == 1)
298
+ unset($this->_duplicate_emails_count[$email_address]);
299
+ }
300
+
301
+ // how come we need to do that sometimes? how a lines count could become negative?
302
+ if ($this->_lines_count < 0)
303
+ $this->_lines_count = 0;
304
+
305
+ // all of these numbers were useful at some point when we were showing more information after an import
306
+ $this->_data_numbers['ignored'] = ($this->_data_numbers['valid_email_processed'] - $this->_data_numbers['inserted']);
307
+ $this->_data_numbers['ignored_list'] = ( ($this->_data_numbers['list_user_ids'] * $this->_data_numbers['list_list_ids']) - $this->_data_numbers['list_added'] );
308
+
309
+
310
+ return $this->_data_numbers;
311
+ }
312
+
313
+ public function get_duplicate_emails_count() {
314
+ return $this->_duplicate_emails_count;
315
+ }
316
+
317
+ /**
318
+ * convert a csv string to an array
319
+ * @param type $csv_file_content
320
+ * @param type $rows_to_read
321
+ * @param type $delimiter
322
+ * @param type $enclosure
323
+ * @return array
324
+ */
325
+ private function _csv_to_array($csv_file_content, $rows_to_read = 0, $delimiter = ',', $enclosure = '') {
326
+ $data = array();
327
+
328
+ if( !(in_array($delimiter, $this->_field_separators_to_test) && in_array($enclosure, $this->_field_enclosers_to_test)) ){
329
+ $this->error('Unknown csv separators.');
330
+ return false;
331
+ }
332
+
333
+ // the new way for splitting a string into an array of lines
334
+ $csv_data_array = explode( $this->_line_delimiter, $csv_file_content );
335
+
336
+ $i=1;
337
+ foreach($csv_data_array as $csv_line){
338
+ if($rows_to_read!=0 && $i> $rows_to_read) return $data;
339
+
340
+ // str_getcsv only exists in php5 and is a faster and cleaner function than our csv_explode
341
+ if (!function_exists('str_getcsv') || strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
342
+ $data[] = $this->_lines_explode($csv_line, $delimiter, $enclosure);
343
+ } else {
344
+ $data[] = str_getcsv($csv_line, $delimiter, $enclosure);
345
+
346
+ }
347
+
348
+ $i++;
349
+ }
350
+
351
+ return $data;
352
+ }
353
+
354
+ /**
355
+ * explode lines to columns
356
+ * @param type $csv_line
357
+ * @param type $delimiter
358
+ * @param type $enclose
359
+ * @param type $preserve
360
+ * @return type
361
+ */
362
+ private function _lines_explode($csv_line, $delimiter, $enclose, $preserve = false) {
363
+ $resArr = array();
364
+ $n = 0;
365
+ if (empty($enclose)) {
366
+ $resArr = explode($delimiter, $csv_line);
367
+ } else {
368
+ $expEncArr = explode($enclose, $csv_line);
369
+ foreach ($expEncArr as $EncItem) {
370
+ if ($n++ % 2) {
371
+ array_push($resArr, array_pop($resArr) . ($preserve ? $enclose : '') . $EncItem . ( $preserve ? $enclose : ''));
372
+ } else {
373
+ $expDelArr = explode($delimiter, $EncItem);
374
+ array_push($resArr, array_pop($resArr) . array_shift($expDelArr));
375
+ $resArr = array_merge($resArr, $expDelArr);
376
+ }
377
+ }
378
+ }
379
+
380
+ return $resArr;
381
+ }
382
+
383
+ /**
384
+ * function processing a chunk of a csv array to import it in the DB
385
+ * @global object $wpdb
386
+ * @param array $csv_chunk
387
+ * @return boolean|string
388
+ */
389
+ private function _import_rows($csv_chunk) {
390
+
391
+ global $wpdb;
392
+
393
+ $this->_emails_inserted_in_current_chunk = array();
394
+ $time = time();
395
+ $lines = array();
396
+ $lines_count = count($csv_chunk);
397
+ $columns_count = count($this->_data_to_insert);
398
+
399
+ $query = $this->_get_import_query_header();
400
+
401
+ // make sure that each line has the right numbers of columns if it doesn't then we can skip it
402
+ foreach ($csv_chunk as $k => $line) {
403
+ if (!(count($line) >= (count($this->_data_to_insert) - 1))) {
404
+ unset($csv_chunk[$k]);
405
+ $lines_count--;
406
+ }
407
+ }
408
+
409
+ $valid_email_processed = 0;
410
+ $j = 1;
411
+
412
+ foreach ($csv_chunk as $key_line => $line) {
413
+
414
+ // if first row is not data but header then we just skip it only on the first chunk
415
+ if ($this->_first_row_is_data === false && $j == 1 && $this->_chunks_count == 0) {
416
+ $j++;
417
+ continue;
418
+ }
419
+
420
+ $i = 1;
421
+ $values = array();
422
+
423
+ // TODO maybe we should check the value of the status column so that if we export a wysija's subscribers' list
424
+ // and import it again in another site then we keep the status
425
+ if (isset($this->_data_to_insert['status']))
426
+ $line['status'] = 1;
427
+
428
+ foreach ($line as $key_column => &$value_column) {
429
+
430
+ // make sure this column is a column we want to insert in our DB
431
+ if (isset($this->_data_to_insert[$key_column])) {
432
+ $column_name = $this->_data_to_insert[$key_column];
433
+ $original_value_column = $value_column;
434
+ $value_column = $this->_validate_value($column_name, $value_column);
435
+
436
+ // if it is a a date column, we convert it as a unixtimestamp
437
+ if(isset($this->_custom_fields[$column_name]) && $this->_custom_fields[$column_name]->type == 'date'){
438
+ $value_column = strtotime($value_column);
439
+ }
440
+
441
+ // this kind of result invalidates the whole row
442
+ if ($value_column === false) {
443
+ // record the invalid row and continue with the loop
444
+ $this->_data_numbers['invalid'][] = $original_value_column;
445
+ unset($csv_chunk[$key_line]);
446
+ $lines_count--;
447
+ continue 2;
448
+ } else {
449
+ // only if this is the email row we record an entry in the recorded emails and the email processed count
450
+ if ($this->_email_key === $key_column) {
451
+ $this->_emails_inserted_in_current_chunk[] = $value_column;
452
+ $valid_email_processed++;
453
+ }
454
+ }
455
+
456
+ // prepare the query
457
+ $values[] = "'" . esc_sql($value_column, $wpdb->dbh) . "'";
458
+ }
459
+ }
460
+
461
+ $values[] = $time;
462
+ $lines[] .= "(" . implode(', ', $values) . ")";
463
+ }
464
+
465
+ $query .= implode(', ', $lines);
466
+
467
+ // update values when the user already exists
468
+ $query .= ' ON DUPLICATE KEY UPDATE '.implode(', ', array_map(array($this, 'process_data_to_insert'), $this->_data_to_insert));
469
+
470
+ // replace query to import the subscribers
471
+ $model_wysija = new WYSIJA_model();
472
+ $import_query = $model_wysija->query($query);
473
+
474
+ $lines_count = $wpdb->rows_affected;
475
+ $this->_data_numbers['inserted'] += $wpdb->rows_affected;
476
+ $this->_data_numbers['valid_email_processed'] += $valid_email_processed;
477
+
478
+ if ($import_query === false) {
479
+ $this->error(__('Error when inserting emails.', WYSIJA), true);
480
+ return false;
481
+ }
482
+ $time_now = time();
483
+ $result_query_import_list = $this->_import_new_users_into_lists($time_now);
484
+
485
+ $this->_trigger_active_autoresponders($time_now);
486
+
487
+ if ($result_query_import_list === false) {
488
+ $this->error(__('Error when inserting list.', WYSIJA), true);
489
+ return false;
490
+ }
491
+
492
+ if ($import_query == 0)
493
+ return '0';
494
+
495
+ return $lines_count;
496
+ }
497
+
498
+ /**
499
+ * used to validate or cast values before importing
500
+ * TODO should we add a type for import of custom fields ?
501
+ * Comment : Marco, feel free to modify entirely
502
+ * @param type $column_name
503
+ * @param type $value
504
+ */
505
+ function _validate_value($column_name, $value) {
506
+ $value = esc_attr(trim($value));
507
+
508
+ switch ($column_name) {
509
+ case 'email':
510
+ return is_email($value);
511
+ break;
512
+ case 'status':
513
+
514
+ if (in_array(strtolower($value), array('subscribed', 'confirmed', 1, '1', 'true'))) {
515
+ return 1;
516
+ } elseif (in_array(strtolower($value), array('unsubscribed', -1, '-1', 'false'))) {
517
+ return -1;
518
+ } elseif (in_array(strtolower($value), array('unconfirmed', 0, '0'))) {
519
+ return 0;
520
+ }
521
+ else
522
+ return 1;
523
+ break;
524
+ default :
525
+ return $value;
526
+ }
527
+ }
528
+
529
+ /**
530
+ * take care of active autoresponders retro-activity
531
+ * @param type $time_now
532
+ * @return boolean
533
+ */
534
+ private function _trigger_active_autoresponders($time_now) {
535
+ $helper_email = WYSIJA::get('email', 'helper');
536
+ $model_wysija = new WYSIJA_model();
537
+
538
+ // list the active auto responders emails
539
+ $active_autoresponders_per_list = $helper_email->get_active_follow_ups(array('email_id', 'params'), true);
540
+
541
+ if (!empty($active_autoresponders_per_list)) {
542
+ foreach ($_REQUEST['wysija']['user_list']['list'] as $list_id) {
543
+ // checking if this list has a list of follow ups
544
+ if (isset($active_autoresponders_per_list[$list_id])) {
545
+ // for each follow up of that list we queu an email
546
+ foreach ($active_autoresponders_per_list[$list_id] as $key_queue => $follow_up) {
547
+ // insert query per active followup
548
+ $query_queue = 'INSERT IGNORE INTO [wysija]queue (`email_id` ,`user_id`,`send_at`) ';
549
+ $query_queue .= ' SELECT ' . (int)$follow_up['email_id'] . ' , B.user_id , ' . ($time_now + $follow_up['delay']);
550
+ $query_queue .= ' FROM [wysija]user_list as B';
551
+ $query_queue .= ' WHERE B.list_id=' . (int) $list_id . ' AND sub_date=' . $time_now;
552
+
553
+ $model_wysija->query($query_queue);
554
+
555
+ $this->_data_numbers['emails_queued'] += $wpdb->rows_affected;
556
+ }
557
+ }
558
+ }
559
+ return true;
560
+ }
561
+ return false;
562
+ }
563
+
564
+ /**
565
+ *
566
+ * @global type $wpdb
567
+ * @param type $time_now
568
+ * @return type
569
+ */
570
+ private function _import_new_users_into_lists($time_now) {
571
+ global $wpdb;
572
+ $wpdb->rows_affected = 0;
573
+ $model_wysija = new WYSIJA_model();
574
+
575
+ $user_ids = $this->_get_imported_user_ids();
576
+
577
+ // insert query per list
578
+ $query = 'INSERT IGNORE INTO [wysija]user_list (`list_id` ,`user_id`,`sub_date`) VALUES ';
579
+
580
+ foreach ($_REQUEST['wysija']['user_list']['list'] as $keyl => $list_id) {
581
+ if (empty($list_id))
582
+ continue;
583
+ // for each list pre selected go through that process
584
+ foreach ($user_ids as $key => $user_data) {
585
+
586
+ // inserting each user id to this list
587
+ $query.='(' . (int)$list_id . ' , ' . (int)$user_data['user_id'] . ' , ' . (int)$time_now . ')';
588
+
589
+ // if this is not the last row we put a comma for the next row
590
+ if (count($user_ids) > ($key + 1)) {
591
+ $query.=' , ';
592
+ }
593
+ }
594
+
595
+ // if this is not the last row we put a comma for the next row
596
+ if (count($_REQUEST['wysija']['user_list']['list']) > ($keyl + 1)) {
597
+ $query.=',';
598
+ }
599
+ }
600
+
601
+ $result_query = $model_wysija->query($query);
602
+
603
+ $this->_data_numbers['list_added']+=$wpdb->rows_affected;
604
+ $this->_data_numbers['list_user_ids']+=count($user_ids);
605
+ return $result_query;
606
+ }
607
+
608
+ /**
609
+ * get a list of user_ids freshly imported
610
+ * @return type
611
+ */
612
+ private function _get_imported_user_ids() {
613
+ $model_user = WYSIJA::get('user', 'model');
614
+ // select query to get all of the ids of the emails that have just been inserted
615
+ return $model_user->get(array('user_id'), array('email' => $this->_emails_inserted_in_current_chunk));
616
+ }
617
+
618
+
619
+ /**
620
+ * this save a default list of column matching to ease the import process, this is done only the first time when the
621
+ * field is not populated yet
622
+ */
623
+ private function _save_default_import_field_match(){
624
+ $import_fields = get_option('wysija_import_fields');
625
+ if (!$import_fields) {
626
+ $import_fields = array(
627
+ 'fname' => 'firstname',
628
+ 'firstname' => 'firstname',
629
+ 'prenom' => 'firstname',
630
+ 'nom' => 'lastname',
631
+ 'name' => 'lastname',
632
+ 'lastname' => 'lastname',
633
+ 'lname' => 'lastname',
634
+ 'ipaddress' => 'ip',
635
+ 'ip' => 'ip',
636
+ 'addresseip' => 'ip',
637
+ );
638
+ WYSIJA::update_option('wysija_import_fields', $import_fields);
639
+ }
640
+ }
641
+
642
+
643
+ /**
644
+ * put the whole file or posted string into one string and clean up the string that may cause trouble during import
645
+ * @return boolean
646
+ */
647
+ private function _get_csv_file_cleaned_up(){
648
+ // is it a text import or a file import?
649
+ if($_POST['wysija']['import']['type'] == 'copy'){
650
+ if(!isset($_POST['wysija']['user_list']['csv'])){
651
+ // memory limit has been reached
652
+ $this->error(__('The list you\'ve pasted is too big for the browser. <strong>Upload the file</strong> instead.', WYSIJA), true);
653
+ return false;
654
+ }
655
+ $this->_csv_file_string = trim(stripslashes($_POST['wysija']['user_list']['csv']));
656
+
657
+ }else{
658
+ // move_uploaded_file($_importfile, $destination);
659
+ $this->_csv_file_string = trim(file_get_contents($_FILES['importfile']['tmp_name']));
660
+ }
661
+
662
+ $this->_csv_file_string = str_replace(array("\r", "\n\n", "\n\t\t\n\t\n\t\n\t\n", "\n\t\t\n\t\n\t\n", "\xEF\xBB\xBF", "\n\t\n", "\n(+1)"), array("\n", "\n", "\n ;", "\n", '', ';', ''), $this->_csv_file_string);
663
+
664
+
665
+ // this might be gmail recipients(copy-paste from a gmail account) rare paste ...
666
+ if(!preg_match_all('/<([a-z0-9_\'&\.\-\+])+\@(([a-z0-9\-])+\.)+([a-z0-9]{2,10})+>/i' , $this->_csv_file_string , $matches)){
667
+ //return false;
668
+ }else{
669
+
670
+ if (substr($this->_csv_file_string, -1) != ",")
671
+ $this->_csv_file_string = trim($this->_csv_file_string) . ',';
672
+
673
+
674
+ if (count($matches[0]) == count($matches)) {
675
+ //this is gmail simple paste
676
+ $this->_csv_file_string = str_replace(array('>,', '<'), array("\n", ','), $this->_csv_file_string);
677
+ }
678
+ $this->_csv_file_string = trim($this->_csv_file_string);
679
+ }
680
+ }
681
+
682
+
683
+ /**
684
+ * try to figure out the format of that CSV file, which separators and enclosure strings does it use
685
+ * @return boolean
686
+ */
687
+ private function _run_test_on_csv_file(){
688
+ // try different set of enclosure and separator for the csv which can have different look depending on the data carried
689
+
690
+ $this->_csv_data['fsep'] = false;
691
+ $this->_csv_data['fenc'] = '';
692
+ $helper_user = WYSIJA::get('user','helper');
693
+
694
+ foreach($this->_field_enclosers_to_test as $enclosure){
695
+ foreach($this->_field_separators_to_test as $fsep){
696
+
697
+ // testing different combinations of separator and enclosers
698
+ $this->_csv_array = $this->_csv_to_array( $this->_csv_file_string, 10, $fsep, $enclosure );
699
+
700
+ // make sure that our CSV has more than one row and that it has the same number of values in the first row and the second row
701
+ if ( ( count( $this->_csv_array ) > 1 && count( $this->_csv_array[0] ) == count( $this->_csv_array[1] ) ) ) {
702
+ if ( count( $this->_csv_array[0] ) > 1 || $helper_user->validEmail( trim( $this->_csv_array[0][0] ) ) || $helper_user->validEmail( trim( $this->_csv_array[1][0] ) ) ) {
703
+ $this->_csv_data['fsep'] = $fsep;
704
+ $this->_csv_data['fenc'] = $enclosure;
705
+ break(2);
706
+ }
707
+ }
708
+ }
709
+ }
710
+
711
+ // if we didn't manage to find a separator in that file then it is not a csv file and we come out
712
+ if(empty($this->_csv_data['fsep'])){
713
+ $this->notice( sprintf(
714
+ "%s <a href='http://support.mailpoet.com/knowledgebase/importing-subscribers-with-a-csv-file/' target='_blank'>%s</a>",
715
+ __("The data you are trying to import doesn't appear to be in the CSV format (Comma Separated Values).", WYSIJA),
716
+ __("Read More", WYSIJA)
717
+ ) );
718
+ $this->notice(__('The first line of a CSV file should be the column headers : "email","lastname","firstname".',WYSIJA));
719
+ $this->notice(__('The second line of a CSV file should be a set of values : "joeeg@example.com","Average","Joe".',WYSIJA));
720
+
721
+ $this->notice(__('The two first lines of the file you\'ve uploaded are as follow:', WYSIJA));
722
+
723
+ $arraylines = explode("\n", $this->_csv_file_string);
724
+
725
+ if (empty($arraylines[0]))
726
+ $text = __('Line is empty', WYSIJA);
727
+ else
728
+ $text = $arraylines[0];
729
+ $this->notice('<strong>' . esc_html($text) . '</strong>');
730
+
731
+ if (empty($arraylines[1]))
732
+ $text = __('Line is empty', WYSIJA);
733
+ else
734
+ $text = $arraylines[1];
735
+ $this->notice('<strong>' . esc_html($text) . '</strong>');
736
+
737
+ return false;
738
+ }
739
+
740
+ // test the size of the file
741
+ $temp_csv_array = $this->_csv_to_array($this->_csv_file_string, 0, $this->_csv_data['fsep'], $this->_csv_data['fenc']);
742
+
743
+ $this->_data_result['totalrows'] = count($temp_csv_array);
744
+ end($temp_csv_array);
745
+ $this->_data_result['lastrow'] = current($temp_csv_array);
746
+ }
747
+
748
+
749
+ /**
750
+ * save the CSV string into a file so that we can use it later in the next step of the process
751
+ * @return boolean|string
752
+ */
753
+ private function _save_csv_file(){
754
+ // try to make a wysija dir to save the import file
755
+ $helper_file = WYSIJA::get('file', 'helper');
756
+ $result_dir = $helper_file->makeDir('import');
757
+ if (!$result_dir) {
758
+ return false;
759
+ }
760
+
761
+ $file_name = 'import-' . time() . '.csv';
762
+ $handle = fopen($result_dir . $file_name, 'w');
763
+ fwrite($handle, $this->_csv_file_string);
764
+ fclose($handle);
765
+
766
+ return $file_name;
767
+ }
768
+
769
+
770
+ /**
771
+ * detect which column is an email one
772
+ */
773
+ private function _test_csv_emails(){
774
+ $found_email = 0;
775
+ $this->_email_key = array();
776
+ $helper_user = WYSIJA::get('user', 'helper');
777
+ foreach ($this->_csv_array as $csv_row) {
778
+ foreach ($csv_row as $key_column => $value_column) {
779
+ if ($helper_user->validEmail(trim($value_column))) {
780
+ $found_email++;
781
+
782
+ $this->_email_key[$key_column] = $this->_csv_array[0][$key_column];
783
+ }
784
+ }
785
+ }
786
+
787
+ $this->_data_result['errormatch'] = false;
788
+ $check_again = __('Check again what you\'re trying to import.',WYSIJA);
789
+ if (($found_email < 1)) {
790
+ $this->error(__('We couldn\'t find any valid addresses in the first 10 rows.', WYSIJA).' '.$check_again, true);
791
+ }
792
+
793
+ if ((count($this->_csv_array) < 2)) {
794
+ $this->error(__('You\'re import file is not valid.', WYSIJA).' '.$check_again, true);
795
+ }
796
+ }
797
+
798
+
799
+ /**
800
+ * function used to scan the CSV before trying to match each column with our own fields
801
+ * @return boolean
802
+ */
803
+ public function scan_csv_file(){
804
+ $this->_data_result = array();
805
+
806
+ // make sure the import match will be as easy as possible with default matches
807
+ if( $this->_save_default_import_field_match() === false) return false;
808
+ // get the csv into a string and check for messy email address etc
809
+ if( $this->_get_csv_file_cleaned_up() === false) return false;
810
+ // find out the format of that CSV file comma semi colon etc ..
811
+ if( $this->_run_test_on_csv_file() === false) return false;
812
+
813
+ // save the string into a file for later use
814
+ $file_name = $this->_save_csv_file();
815
+ if ($file_name === false)
816
+ return false;
817
+
818
+ // look for the email column
819
+ $this->_test_csv_emails();
820
+
821
+ // stock the data we will use in the next page
822
+ $this->_data_result['csv'] = $this->_csv_array;
823
+
824
+ $data_import = array(
825
+ 'csv' => $file_name,
826
+ 'fsep' => $this->_csv_data['fsep'],
827
+ 'fenc' => $this->_csv_data['fenc']);
828
+ $this->_data_result['dataImport'] = base64_encode(json_encode($data_import));
829
+
830
+ $this->_data_result['keyemail'] = $this->_email_key;
831
+
832
+ //test if the first row is data or not
833
+ //test the email column
834
+ foreach ($this->_data_result['keyemail'] as $k)
835
+ $this->_email_key = $k;
836
+
837
+
838
+ // test whether the first row is a data row or is a descriptive header row
839
+ $helper_user = WYSIJA::get('user','helper');
840
+ if($helper_user->validEmail( $this->_email_key )){
841
+ $this->_data_result['firstrowisdata']=true;
842
+ }else{
843
+ $this->_data_result['totalrows']--;
844
+ }
845
+
846
+ return $this->_data_result;
847
+ }
848
+
849
+ private function process_data_to_insert($v) {
850
+ return '`'.$v.'` = VALUES(`'.$v.'`)';
851
+ }
852
+
853
+ }
trunk/classes/WJ_Settings.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * Settings.
5
+ * Global Wysija Premium settings singleton.
6
+ */
7
+ class WJ_Settings {
8
+
9
+ static private $db_prefix;
10
+ static private $name = 'wysija';
11
+
12
+ private function __construct(){}
13
+
14
+ // db_prefix();
15
+ // # => wp_wysija_
16
+ // db_prefix('custom_field');
17
+ // # => wp_wysija_custom_field
18
+ static function db_prefix($table_name = false) {
19
+ global $wpdb;
20
+ self::$db_prefix = $wpdb->prefix . self::$name . '_';
21
+ if ($table_name) {
22
+ $prefixed = self::$db_prefix . $table_name;
23
+ } else {
24
+ $prefixed = self::$db_prefix;
25
+ }
26
+ return $prefixed;
27
+ }
28
+
29
+ }
trunk/classes/WJ_Sparkpost.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WJ_Sparkpost {
5
+ public $error;
6
+ private $api_key = '';
7
+
8
+ public function __construct($api_key) {
9
+ $this->api_key = $api_key;
10
+ }
11
+
12
+ public function send_mail(& $object) {
13
+ $msg = array(
14
+ 'recipients' => array(
15
+ array(
16
+ 'address' => array(
17
+ 'email' => $object->to[0][0]
18
+ )
19
+ )
20
+ ),
21
+ 'content' => array(
22
+ 'from' => array(
23
+ 'name' => $object->FromName,
24
+ 'email' => $object->From
25
+ ),
26
+ 'reply_to' => $object->ReplyTo[0][0]
27
+ )
28
+ );
29
+
30
+ // set the subject
31
+ if(!empty ($object->Subject)) $msg['content']['subject'] = $object->Subject;
32
+
33
+ // set the body
34
+ if(!empty ($object->sendHTML) || !empty($object->AltBody)) {
35
+ $msg['content']['html'] = $object->Body;
36
+ if(!empty ($object->AltBody)) $msg['content']['text'] = $object->AltBody;
37
+ } else {
38
+ $msg['content']['text'] = $object->Body;
39
+ }
40
+
41
+ $url = 'https://api.sparkpost.com/api/v1/transmissions';
42
+
43
+ return $this->run($url, $msg);
44
+
45
+ }
46
+
47
+ protected function run($url, $msg) {
48
+ $return = null;
49
+ $params = array(
50
+ 'headers' => array(
51
+ 'Content-Type: application/json',
52
+ 'Authorization' => $this->api_key
53
+ ),
54
+ 'body' => json_encode($msg)
55
+ );
56
+
57
+ $result = null;
58
+ $result = wp_remote_post($url, $params);
59
+ try {
60
+ if(!is_wp_error($result)) {
61
+ switch($result['response']['code']) {
62
+ case 200:
63
+ $return = true;
64
+ break;
65
+ default:
66
+ $body = json_decode($result['body'], true);
67
+ if(isset($body['errors']) && isset($body['errors'][0]) && isset($body['errors'][0]['description'])) {
68
+ $this->error = $body['errors'][0]['description'];
69
+ } else {
70
+ $this->error = $result['response']['message'];
71
+ }
72
+ break;
73
+ }
74
+ } else {
75
+ $this->error = (is_wp_error($result)) ?
76
+ $result->get_error_messages() :
77
+ __('We were unable to contact the API, the site may be down. Please try again later.', WYSIJA);
78
+ }
79
+ } catch(Exception $e) {
80
+ $this->error = 'Unexpected error: ' . $e->getMessage() . ' [' . var_export($result, true) . ']';// do nothing
81
+ }
82
+
83
+ return $return;
84
+ }
85
+
86
+ }
trunk/classes/WJ_Stats.php ADDED
@@ -0,0 +1,491 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * Class Stats.
5
+ *
6
+ * Handling subscribers click and open action of an email
7
+ */
8
+ class WJ_Stats extends WYSIJA_object {
9
+
10
+ public $email_id = null;
11
+ public $user_id = null;
12
+ public $clicked_url = '';
13
+ public $is_preview = false;
14
+
15
+ /**
16
+ * Email object
17
+ * @var Wysija_email
18
+ */
19
+ private $_email;
20
+
21
+ /**
22
+ * User object
23
+ * @var Wysija_user
24
+ */
25
+ private $_user;
26
+
27
+ private $_url_id = null;
28
+ private $_unique_click = false;
29
+ public $decoded_url = '';
30
+
31
+
32
+ /**
33
+ * load some global variables into the class
34
+ */
35
+ function __construct() {
36
+ if (!empty($_REQUEST['email_id']))
37
+ $this->email_id = (int) $_REQUEST['email_id'];
38
+ if (!empty($_REQUEST['user_id']))
39
+ $this->user_id = (int) $_REQUEST['user_id'];
40
+ if (!empty($_REQUEST['demo']))
41
+ $this->is_preview = true;
42
+ $this->_get_clicked_url();
43
+
44
+ // $this->_user can be empty, it's helpful in case an email was sent as a preview to a non-existing user, then a link is opened from there
45
+ $this->_user = WYSIJA::get('user', 'model')->getOne(false,(int)$this->user_id);
46
+
47
+ $this->_email = WYSIJA::get('email', 'model')->getOne(false,(int)$this->email_id);
48
+ if (empty($this->_email))
49
+ exit;
50
+
51
+ // consider to get / insert URL record here
52
+ // $this->_url = $this->_get_url($this->clicked_url);
53
+ }
54
+
55
+ /**
56
+ * Get user object
57
+ * @param type $user_id
58
+ */
59
+ public function get_user() {
60
+ return $this->_user;
61
+ }
62
+
63
+ /**
64
+ * Get email object
65
+ * @param type $user_id
66
+ */
67
+ public function get_email() {
68
+ return $this->_email;
69
+ }
70
+
71
+ /**
72
+ * count the action as an open and display the empty picture
73
+ */
74
+ public function subscriber_opened() {
75
+ if (!$this->_is_open_action())
76
+ exit;
77
+
78
+ $model_email_user_stat = WYSIJA::get('email_user_stat', 'model');
79
+ $model_email_user_stat->reset();
80
+
81
+ // update status to 1 and set opened_at time
82
+ // only if the status = 0
83
+ $model_email_user_stat->update(
84
+ array('status' => 1, 'opened_at' => time()),
85
+ array('email_id' => $this->email_id, 'user_id' => $this->user_id, 'status' => 0)
86
+ );
87
+
88
+ $this->_update_user(array('last_opened' => time()));
89
+
90
+ header('Cache-Control: no-store, no-cache, must-revalidate');
91
+ header('Cache-Control: post-check=0, pre-check=0', false);
92
+ header('Pragma: no-cache');
93
+
94
+ if (empty($picture))
95
+ $picture = WYSIJA_DIR_IMG . 'statpicture.png';
96
+ $handle = fopen($picture, 'r');
97
+
98
+ if (!$handle)
99
+ exit;
100
+ header('Content-type: image/png');
101
+ $contents = fread($handle, filesize($picture));
102
+ fclose($handle);
103
+ echo $contents;
104
+ exit;
105
+ }
106
+
107
+ public function subscriber_clicked() {
108
+ if (!$this->_is_click_action())
109
+ exit;
110
+
111
+ if ($this->email_id && $this->is_preview === false) { //if not email_id that means it is an email preview
112
+ $this->_record_url();
113
+
114
+ $this->_record_user_url();
115
+
116
+ $this->_record_url_mail();
117
+
118
+ $redirect = $this->_record_email_user_stat();
119
+ if (!empty($redirect))
120
+ $this->decoded_url = $redirect;
121
+ $this->_update_user(array('last_clicked' => time()));
122
+ }else {
123
+ $this->_get_url_preview();
124
+ }
125
+ //sometimes this will be a life saver :)
126
+ $this->decoded_url = str_replace('&amp;', '&', $this->decoded_url);
127
+ if ($this->is_browser_link($this->decoded_url)) {
128
+ $this->decoded_url = $this->attach_user($this->decoded_url);
129
+ }
130
+ return $this->decoded_url;
131
+ }
132
+
133
+ /**
134
+ * Attach user_id as a param of an url
135
+ * @param string $url
136
+ * @param int $user_id
137
+ * @return string
138
+ */
139
+ protected function attach_user($url) {
140
+ if (!empty($this->_user) && !empty($this->_user['user_id'])) {
141
+ $url_components = parse_url($url);
142
+ $arr_params = array();
143
+ if (!empty($url_components['query']))
144
+ parse_str($url_components['query'],$arr_params);
145
+ if (empty($arr_params['user_id'])) {
146
+ $url .= ((strpos($url, '?') !== false) ? '&' : '?');
147
+ $url .= 'user_id='.$this->_user['user_id'];
148
+ }
149
+ }
150
+ return $url;
151
+ }
152
+
153
+ /**
154
+ * record entry into the table email_user_url
155
+ */
156
+ private function _record_user_url() {
157
+ //look for email_user_url entry and insert if not exists
158
+ $model_email_user_url = WYSIJA::get('email_user_url', 'model');
159
+ $data_email_user_url = array('email_id' => $this->email_id, 'user_id' => $this->user_id, 'url_id' => $this->_url_id);
160
+ $email_user_url_array = $model_email_user_url->getOne(false, $data_email_user_url);
161
+
162
+ if (!$email_user_url_array && $this->email_id > 0 && $this->user_id > 0 && $this->_url_id > 0) {
163
+ //we need to insert in email_user_url
164
+ $model_email_user_url->reset();
165
+ $query_EmailUserUrl = 'INSERT IGNORE INTO [wysija]email_user_url (`email_id` ,`user_id`,`url_id`) ';
166
+ $query_EmailUserUrl .= 'VALUES (' . $this->email_id . ', ' . $this->user_id . ', ' . $this->_url_id . ')';
167
+
168
+ $model_email_user_url->query($query_EmailUserUrl);
169
+
170
+ //$modelEmailUserUrl->insert($dataEmailUserUrl);
171
+ $this->_unique_click = true;
172
+ }
173
+
174
+ //increment stats counter on email_user_url clicked
175
+ $model_email_user_url = WYSIJA::get('email_user_url', 'model');
176
+ $model_email_user_url->update(array('clicked_at' => time(), 'number_clicked' => '[increment]'), $data_email_user_url);
177
+ }
178
+
179
+ /**
180
+ * record entry into the table url_mail
181
+ */
182
+ private function _record_url_mail() {
183
+ //look for url_mail entry and insert if not exists
184
+ $model_url_mail = WYSIJA::get('url_mail', 'model');
185
+ $data_url_mail = array('email_id' => $this->email_id, 'url_id' => $this->_url_id);
186
+ $urlMailObj = $model_url_mail->getOne(false, $data_url_mail);
187
+ if (!$urlMailObj) {
188
+ //we need to insert in url_mail
189
+ $model_url_mail->reset();
190
+ $model_url_mail->insert($data_url_mail);
191
+ }
192
+
193
+ $data_update = array('total_clicked' => '[increment]');
194
+ if (!$this->_unique_click)
195
+ $data_update['unique_clicked'] = '[increment]';
196
+ //increment stats counter on url_mail clicked
197
+ $model_url_mail->update($data_update, $data_url_mail);
198
+ }
199
+
200
+ /**
201
+ * record entry into the table email_user_stat
202
+ */
203
+ private function _record_email_user_stat() {
204
+ // clicked status
205
+ $status_email_user_stat = 2;
206
+
207
+ // this is the system url case (unsubscribe, view in browser and subscriptions)
208
+ if (in_array($this->clicked_url, array('[unsubscribe_link]', '[subscriptions_link]', '[view_in_browser_link]'))) {
209
+ $this->subscriberClass = WYSIJA::get('user', 'model');
210
+ $this->subscriberClass->getFormat = OBJECT;
211
+
212
+ //check if the security hash is passed to insure privacy
213
+ $receiver = $link = false;
214
+ if (isset($_REQUEST['hash'])) {
215
+ if ($_REQUEST['hash'] == md5(AUTH_KEY . $this->clicked_url . $this->user_id)) {
216
+ $receiver = $this->subscriberClass->getOne(array('user_id' => $this->user_id));
217
+ } else {
218
+ die('Security check failure.');
219
+ }
220
+ } else {
221
+ //link is not valid anymore
222
+ //propose to resend the newsletter with good links ?
223
+ $link = $this->subscriberClass->old_get_new_link_for_expired_links($this->user_id, $this->email_id);
224
+ }
225
+
226
+
227
+ switch ($this->clicked_url) {
228
+ case '[unsubscribe_link]':
229
+ // we need to make sure that this link belongs to that user
230
+ if ($receiver) {
231
+ $link = $this->subscriberClass->getUnsubLink($receiver, true);
232
+ // unsubscribe status
233
+ $status_email_user_stat = 3;
234
+ }
235
+ break;
236
+ case '[subscriptions_link]':
237
+ if ($receiver) {
238
+ $link = $this->subscriberClass->getEditsubLink($receiver, true);
239
+ }
240
+ break;
241
+ case '[view_in_browser_link]':
242
+ $model_email = WYSIJA::get('email', 'model');
243
+ $data_email = $model_email->getOne(false, array('email_id' => $this->email_id));
244
+ $helper_email = WYSIJA::get('email', 'helper');
245
+ $link = $helper_email->getVIB($data_email);
246
+ break;
247
+ }
248
+
249
+ //if the subscriber already exists in the DB we will have a link
250
+ if ($link) {
251
+ $this->decoded_url = $link;
252
+ } else {
253
+ //the subscriber doesn't appear in the DB we can redirect to the web version
254
+ $this->decoded_url = $this->_get_browser_link();
255
+
256
+ return $this->decoded_url;
257
+ }
258
+ } else {
259
+ // this is the standard non-system url case
260
+ if (strpos($this->decoded_url, 'http://') === false && strpos($this->decoded_url, 'https://') === false) {
261
+ $this->decoded_url = 'http://' . $this->decoded_url;
262
+ }
263
+
264
+ // check that there is no broken unsubscribe link such as http://[unsubscribe_link]
265
+ if (strpos($this->decoded_url, '[unsubscribe_link]') !== false) {
266
+ $this->subscriberClass = WYSIJA::get('user', 'model');
267
+ $this->subscriberClass->getFormat = OBJECT;
268
+ $receiver = $this->subscriberClass->getOne($this->user_id);
269
+ $this->decoded_url = $this->subscriberClass->getUnsubLink($receiver, true);
270
+ }
271
+
272
+ if (strpos($this->decoded_url, '[view_in_browser_link]') !== false) {
273
+ $link = $this->_get_browser_link();
274
+ $this->decoded_url = $link;
275
+ }
276
+ }
277
+
278
+ $data_update = array();
279
+
280
+ // check if we already have a record
281
+ $model_email_user_stat = WYSIJA::get('email_user_stat', 'model');
282
+ $exists = $model_email_user_stat->getOne(false, array('equal' => array('email_id' => $this->email_id, 'user_id' => $this->user_id), 'less' => array('status' => $status_email_user_stat)));
283
+
284
+ // fix "opened_at" value in case the "opened" status was not properly recorded (blocked images)
285
+ if(is_array($exists) && array_key_exists('opened_at', $exists) && (int)$exists['opened_at'] === 0) {
286
+ // set opened at in case it was not recorded
287
+ $data_update['opened_at'] = time();
288
+ }
289
+
290
+ $model_email_user_stat->reset();
291
+ $model_email_user_stat->colCheck = false;
292
+
293
+ // set new status
294
+ $data_update['status'] = $status_email_user_stat;
295
+
296
+ // update email user stat
297
+ $model_email_user_stat->update($data_update, array('equal' => array('email_id' => $this->email_id, 'user_id' => $this->user_id), 'less' => array('status' => $status_email_user_stat)));
298
+ }
299
+
300
+ /**
301
+ * update the user last_clicked or last_opened parameter
302
+ * @param type $data_update
303
+ */
304
+ private function _update_user($data_update) {
305
+ if (!empty($data_update)) {
306
+ $model_user = WYSIJA::get('user', 'model');
307
+ $model_user->update($data_update, array('user_id' => $this->user_id));
308
+ }
309
+ }
310
+
311
+ /**
312
+ * when the email sent is a preview email, we just need to emulate actions, no need to count stats or to unsubscribe user etc ...
313
+ * @return boolean
314
+ */
315
+ private function _get_url_preview() {
316
+ // we're in the case of an email preview
317
+ if (in_array($this->clicked_url, array('[unsubscribe_link]', '[subscriptions_link]', '[view_in_browser_link]'))) {
318
+ $model_user = WYSIJA::get('user', 'model');
319
+ $model_user->getFormat = OBJECT;
320
+ $user_object = $model_user->getOne(false, array('wpuser_id' => get_current_user_id()));
321
+ switch ($this->clicked_url) {
322
+ case '[unsubscribe_link]':
323
+ $link = $model_user->getConfirmLink($user_object, 'unsubscribe', false, true) . '&demo=1';
324
+
325
+ break;
326
+ case '[subscriptions_link]':
327
+ $link = $model_user->getConfirmLink($user_object, 'subscriptions', false, true) . '&demo=1';
328
+ break;
329
+ case 'view_in_browser_link':
330
+ case '[view_in_browser_link]':
331
+ if (!$this->email_id)
332
+ $this->email_id = $_REQUEST['id'];
333
+
334
+ $link = $this->_get_browser_link();
335
+ break;
336
+ }
337
+
338
+ $this->decoded_url = $link;
339
+ }else {
340
+ if (strpos($this->decoded_url, 'http://') === false && strpos($this->decoded_url, 'https://') === false)
341
+ $this->decoded_url = 'http://' . $this->decoded_url;
342
+ }
343
+ return true;
344
+ }
345
+
346
+ /**
347
+ * construct the view in your browser link
348
+ * @return type
349
+ */
350
+ private function _get_browser_link() {
351
+ $params_url = array(
352
+ 'wysija-page' => 1,
353
+ 'controller' => 'email',
354
+ 'action' => 'view',
355
+ 'email_id' => $this->email_id,
356
+ 'user_id' => 0
357
+ );
358
+ $config = WYSIJA::get('config', 'model');
359
+ return WYSIJA::get_permalink($config->getValue('confirm_email_link'), $params_url);
360
+ }
361
+
362
+ /**
363
+ * Detect if the current link is a browser link
364
+ * @param string $url
365
+ * @return boolean
366
+ */
367
+ protected function is_browser_link($url) {
368
+ $flag = false;
369
+ $helper_toolbox = WYSIJA::get('toolbox', 'helper');
370
+ if ($helper_toolbox->is_internal_link($url)) {
371
+ $url_components = parse_url($url);
372
+ if (!empty($url_components['query'])) {
373
+ $params = array();
374
+ parse_str($url_components['query'], $params);
375
+ if (!empty($params['controller']) && strtolower($params['controller']) == 'email'
376
+ && !empty($params['action']) && strtolower($params['action']) == 'view'
377
+ ) {
378
+ $flag = true;
379
+ }
380
+ }
381
+ }
382
+ return $flag;
383
+ }
384
+
385
+ /**
386
+ * check that this is a valid open action
387
+ * @return boolean
388
+ */
389
+ private function _is_open_action() {
390
+ if (empty($this->email_id) || empty($this->user_id))
391
+ return false;
392
+
393
+ return true;
394
+ }
395
+
396
+ /**
397
+ * check that this is a valid click action
398
+ * @return boolean
399
+ */
400
+ private function _is_click_action() {
401
+ if ((empty($this->email_id) || empty($this->user_id) || empty($this->clicked_url)) && $this->is_preview === false)
402
+ return false;
403
+
404
+ return true;
405
+ }
406
+
407
+ /**
408
+ * record the url into the db if not recorded already
409
+ * @return boolean
410
+ */
411
+ private function _record_url() {
412
+ //look for url entry and insert if not exists
413
+ $model_url = WYSIJA::get('url', 'model');
414
+ $url_found = $model_url->getOne(false, array('url' => $this->clicked_url));
415
+
416
+ if ($url_found) {
417
+ // we need to keep it
418
+ $this->_url_id = $url_found['url_id'];
419
+ } else {
420
+ // we need to record in database
421
+ $this->_url_id = $model_url->insert(array('url' => $this->clicked_url));
422
+ }
423
+ }
424
+
425
+ /**
426
+ * get/alter clicked url based on the global parameters
427
+ */
428
+ private function _get_clicked_url() {
429
+
430
+ if (isset($_REQUEST['urlencoded'])) {
431
+ $this->clicked_url = $_REQUEST['urlencoded'];
432
+ } elseif (isset($_REQUEST['urlpassed'])) {
433
+ $this->clicked_url = $_REQUEST['urlpassed'];
434
+ }
435
+
436
+ // make sure the url is or is not base64 encoded, some server cannot handle long url or url with encoded parameter which is the default behaviour
437
+ if (isset($_REQUEST['no64'])) {
438
+ $this->decoded_url = $this->clicked_url;
439
+ } else {
440
+ $this->clicked_url = $this->decoded_url = base64_decode($this->clicked_url);
441
+ }
442
+
443
+ if (strpos($this->clicked_url, 'utm_source') !== false) {
444
+ $this->clicked_url = $this->_clean_params_url(array('utm_source', 'utm_campaign', 'utm_medium'), $this->clicked_url);
445
+ }
446
+ return true;
447
+ }
448
+
449
+ /**
450
+ * remove any params from a url
451
+ * @param array $params_to_remove
452
+ * @param string $url
453
+ * @return string
454
+ */
455
+ private function _clean_params_url($params_to_remove = array(), $url = '') {
456
+ if (!$url){
457
+ return $url;
458
+ }
459
+
460
+ $url_splitted = explode('?', $url);
461
+ $params_in_url = array();
462
+
463
+ // lets parse the parameters of the url
464
+ parse_str($url_splitted[1], $params_in_url);
465
+
466
+ foreach ($params_to_remove as $param_key){
467
+ unset($params_in_url[$param_key]);
468
+ }
469
+
470
+ // let's use the base of that url to rebuild it without the cleaned out parameters.
471
+ $new_url = $url_splitted[0];
472
+
473
+ // when there are params left other than the ones we cleaned out of the url, we stick them back together
474
+ if($params_in_url) {
475
+ $new_url .= '?';
476
+ $i = 0;
477
+ foreach ($params_in_url as $k => $v) {
478
+ if ($i > 0){
479
+ $new_url .= '&';
480
+ }
481
+
482
+ // parse_str keeps the ampersand as a html number, let's clean it out so that the url look good when recorded
483
+ $new_url .= str_replace($k,'&#38;','') . '=' . $v;
484
+ $i++;
485
+ }
486
+ }
487
+
488
+ return $new_url;
489
+ }
490
+
491
+ }
trunk/classes/WJ_StatsSessionManager.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WJ_StatsSession {
5
+ public $last_days = null;
6
+ public $from = null;
7
+ public $to = null;
8
+ }
9
+
10
+ class WJ_StatsSessionManager {
11
+ /**
12
+ * default selection of predefined dates
13
+ * @var WJ_StatsSession
14
+ */
15
+ protected $default_selection;
16
+
17
+ protected $pre_defined_dates;
18
+
19
+ public function __construct(){}
20
+
21
+ public function set_pre_defined_dates(Array $pre_defined_dates) {
22
+ $this->pre_defined_dates = $pre_defined_dates;
23
+ }
24
+
25
+ public function get_pre_defined_dates() {
26
+ return $this->pre_defined_dates;
27
+ }
28
+
29
+ public function set_default_selection(WJ_StatsSession $stats_session) {
30
+ $this->default_selection = $stats_session;
31
+ }
32
+
33
+ public function get_default_selection() {
34
+ return $this->default_selection;
35
+ }
36
+
37
+ public function get_last_selection() {
38
+ $last_selection = new WJ_StatsSession();
39
+
40
+ $stats_session_last_days = $this->get_stats_session_last_days();
41
+ if ($stats_session_last_days !== null) {
42
+ $last_selection->last_days = $stats_session_last_days;
43
+ if ($stats_session_last_days == 0) {// custom dates, "from" and "to" are fixed since the last session
44
+ $last_selection->from = $this->get_stats_session_from();
45
+ $last_selection->to = $this->get_stats_session_to();
46
+ } else {// pre-defined dates, "from" and "to" are relatively assigned
47
+ $pre_defined_dates = $this->get_pre_defined_dates();
48
+ foreach ($pre_defined_dates as $pre_defined_date) {
49
+ if ($pre_defined_date['value'] == $stats_session_last_days) {
50
+ $last_selection->from = $pre_defined_date['from'];
51
+ $last_selection->to = $pre_defined_date['to'];
52
+ break;
53
+ }
54
+ }
55
+ }
56
+ } else {
57
+ $last_selection = $this->get_default_selection();
58
+ }
59
+
60
+ $this->set_last_selection($last_selection);
61
+
62
+ return $last_selection;
63
+ }
64
+
65
+ public function set_last_selection(WJ_StatsSession $stats_session) {
66
+ $this->set_stats_session_last_days($stats_session->last_days);
67
+ $this->set_stats_session_from($stats_session->from);
68
+ $this->set_stats_session_to($stats_session->to);
69
+ }
70
+
71
+ protected function is_default_selection(WJ_StatsSession $stats_session) {
72
+ $stats_session = $stats_session;
73
+ return true;
74
+ }
75
+
76
+ protected function set_stats_session_last_days($value) {
77
+ setcookie('stats_session_last_days', $value);
78
+ }
79
+
80
+ protected function get_stats_session_last_days() {
81
+ return isset($_COOKIE['stats_session_last_days']) ? $_COOKIE['stats_session_last_days'] : null;
82
+ }
83
+
84
+ protected function set_stats_session_from($value) {
85
+ setcookie('stats_session_from', $value);
86
+ }
87
+
88
+ protected function get_stats_session_from() {
89
+ return isset($_COOKIE['stats_session_from']) ? $_COOKIE['stats_session_from'] : null;
90
+ }
91
+
92
+ protected function set_stats_session_to($value) {
93
+ setcookie('stats_session_to', $value);
94
+ }
95
+
96
+ protected function get_stats_session_to() {
97
+ return isset($_COOKIE['stats_session_to']) ? $_COOKIE['stats_session_to'] : null;
98
+ }
99
+ }
100
+
trunk/classes/WJ_Upgrade.php ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WJ_Upgrade extends WYSIJA_object {
4
+ /**
5
+ * A static variable that holds a dinamic instance of the class
6
+ * @var [object||null]
7
+ */
8
+ public static $instance = null;
9
+
10
+ public static $plugins = array( 'wysija-newsletters/index.php', 'wysija-newsletters-premium/index.php' );
11
+
12
+ public static $baseurl = array(
13
+ 'core' => 'https://downloads.wordpress.org/plugin/',
14
+ 'packager' => 'http://packager.mailpoet.com/release/',
15
+ );
16
+
17
+ public static function hook(){
18
+ null === self::$instance and self::$instance = new self;
19
+
20
+ if ( ! is_admin() ) {
21
+ return;
22
+ }
23
+
24
+ self::$baseurl = (object) self::$baseurl;
25
+
26
+ add_action( 'current_screen', array( self::$instance, 'setup_bulk_screen' ) );
27
+ add_action( 'shutdown', array( self::$instance, 'setup_bulk_screen_footer' ) );
28
+ add_action( 'current_screen', array( self::$instance, 'iframe_intercept' ) );
29
+
30
+ add_action( 'init', array( self::$instance, 'update_warning' ) );
31
+
32
+ add_filter( 'pre_set_site_transient_update_plugins', array( self::$instance, 'pre_set_site_transient_update_plugins' ), 100 );
33
+ }
34
+
35
+ public function update_warning() {
36
+ if ( ! is_admin() ){
37
+ return;
38
+ }
39
+
40
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
41
+ return;
42
+ }
43
+
44
+ if ( ! ( ( is_multisite() && current_user_can( 'manage_network' ) ) || current_user_can( 'update_plugins' ) ) ){
45
+ return;
46
+ }
47
+
48
+ if ( ! function_exists( 'get_plugin_data' ) ){
49
+ include_once ABSPATH . 'wp-admin/includes/plugin.php';
50
+ }
51
+
52
+ $current = get_site_transient( 'update_plugins' );
53
+
54
+ foreach ( self::$plugins as $plugin ){
55
+ if ( isset( $current->response[ $plugin ] ) ){
56
+ $data = self::get_plugin_data( $plugin );
57
+
58
+ if ( version_compare( $current->response[ $plugin ]->new_version, $data->info->Version, '<=' ) ){
59
+ continue;
60
+ }
61
+
62
+ $this->notice(
63
+ sprintf(
64
+ __( 'Hey! %1$s has an update (version %2$s), <a href="%3$s">click here to update</a>.', WYSIJA ),
65
+ '<strong>' . esc_attr( $data->info->Name ) . '</strong>',
66
+ $current->response[ $plugin ]->new_version,
67
+ wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $plugin, 'upgrade-plugin_' . $plugin )
68
+ ),
69
+ true,
70
+ true
71
+ );
72
+ }
73
+ }
74
+ }
75
+
76
+ //$titlelink=str_replace(array('[link]','[\link]'), array('<a href="">','</a>'),'');
77
+
78
+
79
+
80
+ public function update_plugin_complete_actions( $update_actions, $mixed = null, $plugin = null ){
81
+ $actions = array(
82
+ 'refresh_page' => '<a href="#" onclick="window.parent.location.reload(true);return false;" title="' . esc_attr__( 'Refresh the page you current are!', WYSIJA ) . '" target="_parent">' . __( 'Return to MailPoet', WYSIJA ) . '</a>'
83
+ );
84
+
85
+ return $actions;
86
+ }
87
+
88
+ public function iframe_intercept( $current_screen ) {
89
+ $is_mailpoet_page = preg_match('/^mailpoet.*?_page_wysija_config$/i', $current_screen->base);
90
+ $is_packager_switcher = (isset( $_GET['action'] ) && $_GET['action'] === 'packager-switch');
91
+
92
+ if(!$is_mailpoet_page || !$is_packager_switcher) {
93
+ return;
94
+ }
95
+
96
+ if (!(wp_verify_nonce( $_GET['_wpnonce'], $_GET['action'] ) === 1)) {
97
+ return;
98
+ }
99
+
100
+ // Require the Updater classes
101
+ include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
102
+
103
+ $to = (isset($_GET['stable']) && $_GET['stable']?'stable':'beta');
104
+
105
+ add_filter( 'pre_site_transient_update_plugins', array( $this, 'pre_site_transient_update_plugins' ) );
106
+
107
+ $plugins = array();
108
+
109
+ // Check for the action, it might be upgrading or installing
110
+ $action = 'upgrade';
111
+ if ( isset( $_GET['_mp_action'] ) && in_array( $_GET['_mp_action'], array( 'upgrade', 'install' ) ) ){
112
+ $action = strtolower( $_GET['_mp_action'] );
113
+ }
114
+
115
+ foreach ( self::$plugins as $k => $plugin ) {
116
+ if ( is_plugin_active( $plugin ) ){
117
+ $plugins[] = $plugin;
118
+ }
119
+ }
120
+
121
+ // Ajust the Padding/margin of the iFrame
122
+ define( 'IFRAME_REQUEST', true );
123
+ echo "<div style='margin: 0 20px;'>";
124
+
125
+ // Thats how WordPress calls for an iFrame page
126
+ wp_enqueue_script( 'jquery' );
127
+ iframe_header();
128
+
129
+ if ( $action === 'upgrade' ) {
130
+ add_filter( 'update_bulk_plugins_complete_actions', array( $this, 'update_plugin_complete_actions' ), 10, 2 );
131
+ $upgrader = new Plugin_Upgrader( new Bulk_Plugin_Upgrader_Skin( compact( 'nonce', 'url' ) ) );
132
+ $upgrader->bulk_upgrade( $plugins );
133
+ } elseif ( $action === 'install' ) {
134
+ // If the action is install, it will only happen if it's the Premium
135
+ add_filter( 'install_plugin_complete_actions', array( $this, 'update_plugin_complete_actions' ), 10, 3 );
136
+ $upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin() );
137
+ $result = $upgrader->install( self::get_url( self::$plugins[1], WYSIJA::is_beta(), 'zip' ) );
138
+ }
139
+
140
+ iframe_footer();
141
+ echo '</div>';
142
+
143
+ remove_filter( 'pre_site_transient_update_plugins', array( $this, 'pre_site_transient_update_plugins' ) );
144
+
145
+ $model_config = WYSIJA::get( 'config', 'model' );
146
+ $model_config->save( array( 'beta_mode' => ( $to === 'stable' ? false : true ) ) );
147
+ set_site_transient( 'update_plugins', '' );
148
+
149
+ exit();
150
+ }
151
+
152
+ /**
153
+ * A static method to grab the url from the packager to grab the ZIP
154
+ * or the version of the plugin there.
155
+ *
156
+ * @uses bool_from_yn
157
+ * @uses esc_url
158
+ * @uses add_query_arg
159
+ *
160
+ * @param string $package Which package you want to grab
161
+ * @param boolean|string $beta Beta URL or not
162
+ * @param string $action Which kind of URL you need? [zip|check]
163
+ * @param string $version The version you want the URL to be related to
164
+ * @return string|null It will return the URL from the packager related to the asked action
165
+ */
166
+ public static function get_url( $package = null, $beta = false, $action = 'zip', $version = null ){
167
+ if ( is_string( $beta ) ){
168
+ if ( $beta === 'beta' ) {
169
+ $beta = true;
170
+ } else {
171
+ $beta = bool_from_yn( $beta );
172
+ }
173
+ } else {
174
+ $beta = (bool) $beta;
175
+ }
176
+
177
+ if ( ! in_array( $action, array( 'zip', 'check' ) ) ) {
178
+ return null;
179
+ }
180
+
181
+ $slug = self::get_slug( $package );
182
+
183
+ if ( true === $beta || 'wysija-newsletters-premium' === $slug ) {
184
+ $url = self::$baseurl->packager . $action;
185
+
186
+ $params = array(
187
+ 'key' => self::get_slug( $package ),
188
+ );
189
+
190
+ if ( $beta === true ){
191
+ $params['beta'] = 'true';
192
+ }
193
+
194
+ $url = add_query_arg( $params, $url );
195
+
196
+ return (string) $url;
197
+ } else {
198
+ return (string) self::$baseurl->core . $slug . '.zip';
199
+ }
200
+ }
201
+
202
+ public static function get_version( $package = null, $beta = false ){
203
+ $request = wp_remote_get( self::get_url( $package, $beta, 'check' ) );
204
+
205
+ if ( is_wp_error( $request ) ){
206
+ return false;
207
+ }
208
+
209
+ $version = wp_remote_retrieve_body( $request );
210
+
211
+ return $version;
212
+ }
213
+
214
+ public static function get_slug( $package = null ){
215
+ switch ( $package ) {
216
+ case self::$plugins[1]:
217
+ case 'premium':
218
+ case 'wysija-newsletters-premium':
219
+ return 'wysija-newsletters-premium';
220
+ break;
221
+
222
+ case self::$plugins[0]:
223
+ case 'base':
224
+ case 'wysija-newsletters':
225
+ default:
226
+ return 'wysija-newsletters';
227
+ break;
228
+ }
229
+ }
230
+
231
+ public static function get_plugin_data( $package = null, $beta = false, $new_version = false ){
232
+ $data = (object) array();
233
+ if ( is_null( $package ) ){
234
+ return $data;
235
+ }
236
+
237
+ $data->id = 27505;
238
+ $data->slug = self::get_slug( $package );
239
+ $data->package = self::get_url( $package, $beta, 'zip' );
240
+
241
+ if ( function_exists( 'get_plugin_data' ) ){
242
+ $data->info = (object) get_plugin_data( plugin_dir_path( dirname( dirname( __FILE__ ) ) ) . $package );
243
+ }
244
+
245
+ if ( $data->slug === 'wysija-newsletters' ){
246
+ $data->url = "https://wordpress.org/plugins/{$data->slug}/";
247
+ } else {
248
+ $data->url = 'http://www.mailpoet.com/wordpress-newsletter-plugin-premium/';
249
+ }
250
+ $data->url = esc_url( $data->url );
251
+
252
+ if ( $new_version !== false ){
253
+ $data->new_version = (string) $new_version;
254
+ }
255
+
256
+ return $data;
257
+ }
258
+
259
+ public function pre_set_site_transient_update_plugins( $update_data ){
260
+
261
+ if ( ! function_exists( 'get_plugin_data' ) ){
262
+ return (object) array();
263
+ }
264
+
265
+ if ( ! is_object( $update_data ) && strlen( trim( $update_data ) ) === 0 ){
266
+ return (object) array();
267
+ }
268
+
269
+ if ( ! isset( $update_data->last_checked ) ){
270
+ $update_data->last_checked = 0;
271
+ }
272
+
273
+ if ( ( time() - ( 60 * 60 * 12 ) ) > ( $update_data->last_checked ) ) { // Just check once every 12 hours
274
+ return $update_data;
275
+ }
276
+
277
+ foreach ( self::$plugins as $plugin ){
278
+ if ( ! function_exists( 'is_plugin_active' ) ) {
279
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
280
+ }
281
+
282
+ if ( ! is_plugin_active( $plugin ) ){
283
+ continue;
284
+ }
285
+
286
+ if ( ! WYSIJA::is_beta() && $plugin === 'wysija-newsletters/index.php' ) {
287
+ continue;
288
+ }
289
+
290
+ $version = self::get_version( $plugin, WYSIJA::is_beta() );
291
+ $update_data->last_checked = time();
292
+
293
+ if ( version_compare( WYSIJA::get_version( $plugin ), $version, '>=' ) ){
294
+ continue;
295
+ }
296
+
297
+ $update_data->response[ $plugin ] = self::get_plugin_data( $plugin, WYSIJA::is_beta(), $version );
298
+ }
299
+
300
+ return $update_data;
301
+ }
302
+
303
+ public function pre_site_transient_update_plugins( $transient ) {
304
+ $update_data = (object) array(
305
+ 'last_checked' => time() - 10,
306
+ 'response' => array()
307
+ );
308
+ $to = (isset($_GET['stable']) && $_GET['stable']?'stable':'beta');
309
+
310
+ foreach ( self::$plugins as $plugin ) {
311
+ if ( ! function_exists( 'is_plugin_active' ) ){
312
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
313
+ }
314
+
315
+ if ( ! is_plugin_active( $plugin ) ) {
316
+ continue;
317
+ }
318
+
319
+ $update_data->response[ $plugin ] = self::get_plugin_data( $plugin, $to, self::get_version( $plugin, $to ) );
320
+ }
321
+
322
+ return $update_data;
323
+ }
324
+
325
+ public function setup_bulk_screen( $current_screen ) {
326
+ global $title, $parent_file, $submenu_file;
327
+
328
+ if ( strtoupper( $_SERVER['REQUEST_METHOD'] ) === 'POST' && in_array( $current_screen->id, array( 'update-core', 'plugins' ) ) ) {
329
+ if ( ! isset( $_POST['checked'] ) ){
330
+ return;
331
+ }
332
+
333
+ $plugins = (array) $_POST['checked'];
334
+ $plugins = array_map( 'urldecode', $plugins );
335
+
336
+ $__intersection = array_intersect( $plugins, self::$plugins );
337
+
338
+ if ( empty( $__intersection ) ){
339
+ return;
340
+ }
341
+
342
+ $action = (isset($_POST['action']) ? $_POST['action'] : null);
343
+
344
+ switch($action) {
345
+ case 'delete-selected':
346
+
347
+ break;
348
+
349
+ case 'deactivate-selected':
350
+ if ( in_array( self::$plugins[0], $plugins ) && ! in_array( self::$plugins[1], $plugins ) && is_plugin_active( self::$plugins[1] ) ){
351
+ $plugins[] = self::$plugins[1];
352
+ }
353
+ break;
354
+
355
+ case 'update-selected':
356
+ case 'activate-selected':
357
+ if ( in_array( self::$plugins[1], $plugins ) && ! in_array( self::$plugins[0], $plugins ) ){
358
+ $plugins[] = self::$plugins[0];
359
+ }
360
+ break;
361
+ }
362
+
363
+ $_POST['checked'] = $plugins;
364
+
365
+ return;
366
+ }
367
+
368
+ if ( $current_screen->id !== 'update' ){
369
+ return;
370
+ }
371
+
372
+ if ( $_GET['action'] !== 'upgrade-plugin' ){
373
+ return;
374
+ }
375
+
376
+ if ( $_GET['action'] === 'upgrade-plugin' && ! in_array( $_GET['plugin'], self::$plugins ) ){
377
+ return;
378
+ }
379
+
380
+ foreach ( self::$plugins as $plugin ) {
381
+ if ( ! is_plugin_active( $plugin ) ) {
382
+ return;
383
+ }
384
+ }
385
+
386
+ $_GET['action'] = $_REQUEST['action'] = 'update-selected';
387
+ $_GET['plugins'] = $_REQUEST['plugins'] = implode( ',', array_map( 'urlencode', self::$plugins ) );
388
+ $_GET['_wpnonce'] = $_REQUEST['_wpnonce'] = wp_create_nonce( 'bulk-update-plugins' );
389
+ $_GET['_wysija_bulk_screen'] = $_REQUEST['_wysija_bulk_screen'] = true;
390
+
391
+ $title = esc_attr__( 'Update Plugin' );
392
+ $parent_file = 'plugins.php';
393
+ $submenu_file = 'plugins.php';
394
+ require_once(ABSPATH . 'wp-admin/admin-header.php');
395
+ echo
396
+ "<div class='wrap'>" .
397
+ '<h2>' . esc_attr( $title ) . '</h2>';
398
+
399
+ }
400
+
401
+ public function setup_bulk_screen_footer(){
402
+ if ( ! isset( $_GET['_wysija_bulk_screen'] ) ){
403
+ return;
404
+ }
405
+ echo '</div>';
406
+ include(ABSPATH . 'wp-admin/admin-footer.php');
407
+ }
408
+ }
trunk/classes/WJ_Utils.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * Wysija Premium Utils.
5
+ * Utilities singleton not related to a specific model.
6
+ */
7
+ class WJ_Utils {
8
+
9
+ private function __construct(){}
10
+
11
+ public static function to_int( $value ) {
12
+ $boolean = (bool) $value;
13
+ if ( $boolean ) {
14
+ $int = 1;
15
+ } else {
16
+ $int = 0;
17
+ }
18
+ return $int;
19
+ }
20
+
21
+ public static function to_bool( $value ) {
22
+ $int = (int) $value;
23
+ if ( $int == 0 ) {
24
+ $boolean = false;
25
+ } else {
26
+ $boolean = true;
27
+ }
28
+ return $boolean;
29
+ }
30
+
31
+ /**
32
+ * Retuns plain domain name.
33
+ *
34
+ * @return string $domain
35
+ */
36
+ public static function get_domain() {
37
+ if ( isset($_SERVER['SERVER_NAME'] ) && strlen( trim( $_SERVER['SERVER_NAME'] ) ) > 0 ) {
38
+ $domain = strtolower( $_SERVER['SERVER_NAME'] );
39
+ } else {
40
+ $domain = preg_replace( '@http[s]?:\/\/@', '', get_site_url() );
41
+ }
42
+
43
+ return preg_replace( '@^www\.@', '', $domain );
44
+ }
45
+
46
+ /**
47
+ * Reruns necessary data for tooltip.
48
+ *
49
+ * @return array $data
50
+ */
51
+ public static function get_tip_data() {
52
+ $model_config = WYSIJA::get( 'config', 'model' );
53
+ $is_gmail = 'false';
54
+
55
+ if ( 'gmail' === $model_config->getValue( 'sending_method' ) ) {
56
+ $is_gmail = 'true';
57
+ }
58
+
59
+ $data = array(
60
+ 'text' => sprintf( __( 'Use an email from your domain, like <strong>info@%s</strong> to avoid the spam folder, or even be blocked.', WYSIJA ), self::get_domain() ),
61
+ 'gmailText' => sprintf( __( 'If you want to use a Gmail address, you need to send with Gmail. Check <a id="tip-send-with" href="%s">sending settings</a>.', WYSIJA ), admin_url( 'admin.php?page=wysija_config#tab-sendingmethod' ) ),
62
+ 'domain' => self::get_domain(),
63
+ 'isGmail' => $is_gmail,
64
+ );
65
+
66
+ return $data;
67
+ }
68
+
69
+ public static function esc_json_attr( $json ){
70
+ $search = array(
71
+ '\"',
72
+ '\'',
73
+ '<',
74
+ '>',
75
+ '&',
76
+ );
77
+ $replace = array(
78
+ '\\u0022',
79
+ '\\u0027',
80
+ '\\u003C',
81
+ '\\u003E',
82
+ '\\u0026',
83
+ );
84
+
85
+ return str_replace( $search, $replace, json_encode( $json ) );
86
+ }
87
+
88
+ }
trunk/classes/index.html ADDED
File without changes
trunk/controllers/ajax/campaigns.php ADDED
@@ -0,0 +1,978 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_control_back_campaigns extends WYSIJA_control{
4
+
5
+ function __construct(){
6
+ if(!WYSIJA::current_user_can('wysija_newsletters')) die('Action is forbidden.');
7
+ parent::__construct();;
8
+ }
9
+
10
+ function save_poll(){
11
+ $this->requireSecurity();
12
+
13
+ if( in_array($_REQUEST['how'], array('repository' , 'search_engine' , 'friend', 'url' )) ){
14
+
15
+ $data_conf = array( 'poll_origin' => $_REQUEST['how'] );
16
+ if( !empty( $_REQUEST['where'] ) ){
17
+ $data_conf['poll_origin_url'] = esc_url($_REQUEST['where']);
18
+ }
19
+ $model_config = WYSIJA::get('config','model');
20
+ $model_config->save( $data_conf );
21
+
22
+ $res['result'] = true;
23
+ $res['msg'] = '<span><span class="checkmark">---</span>'. __('Thanks!',WYSIJA). '</span>';
24
+ return $res;
25
+ }
26
+
27
+ $res['result'] = false;
28
+ return $res;
29
+
30
+ }
31
+
32
+ function switch_theme() {
33
+ $this->requireSecurity();
34
+ if(isset($_POST['wysijaData'])) {
35
+ $rawData = $_POST['wysijaData'];
36
+ // avoid using stripslashes as it's not reliable depending on the magic quotes settings
37
+ $rawData = str_replace('\"', '"', $rawData);
38
+ // decode JSON data
39
+ $rawData = json_decode($rawData, true);
40
+
41
+ $theme = (isset($rawData['theme'])) ? $rawData['theme'] : 'default';
42
+
43
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
44
+ $res['templates'] = $helper_wj_engine->renderTheme($theme);
45
+
46
+ $email_id = (int)$_REQUEST['id'];
47
+
48
+ $campaignsHelper = WYSIJA::get('campaigns', 'helper');
49
+
50
+ if(isset($res['templates']['divider_options'])) {
51
+ // save divider
52
+ $campaignsHelper->saveParameters($email_id, 'divider', $res['templates']['divider_options']);
53
+ }
54
+
55
+ // save theme used
56
+ $campaignsHelper->saveParameters($email_id, 'theme', $theme);
57
+
58
+ $res['templates']['theme'] = $theme;
59
+ $res['styles'] = $helper_wj_engine->renderThemeStyles($theme);
60
+ } else {
61
+ $res['msg'] = __("The theme you selected could not be loaded.",WYSIJA);
62
+ $res['result'] = false;
63
+ }
64
+ return $res;
65
+ }
66
+
67
+ function save_editor() {
68
+ $this->requireSecurity();
69
+ // decode json data and convert to array
70
+ $rawData = '';
71
+ if(isset($_POST['wysijaData'])) {
72
+ $rawData = $_POST['wysijaData'];
73
+ // avoid using stripslashes as it's not reliable depending on the magic quotes settings
74
+ $rawData = str_replace('\"', '"', $rawData);
75
+ // decode JSON data
76
+ $rawData = json_decode($rawData, true);
77
+ }
78
+
79
+ if(!$rawData){
80
+ $this->error('Error saving',false);
81
+ return array('result' => false);
82
+ }
83
+
84
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
85
+ $helper_wj_engine->setData( $rawData );
86
+ $result = false;
87
+
88
+ // get email id
89
+ $email_id = (int)$_REQUEST['id'];
90
+
91
+ $model_email = WYSIJA::get('email', 'model');
92
+ $emailData = $model_email->getOne(array('wj_styles', 'subject', 'params', 'email_id', 'campaign_id'), array('email_id' => $email_id));
93
+
94
+ $helper_wj_engine->setStyles($emailData['wj_styles'], true);
95
+
96
+ $values = array('wj_data' => $helper_wj_engine->getEncoded('data'));
97
+ $values['body'] = $helper_wj_engine->renderEmail($emailData);
98
+ $values['email_id'] = $email_id;
99
+
100
+ $updated_email = $helper_wj_engine->getEmailData();
101
+
102
+ // update modified_at timestamp
103
+ $model_email->columns['modified_at']['autoup']=1;
104
+
105
+ // update data in DB
106
+ $result = $model_email->update($values, array('email_id' => $email_id));
107
+
108
+ if(!$result) {
109
+ // throw error
110
+ $this->error(__('Your email could not be saved', WYSIJA));
111
+ } else {
112
+ // save successful
113
+ $this->notice(__('Your email has been saved', WYSIJA));
114
+ }
115
+
116
+ return array('result' => $result);
117
+ }
118
+
119
+ function save_styles() {
120
+ $this->requireSecurity();
121
+ // decode json data and convert to array
122
+ $rawData = '';
123
+ if(isset($_POST['wysijaStyles'])) {
124
+ $rawData = $_POST['wysijaStyles'];
125
+ // avoid using stripslashes as it's not reliable depending on the magic quotes settings
126
+ $rawData = str_replace('\"', '"', $rawData);
127
+ // decode JSON data
128
+ $rawData = json_decode($rawData, true);
129
+
130
+ }
131
+
132
+ // handle checkboxes
133
+ if(array_key_exists('a-underline', $rawData) === false) {
134
+ $rawData['a-underline'] = -1;
135
+ }
136
+
137
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
138
+ $helper_wj_engine->setStyles($helper_wj_engine->formatStyles($rawData));
139
+
140
+ $result = false;
141
+
142
+ $values = array(
143
+ 'wj_styles' => $helper_wj_engine->getEncoded('styles')
144
+ );
145
+
146
+ // get email id
147
+ $email_id = (int)$_REQUEST['id'];
148
+
149
+ // update data in DB
150
+ $model_email = WYSIJA::get('email', 'model');
151
+ $result = $model_email->update($values, array('email_id' => $email_id));
152
+
153
+ if(!$result) {
154
+ // throw error
155
+ $this->error(__('Styles could not be saved', WYSIJA));
156
+ } else {
157
+ // save successful
158
+ $this->notice(__('Styles have been saved', WYSIJA));
159
+ }
160
+
161
+ return array(
162
+ 'styles' => $helper_wj_engine->renderStyles(),
163
+ 'result' => $result
164
+ );
165
+ }
166
+
167
+ function deleteimg(){
168
+ $this->requireSecurity();
169
+ if(isset($_REQUEST['imgid']) && $_REQUEST['imgid']>0){
170
+ /* delete the image with id imgid */
171
+ $result=wp_delete_attachment($_REQUEST['imgid'],true);
172
+ if($result){
173
+ $this->notice(__('Image has been deleted.',WYSIJA));
174
+ }
175
+ }
176
+
177
+ $res=array();
178
+ $res['result'] = $result;
179
+ return $res;
180
+ }
181
+
182
+ function deleteTheme(){
183
+ $this->requireSecurity();
184
+ if(isset($_REQUEST['themekey']) && $_REQUEST['themekey']){
185
+ /* delete the image with id imgid */
186
+ $helperTheme=WYSIJA::get('themes','helper');
187
+ $result=$helperTheme->delete($_REQUEST['themekey']);
188
+ }
189
+
190
+ $res=array();
191
+ $res['result'] = $result;
192
+ return $res;
193
+ }
194
+
195
+ // set newsletter default theme
196
+ function setDefaultTheme() {
197
+ $this->requireSecurity();
198
+ if(isset($_REQUEST['theme']) && $_REQUEST['theme']) {
199
+ // check that the theme exists
200
+ // TODO
201
+ $theme_exists = true;
202
+ if($theme_exists === true) {
203
+ // update config
204
+ $model_config = WYSIJA::get('config', 'model');
205
+ $model_config->save(array('newsletter_default_theme' => $_REQUEST['theme']));
206
+
207
+ $result = true;
208
+ } else {
209
+ $result = false;
210
+ }
211
+ }
212
+
213
+ return array('result' => $result);
214
+ }
215
+
216
+ function save_IQS() {
217
+ $this->requireSecurity();
218
+ // decode json data and convert to array
219
+ $wysijaIMG = '';
220
+ if(isset($_POST['wysijaIMG'])) {
221
+ $wysijaIMG = json_decode(stripslashes($_POST['wysijaIMG']), TRUE);
222
+ }
223
+ $values = array(
224
+ 'params' => array('quickselection'=>$wysijaIMG)
225
+ );
226
+
227
+ // get email id
228
+ $email_id = (int)$_REQUEST['id'];
229
+ $values['email_id']=$email_id;
230
+
231
+ // update data in DB
232
+ $model_email = WYSIJA::get('email', 'model');
233
+ $result = $model_email->update($values, array('email_id' => $email_id));
234
+
235
+ if(!$result) {
236
+ // throw error
237
+ $this->error(__('Image selection has not been saved.', WYSIJA));
238
+ } else {
239
+ // save successful
240
+ $this->notice(__('Image selection has been saved.', WYSIJA));
241
+ }
242
+
243
+ return array('result' => $result);
244
+ }
245
+
246
+ function insert_articles() {
247
+ $this->requireSecurity();
248
+ // get raw params
249
+ $raw_params = $_REQUEST['data'];
250
+
251
+ // format params
252
+ $params = array();
253
+ foreach($raw_params as $value) {
254
+ $params[$value['name']] = $value['value'];
255
+ }
256
+
257
+ if($params['show_divider'] === 'yes') {
258
+ // get divider
259
+ $divider = $_REQUEST['divider'];
260
+ } else {
261
+ $divider = null;
262
+ }
263
+ $params['divider'] = $divider;
264
+
265
+ // get post ids
266
+ $post_ids = array();
267
+ if(isset($_REQUEST['post_ids']) && strlen(trim($_REQUEST['post_ids'])) > 0) {
268
+ $post_ids = explode(',', $_REQUEST['post_ids']);
269
+ }
270
+
271
+ if(empty($post_ids)) {
272
+ // return error
273
+ $res['msg'] = __('Please select an article.', WYSIJA);
274
+ $res['result'] = false;
275
+ return $res;
276
+ }
277
+
278
+ // specify custom fields to get from posts
279
+ $post_params = array('include' => $post_ids);
280
+
281
+ // include sort by parameter into post params
282
+ $post_params['sort_by'] = $params['sort_by'];
283
+
284
+ // get posts
285
+ $model_wp_posts = WYSIJA::get('wp_posts', 'model');
286
+ $posts = $model_wp_posts->get_posts($post_params);
287
+
288
+ // check if we need to interpret shortcodes
289
+ $model_config = WYSIJA::get('config', 'model');
290
+ $interpret_shortcode = (bool)$model_config->getValue('interp_shortcode');
291
+
292
+ // get some model and helpers
293
+ $helper_articles = WYSIJA::get('articles', 'helper');
294
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
295
+
296
+ $output = '';
297
+
298
+ // save parameters for next time
299
+ $model_config->save(array('insert_post_parameters' => $helper_wj_engine->encodeParameters($params)));
300
+
301
+ foreach($posts as $key => $post) {
302
+ if($interpret_shortcode === true) {
303
+ // interpret shortcodes
304
+ $posts[$key]['post_content'] = apply_filters('the_content', $post['post_content']);
305
+ }
306
+ // get thumbnail
307
+ $posts[$key]['post_image'] = $helper_articles->getImage($post);
308
+ }
309
+
310
+ $output .= base64_encode($helper_wj_engine->renderPostsToBlocks($posts, $params));
311
+
312
+ if(strlen($output) > 0) {
313
+ $res['result'] = true;
314
+ $res['posts'] = $output;
315
+ }else {
316
+ $res['msg'] = __('There are no posts corresponding to that search.',WYSIJA);
317
+ $res['result'] = false;
318
+ }
319
+
320
+ return $res;
321
+ }
322
+
323
+ function send_preview($spamtest=false){
324
+ $this->requireSecurity();
325
+ $mailer=WYSIJA::get('mailer','helper');
326
+ $email_id = $_REQUEST['id'];
327
+ $resultarray=array();
328
+
329
+ // update data in DB
330
+ $model_email = WYSIJA::get('email', 'model');
331
+ $model_email->getFormat=OBJECT;
332
+ $email_object = $model_email->getOne(false,array('email_id' => $email_id));
333
+ $mailer->testemail=true;
334
+
335
+
336
+ if(isset($_REQUEST['data'])){
337
+ $dataTemp=$_REQUEST['data'];
338
+ $_REQUEST['data']=array();
339
+ foreach($dataTemp as $val) $_REQUEST['data'][$val['name']]=$val['value'];
340
+ unset($dataTemp);
341
+ foreach($_REQUEST['data'] as $k =>$v){
342
+ $newkey=str_replace(array('wysija[email][',']'),'',$k);
343
+ $configVal[$newkey]=$v;
344
+ }
345
+ if(isset($configVal['from_name'])){
346
+ $params=array(
347
+ 'from_name'=>$configVal['from_name'],
348
+ 'from_email'=>$configVal['from_email'],
349
+ 'replyto_name'=>$configVal['replyto_name'],
350
+ 'replyto_email'=>$configVal['replyto_email']);
351
+ if(isset($configVal['subject'])) $email_object->subject=$configVal['subject'];
352
+ }
353
+
354
+ }else{
355
+ $params=array(
356
+ 'from_name'=>$email_object->from_name,
357
+ 'from_email'=>$email_object->from_email,
358
+ 'replyto_name'=>$email_object->replyto_name,
359
+ 'replyto_email'=>$email_object->replyto_email
360
+ );
361
+ }
362
+ if(strpos($_REQUEST['receiver'], ',')) {
363
+ $receivers = explode(',',$_REQUEST['receiver']);
364
+ } else if(strpos($_REQUEST['receiver'], ';')) {
365
+ $receivers = explode(';',$_REQUEST['receiver']);
366
+ } else {
367
+ $receivers = array($_REQUEST['receiver']);
368
+ }
369
+
370
+ $user_model = WYSIJA::get('user', 'model');
371
+ foreach($receivers as $key => $receiver){
372
+ $receiver = trim($receiver);
373
+ $dummy_receiver = $user_model->get_object_by_email($receiver);
374
+ if(empty($dummy_receiver)){
375
+ $dummy_receiver = new stdClass();
376
+ $dummy_receiver->user_id = 0;
377
+ $dummy_receiver->email = $receiver;
378
+ $dummy_receiver->status = 1;
379
+ $dummy_receiver->lastname = $dummy_receiver->firstname = '';
380
+ }
381
+
382
+ if($spamtest){
383
+ $langextra = '';
384
+ $dummy_receiver->firstname ='Mail Tester';
385
+
386
+ $wp_lang = get_locale();
387
+ if(!empty($wp_lang)) $langextra ='&lang='.$wp_lang;
388
+ $resultarray['urlredirect']='http://www.mail-tester.com/check.php?id='.urlencode($dummy_receiver->email).$langextra;
389
+ }
390
+ $receivers[$key] = $dummy_receiver;
391
+
392
+ }
393
+
394
+ $email_clone=array();
395
+ foreach($email_object as $kk=>$vv) $email_clone[$kk]=$vv;
396
+
397
+
398
+ $wj_engine = WYSIJA::get('wj_engine', 'helper');
399
+ // set data & styles
400
+ if(isset($email_clone['wj_data'])) { $wj_engine->setData($email_clone['wj_data'], true); } else { $wj_engine->setData(); }
401
+ if(isset($email_clone['wj_styles'])) { $wj_engine->setStyles($email_clone['wj_styles'], true); } else { $wj_engine->setStyles(); }
402
+
403
+ // generate email html body
404
+ $body = $wj_engine->renderEmail($email_clone);
405
+
406
+ // get back email data as it will be updated during the rendering (articles ids + articles count)
407
+ $email_child = $wj_engine->getEmailData();
408
+
409
+ // [total] [number] and [post_title] are only valid for post notifications newsletter
410
+ if((int)$email_child['type'] === 2 && isset($email_child['params']['autonl']['event']) &&
411
+ $email_child['params']['autonl']['event'] === 'new-articles' && isset($email_child['params']['autonl']['articles'])){
412
+
413
+ $item_count = 0;
414
+ $total_count = 1;
415
+ $first_subject = '';
416
+
417
+ if(isset($email_child['params']['autonl']['articles']['count'])) $item_count = (int)$email_child['params']['autonl']['articles']['count'];
418
+ if(isset($email_child['params']['autonl']['articles']['first_subject'])) $first_subject = $email_child['params']['autonl']['articles']['first_subject'];
419
+ if(isset($email_child['params']['autonl']['total_child'])) $total_count = (int)$email_child['params']['autonl']['total_child'] + 1;
420
+
421
+ $email_object->subject = str_replace(
422
+ array('[total]','[number]','[post_title]'),
423
+ array($item_count, $total_count, $first_subject),
424
+ $email_child['subject']
425
+ );
426
+ }
427
+ $successmsg = __('Your email preview has been sent to %1$s', WYSIJA);
428
+
429
+ // correction added for post notifications with the tag [newsletter:post_title] failing to send
430
+ if(isset($email_object->params['autonl']) && isset($email_child['params']['autonl'])){
431
+ $email_object->params['autonl']=$email_child['params']['autonl'];
432
+ }
433
+
434
+ if(isset($email_object->params)) {
435
+ $params['params']=$email_object->params;
436
+
437
+ if(isset($configVal['params[googletrackingcode'])){
438
+ $paramsemail=array();
439
+ if(!is_array($email_object->params)) $paramsemail=unserialize(base64_decode($email_object->params));
440
+
441
+ if(trim($configVal['params[googletrackingcode'])) {
442
+ $paramsemail['googletrackingcode']=$configVal['params[googletrackingcode'];
443
+ }
444
+ else {
445
+ unset($paramsemail['googletrackingcode']);
446
+ }
447
+ $params['params'] = base64_encode(serialize($paramsemail));
448
+ }
449
+ }
450
+
451
+ $params['email_id'] = $email_object->email_id;
452
+ $receiversList = array();
453
+ $res = false;
454
+ foreach($receivers as $receiver){
455
+ if($mailer->sendSimple($receiver, stripslashes($email_object->subject),$email_object->body,$params)) {
456
+ $res = true;
457
+ $receiversList[] = $receiver->email;
458
+ }
459
+ WYSIJA::log('preview_sent', $mailer, 'manual');
460
+ }
461
+
462
+ if($res === true) {
463
+ $this->notice(sprintf($successmsg, implode(', ', $receiversList)));
464
+ }
465
+
466
+ $resultarray['result'] = $res;
467
+
468
+ return $resultarray;
469
+ }
470
+
471
+ /**
472
+ * send spam test function step 2 of the newsletter edition process
473
+ */
474
+ function send_spamtest(){
475
+ $this->requireSecurity();
476
+ return apply_filters('wysija_send_spam_test','',$this);
477
+ }
478
+
479
+ function set_divider()
480
+ {
481
+ $this->requireSecurity();
482
+ $src = isset($_POST['wysijaData']['src']) ? $_POST['wysijaData']['src'] : NULL;
483
+ $width = isset($_POST['wysijaData']['width']) ? (int)$_POST['wysijaData']['width'] : NULL;
484
+ $height = isset($_POST['wysijaData']['height']) ? (int)$_POST['wysijaData']['height'] : NULL;
485
+
486
+ if($src === NULL OR $width === NULL OR $height === NULL) {
487
+ // there is a least one missing parameter, fallback to default divider
488
+ $dividersHelper = WYSIJA::get('dividers', 'helper');
489
+ $divider = $dividersHelper->getDefault();
490
+ } else {
491
+ // use provided params
492
+ $divider = array(
493
+ 'src' => $src,
494
+ 'width' => $width,
495
+ 'height' => $height
496
+ );
497
+ }
498
+
499
+ // update campaign parameters
500
+ $email_id = (int)$_REQUEST['id'];
501
+ $campaignsHelper = WYSIJA::get('campaigns', 'helper');
502
+ $campaignsHelper->saveParameters($email_id, 'divider', $divider);
503
+
504
+ // set params
505
+ $block = array_merge(array('no-block' => true, 'type' => 'divider'), $divider);
506
+
507
+ $helper_wj_engine=WYSIJA::get('wj_engine','helper');
508
+ return base64_encode($helper_wj_engine->renderEditorBlock($block));
509
+ }
510
+
511
+ function generate_social_bookmarks() {
512
+ $this->requireSecurity();
513
+ $size = 'medium';
514
+ $iconset = '01';
515
+
516
+ if(isset($_POST['wysijaData']) && !empty($_POST['wysijaData'])) {
517
+ $data = $_POST['wysijaData'];
518
+ $items = array();
519
+
520
+ foreach($data as $key => $values) {
521
+ if($values['name'] === 'bookmarks-size') {
522
+ // get size
523
+ $size = $values['value'];
524
+ } else if($values['name'] === 'bookmarks-theme') {
525
+ // get theme name
526
+ $theme = $values['value'];
527
+ } else if($values['name'] === 'bookmarks-iconset') {
528
+ // get iconset
529
+ $iconset = $values['value'];
530
+ if(strlen(trim($iconset)) === 0) {
531
+ $this->error('No iconset specified', false);
532
+ return false;
533
+ }
534
+ } else {
535
+ $keys = explode('-', $values['name']);
536
+ $network = $keys[1];
537
+ $property = $keys[2];
538
+ if(array_key_exists($network, $items)) {
539
+ $items[$network][$property] = $values['value'];
540
+ } else {
541
+ $items[$network] = array($property => $values['value']);
542
+ }
543
+ }
544
+ }
545
+ }
546
+
547
+ $urls = array();
548
+ // check data and remove network with an empty url
549
+ foreach($items as $network => $item) {
550
+ if(strlen(trim($item['url'])) === 0) {
551
+ // empty url
552
+ unset($items[$network]);
553
+ } else {
554
+ // url specified
555
+ $urls[$network] = $item['url'];
556
+ }
557
+ }
558
+
559
+ // check if there's at least one url left
560
+ if(empty($urls)) {
561
+ $this->error('No url specified', false);
562
+ return false;
563
+ }
564
+
565
+ // save url in config
566
+ $config=WYSIJA::get('config','model');
567
+ $config->save(array('social_bookmarks' => $urls));
568
+
569
+ // get iconset icons
570
+ $bookmarksHelper = WYSIJA::get('bookmarks', 'helper');
571
+
572
+ // if the iconset is 00, then it's the theme's bookmarks
573
+ if($iconset === '00') {
574
+ $icons = $bookmarksHelper->getAllByTheme($theme);
575
+ } else {
576
+ // otherwise it's a basic iconset
577
+ $icons = $bookmarksHelper->getAllByIconset($size, $iconset);
578
+ }
579
+
580
+
581
+ // format data
582
+ $block = array(
583
+ 'position' => 1,
584
+ 'type' => 'gallery',
585
+ 'items' => array(),
586
+ 'alignment' => 'center'
587
+ );
588
+
589
+ $width = 0;
590
+ foreach($items as $key => $item) {
591
+ $block['items'][] = array_merge($item, $icons[$key], array('alt' => ucfirst($key)));
592
+ $width += (int)$icons[$key]['width'];
593
+ }
594
+ // add margin between icons
595
+ $width += (count($block['items']) - 1) * 10;
596
+ // set optimal width
597
+ $block['width'] = max(0, min($width, 564));
598
+
599
+ $helper_wj_engine=WYSIJA::get('wj_engine','helper');
600
+ return base64_encode($helper_wj_engine->renderEditorBlock($block));
601
+ }
602
+
603
+ function install_theme() {
604
+ $this->requireSecurity();
605
+ if( isset($_REQUEST['theme_id'])){
606
+ global $wp_version;
607
+ //check if theme is premium if you have the premium licence
608
+ if(isset($_REQUEST['premium']) && $_REQUEST['premium']){
609
+ $getpremiumtheme=apply_filters('wysija_install_theme_premium', false);
610
+
611
+ if(!$getpremiumtheme){
612
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
613
+ $themes = $helper_wj_engine->renderThemes();
614
+ return array('result'=>false, 'themes' => $themes);
615
+ }
616
+ }
617
+
618
+ $helperToolbox = WYSIJA::get('toolbox','helper');
619
+ $domain_name = $helperToolbox->_make_domain_name(admin_url('admin.php'));
620
+
621
+ $request = 'http://api.mailpoet.com/download/zip/'.$_REQUEST['theme_id'].'?domain='.$domain_name;
622
+
623
+ $args = array(
624
+ 'timeout' => 30,
625
+ 'body' => array( ),
626
+ 'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
627
+ );
628
+ $raw_response = wp_remote_post( $request, $args );
629
+
630
+ if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) ){
631
+ if(method_exists($raw_response, 'get_error_messages')){
632
+ $this->error($raw_response->get_error_messages());
633
+ }
634
+ $ZipfileResult = false;
635
+ }else{
636
+ $ZipfileResult = maybe_unserialize( wp_remote_retrieve_body( $raw_response ) );
637
+ }
638
+
639
+ if($ZipfileResult === false){
640
+ $result = false;
641
+ $this->error(__('We were unable to contact the API, the site may be down. Please try again later.',WYSIJA),true);
642
+ }else{
643
+ $themesHelp=WYSIJA::get('themes','helper');
644
+ $result = $themesHelp->installTheme($ZipfileResult);
645
+
646
+ // refresh themes list
647
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
648
+ $themes = $helper_wj_engine->renderThemes();
649
+ }
650
+ }else{
651
+ $result = false;
652
+ $themes = '';
653
+ $this->notice('missing info');
654
+ }
655
+
656
+ return array('result' => $result, 'themes' => $themes);
657
+ }
658
+
659
+ function get_social_bookmarks() {
660
+ $size = isset($_POST['wysijaData']['size']) ? $_POST['wysijaData']['size'] : NULL;
661
+ $theme = isset($_POST['wysijaData']['theme']) ? $_POST['wysijaData']['theme'] : NULL;
662
+
663
+ $bookmarksHelper = WYSIJA::get('bookmarks', 'helper');
664
+ $bookmarks = $bookmarksHelper->getAll($size, $theme);
665
+ return json_encode(array('icons' => $bookmarks));
666
+ }
667
+
668
+ function refresh_themes() {
669
+ // refresh themes list
670
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
671
+ return array('result'=>true, 'themes' => $helper_wj_engine->renderThemes());
672
+ }
673
+
674
+ function generate_auto_post() {
675
+ // get params and generate html
676
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
677
+ $helper_articles = WYSIJA::get('articles', 'helper');
678
+
679
+ // get parameters
680
+ $block_params = array();
681
+ if(isset($_POST['wysijaData'])) {
682
+ // store category ids (TBR)
683
+ $category_ids = array();
684
+
685
+ foreach($_POST['wysijaData'] as $pairs) {
686
+ // special cases
687
+ switch($pairs['name']) {
688
+ case 'author_label':
689
+ case 'category_label':
690
+ case 'readmore':
691
+ case 'nopost_message':
692
+ $block_params[] = array('key' => $pairs['name'], 'value' => base64_encode(stripslashes($pairs['value'])));
693
+ break;
694
+ case 'category_ids':
695
+ $category_ids = array_filter( array_map( 'absint', explode( ',', $pairs['value'] ) ) );
696
+ break;
697
+ default:
698
+ $block_params[] = array('key' => $pairs['name'], 'value' => $pairs['value']);
699
+ }
700
+ }
701
+
702
+ // make sure we have only unique ids in categories
703
+ $block_params[] = array('key' => 'category_ids', 'value' => join(',', array_unique($category_ids)));
704
+ }
705
+
706
+ if(empty($block_params)) {
707
+ // an error occurred, do something!
708
+ return false;
709
+ } else {
710
+ $data = array(
711
+ 'type' => 'auto-post',
712
+ 'params' => $block_params
713
+ );
714
+ return base64_encode($helper_wj_engine->renderEditorBlock($data));
715
+ }
716
+ }
717
+
718
+ function load_auto_post() {
719
+ $params = array();
720
+
721
+ if(isset($_POST['wysijaData'])) {
722
+
723
+ $pairs = explode('&', $_POST['wysijaData']);
724
+
725
+ foreach($pairs as $pair) {
726
+ list($key, $value) = explode('=', $pair);
727
+ switch($key) {
728
+ case 'autopost_count':
729
+ $params[$key] = (int)$value;
730
+ break;
731
+ case 'readmore':
732
+ case 'author_label':
733
+ case 'category_label':
734
+ case 'nopost_message':
735
+ $params[$key] = base64_decode($value);
736
+ break;
737
+ case 'exclude':
738
+ $params[$key] = explode(',', $value);
739
+ break;
740
+ default:
741
+ $params[$key] = $value;
742
+ }
743
+ }
744
+ }
745
+
746
+ if(empty($params)) {
747
+ // an error occurred, do something!
748
+ return false;
749
+ } else {
750
+
751
+ // get email params
752
+ $email_id = (int)$_REQUEST['id'];
753
+ $model_email = WYSIJA::get('email', 'model');
754
+ $email = $model_email->getOne(array('params','sent_at','campaign_id'), array('email_id' => $email_id));
755
+
756
+ $helper_articles = WYSIJA::get('articles', 'helper');
757
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
758
+
759
+ // see if posts have already been sent
760
+ if(!empty($email['params']['autonl']['articles']['ids'])) {
761
+ if(!isset($params['exclude'])) { $params['exclude'] = array(); }
762
+
763
+ $params['exclude'] = array_unique(array_merge($email['params']['autonl']['articles']['ids'], $params['exclude']));
764
+ }
765
+
766
+ //we set the post_date to filter articles only older than that one
767
+ if(isset($email['params']['autonl']['firstSend'])){
768
+ $params['post_date'] = $email['params']['autonl']['firstSend'];
769
+ }
770
+
771
+ // if immediate let it know to the get post
772
+ if(isset($email['params']['autonl']['articles']['immediatepostid'])){
773
+ $params['include'] = $email['params']['autonl']['articles']['immediatepostid'];
774
+ $params['post_limit'] = 1;
775
+ }else{
776
+ //we set the post_date to filter articles only older than the last time we sent articles
777
+ if(isset($email['params']['autonl']['lastSend'])){
778
+ $params['post_date'] = $email['params']['autonl']['lastSend'];
779
+ }else{
780
+ //get the latest child newsletter sent_at value
781
+ $mEmail=WYSIJA::get('email','model');
782
+ $mEmail->reset();
783
+ $mEmail->orderBy('email_id','DESC');
784
+ $lastEmailSent=$mEmail->getOne(false,array('campaign_id'=>$email['campaign_id'],'type'=>'1'));
785
+
786
+ if(!empty($lastEmailSent)) $params['post_date'] = $lastEmailSent['sent_at'];
787
+ }
788
+ }
789
+
790
+ // get posts
791
+ $model_wp_posts = WYSIJA::get('wp_posts','model');
792
+ $posts = $model_wp_posts->get_posts($params);
793
+
794
+ if(empty($posts)) {
795
+ // nothing to display
796
+ $posts = array();
797
+ } else {
798
+ // used to keep track of post ids present in the auto post
799
+ $post_ids = array();
800
+
801
+ // cleanup post and get image
802
+ foreach($posts as $key => $post) {
803
+ if($params['image_alignment'] !== 'none') {
804
+ // attempt to get post image
805
+ $posts[$key]['post_image'] = $helper_articles->getImage($post);
806
+ }
807
+
808
+ // store article id
809
+ $post_ids[] = $post['ID'];
810
+ }
811
+ // store article ids
812
+ $params['post_ids'] = join(',', $post_ids);
813
+ }
814
+
815
+ // get divider if necessary (for immediate post notification, the "show_divider" parameter is not available)
816
+ if(isset($params['show_divider']) && $params['show_divider'] === 'yes') {
817
+ if(isset($email['params']['divider'])) {
818
+ $params['divider'] = $email['params']['divider'];
819
+ } else {
820
+ $helper_dividers = WYSIJA::get('dividers', 'helper');
821
+ $params['divider'] = $helper_dividers->getDefault();
822
+ }
823
+ }
824
+
825
+ return base64_encode($helper_wj_engine->renderEditorAutoPost($posts, $params));
826
+ }
827
+ }
828
+
829
+ function search_terms( $request = null ){
830
+ $response = (object) array(
831
+ 'status' => false,
832
+ 'message' => __( 'Your request has failed', WYSIJA ),
833
+ 'results' => array(),
834
+ 'more' => true,
835
+ );
836
+
837
+ if ( ( ! defined( 'DOING_AJAX' ) && is_null( $request ) ) || ! is_user_logged_in() ){
838
+ return $response;
839
+ }
840
+
841
+ $request = (object) wp_parse_args(
842
+ $request,
843
+ array(
844
+ 'search' => isset( $_GET['search'] ) ? $_GET['search'] : '',
845
+ 'post_type' => isset( $_GET['post_type'] ) ? $_GET['post_type'] : null,
846
+ 'page' => absint( isset( $_GET['page'] ) ? $_GET['page'] : 0 ),
847
+ 'page_limit' => absint( isset( $_GET['page_limit'] ) ? $_GET['page_limit'] : 10 ),
848
+ )
849
+ );
850
+
851
+ if ( is_null( $request->post_type ) ){
852
+ return $response;
853
+ }
854
+
855
+ $response->status = true;
856
+ $response->message = __( 'Request successful', WYSIJA );
857
+
858
+ $response->post_type = get_post_types( array( 'name' => $request->post_type ) );
859
+ $response->post_type = reset( $response->post_type );
860
+
861
+ preg_match( '/@(\w+)/i', $request->search, $response->regex );
862
+
863
+ if ( ! empty( $response->regex ) ){
864
+ $request->search = array_filter( array_map( 'trim', explode( '|', str_replace( $response->regex[0], '|', $request->search ) ) ) );
865
+ $request->search = reset( $request->search );
866
+ $taxonomies = $response->regex[1];
867
+ } else {
868
+ $taxonomies = get_object_taxonomies( $response->post_type );
869
+ }
870
+ $response->taxonomies = get_object_taxonomies( $response->post_type, 'objects' );
871
+
872
+ $response->results = get_terms(
873
+ (array) $taxonomies,
874
+ array(
875
+ 'hide_empty' => false,
876
+ 'search' => $request->search,
877
+ 'number' => $request->page_limit,
878
+ 'offset' => $request->page_limit * ( $request->page - 1 ),
879
+ )
880
+ );
881
+
882
+ if ( empty( $response->results ) || count( $response->results ) < $request->page_limit ){
883
+ $response->more = false;
884
+ }
885
+
886
+ return $response;
887
+ }
888
+
889
+ /**
890
+ * returns a list of articles to the popup in the visual editor
891
+ * @global type $wpdb
892
+ * @return boolean
893
+ */
894
+ function get_articles(){
895
+ // fixes issue with pcre functions
896
+ @ini_set('pcre.backtrack_limit', 1000000);
897
+
898
+ // get parameters
899
+ $raw_data = $_REQUEST['data'];
900
+ $params = array();
901
+ foreach ($raw_data as $value) {
902
+ $params[$value['name']] = $value['value'];
903
+ }
904
+
905
+ // get options
906
+ $model_config = WYSIJA::get('config', 'model');
907
+ $interpret_shortcode = (bool)$model_config->getValue('interp_shortcode');
908
+
909
+ // post statuses
910
+ $helper_wp_tools = WYSIJA::get('wp_tools', 'helper');
911
+ $post_statuses = $helper_wp_tools->get_post_statuses();
912
+ $post_types = $helper_wp_tools->get_post_types();
913
+
914
+ // filter by post_type
915
+ if(isset($params['post_type'])) {
916
+ $post_types_filter = array();
917
+ if(strlen(trim($params['post_type'])) === 0) {
918
+ $post_types_filter = array_keys($post_types);
919
+ $post_types_filter[] = 'post';
920
+ $post_types_filter[] = 'page';
921
+ } else {
922
+ $post_types_filter = trim($params['post_type']);
923
+ }
924
+ // set condition on post type
925
+ $params['post_type'] = $post_types_filter;
926
+ }
927
+
928
+ // query offset when doing incremental loading
929
+ $query_offset = (isset($_REQUEST['query_offset']) && (int)$_REQUEST['query_offset'] >= 0) ? (int)$_REQUEST['query_offset'] : 0;
930
+ $params['query_offset'] = $query_offset;
931
+
932
+ // fetch posts
933
+ $helper_articles = WYSIJA::get('articles', 'helper');
934
+
935
+ // set is_search_query (true) to get a count in addition to the results
936
+ $params['is_search_query'] = true;
937
+
938
+ $model_wp_posts = WYSIJA::get('wp_posts','model');
939
+ $data = $model_wp_posts->get_posts($params);
940
+
941
+ // extract data
942
+ $posts = $data['rows'];
943
+ // contains the total number of rows available
944
+ $count = $data['count'];
945
+
946
+ // return results
947
+ $result = array(
948
+ 'result' => true,
949
+ 'append' => ($query_offset > 0)
950
+ );
951
+
952
+ if(empty($posts) === false) {
953
+ foreach($posts as $key => $post) {
954
+ // interpret shortcodes
955
+ if($interpret_shortcode === true) {
956
+ $posts[$key]['post_content'] = apply_filters('the_content', $posts[$key]['post_content']);
957
+ }
958
+
959
+ // get thumbnail
960
+ $posts[$key]['post_image'] = $helper_articles->getImage($post);
961
+
962
+ // set post status
963
+ $post_status_label = '';
964
+ if(isset($post_statuses[$posts[$key]['post_status']])) {
965
+ $post_status_label = $post_statuses[$posts[$key]['post_status']];
966
+ }
967
+ $posts[$key]['post_status'] = $post_status_label;
968
+ }
969
+ $result['posts'] = $posts;
970
+ $result['total'] = (int)$count['total'];
971
+ }else {
972
+ $result['msg'] = __('There are no posts corresponding to that search.', WYSIJA);
973
+ $result['result'] = false;
974
+ }
975
+
976
+ return $result;
977
+ }
978
+ }
trunk/controllers/ajax/config.php ADDED
@@ -0,0 +1,470 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_control_back_config extends WYSIJA_control{
4
+
5
+ function __construct(){
6
+ if(!WYSIJA::current_user_can('wysija_config')) die("Action is forbidden.");
7
+ parent::__construct();
8
+ }
9
+
10
+ function _displayErrors(){
11
+ if(version_compare(phpversion(), '5.4')>= 0){
12
+ error_reporting(E_ALL ^ E_STRICT);
13
+
14
+ }else{
15
+ error_reporting(E_ALL);
16
+ }
17
+ @ini_set("display_errors", 1);
18
+ }
19
+
20
+ function _hideErrors(){
21
+ error_reporting(0);
22
+ @ini_set('display_errors', '0');
23
+ }
24
+
25
+ function send_test_mail(){
26
+ $this->requireSecurity();
27
+ $this->_displayErrors();
28
+ /*switch the send method*/
29
+ $configVal=$this->_convertPostedInarray();
30
+
31
+ /*send a test mail*/
32
+ $hEmail=WYSIJA::get('email','helper');
33
+ $res['result']=$hEmail->send_test_mail($configVal);
34
+
35
+ if($res['result']){
36
+ $modelConf=WYSIJA::get('config','model');
37
+ $modelConf->save(array('sending_emails_ok'=>$res['result']));
38
+ }
39
+ $this->_hideErrors();
40
+ return $res;
41
+ }
42
+
43
+ function send_test_mail_ms(){
44
+ $this->requireSecurity();
45
+ $this->_displayErrors();
46
+ /*switch the send method*/
47
+ $configVal=$this->_convertPostedInarray();
48
+
49
+ /*send a test mail*/
50
+ $hEmail=WYSIJA::get('email','helper');
51
+ $res['result']=$hEmail->send_test_mail($configVal,true);
52
+ if($res['result']){
53
+ $modelConf=WYSIJA::get('config','model');
54
+ $modelConf->save(array('ms_sending_emails_ok'=>$res['result']));
55
+ }
56
+ //$this->_hideErrors();
57
+ return $res;
58
+ }
59
+
60
+ function bounce_connect(){
61
+
62
+ $configVal=$this->_convertPostedInarray();
63
+ /*try to connect to thebounce server*/
64
+ $bounceClass=WYSIJA::get('bounce','helper');
65
+ $bounceClass->report = true;
66
+ $res['result']=false;
67
+ if($bounceClass->init($configVal)){
68
+ if($bounceClass->connect()){
69
+ $nbMessages = $bounceClass->getNBMessages();
70
+ $this->notice(sprintf(__('Successfully connected to %1$s',WYSIJA),$bounceClass->config->getValue('bounce_login')));
71
+ $this->notice(sprintf(__('There are %1$s messages in your mailbox',WYSIJA),$nbMessages));
72
+ $bounceClass->close();
73
+ if((int)$nbMessages >0) $res['result']=true;
74
+ else $this->notice(sprintf(__('There are no bounced messages to process right now!',WYSIJA),$nbMessages));
75
+ if(!empty($nbMessages)){
76
+ //$app->enqueueMessage('<a class="modal" style="text-decoration:blink" rel="{handler: \'iframe\', size: {x: 640, y: 480}}" href="'.acymailing_completeLink("bounces&task=process",true ).'">'.__("CLICK HERE to handle the messages",WYSIJA).'</a>');
77
+ }
78
+ }else{
79
+ $errors = $bounceClass->getErrors();
80
+ if(!empty($errors)){
81
+ $this->error($errors,true);
82
+ $errorString = implode(' ',$errors);
83
+ $port = $bounceClass->config->getValue('bounce_port','');
84
+ if(preg_match('#certificate#i',$errorString) && !$bounceClass->config->getValue('bounce_selfsigned',false)){
85
+ $this->notice(__('You may need to turn ON the option <i>Self-signed certificates</i>', WYSIJA));
86
+ }elseif(!empty($port) AND !in_array($port,array('993','143','110'))){
87
+ $this->notice(__('Are you sure you selected the right port? You can leave it empty if you do not know what to specify',WYSIJA));
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+
94
+ return $res;
95
+ }
96
+
97
+ /**
98
+ * processing the bounce manually through the config
99
+ * @return type
100
+ */
101
+ function bounce_process(){
102
+ $this->requireSecurity();
103
+ // bounce handling
104
+ $helper_bounce = WYSIJA::get('bounce','helper');
105
+
106
+ // in a multisite case we process first the bounce recording into the bounce table
107
+ if(is_multisite()){
108
+ $helper_bounce->record_bounce_ms();
109
+
110
+ // then we take actions from what has been returned by the bounce
111
+ return $helper_bounce->process_bounce_ms();
112
+ }else{
113
+ return $helper_bounce->process_bounce();
114
+ }
115
+ }
116
+
117
+ function linkignore(){
118
+ $this->requireSecurity();
119
+ $this->_displayErrors();
120
+
121
+ $modelConf=WYSIJA::get('config','model');
122
+
123
+ $ignore_msgs=$modelConf->getValue('ignore_msgs');
124
+ if(!$ignore_msgs) $ignore_msgs=array();
125
+
126
+ $ignore_msgs[$_REQUEST['ignorewhat']]=1;
127
+ $modelConf->save(array('ignore_msgs'=>$ignore_msgs));
128
+
129
+ $res['result']=true;
130
+ $this->_hideErrors();
131
+ return $res;
132
+ }
133
+
134
+ // Ajax called function to enable analytics sharing from welcome page.
135
+ function share_analytics() {
136
+ $this->requireSecurity();
137
+ $this->_displayErrors();
138
+
139
+ $model_config = WYSIJA::get('config','model');
140
+ $model_config->save(array('analytics' => 1));
141
+
142
+ $res['result'] = true;
143
+ $this->_hideErrors();
144
+ return $res;
145
+ }
146
+
147
+ function validate(){
148
+ $this->requireSecurity();
149
+ $helper_licence = WYSIJA::get('licence','helper');
150
+ $result = $helper_licence->check();
151
+
152
+ if(!isset($result['result'])){
153
+ $result['result']=false;
154
+ }
155
+
156
+ return $result;
157
+ }
158
+
159
+ function _convertPostedInarray(){
160
+ $_POST = stripslashes_deep($_POST);
161
+ $data_temp = $_POST['data'];
162
+ $_POST['data']=array();
163
+ foreach($data_temp as $val) $_POST['data'][$val['name']]=$val['value'];
164
+ $data_temp = null;
165
+ foreach($_POST['data'] as $k =>$v){
166
+ $new_key = str_replace(array('wysija[config][',']'),'',$k);
167
+ $config_val[$new_key] = $v;
168
+ }
169
+ return $config_val;
170
+ }
171
+
172
+ // WYSIJA Form Editor
173
+ function wysija_form_generate_template() {
174
+ $data = $this->_wysija_form_get_data();
175
+
176
+ $helper_form_engine = WYSIJA::get('form_engine', 'helper');
177
+ return base64_encode($helper_form_engine->render_editor_template($data));
178
+ }
179
+
180
+ function wysija_form_manage_field() {
181
+ $this->requireSecurity();
182
+ $response = array('result' => true, 'error' => null);
183
+
184
+ // get data
185
+ $data = $this->_wysija_form_get_data();
186
+ $form_id = (int)$_REQUEST['form_id'];
187
+
188
+ // check for required fields
189
+ if(!isset($data['type']) || isset($data['type']) && strlen(trim($data['type'])) === 0) {
190
+ $response['error'] = __('You need to select a type for this field', WYSIJA);
191
+ $response['result'] = false;
192
+ }
193
+ if(!isset($data['name']) || isset($data['name']) && strlen(trim($data['name'])) === 0) {
194
+ $response['error'] = __('You need to specify a name for this field', WYSIJA);
195
+ $response['result'] = false;
196
+ }
197
+
198
+ // only proceed if there is no error
199
+ if($response['error'] === null) {
200
+ $is_required = (isset($data['params']['required']) ? WJ_Utils::to_bool($data['params']['required']) : false);
201
+
202
+ if(isset($data['field_id']) && (int)$data['field_id'] > 0) {
203
+ // it's an update
204
+ $custom_field = WJ_Field::get($data['field_id']);
205
+
206
+ if($custom_field !== NULL) {
207
+ $data['params'] = array_merge($custom_field->settings, $data['params']);
208
+ // update fields
209
+ $custom_field->name = $data['name'];
210
+ $custom_field->type = $data['type'];
211
+ $custom_field->required = $is_required;
212
+ $custom_field->settings = $data['params'];
213
+ $custom_field->save();
214
+ } else {
215
+ // throw error if field does not exist
216
+ $response['error'] = __('This field does not exist', WYSIJA);
217
+ $response['result'] = false;
218
+ }
219
+ } else {
220
+ // create new custom field
221
+ $custom_field = new WJ_Field();
222
+ $custom_field->set(array(
223
+ 'name' => $data['name'],
224
+ 'type' => $data['type'],
225
+ 'required' => $is_required,
226
+ 'settings' => $data['params']
227
+ ));
228
+ $custom_field->save();
229
+ }
230
+
231
+ if($response['error'] === null) {
232
+ $helper_form_engine = WYSIJA::get('form_engine', 'helper');
233
+
234
+ // need to update each block instance of this custom field
235
+ $block = $helper_form_engine->refresh_custom_field($form_id, array(
236
+ 'name' => $data['name'],
237
+ 'field' => $custom_field->user_column_name(),
238
+ 'type' => $data['type'],
239
+ 'required' => $is_required,
240
+ 'settings' => $data['params']
241
+ ));
242
+
243
+ // render editor toolbar & templates
244
+ $response['data'] = array(
245
+ 'toolbar' => base64_encode($helper_form_engine->render_editor_toolbar()),
246
+ 'templates' => base64_encode($helper_form_engine->render_editor_templates())
247
+ );
248
+
249
+ if($block !== null) {
250
+ // refresh block using this custom field in the current form
251
+ $block_template = $helper_form_engine->render_editor_template($block);
252
+
253
+ if($block_template !== null) {
254
+ $response['data']['block'] = base64_encode($block_template);
255
+ }
256
+ }
257
+ }
258
+ }
259
+
260
+ return $response;
261
+ }
262
+
263
+ // get wysija form data from post (auto decoding)
264
+ private function _wysija_form_get_data() {
265
+ if(isset($_POST['wysijaData'])) {
266
+ // decode the data string
267
+ $decoded_data = base64_decode($_POST['wysijaData']);
268
+
269
+ // avoid using stripslashes as it's not reliable depending on the magic quotes settings
270
+ $json_data = str_replace('\"', '"', $decoded_data);
271
+ return json_decode($json_data, true);
272
+ }
273
+ return array();
274
+ }
275
+
276
+ // remove a custom field
277
+ function form_field_delete() {
278
+ $this->requireSecurity();
279
+ $data = $this->_wysija_form_get_data();
280
+
281
+ // check for field_id parameter
282
+ if(isset($data['field_id']) && (int)$data['field_id'] > 0) {
283
+ // get custom field by id
284
+ $custom_field = WJ_Field::get($data['field_id']);
285
+
286
+ // if the custom field exists
287
+ if($custom_field !== null) {
288
+ // we need to remove the field in any form
289
+ // get all forms
290
+ $model_forms = WYSIJA::get('forms', 'model');
291
+ $forms = $model_forms->getRows();
292
+
293
+ // get custom field name
294
+ $field_name = $custom_field->user_column_name();
295
+ if(is_array($forms) && count($forms) > 0) {
296
+ // loop through each form
297
+ foreach ($forms as $i => $form) {
298
+ $requires_update = false;
299
+
300
+ // decode form data
301
+ $data = unserialize(base64_decode($form['data']));
302
+
303
+ // loop through each block
304
+ foreach($data['body'] as $j => $block) {
305
+ // in case we find a text block
306
+ if($block['field'] === $field_name) {
307
+ unset($data['body'][$j]);
308
+ // flag form to be updated
309
+ $requires_update = true;
310
+ }
311
+ }
312
+
313
+ // if the form requires update, let's do it
314
+ if($requires_update === true) {
315
+ $model_forms->reset();
316
+ $model_forms->update(array('data' => base64_encode(serialize($data))), array('form_id' => (int)$form['form_id']));
317
+ }
318
+ }
319
+ }
320
+
321
+ // delete custom field
322
+ $custom_field->delete();
323
+ }
324
+ }
325
+ }
326
+
327
+ function form_name_save() {
328
+ $this->requireSecurity();
329
+ // get name from post and stripslashes it
330
+ $form_name = trim(stripslashes($_POST['name']));
331
+ // get form_id from post
332
+ $form_id = (int)$_POST['form_id'];
333
+
334
+ if(strlen($form_name) > 0 && $form_id > 0) {
335
+ // update the form name within the database
336
+ $model_forms = WYSIJA::get('forms', 'model');
337
+ $model_forms->update(array('name' => $form_name), array('form_id' => $form_id));
338
+ }
339
+ return array('name' => $form_name);
340
+ }
341
+
342
+ function form_save() {
343
+ $this->requireSecurity();
344
+ // get form id
345
+ $form_id = null;
346
+ if(isset($_POST['form_id']) && (int)$_POST['form_id'] > 0) {
347
+ $form_id = (int)$_POST['form_id'];
348
+ }
349
+
350
+ // decode json data and convert to array
351
+ $raw_data = null;
352
+ if(isset($_POST['wysijaData'])) {
353
+ // decode the data string
354
+ $decoded_data = base64_decode($_POST['wysijaData']);
355
+
356
+ // avoid using stripslashes as it's not reliable depending on the magic quotes settings
357
+ $json_data = str_replace('\"', '"', $decoded_data);
358
+ // decode JSON data
359
+ $raw_data = json_decode($json_data, true);
360
+ }
361
+
362
+ if($form_id === null or $raw_data === null) {
363
+ $this->error('Error saving', false);
364
+ return array('result' => false);
365
+ } else {
366
+
367
+ // flag to see if the user can select his own lists
368
+ $has_list_selection = false;
369
+ $raw_data['settings']['lists_selected_by'] = 'admin';
370
+
371
+ // special case for block params, as we base64_encode the values and serialize arrays, so let's decode it before saving it
372
+ foreach($raw_data['body'] as $block_id => $block) {
373
+ if(isset($block['params']) && !empty($block['params'])) {
374
+ $params = array();
375
+
376
+ foreach($block['params'] as $key => $value) {
377
+ $value = base64_decode($value);
378
+ if(is_serialized($value) === true) {
379
+ $value = (array) unserialize($value);
380
+ }
381
+ $params[$key] = $value;
382
+ }
383
+
384
+ if(!empty($params)) {
385
+ $raw_data['body'][$block_id]['params'] = $params;
386
+ }
387
+ }
388
+ // special case when the list selection widget is present
389
+ if($block['type'] === 'list') {
390
+ $has_list_selection = true;
391
+
392
+ $lists = array();
393
+ foreach($params['values'] as $list) {
394
+ $lists[] = (int)$list['list_id'];
395
+ }
396
+
397
+ // override lists in form settings
398
+ $raw_data['settings']['lists'] = $lists;
399
+ $raw_data['settings']['lists_selected_by'] = 'user';
400
+ }
401
+ }
402
+
403
+ // make sure the lists parameter is an array, otherwise it's not gonna work for a single list
404
+ if($has_list_selection === false) {
405
+ if(!is_array($raw_data['settings']['lists'])) {
406
+ $raw_data['settings']['lists'] = array((int)$raw_data['settings']['lists']);
407
+ }
408
+ }
409
+
410
+ // set form id into data so we can track who subscribed through it
411
+ $raw_data['form_id'] = $form_id;
412
+
413
+ // set data in form engine so we can generate the render the web version
414
+ $helper_form_engine = WYSIJA::get('form_engine', 'helper');
415
+ $helper_form_engine->set_data($raw_data);
416
+
417
+ // check if the form has already been inserted in a widget and therefore display different success message
418
+ $widgets = get_option('widget_wysija');
419
+ $is_form_added_as_widget = false;
420
+ if($widgets !== false) {
421
+ foreach($widgets as $widget) {
422
+ if(is_array($widget) && isset($widget['form']) && (int)$widget['form'] === $form_id) {
423
+ $is_form_added_as_widget = true;
424
+ }
425
+
426
+ }
427
+ }
428
+ if($is_form_added_as_widget === true) {
429
+ $save_message = __('Saved! The changes are already active in your widget.', WYSIJA);
430
+ } else {
431
+ $save_message = str_replace(array(
432
+ '[link_widget]',
433
+ '[/link_widget]'
434
+ ), array(
435
+ '<a href="'.admin_url('widgets.php').'" target="_blank">',
436
+ '</a>'
437
+ ),
438
+ __('Saved! Add this form to [link_widget]a widget[/link_widget].', WYSIJA)
439
+ );
440
+ }
441
+
442
+ // update form data in DB
443
+ $model_forms = WYSIJA::get('forms', 'model');
444
+ $model_forms->reset();
445
+ $result = $model_forms->update(array(
446
+ // get encoded data to store it in the database
447
+ 'data' => $helper_form_engine->get_encoded('data')
448
+ ), array('form_id' => $form_id));
449
+
450
+ // return response depending on db save result
451
+ if(!$result) {
452
+ // throw error
453
+ $this->error(__('Your form could not be saved.', WYSIJA));
454
+ } else {
455
+ // save successful
456
+ $this->notice(__('Your form has been saved.', WYSIJA));
457
+ }
458
+ }
459
+
460
+ return array('result' => $result, 'save_message' => base64_encode($save_message), 'exports' => base64_encode($helper_form_engine->render_editor_export($form_id)));
461
+ }
462
+
463
+ function wysija_dismiss_update_notice() {
464
+ WYSIJA::update_option('wysija_dismiss_update_notice', true);
465
+ }
466
+
467
+ function wysija_dismiss_license_notice() {
468
+ WYSIJA::update_option('wysija_dismiss_license_notice', true);
469
+ }
470
+ }
trunk/controllers/ajax/index.html ADDED
File without changes
trunk/controllers/ajax/statistics.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ require_once(WYSIJA_CORE.'module'.DS.'statistics.php'); // @todo
5
+
6
+ class WYSIJA_control_back_statistics extends WYSIJA_control {
7
+
8
+ /**
9
+ * Main model of this controller
10
+ * @var string
11
+ */
12
+ public $model = 'statistics';
13
+
14
+ /**
15
+ * Main view of this controller
16
+ * @var string
17
+ */
18
+ public $view = 'statistics';
19
+
20
+ /**
21
+ * Date format of filter
22
+ * @var string
23
+ */
24
+ protected $date_format = 'Y/m/d';
25
+
26
+ /**
27
+ * Render a hook of a specific module
28
+ * @return string
29
+ */
30
+ public function get_block() {
31
+ if (!WYSIJA::current_user_can('wysija_stats_dashboard'))
32
+ die('Action is forbidden.');
33
+
34
+ if (empty($_REQUEST['block']))
35
+ return '';
36
+ $module = $_REQUEST['block'];
37
+ $hook_name = 'hook_stats';
38
+ return apply_filters('custom_module_hook', '', $module, $hook_name, $this->get_post_params());
39
+ }
40
+
41
+ protected function get_post_params() {
42
+ $params = array( );
43
+ $order_by = !empty($_REQUEST['filter']['orderBy']) ? $_REQUEST['filter']['orderBy'] : null;
44
+ switch (strtolower($order_by)) {
45
+ case 'sent':
46
+ $order_by = WYSIJA_module_statistics::ORDER_BY_SENT;
47
+ break;
48
+ case 'open':
49
+ $order_by = WYSIJA_module_statistics::ORDER_BY_OPEN;
50
+ break;
51
+ case 'click':
52
+ $order_by = WYSIJA_module_statistics::ORDER_BY_CLICK;
53
+ break;
54
+ case 'unsubscribe':
55
+ $order_by = WYSIJA_module_statistics::ORDER_BY_UNSUBSCRIBE;
56
+ break;
57
+ default:
58
+ $order_by = null;
59
+ break;
60
+ }
61
+ $order_direction = !empty($_REQUEST['filter']['orderDirection']) ? $_REQUEST['filter']['orderDirection'] : null;
62
+ switch (strtolower($order_direction)) {
63
+ case 'asc':
64
+ $order_direction = WYSIJA_module_statistics::ORDER_DIRECTION_ASC;
65
+ break;
66
+ case 'desc':
67
+ default:
68
+ $order_direction = WYSIJA_module_statistics::ORDER_DIRECTION_DESC;
69
+ break;
70
+ }
71
+ $params['top'] = !empty($_REQUEST['filter']['itemPerPage']) ? (int)$_REQUEST['filter']['itemPerPage'] : WYSIJA_module_statistics::DEFAULT_TOP_RECORDS;
72
+ $params['from'] = !empty($_REQUEST['filter']['from']) ? $_REQUEST['filter']['from'] : null;
73
+ $params['to'] = !empty($_REQUEST['filter']['to']) ? $_REQUEST['filter']['to'] : null;
74
+ $params['last_days'] = isset($_REQUEST['filter']['lastDays']) ? $_REQUEST['filter']['lastDays'] : null;
75
+
76
+ $params['order_by'] = $order_by;
77
+ $params['order_direction'] = $order_direction;
78
+ $params['additional_param'] = !empty($_REQUEST['filter']['additionalParam']) ? trim($_REQUEST['filter']['additionalParam']) : null;
79
+
80
+ // this doesn't work when php is less than 5.3, this is the case on my host (ben) which is very popular in France, SPain and UK
81
+ // we cannot use functions from php 5.3
82
+ if (function_exists('date_diff')) {
83
+ $this->data['date_interval'] = date_diff(date_create($params['from']), date_create($params['to']));
84
+ }
85
+ else {
86
+ $duration = strtotime($params['to']) - strtotime($params['from']);
87
+ $helper_toolbox = WYSIJA::get('toolbox', 'helper');
88
+ $this->data['date_interval'] = (object)$helper_toolbox->convert_seconds_to_array($duration, false);
89
+ }
90
+ $params['group_by'] = ( $this->data['date_interval']->days == 0 || $this->data['date_interval']->days > WYSIJA_module_statistics::SWITCHING_DATE_TO_MONTH_THRESHOLD) ?
91
+ WYSIJA_module_statistics::GROUP_BY_MONTH :
92
+ WYSIJA_module_statistics::GROUP_BY_DATE; // $date_interval->days == 0, means, no begin date, no end date
93
+ // Hack!
94
+ $_REQUEST['limit_pp'] = $params['top']; // Pagination, mark current selected value
95
+
96
+ $this->save_last_selection($params);
97
+
98
+ // Modify TO date to make sure we always count 23:59:59 of that day
99
+ $to = new DateTime($params['to']);
100
+ $to->modify('+1 day');
101
+ $params['to'] = $to->format($this->date_format);
102
+
103
+ return $params;
104
+ }
105
+
106
+ protected function save_last_selection($params) {
107
+ $stats_session_manager = new WJ_StatsSessionManager();
108
+ $stats_session = new WJ_StatsSession();
109
+ $stats_session->last_days = $params['last_days'];
110
+ $stats_session->from = $params['from'];
111
+ $stats_session->to = $params['to'];
112
+ $stats_session_manager->set_last_selection($stats_session);
113
+ }
114
+
115
+ }
trunk/controllers/ajax/subscribers.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ include(dirname(dirname(__FILE__)).DS.'front.php');
4
+ class WYSIJA_control_back_subscribers extends WYSIJA_control_front{
5
+ var $model='user';
6
+ var $view='';
7
+
8
+ function __construct(){
9
+ parent::__construct();
10
+ $data=array();
11
+ foreach($_REQUEST['data'] as $vals){
12
+ $data[esc_sql($vals['name'])]=esc_sql($vals['value']);
13
+ }
14
+ if(isset($data['message_success'])){
15
+ $this->messages['insert'][true]=$data['message_success'];
16
+ }else{
17
+ $this->messages['insert'][true]=__('User has been inserted.',WYSIJA);
18
+ }
19
+
20
+ $this->messages['insert'][false]=__('User has not been inserted.',WYSIJA);
21
+ $this->messages['update'][true]=__('User has been updated.',WYSIJA);
22
+ $this->messages['update'][false]=__('User has not been updated.',WYSIJA);
23
+ }
24
+
25
+ function save(){
26
+ $datarequested=array();
27
+ $i=0;
28
+ foreach($_REQUEST['data'] as $vals){
29
+ if($vals['name']=='wysija[user_list][list_id][]'){
30
+ $datarequested[str_replace('wysija[user_list][list_id][]', 'wysija[user_list][list_id]['.$i.']', esc_sql($vals['name']))]=esc_sql($vals['value']);
31
+ $i++;
32
+ }else $datarequested[esc_sql($vals['name'])]=esc_sql($vals['value']);
33
+ }
34
+
35
+ $data=$this->convertUserData($datarequested);
36
+
37
+ $helperUser=WYSIJA::get('user','helper');
38
+ if(!$helperUser->checkData($data))return false;
39
+ if(!$helperUser->throttleRepeatedSubscriptions($data))return false;
40
+ if($helperUser->addSubscriber($data)) {
41
+ $helperUser->storeSubscriberIP();
42
+ }
43
+
44
+ return true;
45
+ }
46
+
47
+ // REFACTOR: Insanely complicated and inefficient
48
+ function convertUserData($datarequested){
49
+ $data=array();
50
+
51
+ //get the lists
52
+ if(isset($datarequested['wysija[user_list][list_ids]'])){
53
+ $listids=explode(',',$datarequested['wysija[user_list][list_ids]']);
54
+ $subdate=time();
55
+ unset($datarequested['wysija[user_list][list_ids]']);
56
+ }else{
57
+ $i=0;
58
+ $listids=array();
59
+ for ($i = 0; $i <= 25; $i++) {
60
+ $testkey='wysija[user_list][list_id]['.$i.']';
61
+ if(isset($datarequested[$testkey])) $listids[]=$datarequested[$testkey];
62
+ unset($datarequested[$testkey]);
63
+ }
64
+ }
65
+ $data['user_list']['list_ids']=$listids;
66
+
67
+ // define array for custom user fields
68
+ $data['user_field'] = array();
69
+
70
+ //get the user info and the rest of the data posted
71
+ foreach($datarequested as $key => $val){
72
+ if(strpos($key, 'wysija[user]')!== false) {
73
+ $keymodified=str_replace(array('wysija[','][',']'),array('','#',''),$key);
74
+ $keystabcol=explode('#',$keymodified);
75
+ switch(count($keystabcol)){
76
+ case 2:
77
+ $data[$keystabcol[0]][$keystabcol[1]]=$val;
78
+ break;
79
+ case 3:
80
+ $data[$keystabcol[0]][$keystabcol[1]][$keystabcol[2]]=$val;
81
+ break;
82
+ }
83
+ } else if(strpos($key, 'wysija[field]')!== false){
84
+ $keymodified=str_replace(array('wysija[','][',']'),array('','#',''),$key);
85
+ $keystabcol=explode('#',$keymodified);
86
+
87
+ switch(count($keystabcol)){
88
+ case 2:
89
+ $data['user_field'][$keystabcol[1]] = $val;
90
+ break;
91
+ case 3:
92
+ $data['user_field'][$keystabcol[1]][$keystabcol[2]] = $val;
93
+ break;
94
+ }
95
+ } else {
96
+ if(!isset($data[$key])) $data[$key]=$val;
97
+ }
98
+ }
99
+
100
+ return $data;
101
+ }
102
+
103
+ function registerToLists($data,$uid){
104
+ $model=WYSIJA::get('user_list','model');
105
+ if(isset($data['wysija[user_list][list_ids]'])){
106
+ $listids=explode(',',$data['wysija[user_list][list_ids]']);
107
+
108
+ $subdate=time();
109
+
110
+
111
+ }else{
112
+ $i=0;
113
+ $listids=array();
114
+ for ($i = 0; $i <= 25; $i++) {
115
+ $testkey='wysija[user_list][list_id]['.$i.']';
116
+ if(isset($data[$testkey])) $listids[]=$data[$testkey];
117
+ }
118
+
119
+ //$listids=$data['wysija[user_list][list_id]'];
120
+ }
121
+ foreach($listids as $listid){
122
+ $model->replace(array('list_id'=>$listid,'user_id'=>$uid,'sub_date'=>$subdate));
123
+ $model->reset();
124
+ }
125
+
126
+ }
127
+ }
trunk/controllers/ajax/tmce.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_control_back_tmce extends WYSIJA_control{
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ $this->viewObj=WYSIJA::get('tmce','view');
8
+ }
9
+
10
+ function registerAdd(){
11
+ $this->viewObj->title=__('Insert Subscription Form',WYSIJA);
12
+
13
+ $this->viewObj->registerAdd( );
14
+ exit;
15
+ }
16
+
17
+ }
trunk/controllers/back.php ADDED
@@ -0,0 +1,779 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ global $wysi_location;
4
+ class WYSIJA_control_back extends WYSIJA_control{
5
+ var $redirectAfterSave=true;
6
+ var $searchable=array();
7
+ var $data=array();
8
+ var $jsTrans=array();
9
+ var $msgOnSave=true;
10
+ var $pref=array();
11
+ var $statuses=array();
12
+ var $viewShow=null;
13
+ var $_affected_rows = 0; //affected rows by batch select
14
+
15
+ function __construct($extension="wysija-newsletters"){
16
+ $this->extension=$extension;
17
+ parent::__construct();
18
+ global $wysija_msg,$wysija_queries,$wysija_queries_errors;
19
+ $wysija_msgTemp=get_option('wysija_msg');
20
+
21
+ if(is_array($wysija_msgTemp) && count($wysija_msgTemp)>0){
22
+ $wysija_msg=$wysija_msgTemp;
23
+ }
24
+
25
+ $wysija_qryTemp=get_option('wysija_queries');
26
+ $wysija_qryErrors=get_option('wysija_queries_errors');
27
+ if(is_array($wysija_qryTemp) && count($wysija_qryTemp)>0){
28
+ $wysija_queries=$wysija_qryTemp;
29
+ }
30
+
31
+ if(is_array($wysija_qryErrors) && count($wysija_qryErrors)>0){
32
+ $wysija_queries_errors=$wysija_qryErrors;
33
+ }
34
+
35
+ WYSIJA::update_option('wysija_queries','');
36
+ WYSIJA::update_option('wysija_queries_errors','');
37
+ WYSIJA::update_option('wysija_msg','');
38
+ global $wysija_installing;
39
+ if($wysija_installing===true) return;
40
+ $this->pref=get_user_meta(WYSIJA::wp_get_userdata('ID'),'wysija_pref',true);
41
+
42
+ $prefupdate=false;
43
+ if($this->pref) {
44
+ $prefupdate=true;
45
+ $this->pref=unserialize(base64_decode($this->pref));
46
+ }else{
47
+ $this->pref=array();
48
+ }
49
+
50
+ if(!isset($_GET['action'])) $action='default';
51
+ else $action=$_GET['action'];
52
+
53
+ if(isset($_REQUEST['limit_pp'])){
54
+ $this->pref[$_REQUEST['page']][$action]['limit_pp']=$_REQUEST['limit_pp'];
55
+ }
56
+
57
+ if (!empty($_REQUEST['orderby'])) {
58
+ $_REQUEST['orderby'] = preg_replace('|[^a-z0-9#_.-]|i','',$_REQUEST['orderby']);
59
+ }
60
+ if (!empty($_REQUEST['ordert']) && !in_array(strtoupper($_REQUEST['ordert']), array('DESC', 'ASC'))){
61
+ $_REQUEST['ordert'] = 'DESC';
62
+ }
63
+
64
+ if(!empty($_REQUEST['id'])){
65
+ $_REQUEST['id'] = (int) $_REQUEST['id'];
66
+ }
67
+
68
+ if(!empty($_REQUEST['search'])){
69
+ $_REQUEST['search'] = esc_attr($_REQUEST['search']);
70
+ }
71
+
72
+ if($this->pref && isset($_REQUEST['page']) && $_REQUEST['page'] && isset($this->pref[$_REQUEST['page']][$action]['limit_pp'])){
73
+ $this->viewObj->limit_pp=$this->pref[$_REQUEST['page']][$action]['limit_pp'];
74
+ $this->modelObj->limit_pp=$this->pref[$_REQUEST['page']][$action]['limit_pp'];
75
+ }
76
+
77
+ if($prefupdate){
78
+ update_user_meta(WYSIJA::wp_get_userdata('ID'),'wysija_pref',base64_encode(serialize($this->pref)));
79
+ }else{
80
+ add_user_meta(WYSIJA::wp_get_userdata('ID'),'wysija_pref',base64_encode(serialize($this->pref)));
81
+ }
82
+ add_action('wysija_various_check',array($this,'variousCheck'));
83
+ do_action('wysija_various_check');
84
+
85
+ }
86
+
87
+ function variousCheck(){
88
+ $model_config = WYSIJA::get('config','model');
89
+
90
+ if(get_option('wysicheck')){
91
+ $helper_licence = WYSIJA::get('licence','helper');
92
+ $result = $helper_licence->check(true);
93
+ if($result['nocontact']){
94
+ // redirect instantly to a page with a javascript file where we check the domain is ok
95
+ $data = get_option('wysijey');
96
+ // remotely connect to host
97
+ wp_enqueue_script('wysija-verif-licence', 'http://www.mailpoet.com/?wysijap=checkout&wysijashop-page=1&controller=customer&action=checkDomain&js=1&data='.$data, array( 'jquery' ), time());
98
+ }
99
+ }
100
+
101
+ }
102
+
103
+
104
+ function errorInstall(){
105
+ $this->viewObj->renderErrorInstall();
106
+ }
107
+
108
+ function _resetGlobMsg(){
109
+ global $wysija_msg,$wysija_queries,$wysija_queries_errors;
110
+
111
+ $wysija_msg=$wysija_queries=$wysija_queries_errors=array();
112
+ }
113
+ function defaultDisplay(){
114
+ $this->viewShow=$this->action='main';
115
+
116
+ // if it has not been enqueud in the head we print it here(can happens based on the action after a save or so)
117
+ $this->js[]='wysija-admin-list';
118
+
119
+ // get the filters
120
+ if(isset($_REQUEST['search']) && $_REQUEST['search']){
121
+ $this->filters['like']=array();
122
+ foreach($this->searchable as $searchable){
123
+ $this->filters['like'][$searchable]=$_REQUEST['search'];
124
+ }
125
+
126
+ }
127
+
128
+ if($this->filters){
129
+ $this->modelObj->setConditions($this->filters);
130
+ }
131
+
132
+ if($this->joins){
133
+ $this->modelObj->setJoin($this->joins);
134
+ }
135
+
136
+ if($this->statuses){
137
+ //we count by statuses
138
+ $query='SELECT count('.$this->modelObj->pk.') as count, status FROM `[wysija]'.$this->modelObj->table_name.'` GROUP BY status';
139
+ $countss=$this->modelObj->query('get_res',$query,ARRAY_A);
140
+ $counts=array();
141
+ $this->modelObj->countRows=0;
142
+
143
+ foreach($countss as $count){
144
+ $mystat=(int)$count['status'];
145
+
146
+ $this->statuses[$mystat]['count']=$count['count'];
147
+ $this->statuses[$mystat]['uri']=$this->getDefaultUrl(false).'&link_filter='.$this->statuses[$mystat]['key'];
148
+
149
+ $this->modelObj->countRows=$this->modelObj->countRows+$count['count'];
150
+ $this->viewObj->statuses=$this->statuses;
151
+ }
152
+
153
+ }else{
154
+ $this->modelObj->countRows=$this->modelObj->count();
155
+ }
156
+
157
+
158
+
159
+
160
+ if(isset($_REQUEST['orderby'])){
161
+ $this->modelObj->orderBy($_REQUEST['orderby'],strtoupper($_REQUEST['ordert']));
162
+ }else{
163
+ $this->modelObj->orderBy($this->modelObj->getPk(),'DESC');
164
+ }
165
+ $this->modelObj->limitON=true;
166
+
167
+ $data=$this->modelObj->getRows($this->list_columns);
168
+
169
+ $methodDefaultData='defaultData';
170
+ if(method_exists($this,$methodDefaultData )){
171
+ $this->$methodDefaultData($data);
172
+ }
173
+
174
+ }
175
+
176
+ function defaultData($data){
177
+ $this->data=$data;
178
+ }
179
+
180
+
181
+ function render(){
182
+
183
+ $this->viewObj->render($this->viewShow,$this->data);
184
+ }
185
+
186
+ /**
187
+ * by default this is the first method called from a controller this is from where we route to other methods
188
+ */
189
+ function main(){
190
+ $this->__construct();
191
+ if($this->model){
192
+ if(isset($_REQUEST['action'])) $action=$_REQUEST['action'];
193
+ else $action='defaultDisplay';
194
+ if(!$action) $action='defaultDisplay';
195
+
196
+ if($action){
197
+ $this->_tryAction($action);
198
+ }
199
+ }else{
200
+ $this->error('No Model is linked to this controller : '. get_class($this));
201
+ return false;
202
+ }
203
+
204
+ return true;
205
+ }
206
+
207
+ function __setMetaTitle(){
208
+ global $title;
209
+
210
+ if(isset($this->title))$title=$this->title;
211
+ else $title=$this->viewObj->title;
212
+ }
213
+
214
+ function _tryAction($action){
215
+ $action=strip_tags($action);
216
+ $_REQUEST = stripslashes_deep($_REQUEST);
217
+ $_POST = stripslashes_deep($_POST);
218
+
219
+ $is_batch_select = $this->_batchSelect();
220
+ $this->_affected_rows = $is_batch_select ? $this->_batch_select['count'] : (!empty($_REQUEST['wysija']['user']['user_id']) ? count($_REQUEST['wysija']['user']['user_id']) : 0);
221
+ if(method_exists($this, $action)){
222
+ /* in some bulk actions we need to specify the action name and one or few variables*/
223
+ $this->action=$action;
224
+ $this->viewShow=$this->action;
225
+ if(!$this->viewShow) $this->viewShow='defaultDisplay';
226
+
227
+ if(strpos($action, 'bulk_')===false)$this->$action();
228
+ else {
229
+ $this->$action($_REQUEST['wysija'][$this->model][$this->modelObj->pk]);
230
+ }
231
+
232
+ $this->__setMetaTitle();
233
+ }else{
234
+ /* in some bulk actions we need to specify the action name and one or few variables*/
235
+ if(strpos($action,'actionvar_')!== false){
236
+ $data=explode('-',$action);
237
+ $datas=array();
238
+
239
+ foreach($data as $dt){
240
+ $res=explode('_',$dt);
241
+ $datas[$res[0]]=$res[1];
242
+ }
243
+
244
+ $action =$datas['actionvar'];
245
+ unset($datas['actionvar']);
246
+ $this->action=$action;
247
+
248
+ if(method_exists($this, $this->action)){
249
+ $this->viewShow=$this->action;
250
+ $this->$action($datas);
251
+ $this->__setMetaTitle();
252
+
253
+ }else{
254
+ $this->error("Action '".$action."' does not exist in controller : ". get_class($this));
255
+ $this->redirect();
256
+ }
257
+ }else{
258
+ $this->error("Action '".$action."' does not exist in controller : ". get_class($this));
259
+ $this->redirect();
260
+ //$this->defaultDisplay();
261
+ }
262
+
263
+ }
264
+
265
+ if(defined('WYSIJA_REDIRECT')) $this->redirectProcess();
266
+
267
+ if( !empty( $_REQUEST['page'] ) && $_REQUEST['page'] !== 'wysija_premium'){
268
+ $this->checkTotalSubscribers();
269
+ }
270
+
271
+ }
272
+
273
+ function checkTotalSubscribers(){
274
+ add_action('wysija_check_total_subscribers',array($this,'_checkTotalSubscribers'));
275
+ do_action('wysija_remove_action_check_total_subscribers');
276
+ do_action('wysija_check_total_subscribers');
277
+ }
278
+
279
+ /**
280
+ * Batch select process
281
+ * - Currently, is for subscribers only
282
+ * - Get all matched subscribers and override to $_REQUEST['wysija']['user']['user_id']
283
+ */
284
+ function _batchSelect(){
285
+ if(empty($_REQUEST['wysija']['user']['force_select_all']))
286
+ return FALSE;
287
+ if (!(bool)$_REQUEST['wysija']['user']['force_select_all'])
288
+ return FALSE;
289
+ if(empty($_REQUEST['wysija']['user']['timestamp']))
290
+ return FALSE;
291
+ //$_POST['wysija']['filter'] = array(
292
+ // link_filter => '', //[subscribed, unsubscribed, unsubscribed, all]
293
+ // filter_list => int
294
+ //);
295
+ //
296
+ //$_POST['wysija']['user']['timestamp'] = int
297
+ //
298
+ //select all users which match to $_POST['wysija']['filter'] and create_at <= $_POST['wysija']['user']['timestamp']
299
+ // - build query
300
+
301
+ $select = array( '[wysija]user.user_id');
302
+
303
+ // filters for unsubscribed
304
+ $filters = $this->modelObj->detect_filters();
305
+
306
+
307
+ $this->_batch_select = array();
308
+
309
+
310
+ $this->_batch_select['query'] = $this->modelObj->get_subscribers( $select, $filters, '', true );
311
+ $this->_batch_select['query_count'] = $this->modelObj->get_subscribers( array( 'COUNT(DISTINCT([wysija]user.user_id))'), $filters, '', true );
312
+
313
+
314
+ //Create a temporary table
315
+ $temp_table_name = '[wysija]user'. time();
316
+ $temp_table_create = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$temp_table_name . ' (user_id int (10) NOT NULL, PRIMARY KEY (user_id))';
317
+ $temp_table_insert = 'INSERT IGNORE INTO '.$temp_table_name.' ' . $this->_batch_select['query'];
318
+ $model_user = WYSIJA::get('user','model');
319
+
320
+ $model_user->query($temp_table_create);
321
+ $model_user->query($temp_table_insert);
322
+
323
+ //Override the queres with temporary table
324
+ unset($this->_batch_select['where']);
325
+ $row_count = $model_user->query('get_row', 'SELECT COUNT(*) as row_count FROM '.$temp_table_name);
326
+ $this->_batch_select['original_query'] = $this->_batch_select['query']; // useful for export feature; in this case, we don't use temporary table
327
+ $this->_batch_select['select'] = 'SELECT DISTINCT user_id';
328
+ $this->_batch_select['from'] = 'FROM '.$temp_table_name . ' A';
329
+ $this->_batch_select['query'] = 'SELECT user_id FROM '.$temp_table_name;
330
+ $this->_batch_select['count'] = $row_count['row_count'];
331
+ return true;
332
+ }
333
+
334
+
335
+
336
+ function _checkTotalSubscribers(){
337
+
338
+ $config=WYSIJA::get('config','model');
339
+ $totalSubscribers=$config->getValue('total_subscribers');
340
+ $helper_licence = WYSIJA::get('licence','helper');
341
+
342
+ if((int)$totalSubscribers>1900){
343
+ if((int)$totalSubscribers>2000){
344
+
345
+ $url_checkout = $helper_licence->get_url_checkout('over200');
346
+ $this->error(str_replace(array('[link]','[/link]'),
347
+ array('<a title="'.__('Get Premium now',WYSIJA).'" target="_blank" href="'.$url_checkout.'">','</a>'),
348
+ sprintf(__('Yikes. You\'re over the limit of 2000 subscribers for the free version of MailPoet (%1$s in total). Sending is disabled now. Please upgrade your version to [link]premium[/link] to send without limits.',WYSIJA)
349
+ ,$totalSubscribers)),true);
350
+
351
+ }else{
352
+ $url_checkout = $helper_licence->get_url_checkout('near200');
353
+ $this->notice(str_replace(array('[link]','[/link]'),
354
+ array('<a title="'.__('Get Premium now',WYSIJA).'" target="_blank" href="'.$url_checkout.'">','</a>'),
355
+ sprintf(__('Yikes! You\'re near the limit of %1$s subscribers for MailPoet\'s free version. Upgrade to [link]Premium[/link] to send without limits, and more.',WYSIJA)
356
+ ,"2000")));
357
+ }
358
+ }
359
+ }
360
+
361
+ function edit($id=false){
362
+
363
+ if(isset($_REQUEST['id']) || $id){
364
+ if(!$id) $id=$_REQUEST['id'];
365
+ $this->data[$this->modelObj->table_name]=$this->modelObj->getOne($this->form_columns,array($this->modelObj->pk=>$id));
366
+ }else{
367
+ $this->error('Cannot edit element primary key is missing : '. get_class($this));
368
+ }
369
+
370
+ }
371
+
372
+ function view($id=false){
373
+
374
+ if(isset($_REQUEST['id']) || $id){
375
+ if(!$id) $id=$_REQUEST['id'];
376
+ $this->data[$this->modelObj->table_name]=$this->modelObj->getOne($this->form_columns,array($this->modelObj->pk=>$id));
377
+
378
+ }else{
379
+ $this->error('Cannot view element primary key is missing : '. get_class($this));
380
+ }
381
+
382
+ }
383
+
384
+ function add($dataPost=false){
385
+
386
+ if(!$dataPost){
387
+ $data=array();
388
+ foreach($this->form_columns as $key){
389
+ $data[$key]='';
390
+ }
391
+ }else{
392
+
393
+ $data=array();
394
+ foreach($this->form_columns as $key){
395
+ if($key != $this->viewObj->model->pk) $data[$key]=$dataPost[$key];
396
+ }
397
+ $data[$this->viewObj->model->pk]='';
398
+ }
399
+
400
+ }
401
+
402
+ function save(){
403
+ $this->requireSecurity();
404
+ //see if it's an update or an insert
405
+ //get the pk and its value as a conditions where pk = pkval
406
+ $conditions=$this->getPKVal($this->modelObj);
407
+
408
+ if($conditions){
409
+ //this an update
410
+
411
+ $result=$this->modelObj->update($_POST['wysija'][$this->model],$conditions);
412
+
413
+ if($this->msgOnSave){
414
+
415
+ // Create the update success message and add edit again link.
416
+ $update_success = str_replace(array('[link]','[/link]'),array('<a href="admin.php?page=wysija_subscribers&action=edit&id='.$result.'" >',"</a>"), $this->messages['update'][true]);
417
+
418
+ if ($result) {
419
+ $this->notice($update_success);
420
+ } else {
421
+ if($result==0){
422
+
423
+ }else{
424
+ $this->error($this->messages['update'][false],true);
425
+ }
426
+
427
+ }
428
+ }
429
+
430
+
431
+ if($this->redirectAfterSave){
432
+ if(isset($this->modelObj->stay)){
433
+ $this->action='edit';
434
+ $this->redirect();
435
+ }else{
436
+ $this->action='edit';
437
+ $this->redirect();
438
+ }
439
+ }
440
+
441
+ }else{
442
+ //this is an insert
443
+ unset($_POST['wysija'][$this->model][$this->modelObj->pk]);
444
+ $result=$this->modelObj->insert($_POST['wysija'][$this->model]);
445
+
446
+ if($this->msgOnSave){
447
+ if($result) $this->notice($this->messages['insert'][true]);
448
+ else{
449
+ $this->error($this->messages['insert'][false],true);
450
+ }
451
+ }
452
+
453
+
454
+ if($this->redirectAfterSave){
455
+ if(isset($this->modelObj->stay)){
456
+ $this->action='add';
457
+ $this->add($_POST['wysija'][$this->model]);
458
+ }else{
459
+ $this->action='main';
460
+ $this->redirect();
461
+ }
462
+ }
463
+
464
+ }
465
+
466
+ //now we redirect to the edit page with the data in it
467
+ return $result;
468
+ }
469
+
470
+ function bulk_delete($ids){
471
+ $this->requireSecurity();
472
+ foreach($ids as $id){
473
+
474
+ $conditions=$this->getPKVal($this->modelObj);
475
+ if(!$conditions) $this->error('Cannot obtain PKVal from GET or POST.');
476
+
477
+ $result=$this->modelObj->delete($conditions);
478
+ $this->modelObj->reset();
479
+ }
480
+ $this->notice(__('Elements deleted',WYSIJA));
481
+ $this->redirect();
482
+ }
483
+
484
+ function delete(){
485
+ // see if it's an update or an insert
486
+ $this->requireSecurity();
487
+ $conditions=$this->getPKVal($this->modelObj);
488
+ if(!$conditions) $this->error('Cannot obtain PKVal from GET or POST.');
489
+
490
+ $result=$this->modelObj->delete($conditions);
491
+ if($result){
492
+ $this->notice(__('Element has been deleted.',WYSIJA));
493
+ }
494
+
495
+
496
+ $this->modelObj->reset();
497
+ //now we redirect to the edit page with the data in it
498
+ $this->action='main';
499
+ $this->redirect();
500
+ }
501
+
502
+ function redirect($location=false){
503
+ global $wysi_location;
504
+ define('WYSIJA_REDIRECT',true);
505
+ if($location)
506
+ {
507
+ $url = parse_url($location);
508
+ if(!empty($url['query'])) {
509
+ $location .= '&';
510
+ } else {
511
+ $location .= '?';
512
+ }
513
+
514
+ $location .= 'redirect=1';
515
+ }
516
+ $wysi_location=$location;
517
+ }
518
+
519
+ function redirectProcess(){
520
+ global $wysi_location;
521
+
522
+ if(!$wysi_location) {
523
+ $wysi_location=$this->getDefaultUrl();
524
+ }
525
+ WYSIJA::redirect($wysi_location);
526
+
527
+ }
528
+
529
+ function popupReturn($viewFunc) {
530
+ return wp_iframe( array($this->viewObj,'popup_'.$viewFunc), $this->data);
531
+ }
532
+
533
+ function _addTab($defaulttab){
534
+ return $this->iframeTabs;
535
+ }
536
+
537
+ function popupContent(){
538
+ // remove auth check
539
+ remove_action('admin_enqueue_scripts', 'wp_auth_check_load');
540
+
541
+ // add popup css
542
+ wp_enqueue_style('custom_popup_css', WYSIJA_URL.'css/adminPopup.css', array(), WYSIJA::get_version(), 'screen');
543
+
544
+ global $viewMedia;
545
+ $viewMedia=$this->viewObj;
546
+ $_GET['type']=$_REQUEST['type']='image';
547
+
548
+ $config=WYSIJA::get('config','model');
549
+ $_GET['post_id']=$_REQUEST['post_id']=$config->getValue('confirm_email_link');
550
+ $post_id = isset($_GET['post_id'])? (int) $_GET['post_id'] : 0;
551
+ if(file_exists(ABSPATH.'wp-admin'.DS.'admin.php')) require_once(ABSPATH.'wp-admin'.DS.'admin.php');
552
+
553
+ @header('Content-Type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset'));
554
+
555
+ add_filter('media_upload_tabs', array($this,'_addTab'));
556
+
557
+ if(!isset($this->iframeTabs)) {
558
+
559
+
560
+ $this->iframeTabs=array(
561
+ 'special_new_wordp_upload'=>__('Upload',WYSIJA));
562
+
563
+ $this->iframeTabs['special_wysija_browse']=__('Newsletter Images',WYSIJA);
564
+ $this->iframeTabs['special_wordp_browse']=__('WordPress Posts\' Images',WYSIJA);
565
+
566
+ foreach($this->iframeTabs as $actionKey =>$actionTitle)
567
+ add_action('media_upload_'.$actionKey, array($this,$actionKey));
568
+ }else add_action('media_upload_standard', array($this,'popupReturn'));
569
+
570
+ // upload type: image, video, file, ..?
571
+ if ( isset($_GET['type']) )
572
+ $type = strval($_GET['type']);
573
+ else
574
+ $type = apply_filters('media_upload_default_type', 'file');
575
+
576
+ // tab: gallery, library, or type-specific
577
+ if ( isset($_GET['tab']) )
578
+ $tab = strval($_GET['tab']);
579
+ else
580
+ $tab ='special_wysija_browse';
581
+
582
+ $body_id = 'media-upload';
583
+ // let the action code decide how to handle the request
584
+ if ( $tab == 'type' || $tab == 'type_url' )
585
+ //i'm not so sure we need that line
586
+ do_action("media_upload_$type");
587
+ else{
588
+ if(strpos($tab, 'special_')!==false){
589
+ do_action("media_upload_$tab");
590
+ }else{
591
+ do_action('media_upload_standard',$tab);
592
+ }
593
+ }
594
+
595
+ exit;
596
+
597
+ }
598
+
599
+ function getDefaultUrl($filter=true){
600
+ $location="admin.php?page=".$_REQUEST['page'];
601
+
602
+ if($filter){
603
+ if(isset($_REQUEST['search']) && $_REQUEST['search']){
604
+ $location.='&search='.$_REQUEST['search'];
605
+ }
606
+
607
+ if(isset($_REQUEST['filter-list']) && $_REQUEST['filter-list']){
608
+ $location.='&filter-list='.$_REQUEST['filter-list'];
609
+ }
610
+
611
+ if(isset($_REQUEST['link_filter']) && $_REQUEST['link_filter']){
612
+ $location.='&link_filter='.$_REQUEST['link_filter'];
613
+ }
614
+
615
+ if(isset($_REQUEST['orderby']) && $_REQUEST['orderby']){
616
+ $location.='&orderby='.$_REQUEST['orderby'];
617
+ }
618
+
619
+ if(isset($_REQUEST['ordert']) && $_REQUEST['ordert']){
620
+ $location.='&ordert='.$_REQUEST['ordert'];
621
+ }
622
+ }
623
+
624
+ return $location;
625
+ }
626
+
627
+ /**
628
+ * to remove the conflicts in wysija's interfaces
629
+ * @param boolean $themes
630
+ */
631
+ function get_conflictive_plugins($themes=false){
632
+
633
+ /**
634
+ * List of all the conflictive extensions which invite themselves on our interfaces and break some of our js:
635
+ * tribulant newsletter
636
+ */
637
+ $conflictivePlugins = array(
638
+ 'tribulant-wp-mailinglist' => array(
639
+ 'file' => 'wp-mailinglist/wp-mailinglist.php',
640
+ 'version' => '3.8.7',
641
+ 'clean' => array(
642
+ 'admin_head' => array(
643
+ '10' => array(
644
+ 'objects' => array('wpMail')
645
+ )
646
+ )
647
+ )
648
+ ),
649
+ 'wp-events' => array(
650
+ 'file' => 'wp-events/wp-events.php',
651
+ 'version' => '',
652
+ 'clean' => array(
653
+ 'admin_head' => array(
654
+ '10' => array(
655
+ 'function' => 'events_editor_admin_head'
656
+ )
657
+ )
658
+ )
659
+ ),
660
+ 'email-users' => array(
661
+ 'file' => 'email-users/email-users.php',
662
+ 'version' => '',
663
+ 'clean' => array(
664
+ 'admin_head' => array(
665
+ '10' => array(
666
+ 'function' => 'editor_admin_head'
667
+ )
668
+ )
669
+ )
670
+ ),
671
+ 'acf' => array(
672
+ 'file' => 'advanced-custom-fields/acf.php',
673
+ 'version' => '3.1.7',
674
+ 'clean' => array(
675
+ 'init' => array(
676
+ '10' => array(
677
+ 'objects' => array('Acf')
678
+ )
679
+ )
680
+ )
681
+ ),
682
+ 'wptofacebook' => array(
683
+ 'file' => 'wptofacebook/index.php',
684
+ 'version' => '1.2.3',
685
+ 'clean' => array(
686
+ 'admin_head' => array(
687
+ '10' => array(
688
+ 'function' => 'WpToFb::wptofb_editor_admin_head'
689
+ )
690
+ )
691
+ )
692
+ ),
693
+ 'mindvalley-pagemash' => array(
694
+ 'file' => 'mindvalley-pagemash/pagemash.php',
695
+ 'version' => '1.1',
696
+ 'clean' => array(
697
+ 'admin_print_scripts' => array(
698
+ '10' => array(
699
+ 'function' => 'pageMash_head'
700
+ )
701
+ )
702
+ )
703
+ ),
704
+ 'wp-polls' => array(
705
+ 'file' => 'wp-polls/wp-polls.php',
706
+ 'version' => '2.63',
707
+ 'clean' => array(
708
+ 'wp_enqueue_scripts' => array(
709
+ '10' => array(
710
+ 'function' => 'poll_scripts'
711
+ )
712
+ )
713
+ )
714
+ ),
715
+ 'wp_rokajaxsearch' => array(
716
+ 'file' => 'wp_rokajaxsearch/rokajaxsearch.php',
717
+ 'version' => '',
718
+ 'clean' => array(
719
+ 'init' => array(
720
+ '-50' => array(
721
+ 'function' => 'rokajaxsearch_mootools_init'
722
+ )
723
+ )
724
+ )
725
+ ),
726
+ 'wp_rokstories' => array(
727
+ 'file' => 'wp_rokstories/rokstories.php',
728
+ 'version' => '',
729
+ 'clean' => array(
730
+ 'init' => array(
731
+ '-50' => array(
732
+ 'function' => 'rokstories_mootools_init'
733
+ )
734
+ )
735
+ )
736
+ ),
737
+ 'simple-links' => array(
738
+ 'file' => 'simple-links/simple-links.php',
739
+ 'version' => '1.5',
740
+ 'clean' => array(
741
+ 'admin_print_scripts' => array(
742
+ '10' => array(
743
+ 'objects' => array('simple_links_admin')
744
+ )
745
+ )
746
+ )
747
+ )
748
+ );
749
+
750
+ $conflictiveThemes = array(
751
+ 'smallbiz' => array(
752
+ 'clean' => array(
753
+ 'admin_head' => array(
754
+ '10' => array(
755
+ 'function' => 'smallbiz_on_admin_head'
756
+ )
757
+ )
758
+ )
759
+ ),
760
+ 'balance' => array(
761
+ 'clean' => array(
762
+ 'admin_enqueue_scripts' => array(
763
+ '10' => array(
764
+ 'functions' => array('al_admin_scripts', 'al_adminpanel_scripts', 'al_pricing_tables_scripts')
765
+ )
766
+ ),
767
+ 'admin_head' => array(
768
+ '10' => array(
769
+ 'function' => 'al_admin_head'
770
+ )
771
+ )
772
+ )
773
+ )
774
+ );
775
+
776
+ if($themes) return $conflictiveThemes;
777
+ return $conflictivePlugins;
778
+ }
779
+ }
trunk/controllers/back/campaigns.php ADDED
@@ -0,0 +1,2665 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ global $viewMedia;
4
+ defined('WYSIJA') or die('Restricted access');
5
+
6
+ class WYSIJA_control_back_campaigns extends WYSIJA_control_back {
7
+
8
+ var $model = 'campaign';
9
+ var $view = 'campaigns';
10
+ var $list_columns = array('campaign_id', 'name', 'description');
11
+ var $searchable = array('name', 'subject');
12
+ var $filters = array();
13
+ var $base_url = 'admin.php';
14
+
15
+ function __construct(){
16
+ global $wpdb;
17
+ parent::__construct();
18
+ $this->wpdb = $wpdb;
19
+ }
20
+
21
+ private function _wysija_subaction() {
22
+ if (isset($_REQUEST['subaction'])) {
23
+ if ($_REQUEST['subaction'] === 'delete') {
24
+ $this->_verify_nonce_subaction();
25
+ if (isset($_REQUEST['imgid']) && (int) $_REQUEST['imgid'] > 0) {
26
+ // delete the image with id imgid
27
+ $res = wp_delete_attachment((int) $_REQUEST['imgid'], true);
28
+ if ($res) {
29
+ $this->notice(__('Image has been deleted.', WYSIJA));
30
+ }
31
+ }
32
+ }
33
+ }
34
+ return true;
35
+ }
36
+
37
+ private function _verify_nonce_subaction(){
38
+ if(!wp_verify_nonce($_REQUEST['_wpnonce'], $_REQUEST['page'].'-action_sub_delete_image') ){
39
+ wp_die("<h2>" . __('Security failure during request') . "</h2>", __("Security Problem"), array(
40
+ 'response' => 403,
41
+ 'back_link' => false
42
+ ));
43
+ }
44
+ }
45
+
46
+ private function _getLists($enabled = true, $count = false, $simple_query = false) {
47
+ $model_list = WYSIJA::get('list', 'model');
48
+ //get lists which have users and are enabled */
49
+ if ($enabled){
50
+ $sql_enabled_condition = ' is_enabled>0 and';
51
+ }else{
52
+ $sql_enabled_condition = '';
53
+ }
54
+
55
+ $extra_sql = '';
56
+ if (!$simple_query){
57
+ $extra_sql = 'WHERE list_id in (SELECT distinct(list_id) from [wysija]user_list )';
58
+ }
59
+
60
+ $query = 'SELECT * FROM [wysija]list ' . $extra_sql;
61
+ $listres = $model_list->query('get_res', $query);
62
+
63
+ if ($count) {
64
+ $model_config = WYSIJA::get('config', 'model');
65
+ $condition = '>=';
66
+ if ($model_config->getValue('confirm_dbleoptin'))
67
+ $condition = '>';
68
+ $qry1 = "SELECT count(distinct A.user_id) as nbsub,A.list_id FROM `[wysija]user_list` as A LEFT JOIN `[wysija]user` as B on A.user_id=B.user_id WHERE B.status $condition 0 and A.unsub_date=0 GROUP BY list_id";
69
+
70
+ $total = $model_list->getResults($qry1);
71
+
72
+ foreach ($total as $tot) {
73
+ foreach ($listres as $key => $res) {
74
+ if ($tot['list_id'] == $res['list_id'])
75
+ $listres[$key]['count'] = $tot['nbsub'];
76
+ }
77
+ }
78
+ }
79
+ foreach ($listres as $key => $res) {
80
+ if (!isset($res['count']))
81
+ $listres[$key]['count'] = 0;
82
+ }
83
+ return $listres;
84
+ }
85
+
86
+ /**
87
+ * Welcome page first time install
88
+ * @return boolean
89
+ */
90
+ function welcome_new() {
91
+ $this->title = $this->viewObj->title = __('Welcome Page!', WYSIJA);
92
+ $this->jsTrans['instalwjp'] = __('Installing MailPoet Newsletter Premium plugin', WYSIJA);
93
+ $helper_readme = WYSIJA::get('readme', 'helper');
94
+ $helper_readme->scan();
95
+ $this->data = array();
96
+ $this->data['abouttext'] = __('A Brand New MailPoet. Let the Fun Begin.', WYSIJA);
97
+
98
+ $model_config = WYSIJA::get('config', 'model');
99
+ $is_multisite = is_multisite();
100
+ $is_network_admin = WYSIJA::current_user_can('manage_network');
101
+ if ($is_multisite && $is_network_admin) {
102
+ $model_config->save(array('ms_wysija_whats_new' => WYSIJA::get_version()));
103
+ } else {
104
+ $model_config->save(array('wysija_whats_new' => WYSIJA::get_version()));
105
+ }
106
+
107
+ //add a new language code with a new video
108
+ $video_language=array();
109
+ $video_language['en_EN'] = '<iframe src="//player.vimeo.com/video/130224536" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
110
+
111
+ $wp_lang = get_locale();
112
+ if (!empty($wp_lang) && isset($video_language[$wp_lang])) {
113
+ $welcome_video_link = $video_language[$wp_lang];
114
+ } else {
115
+ $welcome_video_link = $video_language['en_EN'];
116
+ }
117
+
118
+ $this->data['sections'][] = array(
119
+ 'title' => __("We're changing. So should you.", WYSIJA),
120
+ 'format' => 'title-content',
121
+ 'paragraphs' => array('
122
+ <iframe src="https://player.vimeo.com/video/223581490" width="640" height="360" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
123
+ <ul style="list-style: disc inside none">
124
+ <li>'.$this->viewObj->replace_link_shortcode(__("[link]Read the FAQ[/link] on what's going to happen to this current version of MailPoet (version 2)", WYSIJA), 'http://www.mailpoet.com/faq-mailpoet-version-2/').'</li>
125
+ <li>'.__('MailPoet version 3 is completely rewritten', WYSIJA).'</li>
126
+ <li>'.__('New email designer', WYSIJA).'</li>
127
+ <li>'.__('Responsive templates', WYSIJA).'</li>
128
+ <li>'.__('Fast user interface', WYSIJA).'</li>
129
+ <li>'.__('Same easy configuration', WYSIJA).'</li>
130
+ <li>'.__('Weekly releases', WYSIJA).'</li>
131
+ <li>'.__('Version 2 and 3 can live side by side', WYSIJA).'</li>
132
+ <li><a href="http://beta.docs.mailpoet.com/article/189-comparison-of-mailpoet-2-and-3?utm_source=mp2&amp;utm_medium=welcomeupdate&amp;utm_campaign=comparison">'.__('Comparison table of both versions', WYSIJA).'</a></li>
133
+ <li>'.$this->viewObj->replace_link_shortcode(__('Try [link]the online demo[/link]', WYSIJA), 'http://demo3.mailpoet.com/launch/?utm_source=mp2&amp;utm_medium=updatewelcome&amp;utm_campaign=demo3').'</li>
134
+ <li>'.__('Multisite works, but not officially supported. Please test MailPoet 3 on a staging server', WYSIJA).'</li>
135
+ <li>'.__('Right-to-left languages works, but can be improved', WYSIJA).'</li>
136
+ <li>'.
137
+ $this->viewObj->replace_link_shortcode(
138
+ $this->viewObj->replace_link_shortcode(
139
+ __('Get in touch in the [link]forums[/link] for further help. Customers can reach via our [link]support page[/link]', WYSIJA),
140
+ 'https://wordpress.org/support/plugin/wysija-newsletters'
141
+ ),
142
+ 'https://www.mailpoet.com/support/'
143
+ ).'</li>
144
+ </ul>
145
+ <br>
146
+ <h3 style="font-size: 25px; color: #626262; font-weight: 600;"><strong>'.__('Comes with a 1-click migration tool:', WYSIJA).'</strong></h3>
147
+ <ul style="list-style: disc inside none">
148
+ <li>'.__('Your subscribers, lists, forms and settings will be migrated', WYSIJA).'</li>
149
+ <li>'.__('Automatic emails will not be migrated', WYSIJA).'</li>
150
+ <li>'.__('Archive of sent emails will not be migrated', WYSIJA).'</li>
151
+ <li>'.__('Your statistics will not be migrated', WYSIJA).'</li>
152
+ </ul>
153
+ <a class="button-primary" href="plugin-install.php?s=mailpoet&tab=search&type=author">'.__('Download MailPoet 3 now', WYSIJA).'</a>
154
+ ')
155
+ );
156
+
157
+ $this->viewObj->skip_header = true;
158
+
159
+ return true;
160
+ }
161
+
162
+ /**
163
+ * Welcome page for updaters
164
+ * @return boolean
165
+ */
166
+ function whats_new() {
167
+
168
+ $this->title = $this->viewObj->title = __('What\'s new?', WYSIJA);
169
+ $this->jsTrans['instalwjp'] = __('Installing MailPoet Newsletter Premium plugin', WYSIJA);
170
+ wp_enqueue_style('wysija-admin-css-premium', WYSIJA_URL.'css/admin-premium.css',array(),WYSIJA::get_version());
171
+
172
+ $this->viewObj->skip_header = true;
173
+ return true;
174
+ }
175
+
176
+
177
+
178
+ /* START prem check hook */
179
+
180
+ // when curl or any php remote function not available mailpoet.com returns lcheck to that function
181
+ function licok() {
182
+ parent::__construct();
183
+ $dt = get_option('wysijey');
184
+
185
+ if (isset($_REQUEST['xtz']) && $dt === $_REQUEST['xtz']) {
186
+ $dataconf = array(
187
+ 'premium_key' => base64_encode(get_option('home') . time()),
188
+ 'premium_val' => time(),
189
+ 'premium_expire_at' => (int)$_REQUEST['expire_at']
190
+ );
191
+ $this->notice(__('Premium version is valid for your site.', WYSIJA));
192
+ } else {
193
+ $dataconf = array('premium_key' => '', 'premium_val' => '');
194
+ if(!empty($_REQUEST['expire_at'])){
195
+ $dataconf['premium_expire_at'] = (int)$_REQUEST['expire_at'];
196
+ }else{
197
+ $url_premium = 'http://www.mailpoet.com/checkout/?wysijadomain=' . $dt . '&nc=1&utm_source=wpadmin&utm_campaign=error_licence_activation';
198
+ $this->error(str_replace(array('[link]', '[/link]'), array('<a href="' . $url_premium . '" target="_blank">', '</a>'), __('Premium licence does not exist for your site. Purchase it [link]here[/link].', WYSIJA)), 1);
199
+ }
200
+
201
+ }
202
+ WYSIJA::update_option('wysicheck', false);
203
+ $modelConf = WYSIJA::get('config', 'model');
204
+ $modelConf->save($dataconf);
205
+
206
+ $this->redirect('admin.php?page=wysija_config#tab-premium');
207
+ }
208
+
209
+ /* END prem check hook */
210
+
211
+ function validateLic() {
212
+ $helpLic = WYSIJA::get('licence', 'helper');
213
+ $res = $helpLic->check();
214
+
215
+ $this->redirect();
216
+ }
217
+
218
+ /**
219
+ * this function is triggered when sending manually the emails with the "Don't wait and send right now" button
220
+ * @param type $dataPost
221
+ */
222
+ function manual_send($dataPost = false) {
223
+ $this->requireSecurity();
224
+ $modelQ = WYSIJA::get('queue', 'model');
225
+ $config = WYSIJA::get('config', 'model');
226
+ if ((int) $config->getValue('total_subscribers') < 2000) {
227
+ if ($modelQ->count() > 0) {
228
+ $helperQ = WYSIJA::get('queue', 'helper');
229
+ $emailid = false;
230
+ if ($_REQUEST['emailid']) {
231
+ $emailid = (int)$_REQUEST['emailid'];
232
+ }
233
+ $helperQ->process($emailid);
234
+ } else {
235
+ echo '<strong style="font-family: Arial; font-weight: bold; font-size: 12px;">' . __('Queue is empty!', WYSIJA) . '</strong>';
236
+ }
237
+ exit;
238
+ } else {
239
+ //deprecated
240
+ do_action('wysija_send_test_editor');
241
+
242
+ do_action('wysija_manual_send');
243
+ }
244
+
245
+ exit;
246
+ }
247
+
248
+ /**
249
+ * test the bounce handling maybe this should move somewhere else like config controller
250
+ * @return boolean
251
+ */
252
+ function test_bounce() {
253
+ // bounce handling
254
+ $helper_bounce = WYSIJA::get('bounce', 'helper');
255
+
256
+ // in a multisite case we process first the bounce recording into the bounce table
257
+ if (is_multisite()) {
258
+ $helper_bounce->record_bounce_ms();
259
+
260
+ // then we take actions from what has been returned by the bounce
261
+ $helper_bounce->process_bounce_ms();
262
+ } else {
263
+ $helper_bounce->process_bounce();
264
+ }
265
+ exit;
266
+ }
267
+
268
+ function add($dataPost = false) {
269
+ $this->title = sprintf(__('Step %1$s', WYSIJA), 1);
270
+ $this->js[] = 'wysija-validator';
271
+
272
+ $this->js[] = 'wysija-edit-autonl';
273
+ $this->js['admin-campaigns-edit'] = 'admin-campaigns-edit';
274
+ $this->jsTrans['descauto'] = str_replace(array('[newsletter:number]', '[newsletter:total]', '[newsletter:post_title]'), array('<b>[newsletter:number]</b>', '<b>[newsletter:total]</b>', '<b>[newsletter:post_title]</b>'), __('Insert [newsletter:total] to show number of posts, [newsletter:post_title] to show the latest post\'s title & [newsletter:number] to display the issue number.', WYSIJA));
275
+ $this->jsTrans['descstandard'] = __('The first thing your subscribers see. Be creative and increase your open rate!', WYSIJA);
276
+ $this->immediateWarning();
277
+ $this->viewObj->title = __('First step: main details', WYSIJA);
278
+ $this->viewShow = 'add';
279
+ $this->data = array();
280
+ $this->data['campaign'] = array('name' => '', 'description' => '');
281
+ $modelConfig = WYSIJA::get('config', 'model');
282
+ $this->data['email'] = array('subject' => '', 'from_email' => $modelConfig->getValue('from_email'), 'from_name' => $modelConfig->getValue('from_name'));
283
+ $this->data['lists'] = $this->_getLists(false, true, true);
284
+
285
+ $this->dataAutoNl();
286
+ $this->jsLoc['admin-campaigns-edit']['autofields'] = $this->data['autonl']['fields'];
287
+ }
288
+
289
+ /**
290
+ * get the fields and fields value necessary when dealing with automatic newsletters
291
+ */
292
+ function dataAutoNl() {
293
+ $dataFrequencyNoImmediate = $dataFrequency = array('daily' => __('once a day at...', WYSIJA),
294
+ 'weekly' => __('weekly on...', WYSIJA),
295
+ 'monthly' => __('monthly on the...', WYSIJA),
296
+ 'monthlyevery' => __('monthly every...', WYSIJA),
297
+ 'immediate' => __('immediately.', WYSIJA));
298
+
299
+ unset($dataFrequencyNoImmediate['immediate']);
300
+
301
+ $times = array();
302
+ $time = strtotime('00:00:00');
303
+ $toolboxH = WYSIJA::get('toolbox', 'helper');
304
+ $times['00:00:00'] = $toolboxH->localtime($time);
305
+
306
+ for ($i = 1; $i < 24; $i++) {
307
+ $time = strtotime('+ 1hour', $time);
308
+ $key = date('H:i:s', $time);
309
+ $times[$key] = $toolboxH->localtime($time);
310
+ }
311
+
312
+ $daysvalues = $toolboxH->getday();
313
+
314
+ $numberweeks = $toolboxH->getweeksnumber();
315
+ $daynumbers = $toolboxH->getdaynumber();
316
+
317
+
318
+ $dataLists = array();
319
+
320
+ foreach ($this->data['lists'] as $datal) {
321
+ if ($datal['is_enabled'])
322
+ $dataLists[$datal['list_id']] = $datal['name'];
323
+ }
324
+
325
+ // Get all available roles
326
+ $wptoolsH = WYSIJA::get('wp_tools', 'helper');
327
+ $roles = $wptoolsH->wp_get_all_roles();
328
+ $available_roles = array('any' => __('in any WordPress role', WYSIJA));
329
+ foreach ($roles as $role => $name) {
330
+ $available_roles[$role] = $name;
331
+ }
332
+
333
+ $this->data['autonl']['fields'] = array(
334
+ 'event' => array(
335
+ 'values' => array(
336
+ 'new-articles' => __('When there\'s new content...', WYSIJA),
337
+ 'subs-2-nl' => __('When someone subscribes to the list...', WYSIJA),
338
+ 'new-user' => __('When a new WordPress user is added to your site...', WYSIJA),
339
+ ),
340
+ 'valueshow' => array(
341
+ 'new-articles' => array('when-article'),
342
+ 'subs-2-nl' => array('subscribetolist', 'numberafter', 'numberofwhat', 'unique_send'),
343
+ 'new-user' => array('roles', 'numberafter', 'numberofwhat', 'unique_send'),
344
+ ),
345
+ 'style' => 'width:300px;'
346
+ ),
347
+ 'when-article' => array(
348
+ 'values' => $dataFrequency,
349
+ 'valueshow' => array(
350
+ 'daily' => array('time'),
351
+ 'weekly' => array('dayname', 'time'),
352
+ 'monthly' => array('daynumber', 'time'),
353
+ 'monthlyevery' => array('dayevery', 'dayname', 'time'),
354
+ )
355
+ ),
356
+ 'subscribetolist' => array(
357
+ 'values' => $dataLists,
358
+ 'style' => 'width:300px;'
359
+ ),
360
+ 'roles' => array(
361
+ 'values' => $available_roles
362
+ ),
363
+ 'numberafter' => array(
364
+ 'type' => 'input',
365
+ 'style' => 'width:35px;',
366
+ 'class' => 'validate[required,custom[integer],min[1]]',
367
+ ),
368
+ 'numberofwhat' => array(
369
+ 'values' => array(
370
+ 'immediate' => __('immediately.', WYSIJA),
371
+ 'hours' => __('hour(s) after.', WYSIJA),
372
+ 'days' => __('day(s) after.', WYSIJA),
373
+ 'weeks' => __('week(s) after.', WYSIJA)
374
+ ),
375
+ 'valuesunit' => array(
376
+ 'immediate' => __('immediately', WYSIJA),
377
+ 'hours' => __('hour(s)', WYSIJA),
378
+ 'days' => __('day(s)', WYSIJA),
379
+ 'weeks' => __('week(s)', WYSIJA)
380
+ ),
381
+ ),
382
+ 'dayevery' => array(
383
+ 'values' => $numberweeks,
384
+ ),
385
+ 'dayname' => array(
386
+ 'values' => $daysvalues,
387
+ ),
388
+ 'daynumber' => array(
389
+ 'values' => $daynumbers,
390
+ ),
391
+ 'time' => array(
392
+ 'values' => $times,
393
+ ),
394
+ /* 'unique_send'=>array(
395
+ 'label_before'=>__('Send this email only once.',WYSIJA),
396
+ 'type'=>'checkbox'
397
+ ), */
398
+ );
399
+ $helpersEvent = WYSIJA::get('autonews', 'helper');
400
+ $extraEvents = $helpersEvent->events();
401
+
402
+ /* if there are plugin to add autonewsletter event they are adding their customized field over here */
403
+ if ($extraEvents) {
404
+ foreach ($extraEvents as $k => $v) {
405
+
406
+ $this->data['autonl']['fields']['event']['values'][$k] = $v['title'];
407
+ foreach ($v['fields'] as $fieldCKEY => $fieldCVAL) {
408
+ if (isset($this->data['autonl']['fields'][$fieldCKEY]))
409
+ continue;
410
+ }
411
+ $this->data['autonl']['fields']['event']['valueshow'][$k] = array_keys($v['fields']);
412
+ }
413
+ }
414
+ }
415
+
416
+
417
+ function edit($dataPost = false) {
418
+ if (!$this->_checkEmailExists($_REQUEST['id']))
419
+ return;
420
+ $this->add();
421
+
422
+ $modelEmail = WYSIJA::get('email', 'model');
423
+
424
+ $this->data['email'] = $modelEmail->getOne(false, array('email_id' => $_REQUEST['id']));
425
+
426
+ if ($this->data['email']['status'] > 0) {
427
+ $this->redirect();
428
+ }
429
+ $this->title = sprintf(__('Step %1$s', WYSIJA), 1) . ' | ' . $this->data['email']['subject'];
430
+ $modelCamp = WYSIJA::get('campaign', 'model');
431
+ $this->data['campaign'] = $modelCamp->getOne(false, array('campaign_id' => $this->data['email']['campaign_id']));
432
+
433
+ $modelCL = WYSIJA::get('campaign_list', 'model');
434
+ $this->data['campaign_list'] = $modelCL->get(false, array('campaign_id' => $this->data['email']['campaign_id']));
435
+ }
436
+
437
+ function editTemplate() {
438
+ // make sure the editor content is not cached
439
+ header('Cache-Control: no-cache, max-age=0, must-revalidate, no-store'); // HTTP/1.1
440
+ header('Expires: Fri, 9 Mar 1984 00:00:00 GMT');
441
+
442
+ if (!$this->_checkEmailExists($_REQUEST['id']))
443
+ return;
444
+ $this->viewShow = 'editTemplate';
445
+
446
+ wp_enqueue_style('thickbox');
447
+
448
+ $wjEngine = WYSIJA::get('wj_engine', 'helper');
449
+ /* WJ editor translations */
450
+ $this->jsTrans = array_merge($this->jsTrans, $wjEngine->getTranslations(), $wjEngine->getApplicationData());
451
+
452
+ $this->jsTrans['savingnl'] = __('Saving newsletter...', WYSIJA);
453
+ $this->jsTrans['errorsavingnl'] = __('Error Saving newsletter...', WYSIJA);
454
+ $this->jsTrans['savednl'] = __('Newsletter has been saved.', WYSIJA);
455
+ $this->jsTrans['previewemail'] = __('Sending preview...', WYSIJA);
456
+ $this->jsTrans['spamtestresult'] = __('Spam test results', WYSIJA);
457
+
458
+ /* WJ editor JS */
459
+ $this->js[] = 'wysija-editor';
460
+ $this->js[] = 'wysija-admin-ajax-proto';
461
+ $this->js[] = 'wysija-admin-ajax';
462
+ $this->js[] = 'wysija-base-script-64';
463
+ $this->js[] = 'media-upload';
464
+ $this->js['admin-campaigns-editDetails'] = 'admin-campaigns-editDetails';
465
+ $modelEmail = WYSIJA::get('email', 'model');
466
+ $this->data = array();
467
+ $this->data['email'] = $modelEmail->getOne(false, array('email_id' => $_REQUEST['id']));
468
+
469
+ $this->checkIsEditable();
470
+
471
+ $this->viewObj->title = sprintf(__('Second step: "%1$s"', WYSIJA), $this->data['email']['subject']);
472
+ $this->title = sprintf(__('Step %1$s', WYSIJA), 2) . " | " . $this->data['email']['subject'];
473
+
474
+ // check if html source is enabled in the config (this will add the "html source" button in tinymce)
475
+ $model_config = WYSIJA::get('config', 'model');
476
+ $this->jsTrans['html_source_enabled'] = (int) $model_config->getValue('html_source');
477
+ }
478
+
479
+ function checkIsEditable() {
480
+ if (
481
+ !($this->data['email'] == 2 || isset($this->data['email']['params']['schedule']['isscheduled'])) && $this->data['email']['status'] > 0
482
+ ) {
483
+ $this->redirect();
484
+ }
485
+ }
486
+
487
+ function pause() {
488
+ /* pause the campaign entry */
489
+ $this->requireSecurity();
490
+ if (isset($_REQUEST['id']) && $_REQUEST['id']) {
491
+ $modelEmail = WYSIJA::get('email', 'model');
492
+ $myemail = $modelEmail->getOne(false, array('email_id' => $_REQUEST['id']));
493
+ $modelEmail->reset();
494
+ $modelEmail->columns['modified_at']['autoup'] = 1;
495
+ $modelEmail->update(array('status' => -1), array('email_id' => $_REQUEST['id']));
496
+
497
+ if ($myemail['type'] == 2) {
498
+ return $this->redirect('admin.php?page=wysija_campaigns&id=' . $myemail['email_id'] . '&action=edit');
499
+ } else {
500
+ $this->notice(__('Sending is now paused.', WYSIJA));
501
+ }
502
+ }
503
+
504
+ $this->redirect();
505
+ }
506
+
507
+ function resume() {
508
+ /* pause the campaign entry */
509
+ $this->requireSecurity();
510
+ if (isset($_REQUEST['id']) && $_REQUEST['id']) {
511
+ $modelEmail = WYSIJA::get('email', 'model');
512
+ $modelEmail->columns['modified_at']['autoup'] = 1;
513
+ $modelEmail->update(array('status' => 99), array('email_id' => $_REQUEST['id']));
514
+ $this->notice(__('Sending has resumed.', WYSIJA));
515
+ }
516
+
517
+ $this->redirect();
518
+ }
519
+
520
+ function duplicate() {
521
+ /* 1 - copy the campaign entry */
522
+ $this->requireSecurity();
523
+ $model = WYSIJA::get( 'campaign', 'model' );
524
+ $query = 'INSERT INTO `[wysija]campaign` (`name`,`description`)
525
+ SELECT concat("' . $this->wpdb->_real_escape( __( 'Copy of ', WYSIJA ) ) . '",`name`),`description` FROM [wysija]campaign
526
+ WHERE campaign_id=' . (int) $_REQUEST['id'];
527
+ $campaignid = $model->query( $query );
528
+
529
+ /* 2 - copy the email entry */
530
+ $query = 'INSERT INTO `[wysija]email` (`campaign_id`,`subject`,`body`,`type`,`params`,`wj_data`,`wj_styles`,`from_email`,`from_name`,`replyto_email`,`replyto_name`,`attachments`,`status`,`created_at`,`modified_at`)
531
+ SELECT ' . $campaignid . ', concat("' . $this->wpdb->_real_escape( __( 'Copy of ', WYSIJA ) ) . '",`subject`),`body`,`type`,`params`,`wj_data`,`wj_styles`,`from_email`,`from_name`,`replyto_email`,`replyto_name`,`attachments`,0,' . time() . ',' . time() . ' FROM [wysija]email
532
+ WHERE email_id=' . (int) $_REQUEST['email_id'];
533
+ $emailid = $model->query( $query );
534
+
535
+ //let's reset the count of total childs for auto newsletter
536
+ $mEmail = WYSIJA::get( 'email', 'model' );
537
+ $emailData = $mEmail->getOne( false, array( 'email_id' => $emailid ) );
538
+
539
+ if ( $emailData['type'] == 1 ){
540
+ $params = $emailData['params'];
541
+
542
+ if ( isset( $params['schedule'] ) ){
543
+ $date_scheduled = strtotime( $params['schedule']['day'] . ' ' . $params['schedule']['time'] );
544
+
545
+ if ( $date_scheduled === false || $date_scheduled < time() ){
546
+ unset( $params['schedule'] );
547
+ }
548
+ }
549
+ $mEmail->update( array( 'params' => $params ), array( 'email_id' => $emailid ) );
550
+ } elseif ( $emailData['type'] == 2 ) {
551
+ $paramsReseted = $emailData['params'];
552
+ if ( isset( $paramsReseted['autonl']['total_child'] ) ){
553
+ $paramsReseted['autonl']['total_child'] = 0;
554
+ }
555
+
556
+ if ( isset( $paramsReseted['autonl']['nextSend'] ) ){
557
+ $paramsReseted['autonl']['nextSend'] = 0;
558
+ }
559
+
560
+ if ( isset( $paramsReseted['autonl']['firstSend'] ) ){
561
+ unset( $paramsReseted['autonl']['firstSend'] );
562
+ }
563
+
564
+ if ( isset( $paramsReseted['autonl']['lastSend'] ) ){
565
+ unset( $paramsReseted['autonl']['lastSend'] );
566
+ }
567
+
568
+ if ( isset( $paramsReseted['autonl']['articles']['ids'] ) ){
569
+ unset( $paramsReseted['autonl']['articles']['ids'] );
570
+ }
571
+
572
+ $mEmail->update( array( 'params' => $paramsReseted ), array( 'email_id' => $emailid ) );
573
+ }
574
+
575
+ /* 3 - copy the campaign_list entry */
576
+ $query = "INSERT INTO `[wysija]campaign_list` (`campaign_id`,`list_id`,`filter`)
577
+ SELECT $campaignid,`list_id`,`filter` FROM [wysija]campaign_list
578
+ WHERE campaign_id=" . (int) $_REQUEST['id'];
579
+ $model->query( $query );
580
+
581
+ $this->notice( __( 'The newsletter has been duplicated.', WYSIJA ) );
582
+
583
+ $this->redirect( 'admin.php?page=wysija_campaigns&id=' . $emailid . '&action=edit' );
584
+ }
585
+
586
+ function immediateWarning() {
587
+ $model_config = WYSIJA::get('config', 'model');
588
+ $is_multisite = is_multisite();
589
+
590
+ //$is_multisite=true;//PROD comment that line
591
+ if ($is_multisite && $model_config->getValue('sending_method') == 'network') {
592
+ $sending_emails_each = $model_config->getValue('ms_sending_emails_each');
593
+ $number = $model_config->getValue('ms_sending_emails_number');
594
+ } else {
595
+ $sending_emails_each = $model_config->getValue('sending_emails_each');
596
+ $number = $model_config->getValue('sending_emails_number');
597
+ }
598
+
599
+ $formsHelp = WYSIJA::get('forms', 'helper');
600
+
601
+ $timespan = $formsHelp->eachValuesSec[$sending_emails_each];
602
+ $helper_toolbox = WYSIJA::get('toolbox', 'helper');
603
+
604
+ $this->immediatewarning = str_replace(
605
+ array('[link]', '[/link]', '[settings]'), array('<a href="#">', '</a>', sprintf(__('%1$s emails every %2$s', WYSIJA), $number, trim($helper_toolbox->duration_string($timespan, true)))), __('Your sending settings ([settings]) can\'t send that quickly to [number] subscribers. Expect delivery delays. [link]Read more[/link]', WYSIJA));
606
+ $this->viewObj->immediatewarning = '<span class="warning-msg" id="immediatewarning">' . $this->immediatewarning . '</span>';
607
+
608
+ $this->jsTrans['immediatewarning'] = $this->immediatewarning;
609
+
610
+ //how many emails can be sent in 12 hours
611
+ //if the frequency is less than 12hours
612
+ if ($timespan < 43200) {
613
+ $ratio = floor(43200 / $timespan);
614
+ $this->jsTrans['possibleemails'] = $ratio * $number;
615
+ } else {
616
+ if ($timespan == 43200) {
617
+ $this->jsTrans['possibleemails'] = $number;
618
+ } else {
619
+ $ratio = floor($timespan / 43200);
620
+ $this->jsTrans['possibleemails'] = $number / $ratio;
621
+ }
622
+ }
623
+ }
624
+
625
+ function editDetails() {
626
+ if (!$this->_checkEmailExists($_REQUEST['id']))
627
+ return;
628
+
629
+ $this->viewObj->title = __('Final step: last details', WYSIJA);
630
+ $this->viewShow = 'editDetails';
631
+ $this->js[] = 'wysija-validator';
632
+ $this->jsTrans['previewemail'] = __('Sending preview...', WYSIJA);
633
+ $this->jsTrans['pickadate'] = __('Pick a date', WYSIJA);
634
+ $this->jsTrans['saveclose'] = __('Save & close', WYSIJA);
635
+ $this->jsTrans['sendlater'] = __('Send later', WYSIJA);
636
+
637
+ $this->jsTrans['schedule'] = __('Schedule', WYSIJA);
638
+
639
+ $this->jsTrans['emailCheck'] = WJ_Utils::get_tip_data();
640
+
641
+
642
+ $this->js[] = 'jquery-ui-datepicker';
643
+ $this->js[] = 'wysija-tooltip';
644
+
645
+ $model_list = WYSIJA::get('list', 'model');
646
+ $model_list->limitON = false;
647
+ $this->data = array();
648
+ $this->data['lists'] = $this->_getLists(false, true, true);
649
+
650
+ $model_email = WYSIJA::get('email', 'model');
651
+ $this->data['email'] = $model_email->getOne(false, array('email_id' => $_REQUEST['id']));
652
+
653
+ // The first newsletter, we don't have replyto_email and replyto_name
654
+ if (empty($this->data['email']['replyto_email']) || empty($this->data['email']['replyto_name'])) {
655
+ $current_user = wp_get_current_user();
656
+ $this->data['email']['replyto_email'] = $current_user->data->user_email;
657
+ $this->data['email']['replyto_name'] = $current_user->data->display_name;
658
+ }
659
+
660
+ if ((int) $this->data['email']['type'] == 2) {
661
+ $this->js['wysija-edit-autonl'] = 'wysija-edit-autonl';
662
+ $this->jsTrans['autonl'] = true;
663
+ $this->immediateWarning();
664
+ $this->jsTrans['send'] = __('Activate now', WYSIJA);
665
+ } else {
666
+ $this->jsTrans['autonl'] = true;
667
+ $this->viewObj->immediatewarning = '';
668
+ $this->jsTrans['send'] = __('Send', WYSIJA);
669
+ }
670
+
671
+ if ((int) $this->data['email']['type'] == 1) {
672
+ $this->jsTrans['alertsend'] = __('You are about to send this newsletter. Please confirm.', WYSIJA);
673
+ } else {
674
+ if (isset($this->data['email']['params']['autonl']['event']) && $this->data['email']['params']['autonl']['event'] == 'subs-2-nl') {
675
+ $this->data['autoresponder'] = 1;
676
+ foreach ($this->data['lists'] as $list) {
677
+ if ($list['list_id'] == $this->data['email']['params']['autonl']['subscribetolist']) {
678
+ break;
679
+ }
680
+ }
681
+
682
+ $this->jsTrans['ignoreprevious'] = sprintf(__('Are you sure you want to ignore the %1$s subscribers of the list %2$s?', WYSIJA), '"' . $list['count'] . '"', '"' . $list['name'] . '"');
683
+ }
684
+ }
685
+
686
+ $this->checkIsEditable();
687
+
688
+ $this->title = sprintf(__('Step %1$s', WYSIJA), 3) . " | " . $this->data['email']['subject'];
689
+ $this->dataAutoNl();
690
+
691
+ $this->jsLoc['wysija-edit-autonl']['autofields'] = $this->data['autonl']['fields'];
692
+
693
+ $modelCL = WYSIJA::get('campaign_list', 'model');
694
+ $this->data['campaign_list'] = $modelCL->get(false, array('campaign_id' => $this->data['email']['campaign_id']));
695
+ }
696
+
697
+ function delete() {
698
+ $this->requireSecurity();
699
+
700
+ $campaign_ids = array();
701
+ if(isset($_REQUEST['id'])) $campaign_ids[] = $_REQUEST['id'];
702
+ if(isset($_REQUEST['campaign']['campaign_id'])) $campaign_ids[] = $_REQUEST['campaign']['campaign_id'];
703
+ if(isset($_REQUEST['wysija']['campaign']['campaign_id'][0])){
704
+ $campaign_ids = array_merge($campaign_ids, $_REQUEST['wysija']['campaign']['campaign_id']);
705
+ }
706
+
707
+ if (!empty($campaign_ids)) {
708
+ foreach($campaign_ids as $campaign_id){
709
+ if($campaign_id > 0){
710
+ $model_campaign = WYSIJA::get('campaign', 'model');
711
+ $model_campaign->delete(array('campaign_id' => $campaign_id));
712
+
713
+ $model_campaign_list = WYSIJA::get('campaign_list', 'model');
714
+ $model_campaign_list->delete(array('campaign_id' => $campaign_id));
715
+
716
+ $modelEmail = WYSIJA::get('email', 'model');
717
+ $modelEmail->delete(array('campaign_id' => $campaign_id));
718
+ }
719
+ }
720
+
721
+ $this->notice(_n(__('Newsletter deleted.', WYSIJA), __('Newsletters deleted.', WYSIJA), count($campaign_ids), WYSIJA));
722
+ } else {
723
+ $this->notice(__('Newsletter can\'t be deleted.', WYSIJA));
724
+ }
725
+
726
+ // retrieve saved filter
727
+ if (!empty($_REQUEST['action']))
728
+ unset($_REQUEST['action']);
729
+ if (!empty($_REQUEST['id']))
730
+ unset($_REQUEST['id']);
731
+ if (!empty($_REQUEST['_wpnonce']))
732
+ unset($_REQUEST['_wpnonce']);
733
+ $redirect = $this->base_url . '?' . http_build_query($_REQUEST);
734
+ $this->redirect($redirect);
735
+ }
736
+
737
+ /**
738
+ *
739
+ * this function is to delete an email that belongs to a campaign
740
+ * when we have a post notification all emails belong to the same campaign
741
+ * we don't want to delete an entire campaign when we delete a single email
742
+ */
743
+ function deleteEmail(){
744
+ $this->requireSecurity();
745
+ if(!$this->_checkEmailExists($_REQUEST['id'])) return;
746
+
747
+ if(isset($_REQUEST['id'])){
748
+ $modelEmail=WYSIJA::get('email','model');
749
+ $modelEmail->delete(array('email_id'=>$_REQUEST['id']));
750
+ $this->notice(__('Newsletter deleted.',WYSIJA));
751
+ }else{
752
+ $this->notice(__('Newsletter can\'t be deleted.',WYSIJA));
753
+ }
754
+
755
+ $this->redirect();
756
+ }
757
+
758
+ function savecamp() {
759
+ $this->redirectAfterSave = false;
760
+ $this->requireSecurity();
761
+ /* update email */
762
+ $data = array();
763
+ // in case the newsletter already exists
764
+ if (isset($_REQUEST['id'])) {
765
+ $modelEmail = WYSIJA::get('email', 'model');
766
+ $modelEmail->fieldValid = false;
767
+ $emaildataarr = $modelEmail->getOne(false, array('email_id' => $_REQUEST['id']));
768
+
769
+ $model_campaign = WYSIJA::get('campaign', 'model');
770
+ $model_campaign->update(array('name' => $_POST['wysija']['email']['subject'], 'description' => ''), array('campaign_id' => $emaildataarr['campaign_id']));
771
+
772
+ $campaign_id = $emaildataarr['campaign_id'];
773
+ $email_id = $emaildataarr['email_id'];
774
+ $dataEmail = array(
775
+ 'campaign_id' => $campaign_id,
776
+ 'subject' => $_POST['wysija']['email']['subject'],
777
+ 'type' => $_POST['wysija']['email']['type']);
778
+
779
+ if((int)$dataEmail['type'] === 2) {
780
+ // set autonl params
781
+ $dataEmail['params'] = array('autonl' => $_POST['wysija']['email']['params']['autonl']);
782
+
783
+ // WTF?
784
+ if(!isset($newparams['autonl']['unique_send'])) {
785
+ unset($dataEmail['params']['autonl']['unique_send']);
786
+ } else {
787
+ $dataEmail['params']['autonl']['unique_send'] = true;
788
+ }
789
+ }
790
+
791
+ // check if the newsletter used to be an automatic newsletter (if )
792
+ if((int)$dataEmail['type'] === 1 && (int)$emaildataarr['type'] === 2) {
793
+ // make sure we remove any kind of auto-post block
794
+ $helper_autonews = WYSIJA::get('autonews', 'helper');
795
+ $updated_email_data = $helper_autonews->remove_autopost_blocks($emaildataarr['wj_data']);
796
+ if($updated_email_data !== false) {
797
+ // if the email data has been changed, make sure to update it in the DB
798
+ $dataEmail['wj_data'] = $updated_email_data;
799
+ }
800
+ }
801
+
802
+ $modelEmail->columns['modified_at']['autoup'] = 1;
803
+ $modelEmail->debugupdate = true;
804
+ $dataEmail['email_id'] = $_REQUEST['id'];
805
+
806
+ if(isset($_REQUEST['save-reactivate'])) {
807
+ //if the button save and reactivate has been clicked then we reactivate and redirect to the newsletter page
808
+ $dataEmail['status'] = 99;
809
+ $_REQUEST['return'] = 1;
810
+ }
811
+
812
+ $data['email']['email_id'] = $modelEmail->update($dataEmail, array('email_id' => (int)$_REQUEST['id']));
813
+ } else {
814
+ // get default theme
815
+ $model_config = WYSIJA::get('config', 'model');
816
+ $default_theme = $model_config->getValue('newsletter_default_theme', 'default');
817
+
818
+ $helper_themes = WYSIJA::get('themes', 'helper');
819
+ $theme_data = $helper_themes->getData($default_theme);
820
+
821
+ // get campaign data
822
+ $model_campaign = WYSIJA::get('campaign', 'model');
823
+ $campaign_id = $model_campaign->insert(array('name' => $_POST['wysija']['email']['subject'], 'description' => ''));
824
+
825
+ $modelEmail = WYSIJA::get('email', 'model');
826
+ $modelEmail->fieldValid = false;
827
+ $emaildata = array(
828
+ 'campaign_id' => $campaign_id,
829
+ 'subject' => $_POST['wysija']['email']['subject'],
830
+ 'type' => (int) $_POST['wysija']['email']['type']
831
+ );
832
+
833
+
834
+ // create autonl parameters if necessary
835
+ if ((int) $_POST['wysija']['email']['type'] === 2 && isset($_POST['wysija']['email']['params']['autonl'])) {
836
+ $emaildata['params'] = array('autonl' => $_POST['wysija']['email']['params']['autonl']);
837
+ }
838
+
839
+ // create sample data depending on newsletter's type
840
+ if ((int) $_POST['wysija']['email']['type'] === 2 && $_POST['wysija']['email']['params']['autonl']['event'] === 'new-articles') {
841
+
842
+ // if immediate, post_limit is set to 1
843
+ if ($emaildata['params']['autonl']['when-article'] === 'immediate') {
844
+ $autopostParams = array(
845
+ array('key' => 'category_ids', 'value' => null),
846
+ array('key' => 'title_tag', 'value' => 'h2'),
847
+ array('key' => 'title_alignment', 'value' => 'left'),
848
+ array('key' => 'title_position', 'value' => 'inside'),
849
+ array('key' => 'image_alignment', 'value' => 'alternate'),
850
+ array('key' => 'image_width', 'value' => 325),
851
+ array('key' => 'post_content', 'value' => 'excerpt'),
852
+ array('key' => 'readmore', 'value' => base64_encode(__('Read more.', WYSIJA))),
853
+ array('key' => 'show_divider', 'value' => 'yes'),
854
+ array('key' => 'post_limit', 'value' => 1),
855
+ array('key' => 'post_type', 'value' => 'post'),
856
+ array('key' => 'author_show', 'value' => 'no'),
857
+ array('key' => 'author_label', 'value' => base64_encode(__('Author:', WYSIJA))),
858
+ array('key' => 'category_show', 'value' => 'no'),
859
+ array('key' => 'category_label', 'value' => base64_encode(__('Categories:', WYSIJA))),
860
+ array('key' => 'nopost_message', 'value' => base64_encode(__('Latest content already sent.', WYSIJA))),
861
+ array('key' => 'bgcolor1', 'value' => null),
862
+ array('key' => 'bgcolor2', 'value' => null),
863
+ array('key' => 'sort_by', 'value' => 'newest')
864
+ );
865
+ } else {
866
+ $autopostParams = array(
867
+ array('key' => 'category_ids', 'value' => null),
868
+ array('key' => 'title_tag', 'value' => 'h2'),
869
+ array('key' => 'title_alignment', 'value' => 'left'),
870
+ array('key' => 'title_position', 'value' => 'inside'),
871
+ array('key' => 'image_alignment', 'value' => 'alternate'),
872
+ array('key' => 'image_width', 'value' => 325),
873
+ array('key' => 'post_content', 'value' => 'excerpt'),
874
+ array('key' => 'readmore', 'value' => base64_encode(__('Read more.', WYSIJA))),
875
+ array('key' => 'show_divider', 'value' => 'yes'),
876
+ array('key' => 'post_limit', 'value' => 2),
877
+ array('key' => 'post_type', 'value' => 'post'),
878
+ array('key' => 'author_show', 'value' => 'no'),
879
+ array('key' => 'author_label', 'value' => base64_encode(__('Author:', WYSIJA))),
880
+ array('key' => 'category_show', 'value' => 'no'),
881
+ array('key' => 'category_label', 'value' => base64_encode(__('Categories:', WYSIJA))),
882
+ array('key' => 'nopost_message', 'value' => base64_encode(__('Latest content already sent.', WYSIJA))),
883
+ array('key' => 'bgcolor1', 'value' => null),
884
+ array('key' => 'bgcolor2', 'value' => null),
885
+ array('key' => 'sort_by', 'value' => 'newest')
886
+ );
887
+ }
888
+
889
+ // sample data for post notifications
890
+ $newwjdata = array(
891
+ 'version' => WYSIJA::get_version(),
892
+ 'header' => array(
893
+ 'text' => NULL,
894
+ 'image' => array(
895
+ 'src' => WYSIJA_EDITOR_IMG . 'transparent.png',
896
+ 'width' => 600,
897
+ 'height' => 86,
898
+ 'alignment' => 'center',
899
+ 'static' => true,
900
+ ),
901
+ 'alignment' => 'center',
902
+ 'static' => true,
903
+ 'type' => 'header'
904
+ ),
905
+ 'body' => array(
906
+ 'block-1' => array(
907
+ 'text' => array(
908
+ 'value' => '<h3 class="align-right">' . sprintf(__("The posts below were added with the widget %sAutomatic latest content%s", WYSIJA), '<strong>', '</strong>') . '</h3>'
909
+ ),
910
+ 'image' => array(
911
+ 'src' => WYSIJA_EDITOR_IMG . 'default-newsletter/autonewsletter/arrow-up.png',
912
+ 'width' => 45,
913
+ 'height' => 45,
914
+ 'alignment' => 'right',
915
+ 'static' => false
916
+ ),
917
+ 'alignment' => 'right',
918
+ 'static' => false,
919
+ 'position' => '1',
920
+ 'type' => 'content'
921
+ ),
922
+ 'block-2' => array(
923
+ 'text' => array(
924
+ 'value' => '<h3>' . sprintf(__('%sTo edit%s, mouse over to show edit button below.', WYSIJA), '<strong>', '</strong>') . '</h3>'
925
+ ),
926
+ 'image' => array(
927
+ 'src' => WYSIJA_EDITOR_IMG . 'default-newsletter/autonewsletter/arrow-down.png',
928
+ 'width' => 150,
929
+ 'height' => 53,
930
+ 'alignment' => 'left',
931
+ 'static' => false
932
+ ),
933
+ 'alignment' => 'left',
934
+ 'static' => false,
935
+ 'position' => '2',
936
+ 'type' => 'content'
937
+ ),
938
+ 'block-3' => array(
939
+ 'params' => $autopostParams,
940
+ 'position' => '3',
941
+ 'type' => 'auto-post'
942
+ )
943
+ ),
944
+ 'footer' => array(
945
+ 'text' => NULL,
946
+ 'image' => array(
947
+ 'src' => WYSIJA_EDITOR_IMG . 'transparent.png',
948
+ 'width' => 600,
949
+ 'height' => 86,
950
+ 'alignment' => 'center',
951
+ 'static' => true,
952
+ ),
953
+ 'alignment' => 'center',
954
+ 'static' => true,
955
+ 'type' => 'footer'
956
+ )
957
+ );
958
+ } else {
959
+ if(!isset($emaildata['params'])) {
960
+ $emaildata['params'] = array();
961
+ }
962
+
963
+ $emaildata['params']['quickselection'] = array(
964
+ 'wp-301' => array(
965
+ 'identifier' => 'wp-301',
966
+ 'width' => 281,
967
+ 'height' => 190,
968
+ 'url' => WYSIJA_EDITOR_IMG . 'default-newsletter/newsletter/pigeon.png',
969
+ 'thumb_url' => WYSIJA_EDITOR_IMG . 'default-newsletter/newsletter/pigeon-150x150.png'
970
+ )
971
+ );
972
+
973
+ if($theme_data['divider'] === null) {
974
+ // default theme does not exist anymore or there is no divider associated to the theme
975
+ // we need to get the default divider in this case
976
+ $helper_dividers = WYSIJA::get('dividers', 'helper');
977
+ $default_divider = $helper_dividers->getDefault();
978
+ } else {
979
+ // set default divider
980
+ $default_divider = $theme_data['divider'];
981
+ }
982
+ // set default divider in email parameters
983
+ $emaildata['params']['divider'] = $default_divider;
984
+
985
+ // get bookmarks from iconset 2
986
+ $helper_bookmarks = WYSIJA::get('bookmarks', 'helper');
987
+ $bookmarks = $helper_bookmarks->getAllByIconset('medium', '02');
988
+
989
+ // sample data for regular newsletter
990
+ $newwjdata = array(
991
+ 'version' => WYSIJA::get_version(),
992
+ 'header' => array(
993
+ 'text' => null,
994
+ 'image' => array(
995
+ // 'src' => WYSIJA_EDITOR_IMG.'default-newsletter/newsletter/header.png',
996
+ 'src' => WYSIJA_EDITOR_IMG . 'transparent.png',
997
+ 'width' => 600,
998
+ 'height' => 86,
999
+ 'alignment' => 'center',
1000
+ 'static' => true
1001
+ ),
1002
+ 'alignment' => 'center',
1003
+ 'static' => true,
1004
+ 'type' => 'header'
1005
+ ),
1006
+ 'body' => array(
1007
+ 'block-1' => array(
1008
+ 'text' => array(
1009
+ 'value' => '<h2><strong>' . __('Step 1:', WYSIJA) . '</strong> ' . __('hey, click on this text!', WYSIJA) . '</h2>' . '<p>' . __('To edit, simply click on this block of text.', WYSIJA) . '</p>'
1010
+ ),
1011
+ 'image' => null,
1012
+ 'alignment' => 'left',
1013
+ 'static' => false,
1014
+ 'position' => 1,
1015
+ 'type' => 'content'
1016
+ ),
1017
+ 'block-2' => array_merge(array(
1018
+ 'position' => 2,
1019
+ 'type' => 'divider'
1020
+ ),
1021
+ $default_divider
1022
+ ),
1023
+ 'block-3' => array(
1024
+ 'text' => array(
1025
+ 'value' => '<h2><strong>' . __('Step 2:', WYSIJA) . '</strong> ' . __('play with this image', WYSIJA) . '</h2>'
1026
+ ),
1027
+ 'image' => null,
1028
+ 'alignment' => 'left',
1029
+ 'static' => false,
1030
+ 'position' => 3,
1031
+ 'type' => 'content'
1032
+ ),
1033
+ 'block-4' => array(
1034
+ 'text' => array(
1035
+ 'value' => '<p>' . __('Position your mouse over the image to the left.', WYSIJA) . '</p>'
1036
+ ),
1037
+ 'image' => array(
1038
+ 'src' => WYSIJA_EDITOR_IMG . 'default-newsletter/newsletter/pigeon.png',
1039
+ 'width' => 281,
1040
+ 'height' => 190,
1041
+ 'alignment' => 'left',
1042
+ 'static' => false
1043
+ ),
1044
+ 'alignment' => 'left',
1045
+ 'static' => false,
1046
+ 'position' => 4,
1047
+ 'type' => 'content'
1048
+ ),
1049
+ 'block-5' => array_merge(array(
1050
+ 'position' => 5,
1051
+ 'type' => 'divider'
1052
+ ), $default_divider
1053
+ ),
1054
+ 'block-6' => array(
1055
+ 'text' => array(
1056
+ 'value' => '<h2><strong>' . __('Step 3:', WYSIJA) . '</strong> ' . __('drop content here', WYSIJA) . '</h2>' .
1057
+ '<p>' . sprintf(__('Drag and drop %1$stext, posts, dividers.%2$s Look on the right!', WYSIJA), '<strong>', '</strong>') . '</p>' .
1058
+ '<p>' . sprintf(__('You can even %1$ssocial bookmarks%2$s like these:', WYSIJA), '<strong>', '</strong>') . '</p>'
1059
+ ),
1060
+ 'image' => null,
1061
+ 'alignment' => 'left',
1062
+ 'static' => false,
1063
+ 'position' => 6,
1064
+ 'type' => 'content'
1065
+ ),
1066
+ 'block-7' => array(
1067
+ 'width' => 184,
1068
+ 'alignment' => 'center',
1069
+ 'items' => array(
1070
+ array_merge(array(
1071
+ 'url' => 'http://www.facebook.com/mailpoetplugin',
1072
+ 'alt' => 'Facebook',
1073
+ 'cellWidth' => 61,
1074
+ 'cellHeight' => 32
1075
+ ), $bookmarks['facebook']),
1076
+ array_merge(array(
1077
+ 'url' => 'http://www.twitter.com/mail_poet',
1078
+ 'alt' => 'Twitter',
1079
+ 'cellWidth' => 61,
1080
+ 'cellHeight' => 32
1081
+ ), $bookmarks['twitter']),
1082
+ array_merge(array(
1083
+ 'url' => 'https://plus.google.com/+Mailpoet',
1084
+ 'alt' => 'Google',
1085
+ 'cellWidth' => 61,
1086
+ 'cellHeight' => 32
1087
+ ), $bookmarks['google'])
1088
+ ),
1089
+ 'position' => 7,
1090
+ 'type' => 'gallery'
1091
+ ),
1092
+ 'block-8' => array_merge(array(
1093
+ 'position' => 8,
1094
+ 'type' => 'divider'
1095
+ ), $default_divider
1096
+ ),
1097
+ 'block-9' => array(
1098
+ 'text' => array(
1099
+ 'value' => '<h2><strong>' . __('Step 4:', WYSIJA) . '</strong> ' . __('and the footer?', WYSIJA) . '</h2>' .
1100
+ '<p>' . sprintf(__('Change the footer\'s content in MailPoet\'s %1$sSettings%2$s page.', WYSIJA), '<strong>', '</strong>') . '</p>'
1101
+ ),
1102
+ 'image' => null,
1103
+ 'alignment' => 'left',
1104
+ 'static' => false,
1105
+ 'position' => 9,
1106
+ 'type' => 'content'
1107
+ )
1108
+ ),
1109
+ 'footer' => array(
1110
+ 'text' => NULL,
1111
+ 'image' => array(
1112
+ // 'src' => WYSIJA_EDITOR_IMG.'default-newsletter/newsletter/footer.png',
1113
+ 'src' => WYSIJA_EDITOR_IMG . 'transparent.png',
1114
+ 'width' => 600,
1115
+ 'height' => 86,
1116
+ 'alignment' => 'center',
1117
+ 'static' => true,
1118
+ ),
1119
+ 'alignment' => 'center',
1120
+ 'static' => true,
1121
+ 'type' => 'footer'
1122
+ )
1123
+ );
1124
+ }
1125
+
1126
+ // set default styles
1127
+ $helper_engine = WYSIJA::get('wj_engine', 'helper');
1128
+ $styles = $helper_engine->getDefaultStyles();
1129
+ // end - set default styles
1130
+
1131
+ // set theme specific data
1132
+ if($theme_data['header'] !== null) {
1133
+ $newwjdata['header'] = $theme_data['header'];
1134
+ }
1135
+ if($theme_data['footer'] !== null) {
1136
+ $newwjdata['footer'] = $theme_data['footer'];
1137
+ }
1138
+ if($theme_data['divider'] !== null) {
1139
+ $newwjdata['widgets'] = array('divider' => $theme_data['divider']);
1140
+ }
1141
+ // end - set theme specific data
1142
+
1143
+ $emaildata['wj_data'] = base64_encode(serialize($newwjdata));
1144
+ $emaildata['wj_styles'] = base64_encode(serialize($styles));
1145
+
1146
+ $email_id = $data['email']['email_id'] = $modelEmail->insert($emaildata);
1147
+
1148
+ $this->notice(__('Newsletter successfully created.', WYSIJA));
1149
+ }
1150
+
1151
+ $this->_saveLists($campaign_id, true);
1152
+
1153
+ if (isset($_REQUEST['return']))
1154
+ $this->redirect();
1155
+ else {
1156
+ $this->redirect('admin.php?page=wysija_campaigns&action=editTemplate&id=' . $email_id);
1157
+ }
1158
+ }
1159
+
1160
+ function saveemail() {
1161
+ $this->redirectAfterSave = false;
1162
+ $this->requireSecurity();
1163
+ $modelEmail = WYSIJA::get("email", "model");
1164
+ $modelEmail->fieldValid = false;
1165
+ $emaildataarr = $modelEmail->getOne(array('email_id' => $_REQUEST['id']));
1166
+
1167
+ if (isset($_REQUEST['save-reactivate'])) {
1168
+ //if the button save and reactivate has been clicked then we reactivate and redirect to the newsletter page
1169
+ $dataEmail['status'] = 99;
1170
+ $_REQUEST['return'] = 1;
1171
+ }
1172
+
1173
+ if (isset($_REQUEST['return']))
1174
+ $this->redirect();
1175
+ else {
1176
+ $this->redirect('admin.php?page=wysija_campaigns&action=editDetails&id=' . $emaildataarr['email_id']);
1177
+ }
1178
+ }
1179
+
1180
+ function savelast() {
1181
+ $this->redirectAfterSave = false;
1182
+ $post_notification = false;
1183
+ $this->requireSecurity();
1184
+
1185
+ if (!isset($_POST['wysija']['email']['from_name']) || !isset($_POST['wysija']['email']['from_email']) || !isset($_POST['wysija']['email']['replyto_name']) || !isset($_POST['wysija']['email']['replyto_email'])) {
1186
+ $this->error(__('Information is missing.', WYSIJA));
1187
+ return $this->editDetails();
1188
+ }
1189
+ if (isset($_REQUEST['wysija']['email']['params']['googletrackingcode']) && $_REQUEST['wysija']['email']['params']['googletrackingcode'] &&
1190
+ (!is_string($_REQUEST['wysija']['email']['params']['googletrackingcode']) OR
1191
+ preg_match('#[^a-z0-9_\-\s]#i', $_REQUEST['wysija']['email']['params']['googletrackingcode']) !== 0 )) {
1192
+ //force to simple text
1193
+ $_REQUEST['wysija']['email']['params']['googletrackingcode'] = preg_replace('#[^a-z0-9_\-\s]#i', '_', $_REQUEST['wysija']['email']['params']['googletrackingcode']);
1194
+ $this->error(__('Your Google Campaign can only contain latin characters, numbers, spaces and hyphens!', WYSIJA), 1);
1195
+ return $this->editDetails();
1196
+ }
1197
+
1198
+ $update_email = array(
1199
+ 'email_id' => $_POST['wysija']['email']['email_id'],
1200
+ 'from_name' => $_POST['wysija']['email']['from_name'],
1201
+ 'from_email' => $_POST['wysija']['email']['from_email'],
1202
+ 'replyto_name' => $_POST['wysija']['email']['replyto_name'],
1203
+ 'replyto_email' => $_POST['wysija']['email']['replyto_email'],
1204
+ 'subject' => $_POST['wysija']['email']['subject'],
1205
+ );
1206
+ $model_email = WYSIJA::get('email', 'model');
1207
+ if (isset($_POST['wysija']['email']['params']))
1208
+ $update_email['params'] = $_POST['wysija']['email']['params'];
1209
+
1210
+ //insert into campaigns lists
1211
+ $this->_saveLists($_POST['wysija']['campaign']['campaign_id']);
1212
+ $email_data = $model_email->getOne($_POST['wysija']['email']['email_id']);
1213
+
1214
+ // if we just save the draf we don't go through the big sending process setup
1215
+ if (isset($_POST['submit-draft']) || isset($_POST['submit-pause']) || (isset($_REQUEST['wj_redir']) && $_REQUEST['wj_redir'] == 'savelastback')) {
1216
+ if (isset($_POST['wysija']['email']['params']['schedule']['isscheduled']))
1217
+ $this->notice(__('Newsletter has been scheduled.', WYSIJA));
1218
+ else
1219
+ $this->notice(__('Newsletter has been saved as a draft.', WYSIJA));
1220
+
1221
+ if (isset($_POST['submit-draft'])) {
1222
+
1223
+ $update_email['status'] = 0;// Email is being stored as draft
1224
+
1225
+ if (isset($update_email['params']['schedule']['isscheduled'])) {
1226
+ // draft emails should not be scheduled, clear any schedules
1227
+ unset($update_email['params']['schedule']['isscheduled']);
1228
+ }
1229
+ }
1230
+ }else {
1231
+ // we update the param attribute with what's has been posted
1232
+ foreach ($update_email as $ki => $vi) {
1233
+ if ($ki == 'params') {
1234
+ foreach ($vi as $parake => $paraval) {
1235
+ $email_data['params'][$parake] = $paraval;
1236
+ }
1237
+ $update_email[$ki] = $email_data[$ki];
1238
+ }
1239
+ else
1240
+ $email_data[$ki] = $vi;
1241
+ }
1242
+
1243
+ // if the checkbox to ignore retroactivity is here we just tell the class
1244
+ if (isset($_POST['wysija']['email']['ignore_subscribers'])) {
1245
+ $model_email->retro_active_autoresponders = false;
1246
+ }
1247
+
1248
+ // activate or send the email depending on the typ
1249
+ $model_email->send_activate($email_data);
1250
+ }
1251
+
1252
+ // update email
1253
+ $update_email['type'] = $email_data['type'];
1254
+
1255
+ if ($post_notification) {
1256
+ $helper_autonews = WYSIJA::get('autonews', 'helper');
1257
+ $update_email['params']['autonl']['nextSend'] = $helper_autonews->getNextSend($update_email);
1258
+ }
1259
+
1260
+ $model_email->reset();
1261
+ $model_email->columns['modified_at']['autoup'] = 1;
1262
+
1263
+ // re-render and save newsletter body (title may change during the last newsletter creation step)
1264
+ $wj_engine = WYSIJA::get('wj_engine', 'helper');
1265
+ // set data & styles
1266
+ $wj_engine->setData($email_data['wj_data'], true);
1267
+ $wj_engine->setStyles($email_data['wj_styles'], true);
1268
+ $email_data['subject'] = $_POST['wysija']['email']['subject'];
1269
+ $update_email['body'] = $wj_engine->renderEmail($email_data);
1270
+ // update some fields of the email
1271
+ $model_email->update($update_email);
1272
+
1273
+ // update the campaign subject which ispretty much useless but good to keep in sync with the email
1274
+ $model_campaign = WYSIJA::get('campaign', 'model');
1275
+ $model_campaign->reset();
1276
+ $update_campaign = array('campaign_id' => $_REQUEST['id'], 'name' => $_POST['wysija']['email']['subject']);
1277
+ $model_campaign->update($update_campaign);
1278
+
1279
+ if (isset($_REQUEST['wj_redir']) && $_REQUEST['wj_redir'] == 'savelastback') {
1280
+ return $this->redirect('admin.php?page=wysija_campaigns&action=editTemplate&id=' . $_POST['wysija']['email']['email_id']);
1281
+ }
1282
+ else
1283
+ return $this->redirect();
1284
+ }
1285
+
1286
+ function _saveLists($campaignId, $flagup = false) {
1287
+ //record the list that we have in that campaign
1288
+ $modelCampL = WYSIJA::get('campaign_list', 'model');
1289
+ if ($flagup || (int) $campaignId > 0) {
1290
+ $modelCampL->delete(array('equal' => array('campaign_id' => $campaignId)));
1291
+ $modelCampL->reset();
1292
+ }
1293
+
1294
+ if (isset($_POST['wysija']['campaign_list']['list_id'])) {
1295
+ //$modelCampL=WYSIJA::get("campaign_list","model");
1296
+ foreach ($_POST['wysija']['campaign_list']['list_id'] as $listid) {
1297
+ $modelCampL->insert(array('campaign_id' => $campaignId, "list_id" => $listid));
1298
+ }
1299
+ }
1300
+ }
1301
+
1302
+ function _addLinkFilter($status, $type = 'status') {
1303
+ switch ($type) {
1304
+ case 'status':
1305
+ switch ($status) {
1306
+ case 'draft':
1307
+ $this->filters['equal'] = array('status' => 0);
1308
+ break;
1309
+ case 'sending':
1310
+ $this->filters['equal'] = array('status' => 99);
1311
+ break;
1312
+ case 'sent':
1313
+ $this->filters['equal'] = array('status' => 2);
1314
+ break;
1315
+ case 'paused':
1316
+ $this->filters['equal'] = array('status' => -1);
1317
+ break;
1318
+ case 'scheduled':
1319
+ $this->filters['equal'] = array('status' => 4);
1320
+ break;
1321
+ }
1322
+ break;
1323
+ case 'type':
1324
+ switch ($status) {
1325
+ case 'regular':
1326
+ $this->filters['equal'] = array('type' => 1);
1327
+ break;
1328
+ case 'autonl':
1329
+ $this->filters['equal'] = array('type' => 2);
1330
+ break;
1331
+ }
1332
+ break;
1333
+ }
1334
+ }
1335
+
1336
+ /**
1337
+ * Get all campaigns, based on the filters
1338
+ */
1339
+ protected function get_campaigns() {
1340
+ $order_by = ' ORDER BY ';
1341
+
1342
+ if (isset($_REQUEST['orderby'])) {
1343
+ if (!is_string($_REQUEST['orderby']) OR preg_match('|[^a-z0-9#_.-]|i', $_REQUEST['orderby']) !== 0) {
1344
+ $_REQUEST['orderby'] = '';
1345
+ }
1346
+ if (!in_array(strtoupper($_REQUEST['ordert']), array('DESC', 'ASC'))){
1347
+ $_REQUEST['ordert'] = 'DESC';
1348
+ }
1349
+ $order_by.=$_REQUEST['orderby'] . ' ' . $_REQUEST['ordert'];
1350
+ }else {
1351
+ $order_by.='FIELD(B.status, 99,3,1,0,2), ';
1352
+ $order_by.='B.status desc, ';
1353
+ $order_by.='B.modified_at desc, ';
1354
+ $order_by.='B.sent_at desc, ';
1355
+ $order_by.='B.type desc, ';
1356
+ $order_by.='A.' . $this->modelObj->getPk() . ' DESC';
1357
+ }
1358
+
1359
+ $query = '
1360
+ SELECT
1361
+ A.`campaign_id`,
1362
+ A.`name` as `campaign_name`,
1363
+ B.`subject` as `name`,
1364
+ A.`description`,
1365
+ B.`params`,
1366
+ B.`type`,
1367
+ B.`number_sent`,
1368
+ B.`number_opened`,
1369
+ B.`number_clicked`,
1370
+ B.`number_unsub`,
1371
+ (B.`number_sent` +
1372
+ B.`number_opened` +
1373
+ B.`number_clicked` +
1374
+ B.`number_unsub` +
1375
+ B.`number_bounce` +
1376
+ B.`number_forward`
1377
+ ) AS `number_total`,
1378
+ B.`status`,
1379
+ B.`created_at`,
1380
+ B.`modified_at`,
1381
+ B.`sent_at`,
1382
+ B.`email_id`
1383
+ FROM
1384
+ `[wysija]' . $this->modelObj->table_name . '` AS A
1385
+ LEFT JOIN
1386
+ `[wysija]email` AS B on A.`campaign_id` = B.`campaign_id`
1387
+ LEFT JOIN
1388
+ `[wysija]campaign_list` AS C on A.`campaign_id` = C.`campaign_id`';
1389
+ $campaigns = $this->modelObj->getResults($query . $this->modelObj->makeWhere() . ' GROUP BY B.email_id' . $order_by . $this->modelObj->setLimit());
1390
+
1391
+ // calculate percetange of open / click / unsubscribe
1392
+ $helper_numbers = WYSIJA::get('numbers', 'helper');
1393
+ foreach ($campaigns as &$campaign) {
1394
+ // open rate, based on sent number
1395
+ $campaign['rate_opened'] = $helper_numbers->calculate_percetage($campaign['number_opened'], $campaign['number_total'], 1);
1396
+ // click rate, based on opened number
1397
+ $campaign['rate_clicked'] = $helper_numbers->calculate_percetage($campaign['number_clicked'], $campaign['number_total'], 1);
1398
+ // unsubscribe rate, based on opened number
1399
+ $campaign['rate_unsub'] = $helper_numbers->calculate_percetage($campaign['number_unsub'], $campaign['number_total'], 1);
1400
+ }
1401
+ return $campaigns;
1402
+ }
1403
+
1404
+ /**
1405
+ * Get the first campaign in history
1406
+ */
1407
+ protected function get_oldest_compaign() {
1408
+ $query = '
1409
+ SELECT
1410
+ MIN(B.created_at) as datemin
1411
+ FROM `[wysija]' . $this->modelObj->table_name . '` as A
1412
+ LEFT JOIN
1413
+ `[wysija]email` AS B on A.campaign_id = B.campaign_id
1414
+ LEFT JOIN
1415
+ `[wysija]campaign_list` as C on A.campaign_id = C.campaign_id';
1416
+
1417
+ return $this->modelObj->query('get_row', $query . $this->modelObj->makeWhere());
1418
+ }
1419
+
1420
+ /**
1421
+ * Count ALL emails of each email-status
1422
+ * @todo: move to model
1423
+ */
1424
+ protected function count_emails_by_status() {
1425
+ $query = '
1426
+ SELECT
1427
+ COUNT(`email_id`) AS `campaigns`,
1428
+ `status`
1429
+ FROM
1430
+ `[wysija]email`
1431
+ WHERE
1432
+ `campaign_id` > 0
1433
+ GROUP BY `status`';
1434
+
1435
+ $countss = $this->modelObj->query('get_res', $query);
1436
+ $counts = array();
1437
+ $total = 0;
1438
+
1439
+ foreach ($countss as $count) {
1440
+ switch ($count['status']) {
1441
+ case '0':
1442
+ $type = 'draft';
1443
+ break;
1444
+ case '1':
1445
+ case '3':
1446
+ case '99':
1447
+ $type = 'sending';
1448
+ break;
1449
+ case '2':
1450
+ $type = 'sent';
1451
+ break;
1452
+ case '-1':
1453
+ $type = 'paused';
1454
+ break;
1455
+ case '4':
1456
+ $type = 'scheduled';
1457
+ break;
1458
+ }
1459
+ $total = $total + $count['campaigns'];
1460
+ $counts['status-' . $type] = $count['campaigns'];
1461
+ }
1462
+ return $counts;
1463
+ }
1464
+
1465
+ /**
1466
+ * Count emails which matched the filters
1467
+ */
1468
+ protected function count_emails() {
1469
+ $query = '
1470
+ SELECT
1471
+ COUNT(DISTINCT B.`email_id`) AS `campaigns`
1472
+ FROM
1473
+ `[wysija]' . $this->modelObj->table_name . '` AS A
1474
+ LEFT JOIN
1475
+ `[wysija]email` AS B ON A.`campaign_id` = B.`campaign_id`
1476
+ LEFT JOIN
1477
+ `[wysija]campaign_list` AS C ON A.`campaign_id` = C.`campaign_id`';
1478
+ return $this->modelObj->count($query . $this->modelObj->makeWhere(), 'campaigns');
1479
+ }
1480
+
1481
+ /**
1482
+ * Count ALL emails of each type of email
1483
+ */
1484
+ protected function count_emails_by_type() {
1485
+ $query = '
1486
+ SELECT
1487
+ COUNT(`email_id`) AS `campaigns`,
1488
+ `type`
1489
+ FROM
1490
+ `[wysija]email`
1491
+ WHERE
1492
+ `campaign_id` > 0
1493
+ GROUP BY `type`';
1494
+ $countss = $this->modelObj->query('get_res', $query, ARRAY_A);
1495
+ $counts = array();
1496
+ foreach ($countss as $count) {
1497
+ switch ($count['type']) {
1498
+ case '1':
1499
+ $type = 'regular';
1500
+ break;
1501
+ case '2':
1502
+ $type = 'autonl';
1503
+ break;
1504
+ }
1505
+ $counts['type-' . $type] = $count['campaigns'];
1506
+ }
1507
+ return $counts;
1508
+ }
1509
+
1510
+ /**
1511
+ * Get all existing lists
1512
+ */
1513
+ protected function get_lists() {
1514
+ $model_list = WYSIJA::get('list', 'model');
1515
+ $query = '
1516
+ SELECT
1517
+ A.`list_id`,
1518
+ A.`name`,
1519
+ A.`is_enabled`,
1520
+ COUNT( B.`campaign_id` ) AS `users`
1521
+ FROM
1522
+ `[wysija]' . $model_list->table_name . '` as A
1523
+ LEFT JOIN
1524
+ `[wysija]campaign_list` AS B on A.`list_id` = B.`list_id`
1525
+ GROUP BY A.`list_id`';
1526
+ $result = $model_list->getResults($query);
1527
+ $lists = array();
1528
+ foreach ($result as $list_obj) {
1529
+ $lists[$list_obj['list_id']] = $list_obj;
1530
+ }
1531
+ return $lists;
1532
+ }
1533
+
1534
+ function defaultDisplay() {
1535
+ $this->data['base_url'] = $this->base_url . '?' . http_build_query($_REQUEST); // saved filter
1536
+ $this->title = __('Newsletters', WYSIJA);
1537
+ $this->viewShow = $this->action = 'main';
1538
+ $this->js[] = 'wysija-admin-list';
1539
+ $this->jsTrans["selecmiss"] = __('Please select a newsletter.', WYSIJA);
1540
+ $this->jsTrans['suredelete'] = __('Delete this newsletter for ever?', WYSIJA);
1541
+ $this->jsTrans['suredelete_bulk'] = __('Delete these newsletters for ever?', WYSIJA);
1542
+ $this->jsTrans['processqueue'] = __('Sending batch of emails...', WYSIJA);
1543
+ $this->jsTrans['viewnews'] = __('View newsletter', WYSIJA);
1544
+ $this->jsTrans['confirmpauseedit'] = __('The newsletter will be deactivated, you will need to reactivate it once you\'re over editing it. Do you want to proceed?', WYSIJA);
1545
+
1546
+
1547
+ //get the filters
1548
+ if (isset($_REQUEST['search']) && $_REQUEST['search']) {
1549
+ $this->filters['like'] = array();
1550
+ foreach ($this->searchable as $field)
1551
+ $this->filters['like'][$field] = $_REQUEST['search'];
1552
+ }
1553
+
1554
+ if (isset($_REQUEST['filter-list']) && $_REQUEST['filter-list']) {
1555
+ $this->filters['equal'] = array('C.list_id' => $_REQUEST['filter-list']);
1556
+ }
1557
+
1558
+ if (isset($_REQUEST['filter-date']) && $_REQUEST['filter-date']) {
1559
+ $this->filters['greater_eq'] = array('created_at' => $_REQUEST['filter-date']);
1560
+ $this->filters['less_eq'] = array('created_at' => strtotime('+1 month', $_REQUEST['filter-date']));
1561
+ }
1562
+
1563
+ $this->filters['is'] = array('type' => 'IS NOT NULL');
1564
+
1565
+
1566
+ if (isset($_REQUEST['link_filter']) && $_REQUEST['link_filter']) {
1567
+ $linkfilters = explode('-', $_REQUEST['link_filter']);
1568
+
1569
+ if (count($linkfilters) > 1) {
1570
+ $this->_addLinkFilter($linkfilters[1], $linkfilters[0]);
1571
+ } else {
1572
+ $this->_addLinkFilter($_REQUEST['link_filter']);
1573
+ }
1574
+ }
1575
+
1576
+ $this->modelObj->noCheck = true;
1577
+ $this->modelObj->reset();
1578
+ if ($this->filters){
1579
+ $this->modelObj->setConditions($this->filters);
1580
+ }
1581
+
1582
+
1583
+ // Count emails by status and type
1584
+ $emails_by_status = $this->count_emails_by_status();
1585
+ $emails_by_type = $this->count_emails_by_type();
1586
+ $counts = array_merge($emails_by_status, $emails_by_type);
1587
+ $counts['all'] = array_sum($emails_by_status);
1588
+
1589
+ // collect data
1590
+ $this->data['campaigns'] = $this->get_campaigns();
1591
+ $this->data['datemin'] = $this->get_oldest_compaign();
1592
+ $lists = $this->get_lists(); // $lists is in use later within this scope
1593
+ $this->data['lists'] = $lists;
1594
+
1595
+ // for paging
1596
+ $this->modelObj->countRows = $counts['all'];
1597
+ if ($this->filters){
1598
+ $count_emails = $this->count_emails();
1599
+ if( !empty($count_emails) ){
1600
+ $this->modelObj->countRows = $count_emails;
1601
+ }
1602
+ }
1603
+
1604
+ // count queue
1605
+ $email_ids = array();
1606
+ foreach ($this->data['campaigns'] as $emailcamp) {
1607
+ if (in_array($emailcamp['status'], array(1, 3, 99)))
1608
+ $email_ids[] = $emailcamp['email_id'];
1609
+ }
1610
+ $model_queue = WYSIJA::get('queue', 'model');
1611
+ $model_queue->setConditions(array("email_id" => $email_ids));
1612
+ $model_queue->groupBy('email_id');
1613
+ $queue = $model_queue->count();
1614
+ if ($queue) {
1615
+ $this->viewObj->queuedemails = $queue;
1616
+ }
1617
+
1618
+ $this->modelObj->reset();
1619
+
1620
+ //make a loop from the first created to now and increment an array of months
1621
+ $now = time();
1622
+ $this->data['dates'] = array();
1623
+
1624
+ if ((int) $this->data['datemin']['datemin'] > 1) {
1625
+ setlocale(LC_TIME, 'en_US');
1626
+ $formtlettres = "1 " . date('F', $this->data['datemin']['datemin']) . ' ' . date("Y", $this->data['datemin']['datemin']);
1627
+ $month_start = strtotime($formtlettres);
1628
+
1629
+ if ($month_start > 0) {
1630
+ for ($i = $month_start; $i < $now; $i = strtotime('+1 month', $i)) {
1631
+ $this->data['dates'][$i] = date_i18n('F Y', $i); //date('F Y',$i);
1632
+ }
1633
+ }
1634
+ }
1635
+
1636
+
1637
+
1638
+ $campaign_ids_sent = $campaign_ids = array();
1639
+ foreach ($this->data['campaigns'] as &$campaign) {
1640
+ $campaign_ids[] = $campaign['campaign_id'];
1641
+ $model_email = WYSIJA::get('email', 'model');
1642
+ $model_email->getParams($campaign);
1643
+ if (in_array((int) $campaign['status'], array(-1, 1, 2, 3, 99)))
1644
+ $campaign_ids_sent[] = $campaign['campaign_id'];
1645
+ }
1646
+
1647
+ // 3 - campaign_list request & count request for queue */
1648
+ if ($campaign_ids) {
1649
+ $model_campaign_list = WYSIJA::get('campaign_list', 'model');
1650
+ $userlists = $model_campaign_list->get(array('list_id', 'campaign_id'), array('campaign_id' => $campaign_ids));
1651
+
1652
+ if ($campaign_ids_sent) {
1653
+ $model_campaign_list = WYSIJA::get("email_user_stat", "model");
1654
+ $statstotal = $model_campaign_list->getResults("SELECT COUNT(A.user_id) as count,B.email_id FROM `[wysija]queue` as A
1655
+ JOIN `[wysija]email` as B on A.email_id=B.email_id
1656
+ WHERE B.campaign_id IN (" . implode(",", $campaign_ids_sent) . ") group by B.email_id");
1657
+
1658
+ $senttotalgroupedby = $model_campaign_list->getResults("SELECT COUNT(A.user_id) as count,B.campaign_id,B.email_id,B.type,B.status,A.status as statususer FROM `[wysija]" . $model_campaign_list->table_name . "` as A
1659
+ JOIN `[wysija]email` as B on A.email_id=B.email_id
1660
+ WHERE B.campaign_id IN (" . implode(",", $campaign_ids_sent) . ") group by A.status,B.email_id"); //,A.status
1661
+
1662
+
1663
+ $updateEmail = array();
1664
+ $columnnamestatus = array(0 => "number_sent", 1 => "number_opened", 2 => "number_clicked", 3 => "number_unsub", -1 => "number_bounce");
1665
+ foreach ($senttotalgroupedby as $sentbystatus) {
1666
+ if ($sentbystatus['statususer'] != "-2")
1667
+ $updateEmail[$sentbystatus['email_id']][$columnnamestatus[$sentbystatus['statususer']]] = $sentbystatus['count'];
1668
+ if (isset($senttotal[$sentbystatus['email_id']])) {
1669
+ $senttotal[$sentbystatus['email_id']]['count'] = (int) $senttotal[$sentbystatus['email_id']]['count'] + (int) $sentbystatus['count'];
1670
+ } else {
1671
+ unset($sentbystatus['statususer']);
1672
+ $senttotal[$sentbystatus['email_id']] = $sentbystatus;
1673
+ }
1674
+ }
1675
+
1676
+ $model_email = WYSIJA::get('email', 'model');
1677
+
1678
+ foreach ($updateEmail as $emailid => $update) {
1679
+
1680
+ foreach ($columnnamestatus as $v) {
1681
+ if (!isset($update[$v]))
1682
+ $update[$v] = 0;
1683
+ }
1684
+
1685
+ $model_email->update($update, array('email_id' => $emailid));
1686
+ $model_email->reset();
1687
+ }
1688
+
1689
+
1690
+ $model_config = WYSIJA::get('config', 'model');
1691
+ $running = false;
1692
+
1693
+ $is_multisite = is_multisite();
1694
+
1695
+ if ($is_multisite && $model_config->getValue('sending_method') == 'network') {
1696
+ $sending_emails_each = $model_config->getValue('ms_sending_emails_each');
1697
+ } else {
1698
+ $sending_emails_each = $model_config->getValue('sending_emails_each');
1699
+ }
1700
+
1701
+ if ($model_config->getValue('cron_manual')) {
1702
+ $formsHelp = WYSIJA::get('forms', 'helper');
1703
+ $queue_frequency = $formsHelp->eachValuesSec[$sending_emails_each];
1704
+ $queue_scheduled = WYSIJA::get_cron_schedule('queue');
1705
+
1706
+ $next_scheduled_queue = $queue_scheduled['next_schedule'];
1707
+ $running = $queue_scheduled['running'];
1708
+
1709
+ if ($running) {
1710
+ $helper_toolbox = WYSIJA::get('toolbox', 'helper');
1711
+ $running = time() - $running;
1712
+ $running = $helper_toolbox->duration_string($running, true, 4);
1713
+ }
1714
+ } else {
1715
+ $schedules = wp_get_schedules();
1716
+ $queue_frequency = $schedules[wp_get_schedule('wysija_cron_queue')]['interval'];
1717
+ $next_scheduled_queue = wp_next_scheduled('wysija_cron_queue');
1718
+ }
1719
+
1720
+
1721
+
1722
+ $status_sent_complete = array();
1723
+ if (isset($senttotal) && $senttotal) {
1724
+ foreach ($senttotal as $sentot) {
1725
+ if ($sentot) {
1726
+ $this->data['sent'][$sentot['email_id']]['total'] = $sentot['count'];
1727
+ $this->data['sent'][$sentot['email_id']]['to'] = $sentot['count'];
1728
+ } else {
1729
+ $this->data['sent'][$sentot['email_id']]['total'] = $this->data['sent'][$sentot['email_id']]['to'] = 0;
1730
+ }
1731
+ $this->data['sent'][$sentot['email_id']]['status'] = $sentot['status'];
1732
+ $this->data['sent'][$sentot['email_id']]['type'] = $sentot['type'];
1733
+ $this->data['sent'][$sentot['email_id']]['left'] = (int) $this->data['sent'][$sentot['email_id']]['total'] - (int) $this->data['sent'][$sentot['email_id']]['to'];
1734
+ }
1735
+ }
1736
+
1737
+ foreach ($statstotal as $sentot) {
1738
+ if (!isset($this->data['sent'][$sentot['email_id']])) {
1739
+ $this->data['sent'][$sentot['email_id']]['total'] = 0;
1740
+ $this->data['sent'][$sentot['email_id']]['to'] = 0;
1741
+ }
1742
+ $this->data['sent'][$sentot['email_id']]['total'] = $this->data['sent'][$sentot['email_id']]['total'] + $sentot['count'];
1743
+ $this->data['sent'][$sentot['email_id']]['left'] = (int) $this->data['sent'][$sentot['email_id']]['total'] - (int) $this->data['sent'][$sentot['email_id']]['to'];
1744
+ }
1745
+
1746
+ if ($is_multisite && $model_config->getValue('sending_method') == 'network') {
1747
+ $sending_emails_number = $model_config->getValue('ms_sending_emails_number');
1748
+ } else {
1749
+ $sending_emails_number = $model_config->getValue('sending_emails_number');
1750
+ }
1751
+
1752
+ if (isset($this->data['sent'])) {
1753
+ foreach ($this->data['sent'] as $key => &$camp) {
1754
+ if ($this->data['sent'][$key]['left'] > 0) {
1755
+ $cronsneeded = ceil($this->data['sent'][$key]['left'] / $sending_emails_number);
1756
+ $this->data['sent'][$key]['remaining_time'] = $cronsneeded * $queue_frequency;
1757
+ $this->data['sent'][$key]['running_for'] = $running;
1758
+ $this->data['sent'][$key]['next_batch'] = $next_scheduled_queue - time();
1759
+ $this->data['sent'][$key]['remaining_time'] = $this->data['sent'][$key]['remaining_time'] - ($queue_frequency) + $this->data['sent'][$key]['next_batch'];
1760
+ } else {
1761
+ if ((in_array($this->data['sent'][$key]['status'], array(1, 3, 99))) && $this->data['sent'][$key]['type'] == 1)
1762
+ $status_sent_complete[] = $key;
1763
+ }
1764
+ }
1765
+ }
1766
+
1767
+
1768
+ // status update to sent for the one that are sent
1769
+ if (count($status_sent_complete) > 0) {
1770
+ $model_email = WYSIJA::get('email', 'model');
1771
+ $model_email->noCheck = true;
1772
+ $model_email->reset();
1773
+ $model_email->update(array('status' => 2), array('equal' => array('email_id' => $status_sent_complete)));
1774
+ }
1775
+ }
1776
+ }
1777
+
1778
+ $this->data['counts'] = array_reverse($counts);
1779
+
1780
+ // regrouping all the data in the same array
1781
+ foreach ($this->data['campaigns'] as &$campaign) {
1782
+ // default key while we don't have the data
1783
+ //TODO add data for stats about emails opened clicked etc
1784
+ $campaign["emails"] = 0;
1785
+ $campaign["opened"] = 0;
1786
+ $campaign["clicked"] = 0;
1787
+
1788
+ if ($userlists) {
1789
+ foreach ($userlists as $key => $userlist) {
1790
+ if ($campaign["campaign_id"] == $userlist["campaign_id"] && isset($lists[$userlist["list_id"]])) {
1791
+ if (!isset($campaign["lists"]))
1792
+ $campaign["lists"] = $lists[$userlist["list_id"]]["name"];
1793
+ else
1794
+ $campaign["lists"].=", " . $lists[$userlist["list_id"]]["name"];
1795
+ }
1796
+ }
1797
+ }
1798
+ if (isset($campaign["lists"]) && !$campaign["lists"])
1799
+ unset($campaign["lists"]);
1800
+
1801
+ if (((isset($campaign['params']['schedule']['isscheduled']) ||
1802
+ ($campaign['type'] == 2 && isset($campaign['params']['autonl']['event']) && in_array($campaign['params']['autonl']['event'], array('new-articles'/* ,'subs-2-nl' */)))
1803
+ ) && $campaign['status'] != 2 && !isset($campaign["lists"])) || ($campaign['type'] == 2 && isset($campaign['params']['autonl']['event']) && in_array($campaign['params']['autonl']['event'], array('subs-2-nl')) && $campaign['status'] != 2 && (!isset($campaign['params']['autonl']['subscribetolist']) || !isset($lists[$campaign['params']['autonl']['subscribetolist']]) ))
1804
+ ) {
1805
+ $campaign['classRow'] = " listmissing ";
1806
+ $campaign['msgListEdit'] = '<strong>' . __('The list has been deleted.', WYSIJA) . '</strong>';
1807
+ $campaign['msgSendSuspended'] = '<strong>' . __('Sending suspended.', WYSIJA) . '</strong>';
1808
+ }
1809
+ }
1810
+
1811
+ $this->dataAutoNl();
1812
+ if (!$this->data['campaigns']) {
1813
+ $this->notice(__('There are no newsletters.', WYSIJA));
1814
+ }
1815
+ }
1816
+
1817
+ function setviewStatsfilter() {
1818
+ // get the filters
1819
+ $this->searchable = array("email", "firstname", "lastname");
1820
+ $this->filters = array();
1821
+ if (isset($_REQUEST['search']) && $_REQUEST['search']) {
1822
+ $this->filters["like"] = array();
1823
+ foreach ($this->searchable as $field)
1824
+ $this->filters["like"][$field] = $_REQUEST['search'];
1825
+ }
1826
+ $this->tableQuery = 'email_user_stat';
1827
+ $this->statusemail = 'B.status as umstatus';
1828
+ if (isset($_REQUEST['link_filter']) && $_REQUEST['link_filter']) {
1829
+ switch ($_REQUEST['link_filter']) {
1830
+ case 'inqueue':
1831
+ $this->tableQuery = 'queue';
1832
+ $this->statusemail = '-2 as umstatus';
1833
+ break;
1834
+ case 'sent':
1835
+ $this->filters['equal'] = array('B.status' => 0);
1836
+ break;
1837
+ case 'bounced':
1838
+ $this->filters['equal'] = array('B.status' => -1);
1839
+ break;
1840
+ case 'opened':
1841
+ $this->filters['equal'] = array('B.status' => 1);
1842
+ break;
1843
+ case 'clicked':
1844
+ $this->filters['equal'] = array('B.status' => 2);
1845
+ break;
1846
+ case 'unsubscribe':
1847
+ $this->filters['equal'] = array('B.status' => 3);
1848
+ break;
1849
+ case 'notsent':
1850
+ $this->filters['equal'] = array('B.status' => -2);
1851
+ break;
1852
+ }
1853
+ }
1854
+ // filter by url id
1855
+ if (isset($_REQUEST['url_id']) && (int) $_REQUEST['url_id'] > 0) {
1856
+ $this->tableQuery = 'email_user_url';
1857
+ $this->filters['equal'] = array('B.url_id' => (int) $_REQUEST['url_id']);
1858
+ $this->statusemail = '2 as umstatus'; //by default, when filter by url_id, all subscribers had clicked
1859
+ }
1860
+ }
1861
+
1862
+ function viewstats() {
1863
+ $this->js[] = 'wysija-admin-list';
1864
+ $this->js[] = 'wysija-charts';
1865
+ $this->viewShow = 'viewstats';
1866
+
1867
+ $this->modelObj = WYSIJA::get("email", "model");
1868
+ $this->modelObj->limitON = false;
1869
+
1870
+ $email_object = $this->modelObj->getOne(false, array("email_id" => $_REQUEST['id']));
1871
+ if(empty($email_object)){
1872
+ $this->redirect('admin.php?page=wysija_campaigns');
1873
+ return;
1874
+ }
1875
+ $this->viewObj->model = $this->modelObj;
1876
+ $this->viewObj->namecampaign = $email_object['subject'];
1877
+ $this->viewObj->title = sprintf(__('Stats : %1$s', WYSIJA), $email_object['subject']);
1878
+
1879
+ $modelObjCamp = WYSIJA::get("campaign", "model");
1880
+ $limit_pp = false;
1881
+ if (isset($modelObjCamp->limit_pp))
1882
+ $limit_pp = $modelObjCamp->limit_pp;
1883
+ $modelObjCamp->limitON = false;
1884
+ $campaign = $modelObjCamp->getOne(false, array("campaign_id" => $email_object['campaign_id']));
1885
+
1886
+
1887
+ $this->setviewStatsfilter();
1888
+
1889
+ $this->modelObj->reset();
1890
+ $this->modelObj->noCheck = true;
1891
+
1892
+ // 0 - counting request
1893
+ $queryCmmonStart = 'SELECT count(distinct B.user_id) as users FROM `[wysija]user` as A';
1894
+ $queryCmmonStart.=' LEFT JOIN `[wysija]' . $this->tableQuery . '` as B on A.user_id=B.user_id';
1895
+
1896
+ // all the counts query
1897
+ $query = "SELECT count(user_id) as users, status FROM `[wysija]email_user_stat` as A
1898
+ WHERE A.email_id=" . $email_object['email_id'] . " GROUP BY status";
1899
+ $countss = $this->modelObj->query("get_res", $query, ARRAY_A);
1900
+
1901
+ // we also count what is in the queue
1902
+ $query = "SELECT count(user_id) as users FROM `[wysija]queue` as A
1903
+ WHERE A.email_id=" . $email_object['email_id'];
1904
+ $countss[-2]['status'] = -3;
1905
+ $countss[-2]['users'] = $this->modelObj->count($query, 'users');
1906
+
1907
+ $counts = array();
1908
+ $truetotal = $total = 0;
1909
+
1910
+ foreach ($countss as $count) {
1911
+ switch ($count['status']) {
1912
+ case "-3":
1913
+ $type = 'inqueue';
1914
+ break;
1915
+ case "-2":
1916
+ $type = 'notsent';
1917
+ break;
1918
+ case "-1":
1919
+ $type = 'bounced';
1920
+ break;
1921
+ case "0":
1922
+ $type = 'sent';
1923
+ break;
1924
+ case "1":
1925
+ $type = 'opened';
1926
+ break;
1927
+ case "2":
1928
+ $type = 'clicked';
1929
+ break;
1930
+ case "3":
1931
+ $type = 'unsubscribe';
1932
+ break;
1933
+ }
1934
+ if ($count['status'] != "-2")
1935
+ $total = $total + $count['users'];
1936
+ $truetotal = $truetotal + $count['users'];
1937
+ $counts[$type] = $count['users'];
1938
+ }
1939
+
1940
+ $counts['allsent'] = $total;
1941
+ $counts['all'] = $truetotal;
1942
+
1943
+ $this->modelObj->reset();
1944
+ $this->filters['equal']["B.email_id"] = $email_object['email_id'];
1945
+
1946
+ $this->modelObj->noCheck = true;
1947
+ if ($this->filters){
1948
+ $this->modelObj->setConditions($this->filters);
1949
+ }
1950
+
1951
+
1952
+ // 1 - subscriber request
1953
+ $query = 'SELECT A.user_id, A.firstname, A.lastname,A.status as ustatus,' . $this->statusemail . ' , A.email, B.* FROM `[wysija]user` as A';
1954
+ $query.=' LEFT JOIN `[wysija]' . $this->tableQuery . '` as B on A.user_id=B.user_id';
1955
+ $queryFinal = $this->modelObj->makeWhere();
1956
+
1957
+ // without filter we already have the total number of subscribers
1958
+ if ($this->filters)
1959
+ $this->modelObj->countRows = $this->modelObj->count($queryCmmonStart . $queryFinal, 'users');
1960
+ else
1961
+ $this->modelObj->countRows = $counts['all'];
1962
+
1963
+ $orderby = '';
1964
+ /**
1965
+ * Until now, we have
1966
+ * - 3 possible values of $this->tableQuery (queue, email_user_url, email_user_stat), set by $this->setviewStatsfilter()
1967
+ * - 2 possible values of $_REQUEST['orderby']
1968
+ * => 3x2 = 6 cases
1969
+ */
1970
+ if (isset($_REQUEST['orderby'])) {
1971
+ switch ($this->tableQuery) {
1972
+ case 'email_user_url':
1973
+ case 'email_user_stat':
1974
+ if (!is_string($_REQUEST['orderby']) OR preg_match('|[^a-z0-9#_.-]|i', $_REQUEST['orderby']) !== 0) {
1975
+ $_REQUEST['orderby'] = '';
1976
+ break;
1977
+ }
1978
+ if (!in_array(strtoupper($_REQUEST['ordert']), array('DESC', 'ASC'))){
1979
+ $_REQUEST['ordert'] = 'DESC';
1980
+ }
1981
+
1982
+ $orderby = ' ORDER BY ' . $_REQUEST['orderby'] . ' ' . $_REQUEST['ordert'];
1983
+ break;
1984
+
1985
+ case 'queue':
1986
+ default:
1987
+ $orderby .= ' ORDER BY A.user_id DESC';
1988
+ break;
1989
+ }
1990
+ } else {
1991
+ switch ($this->tableQuery) {
1992
+ case 'email_user_url':
1993
+ $orderby = ' ORDER BY B.clicked_at DESC, B.number_clicked DESC'; // by default, sort by last clicked and biggest hit
1994
+ break;
1995
+
1996
+ case 'email_user_stat':
1997
+ $orderby = ' ORDER BY B.opened_at DESC, B.status DESC'; // by default, sort by last open and its staus value
1998
+ break;
1999
+
2000
+ case 'queue':
2001
+ default:
2002
+ $orderby = ' ORDER BY A.user_id DESC';
2003
+ break;
2004
+ }
2005
+ }
2006
+ $this->data['tableQuery'] = $this->tableQuery;
2007
+ $this->modelObj->limitON = true;
2008
+
2009
+ $subscribers = array();
2010
+ $hook_params = array(
2011
+ 'email_id' => $email_object['email_id'],
2012
+ 'url_id' => isset($_REQUEST['url_id']) && $_REQUEST['url_id'] ? $_REQUEST['url_id'] : false,
2013
+ 'subscribers' => &$subscribers,
2014
+ 'id' => $email_object['campaign_id']
2015
+ );
2016
+ $this->data['subscribers'] = $this->modelObj->getResults($query . $queryFinal . " GROUP BY A.user_id" . $orderby . $this->modelObj->setLimit(0, (int)$limit_pp));
2017
+ $this->modelObj->reset();
2018
+
2019
+ // make the data object for the listing view
2020
+ $modelList = WYSIJA::get("list", "model");
2021
+
2022
+ // 2 - list request
2023
+ $query = "SELECT A.list_id, A.name,A.is_enabled, count( B.user_id ) AS users FROM `[wysija]" . $modelList->table_name . "` as A";
2024
+ $query.=" LEFT JOIN `[wysija]user_list` as B on A.list_id = B.list_id";
2025
+ $query.=" GROUP BY A.list_id";
2026
+ $listsDB = $modelList->getResults($query);
2027
+
2028
+ $lists = array();
2029
+ foreach ($listsDB as $listobj) {
2030
+ $lists[$listobj["list_id"]] = $listobj;
2031
+ }
2032
+
2033
+ $listsDB = null;
2034
+
2035
+ $user_ids = array();
2036
+ foreach ($this->data['subscribers'] as $subscriber) {
2037
+ $user_ids[] = $subscriber['user_id'];
2038
+ }
2039
+
2040
+ // 3 - user_list request
2041
+ if ($user_ids) {
2042
+ $modeluList = WYSIJA::get("user_list", "model");
2043
+ $userlists = $modeluList->get(array("list_id", "user_id"), array("user_id" => $user_ids));
2044
+ }
2045
+
2046
+
2047
+ $this->data['lists'] = $lists;
2048
+ $this->data['counts'] = array_reverse($counts);
2049
+
2050
+ // regrouping all the data in the same array
2051
+ foreach ($this->data['subscribers'] as $keysus => $subscriber) {
2052
+ // default key while we don't have the data
2053
+ //TODO add data for stats about emails opened clicked etc
2054
+ $this->data['subscribers'][$keysus]["emails"] = 0;
2055
+ $this->data['subscribers'][$keysus]["opened"] = 0;
2056
+ $this->data['subscribers'][$keysus]["clicked"] = 0;
2057
+
2058
+ if ($userlists) {
2059
+ foreach ($userlists as $key => $userlist) {
2060
+ if ($subscriber["user_id"] == $userlist["user_id"] && isset($lists[$userlist["list_id"]])) {
2061
+ if (!isset($this->data['subscribers'][$keysus]["lists"]))
2062
+ $this->data['subscribers'][$keysus]["lists"] = $lists[$userlist["list_id"]]["name"];
2063
+ else
2064
+ $this->data['subscribers'][$keysus]["lists"].=", " . $lists[$userlist["list_id"]]["name"];
2065
+ }
2066
+ }
2067
+ }
2068
+ }
2069
+
2070
+ $this->data['email'] = $email_object;
2071
+
2072
+ if (!$this->data['subscribers']) {
2073
+ $this->notice(__("Your request can't retrieve any subscribers. Change your filters!", WYSIJA));
2074
+ }
2075
+
2076
+ // execute hooks
2077
+ $hook_params = array(
2078
+ 'email_id' => $_REQUEST['id'],
2079
+ 'email_object' => $email_object,
2080
+ 'url_id' => !empty($_REQUEST['url_id']) ? (int)$_REQUEST['url_id'] : null,
2081
+ 'id' => $email_object['campaign_id']
2082
+ );
2083
+
2084
+ $this->data['hooks']['hook_newsletter_top'] = apply_filters('hook_newsletter_top', WYSIJA_module::execute_hook('hook_newsletter_top', $hook_params), $hook_params);
2085
+ $this->data['hooks']['hook_newsletter_bottom'] = apply_filters('hook_newsletter_bottom', WYSIJA_module::execute_hook('hook_newsletter_bottom', $hook_params), $hook_params);
2086
+ }
2087
+
2088
+ function getListSubscriberQry($selectcolumns) {
2089
+ $this->modelObj = WYSIJA::get("email", "model");
2090
+ $this->emailObj = $this->modelObj->getOne(false, array('email_id' => $_REQUEST['id']));
2091
+
2092
+ // use the filter if there is
2093
+ $this->setviewStatsfilter();
2094
+
2095
+ if ($selectcolumns == "B.user_id") {
2096
+ //unset($this->filters["like"]);
2097
+ }
2098
+
2099
+ $this->filters['equal']["B.email_id"] = $this->emailObj['email_id'];
2100
+ $this->modelObj->noCheck = true;
2101
+ if ($this->filters)
2102
+ $this->modelObj->setConditions($this->filters);
2103
+
2104
+ // select insert all the subscribers from that campaign into user_list
2105
+ if ($selectcolumns == "B.user_id") {
2106
+ $query = "SELECT $selectcolumns FROM `[wysija]" . $this->tableQuery . "` as B";
2107
+ $query.=$this->modelObj->makeWhere();
2108
+ } else {
2109
+ $query = "SELECT $selectcolumns FROM `[wysija]user` as A";
2110
+ $query.=" LEFT JOIN `[wysija]" . $this->tableQuery . "` as B on A.user_id=B.user_id";
2111
+ $query.=$this->modelObj->makeWhere();
2112
+ }
2113
+
2114
+ return $query;
2115
+ }
2116
+
2117
+ function createnewlist() {
2118
+
2119
+ $this->requireSecurity();
2120
+ // get the email subject
2121
+ $emailModel = WYSIJA::get('email', 'model');
2122
+ $email = $emailModel->getOne(array('subject'), array('email_id' => $_REQUEST['id']));
2123
+
2124
+ $this->modelObj->reset();
2125
+
2126
+ // set the name of the new list
2127
+ $prefix = "";
2128
+ if (isset($_REQUEST['link_filter']))
2129
+ $prefix = ' (' . $this->viewObj->getTransStatusEmail($_REQUEST['link_filter']) . ')';
2130
+ $listname = sprintf(__('Segment of %1$s', WYSIJA), $email['subject'] . $prefix);
2131
+
2132
+ // insert new list
2133
+ $modelL = WYSIJA::get('list', 'model');
2134
+ $listid = $modelL->insert(array('is_enabled' => 1, 'name' => $listname, 'description' => __('List created based on a newsletter segment.', WYSIJA)));
2135
+
2136
+ // get list of subscribers filtered or not
2137
+ $query = $this->getListSubscriberQry($listid . ', A.user_id, ' . time() . ', 0');
2138
+
2139
+ $query2 = 'INSERT INTO `[wysija]user_list` (`list_id`,`user_id`,`sub_date`,`unsub_date`) ' . $query;
2140
+
2141
+ $this->modelObj->query($query2);
2142
+
2143
+ $this->notice(sprintf(__('A new list "%1$s" has been created out of this segment.', WYSIJA), $listname));
2144
+ $this->redirect('admin.php?page=wysija_campaigns&action=viewstats&id=' . $_REQUEST['id']);
2145
+ }
2146
+
2147
+ function unsubscribeall() {
2148
+ // Update user_list, set unsubdate and sub_date
2149
+ $query = $this->getListSubscriberQry('B.user_id');
2150
+ $query1 = "
2151
+ UPDATE `[wysija]user_list`
2152
+ SET
2153
+ `unsub_date` = ".time().",
2154
+ `sub_date` = 0
2155
+ WHERE
2156
+ `user_id` IN ($query)
2157
+ AND `list_id` NOT IN (SELECT `list_id` FROM `[wysija]list` WHERE `is_enabled` < 1)
2158
+ ";
2159
+ $this->modelObj->query($query1);
2160
+
2161
+ // unsubscribe from user where select from email_user_stat
2162
+ $query2 = "UPDATE `[wysija]user` SET `status`=-1 WHERE `user_id` IN ($query)";
2163
+ $this->modelObj->query($query2);
2164
+
2165
+ $this->notice(__('The segment has been unsubscribed from all the lists.', WYSIJA));
2166
+ $this->redirect('admin.php?page=wysija_campaigns&action=viewstats&id=' . $_REQUEST['id']);
2167
+ }
2168
+
2169
+ function removequeue() {
2170
+ $this->requireSecurity();
2171
+ // delete from queue where select from email_user_stat
2172
+ $query = $this->getListSubscriberQry('B.user_id');
2173
+ $query2 = "DELETE FROM `[wysija]queue` where user_id IN ($query) AND email_id=" . $this->emailObj['email_id'];
2174
+ $this->modelObj->query($query2);
2175
+
2176
+ $this->notice(__('The segment has been removed from the queue of this newsletter.', WYSIJA));
2177
+ $this->redirect('admin.php?page=wysija_campaigns&action=viewstats&id=' . $_REQUEST['id']);
2178
+ }
2179
+
2180
+ function export() {
2181
+ $this->requireSecurity();
2182
+ // select from email_user_stat left join user
2183
+ $query = $this->getListSubscriberQry('B.user_id');
2184
+ $result = $this->modelObj->query('get_res', $query);
2185
+ $user_ids = array();
2186
+ foreach ($result as $user){
2187
+ $user_ids[] = $user['user_id'];
2188
+ }
2189
+
2190
+ $helper_file = WYSIJA::get('file', 'helper');
2191
+ $tempfilename = $helper_file->temp(implode(',', $user_ids), 'export_userids', '.txt');
2192
+
2193
+ $wpnonce = '&_wpnonce='.WYSIJA_view::secure(array('controller' => 'wysija_subscribers' , 'action' => 'exportcampaign' ), true);
2194
+
2195
+ $this->redirect('admin.php?page=wysija_subscribers&action=exportcampaign&camp_id=' . $_REQUEST['id'] .$wpnonce .'&file_name=' . base64_encode($tempfilename['name']));
2196
+ }
2197
+
2198
+ function unsubscribelist($data) {
2199
+ $this->requireSecurity();
2200
+ $modelL = WYSIJA::get('list', 'model');
2201
+ $list = $modelL->getOne(false, array('list_id' => $data['listid']));
2202
+ if ($list['is_enabled']) {
2203
+ /* delete from user_lists where select from email_user_stat */
2204
+ $query = $this->getListSubscriberQry("B.user_id");
2205
+ $query2 = "DELETE FROM `[wysija]user_list` where user_id IN ($query) and list_id=" . $data['listid'];
2206
+ $this->modelObj->query($query2);
2207
+
2208
+ $this->notice(sprintf(__('The segment has been unsubscribed from the list "%1$s".', WYSIJA), $list['name']));
2209
+ } else {
2210
+ $this->notice(sprintf(__('The segment cannot be unsubscribed from an [IMPORT] list.', WYSIJA), $list['name']));
2211
+ }
2212
+
2213
+ $this->redirect('admin.php?page=wysija_campaigns&action=viewstats&id=' . $_REQUEST['id']);
2214
+ }
2215
+
2216
+ function articles() {
2217
+ $this->iframeTabs = array('articles' => __("Post Selection", WYSIJA));
2218
+
2219
+ // required js files
2220
+ $this->js[] = 'wysija-admin-ajax';
2221
+ $this->js[] = 'wysija-base-script-64';
2222
+ $this->js[] = 'wysija-scriptaculous';
2223
+ $this->js[] = 'wysija-colorpicker';
2224
+ $this->js[] = 'mailpoet-select2';
2225
+ $this->js[] = 'mailpoet-field-select2-terms';
2226
+ $this->js[] = 'mailpoet-field-select2-simple';
2227
+
2228
+ // translations
2229
+ $this->jsTrans['show_advanced'] = __('Display and insert options', WYSIJA);
2230
+ $this->jsTrans['hide_advanced'] = __('Back to selection', WYSIJA);
2231
+ $this->jsTrans['loading_results'] = __('Loading results...', WYSIJA);
2232
+ $this->jsTrans['inserting_selection'] = __('Inserting selected articles...', WYSIJA);
2233
+ $this->jsTrans['post_selected'] = __('selected', WYSIJA);
2234
+
2235
+ // default tab in popup (this needs to be removed at some point)
2236
+ $_GET['tab'] = 'articles';
2237
+
2238
+ // get parameters
2239
+ $params = array(
2240
+ 'category_ids' => null,
2241
+ 'category' => null,
2242
+ 'title_tag' => 'h2',
2243
+ 'title_alignment' => 'left',
2244
+ 'title_position' => 'inside',
2245
+ 'image_alignment' => 'alternate',
2246
+ 'image_width' => 325,
2247
+ 'post_content' => 'excerpt',
2248
+ 'readmore' => __('Read more.', WYSIJA),
2249
+ 'show_divider' => 'yes',
2250
+ 'post_limit' => 5,
2251
+ 'post_type' => 'post',
2252
+ 'author_show' => 'no',
2253
+ 'author_label' => __('Author:', WYSIJA),
2254
+ 'category_show' => 'no',
2255
+ 'category_label' => __('Categories:', WYSIJA),
2256
+ 'nopost_message' => __('Latest content already sent.', WYSIJA),
2257
+ 'bgcolor1' => null,
2258
+ 'bgcolor2' => null,
2259
+ 'sort_by' => 'newest'
2260
+ );
2261
+
2262
+ // check if GET parameters are specified
2263
+ foreach($params as $key => $value) {
2264
+ if(array_key_exists($key, $_GET)) {
2265
+ switch($key) {
2266
+ case 'autopost_count':
2267
+ $params[$key] = (int)$_GET[$key];
2268
+ break;
2269
+ case 'readmore':
2270
+ case 'nopost_message':
2271
+ $params[$key] = base64_decode($_GET[$key]);
2272
+ break;
2273
+ default:
2274
+ $params[$key] = $_GET[$key];
2275
+ }
2276
+ }
2277
+ }
2278
+
2279
+ $model_config = WYSIJA::get('config', 'model');
2280
+ $insert_post_parameters = $model_config->getValue('insert_post_parameters');
2281
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
2282
+
2283
+ if($insert_post_parameters !== false) {
2284
+ // there are user params
2285
+ $params = $helper_wj_engine->decodeParameters(array_merge($params, $insert_post_parameters));
2286
+ }
2287
+
2288
+ // get autopost count
2289
+ $this->data['autopost_count'] = (array_key_exists('autopost_count', $_GET)) ? (int) $_GET['autopost_count'] : 0;
2290
+
2291
+ // get autopost type (single or multiple)
2292
+ $this->data['autopost_type'] = (array_key_exists('autopost_type', $_GET)) ? $_GET['autopost_type'] : 'multiple';
2293
+
2294
+ // if only one group of post can be added, change default alignment to left
2295
+ if($this->data['autopost_type'] === 'single' && $params['image_alignment'] === 'alternate') {
2296
+ $params['image_alignment'] = 'left';
2297
+ }
2298
+
2299
+ // get post categories (even when there's no post)
2300
+ $post_categories = get_categories(array('hide_empty' => 0));
2301
+ $categories = array();
2302
+ foreach ($post_categories as $category) {
2303
+ $categories[] = array('id' => $category->cat_ID, 'name' => $category->name);
2304
+ }
2305
+ $this->data['categories'] = $categories;
2306
+
2307
+ // max number of posts
2308
+ $this->data['post_limits'] = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 50);
2309
+
2310
+ $this->data['params'] = $params;
2311
+
2312
+ return $this->popupContent();
2313
+ }
2314
+
2315
+ function themeupload() {
2316
+ $this->requireSecurity();
2317
+ $helperNumbers = WYSIJA::get('numbers', 'helper');
2318
+ $bytes = $helperNumbers->get_max_file_upload();
2319
+
2320
+ if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > $bytes['maxbytes']) {
2321
+ if (isset($_FILES['my-theme']['name']) && $_FILES['my-theme']['name']) {
2322
+ $filename = $_FILES['my-theme']['name'];
2323
+ } else {
2324
+ $filename = "";
2325
+ }
2326
+
2327
+ $this->error(sprintf(__('Upload error, file %1$s is too large! (MAX:%2$s)', WYSIJA), $filename, $bytes['maxmegas']), true);
2328
+ $this->redirect('admin.php?page=wysija_campaigns&action=themes');
2329
+
2330
+ return false;
2331
+ }
2332
+
2333
+ if (!$_FILES['my-theme']['tmp_name'] || !is_file($_FILES['my-theme']['tmp_name'])) {
2334
+ $this->error(__('This file is empty. Please try another.', WYSIJA));
2335
+ $this->redirect('admin.php?page=wysija_campaigns&action=themes');
2336
+ return false;
2337
+ }
2338
+
2339
+ $ZipfileResult = trim(file_get_contents($_FILES['my-theme']['tmp_name']));
2340
+
2341
+ $themesHelp = WYSIJA::get('themes', 'helper');
2342
+ $result = $themesHelp->installTheme($_FILES['my-theme']['tmp_name'], true);
2343
+ $this->redirect('admin.php?page=wysija_campaigns&action=themes&reload=1');
2344
+
2345
+ return true;
2346
+ }
2347
+
2348
+ function themes() {
2349
+ $this->iframeTabs = array('themes' => __('Install Themes', WYSIJA));
2350
+ $this->js[] = 'wysija-admin-ajax';
2351
+ $this->js[] = 'wysija-base-script-64';
2352
+ $this->jsTrans['viewinfos'] = __('Details & PSD', WYSIJA);
2353
+ $this->jsTrans['viewback'] = __('<< Back', WYSIJA);
2354
+ $this->jsTrans['install'] = __('Download', WYSIJA);
2355
+ $this->jsTrans['reinstall'] = __('Reinstall', WYSIJA);
2356
+ $this->jsTrans['premiumonly'] = __('Premium', WYSIJA);
2357
+
2358
+ $model_config = WYSIJA::get('config', 'model');
2359
+ //change the translation of the button when it's premium
2360
+ if ($model_config->getValue('premium_key'))
2361
+ $this->jsTrans['ispremium'] = 1;
2362
+ else
2363
+ $this->jsTrans['ispremium'] = 0;
2364
+
2365
+ $this->jsTrans['premiumfiles'] = __('Photoshop file available as part of [link]Premium features[/link].', WYSIJA);
2366
+
2367
+ $helper_licence = WYSIJA::get('licence', 'helper');
2368
+ $url_checkout = $helper_licence->get_url_checkout('themes');
2369
+ $this->jsTrans['premiumfiles'] = str_replace(array('[link]', '[/link]'), array('<a href="' . $url_checkout . '" target="_blank" >', '</a>'), $this->jsTrans['premiumfiles']);
2370
+
2371
+ $this->jsTrans['showallthemes'] = __('Show all themes', WYSIJA);
2372
+ $this->jsTrans['totalvotes'] = __('(%1$s votes)', WYSIJA);
2373
+ $this->jsTrans['voterecorded'] = __("Your vote has been recorded.", WYSIJA);
2374
+ $this->jsTrans['votenotrecorded'] = __("Your vote could not be recorded.", WYSIJA);
2375
+ $this->jsTrans['reinstallwarning'] = __('Watch out! If you reinstall this theme all the files which are in the folder:/wp-content/uploads/wysija/themes/%1$s will be overwritten. Are you sure you want to reinstall?', WYSIJA);
2376
+ $this->jsTrans['errorconnecting'] = __("We were unable to contact the API, the site may be down. Please try again later.", WYSIJA);
2377
+
2378
+ $this->jsTrans['viewallthemes'] = __('View all themes by %1$s', WYSIJA);
2379
+ $this->jsTrans['downloadpsd'] = __("Download original Photoshop file", WYSIJA);
2380
+ $this->jsTrans['downloadzip'] = __("Download as .zip", WYSIJA);
2381
+ $this->jsTrans['viewauthorsite'] = __("View author's website", WYSIJA);
2382
+ $this->jsTrans['stars'] = __('Average rating: %1$s', WYSIJA);
2383
+ $this->jsTrans['starsyr'] = __('My rating: %1$s', WYSIJA);
2384
+ $this->jsTrans['downloads'] = __('Downloads: %1$s', WYSIJA);
2385
+ $this->jsTrans['tags'] = __('Tags: %1$s', WYSIJA);
2386
+ $this->jsTrans['lastupdated'] = __('Last updated: %1$s', WYSIJA);
2387
+ $this->jsTrans['includes'] = __('Includes: %1$s', WYSIJA);
2388
+
2389
+ $helper_themes = WYSIJA::get('themes', 'helper');
2390
+
2391
+ $this->jsTrans['installedthemes'] = $helper_themes->getInstalled();
2392
+
2393
+ $url = admin_url('admin.php');
2394
+ $helper_toolbox = WYSIJA::get("toolbox", "helper");
2395
+ $domain_name = $helper_toolbox->_make_domain_name($url);
2396
+ $this->jsTrans['domainname'] = $domain_name;
2397
+
2398
+ $_GET['tab'] = 'themes';
2399
+
2400
+ return $this->popupContent();
2401
+ }
2402
+
2403
+ function bookmarks() {
2404
+ $this->iframeTabs = array('bookmarks' => __('Bookmarks Selection', WYSIJA));
2405
+ $this->js[] = 'wysija-admin-ajax';
2406
+
2407
+ $_GET['tab'] = 'bookmarks';
2408
+
2409
+ $networks = array(
2410
+ 'facebook' => array(
2411
+ 'label' => 'Facebook',
2412
+ 'url' => null,
2413
+ 'placeholder' => 'https://www.facebook.com/mailpoetplugin'
2414
+ ),
2415
+ 'twitter' => array(
2416
+ 'label' => 'Twitter',
2417
+ 'url' => null,
2418
+ 'placeholder' => 'http://www.twitter.com/mail_poet'
2419
+ ),
2420
+ 'google' => array(
2421
+ 'label' => 'Google+',
2422
+ 'url' => null,
2423
+ 'placeholder' => null
2424
+ ),
2425
+ 'linkedin' => array(
2426
+ 'label' => 'LinkedIn',
2427
+ 'url' => null,
2428
+ 'placeholder' => null
2429
+ )
2430
+ );
2431
+
2432
+ // get networks' url from config
2433
+ $model_config = WYSIJA::get('config', 'model');
2434
+ $urls = $model_config->getValue('social_bookmarks');
2435
+
2436
+ // set url from config for each network if specified
2437
+ foreach ($networks as $network => $values) {
2438
+ if (isset($urls[$network]) and strlen(trim($urls[$network])) > 0) {
2439
+ $networks[$network]['url'] = $urls[$network];
2440
+ }
2441
+ }
2442
+
2443
+ $this->data['networks'] = $networks;
2444
+ $this->data['size'] = 'medium';
2445
+ $this->data['theme'] = isset($_REQUEST['theme']) ? $_REQUEST['theme'] : 'default';
2446
+
2447
+ return $this->popupContent();
2448
+ }
2449
+
2450
+ function dividers() {
2451
+ $this->iframeTabs = array('dividers' => __("Dividers Selection", WYSIJA));
2452
+ $this->js[] = 'wysija-admin-ajax';
2453
+ $this->js[] = 'wysija-base-script-64';
2454
+
2455
+ $_GET['tab'] = 'dividers';
2456
+
2457
+ $model_email = WYSIJA::get('email', 'model');
2458
+ $this->data['email'] = $email = $model_email->getOne(false, array('email_id' => $_REQUEST['emailId']));
2459
+
2460
+ // get dividers
2461
+ $helper_dividers = WYSIJA::get('dividers', 'helper');
2462
+ $dividers = $helper_dividers->getAll();
2463
+
2464
+ // get theme divider if it's not the default theme
2465
+ if (isset($email['params']['theme'])) {
2466
+ $helper_themes = WYSIJA::get('themes', 'helper');
2467
+ $themeDivider = $helper_themes->getDivider($email['params']['theme']);
2468
+ if ($themeDivider !== NULL) {
2469
+ array_unshift($dividers, $themeDivider);
2470
+ }
2471
+ }
2472
+
2473
+ // get selected divider
2474
+ if (isset($email['params']['divider'])) {
2475
+ $selected_divider = $email['params']['divider'];
2476
+ } else {
2477
+ $helper_dividers = WYSIJA::get('dividers', 'helper');
2478
+ $selected_divider = $helper_dividers->getDefault();
2479
+ }
2480
+
2481
+ // set selected divider in first position
2482
+ array_unshift($dividers, $selected_divider);
2483
+
2484
+ // remove selected divider if present in the list
2485
+ for ($i = 1; $i < count($dividers); $i++) {
2486
+ if ($dividers[$i]['src'] === $selected_divider['src']) {
2487
+ unset($dividers[$i]);
2488
+ break;
2489
+ }
2490
+ }
2491
+
2492
+ $this->data['selected'] = $selected_divider;
2493
+ $this->data['dividers'] = $dividers;
2494
+ return $this->popupContent();
2495
+ }
2496
+
2497
+ function autopost() {
2498
+ $this->iframeTabs = array('autopost' => __("Add / Edit group of posts", WYSIJA));
2499
+ $this->js[] = 'wysija-admin-ajax';
2500
+ $this->js[] = 'wysija-base64';
2501
+ $this->js[] = 'wysija-scriptaculous';
2502
+ $this->js[] = 'wysija-colorpicker';
2503
+ $this->js[] = 'mailpoet-select2';
2504
+ $this->js[] = 'mailpoet-field-select2-terms';
2505
+
2506
+ // translations
2507
+ $this->jsTrans['show_advanced'] = __('Show display options', WYSIJA);
2508
+ $this->jsTrans['hide_advanced'] = __('Hide display options', WYSIJA);
2509
+
2510
+ $_GET['tab'] = 'autopost';
2511
+
2512
+ // get parameters
2513
+ $params = array(
2514
+ 'category_ids' => null,
2515
+ 'category_condition' => 'include',
2516
+ 'title_tag' => 'h2',
2517
+ 'title_alignment' => 'left',
2518
+ 'title_position' => 'inside',
2519
+ 'image_alignment' => 'alternate',
2520
+ 'image_width' => 325,
2521
+ 'post_content' => 'excerpt',
2522
+ 'readmore' => __('Read more.', WYSIJA),
2523
+ 'show_divider' => 'yes',
2524
+ 'post_limit' => 5,
2525
+ 'post_type' => 'post',
2526
+ 'author_show' => 'no',
2527
+ 'author_label' => __('Author:', WYSIJA),
2528
+ 'category_show' => 'no',
2529
+ 'category_label' => __('Categories:', WYSIJA),
2530
+ 'nopost_message' => __('Latest content already sent.', WYSIJA),
2531
+ 'bgcolor1' => null,
2532
+ 'bgcolor2' => null,
2533
+ 'sort_by' => 'newest'
2534
+ );
2535
+
2536
+ // backwards compatibility since we replaced the 'cpt' parameter by 'post_type' in 2.6
2537
+ if(isset($_GET['cpt']) && strlen(trim($_GET['cpt'])) > 0) {
2538
+ $params['post_type'] = trim($_GET['cpt']);
2539
+ }
2540
+
2541
+ // check if GET parameters are specified
2542
+ foreach ($params as $key => $value) {
2543
+ if (array_key_exists($key, $_GET)) {
2544
+ switch ($key) {
2545
+ case 'autopost_count':
2546
+ $params[$key] = (int)$_GET[$key];
2547
+ break;
2548
+ case 'author_label':
2549
+ case 'category_label':
2550
+ case 'readmore':
2551
+ case 'nopost_message':
2552
+ $params[$key] = base64_decode($_GET[$key]);
2553
+ break;
2554
+ default:
2555
+ $params[$key] = trim($_GET[$key]);
2556
+ }
2557
+ }
2558
+ }
2559
+
2560
+ // get autopost count
2561
+ $this->data['autopost_count'] = (array_key_exists('autopost_count', $_GET)) ? (int) $_GET['autopost_count'] : 0;
2562
+
2563
+ // get autopost type (single or multiple)
2564
+ $this->data['autopost_type'] = (array_key_exists('autopost_type', $_GET)) ? $_GET['autopost_type'] : 'multiple';
2565
+
2566
+ // if only one group of post can be added, change default alignment to left
2567
+ if ($this->data['autopost_type'] === 'single') {
2568
+ if ($params['image_alignment'] === 'alternate')
2569
+ $params['image_alignment'] = 'left';
2570
+ }
2571
+
2572
+ // we use that now, because categories from a post are different than categories from a CPT
2573
+ // $helper_wp_tools = WYSIJA::get('wp_tools','helper');
2574
+ // $this->data['categories'] = $helper_wp_tools->get_categories();
2575
+
2576
+ // max number of posts
2577
+ $this->data['post_limits'] = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 50);
2578
+
2579
+ $this->data['params'] = $params;
2580
+
2581
+ return $this->popupContent();
2582
+ }
2583
+
2584
+ function image_data() {
2585
+ $this->data['url'] = (isset($_GET['url']) && $_GET['url'] !== '') ? trim(urldecode($_GET['url'])) : null;
2586
+ $this->data['alt'] = (isset($_GET['alt'])) ? trim(urldecode($_GET['alt'])) : '';
2587
+
2588
+ $this->iframeTabs = array('image_data' => __("Image Parameters", WYSIJA));
2589
+ $_GET['tab'] = 'image_data';
2590
+ return $this->popupContent();
2591
+ }
2592
+
2593
+ function medias() {
2594
+ $this->popupContent();
2595
+ }
2596
+
2597
+ function special_wysija_browse() {
2598
+ $this->_wysija_subaction();
2599
+ $this->jsTrans['deleteimg'] = __('Delete image for all newsletters?', WYSIJA);
2600
+ return wp_iframe(array($this->viewObj, 'popup_wysija_browse'), array());
2601
+ }
2602
+
2603
+ function special_wordp_browse() {
2604
+ $this->_wysija_subaction();
2605
+ $this->jsTrans['deleteimg'] = __('This image might be in an article. Delete anyway?', WYSIJA);
2606
+ return wp_iframe(array($this->viewObj, 'popup_wp_browse'), array());
2607
+ }
2608
+
2609
+ function special_new_wordp_upload() {
2610
+ wp_enqueue_script('wysija-plupload-handlers', WYSIJA_URL . 'js/jquery/pluploadHandler.js', array('plupload-all', 'jquery'));
2611
+ $uploader_l10n = array(
2612
+ 'queue_limit_exceeded' => __('You have attempted to queue too many files.'),
2613
+ 'file_exceeds_size_limit' => __('%s exceeds the maximum upload size for this site.'),
2614
+ 'zero_byte_file' => __('This file is empty. Please try another.'),
2615
+ 'invalid_filetype' => __('This file type is not allowed. Please try another.'),
2616
+ 'not_an_image' => __('This file is not an image. Please try another.'),
2617
+ 'image_memory_exceeded' => __('Memory exceeded. Please try another smaller file.'),
2618
+ 'image_dimensions_exceeded' => __('This is larger than the maximum size. Please try another.'),
2619
+ 'default_error' => __('An error occurred in the upload. Please try again later.'),
2620
+ 'missing_upload_url' => __('There was a configuration error. Please contact the server administrator.'),
2621
+ 'upload_limit_exceeded' => __('You may only upload 1 file.'),
2622
+ 'http_error' => __('HTTP error.'),
2623
+ 'upload_failed' => __('Upload failed.'),
2624
+ 'big_upload_failed' => __('Please try uploading this file with the %1$sbrowser uploader%2$s.'),
2625
+ 'big_upload_queued' => __('%s exceeds the maximum upload size for the multi-file uploader when used in your browser.'),
2626
+ 'io_error' => __('IO error.'),
2627
+ 'security_error' => __('Security error.'),
2628
+ 'file_cancelled' => __('File canceled.'),
2629
+ 'upload_stopped' => __('Upload stopped.'),
2630
+ 'dismiss' => __('Dismiss'),
2631
+ 'crunching' => __('Crunching&hellip;'),
2632
+ 'deleted' => __('moved to the trash.'),
2633
+ 'error_uploading' => __('&#8220;%s&#8221; has failed to upload.'),
2634
+ 'files_successfully_uploaded' => __('%d file(s) have been successfully uploaded.')
2635
+ );
2636
+
2637
+ wp_localize_script('wysija-plupload-handlers', 'pluploadL10n', $uploader_l10n);
2638
+
2639
+ wp_enqueue_script('image-edit');
2640
+ wp_enqueue_script('set-post-thumbnail');
2641
+ wp_enqueue_style('imgareaselect');
2642
+ wp_enqueue_script('media-gallery');
2643
+
2644
+ $errors = array();
2645
+ return wp_iframe(array($this->viewObj, 'popup_new_wp_upload'), $errors);
2646
+ }
2647
+
2648
+ function _checkEmailExists($emailId) {
2649
+ $result = false;
2650
+ $model_email = WYSIJA::get('email', 'model');
2651
+
2652
+ if ($model_email->exists(array('email_id' => $emailId))){
2653
+ $result = true;
2654
+ }
2655
+
2656
+ if (!$result) {
2657
+ $this->error(__("The newsletter doesn't exist.", WYSIJA), 1);
2658
+ $this->redirect('admin.php?page=wysija_campaigns');
2659
+ }else{
2660
+ return true;
2661
+ }
2662
+
2663
+ }
2664
+
2665
+ }
trunk/controllers/back/config.php ADDED
@@ -0,0 +1,377 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_control_back_config extends WYSIJA_control_back{
4
+ var $view='config';
5
+ var $model='config';
6
+
7
+ function __construct(){
8
+ parent::__construct();
9
+ }
10
+
11
+ function main() {
12
+ parent::__construct();
13
+ wp_enqueue_style('thickbox');
14
+
15
+ if(!isset($_REQUEST['action'])) $this->action='main';
16
+ else $this->action=$_REQUEST['action'];
17
+ $this->jsTrans['testemail'] = __('Sending a test email', WYSIJA);
18
+ $this->jsTrans['bounceconnect'] = __('Bounce handling connection test', WYSIJA);
19
+ $this->jsTrans['processbounceT'] = __('Bounce handling processing', WYSIJA);
20
+ $this->jsTrans['doubleoptinon'] = __('Subscribers will now need to activate their subscription by email in order to receive your newsletters. This is recommended.', WYSIJA);
21
+ $this->jsTrans['doubleoptinoff'] = __('Unconfirmed subscribers will receive your newsletters from now on without the need to activate their subscriptions.', WYSIJA);
22
+ $this->jsTrans['processbounce'] = __('Process bounce handling now!', WYSIJA);
23
+ $this->jsTrans['errorbounceforward'] = __('When setting up the bounce system, you need to have a different address for the bounce email and the forward to address', WYSIJA);
24
+
25
+ // form list
26
+ $this->jsTrans['suredelete'] = __('Are you sure you want to delete this form?', WYSIJA);
27
+
28
+ switch($this->action) {
29
+ case 'log':
30
+ case 'save':
31
+ case 'clearlog':
32
+ wp_enqueue_script('wysija-config-settings', WYSIJA_URL.'js/admin-config-settings.js', array('wysija-admin-js-global'), WYSIJA::get_version());
33
+ wp_localize_script('wysija-config-settings', 'mpEmailCheck', WJ_Utils::get_tip_data());
34
+ wp_enqueue_script('jquery-cookie', WYSIJA_URL.'js/jquery/jquery.cookie.js', array('jquery'), WYSIJA::get_version());
35
+ case 'form_add':
36
+ case 'form_edit':
37
+ case 'form_duplicate':
38
+ case 'form_delete':
39
+ case 'form_widget_settings':
40
+ case 'form_add_field':
41
+ return $this->{$this->action}();
42
+ break;
43
+ case 'reinstall':
44
+ $this->reinstall();
45
+ return;
46
+ break;
47
+ case 'dkimcheck':
48
+ $this->dkimcheck();
49
+ if(defined('WYSIJA_REDIRECT')) $this->redirectProcess();
50
+ return;
51
+ break;
52
+ case 'doreinstall':
53
+ $this->doreinstall();
54
+ if(defined('WYSIJA_REDIRECT')){
55
+ global $wysi_location;
56
+ $wysi_location='admin.php?page=wysija_campaigns';
57
+ $this->redirectProcess();
58
+ }
59
+ return;
60
+ break;
61
+ default:
62
+ wp_enqueue_script( 'mailpoet.tooltip', WYSIJA_URL . 'js/vendor/bootstrap.tooltip.js', array( 'jquery' ), WYSIJA::get_version(), true );
63
+ wp_enqueue_style( 'mailpoet.tooltip', WYSIJA_URL . 'css/vendor/bootstrap.tooltip.css', array(), WYSIJA::get_version(), 'screen' );
64
+ wp_enqueue_script('wysija-config-settings', WYSIJA_URL.'js/admin-config-settings.js', array('wysija-admin-js-global'), WYSIJA::get_version(), true);
65
+ wp_localize_script('wysija-config-settings', 'mpEmailCheck', WJ_Utils::get_tip_data());
66
+ wp_enqueue_script('jquery-cookie', WYSIJA_URL.'js/jquery/jquery.cookie.js', array('jquery'), WYSIJA::get_version());
67
+ }
68
+
69
+ if(WYSIJA_DBG > 1) {
70
+ $this->viewObj->arrayMenus = array('log' => 'View log');
71
+ }
72
+
73
+ $this->data = array();
74
+ $hook_settings_super_advanced_params = array();
75
+ $this->data['hooks']['hook_settings_super_advanced'] = apply_filters('hook_settings_super_advanced',WYSIJA_module::execute_hook('hook_settings_super_advanced', $hook_settings_super_advanced_params), $hook_settings_super_advanced_params);
76
+ $this->action='main';
77
+
78
+ if(isset($_REQUEST['validate'])){
79
+ $this->notice(str_replace(array('[link]','[/link]'),
80
+ array('<a title="'.__('Get Premium now',WYSIJA).'" class="premium-activate" href="javascript:;">','</a>'),
81
+ __('You\'re almost there. Click this [link]link[/link] to activate the licence you have just purchased.',WYSIJA)));
82
+
83
+ }
84
+
85
+ }
86
+
87
+ function dkimcheck(){
88
+ if(isset($_POST['xtz'])){
89
+
90
+ $dataconf=json_decode(base64_decode($_POST['xtz']));
91
+ if(isset($dataconf->dkim_pubk->key) && isset($dataconf->dkim_privk)){
92
+ $modelConf=WYSIJA::get('config','model');
93
+ $dataconfsave=array('dkim_pubk'=>$dataconf->dkim_pubk->key, 'dkim_privk'=>$dataconf->dkim_privk,'dkim_1024'=>1);
94
+
95
+ $modelConf->save($dataconfsave);
96
+ WYSIJA::update_option('dkim_autosetup',false);
97
+ }
98
+ }
99
+
100
+ $this->redirect('admin.php?page=wysija_config');
101
+ return true;
102
+ }
103
+
104
+ function save(){
105
+ $_REQUEST = stripslashes_deep($_REQUEST);
106
+ $_POST = stripslashes_deep($_POST);
107
+ $this->requireSecurity();
108
+
109
+ $hook_settings_before_save = array(
110
+ 'REQUEST' =>& $_REQUEST
111
+ );
112
+ apply_filters('hook_settings_before_save',WYSIJA_module::execute_hook('hook_settings_before_save', $hook_settings_before_save),$hook_settings_before_save);
113
+
114
+ $this->modelObj->save($_REQUEST['wysija']['config'],true);
115
+
116
+ $hook_settings_super_advanced_params = array();
117
+ $this->data['hooks']['hook_settings_super_advanced'] = apply_filters('hook_settings_super_advanced',WYSIJA_module::execute_hook('hook_settings_super_advanced', $hook_settings_super_advanced_params),$hook_settings_super_advanced_params);
118
+ // redirect so that javascript values get updated
119
+ wp_redirect('admin.php?page=wysija_config'.$_REQUEST['redirecttab']);
120
+ }
121
+
122
+ function reinstall(){
123
+ $this->viewObj->title=__('Reinstall MailPoet?',WYSIJA);
124
+ return true;
125
+ }
126
+
127
+ function doreinstall(){
128
+ $this->requireSecurity();
129
+ if(isset($_REQUEST['postedfrom']) && $_REQUEST['postedfrom'] === 'reinstall') {
130
+ $uninstaller=WYSIJA::get('uninstall','helper');
131
+ $uninstaller->reinstall();
132
+ }
133
+ $this->redirect('admin.php?page=wysija_config');
134
+ return true;
135
+ }
136
+
137
+ function render(){
138
+ $this->checkTotalSubscribers();
139
+ $this->viewObj->render($this->action,$this->data);
140
+ }
141
+
142
+ function log(){
143
+ $this->viewObj->arrayMenus=array('clearlog'=>'Clear log');
144
+ $this->viewObj->title='MailPoet\'s log';
145
+ return true;
146
+ }
147
+
148
+ function clearlog(){
149
+ $this->requireSecurity();
150
+ update_option('wysija_log', array());
151
+ $this->redirect('admin.php?page=wysija_config&action=log');
152
+ return true;
153
+ }
154
+
155
+ // WYSIJA Form Editor
156
+ function form_add() {
157
+ $this->requireSecurity();
158
+ $helper_form_engine = WYSIJA::get('form_engine', 'helper');
159
+ // set default form data
160
+ $helper_form_engine->set_data();
161
+
162
+ // create form in database with default data
163
+ $form = array('name' => __('New Form', WYSIJA));
164
+
165
+ // insert into form table
166
+ $model_forms = WYSIJA::get('forms', 'model');
167
+ $form_id = $model_forms->insert($form);
168
+
169
+ if($form_id !== null && (int)$form_id > 0) {
170
+ // merge form_id into form data for later use
171
+ $data = array_merge(array('form_id' => $form_id), $helper_form_engine->get_data());
172
+ // update form data in form engine
173
+ $helper_form_engine->set_data($data);
174
+ // update form data in database
175
+ $model_forms->update(array('data' => $helper_form_engine->get_encoded('data')), array('form_id' => (int)$form_id));
176
+
177
+ // redirect to form editor, passing along the newly created form id
178
+ WYSIJA::redirect('admin.php?page=wysija_config&action=form_edit&id='.$form_id);
179
+ } else {
180
+ WYSIJA::redirect('admin.php?page=wysija_config#tab-forms');
181
+ }
182
+ return true;
183
+ }
184
+
185
+ function form_duplicate() {
186
+ $this->requireSecurity();
187
+ if(isset($_GET['id']) && (int)$_GET['id'] > 0) {
188
+ $form_id = (int)$_GET['id'];
189
+
190
+ $model_forms = WYSIJA::get('forms', 'model');
191
+
192
+ // get form data
193
+ $form = $model_forms->getOne(array('name', 'data', 'styles'), array('form_id' => $form_id));
194
+
195
+ if(empty($form)) {
196
+ $this->error(__('This form does not exist', WYSIJA), true);
197
+ } else {
198
+ // reset model forms
199
+ $model_forms->reset();
200
+
201
+ // add "copy" to the name
202
+ $form['name'] = $form['name'].' - '.__('Copy', WYSIJA);
203
+
204
+ // insert form (duplicated)
205
+ $model_forms->insert($form);
206
+
207
+ // display notice
208
+ $this->notice(sprintf(__('The form named "%1$s" has been created.', WYSIJA), $form['name']));
209
+ }
210
+ }
211
+
212
+ WYSIJA::redirect('admin.php?page=wysija_config#tab-forms');
213
+ }
214
+
215
+ function form_delete() {
216
+
217
+ $this->requireSecurity();
218
+
219
+ if(isset($_GET['id']) && (int)$_GET['id'] > 0) {
220
+ $form_id = (int)$_GET['id'];
221
+
222
+ $model_forms = WYSIJA::get('forms', 'model');
223
+
224
+ // get form data
225
+ $form = $model_forms->getOne(array('name'), array('form_id' => $form_id));
226
+
227
+ if(empty($form)) {
228
+ $this->error(__('This form has already been deleted.', WYSIJA), true);
229
+ } else {
230
+ // delete the form in the database
231
+ $model_forms->reset();
232
+ $model_forms->delete(array('form_id' => $form_id));
233
+
234
+ // display notice
235
+ $this->notice(sprintf(__('The form named "%1$s" has been deleted.', WYSIJA), $form['name']));
236
+ }
237
+ }
238
+
239
+ WYSIJA::redirect('admin.php?page=wysija_config#tab-forms');
240
+ }
241
+
242
+ function form_edit() {
243
+ // define whether the form can be edited
244
+ $this->data['can_edit'] = true;
245
+
246
+ // wysija form editor javascript files
247
+ $this->js[]='wysija-form-editor';
248
+ $this->js[]='wysija-admin-ajax-proto';
249
+ // $this->js[]='wysija-admin-ajax';
250
+ $this->js[]='wysija-base-script-64';
251
+ $this->js[] = 'mailpoet-select2';
252
+
253
+ // make sure the editor content is not cached
254
+ //header('Cache-Control: no-cache, max-age=0, must-revalidate, no-store'); // HTTP/1.1
255
+ //header('Expires: Fri, 9 Mar 1984 00:00:00 GMT');
256
+
257
+ // get form id
258
+ $form_id = (isset($_REQUEST['id']) && (int)$_REQUEST['id'] > 0) ? (int)$_REQUEST['id'] : null;
259
+ $form = array('name' => __('New form', WYSIJA));
260
+
261
+ // if no form id was specified, then it's a new form
262
+ if($form_id !== null) {
263
+ // try to get form data based on form id
264
+ $model_forms = WYSIJA::get('forms', 'model');
265
+ $form = $model_forms->getOne($form_id);
266
+
267
+ // if the form does not exist
268
+ if(empty($form)) {
269
+ // redirect to forms list
270
+ $this->error(__('This form does not exist.', WYSIJA), true);
271
+ WYSIJA::redirect('admin.php?page=wysija_config#tab-forms');
272
+ } else {
273
+ // pass form id to the view
274
+ $this->data['form_id'] = (int)$form['form_id'];
275
+ }
276
+ }
277
+ // pass form to the view
278
+ $this->data['form'] = $form;
279
+
280
+ $helper_form_engine = WYSIJA::get('form_engine', 'helper');
281
+ $lists = $helper_form_engine->get_lists();
282
+ $this->data['lists'] = $lists;
283
+
284
+ // disable editing capability when there is no list
285
+ if(empty($lists)) {
286
+ $this->data['can_edit'] = false;
287
+ }
288
+
289
+ // get custom fields
290
+ $this->data['custom_fields'] = $helper_form_engine->get_custom_fields();
291
+
292
+ // translations
293
+ $this->jsTrans = array_merge($this->jsTrans, $helper_form_engine->get_translations());
294
+ }
295
+
296
+ /*
297
+ * Handles the settings popup of wysija form widgets
298
+ */
299
+ function form_widget_settings() {
300
+ $this->iframeTabs = array('form_widget_settings' => __('Widget Settings', WYSIJA));
301
+ $this->js[] = 'wysija-admin-ajax';
302
+ $this->js[] = 'wysija-base-script-64';
303
+ $this->js[] = 'wysija-scriptaculous';
304
+
305
+ $_GET['tab'] = 'form_widget_settings';
306
+
307
+ // if there is a field id, let's get all that from this field
308
+ if(isset($_REQUEST['field_id'])) {
309
+ $field_id = ((int)$_REQUEST['field_id'] > 0) ? (int)$_REQUEST['field_id'] : 0;
310
+
311
+ // if the id is positive then try to fetch field data
312
+ $custom_field = WJ_Field::get($field_id);
313
+
314
+ // if field has been found
315
+ if($custom_field !== NULL) {
316
+ $this->data['name'] = (isset($_REQUEST['name'])) ? $_REQUEST['name'] : $custom_field->name;
317
+ $this->data['type'] = (isset($_REQUEST['type'])) ? $_REQUEST['type'] : $custom_field->type;
318
+ $this->data['field'] = $custom_field->user_column_name();
319
+ $this->data['params'] = $custom_field->settings;
320
+ } else {
321
+ $this->data['name'] = (isset($_REQUEST['name'])) ? $_REQUEST['name'] : null;
322
+ $this->data['type'] = (isset($_REQUEST['type'])) ? $_REQUEST['type'] : null;
323
+ $this->data['field'] = null;
324
+ $this->data['params'] = null;
325
+ }
326
+
327
+ $this->data['field_id'] = $field_id;
328
+ } else {
329
+ // extract parameters from url
330
+ $params = array();
331
+ if(isset($_REQUEST['params']) && trim(strlen($_REQUEST['params'])) > 0) {
332
+ $pairs = explode('|', $_REQUEST['params']);
333
+ if(count($pairs) > 0) {
334
+ foreach($pairs as $pair) {
335
+ // extract both key and value
336
+ list($key, $value) = explode(':', $pair);
337
+
338
+ // decode value
339
+ $value = base64_decode($value);
340
+ // unserialize if necessary (using is_serialized from WordPress) and making sure we only unserialize arrays not objects
341
+ if(is_serialized($value) === true && preg_match('/^a:[0-9]+:{/', $value) && !preg_match('/(^|;|{|})O:\+?[0-9]+:"/', $value) ) {
342
+ $value = (array) unserialize($value);
343
+ }
344
+ $params[$key] = $value;
345
+ }
346
+ }
347
+ }
348
+
349
+ // common widget data
350
+ $this->data['name'] = (isset($_REQUEST['name'])) ? $_REQUEST['name'] : null;
351
+ $this->data['type'] = (isset($_REQUEST['type'])) ? $_REQUEST['type'] : null;
352
+ $this->data['field'] = (isset($_REQUEST['field'])) ? $_REQUEST['field'] : null;
353
+
354
+ // widget params
355
+ $this->data['params'] = $params;
356
+
357
+ // extra data that needs to be fetched for some widget
358
+ $extra = array();
359
+
360
+ switch($this->data['type']) {
361
+ // in case of the list widget, we need to pass an array of all available lists
362
+ case 'list':
363
+ $model_list = WYSIJA::get('list', 'model');
364
+
365
+ // get lists users can subscribe to (aka "enabled list")
366
+ $extra['lists'] = $model_list->get(array('name', 'list_id', 'is_public'), array('is_enabled' => 1));
367
+ break;
368
+ }
369
+
370
+ $this->data['extra'] = $extra;
371
+ }
372
+
373
+ return $this->popupContent();
374
+ exit;
375
+ }
376
+ // End: WYSIJA Form Editor
377
+ }
trunk/controllers/back/index.html ADDED
File without changes
trunk/controllers/back/mp3.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined('WYSIJA') or die('Restricted access');
4
+
5
+ class WYSIJA_control_back_mp3 extends WYSIJA_control_back {
6
+
7
+ /**
8
+ * Main view of this controller
9
+ * @var string
10
+ */
11
+ public $view = 'mp3';
12
+ public $model = 'config';
13
+
14
+
15
+ /**
16
+ * Constructor
17
+ */
18
+ function __construct(){
19
+ parent::__construct();
20
+ }
21
+
22
+ function defaultDisplay() {
23
+ $this->jsTrans['premium_activate'] = __('Activate now', WYSIJA);
24
+ $this->jsTrans['premium_activating'] = __('Checking license', WYSIJA);
25
+ }
26
+ }
trunk/controllers/back/premium.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined('WYSIJA') or die('Restricted access');
4
+
5
+ class WYSIJA_control_back_premium extends WYSIJA_control_back {
6
+
7
+ /**
8
+ * Main view of this controller
9
+ * @var string
10
+ */
11
+ public $view = 'premium';
12
+ public $model = 'config';
13
+
14
+
15
+ /**
16
+ * Constructor
17
+ */
18
+ function __construct(){
19
+ parent::__construct();
20
+ }
21
+
22
+ function defaultDisplay() {
23
+ $this->jsTrans['premium_activate'] = __('Activate now', WYSIJA);
24
+ $this->jsTrans['premium_activating'] = __('Checking license', WYSIJA);
25
+ }
26
+ }
trunk/controllers/back/statistics.php ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ require_once(WYSIJA_CORE.'module'.DS.'statistics.php'); // @todo
4
+
5
+ class WYSIJA_control_back_statistics extends WYSIJA_control_back {
6
+
7
+ /**
8
+ * Main model of this controller
9
+ * @var string
10
+ */
11
+ public $model = 'statistics';
12
+
13
+ /**
14
+ * Main view of this controller
15
+ * @var string
16
+ */
17
+ public $view = 'statistics';
18
+
19
+ /**
20
+ * Base URL of all requests
21
+ * @var string
22
+ */
23
+ public $base_url = 'admin.php';
24
+
25
+ /**
26
+ * Load blocks at a same time (FALSE) or one by one (TRUE)
27
+ * @var TRUE
28
+ */
29
+ protected $lazy_load = true;
30
+
31
+ /**
32
+ * list of pre-defined dates
33
+ * @var Array
34
+ */
35
+ protected $pre_defined_dates = array( );
36
+
37
+ protected $date_format = 'Y/m/d';
38
+
39
+ protected $js_date_format = 'yy/mm/dd';
40
+
41
+ /**
42
+ * Constructor
43
+ */
44
+ function __construct(){
45
+ parent::__construct();
46
+ }
47
+
48
+ public function defaultDisplay() {
49
+ if (!WYSIJA::current_user_can('wysija_stats_dashboard'))
50
+ die('Action is forbidden.');
51
+
52
+ $this->pre_defined_dates = $this->get_pre_defined_dates();
53
+ // Define view
54
+ $this->viewShow = $this->action = 'main';
55
+ $this->js['jquery.core'] = 'jquery/ui/jquery.ui.core';
56
+ $this->js['jquery.datepicker'] = 'jquery/ui/jquery.ui.datepicker';
57
+ $this->js['wysijalazyload'] = 'wysija-lazyload';
58
+ $this->js['admin-statistics-filter'] = 'admin-statistics-filter';
59
+ wp_enqueue_style('jquery.core', WYSIJA_URL.'css/jquery/ui/themes/base/jquery.ui.core.min.css', array( ), WYSIJA::get_version());
60
+ wp_enqueue_style('jquery.core', WYSIJA_URL.'css/jquery/ui/themes/base/jquery.ui.theme.min.css', array( ), WYSIJA::get_version());
61
+
62
+ // date filter
63
+ $default_duration = $this->get_default_duration();
64
+ if (function_exists('date_diff')) {
65
+ $this->data['date_interval'] = date_diff(date_create($default_duration->from), date_create($default_duration->to));
66
+ }
67
+ else {
68
+ $duration = strtotime($default_duration->to) - strtotime($default_duration->from);
69
+ $helper_toolbox = WYSIJA::get('toolbox', 'helper');
70
+ $this->data['date_interval'] = (object)$helper_toolbox->convert_seconds_to_array($duration, false);
71
+ }
72
+
73
+ $this->data['custom_dates'] = $this->pre_defined_dates;
74
+ $this->data['default_duration'] = $default_duration;
75
+ $this->data['js_date_format'] = $this->js_date_format;
76
+
77
+ // Process and push data into view
78
+ $this->data['lazy_load'] = $this->lazy_load;
79
+ $hook_name = 'hook_stats';
80
+ $hook_params = array( );
81
+ $hook_params['top'] = WYSIJA_module_statistics::DEFAULT_TOP_RECORDS;
82
+ $hook_params['from'] = !empty($_REQUEST['filter']['from']) ? $_REQUEST['filter']['from'] : $default_duration->from;
83
+ $hook_params['to'] = !empty($_REQUEST['filter']['to']) ? $_REQUEST['filter']['to'] : $default_duration->to;
84
+ $hook_params['group_by'] = ($this->data['date_interval']->days == 0 || $this->data['date_interval']->days > WYSIJA_module_statistics::SWITCHING_DATE_TO_MONTH_THRESHOLD) ?
85
+ WYSIJA_module_statistics::GROUP_BY_MONTH :
86
+ WYSIJA_module_statistics::GROUP_BY_DATE; // $this->data['date_interval']->days == 0, means, no begin date, no end date
87
+ // Hack!
88
+ $_REQUEST['limit_pp'] = $hook_params['top']; // Pagination, mark current selected value
89
+ // Modify TO date to make sure we always count 23:59:59 of that day
90
+ $to = new DateTime($hook_params['to']);
91
+ $to->modify('+1 day');
92
+ $hook_params['to'] = $to->format($this->date_format);
93
+
94
+ $modules = WYSIJA_module::get_modules_from_hook($hook_name);
95
+ $this->data['modules'] = $modules;
96
+ $this->data['lazy_load_modules'] = array( );
97
+ $this->data['first_module'] = '';
98
+
99
+ if (!$this->lazy_load) {
100
+ $this->data['hooks'][$hook_name] = apply_filters('hook_stats', '', $hook_params);
101
+ }
102
+ else {
103
+ if (!empty($modules)) {
104
+ $first_module = array_shift($modules);
105
+ // List of lazy loaded modules
106
+ $this->data['lazy_load_modules'] = $modules;
107
+
108
+ // Evenly we are lazy loading, we always load the first module by default
109
+ $this->data['first_module'] = apply_filters('custom_module_hook', '', $first_module, $hook_name, $hook_params);
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * get pre defined dates (duration)
116
+ * @return type
117
+ */
118
+ protected function get_pre_defined_dates() {
119
+ return array(
120
+ array(
121
+ 'value' => 7,
122
+ 'label' => __('Last 7 days', WYSIJA),
123
+ 'selected' => false,
124
+ 'from' => date($this->date_format, strtotime('-7 days')),
125
+ 'to' => date($this->date_format, strtotime('today'))
126
+ ),
127
+ array(
128
+ 'value' => 'last_month',
129
+ 'label' => __('Last month', WYSIJA),
130
+ 'selected' => false,
131
+ 'from' => date($this->date_format, mktime(0, 0, 0, date('m') - 1, 1, date('Y'))),
132
+ 'to' => date($this->date_format, mktime(0, 0, 0, date('m'), 0, date('Y')))
133
+ ),
134
+ array(
135
+ 'value' => 30,
136
+ 'label' => __('Last 30 days', WYSIJA),
137
+ 'selected' => false,
138
+ 'from' => date($this->date_format, strtotime('-30 days')),
139
+ 'to' => date($this->date_format, strtotime('today'))
140
+ ),
141
+ array(
142
+ 'value' => 90,
143
+ 'label' => __('Last 90 days', WYSIJA),
144
+ 'selected' => true,
145
+ 'from' => date($this->date_format, strtotime('-90 days')),
146
+ 'to' => date($this->date_format, strtotime('today'))
147
+ ),
148
+ array(
149
+ 'value' => 180,
150
+ 'label' => __('Last 180 days', WYSIJA),
151
+ 'selected' => false,
152
+ 'from' => date($this->date_format, strtotime('-180 days')),
153
+ 'to' => date($this->date_format, strtotime('today'))
154
+ ),
155
+ array(
156
+ 'value' => 365,
157
+ 'label' => __('Last 365 days', WYSIJA),
158
+ 'selected' => false,
159
+ 'from' => date($this->date_format, strtotime('-365 days')),
160
+ 'to' => date($this->date_format, strtotime('today'))
161
+ ),
162
+ array(
163
+ 'value' => 0,
164
+ 'label' => __('Custom dates', WYSIJA),
165
+ 'selected' => false,
166
+ 'from' => '',
167
+ 'to' => ''
168
+ ),
169
+ );
170
+ }
171
+
172
+ /**
173
+ * Get default duration of stats
174
+ * @return WJ_StatsSession
175
+ */
176
+ protected function get_default_duration() {
177
+ $_duration = null;
178
+ foreach ($this->pre_defined_dates as $duration) {
179
+ if (isset($duration['selected']) && $duration['selected']) {
180
+ $_duration = $duration;
181
+ break;
182
+ }
183
+ }
184
+ if (empty($_duration))
185
+ $_duration = end($this->pre_defined_dates);
186
+
187
+ $stats_session_manager = new WJ_StatsSessionManager();
188
+ $stats_session = new WJ_StatsSession();
189
+ $stats_session->last_days = $_duration['value'];
190
+ $stats_session->from = $_duration['from'];
191
+ $stats_session->to = $_duration['to'];
192
+ $stats_session_manager->set_default_selection($stats_session);
193
+ $stats_session_manager->set_pre_defined_dates($this->get_pre_defined_dates());
194
+ return $stats_session_manager->get_last_selection();
195
+ }
196
+
197
+ function date_diff($time_start, $time_end) {
198
+ $result = null;
199
+ $duration = $time_end - $time_start;
200
+ $result->days = floor($duration / (60 * 60 * 24));
201
+ return $result;
202
+ }
203
+
204
+ }
trunk/controllers/back/subscribers.php ADDED
@@ -0,0 +1,1043 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_control_back_subscribers extends WYSIJA_control_back{
4
+ var $model='user';
5
+ var $view='subscribers';
6
+ var $list_columns=array('user_id','firstname', 'lastname','email','created_at');
7
+ var $searchable=array('email','firstname', 'lastname');
8
+ var $_separators = array(',', ';'); // csv separator; comma is for standard csv, semi-colon is good for Excel
9
+ var $_default_separator = ';';
10
+
11
+ /**
12
+ * Inactive users = users who never opened or clicked
13
+ * @todo: disabled on 2.6. Once it's enabled, please double check in term of "inactive users".
14
+ * OR - users who never opened or clicked
15
+ * OR - users who never opened or clicked AND received at least 1 newsletter.
16
+ * @var boolean
17
+ */
18
+ var $_filter_by_inactive_users = true;
19
+
20
+ function __construct() {
21
+ global $wpdb;
22
+ WYSIJA_control_back::__construct();
23
+ if ($this->_filter_by_inactive_users) {
24
+ // load the inactive subscribers on the listing and when a any bulk action is executed
25
+ if ( empty($_REQUEST['action'])
26
+ ||
27
+ ( !empty($_REQUEST['action'])
28
+ &&
29
+ ( in_array($_REQUEST['action'], array('export_get','exportlist', 'deleteusers'))
30
+ ||
31
+ substr($_REQUEST['action'], 0,10)=='actionvar_')
32
+ )
33
+ ) {
34
+ $this->modelObj->prepare_inactive_users_table();
35
+ }
36
+ }
37
+ $this->wpdb = $wpdb;
38
+ }
39
+
40
+ /*
41
+ * common task to all the list actions
42
+ */
43
+ private function _commonlists(){
44
+ $this->js[]='wysija-validator';
45
+
46
+ $this->data=array();
47
+ $this->data['list']=$this->_getLists(10);
48
+
49
+ }
50
+
51
+ /**
52
+ * We are using the same form for different purposes:
53
+ * - Bulk actions
54
+ * - Filter by list
55
+ * We need to remove all un-necessary values from interface
56
+ */
57
+ private function _cleanup_form() {
58
+ if (!empty($_REQUEST['doaction'])) {
59
+ $action_type = strtolower(trim($_REQUEST['doaction']));
60
+ switch ($action_type)
61
+ {
62
+ // Filter by list
63
+ case 'filter':
64
+ if (!empty($_REQUEST['wysija']['user']))
65
+ unset($_REQUEST['wysija']['user']);
66
+ if (!empty($_REQUEST['action']))
67
+ unset($_REQUEST['action']);
68
+ break;
69
+ // Bulk action. Nothing to do, because we will invoke _tryAction() directly right after this step
70
+ case 'apply':
71
+ default:
72
+ break;
73
+ }
74
+ }
75
+ }
76
+
77
+ private function _getLists($limit=false){
78
+
79
+ $model_list = WYSIJA::get('list','model');
80
+ $model_list->escapingOn=true;
81
+ $model_list->_limitison=$limit;
82
+ return $model_list->getLists();
83
+ }
84
+
85
+ private function _getForm($id=false){
86
+ if($id){
87
+ $model_list = WYSIJA::get('list','model');
88
+
89
+ return $model_list->get_one_list($id);
90
+ }else{
91
+ $array=array('name'=>'','list_id'=>'','description'=>'','is_public'=>true,'is_enabled'=>true);
92
+ return $array;
93
+ }
94
+
95
+ }
96
+
97
+ /**
98
+ * Get selected lists
99
+ * @return array
100
+ */
101
+ private function _get_selected_lists() {
102
+ $result = array();
103
+ if (isset($_REQUEST['wysija']['filter']['filter_list'])) {
104
+ $result[] = $_REQUEST['wysija']['filter']['filter_list'];
105
+ } elseif (!empty($_REQUEST['filter-list'])) {
106
+ $lists = explode(',', trim($_REQUEST['filter-list']));// currently, only single list is allowed.
107
+ if (!empty($lists)) {
108
+ $result = array_merge ($result, $lists);
109
+ }
110
+ }
111
+ return $result;
112
+ }
113
+
114
+ function save(){
115
+ $this->redirectAfterSave=false;
116
+ $this->requireSecurity();
117
+ $helper_user = WYSIJA::get('user','helper');
118
+ if( isset( $_REQUEST['id'] ) ){
119
+ $id = $_REQUEST['id'];
120
+ parent::save();
121
+
122
+ //run the unsubscribe process if needed
123
+ if((int)$_REQUEST['wysija']['user']['status']==-1){
124
+ $helper_user->unsubscribe($id);
125
+ }
126
+
127
+ /* update subscriptions */
128
+ $model_user_list = WYSIJA::get('user_list','model');
129
+ $model_user_list->backSave=true;
130
+ /* list of core list */
131
+ $model_list = WYSIJA::get('list','model');
132
+ $results = $model_list->get(array('list_id'),array('is_enabled'=>'0'));
133
+ $core_listids = array();
134
+ foreach($results as $res){
135
+ $core_listids[]=$res['list_id'];
136
+ }
137
+
138
+ //0 - get current lists of the user
139
+ $userlists = $model_user_list->get(array('list_id','unsub_date'),array('user_id'=>$id));
140
+
141
+ $oldlistids=$newlistids=array();
142
+ foreach($userlists as $listdata) $oldlistids[$listdata['list_id']]=$listdata['unsub_date'];
143
+
144
+ $model_config = WYSIJA::get('config','model');
145
+ $dbloptin = $model_config->getValue('confirm_dbleoptin');
146
+ //1 - insert new user_list
147
+ if(isset($_POST['wysija']['user_list']) && $_POST['wysija']['user_list']){
148
+ $model_user_list->reset();
149
+ $model_user_list->update(array('sub_date'=>time()),array('user_id'=>$id));
150
+ if(!empty($_POST['wysija']['user_list']['list_id'])){
151
+ foreach($_POST['wysija']['user_list']['list_id'] as $list_id){
152
+ //if the list is not already recorded for the user then we will need to insert it
153
+ if(!isset($oldlistids[$list_id])){
154
+ $model_user_list->reset();
155
+ $newlistids[]=$list_id;
156
+ $dataul=array('user_id'=>$id,'list_id'=>$list_id,'sub_date'=>time());
157
+ //if double optin is on and user is unconfirmed or unsubscribed, then we need to set it as unconfirmed subscription
158
+ if($dbloptin && (int)$_POST['wysija']['user']['status']<1) unset($dataul['sub_date']);
159
+ $model_user_list->insert($dataul);
160
+ //if the list is recorded already then let's check the status, if it is an unsubed one then we update it
161
+ }else{
162
+ if($oldlistids[$list_id]>0){
163
+ $model_user_list->reset();
164
+ $model_user_list->update(array('unsub_date'=>0,'sub_date'=>time()),array('user_id'=>$id,'list_id'=>$list_id));
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ }else{
171
+ // if no list is selected we unsubscribe them all
172
+ $model_user_list->reset();
173
+ $model_user_list->update(array('unsub_date'=>time(),'sub_date'=>0),array('user_id'=>$id));
174
+ }
175
+
176
+ //if a confirmation email needs to be sent then we send it
177
+ if($dbloptin && (int)$_POST['wysija']['user']['status']==0 && !empty($newlistids)){
178
+ $helper_user = WYSIJA::get('user','helper');
179
+ $helper_user->sendConfirmationEmail($id,true,$newlistids);
180
+ }
181
+
182
+ if((int)$_POST['wysija']['user']['status']==0 || (int)$_POST['wysija']['user']['status']==1){
183
+ $model_user_list->reset();
184
+ $model_user_list->update(array('unsub_date'=>0,'sub_date'=>time()),array('user_id'=>$id,'list_id'=>$core_listids));
185
+ }
186
+
187
+ $arrayLists=array();
188
+ if(isset($_POST['wysija']['user_list']['list_id'])) $arrayLists=$_POST['wysija']['user_list']['list_id'];
189
+ $notEqual=array_merge($core_listids, $arrayLists);
190
+
191
+ //unsubscribe from lists which exist in the old list but does not exist in the new list
192
+ $unsubsribe_list = array_diff(array_keys($oldlistids), $arrayLists);
193
+ if(!empty($unsubsribe_list))
194
+ {
195
+ $model_user_list->reset();
196
+ $model_user_list->update(array('unsub_date'=>time()),array('user_id'=>$id,'list_id'=>$unsubsribe_list));
197
+ }
198
+ $model_user_list->reset();
199
+
200
+ /*
201
+ Custom Fields.
202
+ */
203
+ if (isset($_POST['wysija']['field'])) {
204
+ WJ_FieldHandler::handle_all(
205
+ $_POST['wysija']['field'], $id
206
+ );
207
+ }
208
+
209
+
210
+ }else{
211
+ //instead of going through a classic save we should save through the helper
212
+ $data=$_REQUEST['wysija'];
213
+ $data['user_list']['list_ids'] = !empty($data['user_list']['list_id']) ? $data['user_list']['list_id'] : array();
214
+ unset($data['user_list']['list_id']);
215
+ $data['message_success']=__('Subscriber has been saved.',WYSIJA);
216
+ $id=$helper_user->addSubscriber($data,true);
217
+ if(!$id) {
218
+ $this->viewShow=$this->action='add';
219
+ $data=array('details'=>$_REQUEST['wysija']['user']);
220
+ return $this->add($data);
221
+ } else {
222
+ if(isset($_POST['wysija']['field'])) {
223
+ WJ_FieldHandler::handle_all($_POST['wysija']['field'], $id);
224
+ }
225
+ }
226
+ }
227
+ $this->redirect();
228
+ return true;
229
+ }
230
+
231
+
232
+ function defaultDisplay(){
233
+ $this->viewShow=$this->action='main';
234
+ $this->js[]='wysija-admin-list';
235
+ $this->viewObj->msgPerPage = __('Subscribers per page:',WYSIJA);
236
+
237
+ $this->jsTrans['selecmiss'] = __('Select at least 1 subscriber!',WYSIJA);
238
+
239
+ // get the total count for subscribed, unsubscribed and unconfirmed users
240
+ $select = array( 'COUNT(`user_id`) AS users' , 'status' , 'MAX(`created_at`) AS `max_create_at`');
241
+ $count_group_by = 'status';
242
+ $count_by_status = $this->modelObj->get_subscribers( $select , array() , $count_group_by );
243
+ if ($this->_filter_by_inactive_users) {
244
+ $inactive_users = $this->modelObj->count_inactive_users();
245
+ if ($inactive_users) {
246
+ array_unshift($count_by_status, array(
247
+ 'users' => $inactive_users['count'],
248
+ 'status' => -99,//-99 = inactive
249
+ 'max_create_at' => $inactive_users['max_created_at']
250
+ ));
251
+ }
252
+ }
253
+
254
+
255
+ $counts = $this->modelObj->structure_user_status_count_array($count_by_status);
256
+ $arr_max_create_at = $this->modelObj->get_max_create($count_by_status);
257
+
258
+ // count the rows based on the filters
259
+ $filters = $this->modelObj->detect_filters();
260
+
261
+ $select = array( 'COUNT(DISTINCT([wysija]user.user_id)) as total_users', 'MAX([wysija]user.created_at) as max_create_at');
262
+ $count_rows = $this->modelObj->get_subscribers( $select, $filters);
263
+
264
+ // without filter we already have the total number of subscribers
265
+ $this->data['max_create_at'] = null; //max value of create_at field of current list of users
266
+ if(!empty($filters)){
267
+ // used for pagination
268
+ $this->modelObj->countRows = $count_rows['total_users'];
269
+ // used for
270
+ $this->data['max_create_at'] = $count_rows['max_create_at'];
271
+ }else{
272
+ $this->data['max_create_at'] = !empty($arr_max_create_at) ? max($arr_max_create_at) : 0;
273
+ $this->modelObj->countRows=$counts['all'];
274
+ }
275
+
276
+ $select = array(
277
+ '[wysija]user.firstname',
278
+ '[wysija]user.lastname',
279
+ '[wysija]user.status',
280
+ '[wysija]user.email',
281
+ '[wysija]user.created_at',
282
+ '[wysija]user.last_opened',
283
+ '[wysija]user.last_clicked',
284
+ '[wysija]user_list.user_id'
285
+ );
286
+
287
+ $this->data['subscribers'] = $this->modelObj->get_subscribers($select , $filters, '', false, true);
288
+
289
+ $this->data['current_counts'] = $this->modelObj->countRows;
290
+ $this->data['show_batch_select'] = ($this->modelObj->limit >= $this->modelObj->countRows) ? false : true;
291
+ $this->data['selected_lists'] = $this->_get_selected_lists();
292
+ $this->modelObj->reset();
293
+
294
+
295
+ // make the data object for the listing view
296
+ $model_list = WYSIJA::get('list','model');
297
+ $lists_db = $model_list->getLists();
298
+
299
+ $lists=array();
300
+
301
+ foreach($lists_db as $listobj){
302
+ $lists[$listobj['list_id']]=$listobj;
303
+ }
304
+
305
+ $user_ids=array();
306
+ foreach($this->data['subscribers'] as $subscriber){
307
+ $user_ids[]=$subscriber['user_id'];
308
+ }
309
+
310
+ // 3 - user_list request
311
+ if($user_ids){
312
+ $model_user_list = WYSIJA::get('user_list','model');
313
+ $userlists=$model_user_list->get(array('list_id','user_id','unsub_date'),array('user_id'=>$user_ids));
314
+ }
315
+
316
+ $this->data['lists']=$lists;
317
+ $this->data['counts']=array_reverse($counts);
318
+
319
+ // regrouping all the data in the same array
320
+ foreach($this->data['subscribers'] as $keysus=>$subscriber){
321
+ // default key while we don't have the data
322
+ //TODO add data for stats about emails opened clicked etc
323
+ $this->data['subscribers'][$keysus]['emails']=0;
324
+ $this->data['subscribers'][$keysus]['opened']=0;
325
+ $this->data['subscribers'][$keysus]['clicked']=0;
326
+
327
+ if($userlists){
328
+ foreach($userlists as $key=>$userlist){
329
+ if($subscriber['user_id']==$userlist['user_id'] && isset($lists[$userlist['list_id']])){
330
+ //what kind of list ist it ? unsubscribed ? or not
331
+
332
+ if($userlist['unsub_date']>0){
333
+ if(!isset($this->data['subscribers'][$keysus]['unsub_lists']) ){
334
+ $this->data['subscribers'][$keysus]['unsub_lists']=$this->data['lists'][$userlist['list_id']]['name'];
335
+ }else{
336
+ $this->data['subscribers'][$keysus]['unsub_lists'].=', '.$this->data['lists'][$userlist['list_id']]['name'];
337
+ }
338
+ }else{
339
+ if(!isset($this->data['subscribers'][$keysus]['lists']) ){
340
+ $this->data['subscribers'][$keysus]['lists']=$this->data['lists'][$userlist['list_id']]['name'];
341
+ }else{
342
+ $this->data['subscribers'][$keysus]['lists'].=', '.$this->data['lists'][$userlist['list_id']]['name'];
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+ }
349
+ if(!$this->data['subscribers']){
350
+ $this->notice(__('Yikes! Couldn\'t find any subscribers.',WYSIJA));
351
+ }
352
+
353
+ }
354
+
355
+ function main(){
356
+ $this->messages['insert'][true]=__('Subscriber has been saved.',WYSIJA);
357
+ $this->messages['insert'][false]=__('Subscriber has not been saved.',WYSIJA);
358
+ $this->messages['update'][true]=__('Subscriber has been modified. [link]Edit again[/link].',WYSIJA);
359
+ $this->messages['update'][false]=__('Subscriber has not been modified.',WYSIJA);
360
+ $this->_cleanup_form();
361
+ parent::__construct();
362
+
363
+ //we change the default model of the controller based on the action
364
+ if(isset($_REQUEST['action'])){
365
+ switch($_REQUEST['action']){
366
+ case 'listsedit':
367
+ case 'savelist':
368
+ case 'lists':
369
+ $this->model='list';
370
+ break;
371
+ default:
372
+ $this->model='user';
373
+ }
374
+ }
375
+
376
+ WYSIJA_control::__construct();
377
+ if(!isset($_REQUEST['action']) || !$_REQUEST['action']) {
378
+ $this->defaultDisplay();
379
+ $this->checkTotalSubscribers();
380
+ } else {
381
+ $this->_tryAction($_REQUEST['action']);
382
+ }
383
+
384
+ }
385
+
386
+ /**
387
+ * bulk action copy to list
388
+ * @global type $wpdb
389
+ * @param type $data
390
+ */
391
+ function copytolist($data){
392
+ $this->requireSecurity();
393
+ $helper_user = WYSIJA::get('user','helper');
394
+ if(empty($this->_batch_select))
395
+ $helper_user ->addToList($data['listid'],$_POST['wysija']['user']['user_id']);
396
+ else
397
+ $helper_user ->addToList($data['listid'],$this->_batch_select, true);
398
+
399
+ $model_list = WYSIJA::get('list','model');
400
+ $result = $model_list->getOne(array('name'),array('list_id'=>$data['listid']));
401
+
402
+ if($this->_affected_rows > 1)
403
+ $this->notice(sprintf(__('%1$s subscribers have been added to "%2$s".',WYSIJA),$this->_affected_rows,$result['name']));
404
+ else
405
+ $this->notice(sprintf(__('%1$s subscriber have been added to "%2$s".',WYSIJA),$this->_affected_rows,$result['name']));
406
+ $this->redirect_after_bulk_action();
407
+ }
408
+
409
+ /**
410
+ * Moves subscriber to another list.
411
+ *
412
+ * @param array $data List id to move, $data = array('listid' => 1);
413
+ */
414
+ function movetolist($data) {
415
+ $this->requireSecurity();
416
+ $helper_user = WYSIJA::get('user', 'helper');
417
+
418
+ if (!empty($this->_batch_select)) {
419
+ $helper_user->moveToList($data['listid'], $this->_batch_select, true);
420
+ } elseif (isset($_POST['wysija']['user']['user_id'])) {
421
+ $helper_user->moveToList($data['listid'], $_POST['wysija']['user']['user_id']);
422
+ }
423
+
424
+ $model_list = WYSIJA::get('list','model');
425
+ $result = $model_list->getOne(array('name'), array('list_id' => $data['listid']));
426
+
427
+ if ($this->_affected_rows > 1) {
428
+ $this->notice(sprintf(__('%1$s subscribers have been moved to "%2$s".',WYSIJA), $this->_affected_rows, $result['name']));
429
+ } else {
430
+ $this->notice(sprintf(__('%1$s subscriber have been moved to "%2$s".',WYSIJA), $this->_affected_rows, $result['name']));
431
+ }
432
+
433
+ $this->redirect_after_bulk_action();
434
+ }
435
+
436
+ /**
437
+ * After performing a bulk action, let's keep the current list filter
438
+ */
439
+ protected function redirect_after_bulk_action() {
440
+ $filter_list = !empty($_REQUEST['wysija']['filter']['filter_list']) ? $_REQUEST['wysija']['filter']['filter_list'] : 0;
441
+ if (empty($filter_list)) {// view all lists
442
+ $this->redirect('admin.php?page=wysija_subscribers');
443
+ } elseif (is_numeric($filter_list)) {
444
+ $this->redirect('admin.php?page=wysija_subscribers&filter-list='.$filter_list);
445
+ } else {// subscribers in no list
446
+ $this->redirect('admin.php?page=wysija_subscribers&filter-list=orphaned');
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Bulk action remove subscribers from all existing lists
452
+ * @param type $data = array('list_id'=>?)
453
+ */
454
+ function removefromalllists($data){
455
+ $this->requireSecurity();
456
+ $helper_user = WYSIJA::get('user','helper');
457
+ if(!empty($this->_batch_select))
458
+ $helper_user->removeFromLists(array(),$this->_batch_select, true);
459
+ else
460
+ $helper_user->removeFromLists(array(),$_POST['wysija']['user']['user_id']);
461
+
462
+ if($this->_affected_rows > 1)
463
+ $this->notice(sprintf(__('%1$s subscribers have been removed from all existing lists.',WYSIJA),$this->_affected_rows));
464
+ else
465
+ $this->notice(sprintf(__('%1$s subscriber have been removed from all existing lists.',WYSIJA),$this->_affected_rows));
466
+ $this->redirect_after_bulk_action();
467
+ }
468
+
469
+ /**
470
+ * Bulk action remove subscribers from all existing lists
471
+ * @param type $data = array('list_id'=>?)
472
+ */
473
+ function removefromlist($data = array()){
474
+ $this->requireSecurity();
475
+ $helper_user = WYSIJA::get('user','helper');
476
+ if(!empty($this->_batch_select)){
477
+ $helper_user->removeFromLists(array($data['listid']),$this->_batch_select, true);
478
+ }else{
479
+ $helper_user->removeFromLists(array($data['listid']),$_POST['wysija']['user']['user_id']);
480
+ }
481
+
482
+ $model_list = WYSIJA::get('list','model');
483
+ $result = $model_list->getOne(array('name'),array('list_id'=>$data['listid']));
484
+
485
+ if($this->_affected_rows > 1){
486
+ $this->notice(sprintf(__('%1$s subscribers have been removed from "%2$s".',WYSIJA),$this->_affected_rows, $result['name']));
487
+ }else{
488
+ $this->notice(sprintf(__('%1$s subscriber have been removed from "%2$s".',WYSIJA),$this->_affected_rows, $result['name']));
489
+ }
490
+
491
+ $this->redirect_after_bulk_action();
492
+ }
493
+
494
+ /**
495
+ * Bulk confirm users
496
+ */
497
+ function confirmusers(){
498
+ $this->requireSecurity();
499
+ $helper_user = WYSIJA::get('user','helper');
500
+ if(!empty($this->_batch_select)){
501
+ $helper_user->confirmUsers($this->_batch_select, true);
502
+ }else{
503
+ $helper_user->confirmUsers($_POST['wysija']['user']['user_id']);
504
+ }
505
+
506
+ if($this->_affected_rows > 1){
507
+ $this->notice(sprintf(__('%1$s subscribers have been confirmed.',WYSIJA),$this->_affected_rows));
508
+ }else{
509
+ $this->notice(sprintf(__('%1$s subscriber have been confirmed.',WYSIJA),$this->_affected_rows));
510
+ }
511
+
512
+ $this->redirect_after_bulk_action();
513
+ }
514
+
515
+ /*
516
+ * Bulk resend confirmation emails
517
+ * Maximum emails to be sent is 100, and only send to unconfirmed subscribers, of coruse.
518
+ */
519
+ function resendconfirmationemail() {
520
+ $this->requireSecurity();
521
+ $helper_user = WYSIJA::get('user','helper');
522
+ $user_ids = array();
523
+ if(!empty($this->_batch_select)) {
524
+ $model_user = WYSIJA::get('user','model');
525
+ $users = $model_user->get_results($this->_batch_select['query'] . ' LIMIT 0, 100');
526
+ if (!empty($users)) {
527
+ foreach ($users as $user) {
528
+ $user_ids[] = $user['user_id'];
529
+ }
530
+ }
531
+ } else {
532
+ $user_ids = array_filter($_POST['wysija']['user']['user_id'], 'ctype_digit');
533
+ }
534
+
535
+ $sending_statuses = array();// array(user_id => 1/0)
536
+ if (!empty($user_ids)) {
537
+ $model_user_list = WYSIJA::get('user_list','model');
538
+ $user_lists = $model_user_list->get_lists($user_ids);
539
+ if (!empty($user_lists)) {
540
+ foreach ($user_lists as $user_id => $lists) {
541
+ $sending_statuses[$user_id] = $helper_user->sendConfirmationEmail($user_id, true, $lists);
542
+ }
543
+ }
544
+ }
545
+
546
+ $success_sending_number = count(array_values($sending_statuses));
547
+ if ($success_sending_number <= 0) {
548
+ $this->notice(__('No email sent.',WYSIJA));
549
+ } else {
550
+ $this->notice( sprintf(_n( 'One email has been sent.', '%d emails have been sent to unconfirmed subscribers.', (int)$success_sending_number, WYSIJA ), $success_sending_number ) );
551
+ }
552
+
553
+ $this->redirect_after_bulk_action();
554
+ }
555
+
556
+ function lists(){
557
+ $this->js[]='wysija-admin-list';
558
+ $this->_commonlists();
559
+
560
+ $this->modelObj=WYSIJA::get('list','model');
561
+ $this->viewObj->title=__('Edit lists',WYSIJA);
562
+ $this->modelObj->countRows=$this->modelObj->count();
563
+
564
+ $this->viewObj->model=$this->modelObj;
565
+ $this->data['form']=$this->_getForm();
566
+ }
567
+
568
+ function editlist(){
569
+ $this->_commonlists();
570
+ $this->data['form']=$this->_getForm($_REQUEST['id']);
571
+
572
+ $this->viewObj->title=sprintf(__('Editing list %1$s',WYSIJA), '<b><i>'.$this->data['form']['name'].'</i></b>');
573
+ }
574
+
575
+ function addlist(){
576
+ $this->_commonlists();
577
+ $this->viewObj->title=__('How about a new list?',WYSIJA);
578
+ $this->data['form']=$this->_getForm();
579
+ }
580
+
581
+ function duplicatelist(){
582
+ $this->requireSecurity();
583
+ /* get the list's email id
584
+ * 0 duplicate the list's welcome email
585
+ * 1 duplicate the list
586
+ * 2 duplicate the list's subscribers
587
+ */
588
+
589
+ $model_list = WYSIJA::get('list','model');
590
+ $data=$model_list->getOne(array('name','namekey','welcome_mail_id','unsub_mail_id'),array('list_id'=>(int)$_REQUEST['id']));
591
+
592
+ $query='INSERT INTO `[wysija]list` (`created_at`,`name`,`namekey`,`description`,`welcome_mail_id`,`unsub_mail_id`,`is_enabled`,`ordering`)
593
+ SELECT '.time().',concat("' . $this->wpdb->_real_escape( __( 'Copy of ', WYSIJA ) ) . '",`name`) ,"copy_'.$data['namekey'].time().'" ,`description`,0,0 ,1,`ordering` FROM [wysija]list
594
+ WHERE list_id='.(int)$_REQUEST['id'];
595
+
596
+ $list_id = $model_list->query($query);
597
+
598
+ $query='INSERT INTO `[wysija]user_list` (`list_id`,`user_id`,`sub_date`,`unsub_date`)
599
+ SELECT '.$list_id .',`user_id`,`sub_date`,`unsub_date` FROM [wysija]user_list
600
+ WHERE list_id='.(int)$_REQUEST['id'];
601
+
602
+ $model_list->query($query);
603
+
604
+ $this->notice(sprintf(__('List "%1$s" has been duplicated.',WYSIJA),$data['name']));
605
+ $this->redirect('admin.php?page=wysija_subscribers&action=lists');
606
+
607
+ }
608
+
609
+ function add($data=false){
610
+ $this->js[]='wysija-validator';
611
+ $this->viewObj->add=true;
612
+
613
+ $this->title=$this->viewObj->title=__('Add Subscriber',WYSIJA);
614
+
615
+ $this->data=array();
616
+ $this->data['user']=false;
617
+ if($data)$this->data['user']=$data;
618
+ $model_list = WYSIJA::get('list','model');
619
+ $model_list->limitON=false;
620
+ $this->data['list'] = $model_list->get(false,array('greater'=>array('is_enabled'=>'0') ));
621
+
622
+ }
623
+
624
+ function back(){
625
+ $this->redirect();
626
+ }
627
+
628
+ function backtolist(){
629
+ $this->redirect('admin.php?page=wysija_subscribers&action=lists');
630
+ }
631
+
632
+ function edit($id=false){
633
+
634
+ if (empty($_REQUEST['id']) && empty($id)){
635
+ $this->error('Cannot edit element primary key is missing : '. get_class($this));
636
+ return;
637
+ }
638
+
639
+ if(!$id) $id=$_REQUEST['id'];
640
+
641
+ // get detail info of current user
642
+ $this->data['user']=$this->modelObj->getDetails(array('user_id'=>$id));
643
+ if(!$this->data['user']){
644
+ $this->notice(__('No subscriber found, most probably because he was deleted.',WYSIJA));
645
+ return $this->redirect();
646
+ }
647
+
648
+ // get list info
649
+ $model_list=WYSIJA::get('list','model');
650
+ $model_list->limitON=false;
651
+ $model_list->orderBy('is_enabled','DESC');
652
+ $this->data['list']=$model_list->get(false,array('greater'=>array('is_enabled'=>'-1') ));
653
+ $this->viewObj->title=__('Edit',WYSIJA).' '.$this->data['user']['details']['email'];
654
+
655
+ // execute hooks
656
+ $hook_params = array(
657
+ 'user_id' => $id
658
+ );
659
+ $this->data['hooks']['hook_subscriber_left'] = apply_filters('hook_subscriber_left',WYSIJA_module::execute_hook('hook_subscriber_left', $hook_params), $hook_params);
660
+ $this->data['hooks']['hook_subscriber_right'] = apply_filters('hook_subscriber_right',WYSIJA_module::execute_hook('hook_subscriber_right', $hook_params), $hook_params);
661
+ $this->data['hooks']['hook_subscriber_bottom'] = apply_filters('hook_subscriber_bottom',WYSIJA_module::execute_hook('hook_subscriber_bottom', $hook_params), $hook_params);
662
+
663
+
664
+ // prepare js, for rendering
665
+ $this->js[]='wysija-validator';
666
+ }
667
+
668
+ function deletelist(){
669
+ $this->requireSecurity();
670
+
671
+ /* get the list's email id
672
+ * 0 delete the welcome email corresponding to that list
673
+ * 1 delete the list subscribers reference
674
+ * 2 delete the list campaigns references
675
+ * 4 delete the list
676
+ */
677
+ $model_list=WYSIJA::get('list','model');
678
+ $data=$model_list->getOne(array('name','namekey','welcome_mail_id'),array('list_id'=>(int)$_REQUEST['id']));
679
+
680
+ if($data && isset($data['namekey']) && ($data['namekey']!='users')){
681
+
682
+ //there is no welcome email per list that's old stuff
683
+ $model_user_list=WYSIJA::get('user_list','model');
684
+ $model_user_list->delete(array('list_id'=>$_REQUEST['id']));
685
+
686
+ $model_campaign_list=WYSIJA::get('campaign_list','model');
687
+ $model_campaign_list->delete(array('list_id'=>$_REQUEST['id']));
688
+
689
+ $model_list->reset();
690
+ $model_list->delete(array('list_id'=>$_REQUEST['id']));
691
+
692
+ $this->notice(sprintf(__('List "%1$s" has been deleted.',WYSIJA),$data['name']));
693
+ }else{
694
+ $this->error(__('The list does not exists or cannot be deleted.',WYSIJA),true);
695
+ }
696
+
697
+ $this->redirect('admin.php?page=wysija_subscribers&action=lists');
698
+
699
+ }
700
+
701
+
702
+ function synchlist(){
703
+ $this->requireSecurity();
704
+
705
+ $helper_user=WYSIJA::get('user','helper');
706
+ $helper_user->synchList($_REQUEST['id']);
707
+
708
+ $this->redirect('admin.php?page=wysija_subscribers&action=lists');
709
+ }
710
+
711
+ function synchlisttotal(){
712
+ $this->requireSecurity();
713
+
714
+ global $current_user;
715
+
716
+ if(is_multisite() && is_super_admin( $current_user->ID )){
717
+ $helper_user=WYSIJA::get('user','helper');
718
+ $helper_user->synchList($_REQUEST['id'],true);
719
+ }
720
+
721
+ $this->redirect('admin.php?page=wysija_subscribers&action=lists');
722
+ }
723
+
724
+
725
+ function savelist(){
726
+ $this->requireSecurity();
727
+ $this->_resetGlobMsg();
728
+ $update=false;
729
+
730
+ if($_REQUEST['wysija']['list']['list_id']){
731
+ $update=true;
732
+ }
733
+ /* save the result */
734
+ /* 1-save the welcome email*/
735
+ /* 2-save the list*/
736
+ if(isset($_REQUEST['wysija']['list']['is_public'])){
737
+ if($_REQUEST['wysija']['list']['is_public']=='on'){
738
+ $_REQUEST['wysija']['list']['is_public']=1;
739
+ }else{
740
+ $_REQUEST['wysija']['list']['is_public']=0;
741
+ }
742
+ }
743
+
744
+ if($update){
745
+ $this->modelObj->update($_REQUEST['wysija']['list']);
746
+ $this->notice(__('List has been updated.',WYSIJA));
747
+ }else{
748
+ $_REQUEST['wysija']['list']['created_at']=time();
749
+ $_REQUEST['wysija']['list']['is_enabled']=1;
750
+
751
+ $this->modelObj->insert($_REQUEST['wysija']['list']);
752
+ $this->notice(__('Your brand-new list awaits its first subscriber.',WYSIJA));
753
+ }
754
+
755
+
756
+ $this->redirect('admin.php?page=wysija_subscribers&action=lists');
757
+ }
758
+
759
+
760
+
761
+ function importpluginsave($id=false){
762
+ $this->requireSecurity();
763
+ $this->_resetGlobMsg();
764
+ $model_config = WYSIJA::get('config','model');
765
+ $helper_import = WYSIJA::get('plugins_import','helper');
766
+ $plugins_importable=$model_config->getValue('pluginsImportableEgg');
767
+ $plugins_imported=array();
768
+ foreach($_REQUEST['wysija']['import'] as $table_name =>$result){
769
+ $connection_info=$helper_import->getPluginsInfo($table_name);
770
+
771
+ if($result){
772
+ $plugins_imported[]=$table_name;
773
+ if(!$connection_info) $connection_info=$plugins_importable[$table_name];
774
+ $helper_import->import($table_name,$connection_info);
775
+ sleep(2);
776
+ $this->notice(sprintf(__('Import from plugin %1$s has been completed.',WYSIJA),"<strong>'".$connection_info['name']."'</strong>"));
777
+ }else{
778
+ $this->notice(sprintf(__('Import from plugin %1$s has been cancelled.',WYSIJA),"<strong>'".$connection_info['name']."'</strong>"));
779
+ }
780
+
781
+ }
782
+
783
+ $model_config->save(array('pluginsImportedEgg'=>$plugins_imported));
784
+
785
+ $this->redirect('admin.php?page=wysija_subscribers&action=lists');
786
+ }
787
+
788
+ function importplugins($id=false){
789
+ $this->js[]='wysija-validator';
790
+
791
+ $this->viewObj->title=__('Import subscribers from plugins',WYSIJA);
792
+
793
+ $model_config=WYSIJA::get('config','model');
794
+
795
+ $this->data=array();
796
+ $this->data['plugins']=$model_config->getValue('pluginsImportableEgg');
797
+ $imported_plugins=$model_config->getValue('pluginsImportedEgg');
798
+
799
+ if($imported_plugins){
800
+ foreach($imported_plugins as $tablename){
801
+ unset( $this->data['plugins'][$tablename]);
802
+ }
803
+ }
804
+
805
+
806
+ if(!$this->data['plugins']){
807
+ $this->notice(__('There is no plugin to import from.',WYSIJA));
808
+ return $this->redirect();
809
+ }
810
+ $this->viewShow='importplugins';
811
+
812
+ }
813
+
814
+ function import($id=false){
815
+ $this->js[]='wysija-validator';
816
+ $this->viewObj->title=__('Import Subscribers',WYSIJA);
817
+ $this->viewShow='import';
818
+ }
819
+
820
+ function importmatch(){
821
+ $this->requireSecurity();
822
+ $this->jsTrans['subscribers_import_match_confirmation_1'] = __('The selected value is already matched to another column.', WYSIJA);
823
+ $this->jsTrans['subscribers_import_match_confirmation_2'] = __('Can you confirm that this column is corresponding to that field?', WYSIJA);
824
+ $this->js[] = 'wysija-validator';
825
+ $helper_numbers = WYSIJA::get('numbers','helper');
826
+ $bytes = $helper_numbers->get_max_file_upload();
827
+
828
+ if(isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH']>$bytes['maxbytes']){
829
+ if(isset($_FILES['importfile']['name']) && $_FILES['importfile']['name']){
830
+ $file_name = $_FILES['importfile']['name'];
831
+ }else{
832
+ $file_name = __('which you have pasted',WYSIJA);
833
+ }
834
+
835
+ $this->error(sprintf(__('Upload error, file %1$s is too large! (MAX:%2$s)',WYSIJA) , $file_name , $bytes['maxmegas']),true);
836
+ $this->redirect('admin.php?page=wysija_subscribers&action=import');
837
+ return false;
838
+ }
839
+
840
+ $import = new WJ_Import();
841
+ $this->data = $import->scan_csv_file();
842
+
843
+ if($this->data === false){
844
+ $this->redirect('admin.php?page=wysija_subscribers&action=import');
845
+ }
846
+
847
+ $model_config = WYSIJA::get('config', 'model');
848
+ $this->jsTrans['userStatuses'] = array(
849
+ -1 => __('Unsubscribed', WYSIJA),
850
+ 0 => $model_config->getValue('confirm_dbleoptin') ? __('Unconfirmed',WYSIJA) : __('Subscribed',WYSIJA),
851
+ 1 => __('Subscribed',WYSIJA)
852
+ );
853
+ $this->js[] = 'wysija-import-match';
854
+ $this->viewObj->title=__('Import Subscribers',WYSIJA);
855
+ $this->viewShow='importmatch';
856
+
857
+ }
858
+
859
+ function import_save(){
860
+ @ini_set('max_execution_time',0);
861
+
862
+ $this->requireSecurity();
863
+ $this->_resetGlobMsg();
864
+
865
+ //we need to save a new list in that situation
866
+ if(!empty($_REQUEST['wysija']['list']['newlistname'])){
867
+ $model_list = WYSIJA::get('list','model');
868
+ $data_list = array();
869
+ $data_list['is_enabled'] = 1;
870
+ $data_list['name'] = $_REQUEST['wysija']['list']['newlistname'];
871
+ $_REQUEST['wysija']['user_list']['list'][] = $model_list->insert($data_list);
872
+ }
873
+
874
+ //if there is no list selected, we return to the same form prompting the user to take action
875
+ if(!isset($_REQUEST['wysija']['user_list']['list']) || !$_REQUEST['wysija']['user_list']['list']){
876
+ $this->error(__('You need to select at least one list.',WYSIJA),true);
877
+ return $this->importmatch();
878
+ }
879
+
880
+ $import = new WJ_Import();
881
+ $data_numbers = $import->import_subscribers();
882
+ $duplicate_emails_count = $import->get_duplicate_emails_count();
883
+
884
+ if($data_numbers === false){
885
+ return $this->redirect('admin.php?page=wysija_subscribers&action=import');
886
+ }
887
+
888
+ //get a list of list name
889
+ $model_list = WYSIJA::get('list','model');
890
+ $results = $model_list->get(array('name'),array('list_id'=>$_REQUEST['wysija']['user_list']['list']));
891
+
892
+ $list_names=array();
893
+ foreach($results as $k =>$v){
894
+ $list_names[]=$v['name'];
895
+ }
896
+
897
+ $this->notice( sprintf(__('%1$s subscribers added to %2$s.', WYSIJA),
898
+ $data_numbers['list_user_ids'],
899
+ '"'.implode('", "',$list_names).'"'
900
+ ) );
901
+
902
+ if(count($duplicate_emails_count)>0){
903
+ $list_emails = '';
904
+ $i = 0;
905
+ foreach($duplicate_emails_count as $email_address => $occurences){
906
+ if( $i > 0 )$list_emails.=', ';
907
+ $list_emails.= $email_address.' ('.$occurences.')';
908
+ $i++;
909
+ }
910
+ //$emailsalreadyinserted=array_keys($emailsCount);
911
+ $this->notice(sprintf(__('%1$s emails appear more than once in your file : %2$s.',WYSIJA),count($duplicate_emails_count),$list_emails),0);
912
+ }
913
+
914
+ if(count($data_numbers['invalid'])>0){
915
+ $string = sprintf(__('%1$s emails are not valid : %2$s.',WYSIJA),count($data_numbers['invalid']), utf8_encode(implode(', ',$data_numbers['invalid'])));
916
+ $this->notice($string,0);
917
+ }
918
+
919
+ $this->redirect();
920
+ }
921
+
922
+
923
+ function export(){
924
+ $this->js[]='wysija-validator';
925
+
926
+ $this->viewObj->title=__('Export Subscribers',WYSIJA);
927
+ $this->data=array();
928
+ //$this->data['lists']=$this->_getLists();
929
+ $this->data['lists'] = $model_list = WYSIJA::get('list','model');
930
+ $lists_results = $model_list->getLists();
931
+
932
+ $lists=array();
933
+
934
+ foreach($lists_results as $list_row){
935
+ $lists[$list_row['list_id']]=$list_row;
936
+ }
937
+ $this->data['lists']=$lists;
938
+
939
+ $this->viewShow='export';
940
+ }
941
+
942
+ function exportcampaign(){
943
+ $this->requireSecurity();
944
+
945
+ if(isset($_REQUEST['file_name'])){
946
+ $file_name = preg_replace('#[^a-z0-9_\-.]#i','',base64_decode($_REQUEST['file_name']));
947
+
948
+ $helper_file = WYSIJA::get('file', 'helper');
949
+ $exported_file_link = $helper_file->url($file_name, 'temp');
950
+
951
+ $content = file_get_contents( $exported_file_link );
952
+ $user_ids=explode(",",$content);
953
+ }
954
+ $_REQUEST['wysija']['user']['user_id']=$user_ids;
955
+
956
+ $this->exportlist();
957
+ }
958
+
959
+
960
+ /**
961
+ * bulk delete option
962
+ */
963
+ function deleteusers(){
964
+ $this->requireSecurity();
965
+ $helper_user=WYSIJA::get('user','helper');
966
+ if(!empty($this->_batch_select)){
967
+ $helper_user->delete($this->_batch_select, false, true);
968
+ }else{
969
+ $helper_user->delete($_POST['wysija']['user']['user_id']);
970
+ }
971
+
972
+ if($this->_affected_rows > 1){
973
+ $this->notice(sprintf(__(' %1$s subscribers have been deleted.',WYSIJA),$this->_affected_rows));
974
+ }else{
975
+ $this->notice(sprintf(__(' %1$s subscriber have been deleted.',WYSIJA),$this->_affected_rows));
976
+ }
977
+
978
+ // make sure the total count of subscribers is updated
979
+ $helper_user->refreshUsers();
980
+ $this->redirect_after_bulk_action();
981
+ }
982
+
983
+ /**
984
+ * function generating an export file based on an array of user_ids
985
+ */
986
+ function export_get(){
987
+ @ini_set('max_execution_time',0);
988
+ $this->requireSecurity();
989
+ $export = new WJ_Export();
990
+
991
+ if(!empty($this->_batch_select)){
992
+ $export->batch_select = $this->_batch_select;
993
+ }
994
+
995
+ $file_path_result = $export->export_subscribers();
996
+
997
+ $this->notice(str_replace(
998
+ array('[link]','[/link]'),
999
+ array('<a href="'.$file_path_result['url'].'" target="_blank" class="exported-file" >','</a>'),
1000
+ sprintf(__('%1$s subscribers were exported. Get the exported file [link]here[/link].',WYSIJA),$export->get_user_ids_rows())));
1001
+
1002
+ if(isset($_REQUEST['camp_id'])){
1003
+ $this->redirect('admin.php?page=wysija_campaigns&action=viewstats&id='.$_REQUEST['camp_id']);
1004
+ }else{
1005
+ $this->redirect();
1006
+ }
1007
+ }
1008
+
1009
+ public function exportlist(){
1010
+ $this->requireSecurity();
1011
+ if(!empty($_REQUEST['wysija']['user']['force_select_all'])){
1012
+
1013
+ $select = array( 'COUNT(DISTINCT([wysija]user.user_id)) as total_users');
1014
+ if(!empty($_REQUEST['wysija']['filter']['filter_list'])){
1015
+ $select[] = '[wysija]user_list.list_id';
1016
+ }
1017
+
1018
+ // filters for unsubscribed
1019
+ $filters = $this->modelObj->detect_filters();
1020
+
1021
+ $count = $this->modelObj->get_subscribers( $select, $filters );
1022
+ $number = $count['total_users'];
1023
+ } else {
1024
+ $number = count($_REQUEST['wysija']['user']['user_id']);
1025
+ }
1026
+
1027
+ $this->viewObj->title = sprintf(__('Exporting %1$s subscribers',WYSIJA),$number);
1028
+ $this->data=array();
1029
+
1030
+ $this->data['subscribers'] = $_REQUEST['wysija']['user']['user_id'];
1031
+ $this->data['user'] = $_REQUEST['wysija']['user'];//for batch-selecting
1032
+
1033
+ if(!empty($_REQUEST['search'])){
1034
+ $_REQUEST['wysija']['filter']['search'] = $_REQUEST['search'];
1035
+ }
1036
+
1037
+ if(isset($_REQUEST['wysija']['filter'])){
1038
+ $this->data['filter'] = $_REQUEST['wysija']['filter'];//for batch-selecting
1039
+ }
1040
+ $this->viewShow = 'export';
1041
+ }
1042
+
1043
+ }
trunk/controllers/front.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+
5
+ class WYSIJA_control_front extends WYSIJA_control{
6
+
7
+ function __construct($extension="wysija-newsletters"){
8
+ $this->extension=$extension;
9
+ parent::__construct();
10
+ $_REQUEST = stripslashes_deep($_REQUEST);
11
+ $_POST = stripslashes_deep($_POST);
12
+
13
+ if(isset($_REQUEST['action'])){
14
+ $this->action = preg_replace('|[^a-z0-9_\-]|i','',$_REQUEST['action']);
15
+ }else{
16
+ $this->action = 'index';
17
+ }
18
+ }
19
+
20
+ function save(){
21
+ $this->requireSecurity();
22
+ /* see if it's an update or an insert */
23
+ /*get the pk and its value as a conditions where pk = pkval*/
24
+ $conditions=$this->getPKVal($this->modelObj);
25
+
26
+ if($conditions){
27
+ /* this an update */
28
+
29
+ $result=$this->modelObj->update($_REQUEST['wysija'][$this->model],$conditions);
30
+
31
+ if($result) $this->notice($this->messages['update'][true]);
32
+ else{
33
+ $this->error($this->messages['update'][false],true);
34
+ }
35
+
36
+ }else{
37
+ /* this is an insert */
38
+ unset($_REQUEST['wysija'][$this->modelObj->pk]);
39
+
40
+ $result=$this->modelObj->insert($_REQUEST['wysija'][$this->model]);
41
+
42
+ if($result) $this->notice($this->messages['insert'][true]);
43
+ else{
44
+ $this->error($this->messages['insert'][false],true);
45
+ }
46
+
47
+ }
48
+ return $result;
49
+ }
50
+
51
+ function redirect($location) {
52
+ // make sure we encode square brackets as wp_redirect will strip them off
53
+ $location = str_replace(array('[', ']'), array('%5B', '%5D'), $location);
54
+
55
+ // redirect to specified location
56
+ wp_redirect($location);
57
+ exit;
58
+ }
59
+ }
trunk/controllers/front/confirm.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+
5
+ class WYSIJA_control_front_confirm extends WYSIJA_control_front{
6
+ var $model='user';
7
+ var $view='confirm';
8
+
9
+ function __construct(){
10
+ parent::__construct();
11
+ }
12
+
13
+ function _testKeyuser(){
14
+ $this->helperUser=WYSIJA::get('user','helper');
15
+
16
+ $this->userData=$this->helperUser->checkUserKey();
17
+ add_action('init',array($this,'testsession'));
18
+
19
+ if(!$this->userData){
20
+ $this->title=__('Page does not exist.',WYSIJA);
21
+ $this->subtitle=__('Please verify your link to this page.',WYSIJA);
22
+ return false;
23
+ }
24
+ return true;
25
+ }
26
+
27
+ /**
28
+ * confirm subscription page
29
+ * return boolean
30
+ */
31
+ function subscribe(){
32
+ $helper_user = WYSIJA::get('user','helper');
33
+ if(!isset($_REQUEST['demo'])){
34
+ $helper_user->confirm_user();
35
+
36
+ if(!empty($helper_user->title)) $this->title = $helper_user->title;
37
+ if(!empty($helper_user->subtitle)) $this->optional_subtitle = $helper_user->subtitle;
38
+ }else{
39
+ $model_config=WYSIJA::get('config','model');
40
+
41
+ // we need to call the translation otherwise it will not be loaded and translated
42
+ $model_config->add_translated_default();
43
+
44
+ $this->title = sprintf($model_config->getValue('subscribed_title'), 'demo');
45
+ $this->optional_subtitle=$model_config->getValue('subscribed_subtitle');
46
+ }
47
+
48
+ return true;
49
+ }
50
+
51
+ function unsubscribe(){
52
+ remove_action( 'bp_get_request_unsubscribe', 'bp_email_unsubscribe_handler' );
53
+ $model_config=WYSIJA::get('config','model');
54
+
55
+ // we need to call the translation otherwise it will not be loaded and translated
56
+ $model_config->add_translated_default();
57
+
58
+ $this->title = $model_config->getValue('unsubscribed_title');
59
+ if(!isset($model_config->values['unsubscribed_title'])) $this->title = __("You've unsubscribed!",WYSIJA);
60
+
61
+ $this->optional_subtitle = $model_config->getValue('unsubscribed_subtitle');
62
+ if(!isset($model_config->values['unsubscribed_subtitle'])) $this->optional_subtitle = __("Great, you'll never hear from us again!",WYSIJA);
63
+
64
+ $wysija_key = '';
65
+ if(isset( $_GET['wysija-key'] )){
66
+ $wysija_key = filter_var($_GET['wysija-key'], FILTER_SANITIZE_STRING);
67
+ }
68
+ $undo_paramsurl = array(
69
+ 'wysija-page' => 1,
70
+ 'controller' => 'confirm',
71
+ 'action' => 'undounsubscribe',
72
+ 'wysija-key' => $wysija_key
73
+ );
74
+
75
+ if(! isset($_GET['demo']) ){
76
+ if($this->_testKeyuser()){
77
+ $statusint=(int)$this->userData['details']['status'];
78
+ if( ($model_config->getValue('confirm_dbleoptin') && $statusint>0) || (!$model_config->getValue('confirm_dbleoptin') && $statusint>=0)){
79
+ $listids=$this->helperUser->unsubscribe($this->userData['details']['user_id']);
80
+ $this->helperUser->uid=$this->userData['details']['user_id'];
81
+ if($model_config->getValue('emails_notified') && $model_config->getValue('emails_notified_when_unsub')) $this->helperUser->_notify($this->userData['details']['email'],false,$listids);
82
+ }else{
83
+ $this->title=__('You are already unsubscribed.',WYSIJA);
84
+ return false;
85
+ }
86
+ }
87
+ }else{
88
+ $undo_paramsurl['demo'] = 1;
89
+ }
90
+
91
+ $link_undo = WYSIJA::get_permalink($model_config->getValue('unsubscribe_page'),$undo_paramsurl);
92
+
93
+
94
+ $this->undo_unsubscribe = str_replace(
95
+ array('[link]','[/link]'),
96
+ array('<a href="'.$link_undo.'">','</a>'),
97
+ '<p><b>'.__('You made a mistake? [link]Undo unsubscribe[/link].',WYSIJA)).'</b></p>';
98
+ return true;
99
+ }
100
+
101
+ function undounsubscribe(){
102
+ $model_config=WYSIJA::get('config','model');
103
+
104
+ // we need to call the translation otherwise it will not be loaded and translated
105
+ $model_config->add_translated_default();
106
+
107
+ $this->title =__("You've been subscribed!",WYSIJA);
108
+ $user_object = false;
109
+ if(!isset($_REQUEST['demo'])){
110
+ if($this->_testKeyuser()){
111
+ $user_object = (object)$this->userData['details'];
112
+ $this->helperUser->undounsubscribe($this->userData['details']['user_id']);
113
+ }
114
+ }
115
+
116
+ //manage subcription link
117
+ if(($model_config->getValue('manage_subscriptions'))){
118
+ $helper_user = WYSIJA::get('config','helper');
119
+ $model_user = WYSIJA::get('user','model');
120
+ $editsubscriptiontxt = $model_config->getValue('manage_subscriptions_linkname');
121
+ if(empty($editsubscriptiontxt)) $editsubscriptiontxt =__('Edit your subscription',WYSIJA);
122
+ $this->subtitle = '<p>'.$model_user->getEditsubLink($user_object,false,'').'.</p>';
123
+ }
124
+ return true;
125
+ }
126
+
127
+ function subscriptions(){
128
+ $data=array();
129
+
130
+ //get the user_id out of the params passed
131
+ if($this->_testKeyuser()){
132
+
133
+ $data['user']=$this->userData;
134
+ //get the list of user
135
+ $model_list=WYSIJA::get('list','model');
136
+ $model_list->orderBy('ordering','ASC');
137
+ $data['list']=$model_list->get(array('list_id','name','description'),array('is_enabled'=>true,'is_public'=>true));
138
+
139
+ $this->title=sprintf(__('Edit your subscriber profile: %1$s',WYSIJA),$data['user']['details']['email']);
140
+
141
+ $this->subtitle=$this->viewObj->subscriptions($data);
142
+
143
+ return true;
144
+ }
145
+ }
146
+
147
+ function resend(){
148
+ $this->title = $this->subtitle = 'The link you clicked has expired';
149
+ }
150
+
151
+ function save(){
152
+
153
+ //get the user_id out of the params passed */
154
+ if($this->_testKeyuser()){
155
+ //update the general details */
156
+ if(! is_array($_REQUEST['wysija']) || !is_array($_REQUEST['wysija']['user'])){
157
+ return false;
158
+ }
159
+ $userid = $this->userData['details']['user_id'];
160
+ unset($_REQUEST['wysija']['user']['user_id']);
161
+ $model_config=WYSIJA::get('config','model');
162
+ // we need to call the translation otherwise it will not be loaded and translated
163
+ $model_config->add_translated_default();
164
+ $this->helperUser->uid=$userid;
165
+ //if the status changed we might need to send notifications */
166
+ if((int)$_REQUEST['wysija']['user']['status'] !=(int)$this->userData['details']['status']){
167
+ if($_REQUEST['wysija']['user']['status']>0){
168
+ if($model_config->getValue('emails_notified_when_sub')) $this->helperUser->_notify($this->userData['details']['email']);
169
+ }else{
170
+ if($model_config->getValue('emails_notified_when_unsub')) $this->helperUser->_notify($this->userData['details']['email'],false);
171
+ }
172
+ }
173
+
174
+ //check whether the email address has changed if so then we should make sure that the new address doesnt exists already
175
+ if(isset($_REQUEST['wysija']['user']['email'])){
176
+ $_REQUEST['wysija']['user']['email']=trim($_REQUEST['wysija']['user']['email']);
177
+ if($this->userData['details']['email']!=$_REQUEST['wysija']['user']['email']){
178
+ $this->modelObj->reset();
179
+ $result=$this->modelObj->getOne(false,array('email'=>$_REQUEST['wysija']['user']['email']));
180
+ if($result){
181
+ $this->error(sprintf(__('Email %1$s already exists.',WYSIJA),$_REQUEST['wysija']['user']['email']),1);
182
+ unset($_REQUEST['wysija']['user']['email']);
183
+ }
184
+ }
185
+ }
186
+
187
+ $this->modelObj->update($_REQUEST['wysija']['user'],array('user_id'=>$userid));
188
+ $id=$userid;
189
+
190
+ $hUser=WYSIJA::get('user','helper');
191
+ //update the list subscriptions */
192
+ //run the unsubscribe process if needed
193
+ if((int)$_REQUEST['wysija']['user']['status']==-1){
194
+ $hUser->unsubscribe($id);
195
+ }
196
+
197
+ //update subscriptions */
198
+ $modelUL=WYSIJA::get('user_list','model');
199
+ $modelUL->backSave=true;
200
+ /* list of core list */
201
+ $modelLIST=WYSIJA::get('list','model');
202
+
203
+ // Using "like" condition in order to force sql query to OR (instead of AND). It'll be incorrct if status contains other values than 0/1.
204
+ $results=$modelLIST->get(array('list_id'),array('like' => array('is_enabled'=>0, 'is_public' => 0)));
205
+ $static_listids=array();
206
+ foreach($results as $res){
207
+ $static_listids[]=$res['list_id'];
208
+ }
209
+
210
+ //0 - get current lists of the user
211
+ $userlists=$modelUL->get(array('list_id','unsub_date'),array('user_id'=>$id));
212
+
213
+ $oldlistids=$new_list_ids=array();
214
+ foreach($userlists as $listdata) $oldlistids[$listdata['list_id']]=$listdata['unsub_date'];
215
+
216
+ $config=WYSIJA::get('config','model');
217
+ $dbloptin=$config->getValue('confirm_dbleoptin');
218
+ //1 - insert new user_list
219
+ if(!empty($_POST['wysija']['user_list']['list_id']) && is_array($_POST['wysija']['user_list']['list_id'])){
220
+ $modelUL->reset();
221
+ $modelUL->update(array('sub_date'=>time()),array('user_id'=>$id));
222
+ foreach($_POST['wysija']['user_list']['list_id'] as $list_id){
223
+ //if the list is not already recorded for the user then we will need to insert it
224
+ if(!isset($oldlistids[$list_id])){
225
+ $modelUL->reset();
226
+ $new_list_ids[]=$list_id;
227
+ $dataul=array('user_id'=>$id,'list_id'=>$list_id,'sub_date'=>time());
228
+ //if double optin is on then we want to send a confirmation email for newly added subscription
229
+ if($dbloptin){
230
+ unset($dataul['sub_date']);
231
+ $modelUL->nohook=true;
232
+ }
233
+ $modelUL->insert($dataul);
234
+ //if the list is recorded already then let's check the status, if it is an unsubed one then we update it
235
+ }else{
236
+ if($oldlistids[$list_id]>0){
237
+ $modelUL->reset();
238
+ $modelUL->update(array('unsub_date'=>0,'sub_date'=>time()),array('user_id'=>$id,'list_id'=>$list_id));
239
+ }
240
+ //$alreadysubscribelistids[]=$list_id;
241
+ }
242
+ }
243
+ }
244
+
245
+
246
+
247
+
248
+ //if a confirmation email needs to be sent then we send it
249
+
250
+ if($dbloptin && !empty($new_list_ids)){
251
+ $send_confirmation = true;
252
+ $send_confirmation = apply_filters('mpoet_confirm_new_list_subscriptions_page', $send_confirmation);
253
+
254
+ if($send_confirmation === true){
255
+ $hUser->sendConfirmationEmail($id,true,$new_list_ids);
256
+ }else{
257
+ // this case has been made so that when subscribers add themselves to a
258
+ // list through the edit your subscription form they don't receive a confirmation email they already confirmed.
259
+ // so they receive also the autorespo,nders correspondign to that list immediately.
260
+ $helper_user = WYSIJA::get('user','helper');
261
+ $_REQUEST['wysiconf'] = base64_encode(json_encode($new_list_ids));
262
+ $helper_user->confirm_user();
263
+ }
264
+ }
265
+
266
+ // list ids
267
+ $list_ids = !empty($_POST['wysija']['user_list']['list_id']) ? $_POST['wysija']['user_list']['list_id'] : array();
268
+ if(is_array($list_ids) === false) $list_ids = array();
269
+
270
+ $notEqual = array_merge($static_listids, $list_ids);
271
+
272
+ //delete the lists from which you've removed yourself
273
+ $condiFirst = array('notequal'=>array('list_id'=> $notEqual), 'equal' => array('user_id' => $id, 'unsub_date' => 0));
274
+ $modelUL=WYSIJA::get('user_list','model');
275
+ $modelUL->update(array('unsub_date'=>time()),$condiFirst);
276
+ $modelUL->reset();
277
+
278
+ /*
279
+ Custom Fields.
280
+ */
281
+ if (isset($_POST['wysija']['field'])) {
282
+ WJ_FieldHandler::handle_all(
283
+ $_POST['wysija']['field'], $id
284
+ );
285
+ }
286
+
287
+ $this->notice(__('Newsletter profile has been updated.',WYSIJA));
288
+ $this->subscriptions();
289
+
290
+ //reset post otherwise wordpress will not recognise the post !!!
291
+ $_POST=array();
292
+ }
293
+ return true;
294
+ }
295
+ }
trunk/controllers/front/email.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WYSIJA_control_front_email extends WYSIJA_control_front{
5
+ var $model='email';
6
+ var $view='email';
7
+
8
+ function __construct(){
9
+ parent::__construct();
10
+ }
11
+
12
+ function view(){
13
+
14
+ $data=array();
15
+
16
+ header('Content-type:text/html; charset=utf-8');
17
+
18
+ // Get email model as object.
19
+ $emailM = WYSIJA::get('email','model');
20
+ $emailM->getFormat = OBJECT;
21
+ // Get config model
22
+ $configM = WYSIJA::get('config','model');
23
+ $configM->add_translated_default();
24
+ // Helpers
25
+ $emailH = WYSIJA::get('email','helper');
26
+ $mailerH = WYSIJA::get('mailer','helper');
27
+
28
+ $email_id = (int)$_REQUEST['email_id'];
29
+ // Get current email object.
30
+ $current_email = $emailM->getOne($email_id);
31
+ if(empty($current_email)) exit;
32
+ if($current_email->type==2){
33
+
34
+ $emailM->reset();
35
+ $autonewsHelper = WYSIJA::get('autonews','helper');
36
+ $autonewsHelper->refresh_automatic_content(array($email_id));
37
+ $emailM->getFormat = OBJECT;
38
+ $current_email = $emailM->getOne($email_id);
39
+ }
40
+
41
+ // Get current user object if possible
42
+ $current_user = null;
43
+
44
+ // Parse and replace user tags.
45
+ $mailerH->parseUserTags($current_email);
46
+ $mailerH->parseSubjectUserTags($current_email);
47
+ $mailerH->replaceusertags($current_email, $current_user);
48
+
49
+ // Set Body
50
+ $email_render = $current_email->body;
51
+
52
+ // Parse old shortcodes that we are parsing in the queue.
53
+ $find = array('[unsubscribe_linklabel]');
54
+ $replace = array($configM->getValue('unsubscribe_linkname'));
55
+ if (isset($current_email->params['autonl']['articles']['first_subject'])){
56
+ $find[] = '[post_title]';
57
+ $replace[] = $current_email->params['autonl']['articles']['first_subject'];
58
+ }
59
+ if (isset($current_email->params['autonl']['articles']['total'])){
60
+ $find[] = '[total]';
61
+ $replace[] = $current_email->params['autonl']['articles']['total'];
62
+ }
63
+
64
+ // if (isset($current_email->params['autonl']['articles']['ids'])){
65
+ // $find[] = '[number]';
66
+ // $replace[] = count($current_email->params['autonl']['articles']['ids']);
67
+ // }
68
+
69
+ if (isset($current_email->params['autonl']['total_child'])){
70
+ $find[] = '[number]';
71
+ $replace[] = $current_email->params['autonl']['total_child'];
72
+ }
73
+
74
+ $email_render1 = str_replace($find, $replace, $email_render);
75
+ // Strip unsubscribe links.
76
+ $email_render2 = $emailH->stripPersonalLinks($email_render1);
77
+
78
+ echo apply_filters('wysija_preview',$email_render2);
79
+
80
+ exit;
81
+ }
82
+
83
+ }
trunk/controllers/front/index.html ADDED
File without changes
trunk/controllers/front/stats.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+
5
+ class WYSIJA_control_front_stats extends WYSIJA_control_front{
6
+ var $model='' ;
7
+ var $view='';
8
+
9
+ /**
10
+ * Possible characters to be url encoded
11
+ * @var array
12
+ */
13
+ protected $characters_to_encode = array(
14
+ '@'
15
+ );
16
+
17
+ function __construct(){
18
+ parent::__construct();
19
+ }
20
+
21
+ /**
22
+ * count the click statistic and redirect to the right url
23
+ * @return boolean
24
+ */
25
+ function analyse(){
26
+ if(isset($_REQUEST['email_id']) && isset($_REQUEST['user_id'])){
27
+ $WJ_Stats = new WJ_Stats();
28
+ if(!empty($WJ_Stats->clicked_url)){
29
+ // clicked stats
30
+ $url = $this->encode_url($WJ_Stats->subscriber_clicked());
31
+ $external_url_unescaped_and_without_utm = preg_replace('!/?\?utm.*!i', '', $url);
32
+ $external_url_escaped_and_without_utm = preg_replace('!/?\?utm.*!i', '', htmlentities($WJ_Stats->subscriber_clicked())); // remove anything that starts with ?utm or /?utm
33
+ $internal_site_url = preg_replace('!https?://!i', '', htmlentities(get_site_url()));
34
+ $internal_home_url = preg_replace('!https?://!i', '', htmlentities(get_home_url()));
35
+ $model_email = WYSIJA::get('email', 'model');
36
+ $email_object = $model_email->getOne(false,array('email_id' => $_REQUEST['email_id']));
37
+ if (preg_match('!'. preg_quote($external_url_unescaped_and_without_utm, '!') .'!i', $email_object['body']) ||
38
+ preg_match('!'. preg_quote($external_url_escaped_and_without_utm, '!') .'!i', $email_object['body']) ||
39
+ preg_match('!^https?://'. preg_quote($internal_site_url, '!') .'!i', $url) ||
40
+ preg_match('!^https?://'. preg_quote($internal_home_url, '!') .'!i', $url)
41
+
42
+ ) {
43
+ do_action('mpoet_click_stats', $WJ_Stats);
44
+ $this->redirect($url);
45
+ }
46
+ header('HTTP/1.0 404 Not Found');
47
+ echo '<h1>404 Not Found</h1>';
48
+ echo 'The page that you have requested could not be found.';
49
+ exit();
50
+ }else{
51
+ // opened stat
52
+ $WJ_Stats->subscriber_opened();
53
+ }
54
+ }
55
+
56
+ return true;
57
+ }
58
+
59
+ /**
60
+ * Encode some special characters in url
61
+ * @param string $url
62
+ * @return string
63
+ */
64
+ protected function encode_url($url) {
65
+ return str_replace(
66
+ $this->characters_to_encode,
67
+ array_map('urlencode', $this->characters_to_encode),
68
+ $url
69
+ );
70
+ }
71
+
72
+ }
trunk/controllers/front/subscribers.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WYSIJA_control_front_subscribers extends WYSIJA_control_front{
5
+ var $model='user';
6
+ var $view='widget_nl';
7
+
8
+ function __construct(){
9
+ parent::__construct();
10
+ if(isset($_REQUEST['message_success'])){
11
+ $this->messages['insert'][true]=$_REQUEST['message_success'];
12
+ }else{
13
+ $this->messages['insert'][true]=__('User has been inserted.',WYSIJA);
14
+ }
15
+
16
+ $this->messages['insert'][false]=__('User has not been inserted.',WYSIJA);
17
+ $this->messages['update'][true]=__('User has been updated.',WYSIJA);
18
+ $this->messages['update'][false]=__('User has not been updated.',WYSIJA);
19
+ }
20
+
21
+ function save(){
22
+ $config=WYSIJA::get('config','model');
23
+
24
+ if(!$config->getValue('allow_no_js')){
25
+ $this->notice(__('Subscription without JavaScript is disabled.',WYSIJA));
26
+ return false;
27
+ }
28
+
29
+ if(isset($_REQUEST['wysija']['user_list']['list_id'])){
30
+ $_REQUEST['wysija']['user_list']['list_ids']=$_REQUEST['wysija']['user_list']['list_id'];
31
+ unset($_REQUEST['wysija']['user_list']['list_id']);
32
+ }elseif(isset($_REQUEST['wysija']['user_list']['list_ids'])){
33
+ $_REQUEST['wysija']['user_list']['list_ids']=explode(',',$_REQUEST['wysija']['user_list']['list_ids']);
34
+ }
35
+ $_REQUEST['wysija']['user_field'] = $_REQUEST['wysija']['field'];
36
+ $data=$_REQUEST['wysija'];
37
+ unset($_REQUEST['wysija']);
38
+
39
+ foreach($_REQUEST as $key => $val){
40
+ if(!isset($data[$key])) $data[$key]=$val;
41
+ }
42
+
43
+ $helperUser=WYSIJA::get('user','helper');
44
+ if(!$helperUser->checkData($data))return false;
45
+ if(!$helperUser->throttleRepeatedSubscriptions()) return false;
46
+
47
+ if($helperUser->addSubscriber($data)) {
48
+ $helperUser->storeSubscriberIP();
49
+ }
50
+
51
+ return true;
52
+ }
53
+
54
+ /**
55
+ * handles the form generation in iframe mode, basically wysija's iframes call that action to generate the html of the body
56
+ */
57
+ function wysija_outter() {
58
+
59
+ //params used to generate the html in the widget class
60
+ $widget_data=array();
61
+
62
+ if(isset($_REQUEST['wysija_form']) && (int)$_REQUEST['wysija_form'] > 0) {
63
+ // this a wysija form made with the form editor
64
+ // if it's a preview, we need to dynamically render the form
65
+ // get form data
66
+
67
+ $widget_data['form']=(int)$_REQUEST['wysija_form'];
68
+ $widget_data['form_type']='iframe';
69
+
70
+ } else {
71
+
72
+ //this is the old way, we need to keep it for backward compatibility
73
+ if(isset($_REQUEST['encodedForm'])){
74
+ $encoded_form=json_decode(base64_decode(urldecode($_REQUEST['encodedForm'])));
75
+ } else {
76
+ if(isset($_REQUEST['fullWysijaForm'])){
77
+ $encoded_form=json_decode(base64_decode(urldecode($_REQUEST['fullWysijaForm'])));
78
+ } else {
79
+ if(isset($_REQUEST['widgetnumber'])){
80
+
81
+ $widgets=get_option('widget_wysija');
82
+ if(isset($widgets[$_REQUEST['widgetnumber']])){
83
+ $encoded_form=$widgets[$_REQUEST['widgetnumber']];
84
+ }
85
+
86
+ }else{
87
+ $encoded_form=$_REQUEST['formArray'];
88
+ $encoded_form=stripslashes_deep($encoded_form);
89
+ }
90
+
91
+ }
92
+ }
93
+
94
+
95
+ //fill the widget data array based on the parameters found earlier
96
+ if($encoded_form){
97
+ foreach($encoded_form as $key =>$val) {
98
+ if (in_array($key, array('before_widget', 'after_widget', 'before_title', 'title', 'after_title'))) {
99
+ $val = sanitize_text_field($val);
100
+ }
101
+ $widget_data[$key]=$val;
102
+
103
+ //if the value is an object we need to loop through and make an array of it
104
+ //I think we could simply cast the object as an array not sure if that works on objects within objects...
105
+ if(is_object($val)){
106
+ $object_to_array=array();
107
+ foreach($val as $key_in =>$val_in){
108
+ $object_to_array[$key_in]=$val_in;
109
+ if(is_object($val_in)){
110
+ $object_to_array_second_level=array();
111
+ foreach($val_in as $k_in => $v_in){
112
+ $object_to_array_second_level[$k_in]=$v_in;
113
+ }
114
+ $object_to_array[$key_in]=$object_to_array_second_level;
115
+ }
116
+ }
117
+ $widget_data[$key]=$object_to_array;
118
+ }
119
+ }
120
+ }else{
121
+ if(current_user_can('switch_themes')) echo '<b>'.str_replace(array('[link]','[/link]'),array('<a target="_blank" href="'. admin_url('widgets.php').'">','</a>'),__('It seems your widget has been deleted from the WordPress\' [link]widgets area[/link].',WYSIJA)).'</b>';
122
+ exit;
123
+ }
124
+
125
+ //create a unique identifier for the form (the old way)
126
+ if(isset($_REQUEST['widgetnumber'])) $form_identifier=$_REQUEST['widgetnumber'];
127
+ else $form_identifier=rand(5, 1500);
128
+ $widget_data['widget_id']='wysija-nl-iframe-'.$form_identifier;
129
+ }
130
+
131
+
132
+ require_once(WYSIJA_WIDGETS.'wysija_nl.php');
133
+ $widget_NL=new WYSIJA_NL_Widget(true);
134
+ $widget_NL->iFrame=true;
135
+ $subscription_form = $widget_NL->widget($widget_data,$widget_data);
136
+ $subscription_form = str_replace("</head>", '<script type="text/javascript">
137
+ /* <![CDATA[ */
138
+ var wysijaAJAX = {"action":"wysija_ajax","controller":"subscribers","ajaxurl":"'.admin_url('admin-ajax.php','absolute').'","loadingTrans":"'.__('Loading...',WYSIJA).'"};
139
+ /* ]]> */
140
+ </script></head>', $subscription_form);
141
+ echo $subscription_form;
142
+ exit;
143
+ }
144
+ }
trunk/controllers/index.html ADDED
File without changes
trunk/core/autoloader.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * Classes Autoloader.
5
+ * It loads automatically the right class on class instantation.
6
+ * Since we still can't use namespaces, we use 'WJ_' as a prefix for our classes.
7
+ * @param Class $class Class name
8
+ * @return
9
+ */
10
+ function wysija_classes_autoloader($class) {
11
+ // Check if the class name has our prefix.
12
+ if (strpos($class, 'WJ_') !== false) {
13
+ // Class file path.
14
+ $class_path = WYSIJA_CLASSES . $class . '.php';
15
+ // If the class file exists, let's load it.
16
+ if (file_exists($class_path)) {
17
+ require_once $class_path;
18
+ }
19
+ }
20
+ }
21
+
22
+ // This is the global PHP autoload register, where we register our autoloaders.
23
+ spl_autoload_register('wysija_classes_autoloader');
trunk/core/base.php ADDED
@@ -0,0 +1,1632 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Require constants.
3
+ require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'constants.php' );
4
+
5
+ // Require global classes autoloader
6
+ require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'autoloader.php' );
7
+
8
+ defined( 'WYSIJA' ) or die( 'Restricted access' );
9
+
10
+ global $wysija_msg, $wysija_wpmsg;
11
+ if ( ! $wysija_msg ) {
12
+ $wysija_msg = array();
13
+ }
14
+ $wysija_wpmsg = array();
15
+
16
+ class WYSIJA_object{
17
+
18
+ /**
19
+ * Static variable holding core MailPoet's version
20
+ * @var array
21
+ */
22
+ static $version = '2.7.15';
23
+
24
+ function __construct(){}
25
+
26
+ /**
27
+ * Order an array by param name string compare
28
+ *
29
+ * @param array $a Array with the param to compare
30
+ * @param array $b Array with the param to compare
31
+ * @return int Sorting result from strcmp
32
+ */
33
+ public static function sort_by_name( $a, $b ){
34
+ return strcmp( strtolower( $a['name'] ), strtolower( $b['name'] ) );
35
+ }
36
+
37
+ /**
38
+ * Returns the version of based on a path
39
+ *
40
+ * @filter mailpoet/get_version
41
+ * @filter mailpoet/package
42
+ *
43
+ * @param string $path
44
+ * @return string Version of the package
45
+ */
46
+ public static function get_version( $path = null ) {
47
+ $version = self::$version;
48
+ // Backwards compatibility for Premium Versions
49
+ if ( ! has_filter( 'mailpoet/get_version', '_filter_mailpoet_premium_version' ) && in_array( $path, array( 'premium', 'wysija-newsletters-premium', 'wysija-newsletters-premium/index.php' ) ) ){
50
+ if ( ! function_exists( 'get_plugin_data' ) ){
51
+ include_once ABSPATH . 'wp-admin/includes/plugin.php';
52
+ }
53
+ $plugin_data = get_plugin_data( dirname( dirname( plugin_dir_path( __FILE__ ) ) ) . '/wysija-newsletters-premium/index.php' );
54
+ $version = trim( $plugin_data['Version'] );
55
+ }
56
+
57
+ return apply_filters( 'mailpoet/get_version', $version, apply_filters( 'mailpoet/package', 'core', $path ) );
58
+ }
59
+
60
+ /**
61
+ * get the current_user data in a safe manner making sure a field exists before returning it's value
62
+ * @global type $current_user
63
+ * @param string $field
64
+ * @return mixed
65
+ */
66
+ public static function wp_get_userdata( $field = false ) {
67
+ //WordPress globals be careful there
68
+ global $current_user;
69
+ if ( $field ) {
70
+ if ( function_exists( 'wp_get_current_user' ) ) {
71
+ // Here is an exception because of one of the weirdest bug
72
+ // the idea is to make sure we don't call wp_get_current_user() on the wysija_subscribers page when on a multisite
73
+ if ( ! ( isset( $_GET['page'] ) && $_GET['page'] === 'wysija_subscribers' && is_multisite() ) ){
74
+ wp_get_current_user();
75
+ }
76
+ }
77
+ if ( isset( $current_user->{$field} ) ){
78
+ return $current_user->{$field};
79
+ } elseif ( isset( $current_user->data->{$field} ) ){
80
+ return $current_user->data->{$field};
81
+ } else {
82
+ return $current_user;
83
+ }
84
+ }
85
+ return $current_user;
86
+ }
87
+
88
+ /**
89
+ * set a global notice message
90
+ * @global array $wysija_wpmsg
91
+ * @param type $msg
92
+ */
93
+ function wp_notice( $msg ){
94
+ global $wysija_wpmsg;
95
+
96
+ //add the hook only once
97
+ if ( ! $wysija_wpmsg ) {
98
+ add_action( 'admin_notices', array( $this, 'wp_msgs' ) );
99
+ }
100
+
101
+ //record msgs
102
+ $wysija_wpmsg['updated'][] = $msg;
103
+ }
104
+
105
+ /**
106
+ * set a global error message
107
+ * @global array $wysija_wpmsg
108
+ * @param type $msg
109
+ */
110
+ function wp_error( $msg ){
111
+ global $wysija_wpmsg;
112
+
113
+ //add the hook only once
114
+ if ( ! $wysija_wpmsg ){
115
+ add_action( 'admin_notices', array( $this, 'wp_msgs' ) );
116
+ }
117
+
118
+ //record msgs
119
+ $wysija_wpmsg['error'][] = $msg;
120
+ }
121
+
122
+ /**
123
+ * prints a global message in the WordPress' backend identified as belonging to wysija
124
+ * we tend to avoid as much as possible printing messages globally, since this is ugly
125
+ * and make the administrators immune to beige-yellowish messages :/
126
+ * @global array $wysija_wpmsg
127
+ */
128
+ function wp_msgs() {
129
+ global $wysija_wpmsg;
130
+ foreach ( $wysija_wpmsg as $keymsg => $wp2 ){
131
+ $msgs = '<div class="' . $keymsg . ' fade">';
132
+ foreach ( $wp2 as $mymsg ){
133
+ $msgs .= '<p><strong>MailPoet</strong> : ' . $mymsg . '</p>';
134
+ }
135
+ $msgs .= '</div>';
136
+ }
137
+
138
+ // This is bad, we should be checking for valid HTML here.
139
+ echo $msgs;
140
+ }
141
+
142
+ /**
143
+ * returns an error message, it will appear as a red pinkish message in our interfaces
144
+ * @param string $msg
145
+ * @param boolean $public if set to true it will appear as a full message, otherwise it will appear behind a "Show more details." link
146
+ * @param boolean $global if set to true it will appear on all of the backend interfaces, not only wysija's own
147
+ */
148
+ function error( $msg, $public = false, $global = false ){
149
+ $status = 'error';
150
+ if ( $global ){
151
+ $status = 'g-' . $status;
152
+ }
153
+ $this->setInfo( $status, $msg, $public );
154
+ }
155
+
156
+ /**
157
+ * returns a success message, it will appear as a beige yellowish message in our interfaces
158
+ * @param string $msg
159
+ * @param boolean $public if set to true it will appear as a full message, otherwise it will appear behind a "Show more details." link
160
+ * @param boolean $global if set to true it will appear on all of the backend interfaces, not only wysija's own
161
+ */
162
+ function notice( $msg, $public = true, $global = false ){
163
+ $status = 'updated';
164
+ if ( $global ){
165
+ $status = 'g-' . $status;
166
+ }
167
+ $this->setInfo( $status, $msg, $public );
168
+ }
169
+
170
+ /**
171
+ * store all of the error and success messages in a global variable
172
+ * @global type $wysija_msg
173
+ * @param type $status whether this is a success message or an error message
174
+ * @param type $msg
175
+ * @param type $public if set to true it will appear as a full message, otherwise it will appear behind a "Show more details." link
176
+ */
177
+ static function setInfo($status,$msg,$public=false){
178
+ global $wysija_msg;
179
+ if(!$public) {
180
+
181
+ if(!isset($wysija_msg['private'][$status])){
182
+ $wysija_msg['private']=array();
183
+ $wysija_msg['private'][$status]=array();
184
+ }
185
+ array_push($wysija_msg['private'][$status], $msg);
186
+ }else{
187
+ if(!isset($wysija_msg[$status])) $wysija_msg[$status]=array();
188
+ array_push($wysija_msg[$status], $msg);
189
+ }
190
+
191
+ }
192
+
193
+ /**
194
+ * read the global function containing all of the error messages and print them
195
+ * @global type $wysija_msg
196
+ * @return type
197
+ */
198
+ function getMsgs(){
199
+ global $wysija_msg;
200
+
201
+ if(isset($wysija_msg['private']['error'])){
202
+ $wysija_msg['error'][]=str_replace(array('[link]','[/link]'),array('<a class="showerrors" href="javascript:;">','</a>'),__('An error occurred. [link]Show more details.[/link]',WYSIJA));
203
+ }
204
+
205
+ if(isset($wysija_msg['private']['updated'])){
206
+ $wysija_msg['updated'][]=str_replace(array('[link]','[/link]'),array('<a class="shownotices" href="javascript:;">','</a>'),__('[link]Show more details.[/link]',WYSIJA));
207
+ }
208
+ if(isset($wysija_msg['private'])){
209
+ $prv=$wysija_msg['private'];
210
+ unset($wysija_msg['private']);
211
+ if(isset($prv['error'])) $wysija_msg['xdetailed-errors']=$prv['error'];
212
+ if(isset($prv['updated'])) $wysija_msg['xdetailed-updated']=$prv['updated'];
213
+ }
214
+ return $wysija_msg;
215
+ }
216
+
217
+ /**
218
+ * If the current server is Windows-based
219
+ * @return boolean
220
+ */
221
+ public static function is_windows() {
222
+ $is_windows = false;
223
+ $windows = array(
224
+ 'windows nt',
225
+ 'windows',
226
+ 'winnt',
227
+ 'win32',
228
+ 'win'
229
+ );
230
+ $operating_system = strtolower( php_uname( 's' ) );
231
+ foreach ( $windows as $windows_name ) {
232
+ if (strpos($operating_system, $windows_name) !== false) {
233
+ $is_windows = true;
234
+ break;
235
+ }
236
+ }
237
+ return $is_windows;
238
+ }
239
+
240
+ }
241
+
242
+
243
+ class WYSIJA_help extends WYSIJA_object{
244
+ var $controller = null;
245
+
246
+ static $admin_body_class_runner = false;
247
+
248
+ function __construct(){
249
+ add_action( 'widgets_init', array( $this, 'widgets_init' ), 1 );
250
+
251
+ // Only load this when ajax is not used
252
+ if ( !( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
253
+ add_action( 'init', array( $this, 'register_scripts' ), 1 );
254
+ }
255
+
256
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
257
+ add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
258
+ }
259
+
260
+ function WYSIJA_help() { // TODO: remove in next version
261
+ add_action( 'widgets_init', array( $this, 'widgets_init' ), 1 );
262
+
263
+ // Only load this when ajax is not used
264
+ if ( !( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
265
+ add_action( 'init', array( $this, 'register_scripts' ), 1 );
266
+ }
267
+
268
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
269
+ add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
270
+ }
271
+
272
+ function widgets_init() {
273
+ //load the widget file
274
+ require_once(WYSIJA_WIDGETS.'wysija_nl.php');
275
+ register_widget( 'WYSIJA_NL_Widget' );
276
+ }
277
+
278
+ public function admin_enqueue_scripts(){
279
+ if ( WYSIJA_ITF ){
280
+ wp_enqueue_script( 'mailpoet-global' );
281
+ }
282
+ }
283
+
284
+ public function admin_body_class( $body_class_str ){
285
+
286
+ if ( WYSIJA_help::$admin_body_class_runner === true ){
287
+ return $body_class_str;
288
+ }
289
+
290
+ WYSIJA_help::$admin_body_class_runner = true;
291
+
292
+ global $wp_version;
293
+
294
+ $class = array();
295
+ if ( ! empty( $body_class_str ) ){
296
+ $class = explode( ' ', $body_class_str );
297
+ }
298
+
299
+ if ( '3.8' === $wp_version ){
300
+ $class[] = 'mp-menu-icon-font';
301
+ }
302
+
303
+ if ( version_compare( $wp_version, '3.8', '<' ) ){
304
+ $class[] = 'mp-menu-icon-bg';
305
+ } else {
306
+ $class[] = 'mpoet-ui';
307
+ }
308
+
309
+ return implode( ' ', $class );
310
+ }
311
+
312
+ function register_scripts(){
313
+ $helper_toolbox = WYSIJA::get('toolbox','helper');
314
+ $wp_language_code = $helper_toolbox->get_language_code();
315
+ $valid_language = array(
316
+ 'ar',
317
+ 'ca',
318
+ 'cs',
319
+ 'cz',
320
+ 'da',
321
+ 'de',
322
+ 'el',
323
+ 'es',
324
+ 'et',
325
+ 'fa',
326
+ 'fi',
327
+ 'fr',
328
+ 'he',
329
+ 'hr',
330
+ 'hu',
331
+ 'id',
332
+ 'it',
333
+ 'ja',
334
+ 'lt',
335
+ 'nl',
336
+ 'no',
337
+ 'pl',
338
+ 'pt',
339
+ 'pt_BR',
340
+ 'ro',
341
+ 'ru',
342
+ 'sv',
343
+ 'tr',
344
+ 'uk',
345
+ 'vi',
346
+ 'zh_CN',
347
+ 'zh_TW',
348
+ );
349
+
350
+
351
+ if ( in_array( $wp_language_code, $valid_language ) ) {
352
+ wp_register_script('wysija-validator-lang',WYSIJA_URL.'js/validate/languages/jquery.validationEngine-'.$wp_language_code.'.js', array( 'jquery' ),WYSIJA::get_version(),true );
353
+ }else{
354
+ wp_register_script('wysija-validator-lang',WYSIJA_URL.'js/validate/languages/jquery.validationEngine-en.js', array( 'jquery' ),WYSIJA::get_version(),true );
355
+ }
356
+ wp_register_script('wysija-validator',WYSIJA_URL.'js/validate/jquery.validationEngine.js', array( 'jquery' ),WYSIJA::get_version(),true );
357
+ wp_register_script('wysija-front-subscribers', WYSIJA_URL.'js/front-subscribers.js', array( 'jquery' ),WYSIJA::get_version(),true);
358
+
359
+ wp_register_script('wysija-form', WYSIJA_URL.'js/forms.js', array( 'jquery' ),WYSIJA::get_version());
360
+ wp_register_style('validate-engine-css',WYSIJA_URL.'css/validationEngine.jquery.css',array(),WYSIJA::get_version());
361
+ wp_register_script('wysija-admin-ajax', WYSIJA_URL.'js/admin-ajax.js',array(),WYSIJA::get_version());
362
+ wp_register_script('wysija-admin-ajax-proto', WYSIJA_URL.'js/admin-ajax-proto.js',array(),WYSIJA::get_version());
363
+ wp_register_script( 'mailpoet-global', WYSIJA_URL.'js/admin-global.js', array( 'jquery', 'underscore' ), WYSIJA::get_version() );
364
+
365
+ if(defined('WYSIJA_SIDE') && WYSIJA_SIDE=='front') wp_enqueue_style('validate-engine-css');
366
+
367
+ }
368
+
369
+
370
+ /**
371
+ * All the ajax requests are routed through here
372
+ */
373
+ function ajax() {
374
+
375
+ $result_array = array();
376
+ if( !$_REQUEST || !isset( $_REQUEST['controller'] ) || !isset( $_REQUEST['task'] ) ){
377
+ $result_array = array( 'result' => false );
378
+ }else{
379
+ $plugin_requesting_ajax = 'wysija-newsletters';
380
+
381
+ // we override the plugin resquesting ajax if specified in the request
382
+ if( !empty( $_REQUEST['wysijaplugin'] ) ){
383
+ $plugin_requesting_ajax = preg_replace('#[^a-z0-9\-_]#i','',$_REQUEST['wysijaplugin']);
384
+ }
385
+
386
+ // fetching the right controller
387
+ $this->controller = WYSIJA::get( $_REQUEST['controller'] , 'controller' , false, $plugin_requesting_ajax );
388
+
389
+ // let's make sure the requested task exist
390
+ if( method_exists( $this->controller , $_REQUEST['task'] ) ){
391
+ $result_array['result'] = call_user_func(array($this->controller, $_REQUEST['task']));
392
+ }else{
393
+ $this->error( 'Method "' . esc_html($_REQUEST['task']) . '" doesn\'t exist for controller : "'.esc_html($_REQUEST['controller']) );
394
+ }
395
+ }
396
+
397
+ // get the appended messages triggerred during the task execution
398
+ $result_array['msgs'] = $this->getMsgs();
399
+
400
+ // this header will allow ajax request from the home domain, this can be a lifesaver when domain mapping is on
401
+ if(function_exists('home_url')){
402
+ header('Access-Control-Allow-Origin: '.home_url());
403
+ }
404
+
405
+ // let's encode our response in the json format
406
+ $json_data = json_encode($result_array);
407
+
408
+ // in some case scenarios our client will have jQuery forcing the jsonp so we need to adapt ourselves
409
+ if(isset($_REQUEST['callback'])) {
410
+ // special header for json-p
411
+ header('Content-type: application/javascript');
412
+
413
+ $helper_jsonp = WYSIJA::get('jsonp', 'helper');
414
+ if($helper_jsonp->isValidCallback($_REQUEST['callback'])) {
415
+ print $_REQUEST['callback'] . '('.$json_data.');';
416
+ }
417
+ } else {
418
+ // standard header for unwrapped classic json response
419
+ header('Content-type: application/json');
420
+ print $json_data;
421
+ }
422
+ // our ajax response is printed, no need to let WordPress or 3rd party plugin execute more code
423
+ die();
424
+ }
425
+ }
426
+
427
+
428
+ class WYSIJA extends WYSIJA_object{
429
+
430
+ function __construct(){
431
+ parent::__construct();
432
+ }
433
+
434
+ /**
435
+ * function created at the beginning to handle particular cases with WP get_permalink it got much smaller recently
436
+ * @param int $pageid
437
+ * @param array $params
438
+ * @param boolean $simple
439
+ * @return type
440
+ */
441
+ public static function get_permalink( $pageid, $params = array(), $simple = false ){
442
+ $hWPtools = WYSIJA::get( 'wp_tools', 'helper' );
443
+ return $hWPtools->get_permalink( $pageid, $params, $simple );
444
+ }
445
+
446
+ /**
447
+ * translate the plugin
448
+ * @staticvar boolean $extensionloaded
449
+ * @param type $extendedplugin
450
+ * @return boolean
451
+ */
452
+ public static function load_lang( $extendedplugin = false ){
453
+ static $extensionloaded = false;
454
+
455
+ //we return the entire array of extensions loaded if non is specified
456
+ if ( ! $extendedplugin ) {
457
+ return $extensionloaded;
458
+ }
459
+
460
+ //we only need to load this translation loader once on init
461
+ if(!$extensionloaded){
462
+ add_action('init', array('WYSIJA','load_lang_init'));
463
+ }
464
+ //each plugin has a different name
465
+ if ( !$extensionloaded || !isset($extensionloaded[$extendedplugin])) {
466
+ $transstring = null;
467
+ switch($extendedplugin){
468
+ case 'wysija-newsletters':
469
+ $transstring=WYSIJA;
470
+ break;
471
+ case 'wysijashop':
472
+ $transstring=WYSIJASHOP;
473
+ break;
474
+ case 'wysijacrons':
475
+ $transstring=WYSIJACRONS;
476
+ break;
477
+ case 'wysija-newsletters-premium':
478
+ $transstring=WYSIJANLP;
479
+ break;
480
+ case 'get_all':
481
+ return $extensionloaded;
482
+ }
483
+
484
+ //store all the required translations to be loaded in the static variable
485
+ if($transstring !== null) {
486
+ $extensionloaded[$extendedplugin] = $transstring;
487
+ }
488
+ }
489
+ }
490
+
491
+ /**
492
+ * check if the user is tech support as this can be used to switch the language back to english when helping our customers
493
+ * @global type $current_user
494
+ * @param type $debugmode
495
+ * @return type
496
+ */
497
+ public static function is_wysija_admin($debugmode=false){
498
+ //to allow wysija team members to work in english mode if debug is activated
499
+ global $current_user;
500
+
501
+ if((int)$debugmode > 0 && empty($current_user)) return true;
502
+
503
+ if(isset($current_user->data->user_email) && (strpos($current_user->data->user_email, '@mailpoet.com') !== false)) {
504
+ return true;
505
+ }
506
+ return false;
507
+ }
508
+
509
+ /**
510
+ * this function exists just to fix the issue with qtranslate :/ (it only fix it partially)
511
+ * @param type $extended_plugin
512
+ */
513
+ public static function load_lang_init($extended_plugin=false){
514
+ $model_config = WYSIJA::get('config','model');
515
+ $debug_mode = (int)$model_config->getValue('debug_new');
516
+
517
+ if($debug_mode === 0 || ($debug_mode > 0 && WYSIJA::is_wysija_admin($debug_mode) === false)) {
518
+ $extensions_loaded = WYSIJA::load_lang('get_all');
519
+ foreach($extensions_loaded as $extended_plugin => $translation_string){
520
+
521
+ // check for translation file overriding from transstring wp-content/languages/wysija-newsletters/wysija-newsletters-en_US.mo
522
+ $filename = WP_CONTENT_DIR.DS.'languages'.DS.$extended_plugin.DS.$translation_string.'-'.get_locale().'.mo';
523
+
524
+ if( !file_exists($filename) ){
525
+ // get the translation file in our local file
526
+ $filename = WYSIJA_PLG_DIR.$extended_plugin.DS.'languages'.DS.$translation_string.'-'.get_locale().'.mo';
527
+ }
528
+
529
+ // load the translation file with WP's load_textdomain
530
+ if( file_exists( $filename ) ){
531
+ load_textdomain( $translation_string, $filename );
532
+ }
533
+ }
534
+ }
535
+ }
536
+
537
+ /**
538
+ * function to generate objects of different types, managing file requiring in order to be the most efficient
539
+ * @staticvar array $arrayOfObjects
540
+ * @param string $name
541
+ * @param string $type : in which folder do we go and pick the class
542
+ * @param boolean $force_side : this parameter is almost never set to true,
543
+ * it will be useful for instance if you want to get a back controller
544
+ * from the frontend, it was used maybe in the shop but it can be ignored for wysija-newsletters
545
+ * @param type $extended_plugin : used only when calling the url from a different plugin it is used watch those files :
546
+ * -core/controller.php line 21, 23 ,24
547
+ * @param type $load_lang : the load lang is in the get to be sure we don't forget to load the language file for each plugin at least once
548
+ * the way I see it it could be moved to the index.php of each plugin. for now only wysija-newsletters is translated anyway
549
+ * @return boolean
550
+ */
551
+ public static function get($name,$type,$force_side=false,$extended_plugin='wysija-newsletters',$load_lang=true){
552
+ static $array_of_objects;
553
+
554
+ if($load_lang) WYSIJA::load_lang($extended_plugin);
555
+
556
+ // store all the objects made so that we can reuse them accross the application if the object is already set we return it immediately
557
+ if(isset($array_of_objects[$extended_plugin][$type.$name])) {
558
+ return $array_of_objects[$extended_plugin][$type.$name];
559
+ }
560
+
561
+ // which folder do we pick for controllersand views ? back or front ?
562
+ if($force_side) {
563
+ $side=$force_side;
564
+ } else {
565
+ $side=WYSIJA_SIDE;
566
+ }
567
+
568
+ // for each plugin we will define the $extended_constant variable if it's not defined already
569
+ // also we will defined the $extended_plugin_name which corresponds to the folder name and also will be used to build the class to be called
570
+ switch($extended_plugin){
571
+ case 'wysija-newsletters-premium':
572
+ $extended_constant='WYSIJANLP';
573
+ if(!defined($extended_constant)) define($extended_constant,$extended_constant);
574
+ $extended_plugin_name='wysijanlp';
575
+ break;
576
+ case 'wysija-newsletters':
577
+ $extended_constant='WYSIJA';
578
+ if(!defined($extended_constant)) define($extended_constant,$extended_constant);
579
+ $extended_plugin_name='wysija';
580
+ break;
581
+ default :
582
+ $extended_constant=strtoupper($extended_plugin);
583
+ if(!defined($extended_constant)) define($extended_constant,$extended_constant);
584
+ $extended_plugin_name=$extended_plugin;
585
+ }
586
+
587
+ // security to protect against dangerous ./../ includes
588
+ $name = preg_replace('#[^a-z0-9_]#i','',$name);
589
+
590
+ // this switch will require_once the file needed and build a the class name depending on the parameters passed to the function
591
+ switch($type){
592
+ case 'controller':
593
+ // require the parent class necessary
594
+ require_once(WYSIJA_CORE.'controller.php');
595
+
596
+ $ctrdir=WYSIJA_PLG_DIR.$extended_plugin.DS.'controllers'.DS;
597
+ // Require module concept
598
+ require_once(WYSIJA_CORE.'module'.DS.'module.php');
599
+
600
+ // if we are doing ajax we don't go to one side, ajax is for frontend or backend in the same folder
601
+ if(defined('DOING_AJAX')) {
602
+ $class_path=$ctrdir.'ajax'.DS.$name.'.php';
603
+ }else {
604
+ // the other controllers are called in a side folder back or front
605
+ $class_path=$ctrdir.$side.DS.$name.'.php';
606
+ // require the side specific controller file
607
+ require_once(WYSIJA_CTRL.$side.'.php');
608
+ }
609
+ $class_name = strtoupper($extended_plugin_name).'_control_'.$side.'_'.$name;
610
+ break;
611
+ case 'view':
612
+ $viewdir=WYSIJA_PLG_DIR.$extended_plugin.DS.'views'.DS;
613
+ // let's get the right path for the view front or back and the right class_name
614
+ $class_path=$viewdir.$side.DS.$name.'.php';
615
+ $class_name = strtoupper($extended_plugin_name).'_view_'.$side.'_'.$name;
616
+
617
+ // require the common view file and the side view file
618
+ require_once(WYSIJA_CORE.'view.php');
619
+ require_once(WYSIJA_VIEWS.$side.'.php');
620
+ break;
621
+ case 'helper':
622
+ $helpdir=WYSIJA_PLG_DIR.$extended_plugin.DS.'helpers'.DS;
623
+ $class_path=$helpdir.$name.'.php';
624
+ $class_name = strtoupper($extended_plugin_name).'_help_'.$name;
625
+
626
+ break;
627
+ case 'model':
628
+ $modeldir=WYSIJA_PLG_DIR.$extended_plugin.DS.'models'.DS;
629
+ $class_path=$modeldir.$name.'.php';
630
+ $class_name = strtoupper($extended_plugin_name).'_model_'.$name;
631
+ // require the parent class necessary
632
+ require_once(WYSIJA_CORE.'model.php');
633
+ break;
634
+ case 'widget':
635
+ $modeldir=WYSIJA_PLG_DIR.$extended_plugin.DS.'widgets'.DS;
636
+ $class_path=$modeldir.$name.'.php';
637
+ if($name=='wysija_nl') $class_name='WYSIJA_NL_Widget';
638
+ else $class_name = strtoupper($extended_plugin_name).'_widget_'.$name;
639
+ break;
640
+
641
+ case 'module':
642
+ $moduledir = WYSIJA_PLG_DIR . $extended_plugin . DS . 'modules' . DS;
643
+ if (file_exists($moduledir . $name . '.php'))
644
+ $class_path = $moduledir . $name . '.php';
645
+ elseif (file_exists($moduledir . $name . DS . $name . '.php'))
646
+ $class_path = $moduledir . $name . DS . $name . '.php';
647
+ else
648
+ return;
649
+ $class_name = strtoupper($extended_plugin_name) . '_module_' . $name;
650
+ // require the parent class necessary
651
+ //require_once(WYSIJA_CORE.'module'.DS.'module.php');
652
+ require_once(WYSIJA_CORE . 'module' . DS . 'statistics_model.php');
653
+ require_once(WYSIJA_CORE . 'module' . DS . 'statistics.php');
654
+ require_once(WYSIJA_CORE . 'module' . DS . 'statisticschart.php');
655
+ require_once(WYSIJA_CORE . 'module' . DS . 'statisticstable.php');
656
+
657
+ break;
658
+
659
+ default:
660
+ WYSIJA::setInfo('error','WYSIJA::get does not accept this type of file "'.$type.'" .');
661
+ return false;
662
+ }
663
+
664
+ if(!file_exists($class_path)) {
665
+ if(is_admin() && WYSIJA::current_user_can('switch_themes')){
666
+ WYSIJA::setInfo('error','file has not been recognised '.$class_path);
667
+ WYSIJA::setInfo('error',$class_name);
668
+ WYSIJA::setInfo('error',$type);
669
+ }
670
+ return;
671
+ }
672
+
673
+ // require the file needed once and store & return the object needed
674
+ require_once($class_path);
675
+ return $array_of_objects[$extended_plugin][$type.$name]=new $class_name($extended_plugin_name);
676
+
677
+ }
678
+
679
+ /**
680
+ * log function to spot some strange issues when sending emails for instance
681
+ * @param type $key
682
+ * @param type $data
683
+ * @param type $category
684
+ * @return type
685
+ */
686
+ public static function log($key='default',$data='empty',$category='default'){
687
+ $config=WYSIJA::get('config','model');
688
+
689
+ if((int)$config->getValue('debug_new')>1 && $category && $config->getValue('debug_log_'.$category)){
690
+
691
+ $optionlog=get_option('wysija_log');
692
+
693
+
694
+ $optionlog[$category][(string)microtime(true)][$key]=$data;
695
+
696
+ WYSIJA::update_option('wysija_log' , $optionlog);
697
+ }
698
+ return false;
699
+ }
700
+
701
+ /**
702
+ * the filter to add option to the cron frequency instead of being stuck with hourly, daily and twicedaily...
703
+ * we can add filters but we cannot delete other values such as the default ones, as this might break other plugins crons
704
+ * @param type $param
705
+ * @return type
706
+ */
707
+ public static function filter_cron_schedules( $param ) {
708
+ $frequencies=array(
709
+ 'one_min' => array(
710
+ 'interval' => 60,
711
+ 'display' => __( 'Once every minute',WYSIJA)
712
+ ),
713
+ 'two_min' => array(
714
+ 'interval' => 120,
715
+ 'display' => __( 'Once every two minutes',WYSIJA)
716
+ ),
717
+ 'five_min' => array(
718
+ 'interval' => 300,
719
+ 'display' => __( 'Once every five minutes',WYSIJA)
720
+ ),
721
+ 'ten_min' => array(
722
+ 'interval' => 600,
723
+ 'display' => __( 'Once every ten minutes',WYSIJA)
724
+ ),
725
+ 'fifteen_min' => array(
726
+ 'interval' => 900,
727
+ 'display' => __( 'Once every fifteen minutes',WYSIJA)
728
+ ),
729
+ 'thirty_min' => array(
730
+ 'interval' => 1800,
731
+ 'display' => __( 'Once every thirty minutes',WYSIJA)
732
+ ),
733
+ 'two_hours' => array(
734
+ 'interval' => 7200,
735
+ 'display' => __( 'Once every two hours',WYSIJA)
736
+ ),
737
+ 'eachweek' => array(
738
+ 'interval' => 604800,
739
+ 'display' => __( 'Once a week',WYSIJA)
740
+ ),
741
+ 'each28days' => array(
742
+ 'interval' => 2419200,
743
+ 'display' => __( 'Once every 28 days',WYSIJA)
744
+ ),
745
+ );
746
+
747
+ return array_merge($param, $frequencies);
748
+ }
749
+
750
+ /**
751
+ * scheduled task for sending the emails in the queue, the frequency is set in the settings
752
+ */
753
+ public static function croned_queue( $check_scheduled_newsletter = true) {
754
+
755
+ // check the scheduled tasks only if it's a standard WP scheduled task free only
756
+ if($check_scheduled_newsletter){
757
+ WYSIJA::check_scheduled_newsletters();
758
+ }
759
+
760
+ $model_config = WYSIJA::get('config','model');
761
+ // check that the 2000 limit is not passed and process the queue
762
+
763
+ if((int)$model_config->getValue('total_subscribers') < 2000 ){
764
+ $helper_queue = WYSIJA::get('queue','helper');
765
+ $helper_queue->report=false;
766
+ WYSIJA::log('croned_queue process',true,'cron');
767
+
768
+ $helper_queue->process();
769
+ }
770
+
771
+ }
772
+
773
+ public static function check_scheduled_newsletters(){
774
+ $last_scheduled_check = get_option('wysija_last_scheduled_check');
775
+
776
+ // if the latest post notification check was done more than five minutes ago let's check it again
777
+ if(empty($last_scheduled_check) || ( time() > ($last_scheduled_check + 300) ) ){
778
+ // create the scheduled automatic post notifications email if there are any
779
+ $helper_autonews = WYSIJA::get('autonews','helper');
780
+ $helper_autonews->checkPostNotif();
781
+
782
+ // queue the scheduled newsletter also if there are any
783
+ $helper_autonews->checkScheduled();
784
+ WYSIJA::update_option('wysija_last_scheduled_check', time());
785
+ }
786
+
787
+ // send daily report about emails sent
788
+ $model_config = WYSIJA::get('config','model');
789
+ if($model_config->getValue('emails_notified_when_dailysummary')){
790
+ $helper_notification = WYSIJA::get('notifications','helper');
791
+ $helper_notification->send_daily_report();
792
+ }
793
+
794
+ }
795
+
796
+
797
+ /**
798
+ * everyday we make sure not to leave any trash files
799
+ * remove temporary files
800
+ */
801
+ public static function croned_daily() {
802
+
803
+ @ini_set('max_execution_time',0);
804
+
805
+ /*user refresh count total*/
806
+ $helper_user = WYSIJA::get('user','helper');
807
+ $helper_user->refreshUsers();
808
+
809
+ /*user domain generation*/
810
+ $helper_user->generate_domains();
811
+
812
+ /*clear temporary folders*/
813
+ $helper_file = WYSIJA::get('file','helper');
814
+ $helper_file->clear();
815
+
816
+ /*clear queue from unsubscribed*/
817
+ $helper_queue = WYSIJA::get('queue','helper');
818
+ $helper_queue->clear();
819
+
820
+
821
+ }
822
+
823
+ // Weekly cron
824
+ public static function croned_weekly() {
825
+
826
+ @ini_set('max_execution_time',0);
827
+
828
+ $model_config = WYSIJA::get('config','model');
829
+
830
+ // If enabled, flag MixPanel sending on next page load.
831
+ if ($model_config->getValue('analytics') == 1) {
832
+ $model_config->save(array('send_analytics_now' => 1));
833
+ }
834
+
835
+ }
836
+
837
+ // Monthly cron
838
+ public static function croned_monthly() {
839
+
840
+ @ini_set('max_execution_time',0);
841
+
842
+ $model_config = WYSIJA::get('config','model');
843
+
844
+ /* send daily report about emails sent */
845
+ if ($model_config->getValue('sharedata')) {
846
+ $helper_stats = WYSIJA::get('stats','helper');
847
+ $helper_stats->share();
848
+ }
849
+
850
+ }
851
+
852
+ /**
853
+ * when we deactivate the plugin we clear the WP install from those cron records
854
+ */
855
+ public static function deactivate() {
856
+ wp_clear_scheduled_hook('wysija_cron_queue');
857
+ wp_clear_scheduled_hook('wysija_cron_bounce');
858
+ wp_clear_scheduled_hook('wysija_cron_daily');
859
+ wp_clear_scheduled_hook('wysija_cron_weekly');
860
+ wp_clear_scheduled_hook('wysija_cron_monthly');
861
+ }
862
+
863
+
864
+ /**
865
+ * wysija's redirect allows to save some variables for the next page load such as notices etc..
866
+ * @global type $wysija_msg
867
+ * @global type $wysija_queries
868
+ * @global type $wysija_queries_errors
869
+ * @param type $location
870
+ */
871
+ public static function redirect($location) {
872
+ //save the messages
873
+ global $wysija_msg,$wysija_queries,$wysija_queries_errors;
874
+ WYSIJA::update_option('wysija_msg',$wysija_msg);
875
+ WYSIJA::update_option('wysija_queries',$wysija_queries);
876
+ WYSIJA::update_option('wysija_queries_errors',$wysija_queries_errors);
877
+
878
+ // make sure we encode square brackets as wp_redirect will strip them off
879
+ $location = str_replace(array('[', ']'), array('%5B', '%5D'), $location);
880
+
881
+ // redirect to specified location
882
+ wp_redirect($location);
883
+ exit;
884
+ }
885
+
886
+ /**
887
+ * custom post type for wysija is call wysijap as in wysija's post
888
+ */
889
+ public static function create_post_type() {
890
+
891
+ //by default there is url rewriteing on wysijap custom post, though in one client case I had to deactivate it.
892
+ //as this is rare we just need to set this setting to activate it
893
+ //by default let's deactivate the url rewriting of the wysijap confirmation page because it is breaking in some case.
894
+ $show_interface=false;
895
+ if(defined('WYSIJA_DBG') && WYSIJA_DBG>1) $show_interface=true;
896
+ register_post_type( 'wysijap',
897
+ array(
898
+ 'labels' => array(
899
+ 'name' => __('MailPoet page'),
900
+ 'singular_name' => __('MailPoet page')
901
+ ),
902
+ 'public' => true,
903
+ 'has_archive' => false,
904
+ 'show_ui' =>$show_interface,
905
+ 'show_in_menu' =>$show_interface,
906
+ 'rewrite' => false,
907
+ 'show_in_nav_menus'=>false,
908
+ 'can_export'=>false,
909
+ 'publicly_queryable'=>true,
910
+ 'exclude_from_search'=>true,
911
+ )
912
+ );
913
+
914
+ if(!get_option('wysija_post_type_updated')) {
915
+ $modelPosts=new WYSIJA_model();
916
+ $modelPosts->tableWP=true;
917
+ $modelPosts->table_prefix='';
918
+ $modelPosts->table_name='posts';
919
+ $modelPosts->noCheck=true;
920
+ $modelPosts->pk='ID';
921
+ if($modelPosts->exists(array('post_type'=>'wysijapage'))){
922
+ $modelPosts->update(array('post_type'=>'wysijap'),array('post_type'=>'wysijapage'));
923
+ flush_rewrite_rules( false );
924
+ }
925
+ WYSIJA::update_option('wysija_post_type_updated',time());
926
+ }
927
+
928
+ if(!get_option('wysija_post_type_created')) {
929
+ flush_rewrite_rules( false );
930
+ WYSIJA::update_option('wysija_post_type_created',time());
931
+ }
932
+
933
+ }
934
+
935
+ /**
936
+ * wysija update_option function is very similar to WordPress' one but it
937
+ * can also manage new options not automatically loaded each time
938
+ * @param type $option_name
939
+ * @param type $newvalue
940
+ * @param type $defaultload this parameter is the advantage other Wp's update_option here
941
+ */
942
+ public static function update_option($option_name,$newvalue,$defaultload='no'){
943
+ if ( get_option( $option_name ) != $newvalue ) {
944
+ update_option( $option_name, $newvalue );
945
+ } else {
946
+ add_option( $option_name, $newvalue, '', $defaultload );
947
+ }
948
+ }
949
+
950
+ /**
951
+ * When a WordPress user is added we also need to add it to the subscribers list
952
+ * @param type $user_id
953
+ * @return type
954
+ */
955
+ public static function hook_add_WP_subscriber($user_id) {
956
+ $data=get_userdata($user_id);
957
+
958
+
959
+ //check first if a subscribers exists if it doesn't then let's insert it
960
+ $model_config=WYSIJA::get('config','model');
961
+ $model_user=WYSIJA::get('user','model');
962
+ $model_user->getFormat=ARRAY_A; // there is one case where we were getting an object instead of an array
963
+ $subscriber_exists=$model_user->getOne(array('user_id'),array('email'=>$data->user_email));
964
+
965
+ $first_name=$data->first_name;
966
+ $last_name=$data->last_name;
967
+ if(!$data->first_name && !$data->last_name) $first_name=$data->display_name;
968
+
969
+ $model_user->reset();
970
+ if($subscriber_exists){
971
+ $user_id=$subscriber_exists['user_id'];
972
+ // we need to update the current subscriber using it's id
973
+ $model_user->update(array('wpuser_id'=>$data->ID,'firstname'=>$first_name,'lastname'=>$last_name),array('user_id'=>$user_id));
974
+ }else{
975
+ $model_user->noCheck=true;
976
+ $user_id=$model_user->insert(array('email'=>$data->user_email,'wpuser_id'=>$data->ID,'firstname'=>$first_name,'lastname'=>$last_name,'status'=>$model_config->getValue('confirm_dbleoptin')));
977
+ }
978
+
979
+ $model_user_list=WYSIJA::get('user_list','model');
980
+ $model_user_list->insert(array('user_id'=>$user_id,'list_id'=>$model_config->getValue('importwp_list_id'),'sub_date'=>time()),true);
981
+
982
+ $helper_user=WYSIJA::get('user','helper');
983
+ $helper_user->sendAutoNl($user_id,$data,'new-user');
984
+ return true;
985
+ }
986
+
987
+ /**
988
+ * when a WordPress user is updated we also need to update the corresponding subscriber
989
+ * @param type $user_id
990
+ * @return type
991
+ */
992
+ public static function hook_edit_WP_subscriber($user_id) {
993
+ $data=get_userdata($user_id);
994
+
995
+ //check first if a subscribers exists if it doesn't then let's insert it
996
+ $model_user=WYSIJA::get('user','model');
997
+ $model_config=WYSIJA::get('config','model');
998
+ $model_user_list=WYSIJA::get('user_list','model');
999
+ $model_user->getFormat = ARRAY_A;
1000
+ $subscriber_exists=$model_user->getOne(array('user_id'),array('email'=>$data->user_email));
1001
+
1002
+ $model_user->reset();
1003
+
1004
+ $first_name=$data->first_name;
1005
+ $last_name=$data->last_name;
1006
+ if(!$data->first_name && !$data->last_name) $first_name=$data->display_name;
1007
+
1008
+ if($subscriber_exists){
1009
+ $user_id=$subscriber_exists['user_id'];
1010
+
1011
+ $model_user->update(array('wpuser_id'=>$data->ID, 'email'=>$data->user_email,'firstname'=>$first_name,'lastname'=>$last_name),array('user_id'=>$user_id));
1012
+
1013
+ $result=$model_user_list->getOne(false,array('user_id'=>$user_id,'list_id'=>$model_config->getValue('importwp_list_id')));
1014
+ $model_user_list->reset();
1015
+ if(!$result)
1016
+ $model_user_list->insert(array('user_id'=>$user_id,'list_id'=>$model_config->getValue('importwp_list_id'),'sub_date'=>time()));
1017
+ }else{
1018
+ //chck that we didnt update the email
1019
+ $subscriber_exists=$model_user->getOne(false,array('wpuser_id'=>$data->ID));
1020
+
1021
+ if($subscriber_exists){
1022
+ $user_id=$subscriber_exists['user_id'];
1023
+
1024
+ $model_user->update(array('email'=>$data->user_email,'firstname'=>$first_name,'lastname'=>$last_name),array('wpuser_id'=>$data->ID));
1025
+
1026
+ $result=$model_user_list->getOne(false,array('user_id'=>$user_id,'list_id'=>$model_config->getValue('importwp_list_id')));
1027
+ $model_user_list->reset();
1028
+ if(!$result)
1029
+ $model_user_list->insert(array('user_id'=>$user_id,'list_id'=>$model_config->getValue('importwp_list_id'),'sub_date'=>time()));
1030
+ }else{
1031
+ $model_user->noCheck=true;
1032
+ $user_id=$model_user->insert(array('email'=>$data->user_email,'wpuser_id'=>$data->ID,'firstname'=>$first_name,'lastname'=>$last_name,'status'=>$model_config->getValue('confirm_dbleoptin')));
1033
+ $model_user_list->insert(array('user_id'=>$user_id,'list_id'=>$model_config->getValue('importwp_list_id'),'sub_date'=>time()));
1034
+ }
1035
+ }
1036
+ return true;
1037
+ }
1038
+
1039
+ /**
1040
+ * when a wp user is deleted we also delete the subscriber corresponding to it
1041
+ * @param type $user_id
1042
+ */
1043
+ public static function hook_del_WP_subscriber($user_id) {
1044
+ $model_config=WYSIJA::get('config','model');
1045
+ $model_user=WYSIJA::get('user','model');
1046
+ $data = $model_user->getOne(array('email','user_id'),array('wpuser_id'=>$user_id));
1047
+ if(isset($data['email'])) {
1048
+ $model_user->delete(array('email'=>$data['email']));
1049
+ }
1050
+ if(isset($data['user_id'])) {
1051
+ $model_user = WYSIJA::get('user_list','model');
1052
+ $model_user->delete(array('user_id'=>$data['user_id'],'list_id'=>$model_config->getValue('importwp_list_id')));
1053
+ }
1054
+ }
1055
+
1056
+
1057
+ public static function hook_auto_newsletter_refresh($post_id) {
1058
+ $helper_autonews = WYSIJA::get('autonews', 'helper');
1059
+ $helper_autonews->refresh_automatic_content();
1060
+
1061
+ return true;
1062
+ }
1063
+
1064
+ /**
1065
+ * post notification transition hook, know when a post really gets published
1066
+ * @param type $new_status
1067
+ * @param type $old_status
1068
+ * @param type $post
1069
+ * @return type
1070
+ */
1071
+ public static function hook_postNotification_transition($new_status, $old_status, $post) {
1072
+ //we run some process only if the status of the post changes from something to publish
1073
+ if($new_status === 'publish' && $old_status !== $new_status) {
1074
+ $model_email = WYSIJA::get('email', 'model');
1075
+ $emails = $model_email->get(false, array('type' => 2, 'status' => array(1, 3, 99)));
1076
+
1077
+ if(!empty($emails)) {
1078
+ //we loop through all of the automatic emails
1079
+ foreach($emails as $key => $email) {
1080
+
1081
+ //we will try to give birth to a child email only if the automatic newsletter is a post notification email and in immediate mode
1082
+ if(is_array($email) && $email['params']['autonl']['event'] === 'new-articles' && $email['params']['autonl']['when-article'] === 'immediate') {
1083
+ // set default include/exclude categories
1084
+ $include_category_ids = array();
1085
+ $exclude_category_ids = array();
1086
+
1087
+ // ALC need to check for post_type on each block of the autoposts
1088
+ $wj_data = maybe_unserialize( base64_decode( $email['wj_data'] ) );
1089
+ $post_types = array();
1090
+ $has_alc_blocks = false;
1091
+
1092
+ foreach ( $wj_data['body'] as $block_key => $block ){
1093
+ if ( $block['type'] !== 'auto-post' ){
1094
+ continue;
1095
+ }
1096
+
1097
+ $has_alc_blocks = true;
1098
+
1099
+ // get post type and post categories from block parameters
1100
+ foreach( $block['params'] as $param_data ) {
1101
+ if(in_array($param_data['key'], array('post_type', 'cpt')) && strlen(trim($param_data['value'])) > 0) {
1102
+ // store post type
1103
+ $post_types[] = trim($param_data['value']);
1104
+ } else if($param_data['key'] === 'category_ids' && strlen(trim($param_data['value'])) > 0) {
1105
+ // store post category ids
1106
+ $include_category_ids = array_map('intval', explode(',', trim($param_data['value'])));
1107
+ }
1108
+ }
1109
+ }
1110
+
1111
+ if ( $has_alc_blocks === true && ! in_array( $post->post_type, $post_types ) ) {
1112
+ continue;
1113
+ }
1114
+
1115
+ // get post categories
1116
+ $helper_wp_tools = WYSIJA::get('wp_tools', 'helper');
1117
+ $taxonomies = $helper_wp_tools->get_post_category_ids($post);
1118
+
1119
+ // assume the post has to be sent
1120
+ $do_send_post = true;
1121
+
1122
+ // post categories have to match at least one of the email's included categories
1123
+ $include_intersection = array_intersect($taxonomies, $include_category_ids);
1124
+ if(!empty($include_category_ids) && empty($include_intersection)) {
1125
+ $do_send_post = false;
1126
+ }
1127
+
1128
+ $exclude_intersection = array_intersect($taxonomies, $exclude_category_ids);
1129
+ // post categories should not match any one of the email's excluded categories
1130
+ if(!empty($exclude_category_ids) && !empty($exclude_intersection)) {
1131
+ $do_send_post = false;
1132
+ }
1133
+
1134
+ if($do_send_post) {
1135
+ WYSIJA::log('post_transition_hook_give_birth', array(
1136
+ 'post_id' => $post->ID,
1137
+ 'post_title' => $post->post_title,
1138
+ 'newsletter' => $email,
1139
+ 'old_status' => $old_status,
1140
+ 'new_status' => $new_status
1141
+ ),'post_notif');
1142
+
1143
+ $model_email->reset();
1144
+ $model_email->give_birth($email, $post->ID);
1145
+ }
1146
+ }
1147
+ }
1148
+ }
1149
+
1150
+ // we check for automatic latest content widget in automatic newsletter
1151
+ $helper_autonews = WYSIJA::get('autonews', 'helper');
1152
+ $helper_autonews->refresh_automatic_content();
1153
+ }
1154
+
1155
+ return true;
1156
+ }
1157
+
1158
+ /**
1159
+ * uninstall process not used
1160
+ */
1161
+ public static function uninstall(){
1162
+ $helperUS=WYSIJA::get('uninstall','helper');
1163
+ $helperUS->uninstall();
1164
+ }
1165
+
1166
+ /**
1167
+ * this function is run when wysija gets activated
1168
+ * there is no installation process here, all is about checking the global status of the app
1169
+ */
1170
+ public static function activate(){
1171
+ $encoded_option=get_option('wysija');
1172
+ $installApp=false;
1173
+ if($encoded_option){
1174
+ $values=unserialize(base64_decode($encoded_option));
1175
+ if(isset($values['installed'])) $installApp=true;
1176
+ }
1177
+
1178
+ //test again for plugins on reactivation
1179
+ if($installApp){
1180
+ $helper_import=WYSIJA::get('plugins_import','helper');
1181
+ $helper_import->testPlugins();
1182
+
1183
+ //resynch wordpress list
1184
+ $helper_user=WYSIJA::get('user','helper');
1185
+ $helper_user->synchList($values['importwp_list_id']);
1186
+ }
1187
+ }
1188
+
1189
+ /**
1190
+ * the is_plugin_active functions from WordPress sometimes are not loaded so here is one that works for single and multisites anywhere in the code
1191
+ * @param type $pluginName
1192
+ * @return type
1193
+ */
1194
+ public static function is_plugin_active($pluginName){
1195
+ $arrayactiveplugins=get_option('active_plugins');
1196
+ //we check in the list of the site options if the plugin is activated
1197
+ if(in_array($pluginName, $arrayactiveplugins)) {
1198
+ //plugin is activated for that site
1199
+ return true;
1200
+ }
1201
+
1202
+ //if this is a multisite it might not be activated in the site option but network activated though
1203
+ if(is_multisite()){
1204
+ $plugins = get_site_option('active_sitewide_plugins');
1205
+ //plugin is activated for that multisite
1206
+ if(isset($plugins[$pluginName])){
1207
+ return true;
1208
+ }
1209
+ }
1210
+ return false;
1211
+ }
1212
+
1213
+ /**
1214
+ * make sure that the current user has the good access rights corresponding to its role
1215
+ * @global type $current_user
1216
+ * @return type
1217
+ */
1218
+ public static function update_user_caps(){
1219
+ global $current_user;
1220
+
1221
+ if(empty($current_user) && function_exists('wp_get_current_user')) wp_get_current_user();
1222
+ if(empty($current_user)) return false;
1223
+ $current_user->get_role_caps();
1224
+
1225
+ return true;
1226
+ }
1227
+
1228
+ /**
1229
+ * test whether the plugin is a beta version or not
1230
+ * 2.4.4.4 is a beta
1231
+ * 2.4.4 is a bug fix release
1232
+ * 2.4 is a feature release
1233
+ * @param string $plugin_name
1234
+ */
1235
+ public static function is_beta($plugin_name=false){
1236
+ // exceptions
1237
+ $not_beta_versions = array('2.5.9.1', '2.5.9.2', '2.5.9.3', "2.5.9.4");
1238
+ $mailpoet_version = WYSIJA::get_version($plugin_name);
1239
+ if(in_array($mailpoet_version, $not_beta_versions)) return false;
1240
+
1241
+ // standard way of defining a beta version
1242
+ if(count(explode('.', $mailpoet_version)) > 3 ) return true;
1243
+ return false;
1244
+ }
1245
+
1246
+ /**
1247
+ * depending where it's used the base function from WordPress doesn't work, so this one will work anywhere
1248
+ * @param type $capability
1249
+ * @return type
1250
+ */
1251
+ public static function current_user_can($capability){
1252
+ if(!$capability) return false;
1253
+ WYSIJA::update_user_caps();
1254
+ if(!current_user_can($capability)) return false;
1255
+ return true;
1256
+ }
1257
+
1258
+ /**
1259
+ * this function get and sets the cron schedules when MailPoet's own cron system is active
1260
+ * @staticvar type $cron_schedules
1261
+ * @param type $schedule
1262
+ * @return type
1263
+ */
1264
+ public static function get_cron_schedule($schedule='queue'){
1265
+ static $cron_schedules;
1266
+
1267
+ //if the cron schedules are already loaded statically then we just have to return the right schedule value
1268
+ if(!empty($cron_schedules)){
1269
+ if($schedule=='all') return $cron_schedules;
1270
+ if(isset($cron_schedules[$schedule])) {
1271
+ return $cron_schedules[$schedule];
1272
+ }else{
1273
+ WYSIJA::set_cron_schedule($schedule);
1274
+ return false;
1275
+ }
1276
+ }else{
1277
+ //this is the first time this function is executed so let's get them from the db and store them statically
1278
+ $cron_schedules=get_option('wysija_schedules',array());
1279
+ if(!empty($cron_schedules)){
1280
+ if(isset($cron_schedules[$schedule])) return $cron_schedules[$schedule];
1281
+ else return false;
1282
+ }else{
1283
+ WYSIJA::set_cron_schedule();
1284
+ return false;
1285
+ }
1286
+ }
1287
+ return false;
1288
+ }
1289
+
1290
+ /**
1291
+ * return the frequency for each cron task needed by MailPoet
1292
+ * @return type an array of frequencies
1293
+ */
1294
+ public static function get_cron_frequencies(){
1295
+ $model_config = WYSIJA::get('config','model');
1296
+ $helper_forms = WYSIJA::get('forms','helper');
1297
+
1298
+ if(is_multisite() && $model_config->getValue('sending_method')=='network'){
1299
+ $sending_emails_each = $model_config->getValue('ms_sending_emails_each');
1300
+ }else{
1301
+ $sending_emails_each = $model_config->getValue('sending_emails_each');
1302
+ }
1303
+
1304
+ $queue_frequency = $helper_forms->eachValuesSec[$sending_emails_each];
1305
+ $bounce_frequency = 99999999999999;
1306
+ if(isset($helper_forms->eachValuesSec[$model_config->getValue('bouncing_emails_each')])){
1307
+ $bounce_frequency = $helper_forms->eachValuesSec[$model_config->getValue('bouncing_emails_each')];
1308
+ }
1309
+ return array('queue'=>$queue_frequency,'bounce'=>$bounce_frequency,'daily'=>86400,'weekly'=>604800,'monthly'=>2419200);
1310
+ }
1311
+
1312
+ /**
1313
+ * set the next cron schedule
1314
+ * TODO : needs probably to make the difference of running process for the next schedule, so that there is no delay(this is only problematic on some slow servers)
1315
+ * @param string $schedule
1316
+ * @param int $last_saved
1317
+ * @param boolean $set_running
1318
+ * @return boolean
1319
+ */
1320
+ public static function set_cron_schedule($schedule = false , $last_saved = 0 , $set_running = false){
1321
+ $cron_schedules = array();
1322
+
1323
+ $start_time = $last_saved;
1324
+ if(!$start_time) $start_time = time();
1325
+ $processes = WYSIJA::get_cron_frequencies();
1326
+ if(!$schedule){
1327
+ foreach($processes as $process => $frequency){
1328
+ $next_schedule = $start_time + $frequency;
1329
+ $prev_schedule = 0;
1330
+ if(isset($cron_schedules[$process]['running']) && $cron_schedules[$process]['running']) $prev_schedule=$cron_schedules[$process]['running'];
1331
+ $cron_schedules[$process]=array(
1332
+ 'next_schedule' => $next_schedule,
1333
+ 'prev_schedule' => $prev_schedule,
1334
+ 'running' => false);
1335
+ }
1336
+ }else{
1337
+ $cron_schedules = WYSIJA::get_cron_schedule('all');
1338
+ if($set_running){
1339
+ $cron_schedules[$schedule]['running'] = $set_running;
1340
+ }else{
1341
+ $running = 0;
1342
+ if(isset($cron_schedules[$schedule]['running'])) $running = $cron_schedules[$schedule]['running'];
1343
+ // if the process is not running or has been running for more than 15 minutes then we set the next_schedule date
1344
+ $process_frequency = $processes[$schedule];
1345
+
1346
+ if(!$running || ( time() > ($running + $process_frequency) ) ){
1347
+
1348
+ $next_schedule = $start_time + $process_frequency;
1349
+ // if the next schedule is already behind, we give it 30 seconds before it can triggers again
1350
+ if( $next_schedule < $start_time ){
1351
+ $next_schedule = $start_time + 30;
1352
+ }
1353
+
1354
+ $cron_schedules[$schedule] = array(
1355
+ 'next_schedule' => $next_schedule,
1356
+ 'prev_schedule' => $running,
1357
+ 'running' => false);
1358
+ }
1359
+ }
1360
+ }
1361
+ WYSIJA::update_option( 'wysija_schedules' , $cron_schedules , 'yes' );
1362
+ return true;
1363
+ }
1364
+
1365
+ /**
1366
+ * check that there is no passed schedules that need to be executed now
1367
+ * @return void
1368
+ */
1369
+ public static function cron_check() {
1370
+
1371
+ $cron_schedules = WYSIJA::get_cron_schedule('all');
1372
+ if(empty($cron_schedules)) return;
1373
+ else{
1374
+ $processes = WYSIJA::get_cron_frequencies();
1375
+
1376
+ $updated_sched = false;
1377
+ foreach($cron_schedules as $schedule => &$params){
1378
+ $running = 0;
1379
+ $time_now = time();
1380
+ if(isset($params['running'])) $running = $params['running'];
1381
+ //if the process has timedout we reschedule the next execution
1382
+ if($running && ( $time_now> ($running + $processes[$schedule]) ) ){
1383
+ //WYSIJA::setInfo('error','modifying next schedule for '.$proc);
1384
+ $process_frequency = $processes[$schedule];
1385
+
1386
+ $next_schedule = $running + $process_frequency;
1387
+ // if the next schedule is already behind, we give it 30 seconds before it can trigger again
1388
+ if( $next_schedule < $time_now ){
1389
+ $next_schedule = $time_now + 30;
1390
+ }
1391
+ $params=array(
1392
+ 'next_schedule' => $next_schedule,
1393
+ 'prev_schedule' => $running,
1394
+ 'running' => false);
1395
+ $updated_sched=true;
1396
+ }
1397
+ }
1398
+ if($updated_sched){
1399
+ //WYSIJA::setInfo('error','updating scheds');
1400
+ WYSIJA::update_option( 'wysija_schedules' , $cron_schedules , 'yes' );
1401
+ }
1402
+
1403
+ }
1404
+
1405
+ $time_now = time();
1406
+ $processesToRun = array();
1407
+ foreach($cron_schedules as $schedule => $scheduled_times){
1408
+ if(strpos($schedule, '(bounce handling not activated)')!==false) continue;
1409
+ if( !isset($processes[$schedule]) ) continue;
1410
+ $process_frequency = $processes[$schedule];
1411
+ if( ( !$scheduled_times['running'] || (int)$scheduled_times['running'] + $process_frequency < $time_now ) && $scheduled_times['next_schedule'] < $time_now){
1412
+ $processesToRun[] = $schedule;
1413
+ }
1414
+ }
1415
+
1416
+ $model_config = WYSIJA::get('config','model');
1417
+ $page_view_trigger = (int)$model_config->getValue('cron_page_hit_trigger');
1418
+ if(!empty($processesToRun) && $page_view_trigger === 1){
1419
+ //call the cron url
1420
+ // do not call that more than once per 5 minutes attempt at reducing the CPU load for some users
1421
+ // http://wordpress.org/support/topic/wysija-newsletters-slowing-down-my-site-1
1422
+ $last_cron_time_plus_5min = (int)get_option('wysija_last_php_cron_call') + (5*60);
1423
+
1424
+ if($last_cron_time_plus_5min < time()){
1425
+ $cron_url = site_url( 'wp-cron.php').'?'.WYSIJA_CRON.'&action=wysija_cron&process='.implode(',',$processesToRun).'&silent=1';
1426
+ $cron_request = apply_filters( 'cron_request', array(
1427
+ 'url' => $cron_url,
1428
+ 'args' => array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) )
1429
+ ) );
1430
+
1431
+ wp_remote_post( $cron_url, $cron_request['args'] );
1432
+ WYSIJA::update_option('wysija_last_php_cron_call', time());
1433
+ }
1434
+
1435
+
1436
+ }
1437
+ }
1438
+
1439
+ /**
1440
+ * Function somehow necessary to avoid some conflicts in windows server and WordPress autoload of plugins language file
1441
+ * @param type $boolean
1442
+ * @param type $domain
1443
+ * @param type $mofile
1444
+ * @return boolean
1445
+ */
1446
+ public static function override_load_textdomain($boolean, $domain, $mofile){
1447
+ $extensionloaded=WYSIJA::load_lang('get_all');
1448
+
1449
+ if(isset($extensionloaded[$domain]) && !@file_exists($mofile)){
1450
+ return true;
1451
+ }
1452
+
1453
+ return false;
1454
+ }
1455
+
1456
+ /**
1457
+ * function to rewrite the path of the file if the file doesn't exist
1458
+ * @param type $mofile
1459
+ * @param type $domain
1460
+ * @return type
1461
+ */
1462
+ public static function load_textdomain_mofile($mofile, $domain){
1463
+ $extensionloaded=WYSIJA::load_lang('get_all');
1464
+
1465
+ if(isset($extensionloaded[$domain]) && !file_exists($mofile)){
1466
+ return WYSIJA_PLG_DIR.$domain.DS.'languages'.DS.$extensionloaded[$domain].'-'.get_locale().'.mo';
1467
+ }
1468
+ return $mofile;
1469
+ }
1470
+ }
1471
+
1472
+ // subscribers/wp-user synch hooks
1473
+ add_action('user_register', array('WYSIJA', 'hook_add_WP_subscriber'), 1);
1474
+ add_action('added_existing_user', array('WYSIJA', 'hook_add_WP_subscriber'), 1);
1475
+ add_action('profile_update', array('WYSIJA', 'hook_edit_WP_subscriber'), 1);
1476
+ // for standard blog
1477
+ add_action('delete_user', array('WYSIJA', 'hook_del_WP_subscriber'), 1);
1478
+ // for multisite
1479
+ add_action('deleted_user', array('WYSIJA', 'hook_del_WP_subscriber'), 1);
1480
+ add_action('remove_user_from_blog', array('WYSIJA', 'hook_del_WP_subscriber'), 1);
1481
+
1482
+ // Load the Upgrader Class
1483
+ add_action('init', array('WJ_Upgrade', 'hook'), 9);
1484
+
1485
+ // post notif trigger
1486
+ add_action('transition_post_status', array('WYSIJA', 'hook_postNotification_transition'), 1, 3);
1487
+ // refresh auto newsletter content when a post is modified
1488
+ //add_action('save_post', array('WYSIJA', 'hook_auto_newsletter_refresh'), 1, 1);
1489
+ add_action('delete_post', array('WYSIJA', 'hook_auto_newsletter_refresh'), 1, 1);
1490
+
1491
+ // add image size for emails
1492
+ add_image_size('wysija-newsletters-max', 600, 9999);
1493
+
1494
+ $modelConf=WYSIJA::get('config','model');
1495
+ if($modelConf->getValue('installed_time')){
1496
+
1497
+ // START all that concerns the CRON
1498
+ // make sure we check when is the schedule due with wysija's cron
1499
+ if($modelConf->getValue('cron_manual')){
1500
+ // if WP cron tasks are still set, we clear them
1501
+ if(wp_get_schedule('wysija_cron_queue')) WYSIJA::deactivate();
1502
+
1503
+ // set the crons schedule for each process
1504
+ WYSIJA::get_cron_schedule();
1505
+
1506
+ // check that there is no late cron schedules if we are using wysija's cron option and that the cron option is triggerred by any page view
1507
+ if(!isset($_REQUEST['process'])){
1508
+ WYSIJA::cron_check();
1509
+ }
1510
+
1511
+ // this action is triggerred only by a cron job
1512
+ // if we're entering the wysija's cron part, it should end here
1513
+ if(isset($_REQUEST['action']) && $_REQUEST['action']=='wysija_cron'){
1514
+ // priority is hundred so that the messages such as unsubscribe or view in your browser have time to be translated(they get translated around 96, 97)
1515
+ add_action('init', 'init_wysija_cron',100);
1516
+
1517
+ function init_wysija_cron(){
1518
+ $hCron=WYSIJA::get('cron','helper');
1519
+ $hCron->run();
1520
+ }
1521
+ }
1522
+
1523
+ // make sure the scheduled tasks are recorded when using WordPress' cron
1524
+ }else{
1525
+
1526
+ // filter to add new possible frequencies to the cron
1527
+ add_filter( 'cron_schedules', array( 'WYSIJA', 'filter_cron_schedules' ) );
1528
+
1529
+ // action to handle the scheduled tasks in wysija
1530
+ add_action( 'wysija_cron_queue', array( 'WYSIJA', 'croned_queue' ) );
1531
+ add_action( 'wysija_cron_daily', array( 'WYSIJA', 'croned_daily' ) );
1532
+ add_action( 'wysija_cron_weekly', array( 'WYSIJA', 'croned_weekly' ) );
1533
+ add_action( 'wysija_cron_monthly', array( 'WYSIJA', 'croned_monthly' ) );
1534
+
1535
+ // same with the weekly task
1536
+ if(!wp_next_scheduled('wysija_cron_weekly')){
1537
+ wp_schedule_event( $modelConf->getValue('last_save') , 'eachweek', 'wysija_cron_weekly' );
1538
+ }
1539
+ // the monthly task...
1540
+ if(!wp_next_scheduled('wysija_cron_monthly')){
1541
+ wp_schedule_event( $modelConf->getValue('last_save') , 'each28days', 'wysija_cron_monthly' );
1542
+ }
1543
+
1544
+ // the daily task...
1545
+ if(!wp_next_scheduled('wysija_cron_daily')){
1546
+ wp_schedule_event( $modelConf->getValue('last_save') , 'daily', 'wysija_cron_daily' );
1547
+ }
1548
+
1549
+
1550
+ if(is_multisite()){
1551
+
1552
+ // in the case of multisite and the network's method we schedule with a different frequency
1553
+ // this option contains the list of sites already scheduled
1554
+ $ms_wysija_bounce_cron = get_site_option('ms_wysija_bounce_cron');
1555
+ global $blog_id;
1556
+
1557
+ // if this blog is not recorded in our wysija_sending_cron option then we clear its scheduled so that we can reinitialize it
1558
+ if(!$ms_wysija_bounce_cron || !isset($ms_wysija_bounce_cron[$blog_id])){
1559
+ wp_clear_scheduled_hook('wysija_cron_bounce');
1560
+ WYSIJA::set_cron_schedule('queue');
1561
+ $ms_wysija_bounce_cron[$blog_id] = 1;
1562
+ update_site_option('ms_wysija_bounce_cron',$ms_wysija_bounce_cron);
1563
+ }
1564
+
1565
+ }
1566
+
1567
+ // if the bounce task is not scheduled then we initialize it
1568
+ if(!wp_next_scheduled('wysija_cron_bounce')){
1569
+ wp_schedule_event( $modelConf->getValue('last_save') , $modelConf->getValue('bouncing_emails_each'), 'wysija_cron_bounce' );
1570
+ }
1571
+
1572
+ // and the queue processing task ...
1573
+ // if we are in a multisite case we make sure that the ms frequency hasn't been changed, if it has we reset it
1574
+ if(is_multisite() && $modelConf->getValue('sending_method')=='network'){
1575
+ // in the case of multisite and the network's method we schedule with a different frequency
1576
+ // this option contains the list of sites already scheduled
1577
+ $ms_wysija_sending_cron=get_site_option('ms_wysija_sending_cron');
1578
+ global $blog_id;
1579
+
1580
+ // if this blog is not recorded in our wysija_sending_cron option then we clear its scheduled so that we can reinitialize it
1581
+ if(!$ms_wysija_sending_cron || !isset($ms_wysija_sending_cron[$blog_id])){
1582
+ wp_clear_scheduled_hook('wysija_cron_queue');
1583
+ WYSIJA::set_cron_schedule('queue');
1584
+ $ms_wysija_sending_cron[$blog_id]=1;
1585
+ update_site_option('ms_wysija_sending_cron',$ms_wysija_sending_cron);
1586
+ }
1587
+ }
1588
+
1589
+
1590
+ // simply schedule the queue
1591
+ if(!wp_next_scheduled('wysija_cron_queue')){
1592
+
1593
+ // in the case of multisite and the network's method we schedule with a different frequency
1594
+ if(is_multisite() && $modelConf->getValue('sending_method')=='network'){
1595
+ $sending_emails_each=$modelConf->getValue('ms_sending_emails_each');
1596
+ }else{
1597
+ $sending_emails_each=$modelConf->getValue('sending_emails_each');
1598
+ }
1599
+ wp_schedule_event( $modelConf->getValue('last_save') , $sending_emails_each, 'wysija_cron_queue' );
1600
+ }
1601
+
1602
+ }// END all that concerns the CRON
1603
+
1604
+ // filter fixing a bug with automatic load_text_domain_from WP didn't understand yet why this was necessary...
1605
+ // somehow wp_register_script(which is irrelevant) was triggerring this kind of notice
1606
+ // Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(C:\Domains\website.com\wwwroot\web/wp-content/plugins/C:\Domains\website.com\wwwroot\web\wp-content\plugins\wysija-newsletters/languages/wysija-newsletters-en_US.mo) is not within the allowed path(s): (.;C:\Domains\;C:\PHP\;C:\Sites\;C:\SitesData\;/) in C:\Domains\website.com\wwwroot\web\wp-includes\l10n.php on line 339
1607
+ // the only solution is to make sure on our end that the file exists and rewrite it if necessary
1608
+ add_filter( 'override_load_textdomain', array( 'WYSIJA', 'override_load_textdomain' ), 10, 3);
1609
+ add_filter('load_textdomain_mofile', array( 'WYSIJA', 'load_textdomain_mofile' ), 10, 2);
1610
+ }
1611
+
1612
+ register_deactivation_hook(WYSIJA_FILE, array( 'WYSIJA', 'deactivate' ));
1613
+ register_activation_hook(WYSIJA_FILE, array( 'WYSIJA', 'activate' ));
1614
+ add_action( 'init', array('WYSIJA','create_post_type') );
1615
+
1616
+ // check for PHP version and display a warning notice if it's <5.3
1617
+ if ( version_compare( PHP_VERSION , '5.3' , '<' ) &&
1618
+ !get_option("wysija_dismiss_update_notice") &&
1619
+ empty($_SERVER['HTTP_X_REQUESTED_WITH'])
1620
+ ) {
1621
+
1622
+ $a = new WYSIJA_object();
1623
+ $a->notice(__("Your version of PHP is outdated. If you don't upgrade soon, new versions of MailPoet won't work.")
1624
+ . "<br />"
1625
+ . str_replace( array('[link]', '[/link]'), array('<a href="https://support.mailpoet.com/knowledgebase/how-to-prepare-my-site-for-mailpoet-3-0/" target="_blank" >', '</a>'), __("[link]Read how to update your version of PHP.[/link]")
1626
+ . "<br /><br />"
1627
+ . str_replace( array('[link]', '[/link]'), array('<a href="javascript:;" class="wysija_dismiss_update_notice">', '</a>'), __("[link]Dismiss[/link] this notice."))
1628
+ ), true, true);
1629
+ }
1630
+
1631
+ // launch application
1632
+ $helper = WYSIJA::get(WYSIJA_SIDE,'helper');
trunk/core/constants.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*make the difference between frontend and backend routing*/
4
+ /*require what is needed for common purpose in backend such as backend menus*/
5
+ defined( 'ABSPATH' ) or die( 'Not allowed' );
6
+ if(defined('WP_ADMIN')) {
7
+ define('WYSIJA_SIDE','back');
8
+ }else define('WYSIJA_SIDE','front');
9
+
10
+ $plugin_name='wysija-newsletters';
11
+ $plugin_folder_name=dirname(dirname(plugin_basename(__FILE__)));
12
+ $current_folder=dirname(dirname(__FILE__));
13
+
14
+ if(!defined('DS')) define('DS', DIRECTORY_SEPARATOR);
15
+ define('WYSIJA', $plugin_name);
16
+ if(!defined('WYSIJA_PLG_DIR')) define('WYSIJA_PLG_DIR', dirname($current_folder).DS);
17
+ define('WYSIJA_DIR', $current_folder.DS);
18
+ define('WYSIJA_DATA_DIR', WYSIJA_DIR.'data'.DS);
19
+ define('WYSIJA_FILE',WYSIJA_DIR.'index.php');
20
+ define('WYSIJA_URL',plugins_url().'/'.strtolower('wysija-newsletters').'/');
21
+
22
+ $upload_dir = wp_upload_dir();
23
+
24
+ define('WYSIJA_UPLOADS_DIR',str_replace('/',DS,$upload_dir['basedir']).DS.'wysija'.DS);
25
+ define('WYSIJA_UPLOADS_URL',$upload_dir['baseurl'].'/wysija/');
26
+ if(is_multisite()){
27
+ define('WYSIJA_UPLOADS_MS_DIR',str_replace(get_option( 'upload_path' ), get_blog_option(1, 'upload_path'), $upload_dir['basedir']).DS.'wysija'.DS);
28
+ define('WYSIJA_UPLOADS_MS_URL',get_blog_option(1, 'siteurl').'/'.get_blog_option(1, 'upload_path').'/wysija/');
29
+ }
30
+
31
+ define('WYSIJA_INC',WYSIJA_DIR.'inc'.DS);
32
+ define('WYSIJA_CORE',WYSIJA_DIR.'core'.DS);
33
+ define('WYSIJA_VIEWS',WYSIJA_DIR.'views'.DS);
34
+ define('WYSIJA_MODELS',WYSIJA_DIR.'models'.DS);
35
+ define('WYSIJA_HELPERS',WYSIJA_DIR.'helpers'.DS);
36
+ define('WYSIJA_CLASSES',WYSIJA_DIR.'classes'.DS);
37
+ define('WYSIJA_CTRL',WYSIJA_DIR.'controllers'.DS);
38
+ define('WYSIJA_WIDGETS',WYSIJA_DIR.'widgets'.DS);
39
+
40
+ define('WYSIJA_DIR_IMG',WYSIJA_DIR.'img'.DS);
41
+ define('WYSIJA_EDITOR_IMG',WYSIJA_URL.'img/');
42
+ define('WYSIJA_EDITOR_TOOLS',WYSIJA_DIR.'tools'.DS);
43
+ global $blog_id;
44
+ define('WYSIJA_CRON',md5(__FILE__.$blog_id));
trunk/core/controller.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+
5
+ class WYSIJA_control extends WYSIJA_object{
6
+ var $model="";
7
+ var $view="";
8
+ var $action="";
9
+ var $list_columns=array();
10
+ var $form_columns=array();
11
+ var $filters=array();
12
+ var $js=array();
13
+ var $jsLoc=array();
14
+ var $extension="wysija-newsletters";
15
+ var $joins=array();
16
+ var $title="";
17
+
18
+ function __construct(){
19
+ //setup some required objects for the request
20
+ if(!defined('DOING_AJAX')){
21
+ if($this->view) $this->viewObj = WYSIJA::get($this->view,"view",false,$this->extension);
22
+ if(empty($this->viewObj)) $this->viewObj = new stdClass (); // In some cases, viewObj can not be created
23
+ if($this->model){
24
+ $this->modelObj=WYSIJA::get($this->model,"model",false,$this->extension);
25
+ $this->viewObj->model=WYSIJA::get($this->model,"model",false,$this->extension);
26
+ }
27
+ }
28
+ }
29
+
30
+ private function _rebuild_ajax_nonce_action(){
31
+ $actionnonce = 'wysija_ajax';
32
+ if( !empty( $_REQUEST['controller']) && !empty( $_REQUEST['task']) ){
33
+ $actionnonce = 'wysija_'.$_REQUEST['controller'] . '-action_'.$_REQUEST['task'];
34
+ }
35
+ return $actionnonce;
36
+ }
37
+
38
+ private function _rebuild_nonce_action(){
39
+ $actionnonce = '';
40
+ //backend case
41
+ if(is_admin() && !empty($_REQUEST['page'])){
42
+ $actionnonce=$_REQUEST['page'].'-action_'.$_REQUEST['action'];
43
+ if(!empty($_REQUEST['id'])) $actionnonce.='-id_'.$_REQUEST['id'];
44
+ //frontend case
45
+ } elseif (!empty($_REQUEST['controller'])) {
46
+ $actionnonce=$_REQUEST['controller'].'-action_'.$_REQUEST['action'];
47
+ if(!empty($_REQUEST['id'])) $actionnonce.='-id_'.$_REQUEST['id'];
48
+ }
49
+ return $actionnonce;
50
+ }
51
+
52
+ private function _nonce_verification(){
53
+ if(!empty($_REQUEST['_wpnonce'])){
54
+ if($_REQUEST['action']=='wysija_ajax'){
55
+ $actionnonce = $this->_rebuild_ajax_nonce_action();
56
+ }else{
57
+ $actionnonce = $this->_rebuild_nonce_action();
58
+ }
59
+
60
+ //if the wp_nonce has been set up then we test it against the one here if it fails we just die
61
+ $nonce=$_REQUEST['_wpnonce'];
62
+
63
+ if(!wp_verify_nonce($nonce, $actionnonce) ){
64
+ wp_die("<h2>" . __('Security failure during request') . "</h2>", __("Security Problem"), array(
65
+ 'response' => 403,
66
+ 'back_link' => false
67
+ ));
68
+ }
69
+
70
+
71
+ }else{
72
+ if(!wp_verify_nonce($nonce, $actionnonce) ){
73
+ wp_die("<h2>" . __('Security failure during request') . "</h2>", __("Security Problem"), array(
74
+ 'response' => 403,
75
+ 'back_link' => false
76
+ ));
77
+ }
78
+ }
79
+
80
+ }
81
+
82
+
83
+ /**
84
+ * if a controller calls that page then it needs those global parameters to be set
85
+ * @return boolean
86
+ */
87
+ function requireSecurity(){
88
+
89
+ if( !isset($_REQUEST['_wpnonce']) ) {
90
+ die('Your request is not safe.');
91
+ }else{
92
+ $this->_nonce_verification();
93
+ return true;
94
+ }
95
+ }
96
+
97
+
98
+ /**
99
+ * prepare an array of condition for a where statement with the pk and its value.
100
+ * note: not sure this function should be here though.
101
+ * @return array
102
+ */
103
+ function getPKVal(){
104
+
105
+ if(isset($_POST['wysija'][$this->modelObj->table_name][$this->modelObj->pk]) && $_POST['wysija'][$this->modelObj->table_name][$this->modelObj->pk]){
106
+ //this is an update
107
+ $conditions=array($this->modelObj->pk =>$_POST['wysija'][$this->modelObj->table_name][$this->modelObj->pk]);
108
+ unset($_POST['wysija'][$this->modelObj->table_name][$this->modelObj->pk]);
109
+ }elseif(isset($_GET['id'])){
110
+ $conditions=array($this->modelObj->pk =>$_GET['id']);
111
+ }else{
112
+ $conditions=array();
113
+ }
114
+
115
+ return $conditions;
116
+ }
117
+ }
trunk/core/index.html ADDED
File without changes
trunk/core/model.php ADDED
@@ -0,0 +1,1040 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_model extends WYSIJA_object{
4
+
5
+ var $table_prefix='wysija';
6
+ var $table_name='';
7
+ var $pk='';
8
+ var $values=array();
9
+ var $conditions=array();
10
+ var $orderby=array();
11
+ var $groupby=false;
12
+ var $noCheck =false;
13
+ var $replaceQRY=false;
14
+ var $limitON=false;
15
+ var $dbg=false;
16
+ var $colCheck=true;
17
+ var $getFormat=ARRAY_A;
18
+ var $getOne=false;
19
+ var $fieldValid=true;
20
+ var $specialUpdate=false;
21
+ var $escapeFields=array();
22
+ var $escapingOn=false;
23
+ var $tableWP=false;
24
+ var $columns=array();
25
+ var $joins=array();
26
+ var $ignore = false;
27
+ var $sql_error = false;
28
+ var $last_error = '';
29
+ var $comparisonKeys = array('equal', 'notequal', 'like', 'greater', 'less', 'greater_eq', 'less_eq', 'is');
30
+ var $time_start = 0;
31
+ var $query_duration = 0;
32
+
33
+ function __construct($extensions=''){
34
+ if(defined('WYSIJA_DBG') && WYSIJA_DBG>0) $this->dbg=true;
35
+ global $wpdb;
36
+ $this->wpdb = $wpdb;
37
+ $this->wpprefix=$this->wpdb->prefix;
38
+ if($extensions) $this->table_prefix=$extensions;
39
+ }
40
+ /**
41
+ * since we reuse the same objects accross the whole application
42
+ * once in a while for instance between a delete and a select we need to reset the objects to update the conditions
43
+ */
44
+ function reset(){
45
+ $this->values = array();
46
+ $this->conditions = array();
47
+ $this->orderby = array();
48
+ $this->groupby = false;
49
+ $this->getFormat = ARRAY_A;
50
+ $this->getOne = false;
51
+ $this->limitON = false;
52
+ $this->sql_error = false;
53
+ $this->last_error = '';
54
+ }
55
+
56
+ /**
57
+ *
58
+ * @param type $columnsOrPKval
59
+ * @param type $conditions
60
+ * @return type
61
+ */
62
+ function get($columnsOrPKval=false,$conditions=array()){
63
+ /*then columns becomes the pk value*/
64
+ if(!$conditions){
65
+ $conditions=array('equal'=>array($this->pk=>$columnsOrPKval));
66
+ $columnsOrPKval=false;
67
+ $this->noCheck=true;
68
+ }
69
+
70
+ /* if we pass just the id strong in the get conditions then it's the pk*/
71
+ if($conditions && !is_array($conditions)){
72
+ $conditions=array('equal'=>array($this->pk=>$conditions));
73
+ }
74
+ if($this->setConditions($conditions)){
75
+ if($this->getOne) $results=$this->getRows($columnsOrPKval,0,1);
76
+ else $results=$this->getRows($columnsOrPKval);
77
+ //$this->escapeQuotesFromRes($results);
78
+ if($this->getOne && count($results)==1){
79
+ switch($this->getFormat){
80
+ case ARRAY_A:
81
+ foreach($results as $res)return $res;
82
+ break;
83
+ case OBJECT:
84
+ foreach($results as $res)return $res;
85
+ break;
86
+ }
87
+ }
88
+ else return $results;
89
+ }
90
+
91
+ return false;
92
+ }
93
+
94
+ function getOne($columnsOrPKval=false,$conditions=array()){
95
+ $this->getOne=true;
96
+ $this->limitON=true;
97
+
98
+ return $this->get($columnsOrPKval,$conditions);
99
+ }
100
+
101
+ /**
102
+ * get a list of result based on a select query
103
+ * @param type $columns
104
+ * @param type $page
105
+ * @param type $limit
106
+ * @return type
107
+ */
108
+ function getRows($columns=false,$page=0,$limit=false){
109
+
110
+ /*set the columns*/
111
+ if($columns !== false){
112
+ if(is_array($columns)){
113
+
114
+ foreach($columns as $column){
115
+
116
+ if(!isset($this->columns[$column])){
117
+ $this->error(sprintf('Column does not exist.'));
118
+ return false;
119
+ }
120
+ }
121
+ $columns=implode(', ',$columns);
122
+ }else{
123
+ if(!isset($this->columns[$columns])){
124
+ $this->error(sprintf('Column does not exist.'));
125
+ return false;
126
+ }
127
+ }
128
+ }else{
129
+ $columns='*';
130
+
131
+ }
132
+
133
+
134
+ $query='SELECT '.$columns.' FROM `'.$this->getSelectTableName()."`";
135
+ $query.=$this->makeJoins();
136
+ $query.=$this->makeWhere();
137
+ $query.=$this->makeGroupBY();
138
+ $query.=$this->makeOrderBY();
139
+
140
+ if($this->limitON) $query.=$this->setLimit($page,$limit);
141
+ $results=$this->query('get_res',$query,$this->getFormat);
142
+
143
+ //$this->escapeQuotesFromRes($results);
144
+
145
+ return $results;
146
+ }
147
+
148
+ function escapeQuotesFromRes(&$results){
149
+ if(!$this->escapingOn) return false;
150
+ foreach($results as $k =>$r){
151
+
152
+ if(in_array($this->getFormat,array(ARRAY_A,ARRAY_N))){
153
+ foreach($r as $k1 =>$v1){
154
+ if(in_array($k1,$this->escapeFields)){
155
+ $results[$k][$k1]= stripslashes($v1);
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+ function setLimit($page=0,$limit=false){
163
+ /*set the limit of the selection*/
164
+
165
+ if(!$this->getOne){
166
+ if($page==0){
167
+ if(isset($_REQUEST['pagi'])){
168
+ $page=(int)$_REQUEST['pagi'];
169
+ if($page!=0) $page=$page-1;
170
+ }
171
+
172
+ }else $page=$page-1;
173
+ }
174
+
175
+ if(!$limit){
176
+ if(isset($this->limit_pp)) $limit=$this->limit_pp;
177
+ else{
178
+ $config=WYSIJA::get('config','model');
179
+ $limit=$config->getValue('limit_listing');
180
+ }
181
+ }
182
+
183
+ $this->limit=(int)$limit;
184
+ $this->page=$page;
185
+ $this->limit_start=(int)($this->page*$this->limit);
186
+ $this->limit_end=(int)($this->limit_start+$this->limit);
187
+
188
+ return " LIMIT $this->limit_start , $this->limit";
189
+ }
190
+
191
+ /**
192
+ * DEPRECATED
193
+ * to have a custom query through the model and get the result immediately
194
+ * @param type $query
195
+ * @return type
196
+ */
197
+ function getResults($query,$type=ARRAY_A){
198
+ return $this->query('get_res',$query, $type);
199
+ }
200
+
201
+ /**
202
+ * to have a custom query through the model and get the result immediately
203
+ * @param type $query
204
+ * @return type
205
+ */
206
+ public function get_results($query,$type=ARRAY_A){
207
+ return $this->getResults($query,$type);
208
+ }
209
+
210
+
211
+ function getSelectTableName(){
212
+ if($this->joins && isset($this->joins['tablestart'])){
213
+ if(isset($this->joins['prefstart'])) return $this->wpdb->prefix.$this->joins['prefstart'].'_'.$this->joins['tablestart'];
214
+ else return $this->getPrefix().$this->joins['tablestart'];
215
+ }else return $this->getPrefix().$this->table_name;
216
+ }
217
+
218
+ /**
219
+ * simple SQL count
220
+ * @return type
221
+ */
222
+ function count($query=false,$keygetcount=false){
223
+ if(!$query){
224
+ $groupBy=$this->makeGroupBY();
225
+ $columnMore='';
226
+ if($groupBy) $columnMore=','.$this->groupby;
227
+ $query='SELECT COUNT('.$this->getPk().') as count '.$columnMore.' FROM `'.$this->getSelectTableName().'`';
228
+ $query.=$this->makeJoins();
229
+
230
+ $query.=$this->makeWhere();
231
+ $query.=$groupBy;
232
+ }
233
+
234
+
235
+ // if dbg is on we track the duration of the query
236
+ if($this->dbg){
237
+ $this->timer_start();
238
+ }
239
+ $results=$this->query('get_res',$query,$this->getFormat);
240
+
241
+ // if dbg is on we track the duration of the query
242
+ if($this->dbg){
243
+ $this->timer_stop();
244
+ $this->keepQry('count');
245
+ }
246
+
247
+ if(!$results || count($results)>1) return $results;
248
+ else {
249
+ if($keygetcount) return $results[0][$keygetcount];
250
+ else{
251
+ foreach($results[0] as $key => $count) return $count;
252
+ }
253
+ }
254
+
255
+
256
+ return $results;
257
+ }
258
+
259
+ /**
260
+ * make the SQL WHERE condition string
261
+ * @return string
262
+ */
263
+ function makeWhere(){
264
+ $query='';
265
+ if($this->conditions){
266
+ /*set the WHERE clause*/
267
+ $conditions=array();
268
+ foreach($this->conditions as $type=>$values){
269
+ if(!in_array($type, $this->comparisonKeys)){
270
+ $conditionsss=$this->conditions;
271
+ $this->conditions=array();
272
+ $this->conditions['equal']=$conditionsss;
273
+
274
+ break;
275
+ }
276
+ }
277
+ foreach($this->conditions as $type=>$values){
278
+ if($type=='like' && count($values)>1){
279
+ if(is_array($values)){
280
+ $total=count($values);
281
+ $i=1;
282
+ $likeCond='';
283
+ foreach($values as $qfield => $qval){
284
+ $qval = html_entity_decode($qval, ENT_QUOTES);
285
+ $likeCond.=$qfield." LIKE '%".esc_sql(addcslashes($qval, '%_' ))."%'";
286
+ if($i<$total){
287
+ $likeCond.=' OR ';
288
+ }
289
+ $i++;
290
+ }
291
+ $conditions[]='('.$likeCond.')';
292
+ }
293
+ continue;
294
+ }
295
+
296
+ foreach($values as $condK => $condVal){
297
+
298
+ //secure from injections
299
+ $this->_secureFieldVal($condK, $condVal);
300
+
301
+ switch($type){
302
+ case 'equal':
303
+ if(is_array($condVal)){
304
+ $conditions[]=$condK.' IN ("'.implode('","', $condVal).'")';
305
+ }else{
306
+ if(is_null($condVal)) {
307
+ $conditions[] = $condK.' IS NULL';
308
+ } else {
309
+ if(is_numeric($condVal) === false) $condVal = '"'.$condVal.'"';
310
+ $conditions[] = $condK.'='.$condVal;
311
+ }
312
+ }
313
+ break;
314
+ case 'notequal':
315
+ if(is_array($condVal)){
316
+ $conditions[]=$condK.' NOT IN ("'.implode('","', $condVal).'")';
317
+ }else{
318
+ //this means that if I delete something with a list of ids and the array happens to be empty array of ids it will just delete everything by
319
+ if(is_null($condVal)) {
320
+ $conditions[] = $condK.' IS NOT NULL';
321
+ } else {
322
+ if(is_numeric($condVal) === false) $condVal = '"'.$condVal.'"';
323
+ $conditions[] = $condK.' != '.$condVal;
324
+ }
325
+ }
326
+ break;
327
+ case 'like':
328
+ $conditions[]=$condK." LIKE '%".esc_sql(addcslashes($condVal, '%_' ))."%'";
329
+ break;
330
+ case 'greater':
331
+ if(is_numeric($condVal) === false) $condVal = '"'.$condVal.'"';
332
+ $conditions[]=$condK.' > '.$condVal;
333
+ break;
334
+ case 'less':
335
+ if(is_numeric($condVal) === false) $condVal = '"'.$condVal.'"';
336
+ $conditions[]=$condK.' < '.$condVal;
337
+ break;
338
+ case 'greater_eq':
339
+ if(is_numeric($condVal) === false) $condVal = '"'.$condVal.'"';
340
+ $conditions[]=$condK.' >= '.$condVal;
341
+ break;
342
+ case 'less_eq':
343
+ if(is_numeric($condVal) === false) $condVal = '"'.$condVal.'"';
344
+ $conditions[]=$condK.' <= '.$condVal;
345
+ break;
346
+ case 'is':
347
+
348
+ $conditions[]=$condK.' '.$condVal;
349
+ break;
350
+ }
351
+ }
352
+
353
+ }
354
+
355
+ $query.=' WHERE '.implode(' AND ',$conditions);
356
+ }
357
+
358
+ return $query;
359
+ }
360
+
361
+ /**
362
+ * make the SQL ORDER BY condition string
363
+ * @return string
364
+ */
365
+ function makeOrderBY(){
366
+ $query=' ORDER BY ';
367
+ if($this->orderby){
368
+ /*set the ORDER BY clause*/
369
+ $query.=$this->orderby.' '.$this->orderbyt;
370
+ }else{
371
+ /*by default we order by pk desc*/
372
+ if(is_array($this->pk)) return '';
373
+ $query.=$this->pk.' DESC';
374
+ }
375
+ return $query;
376
+ }
377
+
378
+
379
+ function makeJoins(){
380
+
381
+ if($this->joins){
382
+ $join=' as A';
383
+ $arrayLetters=array('B','C','D','E');
384
+ foreach($this->joins['tablejoins'] as $table => $fk){
385
+ $letter=array_shift($arrayLetters);
386
+ $join.=' JOIN `'.$this->getPrefix().$table.'` AS '.$letter." on $letter.$fk=A.".$this->joins['keystart'].' ';
387
+ }
388
+ /*set the ORDER BY clause*/
389
+ return $join;
390
+ }else return '';
391
+
392
+ }
393
+ /**
394
+ * make the SQL ORDER BY condition string
395
+ * @return string
396
+ */
397
+ function makeGroupBY(){
398
+
399
+ if($this->groupby){
400
+ /*set the ORDER BY clause*/
401
+ return ' GROUP BY '.$this->groupby;
402
+ }else return '';
403
+
404
+ }
405
+ function groupBy($name){
406
+
407
+ if (!is_string($name) OR preg_match('|[^a-z0-9#_.-]|i',$name) !== 0 ){
408
+ $this->groupby=false;
409
+ }else $this->groupby=$name;
410
+ }
411
+ function orderBy($name,$type = 'ASC'){
412
+
413
+ if(is_array($name) and count($name) > 0) {
414
+ // set order by to empty string
415
+ $this->orderby = '';
416
+ $this->ordert = '';
417
+
418
+ // count number of arguments
419
+ $count = count($name);
420
+
421
+ // build order by query
422
+ for($i = 0; $i < $count; $i++) {
423
+
424
+ $value = current($name);
425
+
426
+ //security escaping
427
+ if(!is_string(key($name)) OR preg_match('|[^a-z0-9#_.-]|i',key($name)) !== 0 ){
428
+ $orderByCol="";
429
+ }else $orderByCol=key($name);
430
+ //security escaping
431
+ if(!is_string($value) OR preg_match('|[^a-z0-9#_.-]|i',$value) !== 0 ){
432
+ $orderByVal="";
433
+ }else $orderByVal=$value;
434
+
435
+ if($i === ($count - 1)) {
436
+ $this->orderby .= $orderByCol;
437
+ $this->ordert = $orderByVal;
438
+ } else {
439
+ $this->orderby .=$orderByCol.' '.$orderByVal;
440
+ $this->orderby .= ', ';
441
+ next($name);
442
+ }
443
+ }
444
+ } else if(!is_string($name) OR preg_match('|[^a-z0-9#_.-]|i',$name) !== 0 ){
445
+ $this->orderby="";
446
+ }else {
447
+ $this->orderby=$name;
448
+ }
449
+
450
+ if(!in_array($type,array('DESC','ASC'))) $type = 'DESC';
451
+ $this->orderbyt=$type;
452
+ }
453
+
454
+
455
+
456
+ /**
457
+ * prepare for an insert procedure
458
+ * @param type $values
459
+ */
460
+ function insert($values,$ignore=false){
461
+ if($ignore)$this->ignore=true;
462
+ if($this->setValues($values)){
463
+ return $this->save();
464
+ }else{
465
+ $this->error(sprintf('missing values in model insert : %1$s.', get_class($this)));
466
+ }
467
+ }
468
+
469
+
470
+ function replace($values=array()){
471
+ $this->replaceQRY=true;
472
+ $this->insert($values);
473
+ $this->replaceQRY=false;
474
+ }
475
+
476
+ /**
477
+ * prepare for an update procedure
478
+ * @param type $values
479
+ * @param type $conditions
480
+ */
481
+ function update($values=array(),$conditions=array()){
482
+
483
+ if($this->setValues($values)){
484
+ /*if no condition is set then we set it mannualy based on the primary key*/
485
+ if(!$conditions){
486
+ if(!$this->conditions){
487
+ if(isset($values[$this->pk]) && $values[$this->pk]){
488
+
489
+ $this->setConditions(array($this->pk => $values[$this->pk]), true);
490
+
491
+ unset($values[$this->pk]);
492
+
493
+ return $this->save(true);
494
+
495
+ }else{
496
+ $this->error(sprintf('missing pk value in model update : %1$s.', get_class($this)));
497
+ }
498
+ }
499
+
500
+ }else{
501
+ if($this->setConditions($conditions,true)){
502
+ return $this->save(true);
503
+ }else{
504
+ $this->error(sprintf('missing conditions in model update : %1$s.', get_class($this)));
505
+ }
506
+ }
507
+
508
+ }else{
509
+ $this->error(sprintf('missing values in model update : %1$s.', get_class($this)));
510
+ }
511
+ }
512
+
513
+ /**
514
+ * UPDATE with a special where condition
515
+ * @param type $table
516
+ * @param type $data
517
+ * @param type $where
518
+ * @param type $format
519
+ * @param type $where_format
520
+ * @return type
521
+ */
522
+ function specialUpdate( $table, $data, $where, $format = null, $where_format = null ) {
523
+ if ( ! is_array( $data ) || ! is_array( $where ) )
524
+ return false;
525
+
526
+ $formats = $format = (array) $format;
527
+ $bits = $wheres = array();
528
+
529
+ $i=0;
530
+ foreach ( $data as $field => $val) {
531
+ $this->_secureFieldVal($field,$val);
532
+
533
+ switch($format[$i]){
534
+ case "%d":
535
+ $bits[] = "`$field` = ".(int)$val;
536
+ break;
537
+ case '[increment]':
538
+ $bits[] = "`$field` = ".$field.'+1';
539
+ break;
540
+ case '[decrement]':
541
+ $bits[] = "`$field` = ".$field.'-1';
542
+ break;
543
+ default :
544
+ $bits[] = "`$field` = '".$val."'";
545
+ }
546
+ $i++;
547
+ }
548
+
549
+ $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' ' . $this->makeWhere();
550
+ return $this->query( $sql );
551
+ }
552
+
553
+
554
+ function _secureFieldVal( &$field, &$mixed ) {
555
+ if ( ! is_string( $field ) || preg_match( '|[^a-z0-9#_.-]|i', $field ) !== 0 ) {
556
+ die('field "'.$field .'" not secured');
557
+ }
558
+ if ( is_string( $mixed ) || is_numeric( $mixed ) || is_bool( $mixed ) ) {
559
+ $mixed = esc_sql( $mixed );
560
+ } else {
561
+ if(!empty($mixed) && is_array($mixed)){
562
+ foreach ( $mixed as $key => &$value ) {
563
+ $this->_secureFieldVal( $field, $value );
564
+ }
565
+ }
566
+ }
567
+ }
568
+ /**
569
+ * save information as an update or an insert
570
+ * @param type $update
571
+ * @return type
572
+ */
573
+ function save($update=false){
574
+
575
+ if($update)$updateStr='Update';
576
+ else $updateStr='Insert';
577
+ $beforeSave='before'.$updateStr;
578
+ $afterSave='after'.$updateStr;
579
+
580
+
581
+
582
+ if(!$update && isset($this->columns['created_at']))$this->values['created_at']=time();
583
+ foreach($this->columns as $key => $params){
584
+ /*check for auto columns */
585
+ if((isset($params['autoup']) && $update) || (!$update && $key!='sent_at')){
586
+ if(isset($params['type']) && !isset($this->values[$key])){
587
+ switch($params['type']){
588
+ case 'date':
589
+ $this->values[$key]=time();
590
+ break;
591
+ case 'ip':
592
+ $userHelper=WYSIJA::get("user","helper");
593
+ /*record the ip and save the user*/
594
+ $this->values[$key]=$userHelper->getIP();
595
+ break;
596
+ case 'referer':
597
+ /*record the ip and save the user*/
598
+ $this->values[$key]=$_SERVER['HTTP_REFERER'];
599
+ break;
600
+ }
601
+ }
602
+
603
+ }
604
+ }
605
+
606
+ if(method_exists($this,$beforeSave)){
607
+ if(!$this->$beforeSave()){
608
+ //$this->error(sprintf('Problem during validation "%2$s" in model : %1$s.', get_class($this), $beforeSave));
609
+ return false;
610
+ }
611
+ }
612
+
613
+ /*prepare a format list for the update and insert function*/
614
+ $fieldsFormats=array();
615
+ if(!is_array($this->pk) && isset($this->values[$this->pk])) unset($this->values[$this->pk]);
616
+ foreach($this->values as $key =>$val){
617
+ if(!isset($this->columns[$key]['html'])) $this->values[$key]=strip_tags($val);
618
+ /* let's correct the type of the values based on the one defined in the model*/
619
+ if(in_array($val, array('[increment]','[decrement]'))){
620
+ $fieldsFormats[]=$val;
621
+ $this->specialUpdate=true;
622
+ }else{
623
+ //dbg($this->values);
624
+ if(!isset($this->columns[$key]['type'])){
625
+ $this->columns[$key]['type']='default';
626
+ }
627
+ switch($this->columns[$key]['type']){
628
+ case 'integer':
629
+ case 'boolean':
630
+ $fieldsFormats[]="%d";
631
+ break;
632
+ default:
633
+ $fieldsFormats[]="%s";
634
+
635
+ }
636
+ }
637
+
638
+ }
639
+
640
+ if($this->fieldValid && !$this->validateFields()) {
641
+ $this->error(__('Error Validating the fields',WYSIJA),true);
642
+ $this->stay=true;
643
+ return false;
644
+ }
645
+
646
+ // if dbg is on we track the duration of the query
647
+ if($this->dbg){
648
+ $this->timer_start();
649
+ }
650
+
651
+ if($update){
652
+
653
+ if( $this->specialUpdate || isset($this->conditions['equal']) || isset($this->conditions['notequal']) || isset($this->conditions['like'])){
654
+
655
+ $resultSave=$this->specialUpdate($this->getPrefix().$this->table_name,$this->values,$this->conditions,$fieldsFormats);
656
+ $this->logError();
657
+ }else{
658
+
659
+ $this->wpdb->update($this->getPrefix().$this->table_name,$this->values,$this->conditions,$fieldsFormats);
660
+ $this->logError();
661
+ $resultSave=$this->wpdb->result;
662
+ }
663
+
664
+ }else{
665
+ if($this->replaceQRY){
666
+ $resultSave=$this->wpdb->replace($this->getPrefix().$this->table_name,$this->values,$fieldsFormats);
667
+ $this->logError();
668
+ }else{
669
+
670
+ if($this->ignore) $resultSave=$this->wpdb->insert($this->getPrefix().$this->table_name,$this->values,$fieldsFormats);
671
+ else $resultSave=$this->wpdb->insert($this->getPrefix().$this->table_name,$this->values,$fieldsFormats);
672
+
673
+ $this->logError();
674
+ //dbg('hello');
675
+ }
676
+
677
+ }
678
+
679
+ // if dbg is on we track the duration of the query
680
+ if($this->dbg){
681
+ $this->timer_stop();
682
+ $this->keepQry('save');
683
+ }
684
+
685
+ if(!$resultSave){
686
+ $this->wpdb->show_errors();
687
+ return false;
688
+ }else{
689
+ if($update){
690
+ if(isset($this->conditions[$this->getPk()])){
691
+ $resultSave=$this->conditions[$this->getPk()];
692
+ }else{
693
+ if(isset($this->conditions[$this->getPk(1)])) $resultSave=$this->conditions[$this->getPk(1)];
694
+ }
695
+
696
+ }else{
697
+ $resultSave=$this->wpdb->insert_id;
698
+ }
699
+ }
700
+
701
+ $this->wpdb->flush();
702
+
703
+ if(method_exists($this,$afterSave)){
704
+ if(!$this->$afterSave($resultSave)){
705
+ //$this->error(sprintf('Problem during validation "%2$s" in model : %1$s.', get_class($this), $afterSave));
706
+ return false;
707
+ }
708
+ }
709
+ return $resultSave;
710
+ }
711
+
712
+
713
+ function insertMany($values){
714
+ $fields=array_keys($values[0]);
715
+
716
+ $query='INSERT INTO `'.$this->getPrefix().$this->table_name.'` (`' . implode( '`,`', $fields ) . '`) VALUES ';
717
+
718
+ $total=count($values);
719
+ $i=1;
720
+ foreach($values as &$vals){
721
+ foreach($vals as &$v) $v=esc_sql($v);
722
+ $query.= "('" . implode( "','", $vals )."')";
723
+ if($i<$total) $query.=',';
724
+ $i++;
725
+ }
726
+
727
+ $this->query($query.$myvalues);
728
+
729
+ }
730
+
731
+ /**
732
+ * validate the fields type(defined in each model) in the save procedure
733
+ * @return type
734
+ */
735
+ function validateFields(){
736
+ $error=false;
737
+ foreach($this->values as $key =>$val){
738
+ if(isset($this->columns[$key]['req']) && !$val && !in_array( $this->columns[$key]['type'], array( 'boolean', 'integer' )) ){
739
+ $this->error(sprintf(__('Field "%1$s" is required in table "%2$s".',WYSIJA), $key,$this->table_name),true);
740
+ $error=true;
741
+ }
742
+ /* let's correct the type of the values based on the one defined in the model*/
743
+ switch($this->columns[$key]['type']){
744
+ case 'email':
745
+ $userHelper = WYSIJA::get('user','helper');
746
+ if(!$userHelper->validEmail($val)){
747
+ $this->error(sprintf(__('Field "%1$s" needs to be a valid Email.',WYSIJA), $key),true);
748
+ $error=true;
749
+ }
750
+ break;
751
+ }
752
+ }
753
+
754
+ if($error) return false;
755
+ return true;
756
+ }
757
+
758
+ /**
759
+ * delete procedure
760
+ * @param type $conditions
761
+ * @return type
762
+ */
763
+ function delete($conditions){
764
+ $query='DELETE FROM `'.$this->getPrefix().$this->table_name.'`';
765
+
766
+ if($this->setConditions($conditions)){
767
+ $whereQuery=$this->makeWhere();
768
+ if(!$whereQuery){
769
+ $this->error('Cannot delete element without conditions in model : '.get_class($this));
770
+ }
771
+ }else{
772
+ $this->error('Cannot delete element without conditions in model : '.get_class($this));
773
+ return false;
774
+ }
775
+ $result=$this->beforeDelete($conditions);
776
+ if($result) $result=$this->query($query.$whereQuery);
777
+ else return false;
778
+ $this->afterDelete();
779
+
780
+ return true;
781
+ }
782
+
783
+ function exists($conditions){
784
+
785
+ $query='SELECT '.$this->getPk().' FROM `'.$this->getSelectTableName().'`';
786
+
787
+ $query.=$this->makeJoins();
788
+ if($this->setConditions($conditions)){
789
+ $whereQuery=$this->makeWhere();
790
+ if(!$whereQuery){
791
+ $this->error('Cannot test element without conditions in model : '.get_class($this));
792
+ }
793
+ }else{
794
+ $this->error('Cannot test element without conditions in model : '.get_class($this));
795
+ return false;
796
+ }
797
+ $res=$this->query('get_res',$query.$whereQuery, ARRAY_A);
798
+ if($res) return $res;
799
+ else return false;
800
+ }
801
+
802
+ function getPk($numb=0){
803
+ $pk=$this->pk;
804
+ if(is_array($pk)) $pk=$pk[$numb];
805
+ return $pk;
806
+ }
807
+
808
+ /**
809
+ * set the values after verifying them
810
+ * @param type $values
811
+ * @return type
812
+ */
813
+ function setValues($values){
814
+ if($this->colCheck && !$this->checkAreColumns($values)) return false;
815
+
816
+ $this->values=array();
817
+ $this->values=$values;
818
+ return true;
819
+ }
820
+
821
+ /**
822
+ *
823
+ * @param type $values
824
+ * @return type
825
+ */
826
+ function setJoin($joins){
827
+ $this->joins=$joins;
828
+ return true;
829
+ }
830
+
831
+ /**
832
+ * set the conditions after verifying them
833
+ * @param type $conditions
834
+ * @return type
835
+ */
836
+ function setConditions($conditions,$update=false){
837
+ if($conditions && is_array($conditions)){
838
+
839
+ $this->conditions=array();
840
+ if($update){
841
+ foreach($conditions as $key =>$cond){
842
+ if($this->colCheck && !$this->checkAreColumns($conditions)) return false;
843
+
844
+ if(is_array($cond)){
845
+ $this->specialUpdate=true;
846
+ $this->conditions=$conditions;
847
+
848
+ return true;
849
+ }else $this->conditions[$key]=$cond;
850
+
851
+ }
852
+ } else {
853
+ foreach($conditions as $key => $cond) {
854
+ if(!in_array($key, $this->comparisonKeys /*array('like','equal','notequal','greater','less','greater_eq','less_eq')*/)){
855
+ if($this->colCheck && !$this->checkAreColumns($conditions)) return false;
856
+ if(array_key_exists('equal', $this->conditions) === false) $this->conditions['equal'] = array();
857
+ $this->conditions['equal'][$key] = $cond;
858
+ }else{
859
+ if($this->colCheck && !$this->checkAreColumns($cond)) return false;
860
+ $this->conditions[$key]=$cond;
861
+ }
862
+
863
+ }
864
+ }
865
+
866
+ return true;
867
+ }else return false;
868
+ }
869
+
870
+ /**
871
+ * check that the columns corresponds to the columns in the model
872
+ * @param type $arrayColumns
873
+ * @return type
874
+ */
875
+ function checkAreColumns($columns){
876
+ if($this->noCheck) return true;
877
+ foreach($columns as $column => $values) {
878
+ // skip when column is a comparison key
879
+ if(in_array($column, $this->comparisonKeys)) continue;
880
+
881
+ $columnName = $column;
882
+ if(!isset($this->columns[$columnName])){
883
+ $this->error(sprintf('Column %1$s does not exist in model : %2$s', $columnName, get_class($this)));
884
+ return false;
885
+ }
886
+ }
887
+ return true;
888
+ }
889
+
890
+ function timer_start() {
891
+ $this->query_duration = 0;
892
+ $this->time_start = microtime( true );
893
+ return true;
894
+ }
895
+
896
+ function timer_stop() {
897
+ $this->query_duration = ( microtime( true ) - $this->time_start );
898
+ }
899
+
900
+ function query($query,$arg2='',$arg3=ARRAY_A){
901
+ $this->sql_error = false;
902
+ if(!$arg2) $query = str_replace(array('[wysija]','[wp]'),array($this->getPrefix(),$this->wpdb->prefix),$query);
903
+ else $arg2 = str_replace(array('[wysija]','[wp]'),array($this->getPrefix(),$this->wpdb->prefix),$arg2);
904
+
905
+ // if dbg is on we track the duration of the query
906
+ if($this->dbg){
907
+ $this->timer_start();
908
+ }
909
+
910
+ switch($query){
911
+ case 'get_row':
912
+ $result = $this->wpdb->get_row($arg2,$arg3);
913
+ $this->logError();
914
+ break;
915
+ case 'get_res':
916
+ $result = $this->wpdb->get_results($arg2,$arg3);
917
+ //$this->escapeQuotesFromRes($results);
918
+ $this->logError();
919
+ break;
920
+ default:
921
+ $result = $this->wpdb->query($query);
922
+ $this->logError();
923
+
924
+ // get the last insert id if it's an insert query
925
+ if(substr($query, 0, 6) == 'INSERT') $result = $this->wpdb->insert_id;
926
+
927
+ }
928
+ // if dbg is on we track the duration of the query
929
+ if($this->dbg){
930
+ $this->timer_stop();
931
+ $this->keepQry('query');
932
+ }
933
+ return $result;
934
+ }
935
+
936
+ function logError(){
937
+ if(defined('WYSIJA_DBG') && WYSIJA_DBG>1){
938
+ global $wysija_queries_errors;
939
+ if(!$wysija_queries_errors) $wysija_queries_errors = array();
940
+
941
+ $this->sql_error = $this->wpdb->last_error;
942
+
943
+ if( $this->sql_error &&
944
+ ( empty( $this->last_error ) || $this->last_error != $this->sql_error )) {
945
+ $this->last_error = $wysija_queries_errors[] = array('query' => $this->wpdb->last_query, 'error' => $this->sql_error);
946
+ $this->sql_error = false;
947
+ WYSIJA::log('queries_errors' , $this->sql_error , 'query_errors');
948
+ }
949
+
950
+ }
951
+
952
+ }
953
+
954
+ function keepQry($from = 'wpdb'){
955
+ global $wysija_queries;
956
+ $wysija_queries[$from][] = array('duration' => $this->query_duration , 'query' => $this->wpdb->last_query);
957
+ }
958
+
959
+ function getAffectedRows(){
960
+ return $this->wpdb->rows_affected;
961
+ }
962
+
963
+ function getErrorMsg(){
964
+ return $this->wpdb->show_errors();
965
+ }
966
+ /**
967
+ * get the full prefix for the table
968
+ * @return type
969
+ */
970
+ function getPrefix(){
971
+ if($this->tableWP) return $this->wpdb->prefix.$this->table_prefix;
972
+ else return $this->wpdb->prefix.$this->table_prefix.'_';
973
+ }
974
+
975
+ /**
976
+ * this function allows you to get the prefix from the main site on a multisite
977
+ * @return type
978
+ */
979
+ function get_site_prefix($blog_id=1){
980
+
981
+ switch_to_blog( $blog_id );
982
+ $main_site_prefix=$this->wpdb->prefix;
983
+ restore_current_blog();
984
+
985
+ if($this->tableWP) return $main_site_prefix.$this->table_prefix;
986
+ else return $main_site_prefix.$this->table_prefix.'_';
987
+ }
988
+
989
+ /**
990
+ *
991
+ * @param type $field_name name of field which will become a key
992
+ * @param array $dataset list of records
993
+ * @param boolean $removing_field_name decide if we should remove field name from output dataset
994
+ * @param string $field_name_as_value a field in which we consider its value as value of $field_name
995
+ * @return array field based indexed dataset
996
+ */
997
+ protected function indexing_dataset_by_field($field_name, Array $dataset, $removing_field_name = false, $field_name_as_value = null){
998
+ if (empty($dataset))
999
+ return array();
1000
+ $tmp = array();
1001
+ foreach ($dataset as $record){
1002
+ if (isset($record[$field_name]))
1003
+ {
1004
+ if (!empty($field_name_as_value)){
1005
+ $tmp[$record[$field_name]] = isset($record[$field_name_as_value]) ? $record[$field_name_as_value] : null;
1006
+ continue;
1007
+ }
1008
+ $tmp[$record[$field_name]] = $record;
1009
+ if ($removing_field_name)
1010
+ unset($tmp[$record[$field_name]][$field_name]);
1011
+ }
1012
+
1013
+ }
1014
+ return $tmp;
1015
+ }
1016
+
1017
+ function beforeInsert(){
1018
+ return true;
1019
+ }
1020
+
1021
+ function afterInsert($resultSaveID){
1022
+ return true;
1023
+ }
1024
+ function beforeDelete($conditions){
1025
+ return true;
1026
+ }
1027
+
1028
+ function afterDelete(){
1029
+ return true;
1030
+ }
1031
+
1032
+ function beforeUpdate($id = null){
1033
+ return true;
1034
+ }
1035
+
1036
+ function afterUpdate($resultSaveID){
1037
+ return true;
1038
+ }
1039
+
1040
+ }
trunk/core/module/module.php ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined('WYSIJA') or die('Restricted access');
4
+
5
+ class WYSIJA_module extends WYSIJA_control{
6
+
7
+ /**
8
+ * ID of module
9
+ * @var string
10
+ */
11
+ protected $name;
12
+
13
+ /**
14
+ * view class of module
15
+ * @var string
16
+ */
17
+ public $view;
18
+
19
+ /**
20
+ * instance of view class of module
21
+ * @var string
22
+ */
23
+ protected $view_obj;
24
+
25
+
26
+ /**
27
+ * action/view of a hook
28
+ * @var string
29
+ */
30
+
31
+ protected $view_show;
32
+
33
+ /**
34
+ * data which view class will pull from
35
+ * @var array
36
+ */
37
+ protected $data;
38
+
39
+ protected $extended_plugin='wysija-newsletters';
40
+
41
+
42
+
43
+ /**
44
+ * Define hook name and list of modules of each hook
45
+ * @var Array
46
+ * @todo: implement hook management which allows to manage hooks from admin side
47
+ */
48
+
49
+ protected $is_premium = false;
50
+
51
+ public static $hooks = array(
52
+ 'hook_stats' => array(
53
+ 'stats_top_newsletters',
54
+ 'stats_top_subscribers',
55
+ 'stats_top_links',
56
+ 'stats_new_subscribers',
57
+ 'stats_subscriptions',
58
+ 'stats_top_domains'
59
+ ),
60
+
61
+ // the left block in the page "subscriber detail"
62
+ 'hook_subscriber_left' => array(
63
+ ),
64
+
65
+ // the righ block in the page "subscriber detail"
66
+ 'hook_subscriber_right' => array(
67
+ 'stats_subscriber'
68
+ ),
69
+ 'hook_subscriber_bottom' => array(
70
+ 'stats_subscribers_std',
71
+ ),
72
+ // top of newsletter (viewstats) page
73
+ 'hook_newsletter_top' => array(
74
+
75
+ 'stats_newsletter_std',
76
+ 'stats_newsletter',
77
+ ),
78
+
79
+ // Newsletters >> Newsletter detail: bottom block
80
+ 'hook_newsletter_bottom' => array(
81
+ //'stats_newsletter_std',
82
+ ),
83
+
84
+ // the block "super advanced" in Settings >> Advanced tab
85
+ 'hook_settings_super_advanced' => array(
86
+ 'archive_std'
87
+ ),
88
+
89
+ // event: before saving settings (Admin)
90
+ 'hook_settings_before_save' => array(
91
+ 'archive_std'
92
+ )
93
+ );
94
+ /**
95
+ * Constructor
96
+ * This is neccessary to override default action of WYSIJA_control::WYSIJA_control(),
97
+ * which always tries to load a default view object
98
+ */
99
+ public function __construct() {
100
+ if (!empty($this->model)){
101
+ $class_name = $this->model;
102
+ $this->model_obj = new $class_name();
103
+ $this->model_obj->limit = 0; // quickfix "Undefined property: WYSIJA_model_statistics::$limit in views\back.php::limitPerPage()"
104
+ }
105
+ $this->get_view_obj($this->extended_plugin);
106
+ if (!empty($this->view_obj) && !empty($this->model_obj)){
107
+ $this->view_obj->model = $this->model_obj;
108
+ }
109
+
110
+ $this->data['module_name'] = $this->name;
111
+
112
+
113
+ $model_config=WYSIJA::get('config','model');
114
+ if($model_config->getValue('premium_key'))
115
+ $this->is_premium = true;
116
+ $this->data['is_premium'] = $this->is_premium;
117
+ }
118
+
119
+ /**
120
+ * get name of module
121
+ * @return string
122
+ */
123
+ public function get_name(){
124
+ return $this->name;
125
+ }
126
+
127
+ /**
128
+ * Get unique link to the module and hook. This link will be displayed as an independent page and actually it renders [wysijap] postype
129
+ * @param string $module_name
130
+ * @param string $hook_name
131
+ * @param array $params (key => value, key => value)
132
+ * @return type
133
+ */
134
+ public static function get_module_link($module_name, $hook_name, $extended_plugin='wysija-newsletters', Array $params = array()) {
135
+ $model_config=WYSIJA::get('config','model');
136
+ $params = array_merge($params, array(
137
+ 'wysija-page' => 1,
138
+ 'controller'=>'module',
139
+ 'action' => 'init',
140
+ 'module' => $module_name,
141
+ 'extension' => $extended_plugin,
142
+ 'hook' => $hook_name
143
+ ));
144
+ return WYSIJA::get_permalink($model_config->getValue('confirm_email_link'),$params);
145
+ }
146
+
147
+ /**
148
+ * Return Hooks List
149
+ * @param string $hook_name name of hook
150
+ * @module_name string $module_name name of a specific module
151
+ * @return Array list of modules
152
+ */
153
+ public static function get_modules_from_hook($hook_name, $module_name = null){
154
+ $module_list = self::get_hook_module_list();
155
+ $modules = !empty($module_list[$hook_name]) ? $module_list[$hook_name] : array();
156
+ if ($module_name)
157
+ return isset($modules[$module_name]) ? array($modules[$module_name]) : array();
158
+ return $modules;
159
+ }
160
+
161
+ /**
162
+ * Get all registered hooks and modules
163
+ * @return Array
164
+ */
165
+ public static function get_hook_module_list(){
166
+ return self::$hooks;
167
+ }
168
+
169
+ /**
170
+ * Execute a hook, module by module, from first one to last one
171
+ * @param string $hook_name
172
+ * @param string $params
173
+ * @param string $extended_plugin
174
+ *
175
+ * @todo Performance factor:
176
+ * We are calling the same method for free / Premium version.
177
+ * Some modules don't exist at free side.
178
+ * Some modules don't exist at Premium side.
179
+ * This fact leads to an other fact: we have to check_exist() in both cases.
180
+ * Solution 1: cache by using a static attribute, within this class
181
+ * Solution 2: populate data to an external file (xml), and load that file into this static attribute (with solution 1)
182
+ */
183
+ public static function execute_hook($hook_name, $params, $extended_plugin='wysija-newsletters'){
184
+ $hook_output = '';
185
+ if (!empty(self::$hooks[$hook_name])){
186
+ foreach (self::$hooks[$hook_name] as $module_name){
187
+ $module = WYSIJA::get($module_name,'module',false,$extended_plugin);
188
+ if(!empty($module) && method_exists($module, $hook_name))
189
+ $hook_output .= $module->$hook_name($params);
190
+ }
191
+ }
192
+ return $hook_output;
193
+ }
194
+
195
+ /**
196
+ * get an instance of a module class
197
+ * @param string $module_name module to be loaded
198
+ * @param type $extended_plugin : used only when calling the url from a different plugin it is used watch those files :
199
+ * -core/controller.php line 21, 23 ,24
200
+ * @return an instance of WYSIJA_module or its derived classes
201
+ */
202
+ public static function get_instance_by_name($module_name,$extended_plugin='wysija-newsletters'){
203
+ return WYSIJA::get($module_name,'module',false, $extended_plugin);
204
+ }
205
+
206
+ /**
207
+ * Render a view/action
208
+ * @return string
209
+ */
210
+ public function render($buffering_output = true){
211
+ if (!empty($this->view))
212
+ {
213
+ if ($buffering_output)
214
+ ob_start();
215
+ if (!$buffering_output)
216
+ return $this->get_view_obj()->render($this->view_show, $this->data, true);
217
+ else{
218
+ $this->get_view_obj()->render($this->view_show, $this->data, true);
219
+ $view = ob_get_contents();
220
+ ob_end_clean();
221
+ return $view;
222
+ }
223
+ }
224
+ }
225
+
226
+ /**
227
+ * initialize WYSIJA_view instance
228
+ * @return WYSIJA_view
229
+ */
230
+ protected function get_view_obj(){
231
+ require_once(WYSIJA_CORE.'view.php');
232
+ require_once(WYSIJA_VIEWS.WYSIJA_SIDE.'.php');
233
+ if (empty($this->view_obj)){
234
+
235
+ $view_dir=WYSIJA_PLG_DIR.$this->extended_plugin.DS.'modules'.DS.$this->name; // quickfix, @todo
236
+ $class_path=$view_dir.DS.$this->view.'.php';// @todo: check exists
237
+ $class_name = strtoupper('wysija').'_module_view_'.$this->view;
238
+ require_once(WYSIJA_CORE.'view.php');
239
+ require_once($class_path);
240
+ $this->view_obj = new $class_name();
241
+ }
242
+ return $this->view_obj;
243
+ }
244
+ }
trunk/core/module/statistics.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WYSIJA_module_statistics extends WYSIJA_module{
5
+ const GROUP_BY_YEAR = 1;
6
+ const GROUP_BY_MONTH = 2;
7
+ const GROUP_BY_DATE = 3;
8
+ const GROUP_BY_HOUR = 4;
9
+ const GROUP_BY_MINUTE = 5;
10
+
11
+ const ORDER_BY_SENT = 1;
12
+ const ORDER_BY_OPEN = 2;
13
+ const ORDER_BY_CLICK = 3;
14
+ const ORDER_BY_UNSUBSCRIBE = 4;
15
+
16
+ const ORDER_DIRECTION_ASC = 1;
17
+ const ORDER_DIRECTION_DESC = 2;
18
+
19
+ const SWITCHING_DATE_TO_MONTH_THRESHOLD = 90;// if the days between FROM and TO is greater than this value, we will group data by month instead of by date. Useful for charts.
20
+
21
+ const DEFAULT_TOP_RECORDS = 5; // default number of how many first records we should retrieve
22
+
23
+ public function __construct() {
24
+ parent::__construct();
25
+ $this->data['messages'] = $this->init_messages();
26
+ }
27
+
28
+ protected function init_messages() {
29
+ return array(
30
+ 'data_not_available' => __("There's no stats to load!", WYSIJA)
31
+ );
32
+ }
33
+ }
trunk/core/module/statistics_model.php ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined('WYSIJA') or die('Restricted access');
4
+
5
+ class WYSIJA_module_statistics_model extends WYSIJA_model {
6
+
7
+ const STATS_DATE_OF_CREATION = 'STATS_DATE_OF_CREATION';
8
+ /**
9
+ * Time to live of stats data
10
+ */
11
+ const STATS_DATA_LIFE_TIME = 3600; // 1h * 60mins * 60s
12
+ /**
13
+ * Time to live of stats's table (structure)
14
+ */
15
+ const STATS_TABLE_LIFE_TIME = 86400; // 24h * 60mins * 60s
16
+
17
+ const STATS_PREFIX = 'sc_'; // prefix of stat tables
18
+
19
+ public function __construct() {
20
+ parent::__construct();
21
+ $this->clean_up_out_of_date_tables();
22
+ }
23
+
24
+ /**
25
+ *
26
+ * @param array $params array of input params
27
+ */
28
+
29
+ public function get_hash(Array $params) {
30
+ $hash = md5(get_class($this) . json_encode($params));
31
+ return substr($hash, 0, 8);// Only get 8 first characters to not make table name too long (less than 64)
32
+ }
33
+
34
+ /**
35
+ * set a date of creating temporary tables, useful for caching
36
+ * @return type
37
+ */
38
+ protected function set_date_of_creation() {
39
+ $config = WYSIJA::get('config', 'model');
40
+ return $config->save(array(self::STATS_DATE_OF_CREATION => time()));
41
+ }
42
+
43
+ /**
44
+ * Check if cache life time is out of date
45
+ * @return boolean
46
+ */
47
+ protected function is_data_out_of_date() {
48
+ $config = WYSIJA::get('config', 'model');
49
+ $date_of_creation = $config->getValue(self::STATS_DATE_OF_CREATION);
50
+ return (time() - $date_of_creation >= self::STATS_DATA_LIFE_TIME);
51
+ }
52
+
53
+ /**
54
+ * Get the list of tables which are out of date, based on create_time
55
+ * @return type
56
+ */
57
+ protected function get_out_of_date_tables() {
58
+ $query = '
59
+ SELECT
60
+ TABLE_NAME as table_name
61
+ FROM
62
+ INFORMATION_SCHEMA.TABLES
63
+ WHERE
64
+ TABLE_SCHEMA IN (SELECT DATABASE())
65
+ AND (TABLE_NAME LIKE "[wysija]'.self::STATS_PREFIX.'%" OR TABLE_NAME LIKE "[wysija]stats_cache_%")
66
+ AND TIMESTAMPDIFF(SECOND,CREATE_TIME, NOW()) >= '.self::STATS_TABLE_LIFE_TIME.';
67
+ ';
68
+ return $this->get_results($query);
69
+ }
70
+
71
+ /**
72
+ * Auto cleanup out-of-date tables
73
+ */
74
+ protected function clean_up_out_of_date_tables() {
75
+ $tables = $this->get_out_of_date_tables();
76
+ if (!empty($tables) && is_array($tables)) {
77
+ $_temp = array();
78
+ foreach ($tables as $table)
79
+ if (!empty($table['table_name']))
80
+ $_temp[] = $table['table_name'];
81
+ }
82
+ if (!empty($_temp)) {
83
+ $query = 'DROP TABLE IF EXISTS `'. implode('`,`', $_temp).'`';
84
+ $this->get_results($query);
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Check if a table exists
90
+ * @param string $table_name table name
91
+ * @return boolean
92
+ */
93
+ protected function does_table_exists($table_name = null) {
94
+ if (empty($table_name) OR !is_string($table_name))
95
+ return false;
96
+ $query = "SHOW TABLES LIKE '$table_name'";
97
+ $result = $this->get_results($query);
98
+ return !empty($result) ? true : false;
99
+ }
100
+
101
+ /**
102
+ * Generate a table name, based on input params
103
+ * @param type $params
104
+ */
105
+ protected function get_table_name($params) {
106
+ $hash = $this->get_hash($params);
107
+ return '[wysija]' . self::STATS_PREFIX . $hash;
108
+ }
109
+
110
+ /**
111
+ * Generate a cached table
112
+ * @param type $table_name
113
+ * @param array $queries_create_table query to create a new cached table
114
+ * @param array $queries_insert_data query to collect and insert data to the newly created/truncated table
115
+ * @return boolean
116
+ */
117
+ protected function generate_table($table_name, Array $queries_create_table, Array $queries_insert_data) {
118
+ $is_out_of_date = $this->is_data_out_of_date();
119
+ $does_table_exists = $this->does_table_exists($table_name);
120
+
121
+ if (!$is_out_of_date && $does_table_exists)
122
+ return true;
123
+ if ($does_table_exists) {
124
+ $this->query('TRUNCATE TABLE `' . $table_name . '`');
125
+ } else {
126
+ foreach ($queries_create_table as $query_create_table)
127
+ $this->query($query_create_table);
128
+ }
129
+
130
+ foreach ($queries_insert_data as $query_insert_data)
131
+ $this->query($query_insert_data);
132
+
133
+ if ($is_out_of_date) {
134
+ $this->set_date_of_creation();
135
+ }
136
+
137
+ return true;
138
+ }
139
+
140
+ }
trunk/core/module/statisticschart.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ abstract class WYSIJA_module_statisticschart extends WYSIJA_module_statistics{
5
+ public function __construct() {
6
+ parent::__construct();
7
+ $this->data['js_date_format'] = 'yy/mm/dd';
8
+ }
9
+ public function init(){
10
+ }
11
+ }
trunk/core/module/statisticstable.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ abstract class WYSIJA_module_statisticstable extends WYSIJA_module_statistics{
5
+ }
trunk/core/view.php ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WYSIJA_view extends WYSIJA_object {
5
+
6
+ var $title = "DEFAULT TITLE";
7
+
8
+ var $icon = "icon-edit";
9
+
10
+ var $links = array( );
11
+
12
+ var $search = array( );
13
+
14
+ var $cols_nks = array( ); //correspondance between user_id and user-id once processed
15
+
16
+ static $color_coordinates = array( );
17
+
18
+ static $cache_color_schemes = array( );
19
+
20
+ /**
21
+ * Color schemes of MailPoet
22
+ * @var array
23
+ */
24
+ var $color_schemes = array(
25
+ array( '#21759b', '#6697BF', '#487192', '#284c69', '#000333' ), // like blue
26
+ array( '#388e71', '#2c6f58', '#16523d', '#0d3c2c', '#092e21' ), // like green
27
+ array( '#c97575', '#a76262', '#854f4f', '#743a3a', '#5a2a2a' ), // like red
28
+ array( '#00CC00', '#269926', '#008500', '#39E639', '#67E667' ), // http://colorschemedesigner.com/#2P11Tw0w0w0w0 // green
29
+ array( '#FF0000', '#BF3030', '#A60000', '#FF4040', '#FF7373' ) // http://colorschemedesigner.com/#0011Tw0w0w0w0 // red
30
+ );
31
+
32
+ /**
33
+ * Default font family
34
+ * @var type
35
+ */
36
+ var $font_family = array( 'Arial' );
37
+
38
+ /**
39
+ * Default font size in pixel
40
+ * @var int
41
+ */
42
+ var $font_size = 12;
43
+
44
+ function __construct(){
45
+ parent::__construct();
46
+ }
47
+
48
+ /**
49
+ * Swap color schemes, to make sure, we don't use 2 colors in a same scheme continously
50
+ * @return array()
51
+ */
52
+ protected function swap_color_schemes() {
53
+ if (empty(self::$cache_color_schemes)) {
54
+ // swap colors from axis X => Y, Y => X
55
+ $x = count($this->color_schemes[0][0]);
56
+ $y = count($this->color_schemes[0]);
57
+ $tmp = array( );
58
+ foreach ($this->color_schemes as $y => $colors) {
59
+ foreach ($colors as $x => $color) {
60
+ $tmp[$x][$y] = $color;
61
+ }
62
+ }
63
+ self::$cache_color_schemes = $tmp;
64
+ }
65
+ return self::$cache_color_schemes;
66
+ }
67
+
68
+ /**
69
+ * Get one random color from schemes
70
+ * @return type
71
+ *
72
+ * Depreciated
73
+ */
74
+ public function get_random_color() {
75
+ return $this->get_next_color();
76
+ }
77
+
78
+ /**
79
+ * Reset color to default
80
+ */
81
+ public function reset_color() {
82
+ $class_name = get_class($this);
83
+ self::$color_coordinates[$class_name] = array( );
84
+ }
85
+
86
+ public function get_next_color() {
87
+
88
+ $color_schemes = $this->swap_color_schemes();
89
+
90
+ $class_name = get_class($this);
91
+ if (empty(self::$color_coordinates[$class_name]))
92
+ self::$color_coordinates[$class_name] = array( 'x' => 0, 'y' => 0 );
93
+
94
+ $current_color = $color_schemes[self::$color_coordinates[$class_name]['x']][self::$color_coordinates[$class_name]['y']];
95
+
96
+ // find out and set a next color
97
+ $flag = false;
98
+ $detected_new_color = false;
99
+ foreach ($color_schemes as $x => $colors) {
100
+ if ($detected_new_color)
101
+ break;
102
+ foreach ($colors as $y => $color) {
103
+ if ($flag) {
104
+ self::$color_coordinates[$class_name]['x'] = $x;
105
+ self::$color_coordinates[$class_name]['y'] = $y;
106
+ $detected_new_color = true;
107
+ break;
108
+ }
109
+ if ($x == self::$color_coordinates[$class_name]['x'] && $y == self::$color_coordinates[$class_name]['y'])
110
+ $flag = true;
111
+ }
112
+ }
113
+ if (!$detected_new_color) {
114
+ self::$color_coordinates[$class_name]['x'] = 0;
115
+ self::$color_coordinates[$class_name]['y'] = 0;
116
+ }
117
+ return $current_color;
118
+ }
119
+
120
+ /**
121
+ * Get all colors from schemes
122
+ * @return type
123
+ */
124
+ function get_all_colors() {
125
+ $color_schemes = $this->swap_color_schemes(); // this one, to make sure, we don't put same color tone continously
126
+
127
+ $tmp = array( );
128
+ foreach ($color_schemes as $colors) {
129
+ $tmp = array_merge($tmp, $colors);
130
+ }
131
+ return $tmp;
132
+ }
133
+
134
+ function renderErrorInstall() {
135
+ $this->title = __("Your server's configuration doesn't allow us to complete MailPoet's Installation!", WYSIJA);
136
+ $this->header();
137
+ $this->footer();
138
+ }
139
+
140
+ /**
141
+ *
142
+ * @param type $type
143
+ * @param type $data
144
+ * @param bool $is_module is rendering a module view
145
+ */
146
+ function render($type, $data, $is_module = false) {
147
+ $this->action = $type;
148
+ if (!$is_module) {
149
+ $this->header($data);
150
+ }
151
+ if ($type !== NULL) {
152
+ $this->$type($data);
153
+ }
154
+ if (!$is_module) {
155
+ $this->footer();
156
+ }
157
+ }
158
+
159
+ /**
160
+ * display all the messages that have queued
161
+ * @global type $wysija_msg
162
+ */
163
+ function messages($noglobal = false) {
164
+ $wysija_msg = $this->getMsgs();
165
+
166
+ if (isset($wysija_msg['g-updated'])) {
167
+ if (!$noglobal) {
168
+ if (isset($wysija_msg['updated']))
169
+ $wysija_msg['updated'] = array_merge((array)$wysija_msg['updated'], $wysija_msg['g-updated']);
170
+ else
171
+ $wysija_msg['updated'] = $wysija_msg['g-updated'];
172
+ }
173
+ unset($wysija_msg['g-updated']);
174
+ }
175
+ if (isset($wysija_msg['g-error'])) {
176
+ if (!$noglobal) {
177
+ if (isset($wysija_msg['error']))
178
+ $wysija_msg['error'] = array_merge((array)$wysija_msg['error'], $wysija_msg['g-error']);
179
+ else
180
+ $wysija_msg['error'] = $wysija_msg['g-error'];
181
+ }
182
+ unset($wysija_msg['g-error']);
183
+ }
184
+ $wpnonce = '<input type="hidden" value="'.wp_create_nonce("wysija_ajax").'" id="wysijax" />';
185
+ if (!$wysija_msg)
186
+ return '<div class="wysija-msg ajax"></div>'.$wpnonce;
187
+ $html = '<div class="wysija-msg">';
188
+ foreach ($wysija_msg as $level => $messages) {
189
+ $msg_class = '';
190
+ switch ($level) {
191
+ case 'updated':
192
+ $msg_class = 'notice-msg updated';
193
+ break;
194
+ case 'error':
195
+ $msg_class = 'error-msg error';
196
+ break;
197
+ case 'xdetailed-updated':
198
+ $msg_class = 'xdetailed-updated';
199
+ break;
200
+ case 'xdetailed-errors':
201
+ $msg_class = 'xdetailed-errors';
202
+ break;
203
+ }
204
+
205
+ $html.='<div class="'.$msg_class.'">';
206
+ $html.='<ul>';
207
+
208
+ if (count($messages) > 0) {
209
+ foreach ($messages as $msg) {
210
+ // check type of msg variable
211
+ if (is_array($msg)) {
212
+ $msg = var_export($msg, true);
213
+ }
214
+
215
+ // display message
216
+ $html.='<li>'.$msg.'</li>';
217
+ }
218
+ }
219
+
220
+
221
+ $html.='</ul>';
222
+ $html.='</div>';
223
+ }
224
+ $html.='</div><div class="wysija-msg ajax"></div>'.$wpnonce;
225
+
226
+ return $html;
227
+ }
228
+
229
+ /**
230
+ * this function let us generate a nonce which is an encrypted unique word based n the user info and some other stuff.
231
+ * by default it will create an hidden input nonce field
232
+ * @param type $params
233
+ * @param type $get
234
+ * @return type
235
+ */
236
+ static function secure($params = array( ), $get = false, $echo = true) {
237
+ $controller = '';
238
+ if (!is_array($params))
239
+ $action = $params;
240
+ else {
241
+ $action = $params['action'];
242
+ if (isset($params['controller']))
243
+ $controller = $params['controller'];
244
+ elseif (isset($_REQUEST['page']))
245
+ $controller = $_REQUEST['page'];
246
+ }
247
+ $nonceaction = $controller.'-action_'.$action;
248
+
249
+ if (is_array($params) && isset($params['id']) && $params['id'])
250
+ $nonceaction.='-id_'.$params['id'];
251
+
252
+ if ($get) {
253
+ return wp_create_nonce($nonceaction);
254
+ }
255
+ else {
256
+ return wp_nonce_field($nonceaction, '_wpnonce', true, $echo);
257
+ }
258
+ }
259
+
260
+ /**
261
+ * this allows us to get a field class to be validated by when making a form field
262
+ * @param type $params
263
+ * @param string $prefixclass
264
+ * @return string
265
+ */
266
+ function getClassValidate($params, $returnAttr = false, $prefixclass = "") {
267
+ $class_validate = '';
268
+ $recognised_types = array( 'email', 'url' );
269
+
270
+ if (isset($params['req'])) {
271
+ $class_validate = 'required';
272
+ if (isset($params['type']) && in_array($params['type'], $recognised_types)) {
273
+ $class_validate.=',custom['.$params['type'].']';
274
+ }
275
+ }
276
+ else {
277
+ if (isset($params['type']) && in_array($params['type'], $recognised_types)) {
278
+ $class_validate.='custom['.$params['type'].']';
279
+ }
280
+ }
281
+
282
+ if ($prefixclass)
283
+ $prefixclass.=' ';
284
+ if ($class_validate)
285
+ $class_validate = 'validate['.$class_validate.']';
286
+ if (!$returnAttr && $class_validate)
287
+ $class_validate = ' class="'.$prefixclass.$class_validate.'" ';
288
+
289
+ return $class_validate;
290
+ }
291
+
292
+ /**
293
+ * central function to return a translated formated date
294
+ * @param type $val
295
+ * @param type $format
296
+ * @return string
297
+ */
298
+ function fieldListHTML_created_at($val, $format = '') {
299
+ if (!$val)
300
+ return '---';
301
+
302
+ //offset the time to the time of the WP site not the server
303
+ $helper_toolbox = WYSIJA::get('toolbox', 'helper');
304
+ // get current time taking timezone into account.
305
+
306
+ $val = $helper_toolbox->servertime_to_localtime($val);
307
+
308
+ if ($format)
309
+ return date_i18n($format, $val);
310
+ else
311
+ return date_i18n(get_option('date_format'), $val);
312
+ }
313
+
314
+ function fieldListHTML_created_at_time($val) {
315
+ return $this->fieldListHTML_created_at($val, get_option('date_format').', '.get_option('time_format'));
316
+ }
317
+
318
+ }
trunk/css/add-ons.css ADDED
@@ -0,0 +1 @@
 
1
+ .module-container{overflow:hidden;width:100%;min-width:676px;margin:20px 0px}.module-container p,.module-container h2,.module-container h3{margin-left:6px}.mailpoet-module{position:relative;float:left;width:320px;min-height:330px;margin:0px 16px 18px 0px;border:1px solid #e5e5e5;background:#fff;padding:0px 0 14px 0px;box-shadow:0 1px 1px rgba(0,0,0,0.04);overflow:hidden}.mailpoet-module.not-ready{border-color:#eee;cursor:pointer}.mailpoet-module .mailpoet-module-image{margin:0px 12px}.mailpoet-module .mailpoet-module-content p{margin:0px 0px 8px 0px}.mailpoet-module .mailpoet-module-content p span.mailpoet-module-badge{background-color:#df1d4f;color:#fff;font-weight:bold;padding:6px 10px;margin-right:4px;border:1px solid #cc1148;border-radius:0px 0px 3px 3px}.mailpoet-module .mailpoet-module-content p span.mailpoet-module-badge a{color:#fff !important;text-decoration:none;border-bottom:1px dotted #fff}.mailpoet-module .mailpoet-module-content p span.mailpoet-module-badge.new{float:right !important;margin-top:-6px;background-color:#054e6e !important;border:1px solid #054e6e !important}.mailpoet-module .mailpoet-module-actions{display:block;position:absolute;bottom:6px;left:10px}.mailpoet-module .mailpoet-module-actions a{position:relative;margin-bottom:4px}.mailpoet-module-content{margin:0 1em}.mailpoet-module h3{line-height:1.1;margin:6px 12px;padding:3px 0px;font-size:14px;font-weight:bold;font-style:normal;color:#000}.mailpoet-module-description p{line-height:150%;font-size:12px;margin-bottom:20px;color:#666}.submit-idea{clear:both;display:block;padding:8px 15px;margin:8px 4px;overflow:hidden;line-height:180%}
trunk/css/admin-campaigns-articles.css ADDED
@@ -0,0 +1 @@
 
1
+ #results{min-height:430px;padding:0 0 50px 0;width:98%}#results .loading{margin:10px 0 0 0}#results li{border:1px solid #ddd;height:38px;margin:0 0 10px 0;padding:0;background-color:#FFF;position:relative}#results li .checkbox_container{width:38px;height:38px;text-align:center;line-height:35px;float:left;position:relative}#results li .checkbox{cursor:pointer;margin:0 0 0 11px}#results .thumbnail{width:60px;height:38px;overflow:hidden;float:left;margin:0 10px 0 0}#results li label{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;margin:0 0 0 0;line-height:38px;height:38px;overflow:hidden;float:left;width:510px}#results li label.with_thumbnail{width:440px}#results li.selected{border-color:#0074A2;cursor:pointer}#results li.selected label{color:#0074A2}#results hr{border:0 none;border-top:1px solid #dbdbdb;height:1px;line-height:1px}#basic .filters-box{float:left;margin:0}.filters-box #post_type{width:120px}.filters-box .post_category{width:160px}.filters-box #post_status{width:140px}#basic .search-box{float:right;margin:0}input#search{width:160px}#search-submit{font-size:13px;margin:0 14px 0 0;padding:1px 10px}#toggle-advanced{position:relative;right:10px;top:0}#advanced{padding:0 0 50px 0;display:none}#advanced div.block{padding:0.8em 0 0.8em 1em;margin:0}#advanced div.block p{margin:0 0 5px 0;padding:0}#advanced label{float:left;width:200px;padding:0}#advanced div.block p label{float:none}#image_width_slider{float:left;width:252px;margin:15px 0 0 5px;height:0px;position:relative;cursor:pointer;border:2px solid #808080;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}#slider_handle{width:16px;height:16px;cursor:pointer;position:absolute;top:-9px;margin:0 0 0 -2px;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;background-color:#fff;box-shadow:inset 0px 0px 2px rgba(0,0,0,0.1);border:1px solid #ccc}#slider_info{float:left;font-weight:bold;margin:7px}#advanced label span.label{float:none;display:block;font-size:10px;font-style:italic;line-height:1.2em;width:120px}#advanced label.radio{float:left;width:auto;margin:0 9px 0 0}#advanced label.radio input{margin:0 2px 0 0}#advanced div.group{float:left}.cpt-type{background-color:#F1F1F1;border-left:1px solid #ccc;bottom:0;color:#21759B;font-style:italic;padding:0 10px;position:absolute;right:0;top:0;line-height:38px}.cpt-type small{color:#888}.modcoder_excolor_clrbox{width:17px;height:17px;margin:4px 0 0 0;color:transparent;padding:0}
trunk/css/admin-campaigns-autopost.css ADDED
@@ -0,0 +1 @@
 
1
+ .autopost{padding:0 10px 10px 0;display:block}.autopost div.block{padding:0.8em 0 0.8em 1em;margin:0}.autopost div.block p{margin:0 0 5px 0;padding:0}.autopost label{float:left;width:200px;padding:0}.autopost div.block p label{float:none}.autopost label span.label{float:none;display:block;font-size:10px;font-style:italic;line-height:1.2em;width:120px}.autopost label.radio{float:left;width:auto;margin:0 9px 0 0}.autopost label.radio input{margin:0 2px 0 0}.autopost div.group{float:left}#image_width_slider{float:left;width:252px;margin:15px 0 0 5px;height:0px;position:relative;cursor:pointer;border:2px solid #808080;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}#slider_handle{width:16px;height:16px;cursor:pointer;position:absolute;top:-9px;margin:0 0 0 -2px;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;background-color:#fff;box-shadow:inset 0px 0px 2px rgba(0,0,0,0.1);border:1px solid #ccc}#slider_info{float:left;font-weight:bold;margin:7px}select#category_ids{width:400px}#toggle-advanced{margin:0 0 0 12px}#advanced{display:none}.modcoder_excolor_clrbox{width:17px;height:17px;margin:4px 0 0 0;color:transparent;padding:0}
trunk/css/admin-campaigns-bookmarks.css ADDED
@@ -0,0 +1 @@
 
1
+ .bookmarks .networks li{margin:0 0 10px 0}.bookmarks .networks label{width:70px;float:left;font-weight:normal}.bookmarks .networks input{width:350px;float:left}.bookmarks .sizes{margin:20px 0 0 0}.bookmarks .sizes a{margin:0 0 0 10px}.bookmarks .sizes a.selected{font-weight:bold}.bookmarks .sizes .small{font-size:12px}.bookmarks .sizes .medium{font-size:14px}.bookmarks .sizes .large{font-size:16px}.bookmarks .icons{height:230px;overflow:auto}.bookmarks .icons li{margin:10px}.bookmarks .icons li a{padding:5px;margin:0;display:-moz-inline-box;display:inline-block;*display:inline;*float:left}.bookmarks .icons li a.selected{border:2px solid #DD561A;padding:3px}.bookmarks .icons img{margin:0 5px;vertical-align:middle}
trunk/css/admin-campaigns-dividers.css ADDED
@@ -0,0 +1 @@
 
1
+ .wysija_popup_content.divider{width:620px}.dividers ul{height:350px;width:620px;overflow:auto;margin:0 0 20px 0}.dividers li{text-align:center;padding:5px 2px}.dividers li a{padding:2px;display:block}.dividers li a.selected{padding:0;border:2px solid #DD561A}.dividers li img{vertical-align:middle}
trunk/css/admin-campaigns-editDetails.css ADDED
@@ -0,0 +1 @@
 
1
+ #datepicker-day{margin-left:10px;min-width:90px}
trunk/css/admin-campaigns-editTemplate.css ADDED
@@ -0,0 +1 @@
 
1
+ #TB_window.default,#TB_window.default #TB_iframeContent{width:750px !important;height:550px !important}#TB_window.addlink,#TB_window.addlink #TB_iframeContent{width:350px !important;height:205px !important}#TB_window.themes,#TB_window.themes #TB_iframeContent{height:535px !important;overflow:hidden;width:750px !important}#TB_window.dividers,#TB_window.dividers #TB_iframeContent{height:470px !important;width:665px !important}#TB_window.bookmarks,#TB_window.bookmarks #TB_iframeContent{height:475px !important;width:670px !important}#TB_window p.notice{font-style:italic;font-size:11px}.wysija-msg,.updated,.error{display:none}.wysija-msg.ajax,.wysija-msg.ajax .updated,.wysija-msg.ajax .error,.ui-dialog-content .error,.ui-dialog-content .updated{display:block}.sendtestemail{background-color:#EAEAEA;border-color:#BFBFBF;border-radius:14px 14px 14px 14px;border-style:dashed;border-width:2px;height:32px;margin:30px 0 10px;padding-left:10px;padding-top:9px;width:300px}.ui-widget-overlay{z-index:9998 !important;background-image:none !important}.wj_themes span.default-wrap,.wj_themes span.delete-wrap,.wj_images span.delete-wrap{background-color:#DFDFDF;background-image:-moz-linear-gradient(center bottom, #bbb, #eee);border:1px solid #CCCCCC;border-radius:2px 2px 2px 2px;box-shadow:0 1px 0 rgba(0,0,0,0.15),0 0 2px 1px #fff inset;height:20px;position:absolute;width:20px;z-index:9999;text-indent:-99999px;overflow:hidden}.wj_themes span.default-wrap{right:28px;top:2px}.wj_themes span.delete-wrap,.wj_images span.delete-wrap{right:2px;top:2px}.wj_themes span.default,.wj_themes span.delete,.wj_images span.delete{cursor:pointer;display:block;height:20px;text-indent:-9999px;width:20px;z-index:9999}.wj_themes span.delete,.wj_images span.delete{background:url("../img/controls/icons.png") no-repeat scroll -100px 0 transparent}.wj_themes span.default{background:url("../img/controls/icons.png") no-repeat scroll -240px 0 transparent}.wj_themes span.default:hover{background:url("../img/controls/icons.png") no-repeat scroll -240px -20px transparent}.wj_themes span.default.selected,.wj_themes span.default.selected:hover{background:url("../img/controls/icons.png") no-repeat scroll -260px -20px transparent}#screen-meta{z-index:10000}.marginl{margin-left:10px}
trunk/css/admin-campaigns-medias.css ADDED
@@ -0,0 +1 @@
 
1
+ ul#sidemenu{bottom:-1px;float:none !important;font-weight:normal;left:0;margin:0 5px;overflow:hidden;float:none !important}.wysija-thumb{float:left;height:150px;margin:10px;width:150px;position:relative;border:2px dashed transparent;filter:alpha(opacity=60);-moz-opacity:0.6;opacity:0.6;margin:8px}.wysija-thumb:hover,.wysija-thumb.selected:hover{border-color:#000;border-style:dashed}.wysija-thumb.selected{border-color:#4a5b04;border-style:solid;filter:alpha(opacity=100);-moz-opacity:1;opacity:1}.wysija-thumb img{cursor:pointer;max-height:150px;max-width:150px}.wysija-thumb span.delete{background:url("../img/controls/icons.png") no-repeat scroll -100px 0 transparent;cursor:pointer;height:20px;text-indent:-9999px;display:block;width:20px}.wysija-thumb span.delete-wrap{background-color:#DFDFDF;background-image:-moz-linear-gradient(center bottom, #bbb, #eee);border:1px solid #CCCCCC;border-radius:2px 2px 2px 2px;box-shadow:0 1px 0 rgba(0,0,0,0.15),0 0 2px 1px #fff inset;height:20px;position:absolute;right:2px;top:2px;margin:5px 3px 0 0;width:20px;display:none}.wysija-thumb span.thumb_url,.wysija-thumb span.url,.wysija-thumb span.width,.wysija-thumb span.height,.wysija-thumb span.identifier{display:none}.wysija-thumb:hover span.delete-wrap{display:block}.wysija-thumb span.delete:hover{background-position:-100px -20px}.clear{clear:both}.tablenav{margin-right:20px}#media-items{overflow:auto}.media-wp-upload #media-items{display:none}.media-browse #media-items{width:100%;height:340px;margin:0 0 10px 0}.media-wp-browse #media-items{width:100%;height:340px;margin:0 0 10px 0}#media-items em{margin:0 0 0 20px}#media-items,.ml-submit{float:left}.ml-submit{margin-top:15px;margin-left:15px}#loader{left:50%;position:relative;top:50%}#overlay{background-color:#FFFFFF;height:100%;opacity:0.8;position:absolute;width:100%;z-index:999;display:none}#flash-upload-ui{padding:10px 25px}.after-file-upload{padding:0 25px}.after-file-upload,.upload-flash-bypass,.howto{display:none}.wysija-thumb .slidetoggle,.wysija-thumb .toggle{display:none}.max-upload-size{margin:10px 0;display:block}
trunk/css/admin-campaigns-themes.css ADDED
@@ -0,0 +1 @@
 
1
+ ul#sidemenu{bottom:-1px;float:none !important;font-weight:normal;left:0;margin:0 5px;overflow:hidden}#loader{left:50%;position:relative;top:50%}.loading{margin:15px 0 0 0}#overlay{background-color:#fff;opacity:0.8;width:100%;height:100%;position:fixed;top:0;bottom:0;left:0;right:0;z-index:999;display:none}#flash-upload-ui{padding:10px 25px}.after-file-upload{padding:0 25px}#close-pop-alt{float:right;margin-right:50px;margin-top:10px}.after-file-upload,.upload-flash-bypass,.howto{display:none}#theme-view .preview,#theme-view .infos{float:left}#theme-view .infos{width:300px;margin:0 0 0 20px}#theme-view .preview{background:url(../img/wpspin_light.gif) no-repeat scroll center center transparent}#theme-view .preview img{width:320px;display:block}#theme-view{font-size:14px;height:480px;overflow:auto}#theme-view h2{color:#555555;font-family:Tahoma;font-size:24px;margin:4px 0 0;line-height:1.2em}#theme-view .actions{margin-bottom:10px}div.star{background-color:transparent;border:medium none;height:100%;left:0;letter-spacing:1ex;position:absolute;top:0}.stars{background:url(../img/stars.png) repeat-x scroll left bottom transparent;height:17px;position:relative;width:95px}.stars .star-rating{background:url(../img/stars.png) repeat-x scroll left top transparent;float:left;height:17px;overflow:hidden;text-indent:100%;white-space:nowrap}.my-rating a{height:17px;width:19px;float:left;margin:0;padding:0}.my-rating a.active,.my-rating a:hover,.my-rating a.on{background:url(../img/stars.png) no-repeat left top transparent}.my-rating a.active.off,.my-rating a.off{background:none}div.paragraph{margin:10px 0}.star-holder.my-rate img{cursor:pointer}.star-holder.my-rate div.star:hover{background-color:#DD0000}div.star.select.star-rating{background-color:#FFCC00}#theme-upload{display:none}.avatar{border:2px solid #CCC;float:right;margin:0}#overwrite{margin:0px 10px 0 0}#filter-selection{position:relative;top:3px}.theme-screenshot{padding:0;width:320px;border:1px solid #ccc;position:relative;background-color:#fff;-webkit-box-shadow:0 0 4px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1);-moz-box-shadow:0 0 4px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1);box-shadow:0 0 5px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1)}.theme-screenshot:before,.theme-screenshot:after{position:absolute;width:40%;height:10px;content:' ';left:12px;bottom:12px;background:transparent;-webkit-transform:skew(-5deg) rotate(-5deg);-moz-transform:skew(-5deg) rotate(-5deg);-ms-transform:skew(-5deg) rotate(-5deg);-o-transform:skew(-5deg) rotate(-5deg);transform:skew(-5deg) rotate(-5deg);-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);-moz-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3);z-index:-1}.theme-screenshot:after{left:auto;right:12px;-webkit-transform:skew(5deg) rotate(5deg);-moz-transform:skew(5deg) rotate(5deg);-ms-transform:skew(5deg) rotate(5deg);-o-transform:skew(5deg) rotate(5deg);transform:skew(5deg) rotate(5deg)}.theme-screenshot img{width:320px}#wj_paginator{float:right;margin-right:10px;font-size:14px}#wj_paginator a{margin:0 1px}#wj_paginator span{font-weight:bold;margin:0 1px}#wj_paginator a.selected{color:#000;text-decoration:none;cursor:default}#themes-list{height:405px;margin:0}.theme{float:left;margin:0px;overflow:hidden;width:152px;margin:25px 8px 0 0}.theme.last{margin-right:0}.theme .thumbnail{height:170px;width:150px;position:relative;border:1px solid #999999;background-color:#000000}.theme img{width:150px;height:170px;position:absolute;z-index:1;top:0px;left:0px}.theme .install{display:none;float:none !important}.theme:hover img{filter:alpha(opacity=25);-moz-opacity:0.25;opacity:0.25}.theme:hover .thumbnail{border:1px solid #2a749f}.theme:hover .install{display:block;position:relative;z-index:100;text-align:center;margin:0px auto;margin-top:80px;width:80px !important}.theme .infos{display:block;width:100%;margin:5px 0 0 0;padding:0;text-align:left;font-size:12px;line-height:1em;color:#999999;text-decoration:none}.theme .infos:hover{color:#21759b;text-decoration:underline}
trunk/css/admin-campaigns-viewstats.css ADDED
@@ -0,0 +1 @@
 
1
+ #posts-filter{margin-top:40px}#hook_newsletter_top{margin-top:20px}#hook_newsletter_top .left{float:left;width:50%}#hook_newsletter_top .right{float:right}#hook_newsletter_top .actions{width:45%;margin-bottom:20px;padding-left:10px}.action_buttons a:first-child{margin-left:0}.action_buttons{display:block}table.newsletter-stats-block{margin-top:10px}table.newsletter-stats-block td.label{width:25%;font-weight:bold}.wrap .button-secondary2{top:auto !important}.googletrackingcode .action_buttons{padding-left:0}.googletrackingcode{padding-top:10px}.wrap .button-secondary2:first-child{margin-left:0}
trunk/css/admin-campaigns-welcome_new.css ADDED
@@ -0,0 +1 @@
 
1
+ #wysija-app .welcome_poll li{list-style:none outside none;margin:10px 0;font-size:14px;line-height:20px}#wysija-app .welcome_poll li input{margin:0 10px 0 0}#how_did_you_find_us_4_url{width:50%}#poll_result{font-weight:bold;padding-left:5px}#poll_result span.checkmark{background:url("../img/controls/icons.png") no-repeat scroll -260px -20px transparent;display:inline-block;text-indent:-9999px;width:20px}#wysija-app .about-wrap .feature-section{margin-top:0}#wysija-app .about-wrap .feature-section h4{margin:0.6em 0 0.6em}
trunk/css/admin-campaigns.css ADDED
@@ -0,0 +1 @@
 
1
+ #wysija-app{padding-top:10px}.icon32{margin-top:0px !important}#posts-filter{clear:both}#wysija-app h2{display:inline}#icon-edit-news{background:url(../img/mail-big.png) no-repeat scroll 0 5px transparent}#TB_window{display:block}.moredetails{display:none}.sending,.scheduled{background-color:#d5f0e6}.autonl.sending{background-color:#D7E6F2}#wysija-campaign .listmissing{background-color:#EFD5D5}#preview-receiver{width:230px;vertical-align:middle;margin:0 5px 0 0}.ml-submit{margin:15px 15px 0 15px}.automatic-nl{display:none}#titlediv .titlebox{font-size:1.7em;background-color:#FFFFFF;border-color:#CCCCCC;line-height:100%;outline:medium none;padding:3px 8px;width:100%}label .description{cursor:auto}.about-wrap .feature-section.three-col>div{float:left;width:28%;padding-right:30px;padding-left:0}#socials-block div{float:none;margin:5px 5px 2px 0;width:100%}.progress_bar{padding-bottom:10px}.progress_bar .bar{display:block;width:100%;height:22px;float:left;margin-right:10px;background:#eef6fc;border:1px solid #bbbbbb;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;line-height:22px;position:relative}.progress_bar .progress{display:block;background:#69b1e9;height:100%}.progress_bar .percent{height:100%;position:absolute;top:0px;left:10px}#wysija-badge{position:absolute;top:0;right:0;color:#fff;text-shadow:0 1px 0 rgba(0,0,0,0.3);padding-top:91px;height:50px;width:173px;font-weight:bold;font-size:14px;text-align:center;margin:0 -5px;background:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/wysija-badge.png") no-repeat}#review-follow{position:relative;height:177px}#review-follow div{float:left;top:0}#review-follow .review-left{background:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/update_page/save-the-kitten.jpg") no-repeat;height:175px;background-color:#f8f8f8;border-top:1px solid #efefef;border-bottom:1px solid #efefef;padding-right:10px}#review-follow h4{margin:0 !important}#review-follow .review-left.small{width:450px}#review-follow .review-left.medium{width:490px}#review-follow .review-left.large{width:540px}#review-follow .small .description{margin-top:24px}#review-follow .medium .description{margin-top:20px}#review-follow .large .description{margin-top:18px}#review-follow .review-left p{margin-left:20px}#review-follow .review-right{background:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/update_page/arrow_middle.jpg") no-repeat scroll -30px 0 #f8f8f8;border-bottom:1px solid #EFEFEF;border-top:1px solid #EFEFEF;height:175px;width:24px}#review-follow #mailpoet-subscribe{margin-left:0px;margin-top:10px}#review-follow .subscribe-middle{width:220px;height:175px;background-color:#f8f8f8;border-top:1px solid #efefef;border-bottom:1px solid #efefef}#review-follow .socials{margin-left:30px}#review-follow .follow-left{width:220px;height:175px;background-color:#f8f8f8;border-top:1px solid #efefef;border-bottom:1px solid #efefef}#review-follow .follow-right{background:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/update_page/arrow_right.jpg") no-repeat;width:100px;height:175px}#review-follow .follow-right38{background:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/update_page/arrow-right-38.jpg") no-repeat;width:100px;height:175px}#review-follow .review-left .description{margin-left:146px}#review-follow .link-cat-review{height:140px;left:20px;position:absolute;top:21px;width:120px;outline:medium none}a.ctaupdate,span.ctaupdate{font-size:12px}.pds-links,.pds-totalvotes-outer{display:none !important}#polldaddy_embed_0{width:680px;margin-left:-30px}span.local_time{margin-left:10px}#hook_newsletter_top .hook-column{width:50%}.card-title{font-weight:bold}.report-card{padding-top:10px}.googletrackingcode .action_buttons{padding-left:44px;padding-top:5px}.googletrackingcode span{font-weight:bold}.mpoet-page h1{font-size:34px}.mpoet-page h1,.mpoet-page h2,.mpoet-page h3,.mpoet-page h4{color:#626262;font-weight:bold}.mpoet-page h1 span.version{color:#5e869b}.mpoet-update-subscribe p{font-size:12px}.mpoet-update-subscribe li{font-size:12px;line-height:10px}.mpoet-update-subscribe-left,.mpoet-update-subscribe-right{float:left}.mpoet-update-subscribe-left{margin-right:50px}.about-wrap .feature-section .mpoet-update-subscribe-left p{margin-top:0;margin-bottom:5px}.about-wrap .feature-section .mpoet-update-subscribe-left ul{margin-top:5px;margin-bottom:5px}#update-page{margin-top:0px}.mp_php_alert{margin:5px 0 15px;background-color:#fff;border-left:4px solid #7ad03a;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);padding:1px 12px;outline:0 none}.feature-section ul{list-style:disc inside none}#update-page .about-text{margin-bottom:1em;margin-top:0;min-height:20px}.mpoet-update-subscribe-left .button-primary{font-size:18px;height:32px}#update-loading-icon{background:url("../img/wpspin_light.gif") no-repeat scroll 0 0 transparent;height:20px;margin-left:26%;margin-top:6px;width:20px;display:none}
trunk/css/admin-config-form_widget_settings.css ADDED
@@ -0,0 +1 @@
 
1
+ .form_widget_settings p label{float:left;clear:left;width:200px}#widget-settings-error{margin-right:10px;padding:10px;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;color:#000;font-weight:normal;background-color:#ffebe8;border:1px solid #c00}.sortable li{margin:0;padding:5px}.sortable li:hover{background-color:#eee}.icon span{display:block;height:20px;width:20px}.handle span{cursor:move;background:url(../img/controls/icons.png) no-repeat -120px 0}.handle a.active span,.handle:hover span{background:url(../img/controls/icons.png) no-repeat -120px -20px;cursor:move}.add span{background:url(../img/controls/icons.png) no-repeat -200px 0;float:left}.add.active span,.add:hover span{background:url(../img/controls/icons.png) no-repeat -200px -20px}.remove span{background:url(../img/controls/icons.png) no-repeat -100px 0}.remove.active span,.remove:hover span{background:url(../img/controls/icons.png) no-repeat -100px -20px}#widget-field-settings{margin:0 0 0 10px;display:none}.widget_text textarea,.widget_html textarea{height:120px;width:450px;resize:none}.widget_html input.checkbox,label input[type="checkbox"],label input[type="radio"]{margin:0px 5px 0 0px}.widget_list #lists-available{float:left;padding:0;width:250px}.form_widget_settings .icon.add{line-height:20px;outline:0}.form_widget_settings .selection{background-color:#fff;border:1px solid #dfdfdf;width:100%}.form_widget_settings .selection input[name="is_checked"],.form_widget_settings .selection input.is_checked{margin:0px 0px 2px 3px}.form_widget_settings .selection li{padding:5px 3px;margin:0}.form_widget_settings .selection input{margin:0 5px 0px 0}.form_widget_settings .selection .value{margin:0}.form_widget_settings .selection .is_selected{float:left;margin:3px 0 0 6px !important}.form_widget_settings .selection label{float:left;margin:0 0 0 5px;width:220px;height:20px;line-height:20px;overflow:hidden}.form_widget_settings .selection .handle,.form_widget_settings .selection .remove{float:right;margin:3px 3px 0 0}.form_widget_settings #selection-template{display:none}.form_widget_settings .hidden{display:none}.form_widget_settings label.radio{margin:0 10px 0 0}#date-format-value{display:none}
trunk/css/admin-config.css ADDED
@@ -0,0 +1 @@
 
1
+ tr.title_row>td{padding-left:0}#wysija-tabs a{font-size:14px}#wysija-tabs a:focus{outline:0 none}#wysija-settings .premium_activated{color:#0074A2;font-size:1.2em;padding:15px 0 20px 0}#wysija-settings .premium_activated i{font-size:1.5em;margin:0 6px 3px 0;vertical-align:bottom}#wysija-settings .premium_activated .expiring_at{color:#666;font-size:12px}p.submit{padding:1em 1.4em 1em 0}span.title{font-size:16px;margin:0;color:#000}.mailpoet-frequency_inner_texting{padding:0 10px}.mailpoet-frequency_warning{margin-top:10px}#wysija-settings input[type="checkbox"],#wysija-settings input[type="radio"]{margin-right:6px;vertical-align:baseline}#wysija-settings label input[type="checkbox"],#cron_page_hit_trigger-1{margin-left:0}#wysija-settings .button-secondary{margin-left:6px}#wysija-settings .form-table th{width:300px}#wysija-settings .form-table th.row{border:1px solid #AAAAAA}#warning-msg-frequency{background-color:#FFFFE0;border-color:#E6DB55}#warning-msg-frequency{border-radius:3px 3px 3px 3px;border-style:solid;border-width:1px;margin:5px 15px 2px;padding:0 0.6em}#warning-msg-frequency ul{margin:0}#wysija-settings .form-table th.rolestitle{padding:10px 0 10px 10px;text-align:left;vertical-align:middle;width:220px}#wysija-settings .form-table th.rolestable{padding:3px;text-align:center;vertical-align:middle;width:110px;word-wrap:break-word}#wysija-settings .form-table td.rolestable{padding:6px 0;text-align:center}#wysija-settings .form-table td.title{padding:10px 0 10px 10px;text-align:left;vertical-align:middle}#wysija-settings .form-table td.title p{margin:0}#wysija-settings .form-table td{vertical-align:top}#wysija-settings #bounce .intro{margin:10px 0 20px 10px}#wysija-settings #bounce #bounce-process-auto,#wysija-settings #bounce #bounce-connector{margin-left:0 !important}#wysija-settings #sendingmethod .methods{border-bottom:1px solid #000}#wysija-settings #sendingmethod .choice-sending-method-site{border-top:1px solid #cccccc}#wysija-settings #sendingmethod .choice-sending-method-site th,#wysija-settings #sendingmethod .choice-sending-method-site td{padding-top:18px}label.dkim{margin-right:20px}.cronleft,.cronright{float:left}.cronleft{width:20px;margin-right:10px}#cron_manual_linkname p{margin:0}.labelcheck{float:left;margin-right:15px}.checkbox_optin_label{margin:6px 6px 0 0;float:left}.checkbox_optin_value{float:left;width:500px}#smtp-rest-label{display:none;margin-left:10px}#wysija-settings #multisite #form-ms-config th{width:455px}#wysija-settings #multisite #ms-sendingmethod th{width:300px}#wysija-settings #multisite .intro{margin:0 0 0 10px}#wysija-settings #sendingmethod .methods input,#wysija-settings #multisite .methods input{margin:0 5px 0 0;float:left}#wysija-settings #sendingmethod .methods h3,#wysija-settings #multisite .methods p.title{float:left;margin:0 !important}#wysija-settings #multisite .choice-one-for-all{display:none}#wysija-settings a.view_all{font-style:italic}#wysija-settings .cronright label{display:block;margin-bottom:10px}#wysija-settings .cronright label span{margin-left:36px}#wysija-settings .capabilities_form{width:400px}span.icon{display:block;height:20px;width:20px;cursor:pointer}.geeky-option a,.geeky-option span{float:left}.show-more-geeky-options span{background:url(../img/controls/icons.png) no-repeat -200px 0}.show-more-geeky-options:hover span{background:url(../img/controls/icons.png) no-repeat -200px -20px}.hide-geeky-options span{background:url(../img/controls/icons.png) no-repeat -220px 0}.hide-geeky-options:hover span{background:url(../img/controls/icons.png) no-repeat -220px -20px}@-webkit-keyframes opacity{0%{opacity:1}100%{opacity:0}}@-moz-keyframes opacity{0%{opacity:1}100%{opacity:0}}.wysija-button-loading{text-align:center;margin:100px 0 0 0}.wysija-button-loading span{-webkit-animation-name:opacity;-webkit-animation-duration:1s;-webkit-animation-iteration-count:infinite;-moz-animation-name:opacity;-moz-animation-duration:1s;-moz-animation-iteration-count:infinite}.wysija-button-loading span:nth-child(2){-webkit-animation-delay:100ms;-moz-animation-delay:100ms}.wysija-button-loading span:nth-child(3){-webkit-animation-delay:300ms;-moz-animation-delay:300ms}.links-page{display:none;margin-left:10px}.new_form{margin:16px 0}.new_form a{font-size:16px !important}
trunk/css/admin-global.css ADDED
@@ -0,0 +1 @@
 
1
+ .clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}.clearfix{display:inline-table}* html .clearfix{height:1%}.clearfix{display:block}.hide{display:none}.wysija-version{margin:0 20px 0 165px;padding-bottom:45px}.wysija-footer h2{color:#21759B;cursor:pointer}.wysija-footer h2:hover{text-decoration:underline}.wysija-version{font-size:12px;color:#777777}.wysija-version .social-foot div{float:left;margin-right:10px}.wysija-version .version{float:left}.wysija-version .help{float:left;margin-left:20px}.wysija-version .social-foot .textsocial{margin-left:8px;margin-top:3px;padding-top:0}.wysija-version .social-foot{clear:both;display:inline-block}.wysija-version .version{float:left;margin-bottom:5px}#upperfoot{display:block;float:none}#submitexport label input[type="checkbox"]{margin-left:0px !important}.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}.clearfix{display:inline-table}* html .clearfix{height:1%}.clearfix{display:block}.wysija-footer,.wysija-version{margin:0 20px 0 165px;padding-bottom:45px}.wysija-footer h2{color:#21759B;cursor:pointer}.wysija-footer h2:hover{text-decoration:underline}.wysija-version{font-size:12px;color:#777777;height:65px;border-top:1px solid #DFDFDF}.wysija-version .social-foot div{float:left;margin-right:10px}.social-foot .fb{width:80px}.wysija-version .version{float:left}.wysija-version .help{float:left;margin-left:20px}.wysija-version .social-foot .textsocial{margin-left:8px;margin-top:3px;padding-top:0}.wysija-version .social-foot{clear:both;display:inline-block;float:left;margin-top:2px;padding:6px 13px}.wysija-version .social-foot .socials div{margin-left:20px}.wysija-version .social-foot .socials{margin-left:0px}.wysija-version .social-foot .socials .fb,.wysija-version .social-foot .socials .fb div{margin-left:0px}.wysija-version .version{float:left;margin-bottom:5px}.wysija-version .socials{padding-top:9px}#hidesocials{margin-top:2px;font-size:12px}.social-foot .gplus{width:70px}#upperfoot{display:block;float:none}#wysija-app .form-table td{vertical-align:top}#submitexport label input[type="checkbox"]{margin-left:0px !important}#wysija-app div.warning{margin:5px 0 15px;background-color:#FFFFE0;border-color:#E6DB55;border-radius:3px 3px 3px 3px;border-style:solid;border-width:1px;padding:10px}.submit-box{border-top:1px solid #dbdbdb;background-color:#FFFFFF;bottom:0;height:50px;left:0;margin:0;padding:0;position:fixed;text-align:right;width:100%}#loading-icon{width:20px;height:20px;position:absolute;left:16px;top:16px}.loading #loading-icon{background:url(../img/wpspin_light.gif) no-repeat 0 0 #fff}.counting #loading-icon{background:url(../img/controls/icons.png) no-repeat -140px -20px #fff}.submit-box #loading-message{font-family:"Trebuchet MS";font-size:14px;left:39px;position:absolute;top:17px}.submit-box #insert-selection,.submit-box #back-selection{margin:10px 10px 0 0}.submit-box #back-selection{display:none}#icon-stats{background:url("../img/stats-icon.png") no-repeat scroll 0 0 transparent}
trunk/css/admin-premium.css ADDED
@@ -0,0 +1 @@
 
1
+ #mainmenu .premium{background:url(../img/ui-bg_glass_premium_1x400.png) repeat-x scroll 50% 50% #e6e6e6;border:1px solid #a9abc3}#mainmenu .premium:hover{background:url(../img/ui-bg_glass_premium_hover_1x400.png) repeat-x scroll 50% 50% #e6e6e6;border:1px solid #9c9eb2}#mainmenu .premium a{font-weight:700;color:#5d5e76}#mainmenu .premium a:hover{color:#4b4d69}#mainmenu .ui-state-active{background:white !important;border:1px solid #d8d9e6}.mpoet-page h2{color:#4b4d69;font-size:1.8em;font-weight:200;line-height:1.2em;margin:0}.wysija-premium-wrapper{margin:0 0 20px 0}.wysija-premium-actions{position:fixed;width:1028px;bottom:0;background-color:#eee;border-top:1px solid #ccc;border-left:1px solid #ccc;border-right:1px solid #ccc;-webkit-border-top-left-radius:7px;-webkit-border-top-right-radius:7px;-moz-border-radius-topleft:7px;-moz-border-radius-topright:7px;border-top-left-radius:7px;border-top-right-radius:7px;z-index:999;padding:10px 10px 0}.wysija-premium-actions .licence{margin-right:15px}.wysija-premium-actions p{margin:0px 0px 10px 0;text-align:center}.wysija-premium-actions span.conditions{font-size:12px;margin-right:15px}.wysija-premium-actions .button-primary.wysija-premium-activate{float:none}.wysija-premium-actions-kim{position:fixed;width:1066px;bottom:0;background-color:#eee;border-top:1px solid #ccc;border-left:1px solid #ccc;border-right:1px solid #ccc;z-index:999;margin-left:-30px;padding:10px 10px;text-align:center}.mpoet-page .feature-section.three-col>div{width:29%;float:left;padding-right:30px;padding-left:0}.mpoet-page .three-col img{margin:0.5em 0;max-width:100%}a.wysija-premium-purchase{background-color:#FFB30D !important;background:-webkit-gradient(linear, left top, left bottom, from(#fecb19), to(#ff9c00)) !important;background:-webkit-linear-gradient(#fecb19, #ff9c00) !important;background:-moz-linear-gradient(center top, #fecb19 0%, #ff9c00 100%) !important;background:-moz-gradient(center top, #fecb19 0%, #ff9c00 100%) !important;border:1px solid #ff9c00 !important;color:#ffffff;font-family:"Amaranth", Arial, sans-serif;font-style:italic;font-size:15px !important;font-weight:normal;letter-spacing:1px;text-decoration:none;text-shadow:0 1px 0 #434343;padding:10px 30px;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px;box-shadow:none !important;text-shadow:0px 2px 1px rgba(0,0,0,0.3) !important;display:inline-block;text-align:center;width:auto}a.wysija-premium-purchase:hover{box-shadow:none !important}a.wysija-premium-purchase:hover,a.wysija-premium-purchase:active{text-decoration:none !important;background:#ffd547;background:-webkit-gradient(linear, left top, left bottom, from(#ffd648), to(#ffbe38));background:-webkit-linear-gradient(#ffd648, #ffbe38);background:-moz-linear-gradient(center top, #ffd648 20%, #ffbe38 100%);background:-moz-gradient(center top, #ffd648 20%, #ffbe38 100%)}a.wysija-premium-purchase,a.wysija-premium-activate{margin:10px 0}.mpoet-page .bullet-hold{width:600px;margin:15px 30px 15px 5px}.mpoet-page div.description h3{margin:5px 0 4px 0;font-family:"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",sans-serif;font-size:20px;font-weight:normal;color:black}.mpoet-page div.description p{margin:0}#prices_table{margin-top:55px}#prices_table .one-third{display:block;float:left;width:284px}#prices_table #prices_names{height:63px}#prices_table #prices_names .one-third{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;background:none repeat-x scroll left top transparent;border-color:#414141 -moz-use-text-color #414141 #414141;border-image:none;border-style:solid none solid solid;border-width:1px 0 1px 1px;height:61px;text-align:center}#prices_table #prices_names{display:block}#prices_table #prices_names h3{color:#FFF !important;line-height:1em !important}#prices_table #prices_names .blogger{background-color:#0074A2}#prices_table #prices_names .freelance{background-color:#026187}#prices_table #prices_names .agency{background-color:#014661;border-right:1px solid #414141}#prices_table #prices_cost{height:177px}#prices_table #prices_cost p{margin:0}#prices_table #prices_cost .one-third{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;border-color:-moz-use-text-color -moz-use-text-color #849A97 #849A97;border-image:none;border-style:none none solid solid;border-width:0 0 1px 1px;font-family:'Amaranth',Arial,sans-serif;height:176px}#prices_table #prices_cost .agency{border-right:1px solid #849A97}#prices_table #prices_cost span{display:block}#prices_table #prices_cost .dollars{font-size:80px;height:80px;line-height:normal;padding:20px 55px 0;text-align:center}#prices_table #prices_cost .per_year{font-size:18px;padding:0 60px;text-align:right}#prices_table #prices_cost .blogger .dollars{padding:20px 75px 0}#prices_table #prices_cost .blogger .per_year{padding:0 80px}#prices_table #prices_description{height:62px}#prices_table #prices_description .one-third{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;border-color:-moz-use-text-color -moz-use-text-color #849A97 #849A97;border-image:none;border-style:none none solid solid;border-width:0 0 1px 1px;font-size:22px;height:61px}#prices_table #prices_description .agency{border-right:1px solid #849A97}#prices_table #prices_description .agency p{display:block;margin:-15px 62px 0 0;text-align:right;font-size:.5em}#prices_table #prices_description span{display:block;padding:17px 0;text-align:center}#prices_table #prices_content{height:158px}#prices_table #prices_content .prices_content{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;border-color:-moz-use-text-color #849A97 #849A97;border-image:none;border-right:1px solid #849A97;border-style:none solid solid;border-width:0 1px 1px;color:#414141;font-size:17px;padding:16px 0}#prices_table #prices_content .prices_content span{display:block;padding:2px 0;text-align:center}a.buy-button{background:none repeat scroll 0 0 #2EA2CC;border-color:#0074A2;box-shadow:0 1px 0 rgba(120,200,230,0.5) inset,0 1px 0 rgba(0,0,0,0.15);color:#FFFFFF;-moz-box-sizing:border-box;border-radius:3px;border-style:solid;border-width:1px;cursor:pointer;display:inline-block;font-size:20px;margin-top:20px;margin-bottom:60px;padding:7px 10px 7px;text-decoration:none;white-space:nowrap}a.buy-button:hover{color:#ecf3fe}.mpoet-page h1{font-size:34px}#wysija-app .mpoet-page h2{font-size:25px}.mpoet-page h1,.mpoet-page h2,.mpoet-page h3,.mpoet-page h4{color:#626262;font-weight:bold}.mpoet-page h3{margin-top:5px;line-height:24px}.mpoet-page .three-col .argument-cta{display:table;margin-top:5px}#premium-content-b .pick-licence{margin-bottom:15px}.mpoet-page hr{margin-bottom:20px}#premium-content-b .price{font-weight:bold}#footer-upgrade,#footer-left,#wpfooter .alignright,.wysija-footer{display:none}.about-wrap div.updated,.about-wrap div.error{display:block !important}#wysija-app .about-wrap .feature-section{margin-top:20px}.about-wrap .three-col>div{margin-right:32px}
trunk/css/admin-statistics.css ADDED
@@ -0,0 +1 @@
 
1
+ .stats_date_filter{padding-top:10px}.statistic-title{clear:both;margin-top:5px}.cl{clear:both}#hook_stats .container{clear:both;padding-top:1px;margin-top:20px}#stats-filter .reset{background:none;border:none;cursor:pointer}#stats-filter .reset:hover{text-decoration:underline}.container-top-domains th.rates{text-align:center}.container-top-domains td{word-wrap:normal}.custom_date{margin-right:10px}.spinner{float:left !important}.hook{margin-top:10px;clear:both}.container-top-links .link_column{width:20%}.container-top-links .click_column{width:6%}.container .check-column{width:2.5em}.container-top-subscribers table th.subscriber{width:30%}.container-top-subscribers table th.clicks{width:7%}.container-top-subscribers table th.opens{width:7%}.container-top-subscribers table th.lists{width:41%}.container-top-subscribers table th.date{width:15%}.container-top-links a.newsletter{display:block;padding-top:5px}.container-top-subscribers .username .avatar{padding-left:0px;padding-right:0px}.container-top-subscribers .username .avatar img{margin-right:0px}.container-top-subscribers tbody .check-column{text-align:center}.container-top-newsletters th.newsletter{width:19%}.container-top-newsletters th.sent{width:8%}.container-top-newsletters th.opens{width:8%}.container-top-newsletters th.clicks{width:7%}.container-top-newsletters th.unsubscribes{width:11%}.container-top-newsletters th.rates{width:18%}.container-top-newsletters th.sent_at{width:12%}.container-top-newsletters th.lists{width:14%}.container-top-newsletters td a.stats{display:none}.container-top-newsletters td.newsletter:hover a.stats{display:block}.container-top-subscribers th.desc:hover span.sorting-indicator,.container-top-newsletters th.desc:hover span.sorting-indicator{background-position:-7px 0}.stats_feedback{font-weight:bold;margin-top:20px;clear:both}.tip{font-style:italic}.stats_subscriptions-container .tip{margin-left:70px}.container-top-newsletters th.desc:hover span.sorting-indicator:before,.container-top-subscribers th.desc:hover span.sorting-indicator:before,.container-top-newsletters th.asc span.sorting-indicator:before,.container-top-subscribers th.asc span.sorting-indicator:before{content:'\f140'}#hook_stats td.column-username table tr td{padding-top:0px}#hook_stats .widefat td ul{height:124px;overflow-y:auto}
trunk/css/admin-subscribers-addlist.css ADDED
@@ -0,0 +1 @@
 
1
+ #wysija-edit .form-table th{width:200px}
trunk/css/admin-subscribers-edit.css ADDED
@@ -0,0 +1 @@
 
1
+ #wysija-edit{padding-bottom:20px}#hook_subscriber_left{width:50%;float:left}#hook_subscriber_right{width:50%;float:left}.hook-column .submit{text-align:center}#hook_subscriber_bottom{clear:both;padding-top:1px}.container{clear:both;margin-top:30px}.form-table th label{float:right;white-space:nowrap}.labelcheck{float:left;margin-right:15px}#wysija-edit input[type="checkbox"]{margin-right:6px;vertical-align:baseline}#wysija-edit .form-table th{width:60px}.container-stats-subscribers_std table th.newsletter{width:60%}.container-stats-subscribers_std table th.link{width:20%}.container-stats-subscribers_std table th.click{width:5%}.container-stats-subscribers_std .widefat .check-column{width:2.7em}.container-stats-subscribers_std .widefat th.date{width:15%}
trunk/css/admin-subscribers-export.css ADDED
@@ -0,0 +1 @@
 
1
+ #wysija-app table td label{margin-right:15px}#wysija-app table td input[type="radio"]{margin-right:5px}
trunk/css/admin-subscribers-exportlist.css ADDED
@@ -0,0 +1 @@
 
1
+ #wysija-app table td label{margin-right:15px}#wysija-app table td input[type="radio"]{margin-right:5px}
trunk/css/admin-subscribers-import.css ADDED
@@ -0,0 +1 @@
 
1
+ .empty{color:#888}
trunk/css/admin-subscribers-importmatch.css ADDED
@@ -0,0 +1 @@
 
1
+ #wysija-edit .widefat td{min-width:100px}#wysija-edit .widefat{width:auto}#blocknewlist{width:175px}.import-new-field{display:none;margin-top:4px}.import-new-field label{font-size:12px}.widefat th .import-new-field input{margin:2px 5px 0 4px}.widefat thead{vertical-align:top}#first-row{padding-top:14px}.converted-field-to-date{display:none;margin-left:5px;color:#0e90d2}.converted-field-error{display:none;margin-left:5px;color:#b10000;font-weight:bold}
trunk/css/admin-subscribers-lists.css ADDED
File without changes
trunk/css/admin-subscribers.css ADDED
@@ -0,0 +1 @@
 
1
+ tr.submit_row>td{padding-left:0}.list .check-column{width:10px}#wysija-app .list .column-date{width:70px}#wysija-app .list .column-list-names{width:100px}
trunk/css/admin-widget.css ADDED
@@ -0,0 +1 @@
 
1
+ .wysija-widget-form .lists-block input[type="checkbox"],.wysija-widget-form input[type="radio"]{margin:0 4px 0 0}.wysija-widget-form .labelcheck label{margin:0 4px 0 0}.wysija-widget-form .lists-block{margin:0 3px 0 6px;clear:both;max-height:116px;overflow:auto;float:left;margin:0 10px 0 0}.wysija-widget-form .labelcheck{margin:0 0 5px 0;float:left;margin-left:5px}.wysija-widget-form .divblocks{margin:10px 0 10px 0}#wpfooter .wrap{display:block;margin:3px 0 3px 0 !important}#wpfooter .wrap .add-new-h2{text-decoration:none}
trunk/css/admin.css ADDED
@@ -0,0 +1 @@
 
1
+ .clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}.clearfix{display:inline-table}* html .clearfix{height:1%}.clearfix{display:block}#wysija-app .column-date{width:70px}#wysija-app .column-clic,#wysija-app .column-opened,#wysija-app .column-emails{width:80px}#wysija-app .column-list-names{width:120px}#wysija-app .menuslinks{margin:20px 0}#statscontainer{height:200px;width:400px}#wysistats1{width:400px}#wysistats1 h3{text-align:center}#wysistats2,#wysistats3{width:200px;padding:30px 0 0 20px}#wysistats3{height:200px;overflow:auto}#wysistats2 ul li,#wysistats .title{font-weight:bold;font-size:14px;margin-top:0}#wysistats3 ol li{font-style:italic;font-size:10px;color:#444}#wysistats3 ol li em{font-size:11px;font-weight:bold}th.sorted,th.sortable{cursor:pointer}div#wysija-app .xdetailed-updated li,div#wysija-app .xdetailed-errors li,div#wysija-app .updated li,div#wysija-app .error li{margin:6px 0}.xdetailed-errors,.xdetailed-updated{border-radius:3px 3px 3px 3px;border-style:solid;border-width:1px;margin:5px 15px 2px;padding:0 0.6em}.xdetailed-updated{background-color:#FFFFE0;border-color:#E6DB55;color:#000;display:none}.xdetailed-errors{background-color:#FFEBE8;border-color:#888888;color:#000;display:none}label input[type="checkbox"],label input[type="radio"]{margin:0 5px 0 15px}label:first-child input[type="checkbox"],label:first-child input[type="radio"]{margin-left:0}label.title{font-weight:bold;font-size:14px}.wrap .button-secondary2{background-color:#6697BF;font-family:sans-serif;font-size:12px;color:#FFFFFF;text-decoration:none;text-shadow:0 1px 0 #777777;box-shadow:1px 1px 0 #AAAAAA;margin-left:4px;padding:3px 8px;position:relative;top:-3px;border-radius:3px;-moz-border-radius:3px;-khtml-border-radius:3px;-webkit-border-radius:3px}.wrap .button-secondary2:hover,.wrap .wcurrent{background-color:#1C73B5}.wrap #theme-view .button-secondary2{top:2px}.dots{margin:0 4px}#wysija-pagination{text-align:center}.tablenav .tablenav-pages a,.tablenav-pages span.current{margin:0 2px}.total-pages{padding:0px 3px}input.searchbox{width:225px}.wysija-premium img{display:none}#TB_load,#TB_window,#TB_overlay,.ui-dialog{z-index:100000 !important}.ui-widget-overlay{z-index:9998 !important;background-image:none !important}p.label{font-size:13px}.wysija_popup_content{padding:10px 20px 0 20px}.wysija_popup_content h3{margin:0 0 20px 0}a.linkignore,a.mp_negative{color:#BC0B0B}a.linkignore:hover,a.submitsynch:hover{color:#FF0000}a.submitsynch{color:#52aa05}body{min-width:0 !important}.warning-msg{background-color:#FFFFE0;border-color:#E6DB55}.warning-msg{border-radius:3px 3px 3px 3px;border-style:solid;border-width:1px;margin:5px 15px 2px;padding:0 0.6em}.warning-msg ul{margin:0}span.warning-msg{padding:7px}.about-wrap h3{padding-top:0px}.about-text{margin-bottom:1em;margin-top:0;min-height:20px}.wysija-unsubscribed-on{color:#bbb}.clear_select_all,.force_to_select_all_link{text-align:center}.batch-select{background-color:#E0E0E0;color:#555555;border-bottom:1px solid #e5e5e5}.clear_select_all a:hover,.force_to_select_all_link a:hover{text-decoration:underline;cursor:pointer !important}#wysija-app .notice-msg{background-color:#FFFFE0;border-color:#E6DB55}#wysija-app .error-msg{background-color:#FFEBE8;border-color:#CC0000}#wysija-app .wysija-msg .notice-msg,#wysija-app .wysija-msg .error-msg{border-radius:3px 3px 3px 3px;border-style:solid;border-width:1px;margin:5px 0 15px;padding:0 0.6em}.mpoet-page .changelog .review-follow-kitten{overflow:visible}
trunk/css/adminPopup.css ADDED
@@ -0,0 +1 @@
 
1
+ html{overflow:hidden;overflow-y:auto;height:auto !important}html.wp-toolbar{padding:0 !important}#wpadminbar{display:none}body{-webkit-backface-visibility:hidden}.popup_content{margin:10px 10px 0 10px}.popup_content.addlink{width:300px}.popup_content.articles{width:700px}.popup_content.dividers{width:620px}.popup_content.autopost{width:700px;min-height:380px}.popup_content.themes{width:800px}.popup_content.bookmarks{width:620px}.popup_content.media-browse,.popup_content.media-wp-browse,.popup_content.media-wp-upload{width:715px}.popup_content.form_widget_settings{width:405px}.popup_content.widget_text,.popup_content.widget_html{width:450px}.popup_content.widget_list{width:450px}p.align-right{text-align:right;margin-bottom:0 !important}div.updated,div.error{margin:10px !important}.popup_content.inline_form label{line-height:2em;font-weight:bold}.popup_content.inline_form p input,.popup_content.inline_form p select,.popup_content.inline_form p .group{float:left;width:200px}.submit_button{text-align:right;margin:20px 10px 20px 0}.popup_content.inline_form .submit_button{margin:20px 4px 0 0}.popup_content.inline_form p input[type="submit"],.popup_content.inline_form .group label,.popup_content.inline_form .group input,.popup_content.inline_form .group select{float:none;clear:none;width:auto}.popup_content.inline_form label.radio,.popup_content.inline_form .group label{font-weight:normal}.popup_content.inline_form input[type="radio"],.popup_content.inline_form input[type="checkbox"]{width:16px;height:16px;margin:0 3px 0 0;padding:0}.popup_content.inline_form input[type="radio"]{-webkit-appearance:radio}.popup_content.inline_form input[type="radio"]:checked:before,.popup_content.inline_form input[type="checkbox"]:checked:before{background:none;content:''}.popup_content.inline_form input[type="checkbox"]{-webkit-appearance:checkbox}.popup_content.inline_form textarea,.popup_content.inline_form input[type="text"],.popup_content.inline_form input[type="password"],.popup_content.inline_form input[type="email"],.popup_content.inline_form input[type="number"],.popup_content.inline_form input[type="search"],.popup_content.inline_form input[type="tel"],.popup_content.inline_form input[type="url"],.popup_content.inline_form select{font-size:13px;line-height:15px;padding:3px 5px}
trunk/css/index.html ADDED
File without changes
trunk/css/jquery/ui/themes/base/images/animated-overlay.gif ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_flat_75_ffffff_40x100.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-icons_222222_256x240.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-icons_2e83ff_256x240.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-icons_454545_256x240.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-icons_888888_256x240.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/images/ui-icons_cd0a0a_256x240.png ADDED
Binary file
trunk/css/jquery/ui/themes/base/jquery.ui.core.min.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery UI - v1.10.3 - 2013-05-03
2
+ * http://jqueryui.com
3
+ * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
4
+
5
+ .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}
trunk/css/jquery/ui/themes/base/jquery.ui.datepicker.min.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery UI - v1.10.3 - 2013-05-03
2
+ * http://jqueryui.com
3
+ * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
4
+
5
+ .ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}
trunk/css/rtl.css ADDED
@@ -0,0 +1 @@
 
1
+ body{direction:rtl;unicode-bidi:embed}input#url{direction:ltr}.xdetailed-errors,.xdetailed-updated{margin:2px 15px 5px}.wysija-footer,.wysija-version{margin:0 165px 0 20px}label input[type="checkbox"],label input[type="radio"]{margin:0 15px 0 5px}input.searchsub.button{float:none}a.button-primary.install{float:none}#review-follow div{float:right}.about-wrap .feature-section.three-col div{float:right;padding-left:30px;padding-right:0}.mpoet-update-subscribe-left,.mpoet-update-subscribe-right{float:right}#wysija-badge{left:0;right:auto}.dividers ul{overflow-x:auto;overflow-y:auto}.submit-box{text-align:left}.submit-box #insert-selection,.submit-box #back-selection{margin:10px 0 0 10px}#toggle-advanced{left:10px;top:0;right:auto}.articles #basic .search-box{float:left}.articles #basic .filters-box{float:right}.articles #search-submit{margin:0 0 0 14px}.articles .cpt-type{left:0;right:auto;border-right:1px solid #ccc;border-left:0 none}#advanced div.block{padding:0.8em 1em 0.8em 0}#advanced label{float:right}#image_width_slider{float:right}#slider_info{float:right}#advanced label.radio{float:right;margin:0 0 0 9px}#advanced label.radio input{margin:0 0 0 2px}#advanced div.group{float:right}#results .thumbnail{float:right;margin:0 0 0 10px}#results li .checkbox{cursor:pointer;margin:0 11px 0 0}#results li .checkbox_container{float:right}#results li label{float:right}#loading-icon{left:auto;right:16px;top:16px}.submit-box #loading-message{left:auto;right:39px}.wysija-footer,.wysija-version{margin:0 165px 0 20px}.wysija-version .social-foot{float:right}body.rtl #wysija_wrapper{right:0 !important}#wysija_popup_title h3{float:right;margin-right:10px}#wysija_popup_close{float:left;margin-left:10px}#wysija_toolbar{right:657px}.wj_images li,.wj_themes li{float:right}.wj_images #wj_images_preview,.wj_themes #wj_themes_preview{left:295px;right:auto}.wj_content a.wysija_item,.wysija_widget{padding:0 10px 0 0}.wj_styles form label{margin:0 3px 0 0}.wj_styles #aUnderlineInput{margin-right:10px !important}.wysija_item_settings{left:15px;right:auto}#wysija_toggle_images{left:5px;right:auto}#review-follow .review-left.large{float:right}#review-follow .review-left{background-position:100% 0}#review-follow div{float:right}#review-follow .review-left .description{margin-right:146px;margin-left:0px}#review-follow .review-right{background-image:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/update_page/arrow_middle-rtl.jpg");background-position:100% 0}#review-follow .follow-right{background-image:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/update_page/arrow_right-rtl.jpg");background-position:100% 0}#review-follow .follow-right38{background-image:url("http://s-plugins.wordpress.org/wysija-newsletters/assets/update_page/arrow-right-38-rtl.jpg");background-position:100% 0}#wysija-settings input[type="checkbox"],#wysija-settings input[type="radio"],#wysija-settings label input[type="checkbox"]{margin-left:6px}label:first-child input[type="checkbox"],label:first-child input[type="radio"],label input[type="checkbox"],label input[type="radio"]{margin:0 15px 0 5px}.linknamecboxes,.labelcheck,.geeky-option a,.geeky-option span{float:right}.checkbox_optin_label{margin:6px 0 0 6px;float:right}.checkbox_optin_value{float:right}#wysija-settings .form-table th.rolestitle{text-align:right}.cronleft{float:right;margin:0 0 0 10px}.popup_content{margin:10px 10px 0 10px}#wysija-settings #sendingmethod .methods h3,#wysija-settings #multisite .methods p.title{float:right}#wysija-settings #sendingmethod .methods input,#wysija-settings #multisite .methods input{float:right;margin:0 0 0 5px}h2.title span,h2.title form{float:right;margin-left:5px;margin-right:0px}#wysija_form_toolbar{right:679px !important;left:auto !important}#wysija_form_toolbar a.wysija_form_item,.wysija_form_widget{padding-right:7px}.form_widget_settings p label{float:right;clear:right;width:200px}.form_widget_settings .selection .is_selected{float:right;margin:3px 6px 0 0 !important}.form_widget_settings .selection label{float:right;margin:0 5px 0 0}.form_widget_settings .selection .handle,.form_widget_settings .selection .remove{float:left;margin:3px 0 0 3px}.popup_content.inline_form p input,.popup_content.inline_form p select,.popup_content.inline_form p .group{float:right}.submit_button{margin:20px 0 20px 10px;text-align:left}.popup_content.inline_form .submit_button{margin:20px 0 0 4px}.popup_content.inline_form label.radio,.popup_content.inline_form .group label{float:right}.popup_content.inline_form.autopost label,.popup_content.inline_form.autopost div.group{float:right}.popup_content.inline_form input[type="radio"],.popup_content.inline_form input[type="checkbox"]{margin:0 0 0 3px}.wysija_form_item_settings{left:35px;right:auto !important}.wysija_form_item_delete{left:15px;right:auto !important}.bookmarks .networks label,.bookmarks .networks input{float:right}#results li .checkbox{margin-left:10px}.add span{float:right}.themes #wj_paginator{float:left;margin-right:0;margin-left:10px}
trunk/css/select2/select2.css ADDED
@@ -0,0 +1,615 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013
3
+ */
4
+ .select2-container {
5
+ margin: 0;
6
+ position: relative;
7
+ display: inline-block;
8
+ /* inline-block for ie7 */
9
+ zoom: 1;
10
+ *display: inline;
11
+ vertical-align: middle;
12
+ }
13
+
14
+ .select2-container,
15
+ .select2-drop,
16
+ .select2-search,
17
+ .select2-search input {
18
+ /*
19
+ Force border-box so that % widths fit the parent
20
+ container without overlap because of margin/padding.
21
+
22
+ More Info : http://www.quirksmode.org/css/box.html
23
+ */
24
+ -webkit-box-sizing: border-box; /* webkit */
25
+ -moz-box-sizing: border-box; /* firefox */
26
+ box-sizing: border-box; /* css3 */
27
+ }
28
+
29
+ .select2-container .select2-choice {
30
+ display: block;
31
+ height: 26px;
32
+ padding: 0 0 0 8px;
33
+ overflow: hidden;
34
+ position: relative;
35
+
36
+ border: 1px solid #aaa;
37
+ white-space: nowrap;
38
+ line-height: 26px;
39
+ color: #444;
40
+ text-decoration: none;
41
+
42
+ border-radius: 4px;
43
+
44
+ background-clip: padding-box;
45
+
46
+ -webkit-touch-callout: none;
47
+ -webkit-user-select: none;
48
+ -moz-user-select: none;
49
+ -ms-user-select: none;
50
+ user-select: none;
51
+
52
+ background-color: #fff;
53
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff));
54
+ background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%);
55
+ background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%);
56
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);
57
+ background-image: linear-gradient(top, #fff 0%, #eee 50%);
58
+ }
59
+
60
+ .select2-container.select2-drop-above .select2-choice {
61
+ border-bottom-color: #aaa;
62
+
63
+ border-radius: 0 0 4px 4px;
64
+
65
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff));
66
+ background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%);
67
+ background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%);
68
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
69
+ background-image: linear-gradient(top, #eee 0%, #fff 90%);
70
+ }
71
+
72
+ .select2-container.select2-allowclear .select2-choice .select2-chosen {
73
+ margin-right: 42px;
74
+ }
75
+
76
+ .select2-container .select2-choice > .select2-chosen {
77
+ margin-right: 26px;
78
+ display: block;
79
+ overflow: hidden;
80
+
81
+ white-space: nowrap;
82
+
83
+ text-overflow: ellipsis;
84
+ }
85
+
86
+ .select2-container .select2-choice abbr {
87
+ display: none;
88
+ width: 12px;
89
+ height: 12px;
90
+ position: absolute;
91
+ right: 24px;
92
+ top: 8px;
93
+
94
+ font-size: 1px;
95
+ text-decoration: none;
96
+
97
+ border: 0;
98
+ background: url('../../img/select2/select2.png') right top no-repeat;
99
+ cursor: pointer;
100
+ outline: 0;
101
+ }
102
+
103
+ .select2-container.select2-allowclear .select2-choice abbr {
104
+ display: inline-block;
105
+ }
106
+
107
+ .select2-container .select2-choice abbr:hover {
108
+ background-position: right -11px;
109
+ cursor: pointer;
110
+ }
111
+
112
+ .select2-drop-mask {
113
+ border: 0;
114
+ margin: 0;
115
+ padding: 0;
116
+ position: fixed;
117
+ left: 0;
118
+ top: 0;
119
+ min-height: 100%;
120
+ min-width: 100%;
121
+ height: auto;
122
+ width: auto;
123
+ opacity: 0;
124
+ z-index: 9998;
125
+ /* styles required for IE to work */
126
+ background-color: #fff;
127
+ filter: alpha(opacity=0);
128
+ }
129
+
130
+ .select2-drop {
131
+ width: 100%;
132
+ margin-top: -1px;
133
+ position: absolute;
134
+ z-index: 9999;
135
+ top: 100%;
136
+
137
+ background: #fff;
138
+ color: #000;
139
+ border: 1px solid #aaa;
140
+ border-top: 0;
141
+
142
+ border-radius: 0 0 4px 4px;
143
+
144
+ -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
145
+ box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
146
+ }
147
+
148
+ .select2-drop-auto-width {
149
+ border-top: 1px solid #aaa;
150
+ width: auto;
151
+ }
152
+
153
+ .select2-drop-auto-width .select2-search {
154
+ padding-top: 4px;
155
+ }
156
+
157
+ .select2-drop.select2-drop-above {
158
+ margin-top: 1px;
159
+ border-top: 1px solid #aaa;
160
+ border-bottom: 0;
161
+
162
+ border-radius: 4px 4px 0 0;
163
+
164
+ -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
165
+ box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
166
+ }
167
+
168
+ .select2-drop-active {
169
+ border: 1px solid #5897fb;
170
+ border-top: none;
171
+ }
172
+
173
+ .select2-drop.select2-drop-above.select2-drop-active {
174
+ border-top: 1px solid #5897fb;
175
+ }
176
+
177
+ .select2-container .select2-choice .select2-arrow {
178
+ display: inline-block;
179
+ width: 18px;
180
+ height: 100%;
181
+ position: absolute;
182
+ right: 0;
183
+ top: 0;
184
+
185
+ border-left: 1px solid #aaa;
186
+ border-radius: 0 4px 4px 0;
187
+
188
+ background-clip: padding-box;
189
+
190
+ background: #ccc;
191
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
192
+ background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
193
+ background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
194
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
195
+ background-image: linear-gradient(top, #ccc 0%, #eee 60%);
196
+ }
197
+
198
+ .select2-container .select2-choice .select2-arrow b {
199
+ display: block;
200
+ width: 100%;
201
+ height: 100%;
202
+ background: url('../../img/select2/select2.png') no-repeat 0 1px;
203
+ }
204
+
205
+ .select2-search {
206
+ display: inline-block;
207
+ width: 100%;
208
+ min-height: 26px;
209
+ margin: 0;
210
+ padding-left: 4px;
211
+ padding-right: 4px;
212
+
213
+ position: relative;
214
+ z-index: 10000;
215
+
216
+ white-space: nowrap;
217
+ }
218
+
219
+ .select2-search input {
220
+ width: 100%;
221
+ height: auto !important;
222
+ min-height: 26px;
223
+ padding: 4px 20px 4px 5px;
224
+ margin: 0;
225
+
226
+ outline: 0;
227
+ font-family: sans-serif;
228
+ font-size: 1em;
229
+
230
+ border: 1px solid #aaa;
231
+ border-radius: 0;
232
+
233
+ -webkit-box-shadow: none;
234
+ box-shadow: none;
235
+
236
+ background: #fff url('../../img/select2/select2.png') no-repeat 100% -22px;
237
+ background: url('../../img/select2/select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
238
+ background: url('../../img/select2/select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
239
+ background: url('../../img/select2/select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
240
+ background: url('../../img/select2/select2.png') no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%);
241
+ }
242
+
243
+ .select2-drop.select2-drop-above .select2-search input {
244
+ margin-top: 4px;
245
+ }
246
+
247
+ .select2-search input.select2-active {
248
+ background: #fff url('../../img/select2/select2-spinner.gif') no-repeat 100%;
249
+ background: url('../../img/select2/select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
250
+ background: url('../../img/select2/select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
251
+ background: url('../../img/select2/select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
252
+ background: url('../../img/select2/select2-spinner.gif') no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%);
253
+ }
254
+
255
+ .select2-container-active .select2-choice,
256
+ .select2-container-active .select2-choices {
257
+ border: 1px solid #5897fb;
258
+ outline: none;
259
+
260
+ -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
261
+ box-shadow: 0 0 5px rgba(0, 0, 0, .3);
262
+ }
263
+
264
+ .select2-dropdown-open .select2-choice {
265
+ border-bottom-color: transparent;
266
+ -webkit-box-shadow: 0 1px 0 #fff inset;
267
+ box-shadow: 0 1px 0 #fff inset;
268
+
269
+ border-bottom-left-radius: 0;
270
+ border-bottom-right-radius: 0;
271
+
272
+ background-color: #eee;
273
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee));
274
+ background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%);
275
+ background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%);
276
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
277
+ background-image: linear-gradient(top, #fff 0%, #eee 50%);
278
+ }
279
+
280
+ .select2-dropdown-open.select2-drop-above .select2-choice,
281
+ .select2-dropdown-open.select2-drop-above .select2-choices {
282
+ border: 1px solid #5897fb;
283
+ border-top-color: transparent;
284
+
285
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee));
286
+ background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%);
287
+ background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%);
288
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
289
+ background-image: linear-gradient(bottom, #fff 0%, #eee 50%);
290
+ }
291
+
292
+ .select2-dropdown-open .select2-choice .select2-arrow {
293
+ background: transparent;
294
+ border-left: none;
295
+ filter: none;
296
+ }
297
+ .select2-dropdown-open .select2-choice .select2-arrow b {
298
+ background-position: -18px 1px;
299
+ }
300
+
301
+ /* results */
302
+ .select2-results {
303
+ max-height: 200px;
304
+ padding: 0 0 0 4px;
305
+ margin: 4px 4px 4px 0;
306
+ position: relative;
307
+ overflow-x: hidden;
308
+ overflow-y: auto;
309
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
310
+ }
311
+
312
+ .select2-results ul.select2-result-sub {
313
+ margin: 0;
314
+ padding-left: 0;
315
+ }
316
+
317
+ .select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
318
+ .select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
319
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
320
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
321
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
322
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
323
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
324
+
325
+ .select2-results li {
326
+ list-style: none;
327
+ display: list-item;
328
+ background-image: none;
329
+ }
330
+
331
+ .select2-results li.select2-result-with-children > .select2-result-label {
332
+ font-weight: bold;
333
+ }
334
+
335
+ .select2-results .select2-result-label {
336
+ padding: 3px 7px 4px;
337
+ margin: 0;
338
+ cursor: pointer;
339
+
340
+ min-height: 1em;
341
+
342
+ -webkit-touch-callout: none;
343
+ -webkit-user-select: none;
344
+ -moz-user-select: none;
345
+ -ms-user-select: none;
346
+ user-select: none;
347
+ }
348
+
349
+ .select2-results .select2-highlighted {
350
+ background: #3875d7;
351
+ color: #fff;
352
+ }
353
+
354
+ .select2-results li em {
355
+ background: #feffde;
356
+ font-style: normal;
357
+ }
358
+
359
+ .select2-results .select2-highlighted em {
360
+ background: transparent;
361
+ }
362
+
363
+ .select2-results .select2-highlighted ul {
364
+ background: #fff;
365
+ color: #000;
366
+ }
367
+
368
+
369
+ .select2-results .select2-no-results,
370
+ .select2-results .select2-searching,
371
+ .select2-results .select2-selection-limit {
372
+ background: #f4f4f4;
373
+ display: list-item;
374
+ }
375
+
376
+ /*
377
+ disabled look for disabled choices in the results dropdown
378
+ */
379
+ .select2-results .select2-disabled.select2-highlighted {
380
+ color: #666;
381
+ background: #f4f4f4;
382
+ display: list-item;
383
+ cursor: default;
384
+ }
385
+ .select2-results .select2-disabled {
386
+ background: #f4f4f4;
387
+ display: list-item;
388
+ cursor: default;
389
+ }
390
+
391
+ .select2-results .select2-selected {
392
+ display: none;
393
+ }
394
+
395
+ .select2-more-results.select2-active {
396
+ background: #f4f4f4 url('../../img/select2/select2-spinner.gif') no-repeat 100%;
397
+ }
398
+
399
+ .select2-more-results {
400
+ background: #f4f4f4;
401
+ display: list-item;
402
+ }
403
+
404
+ /* disabled styles */
405
+
406
+ .select2-container.select2-container-disabled .select2-choice {
407
+ background-color: #f4f4f4;
408
+ background-image: none;
409
+ border: 1px solid #ddd;
410
+ cursor: default;
411
+ }
412
+
413
+ .select2-container.select2-container-disabled .select2-choice .select2-arrow {
414
+ background-color: #f4f4f4;
415
+ background-image: none;
416
+ border-left: 0;
417
+ }
418
+
419
+ .select2-container.select2-container-disabled .select2-choice abbr {
420
+ display: none;
421
+ }
422
+
423
+
424
+ /* multiselect */
425
+
426
+ .select2-container-multi .select2-choices {
427
+ height: auto !important;
428
+ height: 1%;
429
+ margin: 0;
430
+ padding: 0;
431
+ position: relative;
432
+
433
+ border: 1px solid #aaa;
434
+ cursor: text;
435
+ overflow: hidden;
436
+
437
+ background-color: #fff;
438
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
439
+ background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%);
440
+ background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%);
441
+ background-image: linear-gradient(top, #eee 1%, #fff 15%);
442
+ }
443
+
444
+ .select2-locked {
445
+ padding: 3px 5px 3px 5px !important;
446
+ }
447
+
448
+ .select2-container-multi .select2-choices {
449
+ min-height: 26px;
450
+ }
451
+
452
+ .select2-container-multi.select2-container-active .select2-choices {
453
+ border: 1px solid #5897fb;
454
+ outline: none;
455
+
456
+ -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
457
+ box-shadow: 0 0 5px rgba(0, 0, 0, .3);
458
+ }
459
+ .select2-container-multi .select2-choices li {
460
+ float: left;
461
+ list-style: none;
462
+ }
463
+ .select2-container-multi .select2-choices .select2-search-field {
464
+ margin: 0;
465
+ padding: 0;
466
+ white-space: nowrap;
467
+ }
468
+
469
+ .select2-container-multi .select2-choices .select2-search-field input {
470
+ padding: 5px;
471
+ margin: 1px 0;
472
+
473
+ font-family: sans-serif;
474
+ font-size: 100%;
475
+ color: #666;
476
+ outline: 0;
477
+ border: 0;
478
+ -webkit-box-shadow: none;
479
+ box-shadow: none;
480
+ background: transparent !important;
481
+ }
482
+
483
+ .select2-container-multi .select2-choices .select2-search-field input.select2-active {
484
+ background: #fff url('../../img/select2/select2-spinner.gif') no-repeat 100% !important;
485
+ }
486
+
487
+ .select2-default {
488
+ color: #999 !important;
489
+ }
490
+
491
+ .select2-container-multi .select2-choices .select2-search-choice {
492
+ padding: 3px 5px 3px 18px;
493
+ margin: 3px 0 3px 5px;
494
+ position: relative;
495
+
496
+ line-height: 13px;
497
+ color: #333;
498
+ cursor: default;
499
+ border: 1px solid #aaaaaa;
500
+
501
+ border-radius: 3px;
502
+
503
+ -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
504
+ box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
505
+
506
+ background-clip: padding-box;
507
+
508
+ -webkit-touch-callout: none;
509
+ -webkit-user-select: none;
510
+ -moz-user-select: none;
511
+ -ms-user-select: none;
512
+ user-select: none;
513
+
514
+ background-color: #e4e4e4;
515
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);
516
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
517
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
518
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
519
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
520
+ }
521
+ .select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
522
+ cursor: default;
523
+ }
524
+ .select2-container-multi .select2-choices .select2-search-choice-focus {
525
+ background: #d4d4d4;
526
+ }
527
+
528
+ .select2-search-choice-close {
529
+ display: block;
530
+ width: 12px;
531
+ height: 13px;
532
+ position: absolute;
533
+ right: 3px;
534
+ top: 4px;
535
+
536
+ font-size: 1px;
537
+ outline: none;
538
+ background: url('../../img/select2/select2.png') right top no-repeat;
539
+ }
540
+
541
+ .select2-container-multi .select2-search-choice-close {
542
+ left: 3px;
543
+ }
544
+
545
+ .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
546
+ background-position: right -11px;
547
+ }
548
+ .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
549
+ background-position: right -11px;
550
+ }
551
+
552
+ /* disabled styles */
553
+ .select2-container-multi.select2-container-disabled .select2-choices {
554
+ background-color: #f4f4f4;
555
+ background-image: none;
556
+ border: 1px solid #ddd;
557
+ cursor: default;
558
+ }
559
+
560
+ .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
561
+ padding: 3px 5px 3px 5px;
562
+ border: 1px solid #ddd;
563
+ background-image: none;
564
+ background-color: #f4f4f4;
565
+ }
566
+
567
+ .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none;
568
+ background: none;
569
+ }
570
+ /* end multiselect */
571
+
572
+
573
+ .select2-result-selectable .select2-match,
574
+ .select2-result-unselectable .select2-match {
575
+ text-decoration: underline;
576
+ }
577
+
578
+ .select2-offscreen, .select2-offscreen:focus {
579
+ clip: rect(0 0 0 0) !important;
580
+ width: 1px !important;
581
+ height: 1px !important;
582
+ border: 0 !important;
583
+ margin: 0 !important;
584
+ padding: 0 !important;
585
+ overflow: hidden !important;
586
+ position: absolute !important;
587
+ outline: 0 !important;
588
+ left: 0px !important;
589
+ top: 0px !important;
590
+ }
591
+
592
+ .select2-display-none {
593
+ display: none;
594
+ }
595
+
596
+ .select2-measure-scrollbar {
597
+ position: absolute;
598
+ top: -10000px;
599
+ left: -10000px;
600
+ width: 100px;
601
+ height: 100px;
602
+ overflow: scroll;
603
+ }
604
+ /* Retina-ize icons */
605
+
606
+ @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
607
+ .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b {
608
+ background-image: url('../../img/select2/select2x2.png') !important;
609
+ background-repeat: no-repeat !important;
610
+ background-size: 60px 40px !important;
611
+ }
612
+ .select2-search input {
613
+ background-position: 100% -21px !important;
614
+ }
615
+ }
trunk/css/smoothness/images/calendar.gif ADDED
Binary file
trunk/css/smoothness/images/index.html ADDED
File without changes
trunk/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
trunk/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png ADDED
Binary file
trunk/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png ADDED
Binary file
trunk/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png ADDED
Binary file
trunk/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png ADDED
Binary file
trunk/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png ADDED
Binary file
trunk/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png ADDED
Binary file
trunk/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png ADDED
Binary file
trunk/css/smoothness/images/ui-icons_222222_256x240.png ADDED
Binary file
trunk/css/smoothness/images/ui-icons_2e83ff_256x240.png ADDED
Binary file
trunk/css/smoothness/images/ui-icons_454545_256x240.png ADDED
Binary file
trunk/css/smoothness/images/ui-icons_888888_256x240.png ADDED
Binary file
trunk/css/smoothness/images/ui-icons_cd0a0a_256x240.png ADDED
Binary file
trunk/css/smoothness/index.html ADDED
File without changes
trunk/css/smoothness/jquery-ui-1.8.20.custom.css ADDED
@@ -0,0 +1,565 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery UI CSS Framework 1.8.20
3
+ *
4
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI/Theming/API
9
+ */
10
+
11
+ /* Layout helpers
12
+ ----------------------------------*/
13
+ .ui-helper-hidden { display: none; }
14
+ .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
15
+ .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
16
+ .ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
17
+ .ui-helper-clearfix:after { clear: both; }
18
+ .ui-helper-clearfix { zoom: 1; }
19
+ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
20
+
21
+
22
+ /* Interaction Cues
23
+ ----------------------------------*/
24
+ .ui-state-disabled { cursor: default !important; }
25
+
26
+
27
+ /* Icons
28
+ ----------------------------------*/
29
+
30
+ /* states and images */
31
+ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
32
+
33
+
34
+ /* Misc visuals
35
+ ----------------------------------*/
36
+
37
+ /* Overlays */
38
+ .ui-widget-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; }
39
+
40
+
41
+ /*!
42
+ * jQuery UI CSS Framework 1.8.20
43
+ *
44
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
45
+ * Dual licensed under the MIT or GPL Version 2 licenses.
46
+ * http://jquery.org/license
47
+ *
48
+ * http://docs.jquery.com/UI/Theming/API
49
+ *
50
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
51
+ */
52
+
53
+
54
+ /* Component containers
55
+ ----------------------------------*/
56
+ .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
57
+ .ui-widget .ui-widget { font-size: 1em; }
58
+ .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
59
+ .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
60
+ .ui-widget-content a { color: #222222; }
61
+ .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
62
+ .ui-widget-header a { color: #222222; }
63
+
64
+ /* Interaction states
65
+ ----------------------------------*/
66
+ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
67
+ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
68
+ .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
69
+ .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
70
+ .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
71
+ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
72
+ .ui-widget :active { outline: none; }
73
+
74
+ /* Interaction Cues
75
+ ----------------------------------*/
76
+ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
77
+ .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
78
+ .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
79
+ .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
80
+ .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
81
+ .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
82
+ .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
83
+ .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
84
+
85
+ /* Icons
86
+ ----------------------------------*/
87
+
88
+ /* states and images */
89
+ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
90
+ .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
91
+ .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
92
+ .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
93
+ .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
94
+ .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
95
+ .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
96
+ .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
97
+
98
+ /* positioning */
99
+ .ui-icon-carat-1-n { background-position: 0 0; }
100
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
101
+ .ui-icon-carat-1-e { background-position: -32px 0; }
102
+ .ui-icon-carat-1-se { background-position: -48px 0; }
103
+ .ui-icon-carat-1-s { background-position: -64px 0; }
104
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
105
+ .ui-icon-carat-1-w { background-position: -96px 0; }
106
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
107
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
108
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
109
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
110
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
111
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
112
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
113
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
114
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
115
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
116
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
117
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
118
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
119
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
120
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
121
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
122
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
123
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
124
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
125
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
126
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
127
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
128
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
129
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
130
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
131
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
132
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
133
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
134
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
135
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
136
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
137
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
138
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
139
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
140
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
141
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
142
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
143
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
144
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
145
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
146
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
147
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
148
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
149
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
150
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
151
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
152
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
153
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
154
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
155
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
156
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
157
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
158
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
159
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
160
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
161
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
162
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
163
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
164
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
165
+ .ui-icon-extlink { background-position: -32px -80px; }
166
+ .ui-icon-newwin { background-position: -48px -80px; }
167
+ .ui-icon-refresh { background-position: -64px -80px; }
168
+ .ui-icon-shuffle { background-position: -80px -80px; }
169
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
170
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
171
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
172
+ .ui-icon-folder-open { background-position: -16px -96px; }
173
+ .ui-icon-document { background-position: -32px -96px; }
174
+ .ui-icon-document-b { background-position: -48px -96px; }
175
+ .ui-icon-note { background-position: -64px -96px; }
176
+ .ui-icon-mail-closed { background-position: -80px -96px; }
177
+ .ui-icon-mail-open { background-position: -96px -96px; }
178
+ .ui-icon-suitcase { background-position: -112px -96px; }
179
+ .ui-icon-comment { background-position: -128px -96px; }
180
+ .ui-icon-person { background-position: -144px -96px; }
181
+ .ui-icon-print { background-position: -160px -96px; }
182
+ .ui-icon-trash { background-position: -176px -96px; }
183
+ .ui-icon-locked { background-position: -192px -96px; }
184
+ .ui-icon-unlocked { background-position: -208px -96px; }
185
+ .ui-icon-bookmark { background-position: -224px -96px; }
186
+ .ui-icon-tag { background-position: -240px -96px; }
187
+ .ui-icon-home { background-position: 0 -112px; }
188
+ .ui-icon-flag { background-position: -16px -112px; }
189
+ .ui-icon-calendar { background-position: -32px -112px; }
190
+ .ui-icon-cart { background-position: -48px -112px; }
191
+ .ui-icon-pencil { background-position: -64px -112px; }
192
+ .ui-icon-clock { background-position: -80px -112px; }
193
+ .ui-icon-disk { background-position: -96px -112px; }
194
+ .ui-icon-calculator { background-position: -112px -112px; }
195
+ .ui-icon-zoomin { background-position: -128px -112px; }
196
+ .ui-icon-zoomout { background-position: -144px -112px; }
197
+ .ui-icon-search { background-position: -160px -112px; }
198
+ .ui-icon-wrench { background-position: -176px -112px; }
199
+ .ui-icon-gear { background-position: -192px -112px; }
200
+ .ui-icon-heart { background-position: -208px -112px; }
201
+ .ui-icon-star { background-position: -224px -112px; }
202
+ .ui-icon-link { background-position: -240px -112px; }
203
+ .ui-icon-cancel { background-position: 0 -128px; }
204
+ .ui-icon-plus { background-position: -16px -128px; }
205
+ .ui-icon-plusthick { background-position: -32px -128px; }
206
+ .ui-icon-minus { background-position: -48px -128px; }
207
+ .ui-icon-minusthick { background-position: -64px -128px; }
208
+ .ui-icon-close { background-position: -80px -128px; }
209
+ .ui-icon-closethick { background-position: -96px -128px; }
210
+ .ui-icon-key { background-position: -112px -128px; }
211
+ .ui-icon-lightbulb { background-position: -128px -128px; }
212
+ .ui-icon-scissors { background-position: -144px -128px; }
213
+ .ui-icon-clipboard { background-position: -160px -128px; }
214
+ .ui-icon-copy { background-position: -176px -128px; }
215
+ .ui-icon-contact { background-position: -192px -128px; }
216
+ .ui-icon-image { background-position: -208px -128px; }
217
+ .ui-icon-video { background-position: -224px -128px; }
218
+ .ui-icon-script { background-position: -240px -128px; }
219
+ .ui-icon-alert { background-position: 0 -144px; }
220
+ .ui-icon-info { background-position: -16px -144px; }
221
+ .ui-icon-notice { background-position: -32px -144px; }
222
+ .ui-icon-help { background-position: -48px -144px; }
223
+ .ui-icon-check { background-position: -64px -144px; }
224
+ .ui-icon-bullet { background-position: -80px -144px; }
225
+ .ui-icon-radio-off { background-position: -96px -144px; }
226
+ .ui-icon-radio-on { background-position: -112px -144px; }
227
+ .ui-icon-pin-w { background-position: -128px -144px; }
228
+ .ui-icon-pin-s { background-position: -144px -144px; }
229
+ .ui-icon-play { background-position: 0 -160px; }
230
+ .ui-icon-pause { background-position: -16px -160px; }
231
+ .ui-icon-seek-next { background-position: -32px -160px; }
232
+ .ui-icon-seek-prev { background-position: -48px -160px; }
233
+ .ui-icon-seek-end { background-position: -64px -160px; }
234
+ .ui-icon-seek-start { background-position: -80px -160px; }
235
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
236
+ .ui-icon-seek-first { background-position: -80px -160px; }
237
+ .ui-icon-stop { background-position: -96px -160px; }
238
+ .ui-icon-eject { background-position: -112px -160px; }
239
+ .ui-icon-volume-off { background-position: -128px -160px; }
240
+ .ui-icon-volume-on { background-position: -144px -160px; }
241
+ .ui-icon-power { background-position: 0 -176px; }
242
+ .ui-icon-signal-diag { background-position: -16px -176px; }
243
+ .ui-icon-signal { background-position: -32px -176px; }
244
+ .ui-icon-battery-0 { background-position: -48px -176px; }
245
+ .ui-icon-battery-1 { background-position: -64px -176px; }
246
+ .ui-icon-battery-2 { background-position: -80px -176px; }
247
+ .ui-icon-battery-3 { background-position: -96px -176px; }
248
+ .ui-icon-circle-plus { background-position: 0 -192px; }
249
+ .ui-icon-circle-minus { background-position: -16px -192px; }
250
+ .ui-icon-circle-close { background-position: -32px -192px; }
251
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
252
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
253
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
254
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
255
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
256
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
257
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
258
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
259
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
260
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
261
+ .ui-icon-circle-check { background-position: -208px -192px; }
262
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
263
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
264
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
265
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
266
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
267
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
268
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
269
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
270
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
271
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
272
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
273
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
274
+
275
+
276
+ /* Misc visuals
277
+ ----------------------------------*/
278
+
279
+ /* Corner radius */
280
+ .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
281
+ .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
282
+ .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
283
+ .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
284
+
285
+ /* Overlays */
286
+ .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
287
+ .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*!
288
+ * jQuery UI Resizable 1.8.20
289
+ *
290
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
291
+ * Dual licensed under the MIT or GPL Version 2 licenses.
292
+ * http://jquery.org/license
293
+ *
294
+ * http://docs.jquery.com/UI/Resizable#theming
295
+ */
296
+ .ui-resizable { position: relative;}
297
+ .ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
298
+ .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
299
+ .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
300
+ .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
301
+ .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
302
+ .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
303
+ .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
304
+ .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
305
+ .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
306
+ .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
307
+ * jQuery UI Selectable 1.8.20
308
+ *
309
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
310
+ * Dual licensed under the MIT or GPL Version 2 licenses.
311
+ * http://jquery.org/license
312
+ *
313
+ * http://docs.jquery.com/UI/Selectable#theming
314
+ */
315
+ .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
316
+ /*!
317
+ * jQuery UI Accordion 1.8.20
318
+ *
319
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
320
+ * Dual licensed under the MIT or GPL Version 2 licenses.
321
+ * http://jquery.org/license
322
+ *
323
+ * http://docs.jquery.com/UI/Accordion#theming
324
+ */
325
+ /* IE/Win - Fix animation bug - #4615 */
326
+ .ui-accordion { width: 100%; }
327
+ .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
328
+ .ui-accordion .ui-accordion-li-fix { display: inline; }
329
+ .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
330
+ .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
331
+ .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
332
+ .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
333
+ .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
334
+ .ui-accordion .ui-accordion-content-active { display: block; }
335
+ /*!
336
+ * jQuery UI Autocomplete 1.8.20
337
+ *
338
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
339
+ * Dual licensed under the MIT or GPL Version 2 licenses.
340
+ * http://jquery.org/license
341
+ *
342
+ * http://docs.jquery.com/UI/Autocomplete#theming
343
+ */
344
+ .ui-autocomplete { position: absolute; cursor: default; }
345
+
346
+ /* workarounds */
347
+ * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
348
+
349
+ /*
350
+ * jQuery UI Menu 1.8.20
351
+ *
352
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
353
+ * Dual licensed under the MIT or GPL Version 2 licenses.
354
+ * http://jquery.org/license
355
+ *
356
+ * http://docs.jquery.com/UI/Menu#theming
357
+ */
358
+ .ui-menu {
359
+ list-style:none;
360
+ padding: 2px;
361
+ margin: 0;
362
+ display:block;
363
+ float: left;
364
+ }
365
+ .ui-menu .ui-menu {
366
+ margin-top: -3px;
367
+ }
368
+ .ui-menu .ui-menu-item {
369
+ margin:0;
370
+ padding: 0;
371
+ zoom: 1;
372
+ float: left;
373
+ clear: left;
374
+ width: 100%;
375
+ }
376
+ .ui-menu .ui-menu-item a {
377
+ text-decoration:none;
378
+ display:block;
379
+ padding:.2em .4em;
380
+ line-height:1.5;
381
+ zoom:1;
382
+ }
383
+ .ui-menu .ui-menu-item a.ui-state-hover,
384
+ .ui-menu .ui-menu-item a.ui-state-active {
385
+ font-weight: normal;
386
+ margin: -1px;
387
+ }
388
+ /*!
389
+ * jQuery UI Button 1.8.20
390
+ *
391
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
392
+ * Dual licensed under the MIT or GPL Version 2 licenses.
393
+ * http://jquery.org/license
394
+ *
395
+ * http://docs.jquery.com/UI/Button#theming
396
+ */
397
+ .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
398
+ .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
399
+ button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
400
+ .ui-button-icons-only { width: 3.4em; }
401
+ button.ui-button-icons-only { width: 3.7em; }
402
+
403
+ /*button text element */
404
+ .ui-button .ui-button-text { display: block; line-height: 1.4; }
405
+ .ui-button-text-only .ui-button-text { padding: .4em 1em; }
406
+ .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
407
+ .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
408
+ .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
409
+ .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
410
+ /* no icon support for input elements, provide padding by default */
411
+ input.ui-button { padding: .4em 1em; }
412
+
413
+ /*button icon element(s) */
414
+ .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
415
+ .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
416
+ .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
417
+ .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
418
+ .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
419
+
420
+ /*button sets*/
421
+ .ui-buttonset { margin-right: 7px; }
422
+ .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
423
+
424
+ /* workarounds */
425
+ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
426
+ /*!
427
+ * jQuery UI Dialog 1.8.20
428
+ *
429
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
430
+ * Dual licensed under the MIT or GPL Version 2 licenses.
431
+ * http://jquery.org/license
432
+ *
433
+ * http://docs.jquery.com/UI/Dialog#theming
434
+ */
435
+ .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
436
+ .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
437
+ .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
438
+ .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
439
+ .ui-dialog .ui-dialog-titlebar-close span { display: block; }
440
+ .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
441
+ .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
442
+ .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
443
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
444
+ .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
445
+ .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
446
+ .ui-draggable .ui-dialog-titlebar { cursor: move; }
447
+ /*!
448
+ * jQuery UI Slider 1.8.20
449
+ *
450
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
451
+ * Dual licensed under the MIT or GPL Version 2 licenses.
452
+ * http://jquery.org/license
453
+ *
454
+ * http://docs.jquery.com/UI/Slider#theming
455
+ */
456
+ .ui-slider { position: relative; text-align: left; }
457
+ .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
458
+ .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
459
+
460
+ .ui-slider-horizontal { height: .8em; }
461
+ .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
462
+ .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
463
+ .ui-slider-horizontal .ui-slider-range-min { left: 0; }
464
+ .ui-slider-horizontal .ui-slider-range-max { right: 0; }
465
+
466
+ .ui-slider-vertical { width: .8em; height: 100px; }
467
+ .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
468
+ .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
469
+ .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
470
+ .ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
471
+ * jQuery UI Tabs 1.8.20
472
+ *
473
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
474
+ * Dual licensed under the MIT or GPL Version 2 licenses.
475
+ * http://jquery.org/license
476
+ *
477
+ * http://docs.jquery.com/UI/Tabs#theming
478
+ */
479
+ .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
480
+ .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
481
+ .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
482
+ .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
483
+ .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
484
+ .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
485
+ .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
486
+ .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
487
+ .ui-tabs .ui-tabs-hide { display: none !important; }
488
+ /*!
489
+ * jQuery UI Datepicker 1.8.20
490
+ *
491
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
492
+ * Dual licensed under the MIT or GPL Version 2 licenses.
493
+ * http://jquery.org/license
494
+ *
495
+ * http://docs.jquery.com/UI/Datepicker#theming
496
+ */
497
+ .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
498
+ .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
499
+ .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
500
+ .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
501
+ .ui-datepicker .ui-datepicker-prev { left:2px; }
502
+ .ui-datepicker .ui-datepicker-next { right:2px; }
503
+ .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
504
+ .ui-datepicker .ui-datepicker-next-hover { right:1px; }
505
+ .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
506
+ .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
507
+ .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
508
+ .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
509
+ .ui-datepicker select.ui-datepicker-month,
510
+ .ui-datepicker select.ui-datepicker-year { width: 49%;}
511
+ .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
512
+ .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
513
+ .ui-datepicker td { border: 0; padding: 1px; }
514
+ .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
515
+ .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
516
+ .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
517
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
518
+
519
+ /* with multiple calendars */
520
+ .ui-datepicker.ui-datepicker-multi { width:auto; }
521
+ .ui-datepicker-multi .ui-datepicker-group { float:left; }
522
+ .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
523
+ .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
524
+ .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
525
+ .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
526
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
527
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
528
+ .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
529
+ .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
530
+
531
+ /* RTL support */
532
+ .ui-datepicker-rtl { direction: rtl; }
533
+ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
534
+ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
535
+ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
536
+ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
537
+ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
538
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
539
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
540
+ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
541
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
542
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
543
+
544
+ /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
545
+ .ui-datepicker-cover {
546
+ display: none; /*sorry for IE5*/
547
+ display/**/: block; /*sorry for IE5*/
548
+ position: absolute; /*must have*/
549
+ z-index: -1; /*must have*/
550
+ filter: mask(); /*must have*/
551
+ top: -4px; /*must have*/
552
+ left: -4px; /*must have*/
553
+ width: 200px; /*must have*/
554
+ height: 200px; /*must have*/
555
+ }/*!
556
+ * jQuery UI Progressbar 1.8.20
557
+ *
558
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
559
+ * Dual licensed under the MIT or GPL Version 2 licenses.
560
+ * http://jquery.org/license
561
+ *
562
+ * http://docs.jquery.com/UI/Progressbar#theming
563
+ */
564
+ .ui-progressbar { height:2em; text-align: left; overflow: hidden; }
565
+ .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
trunk/css/tmce/editor.css ADDED
@@ -0,0 +1,2317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /*------------------------------------------------------------------------------
3
+
4
+ TinyMCE and Quicklinks toolbars
5
+ ------------------------------------------------------------------------------*/
6
+
7
+ /* wp_theme/ui.css */
8
+ .wp_themeSkin table,
9
+ .wp_themeSkin tbody,
10
+ .wp_themeSkin a,
11
+ .wp_themeSkin img,
12
+ .wp_themeSkin tr,
13
+ .wp_themeSkin div,
14
+ .wp_themeSkin td,
15
+ .wp_themeSkin iframe,
16
+ .wp_themeSkin span,
17
+ .wp_themeSkin *,
18
+ .wp_themeSkin .mceText {
19
+ border: 0;
20
+ margin: 0;
21
+ padding: 0;
22
+ white-space: nowrap;
23
+ text-decoration: none;
24
+ font-weight: normal;
25
+ cursor: default;
26
+ vertical-align: baseline;
27
+ width: auto;
28
+ border-collapse: separate;
29
+ }
30
+
31
+ .wp_themeSkin a:hover,
32
+ .wp_themeSkin a:link,
33
+ .wp_themeSkin a:visited,
34
+ .wp_themeSkin a:active {
35
+ text-decoration: none;
36
+ font-weight: normal;
37
+ cursor: default;
38
+ }
39
+
40
+ .wp_themeSkin table td {
41
+ vertical-align: middle;
42
+ }
43
+
44
+ .wp_themeSkin *,
45
+ .wp_themeSkin a:hover,
46
+ .wp_themeSkin a:link,
47
+ .wp_themeSkin a:visited,
48
+ .wp_themeSkin a:active {
49
+ color: #555;
50
+ }
51
+
52
+ /* These are part of TinyMCE, used in TinyMCE Advanced, but not WordPress. These are not updated for 3.8's design. */
53
+ .wp_themeSkin span.mce_sup,
54
+ .wp_themeSkin span.mce_sub,
55
+ .wp_themeSkin span.mce_media,
56
+ .wp_themeSkin span.mce_styleprops,
57
+ .wp_themeSkin span.mce_search,
58
+ .wp_themeSkin span.mce_emotions,
59
+ .wp_themeSkin span.mce_print,
60
+ .wp_themeSkin span.mce_attribs,
61
+ .wp_themeSkin span.mce_hr,
62
+ .wp_themeSkin span.mce_cut,
63
+ .wp_themeSkin span.mce_copy,
64
+ .wp_themeSkin span.mce_paste,
65
+ .wp_themeSkin span.mce_cite,
66
+ .wp_themeSkin span.mce_visualchars,
67
+ .wp_themeSkin span.mce_advhr,
68
+ .wp_themeSkin span.mce_insertdate,
69
+ .wp_themeSkin span.mce_anchor,
70
+ .wp_themeSkin span.mce_visualaid,
71
+ .wp_themeSkin span.mce_cleanup,
72
+ .wp_themeSkin span.mce_table,
73
+ .wp_themeSkin span.mce_row_props,
74
+ .wp_themeSkin span.mce_cell_props,
75
+ .wp_themeSkin span.mce_row_before,
76
+ .wp_themeSkin span.mce_row_after,
77
+ .wp_themeSkin span.mce_delete_row,
78
+ .wp_themeSkin span.mce_col_before,
79
+ .wp_themeSkin span.mce_col_after,
80
+ .wp_themeSkin span.mce_delete_col,
81
+ .wp_themeSkin span.mce_split_cells,
82
+ .wp_themeSkin span.mce_merge_cells,
83
+ .wp_themeSkin span.mce_delete_table,
84
+ .wp_themeSkin span.mce_ins,
85
+ .wp_themeSkin span.mce_abbr,
86
+ .wp_themeSkin span.mce_acronym,
87
+ .wp_themeSkin span.mce_del,
88
+ .wp_themeSkin span.mce_replace,
89
+ .wp_themeSkin span.mce_code,
90
+ .wp_themeSkin span.mce_nonbreaking,
91
+ .wp_themeSkin span.mce_inserttime,
92
+ .wp_themeSkin span.mce_insertlayer,
93
+ .wp_themeSkin span.mce_moveforward,
94
+ .wp_themeSkin span.mce_movebackward,
95
+ .wp_themeSkin span.mce_absolute {
96
+ -moz-transition: none;
97
+ -webkit-transition: none;
98
+ transition: none;
99
+ /*background: url("../js/tinymce/skins/wordpress/images/icons.gif") no-repeat 20px 20px;*/
100
+ }
101
+
102
+ .wp_themeSkin span.mce_code:after {
103
+ content: '\f475';
104
+ font-family: 'dashicons';
105
+ }
106
+
107
+ /* No @font-face support */
108
+ .no-font-face .wp_themeSkin span.mce_undo,
109
+ .no-font-face .wp_themeSkin span.mce_redo,
110
+ .no-font-face .wp_themeSkin span.mce_bullist,
111
+ .no-font-face .wp_themeSkin span.mce_numlist,
112
+ .no-font-face .wp_themeSkin span.mce_blockquote,
113
+ .no-font-face .wp_themeSkin span.mce_charmap,
114
+ .no-font-face .wp_themeSkin span.mce_bold,
115
+ .no-font-face .wp_themeSkin span.mce_italic,
116
+ .no-font-face .wp_themeSkin span.mce_underline,
117
+ .no-font-face .wp_themeSkin span.mce_justifyleft,
118
+ .no-font-face .wp_themeSkin span.mce_justifyright,
119
+ .no-font-face .wp_themeSkin span.mce_justifycenter,
120
+ .no-font-face .wp_themeSkin span.mce_justifyfull,
121
+ .no-font-face .wp_themeSkin span.mce_indent,
122
+ .no-font-face .wp_themeSkin span.mce_outdent,
123
+ .no-font-face .wp_themeSkin span.mce_link,
124
+ .no-font-face .wp_themeSkin span.mce_unlink,
125
+ .no-font-face .wp_themeSkin span.mce_help,
126
+ .no-font-face .wp_themeSkin span.mce_removeformat,
127
+ .no-font-face .wp_themeSkin span.mce_fullscreen,
128
+ .no-font-face .wp_themeSkin span.mce_wp_fullscreen,
129
+ .no-font-face .wp_themeSkin span.mce_media,
130
+ .no-font-face .wp_themeSkin span.mce_pastetext,
131
+ .no-font-face .wp_themeSkin span.mce_pasteword,
132
+ .no-font-face .wp_themeSkin span.mce_wp_help,
133
+ .no-font-face .wp_themeSkin span.mce_wp_adv,
134
+ .no-font-face .wp_themeSkin span.mce_wp_more,
135
+ .no-font-face .wp_themeSkin span.mce_strikethrough,
136
+ .no-font-face .wp_themeSkin span.mce_spellchecker,
137
+ .no-font-face .wp_themeSkin span.mce_forecolor,
138
+ .no-font-face .wp_themeSkin .mce_forecolorpicker,
139
+ .no-font-face .wp_themeSkin .mceSplitButton .mce_spellchecker span.mce_spellchecker,
140
+ .no-font-face .wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor,
141
+ .no-font-face .wp_themeSkin .mceSplitButton span.mce_numlist,
142
+ .no-font-face .wp_themeSkin .mceSplitButton span.mce_bullist {
143
+ -moz-transition: none;
144
+ -webkit-transition: none;
145
+ transition: none;
146
+ background-image: url('../images/wpicons.png?ver=20120720');
147
+ }
148
+
149
+ /* Theme */
150
+ .no-font-face .wp_themeSkin span.mce_undo {background-position:-500px -20px}
151
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_undo,
152
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_undo {background-position:-500px 0}
153
+
154
+ .no-font-face .wp_themeSkin span.mce_redo {background-position:-480px -20px}
155
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_redo,
156
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_redo {background-position:-480px 0}
157
+
158
+ .no-font-face .wp_themeSkin span.mce_bullist {background-position:-40px -20px}
159
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_bullist,
160
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_bullist,
161
+ .no-font-face .wp_themeSkin .mceSplitButton:hover span.mce_bullist {background-position:-40px 0}
162
+
163
+ .no-font-face .wp_themeSkin span.mce_numlist {background-position:-60px -20px}
164
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_numlist,
165
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_numlist,
166
+ .no-font-face .wp_themeSkin .mceSplitButton:hover span.mce_numlist {background-position:-60px 0}
167
+
168
+ .no-font-face .wp_themeSkin span.mce_blockquote {background-position:-80px -20px}
169
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_blockquote,
170
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_blockquote {background-position:-80px 0}
171
+
172
+ .no-font-face .wp_themeSkin span.mce_charmap {background-position:-420px -20px}
173
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_charmap,
174
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_charmap {background-position:-420px 0}
175
+
176
+ .no-font-face .wp_themeSkin span.mce_bold {background-position:0 -20px}
177
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_bold,
178
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_bold {background-position:0 0}
179
+
180
+ .no-font-face .wp_themeSkin span.mce_italic {background-position:-20px -20px}
181
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_italic,
182
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_italic {background-position:-20px 0}
183
+
184
+ .no-font-face .wp_themeSkin span.mce_underline {background-position:-280px -20px}
185
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_underline,
186
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_underline {background-position:-280px 0}
187
+
188
+ .no-font-face .wp_themeSkin span.mce_justifyleft {background-position:-100px -20px}
189
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_justifyleft,
190
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_justifyleft {background-position:-100px 0}
191
+
192
+ .no-font-face .wp_themeSkin span.mce_justifyright {background-position:-140px -20px}
193
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_justifyright,
194
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_justifyright {background-position:-140px 0}
195
+
196
+ .no-font-face .wp_themeSkin span.mce_justifycenter {background-position:-120px -20px}
197
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_justifycenter,
198
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_justifycenter {background-position:-120px 0}
199
+
200
+ .no-font-face .wp_themeSkin span.mce_justifyfull {background-position:-300px -20px}
201
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_justifyfull,
202
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_justifyfull {background-position:-300px 0}
203
+
204
+ .no-font-face .wp_themeSkin span.mce_indent {background-position:-460px -20px}
205
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_indent,
206
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_indent {background-position:-460px 0}
207
+
208
+ .no-font-face .wp_themeSkin span.mce_outdent {background-position:-440px -20px}
209
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_outdent,
210
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_outdent {background-position:-440px 0}
211
+
212
+ .no-font-face .wp_themeSkin span.mce_link {background-position:-160px -20px}
213
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_link,
214
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_link {background-position:-160px 0}
215
+
216
+ .no-font-face .wp_themeSkin span.mce_unlink {background-position:-180px -20px}
217
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_unlink,
218
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_unlink {background-position:-180px 0}
219
+
220
+ .no-font-face .wp_themeSkin span.mce_help {background-position:-520px -20px}
221
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_help,
222
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_help {background-position:-520px 0}
223
+
224
+ .no-font-face .wp_themeSkin span.mce_removeformat {background-position:-380px -20px}
225
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_removeformat,
226
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_removeformat {background-position:-380px 0}
227
+
228
+ .no-font-face .wp_themeSkin span.mce_strikethrough {background-position:-540px -20px;}
229
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_strikethrough,
230
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_strikethrough {background-position:-540px 0}
231
+
232
+ .no-font-face .wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor {background-position:-320px -20px}
233
+ .no-font-face .wp_themeSkin .mceSplitButtonEnabled:hover span.mce_forecolor,
234
+ .no-font-face .wp_themeSkin .mceSplitButtonSelected span.mce_forecolor {background-position:-320px 0}
235
+
236
+ .no-font-face .wp_themeSkin .mce_forecolorpicker {background-position:-320px -20px}
237
+
238
+ /* Plugins in WP */
239
+ .no-font-face .wp_themeSkin span.mce_fullscreen {background-position:-240px -20px}
240
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_fullscreen,
241
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_fullscreen {background-position:-240px 0}
242
+
243
+ .no-font-face .wp_themeSkin span.mce_wp_fullscreen {background-position:-240px -20px}
244
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_wp_fullscreen,
245
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_wp_fullscreen {background-position:-240px 0}
246
+
247
+ .no-font-face .wp_themeSkin span.mce_media {background-position:-400px -20px}
248
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_media,
249
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_media {background-position:-400px 0}
250
+
251
+ .no-font-face .wp_themeSkin span.mce_pastetext {background-position:-340px -20px}
252
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_pastetext,
253
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_pastetext {background-position:-340px 0}
254
+
255
+ .no-font-face .wp_themeSkin span.mce_pasteword {background-position:-360px -20px}
256
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_pasteword,
257
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_pasteword {background-position:-360px 0}
258
+
259
+ .no-font-face .wp_themeSkin span.mce_spellchecker {background-position:-220px -20px}
260
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_spellchecker,
261
+ .no-font-face .wp_themeSkin .mceSplitButtonEnabled:hover span.mce_spellchecker,
262
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_spellchecker,
263
+ .no-font-face .wp_themeSkin .mceSplitButtonSelected span.mce_spellchecker {background-position:-220px 0}
264
+
265
+ .no-font-face .wp_themeSkin span.mce_wp_help {background-position:-520px -20px}
266
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_wp_help,
267
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_wp_help {background-position:-520px 0}
268
+
269
+ .no-font-face .wp_themeSkin span.mce_wp_adv {background-position:-260px -20px}
270
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_wp_adv,
271
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_wp_adv {background-position:-260px 0}
272
+
273
+ .no-font-face .wp_themeSkin span.mce_wp_more {background-position:-200px -20px}
274
+ .no-font-face .wp_themeSkin .mceButtonEnabled:hover span.mce_wp_more,
275
+ .no-font-face .wp_themeSkin .mceButtonActive span.mce_wp_more {background-position:-200px 0}
276
+
277
+ .no-font-face .mceIcon:before {
278
+ display: none !important;
279
+ }
280
+ /* End no @font-face */
281
+
282
+ /* Containers */
283
+ .wp_themeSkin table {}
284
+
285
+ .wp_themeSkin iframe {
286
+ display: block;
287
+ }
288
+
289
+ .wp_themeSkin #mce_fullscreen_ifr {
290
+ background-color: #fff;
291
+ }
292
+
293
+ .wp_themeSkin .mceToolbar {
294
+ padding: 1px;
295
+ }
296
+
297
+ /* External */
298
+ .wp_themeSkin .mceExternalToolbar {
299
+ position: absolute;
300
+ border-bottom: 0;
301
+ display: none;
302
+ }
303
+
304
+ .wp_themeSkin .mceExternalToolbar td.mceToolbar {
305
+ padding-right: 13px;
306
+ }
307
+
308
+ .wp_themeSkin .mceExternalClose {
309
+ position: absolute;
310
+ top: 3px;
311
+ right: 3px;
312
+ width: 7px;
313
+ height: 7px;
314
+ /*background: url("../js/tinymce/skins/wordpress/images/icons.gif") -820px 0;*/
315
+ }
316
+
317
+ /* Layout */
318
+ .wp_themeSkin table.mceToolbar,
319
+ .wp_themeSkin tr.mceFirst .mceToolbar tr td,
320
+ .wp_themeSkin tr.mceLast .mceToolbar tr td {
321
+ border: 0;
322
+ margin: 0;
323
+ padding: 0;
324
+ }
325
+
326
+ .wp_themeSkin table.mceLayout {
327
+ border: 0;
328
+ }
329
+
330
+ .wp_themeSkin .mceStatusbar {
331
+ background: #fff;
332
+ border-top: 1px solid #eee;
333
+ color: #000;
334
+ display: block;
335
+ font-family: sans-serif;
336
+ font-size: 12px;
337
+ height: 20px;
338
+ line-height: 16px;
339
+ padding: 0 0 0 8px;
340
+ overflow: visible;
341
+ }
342
+
343
+ .wp_themeSkin .mceStatusbar * {
344
+ color: #555;
345
+ }
346
+
347
+ .wp_themeSkin .mceStatusbar div {
348
+ float: left;
349
+ padding: 2px;
350
+ }
351
+
352
+ .wp_themeSkin .mceStatusbar a.mceResize {
353
+ display: block;
354
+ float: right;
355
+ /*background: url("../js/tinymce/skins/wordpress/images/icons.gif") -800px 0;*/
356
+ width: 20px;
357
+ height: 20px;
358
+ cursor: se-resize;
359
+ }
360
+
361
+ .wp_themeSkin .mceStatusbar a:hover {
362
+ text-decoration: underline;
363
+ }
364
+
365
+ .wp_themeSkin table.mceToolbar {
366
+ margin: 0 6px 2px;
367
+ }
368
+
369
+ .wp_themeSkin table.mceToolbar :active,
370
+ .wp_themeSkin table.mceToolbar :focus,
371
+ .wp_themeSkin table.mceToolbar:focus,
372
+ .wp_themeSkin span.mceSeparator:focus {
373
+ outline: none;
374
+ }
375
+
376
+ .wp_themeSkin #content_toolbar1 {
377
+ margin-top: 2px;
378
+ }
379
+
380
+ .wp_themeSkin .mceToolbar .mceToolbarEndListBox span {
381
+ display: none;
382
+ }
383
+
384
+ .wp_themeSkin span.mceIcon,
385
+ .wp_themeSkin img.mceIcon {
386
+ display: block;
387
+ width: 20px;
388
+ height: 20px;
389
+ }
390
+
391
+ a .mceIcon, .mceAction {
392
+ text-align: center;
393
+ font: normal 20px/1 'dashicons' !important;
394
+ speak: none;
395
+ -webkit-font-smoothing: antialiased;
396
+ -moz-osx-font-smoothing: grayscale;
397
+ }
398
+
399
+ .mceAction {
400
+ line-height:16px;
401
+ }
402
+
403
+ /* Button */
404
+ .wp_themeSkin .mceButton {
405
+ display: block;
406
+ width: 20px;
407
+ height: 20px;
408
+ cursor: default;
409
+ padding: 1px 2px;
410
+ margin: 1px;
411
+ -webkit-border-radius: 2px;
412
+ border-radius: 2px;
413
+ }
414
+
415
+ .wp_themeSkin a.mceButtonEnabled:hover {
416
+ background-image: inherit 0 -10px;
417
+ }
418
+
419
+ .wp_themeSkin .mceOldBoxModel a.mceButton span, .wp_themeSkin .mceOldBoxModel a.mceButton img {
420
+ margin: 0 0 0 1px;
421
+ }
422
+
423
+ .wp_themeSkin .mceButtonDisabled .mceIcon {
424
+ opacity: 0.2;
425
+ filter: alpha(opacity=20);
426
+ }
427
+
428
+ /* Separator */
429
+ .wp_themeSkin .mceSeparator {
430
+ display: none;
431
+ }
432
+
433
+ /* ListBox */
434
+ .wp_themeSkin .mceListBox,
435
+ .wp_themeSkin .mceListBox a {
436
+ display: block;
437
+ }
438
+
439
+ .wp_themeSkin .mceListBox .mceText {
440
+ padding: 1px 4px 1px 5px;
441
+ width: 70px;
442
+ text-align: left;
443
+ text-decoration: none;
444
+ -webkit-border-bottom-left-radius: 2px;
445
+ -webkit-border-top-left-radius: 2px;
446
+ border-bottom-left-radius: 2px;
447
+ border-top-left-radius: 2px;
448
+ font-family: sans-serif;
449
+ font-size: 12px;
450
+ height: 20px;
451
+ line-height: 20px;
452
+ overflow: hidden;
453
+ }
454
+
455
+ .wp_themeSkin .mceListBox {
456
+ margin: 1px;
457
+ direction: ltr;
458
+ background-color: #fff;
459
+ border: 1px solid #ddd;
460
+ -webkit-box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .2);
461
+ box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .2);
462
+ }
463
+
464
+ .wp_themeSkin .mceListBox .mceOpen {
465
+ width: 12px;
466
+ height: 20px;
467
+ border-collapse: separate;
468
+ padding: 1px;
469
+ -webkit-border-bottom-left-radius: 0;
470
+ -webkit-border-top-left-radius: 0;
471
+ border-bottom-left-radius: 0;
472
+ border-top-left-radius: 0;
473
+ }
474
+
475
+ .wp_themeSkin .mceListBox .mceFirst a {
476
+ border-style: solid;
477
+ border-width: 1px;
478
+ border-bottom-right-radius: 2px;
479
+ border-top-right-radius: 2px;
480
+ }
481
+
482
+ .wp_themeSkin .mceListBoxMenu .mce_formatPreview {
483
+ line-height: normal;
484
+ }
485
+
486
+ .wp_themeSkin .mceListBox .mceOpen,
487
+ .wp_themeSkin .mceListBoxHover .mceOpen,
488
+ .wp_themeSkin .mceListBoxSelected .mceOpen,
489
+ .wp_themeSkin table.mceListBoxEnabled .mceOpen {
490
+ background-image: url("../../../../../wp-includes/images/down_arrow.gif");
491
+ background-position: 3px 1px;
492
+ background-repeat: no-repeat;
493
+ }
494
+
495
+ .wp_themeSkin .mceListBoxDisabled .mceText {
496
+ color: gray;
497
+ }
498
+
499
+ .wp_themeSkin .mceListBoxMenu {
500
+ overflow: auto;
501
+ overflow-x: hidden;
502
+ }
503
+
504
+ .wp_themeSkin .mceOldBoxModel .mceListBox .mceText {
505
+ height: 22px;
506
+ }
507
+
508
+ .wp_themeSkin select.mceListBox {
509
+ font-family: sans-serif;
510
+ font-size: 12px;
511
+ border-color: #b2b2b2;
512
+ background-color: #fff;
513
+ }
514
+
515
+ /* SplitButton */
516
+ .wp_themeSkin .mceSplitButton a,
517
+ .wp_themeSkin .mceSplitButton span {
518
+ display: block;
519
+ height: 20px;
520
+ }
521
+
522
+ .wp_themeSkin .mceSplitButton {
523
+ display: block;
524
+ direction: ltr;
525
+ }
526
+
527
+ .wp_themeSkin table.mceSplitButton td {
528
+ padding: 2px;
529
+ -webkit-border-radius: 2px;
530
+ border-radius: 2px;
531
+ }
532
+
533
+ .wp_themeSkin table.mceSplitButton:hover td {
534
+ background-image: inherit 0 -10px;
535
+ }
536
+
537
+ .wp_themeSkin .mceSplitButton a.mceAction {
538
+ height: 20px;
539
+ width: 20px;
540
+ padding: 1px 2px;
541
+ border-right: 0 none;
542
+ }
543
+
544
+ .wp_themeSkin .mceSplitButton span.mceAction {
545
+ background-image: url("../../../../../wp-includes/js/tinymce/skins/wordpress/images/icons.gif");
546
+ background-repeat: no-repeat;
547
+ background-color: transparent;
548
+ width: 20px;
549
+ }
550
+
551
+ .wp_themeSkin .mceSplitButton span.mceAction.mce_bullist,
552
+ .wp_themeSkin .mceSplitButton span.mceAction.mce_numlist {
553
+ background-image: none;
554
+ }
555
+
556
+ .wp_themeSkin .mceSplitButton a.mceOpen {
557
+ width: 11px;
558
+ height: 20px;
559
+ background-position: 0px 2px;
560
+ background-repeat: no-repeat;
561
+ padding: 1px 0;
562
+ }
563
+
564
+ .wp_themeSkin .mceSplitButton span.mceOpen {
565
+ display: none;
566
+ }
567
+
568
+ .wp_themeSkin .mceSplitButtonDisabled .mceAction {
569
+ opacity: 0.3;
570
+ filter: alpha(opacity=30);
571
+ }
572
+
573
+ .wp_themeSkin .mceListBox a.mceText,
574
+ .wp_themeSkin .mceSplitButton a.mceAction {
575
+ -webkit-border-bottom-left-radius: 2px;
576
+ -webkit-border-top-left-radius: 2px;
577
+ border-bottom-left-radius: 2px;
578
+ border-top-left-radius: 2px;
579
+ }
580
+
581
+ .wp_themeSkin .mceSplitButton a.mceOpen,
582
+ .wp_themeSkin .mceListBox a.mceOpen {
583
+ -webkit-border-bottom-right-radius: 2px;
584
+ -webkit-border-top-right-radius: 2px;
585
+ border-bottom-right-radius: 2px;
586
+ border-top-right-radius: 2px;
587
+ }
588
+
589
+ /* ColorSplitButton */
590
+ .wp_themeSkin div.mceColorSplitMenu table {
591
+ background-color: #ebebeb;
592
+ border-color: #bbb;
593
+ }
594
+
595
+ .wp_themeSkin .mceColorSplitMenu td {
596
+ padding: 2px;
597
+ }
598
+
599
+ .wp_themeSkin .mceColorSplitMenu a {
600
+ display: block;
601
+ width: 9px;
602
+ height: 9px;
603
+ overflow: hidden;
604
+ border-color: #B2B2B2;
605
+ }
606
+
607
+ .wp_themeSkin .mceColorSplitMenu td.mceMoreColors {
608
+ padding: 1px 3px 1px 1px;
609
+ }
610
+
611
+ .wp_themeSkin .mceColorSplitMenu a.mceMoreColors {
612
+ width: 100%;
613
+ height: auto;
614
+ text-align: center;
615
+ font-family: "Open Sans", sans-serif;
616
+ font-size: 11px;
617
+ line-height: 20px;
618
+ border-color: #fff;
619
+ }
620
+
621
+ .wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover {}
622
+ .wp_themeSkin a.mceMoreColors:hover {}
623
+ .wp_themeSkin .mceColorPreview {
624
+ margin: -5px 0 0 2px;
625
+ width: 16px;
626
+ height: 4px;
627
+ overflow: hidden;
628
+ }
629
+
630
+ /* Menu */
631
+ .wp_themeSkin .mceMenu {
632
+ position: absolute;
633
+ left: 0;
634
+ top: 0;
635
+ z-index: 1000;
636
+ border-color: #ddd;
637
+ direction: ltr;
638
+ }
639
+
640
+ .wp_themeSkin .mceNoIcons span.mceIcon {
641
+ width: 0;
642
+ }
643
+
644
+ .wp_themeSkin .mceNoIcons a .mceText {
645
+ padding-left: 10px;
646
+ }
647
+
648
+ .wp_themeSkin .mceMenu table {
649
+ background-color: #ebeaeb;
650
+ }
651
+
652
+ .wp_themeSkin .mceMenu a,
653
+ .wp_themeSkin .mceMenu span,
654
+ .wp_themeSkin .mceMenu {
655
+ display: block;
656
+ }
657
+
658
+ .wp_themeSkin .mceMenu td {
659
+ height: 20px;overflow: hidden;
660
+ }
661
+
662
+ .wp_themeSkin .mceMenu a {
663
+ position: relative;
664
+ padding: 2px 0;
665
+ text-decoration: none !important;
666
+ }
667
+
668
+ .wp_themeSkin .mceMenu .mceText {
669
+ position: relative;
670
+ display: block;
671
+ font-family: "Open Sans", sans-serif;
672
+ cursor: default;
673
+ margin: 0;
674
+ padding: 0 25px;
675
+ color: #000;
676
+ }
677
+
678
+ .wp_themeSkin .mceMenu span.mceText, .wp_themeSkin .mceMenu .mcePreview {
679
+ font-size: 12px;
680
+ }
681
+
682
+ .wp_themeSkin .mceMenu pre.mceText {
683
+ font-family: Monospace;
684
+ }
685
+
686
+ .wp_themeSkin .mceMenu .mceIcon {
687
+ position: absolute;
688
+ top: 0;
689
+ left: 0;
690
+ width: 22px;
691
+ }
692
+
693
+ .wp_themeSkin .mceMenu .mceMenuItemEnabled a:hover,
694
+ .wp_themeSkin .mceMenu .mceMenuItemActive {
695
+ background-color: #f5f5f5;
696
+ }
697
+
698
+ .wp_themeSkin td.mceMenuItemSeparator {
699
+ height: 1px;
700
+ background-color: #aaa;
701
+ }
702
+
703
+ .wp_themeSkin .mceMenuItemTitle a {
704
+ border-top: 0;
705
+ border-right: 0;
706
+ border-left: 0;
707
+ border-bottom: 1px solid #aaa;
708
+ text-decoration: none !important;
709
+ background-color: #ccc;
710
+ }
711
+
712
+ .wp_themeSkin .mceMenuItemTitle span.mceText {
713
+ font-weight: bold;
714
+ padding-left: 4px;
715
+ color: #000;
716
+ }
717
+
718
+ .wp_themeSkin .mceMenuItemSelected .mceIcon {
719
+ background: url("/wp-includes/js/tinymce/skins/wordpress/images/menu_check.gif");
720
+ color: #888;
721
+ }
722
+
723
+ .wp_themeSkin .mceNoIcons .mceMenuItemSelected a {
724
+ background: url("/wp-includes/js/tinymce/skins/wordpress/images/menu_arrow.gif") no-repeat -6px center;
725
+ }
726
+
727
+ .wp_themeSkin .mceMenu span.mceMenuLine {
728
+ display: none;
729
+ }
730
+
731
+ .wp_themeSkin .mceMenuItemSub a {
732
+ background: url("/wp-includes/js/tinymce/skins/wordpress/images/menu_arrow.gif") no-repeat top right;
733
+ }
734
+
735
+ /* Progress,Resize */
736
+ .wp_themeSkin .mceBlocker {
737
+ position: absolute;
738
+ left: 0;
739
+ top: 0;
740
+ z-index: 1000;
741
+ opacity: 0.5;
742
+ filter: alpha(opacity=50);
743
+ background: #FFF;
744
+ }
745
+
746
+ .wp_themeSkin .mceProgress {
747
+ position: absolute;
748
+ left: 0;
749
+ top: 0;
750
+ z-index: 1001;
751
+ background: url("/wp-includes/images/spinner.gif") no-repeat;
752
+ width: 32px;
753
+ height: 32px;
754
+ margin: -16px 0 0 -16px;
755
+ }
756
+
757
+ .wp_themeSkin .mcePlaceHolder {
758
+ border: 1px dotted gray;
759
+ }
760
+
761
+ /* Rtl */
762
+ .mceRtl .mceListBox .mceText {
763
+ text-align: right;
764
+ padding: 0 4px 0 0;
765
+ }
766
+
767
+ .mceRtl .mceMenuItem .mceText {
768
+ text-align: right;
769
+ }
770
+
771
+ /* Formats */
772
+ .wp_themeSkin .mce_p span.mceText {}
773
+ .wp_themeSkin .mce_address span.mceText {
774
+ font-style: italic;
775
+ }
776
+
777
+ .wp_themeSkin .mce_pre span.mceText {
778
+ font-family: monospace;
779
+ }
780
+
781
+ .wp_themeSkin .mce_h1 span.mceText {
782
+ font-weight: bolder;
783
+ font-size: 18px;
784
+ }
785
+
786
+ .wp_themeSkin .mce_h2 span.mceText {
787
+ font-weight: bolder;
788
+ font-size: 14px;
789
+ }
790
+
791
+ .wp_themeSkin .mce_h3 span.mceText {
792
+ font-weight: bolder;
793
+ font-size: 12px;
794
+ }
795
+
796
+ .wp_themeSkin .mce_h4 span.mceText {
797
+ font-weight: bolder;
798
+ font-size: 11px;
799
+ }
800
+
801
+ .wp_themeSkin .mce_h5 span.mceText {
802
+ font-weight: bolder;
803
+ font-size: 11px;
804
+ }
805
+
806
+ .wp_themeSkin .mce_h6 span.mceText {
807
+ font-weight: bolder;
808
+ font-size: 10px;
809
+ }
810
+
811
+ span.mce_bold:before {
812
+ content: '\f200';
813
+ }
814
+
815
+ span.mce_italic:before {
816
+ content: '\f201';
817
+ }
818
+
819
+ span.mce_bullist:before {
820
+ content: '\f203';
821
+ }
822
+
823
+ span.mce_numlist:before {
824
+ content: '\f204';
825
+ }
826
+
827
+ span.mce_blockquote:before {
828
+ content: '\f205';
829
+ }
830
+
831
+ span.mce_justifyleft:before {
832
+ content: '\f206';
833
+ }
834
+
835
+ span.mce_justifycenter:before {
836
+ content: '\f207';
837
+ }
838
+
839
+ span.mce_justifyright:before {
840
+ content: '\f208';
841
+ }
842
+
843
+ span.mce_link:before {
844
+ content: '\f103';
845
+ }
846
+
847
+ span.mce_unlink:before {
848
+ content: '\f225';
849
+ }
850
+
851
+ span.mce_wp_more:before {
852
+ content: '\f209';
853
+ }
854
+
855
+ span.mce_strikethrough:before {
856
+ content: '\f224';
857
+ }
858
+
859
+ span.mce_spellchecker {
860
+ font-size: 20px;
861
+ background: none !important;
862
+ margin-top: 2px;
863
+ }
864
+
865
+ span.mce_spellchecker:before {
866
+ content: '\f210';
867
+ }
868
+
869
+ span.mce_fullscreen:before,
870
+ span.mce_wp_fullscreen:before {
871
+ content: '\f211';
872
+ }
873
+
874
+ span.mce_wp_adv:before {
875
+ content: '\f212';
876
+ }
877
+ span.mce_underline:before {
878
+ content: '\f213';
879
+ }
880
+
881
+ span.mce_justifyfull:before {
882
+ content: '\f214';
883
+ }
884
+
885
+ span.mce_forecolor {
886
+ background: none !important;
887
+ }
888
+
889
+ span.mce_forecolor:before {
890
+ content: '\f215';
891
+ }
892
+
893
+ span.mce_pastetext:before {
894
+ content: '\f217';
895
+ }
896
+
897
+ span.mce_pasteword:before {
898
+ content: '\f216';
899
+ }
900
+
901
+ span.mce_removeformat:before {
902
+ content: '\f218';
903
+ }
904
+
905
+ span.mce_charmap:before {
906
+ content: '\f220';
907
+ }
908
+
909
+ span.mce_outdent:before {
910
+ content: '\f221';
911
+ }
912
+
913
+ span.mce_indent:before {
914
+ content: '\f222';
915
+ }
916
+
917
+ span.mce_undo:before {
918
+ content: '\f171';
919
+ }
920
+
921
+ span.mce_redo:before {
922
+ content: '\f172';
923
+ }
924
+
925
+ span.mce_help:before,
926
+ span.mce_wp_help:before {
927
+ content: '\f223';
928
+ }
929
+
930
+ span.mce_image:before {
931
+ content: '\f104';
932
+ }
933
+
934
+ span.mce_ltr:before {
935
+ content: '\f320';
936
+ }
937
+
938
+ /* Default icons */
939
+ .wp_themeSkin span.mce_cleanup {background-position:-380px -20px}
940
+ .wp_themeSkin span.mce_anchor {background-position:-200px 0}
941
+ .wp_themeSkin span.mce_sub {background-position:-600px 0}
942
+ .wp_themeSkin span.mce_sup {background-position:-620px 0}
943
+ .wp_themeSkin span.mce_newdocument {background-position:-520px 0}
944
+ .wp_themeSkin span.mce_image {background-position:-380px 0}
945
+ .wp_themeSkin span.mce_code {background-position:-260px 0}
946
+ .wp_themeSkin span.mce_hr {background-position:-360px 0}
947
+ .wp_themeSkin span.mce_visualaid {background-position:-660px 0}
948
+ .wp_themeSkin span.mce_paste {background-position:-560px 0}
949
+ .wp_themeSkin span.mce_copy {background-position:-700px 0}
950
+ .wp_themeSkin span.mce_cut {background-position:-680px 0}
951
+ .wp_themeSkin .mce_backcolor span.mceAction {background-position:-760px 0}
952
+ .wp_themeSkin .mce_backcolorpicker {background-position:-760px 0}
953
+
954
+ /* Plugins */
955
+ .wp_themeSkin span.mce_advhr {background-position:-0px -20px}
956
+ .wp_themeSkin span.mce_ltr {background-position:-20px -20px}
957
+ .wp_themeSkin span.mce_rtl {background-position:-40px -20px}
958
+ .wp_themeSkin span.mce_emotions {background-position:-60px -20px}
959
+ .wp_themeSkin span.mce_fullpage {background-position:-80px -20px}
960
+ .wp_themeSkin span.mce_iespell {background-position:-120px -20px}
961
+ .wp_themeSkin span.mce_insertdate {background-position:-140px -20px}
962
+ .wp_themeSkin span.mce_inserttime {background-position:-160px -20px}
963
+ .wp_themeSkin span.mce_absolute {background-position:-180px -20px}
964
+ .wp_themeSkin span.mce_backward {background-position:-200px -20px}
965
+ .wp_themeSkin span.mce_forward {background-position:-220px -20px}
966
+ .wp_themeSkin span.mce_insert_layer {background-position:-240px -20px}
967
+ .wp_themeSkin span.mce_insertlayer {background-position:-260px -20px}
968
+ .wp_themeSkin span.mce_movebackward {background-position:-280px -20px}
969
+ .wp_themeSkin span.mce_moveforward {background-position:-300px -20px}
970
+ .wp_themeSkin span.mce_media {background-position:-320px -20px}
971
+ .wp_themeSkin span.mce_nonbreaking {background-position:-340px -20px}
972
+ .wp_themeSkin span.mce_selectall {background-position:-400px -20px}
973
+ .wp_themeSkin span.mce_preview {background-position:-420px -20px}
974
+ .wp_themeSkin span.mce_print {background-position:-440px -20px}
975
+ .wp_themeSkin span.mce_cancel {background-position:-460px -20px}
976
+ .wp_themeSkin span.mce_save {background-position:-480px -20px}
977
+ .wp_themeSkin span.mce_replace {background-position:-500px -20px}
978
+ .wp_themeSkin span.mce_search {background-position:-520px -20px}
979
+ .wp_themeSkin span.mce_styleprops {background-position:-560px -20px}
980
+ .wp_themeSkin span.mce_table {background-position:-580px -20px}
981
+ .wp_themeSkin span.mce_cell_props {background-position:-600px -20px}
982
+ .wp_themeSkin span.mce_delete_table {background-position:-620px -20px}
983
+ .wp_themeSkin span.mce_delete_col {background-position:-640px -20px}
984
+ .wp_themeSkin span.mce_delete_row {background-position:-660px -20px}
985
+ .wp_themeSkin span.mce_col_after {background-position:-680px -20px}
986
+ .wp_themeSkin span.mce_col_before {background-position:-700px -20px}
987
+ .wp_themeSkin span.mce_row_after {background-position:-720px -20px}
988
+ .wp_themeSkin span.mce_row_before {background-position:-740px -20px}
989
+ .wp_themeSkin span.mce_merge_cells {background-position:-760px -20px}
990
+ .wp_themeSkin span.mce_table_props {background-position:-980px -20px}
991
+ .wp_themeSkin span.mce_row_props {background-position:-780px -20px}
992
+ .wp_themeSkin span.mce_split_cells {background-position:-800px -20px}
993
+ .wp_themeSkin span.mce_template {background-position:-820px -20px}
994
+ .wp_themeSkin span.mce_visualchars {background-position:-840px -20px}
995
+ .wp_themeSkin span.mce_abbr {background-position:-860px -20px}
996
+ .wp_themeSkin span.mce_acronym {background-position:-880px -20px}
997
+ .wp_themeSkin span.mce_attribs {background-position:-900px -20px}
998
+ .wp_themeSkin span.mce_cite {background-position:-920px -20px}
999
+ .wp_themeSkin span.mce_del {background-position:-940px -20px}
1000
+ .wp_themeSkin span.mce_ins {background-position:-960px -20px}
1001
+ .wp_themeSkin span.mce_pagebreak {background-position:0 -40px}
1002
+ .wp_themeSkin span.mce_restoredraft {background-position:-20px -40px}
1003
+ .wp_themeSkin span.mce_visualblocks {background-position: -40px -40px}
1004
+
1005
+ /* border */
1006
+ .wp_themeSkin .mceExternalToolbar,
1007
+ .wp_themeSkin .mceButton,
1008
+ .wp_themeSkin a.mceButtonEnabled:hover,
1009
+ .wp_themeSkin a.mceButtonActive,
1010
+ .wp_themeSkin a.mceButtonSelected,
1011
+ .wp_themeSkin .mceListBox .mceText,
1012
+ .wp_themeSkin .mceListBox .mceOpen,
1013
+ .wp_themeSkin select.mceListBox,
1014
+ .wp_themeSkin .mceSplitButton a.mceAction,
1015
+ .wp_themeSkin .mceSplitButton a.mceOpen,
1016
+ .wp_themeSkin .mceSplitButton a.mceOpen:hover,
1017
+ .wp_themeSkin .mceSplitButtonSelected a.mceOpen,
1018
+ .wp_themeSkin table.mceSplitButtonEnabled:hover a.mceAction,
1019
+ .wp_themeSkin .mceSplitButton a.mceAction:hover,
1020
+ .wp_themeSkin div.mceColorSplitMenu table,
1021
+ .wp_themeSkin .mceColorSplitMenu a,
1022
+ .wp_themeSkin .mceColorSplitMenu a.mceMoreColors,
1023
+ .wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover,
1024
+ .wp_themeSkin a.mceMoreColors:hover,
1025
+ .wp_themeSkin .mceMenu {
1026
+ border-style: solid;
1027
+ border-width: 1px;
1028
+ }
1029
+
1030
+ .wp_themeSkin .mceListBox .mceText {
1031
+ border-right: 0 none;
1032
+ }
1033
+
1034
+ .wp_themeSkin iframe {
1035
+ background: transparent;
1036
+ }
1037
+
1038
+ .wp_themeSkin .mceButton {
1039
+ border-color: transparent;
1040
+ }
1041
+
1042
+ .wp_themeSkin .mceListBox .mceText,
1043
+ .wp_themeSkin .mceListBox .mceOpen {
1044
+ border-color: transparent;
1045
+ }
1046
+
1047
+ .wp_themeSkin a.mceButtonEnabled:hover,
1048
+ .wp_themeSkin table.mceSplitButton:hover {
1049
+ border-color: #bbb;
1050
+ background: #eee;
1051
+ background-image: -webkit-gradient(linear, left bottom, left top, from(#e5e5e5), to(#fff));
1052
+ background-image: -webkit-linear-gradient(bottom, #e5e5e5, #fff);
1053
+ background-image: -moz-linear-gradient(bottom, #e5e5e5, #fff);
1054
+ background-image: -o-linear-gradient(bottom, #e5e5e5, #fff);
1055
+ background-image: linear-gradient(to top, #e5e5e5, #fff);
1056
+ }
1057
+
1058
+ .wp_themeSkin a.mceButton:active,
1059
+ .wp_themeSkin a.mceButtonEnabled:active,
1060
+ .wp_themeSkin a.mceButtonSelected:active,
1061
+ .wp_themeSkin a.mceButtonActive,
1062
+ .wp_themeSkin a.mceButtonActive:active,
1063
+ .wp_themeSkin a.mceButtonActive:hover,
1064
+ .wp_themeSkin .mceSplitButtonSelected table,
1065
+ .wp_themeSkin .mceSplitButtonSelected table:hover {
1066
+ outline: none;
1067
+ border-color: #999 #ccc #ccc #999;
1068
+ background: #eee;
1069
+ background-image: -webkit-gradient(linear, left bottom, left top, from(#f6f6f6), to(#e3e3e3));
1070
+ background-image: -webkit-linear-gradient(bottom, #f6f6f6, #e3e3e3);
1071
+ background-image: -moz-linear-gradient(bottom, #f6f6f6, #e3e3e3);
1072
+ background-image: -o-linear-gradient(bottom, #f6f6f6, #e3e3e3);
1073
+ background-image: linear-gradient(to top, #f6f6f6, #e3e3e3);
1074
+ }
1075
+
1076
+ .wp_themeSkin .mceSplitButtonSelected table a.mceOpen,
1077
+ .wp_themeSkin .mceSplitButtonSelected table a.mceAction {
1078
+ border-color: #999 #ccc #ccc #999;
1079
+ }
1080
+
1081
+ .wp_themeSkin .mceButtonDisabled {
1082
+ border-color: transparent;
1083
+ }
1084
+
1085
+ .wp_themeSkin .mceListBox .mceOpen {
1086
+ border-left: 0;
1087
+ }
1088
+
1089
+ .wp_themeSkin .mceListBoxEnabled:hover,
1090
+ .wp_themeSkin .mceListBoxEnabled:active,
1091
+ .wp_themeSkin .mceListBoxHover,
1092
+ .wp_themeSkin .mceListBoxHover:active,
1093
+ .wp_themeSkin .mceListBoxSelected {
1094
+ -webkit-box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .3);
1095
+ box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .3);
1096
+ border-color: #bbb;
1097
+ }
1098
+
1099
+ /* SplitButton */
1100
+ .wp_themeSkin .mceSplitButton .mceLast span.mceOpen .mceIconOnly {
1101
+ display: block;
1102
+ }
1103
+
1104
+ .wp_themeSkin .mceSplitButton a.mceAction,
1105
+ .wp_themeSkin .mceSplitButton a.mceOpen {
1106
+ border-color: transparent;
1107
+ }
1108
+
1109
+ .wp_themeSkin .mceSplitButton:hover a {
1110
+ border-color: #bbb;
1111
+ }
1112
+
1113
+ .wp_themeSkin .mceSplitButtonEnabled a.mceOpen,
1114
+ .wp_themeSkin .mceSplitButtonSelected a.mceOpen,
1115
+ .wp_themeSkin .mceSplitButtonActive a.mceOpen,
1116
+ .wp_themeSkin .mceSplitButtonEnabled:hover a.mceOpen {
1117
+ background-image: url("../../../../../wp-includes/images/down_arrow.gif");
1118
+ background-position: 1px 2px;
1119
+ background-repeat: no-repeat;
1120
+ border-left: 0;
1121
+ }
1122
+
1123
+ .wp_themeSkin .mceSplitButtonActive td {
1124
+ -webkit-border-radius: 3px;
1125
+ border-radius: 3px;
1126
+ }
1127
+
1128
+ .wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover {
1129
+ border-color: #0A246A;
1130
+ background-color: #B6BDD2;
1131
+ }
1132
+
1133
+ .wp_themeSkin a.mceMoreColors:hover {
1134
+ border-color: #0A246A;
1135
+ }
1136
+
1137
+ .wp_themeSkin .mceMenuItemDisabled .mceText {
1138
+ color: #888;
1139
+ }
1140
+
1141
+ #mceModalBlocker {
1142
+ background: #000;
1143
+ opacity: 0.7;
1144
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
1145
+ filter: alpha(opacity=70);
1146
+ }
1147
+
1148
+ /* WP specific */
1149
+ .wp-editor-wrap {
1150
+ position: relative;
1151
+ }
1152
+
1153
+ .wp-editor-tools {
1154
+ position: relative;
1155
+ z-index: 1;
1156
+ }
1157
+
1158
+ .wp-editor-container {
1159
+ clear: both;
1160
+ }
1161
+
1162
+ .wp-editor-area {
1163
+ font-family: Consolas, Monaco, monospace;
1164
+ font-size: 13px;
1165
+ padding: 10px;
1166
+ margin: 1px 0 0;
1167
+ line-height: 150%;
1168
+ border: 0 none;
1169
+ outline: none;
1170
+ display: block;
1171
+ resize: vertical;
1172
+ -moz-box-sizing: border-box;
1173
+ -webkit-box-sizing: border-box;
1174
+ box-sizing: border-box;
1175
+ }
1176
+
1177
+ .wp-editor-tools {
1178
+ padding: 0;
1179
+ }
1180
+
1181
+ .wp-editor-container textarea.wp-editor-area {
1182
+ width: 100%;
1183
+ margin: 0;
1184
+ -webkit-box-shadow: none;
1185
+ box-shadow: none;
1186
+ }
1187
+
1188
+ .quicktags-toolbar,
1189
+ .wp_themeSkin tr.mceFirst td.mceToolbar {
1190
+ border-bottom: 1px solid #dedede;
1191
+ background: #f5f5f5;
1192
+ }
1193
+
1194
+ .wp-editor-tabs {
1195
+ float: right;
1196
+ }
1197
+
1198
+ .wp-switch-editor {
1199
+ background: #ebebeb;
1200
+ border: 1px solid #dedede;
1201
+ color: #777;
1202
+ cursor: pointer;
1203
+ float: right;
1204
+ font: 13px/19px "Open Sans", sans-serif;
1205
+ height: 19px;
1206
+ margin: 5px 0 0 5px;
1207
+ padding: 3px 8px 4px;
1208
+ position: relative;
1209
+ top: 1px;
1210
+ }
1211
+
1212
+ .wp-switch-editor:active {
1213
+ background-color: #f1f1f1;
1214
+ }
1215
+
1216
+ .wp-switch-editor:hover {
1217
+ text-decoration: none !important;
1218
+ background: #fff;
1219
+ }
1220
+
1221
+ .js .tmce-active .wp-editor-area {
1222
+ color: white;
1223
+ }
1224
+
1225
+ .tmce-active .quicktags-toolbar {
1226
+ display: none;
1227
+ }
1228
+
1229
+ .tmce-active .switch-tmce,
1230
+ .html-active .switch-html {
1231
+ background: #f5f5f5;
1232
+ color: #555;
1233
+ height: 20px;
1234
+ border-bottom: none;
1235
+ }
1236
+
1237
+ .wp-media-buttons {
1238
+ float: left;
1239
+ }
1240
+
1241
+ .wp-media-buttons .button {
1242
+ margin-right: 5px;
1243
+ margin-bottom: 4px;
1244
+ padding-left: 7px;
1245
+ padding-right: 7px;
1246
+ }
1247
+
1248
+ .wp-media-buttons .button:active {
1249
+ position: relative;
1250
+ top: 1px;
1251
+ margin-top: -1px;
1252
+ margin-bottom: 1px;
1253
+ }
1254
+
1255
+ .wp-media-buttons .insert-media {
1256
+ padding-left: 5px;
1257
+ }
1258
+
1259
+ .wp-media-buttons a {
1260
+ text-decoration: none;
1261
+ color: #464646;
1262
+ font-size: 12px;
1263
+ }
1264
+
1265
+ .wp-media-buttons img {
1266
+ padding: 0 4px;
1267
+ vertical-align: middle;
1268
+ }
1269
+
1270
+ .wp-media-buttons span.wp-media-buttons-icon {
1271
+ display: inline-block;
1272
+ width: 18px;
1273
+ height: 18px;
1274
+ vertical-align: text-top;
1275
+ margin: 0 2px;
1276
+ }
1277
+
1278
+ .wp-media-buttons .add_media span.wp-media-buttons-icon {
1279
+ background: none;
1280
+ }
1281
+
1282
+ .wp-media-buttons .add_media span.wp-media-buttons-icon:before {
1283
+ font: normal 18px/1 'dashicons';
1284
+ speak: none;
1285
+ -webkit-font-smoothing: antialiased;
1286
+ -moz-osx-font-smoothing: grayscale;
1287
+ }
1288
+
1289
+ .wp-media-buttons .add_media span.wp-media-buttons-icon:before {
1290
+ content: '\f104';
1291
+ }
1292
+
1293
+ .quicktags-toolbar {
1294
+ border-bottom-style: solid;
1295
+ border-bottom-width: 1px;
1296
+ -webkit-border-top-right-radius: 3px;
1297
+ -webkit-border-top-left-radius: 3px;
1298
+ border-top-right-radius: 3px;
1299
+ border-top-left-radius: 3px;
1300
+ padding: 2px 8px 0;
1301
+ min-height: 29px;
1302
+ }
1303
+
1304
+ .quicktags-toolbar > div {
1305
+ padding: 2px 4px 0;
1306
+ }
1307
+
1308
+ .quicktags-toolbar input {
1309
+ margin: 2px 1px 4px;
1310
+ line-height: 18px;
1311
+ display: inline-block;
1312
+ min-width: 26px;
1313
+ padding: 2px 4px;
1314
+ font: 12px/18px "Open Sans", sans-serif;
1315
+ color: #464646;
1316
+ border: 1px solid #c3c3c3;
1317
+ -webkit-border-radius: 3px;
1318
+ border-radius: 3px;
1319
+ background: #eee;
1320
+ background-image: -webkit-gradient(linear, left bottom, left top, from(#e3e3e3), to(#fff));
1321
+ background-image: -webkit-linear-gradient(bottom, #e3e3e3, #fff);
1322
+ background-image: -moz-linear-gradient(bottom, #e3e3e3, #fff);
1323
+ background-image: -o-linear-gradient(bottom, #e3e3e3, #fff);
1324
+ background-image: linear-gradient(to top, #e3e3e3, #fff);
1325
+ }
1326
+
1327
+ .quicktags-toolbar input:hover {
1328
+ border-color: #aaa;
1329
+ background: #ddd;
1330
+ }
1331
+
1332
+ .quicktags-toolbar input[value="link"] {
1333
+ text-decoration: underline;
1334
+ }
1335
+
1336
+ .quicktags-toolbar input[value="del"] {
1337
+ text-decoration: line-through;
1338
+ }
1339
+
1340
+ .quicktags-toolbar input[value="i"] {
1341
+ font-style: italic;
1342
+ }
1343
+
1344
+ .quicktags-toolbar input[value="b"] {
1345
+ font-weight: bold;
1346
+ }
1347
+
1348
+ #wp_editbtns,
1349
+ #wp_gallerybtns {
1350
+ padding: 2px;
1351
+ position: absolute;
1352
+ display: none;
1353
+ z-index: 155000;
1354
+ }
1355
+
1356
+ #wp_editimgbtn,
1357
+ #wp_delimgbtn,
1358
+ #wp_editgallery,
1359
+ #wp_delgallery {
1360
+ border-color: #999;
1361
+ background-color: #eee;
1362
+ margin: 2px;
1363
+ padding: 2px;
1364
+ border-width: 1px;
1365
+ border-style: solid;
1366
+ -webkit-border-radius: 3px;
1367
+ border-radius: 3px;
1368
+ }
1369
+
1370
+ #wp_editimgbtn:hover,
1371
+ #wp_delimgbtn:hover,
1372
+ #wp_editgallery:hover,
1373
+ #wp_delgallery:hover {
1374
+ border-color: #555;
1375
+ background-color: #ccc;
1376
+ }
1377
+
1378
+ /*------------------------------------------------------------------------------
1379
+ wp-link
1380
+ ------------------------------------------------------------------------------*/
1381
+
1382
+ #wp-link {
1383
+ background-color: #F5F5F5;
1384
+ line-height: 1.4em;
1385
+ font-size: 12px;
1386
+ }
1387
+
1388
+ #wp-link ol,
1389
+ #wp-link ul {
1390
+ list-style: none;
1391
+ margin: 0;
1392
+ padding: 0;
1393
+ }
1394
+
1395
+ #wp-link input[type="text"] {
1396
+ -webkit-box-sizing: border-box;
1397
+ }
1398
+
1399
+ #wp-link input[type="text"],
1400
+ #wp-link textarea {
1401
+ border-width: 1px;
1402
+ border-style: solid;
1403
+ -webkit-border-radius: 4px;
1404
+ border-radius: 4px;
1405
+ font-size: 12px;
1406
+ margin: 1px;
1407
+ padding: 3px;
1408
+ }
1409
+
1410
+ #wp-link #link-options {
1411
+ padding: 10px 0 14px;
1412
+ border-bottom: 1px solid #dfdfdf;
1413
+ margin: 0 6px 14px;
1414
+ }
1415
+
1416
+ #wp-link p.howto {
1417
+ margin: 3px;
1418
+ }
1419
+
1420
+ #wp-link #internal-toggle {
1421
+ display: inline-block;
1422
+ cursor: pointer;
1423
+ padding-left: 18px;
1424
+ }
1425
+
1426
+ #wp-link .toggle-arrow {
1427
+ background: transparent url("../../../../../wp-includes/images/toggle-arrow.png") top left no-repeat;
1428
+ height: 23px;
1429
+ line-height: 23px;
1430
+ }
1431
+
1432
+ #wp-link .toggle-arrow-active {
1433
+ background-position: center left;
1434
+ }
1435
+
1436
+ #wp-link label input[type="text"] {
1437
+ width: 360px;
1438
+ margin-top: 5px;
1439
+ }
1440
+
1441
+ #wp-link #link-options label span,
1442
+ #wp-link #search-panel label span.search-label {
1443
+ display: inline-block;
1444
+ width: 80px;
1445
+ text-align: right;
1446
+ padding-right: 5px;
1447
+ }
1448
+
1449
+ #wp-link .link-search-field {
1450
+ float: left;
1451
+ width: 220px;
1452
+ }
1453
+
1454
+ #wp-link .link-search-wrapper {
1455
+ margin: 5px 6px 9px;
1456
+ display: block;
1457
+ overflow: hidden;
1458
+ }
1459
+
1460
+ #wp-link .link-search-wrapper span {
1461
+ float: left;
1462
+ margin-top: 4px;
1463
+ }
1464
+
1465
+ #wp-link .link-search-wrapper .spinner {
1466
+ display: none;
1467
+ vertical-align: text-bottom;
1468
+ }
1469
+
1470
+ #wp-link .link-target {
1471
+ width: auto;
1472
+ padding: 3px 0 0;
1473
+ margin: 0 0 0 87px;
1474
+ font-size: 11px;
1475
+ }
1476
+
1477
+ #wp-link .query-results {
1478
+ border: 1px #dfdfdf solid;
1479
+ margin: 0 5px 5px;
1480
+ background: #fff;
1481
+ height: 185px;
1482
+ overflow: auto;
1483
+ position: relative;
1484
+ }
1485
+
1486
+ #wp-link li,
1487
+ #wp-link .query-notice {
1488
+ clear: both;
1489
+ margin-bottom: 0;
1490
+ border-bottom: 1px solid #f1f1f1;
1491
+ color: #333;
1492
+ padding: 4px 6px;
1493
+ cursor: pointer;
1494
+ position: relative;
1495
+ }
1496
+
1497
+ #wp-link li:hover {
1498
+ background: #eaf2fa;
1499
+ color: #151515;
1500
+ }
1501
+
1502
+ #wp-link li.unselectable {
1503
+ border-bottom: 1px solid #dfdfdf;
1504
+ }
1505
+
1506
+ #wp-link li.unselectable:hover {
1507
+ background: #fff;
1508
+ cursor: auto;
1509
+ color: #333;
1510
+ }
1511
+
1512
+ #wp-link li.selected {
1513
+ background: #ddd;
1514
+ color: #333;
1515
+ }
1516
+
1517
+ #wp-link li.selected .item-title {
1518
+ font-weight: bold;
1519
+ }
1520
+
1521
+ #wp-link .item-title {
1522
+ display: inline-block;
1523
+ width: 80%;
1524
+ }
1525
+
1526
+ #wp-link .item-info {
1527
+ text-transform: uppercase;
1528
+ color: #666;
1529
+ font-size: 11px;
1530
+ position: absolute;
1531
+ right: 5px;
1532
+ top: 4px;
1533
+ bottom: 0;
1534
+ }
1535
+
1536
+ #wp-link #search-results {
1537
+ display: none;
1538
+ }
1539
+
1540
+ #wp-link #search-panel {
1541
+ float: left;
1542
+ width: 100%;
1543
+ }
1544
+
1545
+ #wp-link .river-waiting {
1546
+ display: none;
1547
+ padding: 10px 0;
1548
+ }
1549
+
1550
+ #wp-link .river-waiting .spinner {
1551
+ margin: 0 auto;
1552
+ display: block;
1553
+ }
1554
+
1555
+ #wp-link .submitbox {
1556
+ padding: 5px 10px;
1557
+ font-size: 11px;
1558
+ overflow: auto;
1559
+ height: 29px;
1560
+ }
1561
+
1562
+ #wp-link-cancel {
1563
+ line-height: 25px;
1564
+ float: left;
1565
+ }
1566
+
1567
+ #wp-link-update {
1568
+ line-height: 23px;
1569
+ float: right;
1570
+ }
1571
+
1572
+ /*!
1573
+ * jQuery UI CSS Framework 1.10.1
1574
+ * http://jqueryui.com
1575
+ *
1576
+ * Copyright 2013 jQuery Foundation and other contributors
1577
+ * Released under the MIT license.
1578
+ * http://jquery.org/license
1579
+ *
1580
+ * http://docs.jquery.com/UI/Theming/API
1581
+ */
1582
+
1583
+ /* Layout helpers
1584
+ ----------------------------------*/
1585
+ .ui-helper-hidden {
1586
+ display: none;
1587
+ }
1588
+ .ui-helper-hidden-accessible {
1589
+ border: 0;
1590
+ clip: rect(0 0 0 0);
1591
+ height: 1px;
1592
+ margin: -1px;
1593
+ overflow: hidden;
1594
+ padding: 0;
1595
+ position: absolute;
1596
+ width: 1px;
1597
+ }
1598
+ .ui-helper-reset {
1599
+ margin: 0;
1600
+ padding: 0;
1601
+ border: 0;
1602
+ outline: 0;
1603
+ line-height: 1.3;
1604
+ text-decoration: none;
1605
+ font-size: 100%;
1606
+ list-style: none;
1607
+ }
1608
+ .ui-helper-clearfix:before,
1609
+ .ui-helper-clearfix:after {
1610
+ content: "";
1611
+ display: table;
1612
+ border-collapse: collapse;
1613
+ }
1614
+ .ui-helper-clearfix:after {
1615
+ clear: both;
1616
+ }
1617
+ .ui-helper-clearfix {
1618
+ min-height: 0; /* support: IE7 */
1619
+ }
1620
+ .ui-helper-zfix {
1621
+ width: 100%;
1622
+ height: 100%;
1623
+ top: 0;
1624
+ left: 0;
1625
+ position: absolute;
1626
+ opacity: 0;
1627
+ filter:Alpha(Opacity=0);
1628
+ }
1629
+
1630
+ .ui-front {
1631
+ z-index: 100;
1632
+ }
1633
+
1634
+
1635
+ /* Interaction Cues
1636
+ ----------------------------------*/
1637
+ .ui-state-disabled {
1638
+ cursor: default !important;
1639
+ }
1640
+
1641
+
1642
+ /* Icons
1643
+ ----------------------------------*/
1644
+
1645
+ /* states and images */
1646
+ .ui-icon {
1647
+ display: block;
1648
+ text-indent: -99999px;
1649
+ overflow: hidden;
1650
+ background-repeat: no-repeat;
1651
+ }
1652
+
1653
+
1654
+ /* Misc visuals
1655
+ ----------------------------------*/
1656
+
1657
+ /* Overlays */
1658
+ .ui-widget-overlay {
1659
+ position: fixed;
1660
+ top: 0;
1661
+ left: 0;
1662
+ width: 100%;
1663
+ height: 100%;
1664
+ }
1665
+
1666
+
1667
+ /*!
1668
+ * jQuery UI Resizable 1.10.1
1669
+ * http://jqueryui.com
1670
+ *
1671
+ * Copyright 2013 jQuery Foundation and other contributors
1672
+ * Released under the MIT license.
1673
+ * http://jquery.org/license
1674
+ *
1675
+ * http://docs.jquery.com/UI/Resizable#theming
1676
+ */
1677
+ .ui-resizable {
1678
+ position: relative;
1679
+ }
1680
+ .ui-resizable-handle {
1681
+ position: absolute;
1682
+ font-size: 0.1px;
1683
+ display: block;
1684
+ }
1685
+ .ui-resizable-disabled .ui-resizable-handle,
1686
+ .ui-resizable-autohide .ui-resizable-handle {
1687
+ display: none;
1688
+ }
1689
+ .ui-resizable-n {
1690
+ cursor: n-resize;
1691
+ height: 7px;
1692
+ width: 100%;
1693
+ top: -5px;
1694
+ left: 0;
1695
+ }
1696
+ .ui-resizable-s {
1697
+ cursor: s-resize;
1698
+ height: 7px;
1699
+ width: 100%;
1700
+ bottom: -5px;
1701
+ left: 0;
1702
+ }
1703
+ .ui-resizable-e {
1704
+ cursor: e-resize;
1705
+ width: 7px;
1706
+ right: -5px;
1707
+ top: 0;
1708
+ height: 100%;
1709
+ }
1710
+ .ui-resizable-w {
1711
+ cursor: w-resize;
1712
+ width: 7px;
1713
+ left: -5px;
1714
+ top: 0;
1715
+ height: 100%;
1716
+ }
1717
+ .ui-resizable-se {
1718
+ cursor: se-resize;
1719
+ width: 12px;
1720
+ height: 12px;
1721
+ right: 1px;
1722
+ bottom: 1px;
1723
+ }
1724
+ .ui-resizable-sw {
1725
+ cursor: sw-resize;
1726
+ width: 9px;
1727
+ height: 9px;
1728
+ left: -5px;
1729
+ bottom: -5px;
1730
+ }
1731
+ .ui-resizable-nw {
1732
+ cursor: nw-resize;
1733
+ width: 9px;
1734
+ height: 9px;
1735
+ left: -5px;
1736
+ top: -5px;
1737
+ }
1738
+ .ui-resizable-ne {
1739
+ cursor: ne-resize;
1740
+ width: 9px;
1741
+ height: 9px;
1742
+ right: -5px;
1743
+ top: -5px;
1744
+ }
1745
+
1746
+ /*!
1747
+ * jQuery UI Dialog 1.10.1
1748
+ * http://jqueryui.com
1749
+ *
1750
+ * Copyright 2013 jQuery Foundation and other contributors
1751
+ * Released under the MIT license.
1752
+ * http://jquery.org/license
1753
+ *
1754
+ * http://docs.jquery.com/UI/Dialog#theming
1755
+ */
1756
+ .ui-dialog {
1757
+ position: absolute;
1758
+ top: 0;
1759
+ /* @noflip */
1760
+ left: 0;
1761
+ padding: .2em;
1762
+ outline: 0;
1763
+ }
1764
+ .ui-dialog .ui-dialog-titlebar {
1765
+ padding: .4em 1em;
1766
+ position: relative;
1767
+ }
1768
+ .ui-dialog .ui-dialog-title {
1769
+ float: left;
1770
+ margin: .1em 0;
1771
+ white-space: nowrap;
1772
+ width: 90%;
1773
+ overflow: hidden;
1774
+ text-overflow: ellipsis;
1775
+ }
1776
+ .ui-dialog .ui-dialog-titlebar-close {
1777
+ position: absolute;
1778
+ right: .3em;
1779
+ top: 50%;
1780
+ width: 21px;
1781
+ margin: -10px 0 0 0;
1782
+ padding: 1px;
1783
+ height: 20px;
1784
+ }
1785
+ .ui-dialog .ui-dialog-content {
1786
+ position: relative;
1787
+ border: 0;
1788
+ padding: .5em 1em;
1789
+ background: none;
1790
+ overflow: auto;
1791
+ }
1792
+ .ui-dialog .ui-dialog-buttonpane {
1793
+ text-align: left;
1794
+ border-width: 1px 0 0 0;
1795
+ background-image: none;
1796
+ margin-top: .5em;
1797
+ padding: .3em 1em .5em .4em;
1798
+ }
1799
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
1800
+ float: right;
1801
+ }
1802
+ .ui-dialog .ui-dialog-buttonpane button {
1803
+ margin: .5em .4em .5em 0;
1804
+ cursor: pointer;
1805
+ }
1806
+ .ui-dialog .ui-resizable-se {
1807
+ width: 12px;
1808
+ height: 12px;
1809
+ right: -5px;
1810
+ bottom: -5px;
1811
+ background-position: 16px 16px;
1812
+ }
1813
+ .ui-draggable .ui-dialog-titlebar {
1814
+ cursor: move;
1815
+ }
1816
+
1817
+ /* WP jQuery Dialog Theme */
1818
+ .wp-dialog {
1819
+ padding: 0;
1820
+ z-index: 300002;
1821
+ border: 0;
1822
+ -webkit-box-shadow: 0 5px 15px rgba(0,0,0,0.7);
1823
+ box-shadow: 0 5px 15px rgba(0,0,0,0.7);
1824
+ background-color: #f5f5f5;
1825
+ }
1826
+
1827
+ .wp-dialog .ui-dialog-title {
1828
+ display: block;
1829
+ text-align: center;
1830
+ padding: 0;
1831
+ }
1832
+
1833
+ .wp-dialog .ui-dialog-titlebar {
1834
+ padding: 0 1em;
1835
+ background-color: #444;
1836
+ font-size: 13px;
1837
+ line-height: 24px;
1838
+ color: #fff;
1839
+ }
1840
+
1841
+ .wp-dialog .ui-dialog-content {
1842
+ padding: 0;
1843
+ }
1844
+
1845
+ .wp-dialog .ui-dialog-titlebar-close {
1846
+ cursor: pointer;
1847
+ -webkit-appearance: none;
1848
+ border: 0;
1849
+ width: 30px;
1850
+ height: 20px;
1851
+ top: 13px;
1852
+ right: 6px;
1853
+ background: none;
1854
+ }
1855
+
1856
+ .wp-dialog .ui-dialog-titlebar-close:before {
1857
+ content: '\f158';
1858
+ font: normal 20px/1 'dashicons';
1859
+ speak: none;
1860
+ -webkit-font-smoothing: antialiased;
1861
+ -moz-osx-font-smoothing: grayscale;
1862
+ color: #999;
1863
+ padding-left: 12px;
1864
+ }
1865
+
1866
+ .wp-dialog .ui-dialog-titlebar-close:hover:before {
1867
+ color: #2ea2cc;
1868
+ }
1869
+
1870
+ .wp-dialog .ui-dialog-titlebar-close .ui-button-text {
1871
+ display: none;
1872
+ }
1873
+
1874
+ .wp-dialog .ui-dialog-titlebar-close:hover,
1875
+ .wp-dialog .ui-dialog-titlebar-close:focus {
1876
+ background-position: -87px -32px;
1877
+ }
1878
+
1879
+ .ui-widget-overlay {
1880
+ z-index: 300001;
1881
+ background-color: #000;
1882
+ opacity: 0.6;
1883
+ filter: alpha(opacity=60);
1884
+ }
1885
+
1886
+ /* TinyMCE modal */
1887
+ .clearlooks2 .mceTop {
1888
+ border-bottom: 1px solid #ccc;
1889
+ }
1890
+
1891
+ .clearlooks2 .mceTop span {
1892
+ font: 13px/24px "Open Sans", sans-serif;
1893
+ color: #e5e5e5;
1894
+ }
1895
+
1896
+ .clearlooks2 .mceTop .mceLeft {
1897
+ background: #444444;
1898
+ border-color: transparent;
1899
+ }
1900
+
1901
+ .clearlooks2 .mceTop .mceRight {
1902
+ background: #444444;
1903
+ border-color: transparent;
1904
+ }
1905
+
1906
+ .clearlooks2 .mceMiddle {
1907
+ clip: rect(24px auto auto auto);
1908
+ }
1909
+
1910
+ .clearlooks2 .mceMiddle .mceLeft {
1911
+ background: #f1f1f1;
1912
+ border-color: transparent;
1913
+ }
1914
+
1915
+ .clearlooks2 .mceMiddle .mceRight {
1916
+ background: #f1f1f1;
1917
+ border-color: transparent;
1918
+ }
1919
+
1920
+ .clearlooks2 .mceBottom {
1921
+ background: #f1f1f1;
1922
+ border-color: transparent;
1923
+ }
1924
+
1925
+ .clearlooks2 .mceBottom .mceLeft {
1926
+ background: #f1f1f1;
1927
+ border-color: transparent;
1928
+ }
1929
+
1930
+ .clearlooks2 .mceBottom .mceCenter {
1931
+ background: #f1f1f1;
1932
+ border-color: transparent;
1933
+ }
1934
+
1935
+ .clearlooks2 .mceBottom .mceRight {
1936
+ background: #f1f1f1;
1937
+ border-color: transparent;
1938
+ }
1939
+
1940
+ .clearlooks2 .mceClose,
1941
+ .clearlooks2 .mceFocus .mceClose,
1942
+ .clearlooks2 .mceFocus .mceClose:hover {
1943
+ background-image: none;
1944
+ }
1945
+ .clearlooks2 .mceClose:before {
1946
+ speak: none;
1947
+ -webkit-font-smoothing: antialiased;
1948
+ -moz-osx-font-smoothing: grayscale;
1949
+ color: #999;
1950
+ padding-left: 12px;
1951
+ }
1952
+
1953
+ /* Distraction Free Writing mode
1954
+ * =Overlay Styles
1955
+ -------------------------------------------------------------- */
1956
+ .fullscreen-overlay {
1957
+ z-index: 149999;
1958
+ display: none;
1959
+ position: fixed;
1960
+ top: 0;
1961
+ bottom: 0;
1962
+ left: 0;
1963
+ right: 0;
1964
+ filter: inherit;
1965
+ }
1966
+
1967
+ .fullscreen-active .fullscreen-overlay,
1968
+ .fullscreen-active #wp-fullscreen-body {
1969
+ display: block;
1970
+ }
1971
+
1972
+ .fullscreen-fader {
1973
+ z-index: 200000;
1974
+ }
1975
+
1976
+ .fullscreen-active .fullscreen-fader {
1977
+ display: none;
1978
+ }
1979
+
1980
+ /* =Overlay Body
1981
+ -------------------------------------------------------------- */
1982
+ #wp-fullscreen-body {
1983
+ width: 100%;
1984
+ z-index: 150005;
1985
+ display: none;
1986
+ position: absolute;
1987
+ top: 0;
1988
+ left: 0;
1989
+ font-size: 12px;
1990
+ }
1991
+
1992
+ #wp-fullscreen-wrap {
1993
+ margin: 0 auto 50px;
1994
+ position: relative;
1995
+ padding-top: 60px;
1996
+ }
1997
+
1998
+ #wp-fullscreen-title {
1999
+ font-size: 1.7em;
2000
+ line-height: 100%;
2001
+ outline: medium none;
2002
+ padding: 6px 7px;
2003
+ width: 100%;
2004
+ margin-bottom: 30px;
2005
+ -webkit-box-shadow: none;
2006
+ box-shadow: none;
2007
+ }
2008
+
2009
+ #wp-fullscreen-container {
2010
+ padding: 4px 10px 50px;
2011
+ }
2012
+
2013
+ #wp-fullscreen-title,
2014
+ #wp-fullscreen-container {
2015
+ -webkit-border-radius: 0;
2016
+ border-radius: 0;
2017
+ border: 1px dashed transparent;
2018
+ background: transparent;
2019
+ -moz-transition-property: border-color;
2020
+ -moz-transition-duration: 0.6s;
2021
+ -webkit-transition-property: border-color;
2022
+ -webkit-transition-duration: 0.6s;
2023
+ -o-transition-property: border-color;
2024
+ -o-transition-duration: 0.6s;
2025
+ transition-property: border-color;
2026
+ transition-duration: 0.6s;
2027
+ }
2028
+
2029
+ #wp_mce_fullscreen {
2030
+ width: 100%;
2031
+ min-height: 300px;
2032
+ border: 0;
2033
+ background: transparent;
2034
+ font-family: Consolas, Monaco, monospace;
2035
+ line-height: 1.6em;
2036
+ padding: 0;
2037
+ overflow-y: hidden;
2038
+ outline: none;
2039
+ resize: none;
2040
+ -webkit-box-shadow: none;
2041
+ box-shadow: none;
2042
+ }
2043
+
2044
+ #wp-fullscreen-tagline {
2045
+ color: #BBBBBB;
2046
+ font-size: 18px;
2047
+ float: right;
2048
+ padding-top: 5px;
2049
+ }
2050
+
2051
+ /* =Top bar
2052
+ -------------------------------------------------------------- */
2053
+ #fullscreen-topbar {
2054
+ background: #f5f5f5;
2055
+ border-bottom: 1px solid #fff;
2056
+ height: 40px;
2057
+ left: 0;
2058
+ min-width: 800px;
2059
+ position: fixed;
2060
+ top: 0;
2061
+ width: 100%;
2062
+ z-index: 150050;
2063
+ }
2064
+
2065
+ #wp-fullscreen-toolbar {
2066
+ padding: 6px 10px 0;
2067
+ clear: both;
2068
+ max-width: 1100px;
2069
+ min-width: 820px;
2070
+ margin: 0 auto;
2071
+ }
2072
+
2073
+ #wp-fullscreen-mode-bar,
2074
+ #wp-fullscreen-button-bar,
2075
+ #wp-fullscreen-close,
2076
+ #wp-fullscreen-count {
2077
+ float: left;
2078
+ }
2079
+
2080
+ #wp-fullscreen-save {
2081
+ float: right;
2082
+ padding: 2px 2px 0 5px;
2083
+ }
2084
+
2085
+ #wp-fullscreen-count,
2086
+ #wp-fullscreen-close {
2087
+ padding-top: 5px;
2088
+ }
2089
+
2090
+ #wp-fullscreen-central-toolbar {
2091
+ margin: auto;
2092
+ padding: 0;
2093
+ }
2094
+
2095
+ #wp-fullscreen-buttons > div {
2096
+ float: left;
2097
+ }
2098
+
2099
+ #wp-fullscreen-mode-bar {
2100
+ padding: 1px 14px 0 0;
2101
+ }
2102
+
2103
+ #wp-fullscreen-modes a {
2104
+ display: block;
2105
+ font-size: 11px;
2106
+ text-decoration: none;
2107
+ float: left;
2108
+ margin: 1px 0 0 0;
2109
+ padding: 2px 6px 2px;
2110
+ border-width: 1px 1px 1px 0;
2111
+ border-style: solid;
2112
+ border-color: #bbb;
2113
+ color: #777;
2114
+ text-shadow: 0 1px 0 #fff;
2115
+ background-color: #f4f4f4;
2116
+ background: #f4f4f4;
2117
+ background-image: -webkit-gradient(linear, left bottom, left top, from(#e4e4e4), to(#f9f9f9));
2118
+ background-image: -webkit-linear-gradient(bottom, #e4e4e4, #f9f9f9);
2119
+ background-image: -moz-linear-gradient(bottom, #e4e4e4, #f9f9f9);
2120
+ background-image: -o-linear-gradient(bottom, #e4e4e4, #f9f9f9);
2121
+ background-image: linear-gradient(to top, #e4e4e4, #f9f9f9);
2122
+ }
2123
+
2124
+ #wp-fullscreen-modes a:hover,
2125
+ .wp-html-mode #wp-fullscreen-modes a:last-child,
2126
+ .wp-tmce-mode #wp-fullscreen-modes a:first-child {
2127
+ color: #333;
2128
+ border-color: #999;
2129
+ background: #eee;
2130
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#e4e4e4), to(#f9f9f9));
2131
+ background-image: -webkit-linear-gradient(top, #e4e4e4, #f9f9f9);
2132
+ background-image: -moz-linear-gradient(top, #e4e4e4, #f9f9f9);
2133
+ background-image: -o-linear-gradient(top, #e4e4e4, #f9f9f9);
2134
+ background-image: linear-gradient(to bottom, #e4e4e4, #f9f9f9);
2135
+ }
2136
+
2137
+ #wp-fullscreen-modes a:first-child {
2138
+ border-width: 1px;
2139
+ -webkit-border-top-left-radius: 3px;
2140
+ -webkit-border-bottom-left-radius: 3px;
2141
+ border-top-left-radius: 3px;
2142
+ border-bottom-left-radius: 3px;
2143
+ }
2144
+
2145
+ #wp-fullscreen-modes a:last-child {
2146
+ -webkit-border-top-right-radius: 3px;
2147
+ -webkit-border-bottom-right-radius: 3px;
2148
+ border-top-right-radius: 3px;
2149
+ border-bottom-right-radius: 3px;
2150
+ }
2151
+
2152
+ #wp-fullscreen-buttons .active a {
2153
+ background: inherit;
2154
+ }
2155
+
2156
+ #wp-fullscreen-buttons .hidden {
2157
+ display: none;
2158
+ }
2159
+
2160
+ #wp-fullscreen-buttons .disabled {
2161
+ opacity: 0.5;
2162
+ }
2163
+
2164
+ .wp-html-mode #wp-fullscreen-buttons div {
2165
+ display: none;
2166
+ }
2167
+
2168
+ .wp-html-mode #wp-fullscreen-buttons div.wp-fullscreen-both {
2169
+ display: block;
2170
+ }
2171
+
2172
+ #fullscreen-topbar.fullscreen-make-sticky {
2173
+ display: block !important;
2174
+ }
2175
+
2176
+ #wp-fullscreen-save img {
2177
+ vertical-align: middle;
2178
+ }
2179
+
2180
+ #wp-fullscreen-save img,
2181
+ #wp-fullscreen-save span {
2182
+ padding-right: 4px;
2183
+ display: none;
2184
+ }
2185
+
2186
+ /* =Thickbox Adjustments
2187
+ -------------------------------------------------------------- */
2188
+ .fullscreen-active #TB_overlay {
2189
+ z-index: 150100;
2190
+ }
2191
+
2192
+ .fullscreen-active #TB_window {
2193
+ z-index: 150102;
2194
+ }
2195
+
2196
+ /* =TinyMCE Adjustments
2197
+ -------------------------------------------------------------- */
2198
+ #wp_mce_fullscreen_ifr {
2199
+ background: transparent;
2200
+ }
2201
+
2202
+ #wp_mce_fullscreen_parent #wp_mce_fullscreen_tbl tr.mceFirst {
2203
+ display : none;
2204
+ }
2205
+
2206
+ #wp-fullscreen-container .wp_themeSkin table td {
2207
+ vertical-align: top;
2208
+ }
2209
+
2210
+ /* Colors */
2211
+ .fullscreen-overlay {
2212
+ background: #fff;
2213
+ }
2214
+
2215
+ .wp-fullscreen-focus #wp-fullscreen-title,
2216
+ .wp-fullscreen-focus #wp-fullscreen-container {
2217
+ border-color: #ccc;
2218
+ }
2219
+
2220
+ /* =CSS 3 transitions
2221
+ -------------------------------------------------------------- */
2222
+
2223
+ .fade-1000,
2224
+ .fade-600,
2225
+ .fade-400,
2226
+ .fade-300 {
2227
+ opacity: 0;
2228
+ -moz-transition-property: opacity;
2229
+ -webkit-transition-property: opacity;
2230
+ -o-transition-property: opacity;
2231
+ transition-property: opacity;
2232
+ }
2233
+
2234
+ .fade-1000 {
2235
+ -moz-transition-duration: 1s;
2236
+ -webkit-transition-duration: 1s;
2237
+ -o-transition-duration: 1s;
2238
+ transition-duration: 1s;
2239
+ }
2240
+
2241
+ .fade-600 {
2242
+ -moz-transition-duration: 0.6s;
2243
+ -webkit-transition-duration: 0.6s;
2244
+ -o-transition-duration: 0.6s;
2245
+ transition-duration: 0.6s;
2246
+ }
2247
+
2248
+ .fade-400 {
2249
+ -moz-transition-duration: 0.4s;
2250
+ -webkit-transition-duration: 0.4s;
2251
+ -o-transition-duration: 0.4s;
2252
+ transition-duration: 0.4s;
2253
+ }
2254
+
2255
+ .fade-300 {
2256
+ -moz-transition-duration: 0.3s;
2257
+ -webkit-transition-duration: 0.3s;
2258
+ -o-transition-duration: 0.3s;
2259
+ transition-duration: 0.3s;
2260
+ }
2261
+
2262
+ .fade-trigger {
2263
+ opacity: 1;
2264
+ }
2265
+
2266
+ /* =Localization
2267
+ -------------------------------------------------------------- */
2268
+ .rtl .wp_themeSkin .mceColorSplitMenu a.mceMoreColors,
2269
+ .rtl .wp_themeSkin .mceMenu .mceText,
2270
+ .rtl .wp-switch-editor,
2271
+ .rtl .quicktags-toolbar input,
2272
+ .rtl .clearlooks2 .mceTop span,
2273
+ .rtl .wp_themeSkin .mceColorSplitMenu a.mceMoreColors {
2274
+ font-family: Tahoma, sans-serif;
2275
+ }
2276
+
2277
+ html:lang(he-il) .rtl .wp_themeSkin .mceColorSplitMenu a.mceMoreColors,
2278
+ html:lang(he-il) .rtl .wp_themeSkin .mceMenu .mceText,
2279
+ html:lang(he-il) .rtl .wp-switch-editor,
2280
+ html:lang(he-il) .rtl .quicktags-toolbar input,
2281
+ html:lang(he-il) .rtl .clearlooks2 .mceTop span,
2282
+ html:lang(he-il) .rtl .wp_themeSkin .mceColorSplitMenu a.mceMoreColors {
2283
+ font-family: Arial, sans-serif;
2284
+ }
2285
+
2286
+
2287
+ /* HiDPI */
2288
+ @media print,
2289
+ (-o-min-device-pixel-ratio: 5/4),
2290
+ (-webkit-min-device-pixel-ratio: 1.25),
2291
+ (min-resolution: 120dpi) {
2292
+ .wp-media-buttons .add_media span.wp-media-buttons-icon,
2293
+ #wp-fullscreen-buttons #wp_fs_image span.mce_image {
2294
+ background: none;
2295
+ }
2296
+
2297
+ .wp_themeSkin .mceListBox .mceOpen,
2298
+ .wp_themeSkin .mceListBoxHover .mceOpen,
2299
+ .wp_themeSkin .mceListBoxSelected .mceOpen,
2300
+ .wp_themeSkin table.mceListBoxEnabled .mceOpen {
2301
+ background-image: url('../../../../../wp-includes/images/down_arrow-2x.gif');
2302
+ background-size: 10px 20px;
2303
+ }
2304
+
2305
+ .wp_themeSkin .mceSplitButtonEnabled a.mceOpen,
2306
+ .wp_themeSkin .mceSplitButtonSelected a.mceOpen,
2307
+ .wp_themeSkin .mceSplitButtonActive a.mceOpen,
2308
+ .wp_themeSkin .mceSplitButtonEnabled:hover a.mceOpen {
2309
+ background-image: url('../../../../../wp-includes/images/down_arrow-2x.gif');
2310
+ background-size: 10px 20px;
2311
+ }
2312
+
2313
+ #wp-link .toggle-arrow {
2314
+ background: transparent url('../../../../../wp-includes/images/toggle-arrow-2x.png') top left no-repeat;
2315
+ background-size: 19px 69px;
2316
+ }
2317
+ }
trunk/css/tmce/index.html ADDED
File without changes
trunk/css/tmce/panelbtns.css ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #wp_wysijaregister {
2
+ display: none;
3
+ padding: 2px;
4
+ position: absolute;
5
+ z-index: 999998;
6
+ }
7
+
8
+ #wp_edit_wysinl_btn:hover, #wp_del_wysinl_btn:hover {
9
+ background-color: #CCCCCC;
10
+ border-color: #555555;
11
+ cursor:pointer;
12
+ }
13
+
14
+ #wp_edit_wysinl_btn, #wp_del_wysinl_btn {
15
+ background-color: #EEEEEE;
16
+ border-color: #999999;
17
+ border-radius: 3px 3px 3px 3px;
18
+ border-style: solid;
19
+ border-width: 1px;
20
+ margin: 2px;
21
+ padding: 2px;
22
+ }
23
+
trunk/css/tmce/style.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ .clear{clear:both;}
2
+ .wysija-register{
3
+ text-indent:-9999px;
4
+ background:url("../../img/nl-placeholder.png") no-repeat scroll center top transparent;
5
+ width:188px;
6
+ height:70px;
7
+ }
trunk/css/tmce/subscribers_count.css ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #widget-form{
2
+ width: 180px;
3
+ float:left;
4
+ margin: 5px;
5
+ padding: 20px;
6
+ }
7
+
8
+ body,html{
9
+ margin:0 !important;
10
+ overflow: hidden;
11
+ font-family: sans-serif;
12
+ font-size: 12px !important;
13
+ line-height: 1.4em;
14
+ }
15
+
16
+ #formTable{
17
+ padding-top: 10px;
18
+ }
19
+
20
+ .wysija-widget-form .divblocks {
21
+ margin:0 0 10px 0;
22
+ }
23
+
24
+ .wysija-widget-form .divblocks div {
25
+ margin:0 0 5px 0;
26
+ }
27
+ .wysija-widget-form .divblocks select {
28
+ margin:0 !important;
29
+ }
30
+
31
+ .wysija-widget-form{
32
+ margin-bottom: 10px;
33
+ }
34
+
35
+ #widget-form select {
36
+ width:180px;
37
+ }
trunk/css/tmce/widget.css ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #widget-form{
2
+ width: 180px;
3
+ float:left;
4
+ margin: 5px;
5
+ padding: 20px;
6
+ }
7
+
8
+ #subscriber-ccount-form{
9
+ width: 450px;
10
+ float:left;
11
+ margin: 5px;
12
+ padding: 20px;
13
+ }
14
+
15
+ body,html{
16
+ margin:0 !important;
17
+ overflow: hidden;
18
+ font-family: sans-serif;
19
+ font-size: 12px !important;
20
+ line-height: 1.4em;
21
+ }
22
+
23
+ #formTable{
24
+ padding-top: 10px;
25
+ }
26
+
27
+ .wysija-widget-form .divblocks {
28
+ margin:0 0 10px 0;
29
+ }
30
+
31
+ .wysija-widget-form .divblocks div {
32
+ margin:0 0 5px 0;
33
+ }
34
+ .wysija-widget-form .divblocks select {
35
+ margin:0 !important;
36
+ }
37
+
38
+ .wysija-widget-form{
39
+ margin-bottom: 10px;
40
+ }
41
+
42
+ #widget-form select {
43
+ width:180px;
44
+ }
trunk/css/validationEngine.jquery.css ADDED
@@ -0,0 +1 @@
 
1
+ .widget_wysija_cont .inputContainer{position:relative;float:left}.widget_wysija_cont .ajaxSubmit{padding:20px;background:#55ea55;border:1px solid #999;display:none}.formError{position:absolute;top:300px;left:300px;display:block;z-index:5000;cursor:pointer}.formError .formErrorContent{background:none repeat scroll 0 0 #8E2121;border:1px solid #BBBBBB;color:#FFFFFF;font-family:tahoma;font-size:11px;padding:4px 10px;position:relative;width:150px;z-index:5001}.widget_wysija_cont .formError .formErrorArrow{width:15px;margin:-2px 0 0 13px;position:relative;z-index:5006}.widget_wysija_cont .formError .formErrorArrowBottom{margin:0px 0 0 12px;top:2px}.widget_wysija_cont .formError .formErrorArrow div{border-left:2px solid #ddd;border-right:2px solid #ddd;font-size:0px;height:1px;background:#8E2121;margin:0 auto;line-height:0;font-size:0;display:block}.widget_wysija_cont .greenPopup .formErrorArrow div{background:#33be40}.widget_wysija_cont .blackPopup .formErrorArrow div{background:#393939;color:#FFF}.widget_wysija_cont .formError .formErrorArrow .line10{width:15px;border:none}.widget_wysija_cont .formError .formErrorArrow .line9{width:13px;border:none}.widget_wysija_cont .formError .formErrorArrow .line8{width:11px}.widget_wysija_cont .formError .formErrorArrow .line7{width:9px}.widget_wysija_cont .formError .formErrorArrow .line6{width:7px}.widget_wysija_cont .formError .formErrorArrow .line5{width:5px}.widget_wysija_cont .formError .formErrorArrow .line4{width:3px}.widget_wysija_cont .formError .formErrorArrow .line3{width:1px;border-left:2px solid #ddd;border-right:2px solid #ddd;border-bottom:0 solid #ddd}.widget_wysija_cont .formError .formErrorArrow .line2{width:3px;border:none;background:#ddd}.widget_wysija_cont .formError .formErrorArrow .line1{width:1px;border:none;background:#ddd}.greenPopup .formErrorContent{background:none repeat scroll 0 0 #FFFBCC;color:#555555}.widget_wysija_cont .updated,.widget_wysija_cont .error,.widget_wysija_cont .xdetailed-errors{margin:5px 0 15px;color:#333333;font-family:sans-serif;font-size:12px;line-height:1.4em}.widget_wysija_cont .error,.widget_wysija_cont .login #login_error{background-color:#FFEBE8;border-color:#CC0000}.widget_wysija_cont .updated,.widget_wysija_cont .error,.widget_wysija_cont .xdetailed-errors{border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-style:solid;border-width:1px;margin:5px 15px 2px;padding:0 0.6em;color:#333333}.widget_wysija_cont.updated,.widget_wysija_cont .login .message{background-color:#FFFFE0;border-color:#E6DB55}.widget_wysija_cont .xdetailed-updated{background-color:#FFFFE0;border-color:#E6DB55;color:#000;font-weight:bold;display:none}.widget_wysija_cont .xdetailed-errors{background-color:#A50000;border-color:#888888;color:#DDDDDD;font-weight:bold;display:none}.widget_wysija_cont .instruct{font-style:italic;font-weight:bold;padding:5px 0;font-size:11px}.widget_wysija_cont .needInfo{padding-left:15px;text-decoration:underline}.widget_wysija_cont .wysija-submit{display:block;margin-top:20px}.widget_wysija_cont input.defaultlabels{color:#888}.widget_wysija_cont input.defaultlabels:focus{color:#373737}.widget_wysija_cont .abs-req{display:none}.widget_wysija_cont p label{display:block}.widget_wysija_cont .iframe-hidden{display:none}.widget_wysija_cont .updated,.widget_wysija_cont .error,.widget_wysija_cont .xdetailed-errors{background-color:#FFFFFF;border:1px solid;border-radius:0 0 0 0;font-weight:normal;margin:4px 0;padding:4px}.widget_wysija_cont .error,.widget_wysija_cont .xdetailed-errors{background-color:#e55057;color:#fff}.widget_wysija_cont .error,.widget_wysija_cont .xdetailed-errors{background-color:#e55057;color:#fff;border-color:#CC0000}.widget_wysija_cont .allmsgs ul{padding:0}.widget_wysija_cont .allmsgs li{list-style-type:none}.widget_wysija_cont .updated,.widget_wysija_cont .login .message{background-color:#FFFFE0;border-color:#E6DB55}.widget_wysija_cont .updated ul{margin:0}.widget_wysija_cont .showerrors{color:#DDDDDD}#wysija-subscriptions input.checkboxx{margin-left:0px;margin-right:10px}#wysija-subscriptions th label{margin-right:10px}#wysija-box-after-comment{width:25px}#wysija-box-after-register{margin:0 6px 0 0;padding:3px}.wysija-after-register{padding-bottom:10px}.wysija-unsubscribed-on{color:#bbb}.widget_wysija .wysija-required{font-weight:bold}.widget_wysija .wysija-radio-label,.widget_wysija .wysija-checkbox-label{margin:0 0 5px 0;cursor:pointer}.widget_wysija .wysija-radio,.widget_wysija .wysija-checkbox{margin:0 5px 0 0;vertical-align:middle}.xdetailed-errors,.xdetailed-updated{display:none}.widget_wysija_cont .allmsgs .updated{display:block !important}
trunk/css/vendor/bootstrap.tooltip.css ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .tooltip {
2
+ position: absolute;
3
+ z-index: 1030;
4
+ display: block;
5
+ visibility: visible;
6
+ font-size: 12px;
7
+ line-height: 1.4;
8
+ opacity: 0;
9
+ filter: alpha(opacity=0);
10
+ }
11
+ .tooltip.in {
12
+ opacity: 0.9;
13
+ filter: alpha(opacity=90);
14
+ }
15
+ .tooltip.top {
16
+ margin-top: -3px;
17
+ padding: 5px 0;
18
+ }
19
+ .tooltip.right {
20
+ margin-left: 3px;
21
+ padding: 0 5px;
22
+ }
23
+ .tooltip.bottom {
24
+ margin-top: 3px;
25
+ padding: 5px 0;
26
+ }
27
+ .tooltip.left {
28
+ margin-left: -3px;
29
+ padding: 0 5px;
30
+ }
31
+ .tooltip-inner {
32
+ max-width: 200px;
33
+ padding: 3px 8px;
34
+ color: #ffffff;
35
+ text-align: center;
36
+ text-decoration: none;
37
+ background-color: #000000;
38
+ border-radius: 4px;
39
+ }
40
+ .tooltip-inner a {
41
+ color: #fff;
42
+ }
43
+ .tooltip-arrow {
44
+ position: absolute;
45
+ width: 0;
46
+ height: 0;
47
+ border-color: transparent;
48
+ border-style: solid;
49
+ }
50
+ .tooltip.top .tooltip-arrow {
51
+ bottom: 0;
52
+ left: 50%;
53
+ margin-left: -5px;
54
+ border-width: 5px 5px 0;
55
+ border-top-color: #000000;
56
+ }
57
+ .tooltip.top-left .tooltip-arrow {
58
+ bottom: 0;
59
+ left: 5px;
60
+ border-width: 5px 5px 0;
61
+ border-top-color: #000000;
62
+ }
63
+ .tooltip.top-right .tooltip-arrow {
64
+ bottom: 0;
65
+ right: 5px;
66
+ border-width: 5px 5px 0;
67
+ border-top-color: #000000;
68
+ }
69
+ .tooltip.right .tooltip-arrow {
70
+ top: 50%;
71
+ left: 0;
72
+ margin-top: -5px;
73
+ border-width: 5px 5px 5px 0;
74
+ border-right-color: #000000;
75
+ }
76
+ .tooltip.left .tooltip-arrow {
77
+ top: 50%;
78
+ right: 0;
79
+ margin-top: -5px;
80
+ border-width: 5px 0 5px 5px;
81
+ border-left-color: #000000;
82
+ }
83
+ .tooltip.bottom .tooltip-arrow {
84
+ top: 0;
85
+ left: 50%;
86
+ margin-left: -5px;
87
+ border-width: 0 5px 5px;
88
+ border-bottom-color: #000000;
89
+ }
90
+ .tooltip.bottom-left .tooltip-arrow {
91
+ top: 0;
92
+ left: 5px;
93
+ border-width: 0 5px 5px;
94
+ border-bottom-color: #000000;
95
+ }
96
+ .tooltip.bottom-right .tooltip-arrow {
97
+ top: 0;
98
+ right: 5px;
99
+ border-width: 0 5px 5px;
100
+ border-bottom-color: #000000;
101
+ }
trunk/css/wysija-editor.css ADDED
@@ -0,0 +1 @@
 
1
+ .clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}.clearfix{display:inline-table}* html .clearfix{height:1%}.clearfix{display:block}.hidden{display:none}strong{font-weight:bold}img{vertical-align:middle}:focus{outline:0 !important}.inline{display:-moz-inline-box;display:inline-block;*display:inline;*float:left}.wysija_tools li,.wysija_tools dd{margin:0 !important}.wysija_controls li{margin:0 0 0 3px !important}#wysija_items{position:fixed;width:275px;right:20px;top:20px;z-index:999}#wysija_items li{line-height:100px;height:100px;outline:1px solid #ccc;text-align:center}.wysija_items li.disabled{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20);-moz-opacity:0.2;opacity:0.2}.wysija_items li.active a{height:100px;cursor:pointer;display:block}.wysija_header,.wysija_footer{position:relative;display:inline-table;display:block;height:1%;margin:0;padding:0;z-index:98}.wysija_header:after,.wysija_footer:after{content:".";display:block;height:0;clear:both;visibility:hidden}.wysija_block{position:relative;margin:0 10px;padding:10px 18px 10px 18px;display:inline-table;display:block;height:1%;margin:0;z-index:98}.wysija_block.dragging,.wysija_header.dragging,.wysija_footer.dragging{z-index:99000}.wysija_block:after{content:".";display:block;height:0;clear:both;visibility:hidden}.wysija_block.hover{border:1px dashed #bbb;margin:0 0 0 0;padding:9px 17px 9px 17px}.wysija_block.static{padding:0;margin:0}.wysija_block .wysija_controls{background-color:#dfdfdf;background-image:-moz-linear-gradient(center bottom, #bbb, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#bbbbbb');background:-webkit-gradient(linear, left bottom, left top, from(#bbb), to(#eee));-moz-border-radius:2px;-webkit-border-radius:2px;-khtml-border-radius:2px;border-radius:2px;border:1px solid #ccc;position:absolute;margin:0;padding:0;width:598px;height:20px;left:-1px;right:0;top:-22px;width:100%}.wysija_block .wysija_controls .handle{width:600px}.wysija_block .wysija_controls li{float:left;width:20px;height:20px}.wysija_block .wysija_controls a{cursor:pointer;float:left;font-size:120%;font-weight:bold;height:20px;line-height:20px;text-align:center;width:20px;color:#000}.wysija_block .handle_container,.wysija_block .handle_container a{float:none;width:40px}.wysija_block .handle_container{left:280px;top:0;position:absolute}.wysija_gallery .wysija_tools,.wysija_image .wysija_tools{position:absolute;height:34px;line-height:34px;margin:0;width:152px;top:-36px;z-index:1010;background-color:#dfdfdf;background-image:-moz-linear-gradient(center bottom, #bbb, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#bbbbbb');background:-webkit-gradient(linear, left bottom, left top, from(#bbb), to(#eee));-moz-border-radius:2px;-webkit-border-radius:2px;-khtml-border-radius:2px;border-radius:2px;border:1px solid #ccc;padding:0 0 0 5px}.wysija_gallery .wysija_tools{width:102px}.left .wysija_image .wysija_tools,.center .wysija_image .wysija_tools,.left.wysija_gallery .wysija_tools,.center.wysija_gallery .wysija_tools{left:0;text-align:left}.right .wysija_image .wysija_tools,.right.wysija_gallery .wysija_tools{right:0;text-align:right}.wysija_text .wysija_tools{position:absolute;height:20px;line-height:20px;top:0;right:0;margin:0;z-index:1000;width:20px}.wysija_text.alone .wysija_tools{display:none}.wysija_gallery .wysija_tools li,.wysija_image .wysija_tools li{float:left;width:25px;height:34px}.wysija_text .wysija_tools li{float:left;width:20px;height:20px}.wysija_gallery .wysija_tools a,.wysija_image .wysija_tools a,.wysija_text .wysija_tools a{background-color:#dfdfdf;background-image:-moz-linear-gradient(center bottom, #bbb, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#bbbbbb');background:-webkit-gradient(linear, left bottom, left top, from(#bbb), to(#eee));float:left;width:20px;height:20px;margin:5px 3px 0 0;-moz-border-radius:2px;-webkit-border-radius:2px;-khtml-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.15),inset 0 0 2px 1px #fff;-moz-box-shadow:0 1px 0 rgba(0,0,0,0.15),inset 0 0 2px 1px #fff;box-shadow:0 1px 0 rgba(0,0,0,0.15),inset 0 0 2px 1px #fff;border:1px solid #ccc;z-index:1010;position:relative}.wysija_text .wysija_tools a{margin:0}.wysija_gallery .wysija_tools a:hover,.wysija_image .wysija_tools a:hover,.wysija_text .wysija_tools a:hover{background-color:#ddd;border-color:#909090}.wysija_gallery .wysija_tools a.active,.wysija_image .wysija_tools a.active,.wysija_text .wysija_tools a.active{background-color:#ddd;background-image:-moz-linear-gradient(center bottom, #eee, #bbb);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#bbbbbb');background:-webkit-gradient(linear, left bottom, left top, from(#eee), to(#bbb));border-color:#909090}.wysija_controls a span,.wysija_gallery .wysija_tools a span,.wysija_image .wysija_tools a span,.wysija_text .wysija_tools a span,.wj_content a span{display:block;height:20px;width:20px}.wysija_controls span input{margin:2px 0 0 0;padding:0;color:transparent}.alignment-left span{background:url(../img/controls/icons.png) no-repeat 0 0}.alignment-left.active span,.alignment-left:hover span{background:url(../img/controls/icons.png) no-repeat 0 -20px}.alignment-center span{background:url(../img/controls/icons.png) no-repeat -20px 0}.alignment-center.active span,.alignment-center:hover span{background:url(../img/controls/icons.png) no-repeat -20px -20px}.alignment-right span{background:url(../img/controls/icons.png) no-repeat -40px 0}.alignment-right.active span,.alignment-right:hover span{background:url(../img/controls/icons.png) no-repeat -40px -20px}.add-link span{background:url(../img/controls/icons.png) no-repeat -60px 0}.add-link.active span,.add-link:hover span{background:url(../img/controls/icons.png) no-repeat -60px -20px}.remove-link span{background:url(../img/controls/icons.png) no-repeat -80px 0}.remove-link.active span,.remove-link:hover span{background:url(../img/controls/icons.png) no-repeat -80px -20px}.remove span{background:url(../img/controls/icons.png) no-repeat -100px 0}.remove.active span,.remove:hover span{background:url(../img/controls/icons.png) no-repeat -100px -20px}.handle span{background:url(../img/controls/grip-handle.png) no-repeat;cursor:move;width:40px !important}.duplicate span{background:url(../img/controls/icons.png) no-repeat -140px 0}.duplicate.active span,.duplicate:hover span{background:url(../img/controls/icons.png) no-repeat -140px -20px}.settings span{background:url(../img/controls/icons.png) no-repeat -160px 0}.settings.active span,.settings:hover span{background:url(../img/controls/icons.png) no-repeat -160px -20px}.icon-plus span{background:url(../img/controls/icons.png) no-repeat -200px 0}.icon-plus.active span,.icon-plus:hover span{background:url(../img/controls/icons.png) no-repeat -200px -20px}.icon-minus span{background:url(../img/controls/icons.png) no-repeat -220px 0}.icon-minus.active span,.icon-minus:hover span{background:url(../img/controls/icons.png) no-repeat -220px -20px}.banner{color:#000;z-index:999;text-align:center;width:600px;position:absolute;top:0;right:0;left:0;bottom:0;white-space:nowrap;font-size:16px !important;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.banner .banner-message{margin:20px auto 0 auto}.banner .banner-icon{background:url(../img/controls/image-placeholder.png) no-repeat;padding:2px 0 0 28px}.banner .banner-notice{margin:10px auto 0 auto;font-size:12px;font-style:italic}#wysija_wrapper{padding:20px;width:600px;border:1px solid #ccc;position:relative;background-color:#fff;-webkit-box-shadow:0 0 4px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1);-moz-box-shadow:0 0 4px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1);box-shadow:0 0 5px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1)}#wysija_wrapper:before,#wysija_wrapper:after{position:absolute;width:40%;height:10px;content:' ';left:12px;bottom:12px;background:transparent;-webkit-transform:skew(-5deg) rotate(-5deg);-moz-transform:skew(-5deg) rotate(-5deg);-ms-transform:skew(-5deg) rotate(-5deg);-o-transform:skew(-5deg) rotate(-5deg);transform:skew(-5deg) rotate(-5deg);-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);-moz-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3);z-index:-1}#wysija_wrapper:after{left:auto;right:12px;-webkit-transform:skew(5deg) rotate(5deg);-moz-transform:skew(5deg) rotate(5deg);-ms-transform:skew(5deg) rotate(5deg);-o-transform:skew(5deg) rotate(5deg);transform:skew(5deg) rotate(5deg)}body.rtl #wysija_wrapper{right:603px !important}#wysija_container{margin:30px 0 0 0;width:600px;border-collapse:collapse;width:600px;margin:0;padding:0}#wysija_header{padding:0}#wysija_body{vertical-align:top;padding:0}#wysija_footer{padding:0}#wysija_block_placeholder{height:0;padding:0;margin:0}.block_placeholder,.text_placeholder{font-weight:bold;height:0;overflow:hidden;line-height:30px;text-align:center;border:0 none;width:598px;z-index:9500;margin:0 auto;text-indent:-9999px}.wysija_block .block_placeholder,.wysija_block .text_placeholder,.wysija_block .image_placeholder{margin:0}.image_placeholder{margin:1px 0 0 1px}.hover .image_placeholder{margin:0}.wysija_content .empty.wysija_editable{font-size:13px;line-height:30px}.wysija_image.empty{height:0;width:0;margin:0 !important;z-index:-1;overflow:hidden}.wysija_image.empty.active{height:auto}.wysija_image.active{background:url(../img/controls/image-placeholder.png) no-repeat center center #f5f5f5;border:1px dashed #dfdfdf}#wysija_header .wysija_image.empty,#wysija_footer .wysija_image.empty{background-image:none;height:auto}#wysija_header .wysija_image.active,#wysija_footer .wysija_image.active{border:0 none}.block_placeholder.active,.text_placeholder.active{text-indent:0;border:1px dashed #dfdfdf;background-color:#f5f5f5;display:block;overflow:auto;height:30px}.image_placeholder.empty.active{display:block}.block_placeholder.hover,.text_placeholder.hover,.image_hover .wysija_image{background-color:#0074a2;border-color:#0074a2;color:#fff !important}.image_placeholder.active{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=25)";filter:alpha(opacity=25);-moz-opacity:0.25;opacity:0.25;z-index:9501}.wysija_image.empty.active,.wysija_text.empty.active{display:block;margin:0}#wysija_header .wysija_image.active,#wysija_footer .wysija_image.active{left:0;top:0;right:0}.wysija_header .image_placeholder,.wysija_footer .image_placeholder{border:0 none !important;margin:0 !important}.wysija_header .image_placeholder.active,.wysija_footer .image_placeholder.active{border:0 none !important}.wysija_options{display:none}.wysija_content .wysija_image{margin:0 auto 15px auto;cursor:move}.wysija_header .wysija_content.left .wysija_image,.wysija_header .wysija_content.right .wysija_image,.wysija_footer .wysija_content.left .wysija_image,.wysija_footer .wysija_content.right .wysija_image{margin:0 0 0 0 !important}.wysija_content.center .image_placeholder.active{margin:0 0 -2px 0}.wysija_header .wysija_content.center .wysija_image,.wysija_footer .wysija_content.center .wysija_image{margin:0 auto !important}.wysija_header .wysija_content.center .image_placeholder.active,.wysija_footer .wysija_content.center .image_placeholder.active{margin:0}.wysija_block .wysija_content.center .wysija_image.empty.active{margin-bottom:5px !important}.wysija_content.left{float:none}.wysija_gallery.left{float:left}.wysija_content.left .wysija_image{float:left;margin:0 15px 5px 0}.wysija_content.left .wysija_image.active{margin:0 13px 3px 0}.wysija_content.left .wysija_image.empty.active{margin:0 15px 5px 0 !important}.wysija_gallery.right{float:right}.wysija_content.right .wysija_image{float:right;margin:0 0 5px 15px}.wysija_content.right .wysija_image.active{margin:0 0 3px 13px}.wysija_content.right .wysija_image.empty.active{margin:0 0 5px 15px !important}.wysija_content .wysija_image.alone{margin:0 !important}.wysija_content.center .wysija_image.alone{margin:0 auto !important}.wysija_image{position:relative;z-index:999}.wysija_image .url-info{position:absolute;bottom:0;left:0;font-size:0.7em;padding:2px;color:#000;background-color:#fff;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80);-moz-opacity:0.8;opacity:0.8}.wysija_content.left .wysija_image .url-info{right:0;left:auto}.wysija_text{position:relative;z-index:998}.wysija_text.wysija_editing{border:1px solid #dfdfdf}.wysija_content.left .wysija_text.wysija_editing{float:left}.wysija_text .wysija_editable:hover{cursor:pointer}#wysija_toolbar{left:657px;position:absolute;top:-1000px;width:295px}#wysija_toolbar .wysija_toolbar_tabs{border-bottom:1px solid #dfdfdf;line-height:0}#wysija_toolbar .wysija_toolbar_tabs li,#wysija_toolbar .wysija_toolbar_tabs a{margin:0;height:30px;line-height:30px;padding:0;display:-moz-inline-box;display:inline-block;*display:inline;*float:left;outline:0 none}#wysija_toolbar .wysija_toolbar_tabs a{outline:0 none;text-decoration:none;color:#a6a6a6}#wysija_toolbar .wysija_toolbar_tabs li{margin:0 0 1px 0}#wysija_toolbar .wysija_toolbar_tabs a{font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif;background-color:#F5F5F5;background-image:-moz-linear-gradient(center top, #f9f9f9, #f5f5f5);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#F5F5F5', endColorstr='#F9F9F9');background:-webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#f5f5f5));border:1px solid #DFDFDF;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;-khtml-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;box-shadow:0 1px 0 #FFFFFF inset;padding:0 7px}#wysija_toolbar .wysija_toolbar_tabs a:hover{background-color:#eee}#wysija_toolbar .wysija_toolbar_tabs a.selected{color:#000;border-bottom:0 none;background:#fcfcfc;filter:none;padding-bottom:1px}#wysija_toolbar .wysija_toolbar_tabs,#wysija_toolbar .wj_content,#wysija_toolbar .wj_images,#wysija_toolbar .wj_styles,#wysija_toolbar .wj_themes{position:relative;z-index:9998;margin:0}#wysija_toolbar #wysija_notices span{font-size:12px !important;font-weight:normal !important}.wj_content{background-color:#fcfcfc;border:1px solid #dfdfdf;border-top:0 none;padding:0 0 10px 0}.wj_content li{padding:10px 10px 0 10px;position:relative}.wj_content li.notice{font-style:italic;font-size:11px;margin:0 !important;border:0 none !important;background:none !important}.wj_images{z-index:999;background-color:#fcfcfc;border:1px solid #dfdfdf;border-top:0 none;padding:9px}.wj_images ul{min-height:200px;max-height:600px;height:360px;overflow:auto;margin:0;padding:0}.wj_images li{float:left;width:80px;margin:2px;height:80px;overflow:hidden;position:relative;border:1px solid #dfdfdf}.wj_images li img{max-height:150px;width:80px}.wj_images li a{float:left;display:block;height:80px;width:80px}.wj_button{text-align:center;width:265px;margin:20px 0;height:30px;line-height:30px}.wj_images img{cursor:move;max-width:275px}#wysija-upload-browse,#wysija-themes-browse{float:none}.wj_images #wj_images_preview{border:3px solid #dfdfdf;position:absolute;right:295px;top:0;background-color:#fff}.wj_styles{z-index:999;background-color:#fcfcfc;border:1px solid #dfdfdf;border-top:0 none;padding:9px}.wj_styles p{margin:10px 0}.wj_styles .preview{width:20px;float:none !important;height:20px;vertical-align:middle;display:-moz-inline-box;display:inline-block;*display:inline;*float:left;border:1px solid #333}.wj_styles input,.wj_styles select{height:20px;border:0 none;border:1px solid #CCC;margin:0 3px 0 0 !important;padding:0 !important;vertical-align:middle;line-height:20px;font-size:12px}.wj_styles #aUnderlineInput{margin:0 0 0 10px !important}.wj_styles select{width:75px}.wj_styles input.checkbox,.wj_styles input[type=checkbox]{border:0 none !important}.wj_styles input.color{width:55px;padding:0 0 0 2px !important}.wj_styles input.color.disabled{background-color:#eee !important;color:#eee !important}.wj_styles select.small-size{width:50px}.wj_styles select.type{width:68px}.wj_styles select.size{width:58px}.wj_styles form label{cursor:normal;margin:0 0 0 3px}.wj_themes{z-index:999;background-color:#fcfcfc;border:1px solid #dfdfdf;border-top:0 none;padding:9px}.wj_themes ul{height:360px;overflow:auto;margin:0;padding:0}.wj_themes li{float:left;width:80px;margin:2px;height:80px;overflow:hidden;border:1px solid #dfdfdf;position:relative}.wj_themes li img{max-height:150px;width:80px}.wj_themes li a{display:block}.wj_themes #wj_themes_preview{border:3px solid #dfdfdf;position:absolute;right:295px;top:0;background-color:#fff}.wysija_widget{width:275px;height:25px;line-height:25px;z-index:9999 !important}.wj_content a.wysija_item,.wysija_widget{height:25px;line-height:25px;background-color:#F5F5F5;background-image:-moz-linear-gradient(center top, #f9f9f9, #ececec);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#ececec');background:-webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec));border:1px solid #DFDFDF;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;box-shadow:0 1px 0 #FFFFFF inset;display:block;font-size:12px;font-weight:bold;padding:0 0 0 7px;cursor:move;color:#222;text-shadow:0 1px 0 #FFFFFF}.wj_content a.wysija_item.disabled{cursor:help;color:#cccccc}.wysija_item_settings{position:absolute;right:15px;top:13px}.wysija_widget.image{z-index:9999 !important;height:auto !important;width:150px !important;background:none !important;border:0 none !important;box-shadow:none !important;border-radius:0 !important;padding:0 !important}#wysija_notices{z-index:20000;position:relative;left:0;top:0;padding:5px;border:1px solid #dfdfdf;border-top:0 none}#wysija_notices.notice{background-color:#FFFFE0;border-color:#E6DB55;z-index:9999}#wysija_notices.error{background-color:#FFEBE8;border-color:#CC0000}#wysija_notice_msg{font-size:14px;font-weight:bold}.align-center{text-align:center}.align-left{text-align:left}.align-right{text-align:right}.align-justify{text-align:justify}.wysija_gallery{position:relative}.wysija_gallery.center{margin:0 auto}.wysija_gallery.right{text-align:right}.wysija_gallery.left{text-align:left}.wysija_row{width:100%}.wysija_cell{float:left;text-align:center}.resize-controls{position:absolute;left:0;right:0;top:0;bottom:0;z-index:99000;border:1px dashed #ccc}.resize-handle{position:absolute;bottom:0;right:0;width:20px;height:20px;border:0 none;z-index:1001;cursor:se-resize;background:transparent url(../img/controls/resize-se.png) no-repeat scroll right bottom}.resize-info{position:absolute;bottom:0;left:4px;font-size:0.8em;padding:0;margin:0;text-shadow:0 1px 0 #F7F5F2;white-space:nowrap}.right .resize-handle{position:absolute;bottom:0;left:0;width:20px;height:20px;border:0 none;z-index:1001;cursor:sw-resize;background:transparent url(../img/controls/resize-sw.png) no-repeat scroll left bottom}.right .resize-info{left:auto !important;right:4px}#adminmenu li .wp-submenu,.folded #adminmenu .wp-has-current-submenu .wp-submenu{z-index:1001 !important}.wysija_divider{margin:0 auto;width:564px}.wysija_block.auto-post.hover .wysija_content *,.wysija_block.auto-post.hover .wysija_divider{z-index:1000;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";filter:alpha(opacity=30);-moz-opacity:0.3;opacity:0.3}.wysija_auto-post .wysija_divider{text-align:center;margin:0 !important;width:100% !important}.wysija_auto-post .nopost{height:100px}.wysija_auto-post .nopost p{margin:25px 0 0 0}.wysija_settings{left:10px;position:absolute;top:0;z-index:1000}.wysija_settings a{background-color:#F5F5F5;background-image:-moz-linear-gradient(center top, #f9f9f9, #ececec);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#ececec');background:-webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec));border:1px solid #DFDFDF;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;box-shadow:0 1px 0 #FFFFFF inset;font-size:12px;font-weight:normal;cursor:pointer;color:#222;text-shadow:0 1px 0 #FFFFFF;text-decoration:none;display:block;padding:5px 5px 3px 27px}.wysija_settings a span{width:20px;height:20px;position:absolute;top:3px;left:5px}#wysija_toggle_images{position:absolute;top:5px;right:5px;z-index:1000;width:73px;height:33px;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);-moz-opacity:0.5;opacity:0.5;background-color:#fff}#wysija_toggle_images.on{background:url(../img/controls/images-toggle-on.png) no-repeat}#wysija_toggle_images.off{background:url(../img/controls/images-toggle-off.png) no-repeat}#wysija_toggle_images:hover{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100);-moz-opacity:1.0;opacity:1.0}.wysija_block.auto-post{padding:0 !important}.wysija_auto-post .wysija_content{padding:10px 17px !important}.wysija_auto-post .wysija_content:after{content:".";display:block;height:0;clear:both;visibility:hidden}.wysija_auto-post .wysija_content{display:inline-table}* html .wysija_auto-post .wysija_content{height:1%}.wysija_auto-post .wysija_content{display:block}.wysija_auto-post .wysija_divider{padding:9px 0 !important}.wysija_block.auto-post.hover .wysija_content{padding:10px 17px !important}.wysija_auto-post .wysija_text{pointer-events:none;cursor:default}.wysija_auto-post .wysija_image{pointer-events:none;cursor:default}.auto-post.hover .wysija_content:last-child{padding:9px 17px 9px 17px !important}.wysija_auto-post .loading{padding:10px 17px;font-size:10px}#wysija_popup_overlay{background-color:#000;height:100%;left:0;position:fixed;top:0;width:100%;z-index:999989;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=75)";filter:alpha(opacity=75);-moz-opacity:0.75;opacity:0.75}#wysija_popup_overlay.loading{background:url(../img/popup/loading.gif) no-repeat 50% 50% #000}#wysija_popup{position:absolute;top:0;left:0;width:600px;height:400px;background-color:#fff;z-index:999999;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;-moz-box-shadow:#000 0 4px 30px;-webkit-box-shadow:#000 0 4px 30px;-khtml-box-shadow:#000 0 4px 30px;box-shadow:#000 0 4px 30px;border:1px solid #555}#wysija_popup_content{padding:0;overflow:hidden;position:relative}#wysija_popup_title{background-color:#222;border:1px solid #333;height:27px;margin:0;padding:0}#wysija_popup_title h3{color:#cfcfcf;font-size:12px;font-weight:normal;margin:6px 0 0 10px;padding:0;float:left;font:12px "Lucida Grande", Verdana, Arial, sans-serif}#wysija_popup_iframe{border:0 none;outline:0 none}#wysija_popup_close{background:url(../img/popup/close.png) no-repeat;height:15px;width:15px;background-color:#333;display:block;float:right;margin:6px 10px 0 0}.mpoet-ui .wysija_item_settings{text-decoration:none}.mpoet-ui .settings span{background:none;color:#999}.mpoet-ui .wysija_item_settings:hover .dashicons-admin-generic:before,.mpoet-ui .settings:hover .dashicons-admin-generic:before{color:#2ea2cc}.wp_themeSkin .mceToolbar{margin:0 !important;padding:0 !important}
trunk/css/wysija-form-editor.css ADDED
@@ -0,0 +1 @@
 
1
+ .clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}.clearfix{display:inline-table}* html .clearfix{height:1%}.clearfix{display:block}.hidden{display:none}strong{font-weight:bold}img{vertical-align:middle}:focus{outline:0 !important}.inline{display:-moz-inline-box;display:inline-block;*display:inline;*float:left}#form-error{padding:10px;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;color:#000;font-weight:normal;background-color:#ffebe8;border:1px solid #c00}#form-notice{padding:10px;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;color:#555555;font-weight:normal;background-color:#FFFBCC;border:1px solid #E6DB55}#wysija_form_editor{padding:20px;width:600px;border:1px solid #ccc;position:relative;background-color:#fff;-webkit-box-shadow:0 0 4px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1);-moz-box-shadow:0 0 4px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1);box-shadow:0 0 5px rgba(0,0,0,0.2),inset 0 0 20px rgba(0,0,0,0.1)}#wysija_form_editor:before,#wysija_form_editor:after{position:absolute;width:40%;height:10px;content:' ';left:12px;bottom:12px;background:transparent;-webkit-transform:skew(-5deg) rotate(-5deg);-moz-transform:skew(-5deg) rotate(-5deg);-ms-transform:skew(-5deg) rotate(-5deg);-o-transform:skew(-5deg) rotate(-5deg);transform:skew(-5deg) rotate(-5deg);-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);-moz-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3);z-index:-1}#wysija_form_editor:after{left:auto;right:12px;-webkit-transform:skew(5deg) rotate(5deg);-moz-transform:skew(5deg) rotate(5deg);-ms-transform:skew(5deg) rotate(5deg);-o-transform:skew(5deg) rotate(5deg);transform:skew(5deg) rotate(5deg)}.wysija_form_block .wysija_warning{font-weight:bold;color:#900}.block_placeholder{margin:0;border:0 none}.block_placeholder.active{border:1px dashed #b4b4b4;margin:10px;display:block}.block_placeholder.hover{margin:10px;border:1px dashed #b4b4b4;background-color:#f5f5f5}.wysija_form_block{background-color:#fff;height:20px;border:0 none}.wysija_form_block.highlighted{border:1px solid #5897FB;padding:9px 17px}.wysija_form_block img{max-width:100%}.wysija_form_block p{margin:5px 0;word-wrap:break-word}.wysija_form_block p input.radio,.wysija_form_block p input.checkbox{margin:0 5px 0 0}#wysija_form_container{width:640px;margin:0}#wysija-add-field{float:none}#wysija_form_toolbar{position:absolute;width:295px}#wysija_form_toolbar .wysija_form_toolbar_tabs{border-bottom:1px solid #dfdfdf;line-height:0}#wysija_form_toolbar .add_custom_field{text-align:center;padding:15px 0 5px 0}#wysija_form_toolbar .wysija_form_toolbar_tabs li,#wysija_form_toolbar .wysija_form_toolbar_tabs a{margin:0;height:30px;line-height:30px;padding:0;display:-moz-inline-box;display:inline-block;*display:inline;*float:left;outline:0 none}#wysija_form_toolbar .wysija_form_toolbar_tabs a{outline:0 none;text-decoration:none;color:#a6a6a6}#wysija_form_toolbar .wysija_form_toolbar_tabs li{margin:0 0 1px 0}#wysija_form_toolbar .wysija_form_toolbar_tabs a{font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif;background-color:#F5F5F5;background-image:-moz-linear-gradient(center top, #f9f9f9, #f5f5f5);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#F5F5F5', endColorstr='#F9F9F9');background:-webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#f5f5f5));border:1px solid #DFDFDF;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;-khtml-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;box-shadow:0 1px 0 #FFFFFF inset;padding:0 7px}#wysija_form_toolbar .wysija_form_toolbar_tabs a:hover{background-color:#eee}#wysija_form_toolbar .wysija_form_toolbar_tabs a.selected{color:#000;border-bottom:0 none;background:#fcfcfc;filter:none;padding-bottom:1px}#wysija_form_toolbar .wysija_form_toolbar_tabs,#wysija_form_toolbar .wj_content,#wysija_form_toolbar .wj_images,#wysija_form_toolbar .wj_styles,#wysija_form_toolbar .wj_themes{position:relative;z-index:9998;margin:0}.wysija_form_widget{width:275px;height:25px;line-height:25px;z-index:9999 !important}#wysija_form_toolbar a.wysija_form_item,.wysija_form_widget{height:25px;line-height:25px;background-color:#F5F5F5;background-image:-moz-linear-gradient(center top, #f9f9f9, #ececec);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#ececec');background:-webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec));border:1px solid #DFDFDF;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;box-shadow:0 1px 0 #FFFFFF inset;display:block;font-size:12px;font-weight:bold;padding:0 0 0 7px;cursor:move;color:#222;text-shadow:0 1px 0 #FFFFFF}#wysija_form_toolbar a.wysija_form_item.disabled{cursor:pointer;color:#cccccc;pointer-events:none}.wysija_form_item_settings{position:absolute;right:35px;top:13px}.wysija_form_item_delete{position:absolute;right:15px;top:13px}.wj_content{background-color:#fcfcfc;border:1px solid #dfdfdf;padding:0 0 10px 0}.wj_content li{padding:10px 10px 0 10px;position:relative}.wj_content li.notice{font-style:italic;font-size:11px;margin:0 !important;border:0 none !important;background:none !important}.wysija_form_block{position:relative;margin:0;padding:10px 18px 10px 18px;display:inline-table;display:block;height:1%;margin:0;z-index:98}.wysija_form_block.dragging{z-index:99000;pointer-events:none}.wysija_form_block:after{content:".";display:block;height:0;clear:both;visibility:hidden}.wysija_form_block.hover{border:1px dashed #bbb;margin:0 0 0 0;padding:9px 17px 9px 17px}.wysija_form_block.static{background-color:#999}.wysija_form_block .wysija_controls{background-color:#dfdfdf;background-image:-moz-linear-gradient(center bottom, #bbb, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#bbbbbb');background:-webkit-gradient(linear, left bottom, left top, from(#bbb), to(#eee));-moz-border-radius:2px;-webkit-border-radius:2px;-khtml-border-radius:2px;border-radius:2px;border:1px solid #ccc;position:absolute;margin:0;padding:0;width:598px;height:20px;left:-1px;right:0;top:-22px}.wysija_form_block .wysija_controls li{float:left;width:20px;height:20px}.wysija_form_block .wysija_controls a{cursor:pointer;float:left;font-size:120%;font-weight:bold;height:20px;line-height:20px;text-align:center;width:20px;color:#000}.wysija_form_block .wysija_controls a.remove{margin:0 0 0 1px}.wysija_form_block .handle_container,.wysija_form_block .handle_container a{float:none;width:40px !important}.wysija_form_block .handle_container{left:280px;top:0;position:absolute}.wysija_controls a span,.wysija_gallery .wysija_tools a span,.wysija_image .wysija_tools a span,.wysija_text .wysija_tools a span,.wj_content a span{display:block;height:20px;width:20px}.wysija_controls span input{margin:2px 0 0 0;padding:0;color:transparent}.alignment-left span{background:url(../img/controls/icons.png) no-repeat 0 0}.alignment-left.active span,.alignment-left:hover span{background:url(../img/controls/icons.png) no-repeat 0 -20px}.alignment-center span{background:url(../img/controls/icons.png) no-repeat -20px 0}.alignment-center.active span,.alignment-center:hover span{background:url(../img/controls/icons.png) no-repeat -20px -20px}.alignment-right span{background:url(../img/controls/icons.png) no-repeat -40px 0}.alignment-right.active span,.alignment-right:hover span{background:url(../img/controls/icons.png) no-repeat -40px -20px}.add-link span{background:url(../img/controls/icons.png) no-repeat -60px 0}.add-link.active span,.add-link:hover span{background:url(../img/controls/icons.png) no-repeat -60px -20px}.remove-link span{background:url(../img/controls/icons.png) no-repeat -80px 0}.remove-link.active span,.remove-link:hover span{background:url(../img/controls/icons.png) no-repeat -80px -20px}.remove span,.delete span{background:url(../img/controls/icons.png) no-repeat -100px 0}.remove.active span,.remove:hover span,.delete.active span,.delete:hover span{background:url(../img/controls/icons.png) no-repeat -100px -20px}.handle span{background:url(../img/controls/grip-handle.png) no-repeat;cursor:move;width:40px !important}.duplicate span{background:url(../img/controls/icons.png) no-repeat -140px 0}.duplicate.active span,.duplicate:hover span{background:url(../img/controls/icons.png) no-repeat -140px -20px}.settings span{background:url(../img/controls/icons.png) no-repeat -160px 0}.settings.active span,.settings:hover span{background:url(../img/controls/icons.png) no-repeat -160px -20px}.icon-plus span{background:url(../img/controls/icons.png) no-repeat -200px 0}.icon-plus.active span,.icon-plus:hover span{background:url(../img/controls/icons.png) no-repeat -200px -20px}.icon-minus span{background:url(../img/controls/icons.png) no-repeat -220px 0}.icon-minus.active span,.icon-minus:hover span{background:url(../img/controls/icons.png) no-repeat -220px -20px}.wysija_options{display:none}.wysija_settings{left:10px;position:absolute;top:0;z-index:1000}.wysija_settings a{background-color:#F5F5F5;background-image:-moz-linear-gradient(center top, #f9f9f9, #ececec);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#ececec');background:-webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec));border:1px solid #DFDFDF;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;box-shadow:0 1px 0 #FFFFFF inset;font-size:12px;font-weight:normal;cursor:pointer;color:#222;text-shadow:0 1px 0 #FFFFFF;text-decoration:none;display:block;padding:5px 5px 3px 27px}.wysija_settings a span{width:20px;height:20px;position:absolute;top:3px;left:5px}.wysija_form_block label{margin:0 5px 0 0;display:block}#wysija_widget_templates{display:none}#wysija_popup_overlay{background-color:#000;height:100%;left:0;position:fixed;top:0;width:100%;z-index:999998;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=75)";filter:alpha(opacity=75);-moz-opacity:0.75;opacity:0.75}#wysija_popup_overlay.loading{background:url(../img/popup/loading.gif) no-repeat 50% 50% #000}#wysija_popup{position:absolute;top:0;left:0;width:600px;height:400px;background-color:#fff;z-index:999999;-moz-border-radius:3px;-webkit-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;-moz-box-shadow:#000 0 4px 30px;-webkit-box-shadow:#000 0 4px 30px;-khtml-box-shadow:#000 0 4px 30px;box-shadow:#000 0 4px 30px;border:1px solid #555}#wysija_popup_content{padding:0;overflow:hidden;clear:both}#wysija_popup_title{background-color:#222;border:1px solid #333;height:27px;margin:0;padding:0}#wysija_popup_title h3{color:#cfcfcf;font-size:12px;font-weight:normal;margin:6px 0 0 10px;padding:0;float:left;font:12px "Lucida Grande", Verdana, Arial, sans-serif}#wysija_popup_title.empty{background-color:transparent;height:0;border:0 none}#wysija_popup_iframe{border:0 none;outline:0 none}#wysija_popup_close{background:url(../img/popup/close.png) no-repeat;height:15px;width:15px;background-color:#333;display:block;float:right;margin:6px 10px 0 0}h2.title{height:40px;line-height:40px;margin:0 0 15px 0}h2.title span,h2.title form{float:left;margin:0 5px 0 0;vertical-align:middle}h2.title span#form-name{padding:0 3px;margin:0 10px 0 0;font-style:italic}h2.title span#form-name-default{display:none}h2.title #edit-form-name{float:left;margin:10px 5px 0 0}h2.title input{margin:0 10px 0 0}#list-selection{margin:30px 0 0 0}#list-selection label{display:block}#after-submit{margin:30px 0 0 0}#after-submit textarea{width:300px;height:50px}#form-export-links{margin:20px 0 0 0}#form-export textarea{width:100%;height:100px}#wysija_notices{z-index:20000;position:relative;left:0;top:0;padding:5px;border:1px solid #dfdfdf;border-top:0 none}#wysija_notices.notice{background-color:#FFFFE0;border-color:#E6DB55;z-index:9999}#wysija_notices.error{background-color:#FFEBE8;border-color:#CC0000}#wysija_notice_msg{font-size:14px;font-weight:bold}.expand-code{cursor:pointer}.wysija_form_block textarea{resize:none}.mpoet-ui .wysija_form_item_settings,.mpoet-ui .wysija_form_item_delete{text-decoration:none}.mpoet-ui .wysija_form_item_settings:hover .dashicons-admin-generic:before,.mpoet-ui .wysija_form_item_delete:hover .dashicons-dismiss:before,.mpoet-ui .settings:hover .dashicons-admin-generic:before{color:#2ea2cc}.mpoet-ui .settings span,.mpoet-ui .delete span{background:none;color:#999}.mpoet-ui .delete span:before{font-size:21px}
trunk/data/bookmarks/index.html ADDED
File without changes
trunk/data/bookmarks/medium/01/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.addthis.com/
trunk/data/bookmarks/medium/01/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/01/google.png ADDED
Binary file
trunk/data/bookmarks/medium/01/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/01/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/02/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.jankoatwarpspeed.com/post/2009/02/23/Handycons-2-another-free-hand-drawn-icon-set.aspx
trunk/data/bookmarks/medium/02/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/02/google.png ADDED
Binary file
trunk/data/bookmarks/medium/02/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/02/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/03/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/03/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/03/google.png ADDED
Binary file
trunk/data/bookmarks/medium/03/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/03/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/04/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/04/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/04/google.png ADDED
Binary file
trunk/data/bookmarks/medium/04/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/04/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/06/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/06/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/06/google.png ADDED
Binary file
trunk/data/bookmarks/medium/06/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/06/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/07/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/07/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/07/google.png ADDED
Binary file
trunk/data/bookmarks/medium/07/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/07/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/08/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/08/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/08/google.png ADDED
Binary file
trunk/data/bookmarks/medium/08/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/08/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/09/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/09/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/09/google.png ADDED
Binary file
trunk/data/bookmarks/medium/09/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/09/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/10/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ We can't find who's the author of these!
trunk/data/bookmarks/medium/10/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/10/google.png ADDED
Binary file
trunk/data/bookmarks/medium/10/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/10/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/11/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/11/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/11/google.png ADDED
Binary file
trunk/data/bookmarks/medium/11/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/11/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/12/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/12/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/12/google.png ADDED
Binary file
trunk/data/bookmarks/medium/12/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/12/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/13/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/medium/13/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/13/google.png ADDED
Binary file
trunk/data/bookmarks/medium/13/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/13/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/14/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.shareaholic.com/
trunk/data/bookmarks/medium/14/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/14/google.png ADDED
Binary file
trunk/data/bookmarks/medium/14/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/14/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/15/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.blogperfume.com/new-27-circular-social-media-icons-in-3-sizes/
trunk/data/bookmarks/medium/15/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/15/google.png ADDED
Binary file
trunk/data/bookmarks/medium/15/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/15/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/16/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://icondock.com/free/vector-social-media-icons
trunk/data/bookmarks/medium/16/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/16/google.png ADDED
Binary file
trunk/data/bookmarks/medium/16/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/16/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/17/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/17/google.png ADDED
Binary file
trunk/data/bookmarks/medium/17/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/17/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/18/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://shapshapy.deviantart.com/art/social-media-icons-267541616
trunk/data/bookmarks/medium/18/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/18/google.png ADDED
Binary file
trunk/data/bookmarks/medium/18/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/18/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/19/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.softicons.com/free-icons/social-media-icons/social-bookmarks-icons-by-deleket
trunk/data/bookmarks/medium/19/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/19/google.png ADDED
Binary file
trunk/data/bookmarks/medium/19/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/19/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/20/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.purtypixels.com/super-social-media-cons/
trunk/data/bookmarks/medium/20/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/20/google.png ADDED
Binary file
trunk/data/bookmarks/medium/20/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/20/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/21/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.designkindle.com/2011/10/27/socialis/
trunk/data/bookmarks/medium/21/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/21/google.png ADDED
Binary file
trunk/data/bookmarks/medium/21/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/21/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/22/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.designkindle.com/2011/10/27/socialis/
trunk/data/bookmarks/medium/22/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/22/google.png ADDED
Binary file
trunk/data/bookmarks/medium/22/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/22/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/23/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/23/google.png ADDED
Binary file
trunk/data/bookmarks/medium/23/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/23/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/24/facebook.png ADDED
Binary file
trunk/data/bookmarks/medium/24/google.png ADDED
Binary file
trunk/data/bookmarks/medium/24/linkedin.png ADDED
Binary file
trunk/data/bookmarks/medium/24/twitter.png ADDED
Binary file
trunk/data/bookmarks/medium/index.html ADDED
File without changes
trunk/data/bookmarks/small/01/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.addthis.com/
trunk/data/bookmarks/small/01/facebook.gif ADDED
Binary file
trunk/data/bookmarks/small/01/google.gif ADDED
Binary file
trunk/data/bookmarks/small/01/linkedin.gif ADDED
Binary file
trunk/data/bookmarks/small/01/twitter.gif ADDED
Binary file
trunk/data/bookmarks/small/02/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.jankoatwarpspeed.com/post/2009/02/23/Handycons-2-another-free-hand-drawn-icon-set.aspx
trunk/data/bookmarks/small/02/facebook.png ADDED
Binary file
trunk/data/bookmarks/small/02/google.png ADDED
Binary file
trunk/data/bookmarks/small/02/linkedin.png ADDED
Binary file
trunk/data/bookmarks/small/02/twitter.png ADDED
Binary file
trunk/data/bookmarks/small/03/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/small/03/facebook.png ADDED
Binary file
trunk/data/bookmarks/small/03/google.png ADDED
Binary file
trunk/data/bookmarks/small/03/linkedin.png ADDED
Binary file
trunk/data/bookmarks/small/03/twitter.png ADDED
Binary file
trunk/data/bookmarks/small/04/credit.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ Credit for icons:
2
+
3
+ http://blog.artcore-illustrations.de/
4
+
5
+ Note: these icons are from a MailPoet theme's Photoshop file.
trunk/data/bookmarks/small/04/facebook.png ADDED
Binary file
trunk/data/bookmarks/small/04/google.png ADDED
Binary file
trunk/data/bookmarks/small/04/linkedin.png ADDED
Binary file
trunk/data/bookmarks/small/04/twitter.png ADDED
Binary file
trunk/data/bookmarks/small/05/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://icondock.com/free/vector-social-media-icons
trunk/data/bookmarks/small/05/facebook.png ADDED
Binary file
trunk/data/bookmarks/small/05/google.png ADDED
Binary file
trunk/data/bookmarks/small/05/linkedin.png ADDED
Binary file
trunk/data/bookmarks/small/05/twitter.png ADDED
Binary file
trunk/data/bookmarks/small/06/credit.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Credit for icons:
2
+
3
+ http://www.softicons.com/free-icons/social-media-icons/social-bookmarks-icons-by-deleket
trunk/data/bookmarks/small/06/facebook.png ADDED
Binary file
trunk/data/bookmarks/small/06/google.png ADDED
Binary file
trunk/data/bookmarks/small/06/linkedin.png ADDED
Binary file
trunk/data/bookmarks/small/06/twitter.png ADDED
Binary file
trunk/data/bookmarks/small/index.html ADDED
File without changes
trunk/data/dividers/artcore-white.png ADDED
Binary file
trunk/data/dividers/artcore.png ADDED
Binary file
trunk/data/dividers/bar.png ADDED
Binary file
trunk/data/dividers/business.png ADDED
Binary file
trunk/data/dividers/business2.png ADDED
Binary file
trunk/data/dividers/cafe.png ADDED
Binary file
trunk/data/dividers/drop1.png ADDED
Binary file
trunk/data/dividers/drop2.png ADDED
Binary file
trunk/data/dividers/drop3.png ADDED
Binary file
trunk/data/dividers/flashback.png ADDED
Binary file
trunk/data/dividers/index.html ADDED
File without changes
trunk/data/dividers/juicy.png ADDED
Binary file
trunk/data/dividers/plus.png ADDED
Binary file
trunk/data/dividers/school.png ADDED
Binary file
trunk/data/dividers/sketchy.png ADDED
Binary file
trunk/data/dividers/solid.jpg ADDED
Binary file
trunk/data/dividers/vintage.png ADDED
Binary file
trunk/data/index.html ADDED
File without changes
trunk/data/themes/default/index.html ADDED
File without changes
trunk/data/themes/default/screenshot.jpg ADDED
Binary file
trunk/data/themes/default/style.css ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ html {
2
+ background-color: #fff;
3
+ }
4
+ .header {
5
+ background-color: #fff;
6
+ }
7
+ body {
8
+ color:#000;
9
+ font-family: Arial;
10
+ font-size: 12px;
11
+ background-color: #fff;
12
+ }
13
+ .footer {
14
+ color: #000;
15
+ font-family: Arial;
16
+ font-size: 12px;
17
+ background-color: #ccc;
18
+ }
19
+ h1 {
20
+ color: #000;
21
+ font-family: Arial;
22
+ font-size: 28px;
23
+ }
24
+ h2 {
25
+ color: #000;
26
+ font-family: Arial;
27
+ font-size: 26px;
28
+ }
29
+ h3 {
30
+ color: #000;
31
+ font-family: Arial;
32
+ font-size: 24px;
33
+ }
34
+ a {
35
+ color: #21759B;
36
+ font-family: Arial;
37
+ font-size: 12px;
38
+ text-decoration:'none';
39
+ }
40
+ .divider {
41
+ border-color: #000;
42
+ border-size: 1px;
43
+ border-style: solid;
44
+ }
45
+
46
+ unsubscribe {
47
+ color:#7f7f7f;
48
+ }
trunk/data/themes/default/thumbnail.jpg ADDED
Binary file
trunk/data/themes/index.html ADDED
File without changes
trunk/docs/german-disclaimer.md ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ ### WICHTIG - HAFTUNGSAUSSCHLUSS
2
+
3
+ Dieses Plugin trägt wesentlich dazu bei, Ihren Newsletter rechtssicher betreiben zu können.
4
+ Es ist durch einen Rechtsanwalt geprüft worden, der ebenfalls die rechtlichen Hinweise & Muster erstellt hat. Sie entsprechen den rechtlichen Anforderungen eines typischen Newsletters. Jedoch kann die rechtliche Sicherheit eines Newsletters nur im Einzelfall geprüft und bestätigt werden, so dass insoweit keine Haftung übernommen werden kann. Daher sind auch die rechtliche Text- & Hinweismuster nur als Vorlagen zu verstehen, deren abschließende rechtliche Prüfung und ggf. Anpassung Ihnen obliegt. Falls Sie eine Prüfung Ihres Newsletters wünschen, können Sie sich an Rechtsanwalt Thomas Schwenke, LL.M. [http://rechtsanwalt-schwenke.de/kontakt](http://rechtsanwalt-schwenke.de/kontakt) wenden.
trunk/font/icon-email.eot ADDED
Binary file
trunk/font/icon-email.svg ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata></metadata>
5
+ <defs>
6
+ <font id="icon-email" horiz-adv-x="1024">
7
+ <font-face units-per-em="1024" ascent="960" descent="-64" />
8
+ <missing-glyph horiz-adv-x="1024" />
9
+ <glyph unicode="&#x20;" d="" horiz-adv-x="512" />
10
+ <glyph unicode="&#xf466;" d="M972.8 217.6v460.8q0 31.744-22.528 54.272t-54.272 22.528h-717.312q-31.744 0-54.272-22.528t-22.528-54.272v-460.8q0-31.744 22.528-54.272t54.272-22.528h717.312q31.744 0 54.272 22.528t22.528 54.272zM905.728 684.032q7.68-7.68 8.96-16.64t-2.048-15.104-8.448-11.264l-207.872-190.464 199.68-207.872q13.312-15.36 3.072-26.112-4.608-5.632-14.336-6.144t-14.336 3.584l-223.744 190.976-109.568-99.84-109.056 99.84-223.744-190.976q-4.608-4.096-14.336-3.584t-14.336 6.144q-10.24 10.752 3.072 26.112l199.68 207.872-207.872 190.464q-5.12 5.12-8.448 11.264t-2.048 15.104 8.96 16.64q20.48 20.48 48.64-3.584l319.488-258.048 320 258.048q28.16 24.064 48.64 3.584z" />
11
+ </font></defs></svg>
trunk/font/icon-email.ttf ADDED
Binary file
trunk/font/icon-email.woff ADDED
Binary file
trunk/helpers/articles.php ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_articles extends WYSIJA_object {
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ }
8
+
9
+ function stripShortcodes($content) {
10
+ if(strlen(trim($content)) === 0) {
11
+ return '';
12
+ }
13
+ // remove captions
14
+ $content = preg_replace("/\[caption.*?\](.*<\/a>)(.*?)\[\/caption\]/", '$1', $content);
15
+
16
+ // remove other shortcodes
17
+ $content = preg_replace('/\[[^\[\]]*\]/', '', $content);
18
+
19
+ return $content;
20
+ }
21
+
22
+ function convertPostToBlock($post, $params = array()) {
23
+
24
+ // defaults
25
+ $defaults = array(
26
+ 'title_tag' => 'h1',
27
+ 'title_alignment' => 'left',
28
+ 'title_position' => 'inside',
29
+ 'image_alignment' => 'left',
30
+ 'image_width' => 325,
31
+ 'readmore' => __('Read online.', WYSIJA),
32
+ 'post_content' => 'full',
33
+ 'author_show' => 'no',
34
+ 'author_label' => '',
35
+ 'category_show' => 'no',
36
+ 'category_label' => ''
37
+ );
38
+
39
+ // merge params with default params
40
+ $params = array_merge($defaults, $params);
41
+
42
+ if($params['post_content'] === 'full') {
43
+ $content = $post['post_content'];
44
+ } else if($params['post_content'] === 'title') {
45
+ $content = $this->getPostTitle($post, $params);
46
+ } else {
47
+ // get excerpt
48
+ if(!empty($post['post_excerpt'])) {
49
+ $content = $post['post_excerpt'];
50
+ } else {
51
+ // strip shortcodes before getting the excerpt
52
+ $post['post_content'] = $this->stripShortcodes($post['post_content']);
53
+
54
+ // if excerpt is empty then try to find the "more" tag
55
+ $excerpts = explode('<!--more-->', $post['post_content']);
56
+ if(count($excerpts) > 1){
57
+ $content = $excerpts[0];
58
+ }else{
59
+ // finally get a made up excerpt if there is no other choice
60
+ $helper_toolbox = WYSIJA::get('toolbox', 'helper');
61
+ $content = $helper_toolbox->excerpt($post['post_content'], apply_filters('mpoet_excerpt_length', 60));
62
+ }
63
+ }
64
+ // strip title tags from excerpt
65
+ $content = preg_replace('/<([\/])?h[123456](.*?)>/', '<$1p$2>', $content);
66
+ }
67
+
68
+ // convert new lines into <p>
69
+ $content = wpautop($content);
70
+
71
+ // remove images
72
+ $content = preg_replace('/<img[^>]+./','', $content);
73
+
74
+ // strip shortcodes
75
+ $content = $this->stripShortcodes($content);
76
+
77
+ // remove wysija nl shortcode
78
+ $content= preg_replace('/\<div class="wysija-register">(.*?)\<\/div>/','',$content);
79
+
80
+ // convert embedded content if necessary
81
+ $content = $this->convertEmbeddedContent($content);
82
+
83
+ // convert h4 h5 h6 to h3
84
+ $content = preg_replace('/<([\/])?h[456](.*?)>/', '<$1h3$2>', $content);
85
+
86
+ // convert ol to ul
87
+ $content = preg_replace('/<([\/])?ol(.*?)>/', '<$1ul$2>', $content);
88
+
89
+ // convert currency signs
90
+ $content = str_replace(array('$', '€', '£', '¥'), array('&#36;', '&euro;', '&pound;', '&#165;'), $content);
91
+
92
+ // strip useless tags
93
+ // TODO should we add table, tr, td and th into that list it could create issues in some cases
94
+ $tags_not_being_stripped = array('<p>','<em>','<span>','<b>','<strong>','<i>','<h1>','<h2>','<h3>','<a>','<ul>','<ol>','<li>','<br>');
95
+
96
+ // filter to modify that list
97
+ $tags_not_being_stripped = apply_filters('mpoet_strip_tags_ignored',$tags_not_being_stripped);
98
+
99
+ $content = strip_tags($content, implode('',$tags_not_being_stripped));
100
+
101
+ // post meta (author, categories)
102
+ $post_meta_above = '';
103
+ // if the author or categories are displayed, open a new paragraph
104
+ if($params['author_show'] === 'above' || $params['category_show'] === 'above') {
105
+ $post_meta_above .= '<p>';
106
+ }
107
+
108
+ // author above
109
+ if($params['author_show'] === 'above') {
110
+ $post_meta_above .= $this->getPostAuthor($post, $params);
111
+ }
112
+ // categories above
113
+ if($params['category_show'] === 'above') {
114
+ // if there is an author already, we need to add an extra break
115
+ if($params['author_show'] === 'above') {
116
+ $post_meta_above .= '<br />';
117
+ }
118
+ // display post categories
119
+ $post_meta_above .= $this->getPostCategories($post, $params);
120
+ }
121
+
122
+ // close the paragraph around author and categories
123
+ if($params['author_show'] === 'above' || $params['category_show'] === 'above') {
124
+ $post_meta_above .= '</p>';
125
+ }
126
+
127
+ if($params['post_content'] !== 'title') {
128
+ if($params['title_position'] === 'inside') {
129
+ // add title
130
+ $content = $this->getPostTitle($post, $params).$post_meta_above.$content;
131
+ } else {
132
+ $content = $post_meta_above.$content;
133
+ }
134
+ } else {
135
+ $content = $post_meta_above.$content;
136
+ }
137
+
138
+ if($params['post_content'] !== 'title') {
139
+ // add read online link
140
+ $content .= '<p><a href="'.get_permalink($post['ID']).'" target="_blank">'.stripslashes($params['readmore']).'</a></p>';
141
+ }
142
+
143
+ // post meta (author, categories) below
144
+ $post_meta_below = '';
145
+
146
+ // if the author or categories are displayed, open a new paragraph
147
+ if($params['author_show'] === 'below' || $params['category_show'] === 'below') {
148
+ $post_meta_below .= '<p>';
149
+ }
150
+
151
+ // author below
152
+ if($params['author_show'] === 'below') {
153
+ $post_meta_below .= $this->getPostAuthor($post, $params);
154
+ }
155
+
156
+ // categories below
157
+ if($params['category_show'] === 'below') {
158
+ // if there is an author already, we need to add an extra break
159
+ if($params['author_show'] === 'below') {
160
+ $post_meta_below .= '<br />';
161
+ }
162
+ $post_meta_below .= $this->getPostCategories($post, $params);
163
+ }
164
+
165
+ // close the paragraph around author and categories
166
+ if($params['author_show'] === 'below' || $params['category_show'] === 'below') {
167
+ $post_meta_below .= '</p>';
168
+ }
169
+
170
+ if($post_meta_below !== '') $content .= $post_meta_below;
171
+
172
+ // set image/text alignment based on present data
173
+ $post_image = null;
174
+
175
+ if(($params['title_tag'] !== 'list') && isset($post['post_image'])) {
176
+ $post_image = $post['post_image'];
177
+
178
+ // set image alignment to match block's
179
+ $post_image['alignment'] = $params['image_alignment'];
180
+
181
+ // constrain size depending on alignment
182
+ if(empty($post_image['height']) or $post_image['height'] === 0) {
183
+ $post_image = null;
184
+ } else {
185
+ $ratio = round(($post_image['width'] / $post_image['height']) * 1000) / 1000;
186
+ switch($params['image_alignment']) {
187
+ case 'alternate':
188
+ case 'left':
189
+ case 'right':
190
+ // constrain width to 325px max
191
+ $post_image['width'] = min($params['image_width'], 325);
192
+ break;
193
+ case 'center':
194
+ // constrain width to 564px max
195
+ $post_image['width'] = min($params['image_width'], 564);
196
+ break;
197
+ }
198
+
199
+ if($ratio > 0) {
200
+ // if ratio has been calculated, deduce image height
201
+ $post_image['height'] = (int)($post_image['width'] / $ratio);
202
+ } else {
203
+ // otherwise skip the image
204
+ $post_image = null;
205
+ }
206
+ }
207
+ }
208
+
209
+ $position = 0;
210
+ if(isset($params['position']) && (int)$params['position'] > 0) {
211
+ $position = (int)$params['position'];
212
+ }
213
+
214
+ $block = array(
215
+ 'position' => $position,
216
+ 'type' => 'content',
217
+ 'text' => array(
218
+ 'value' => base64_encode($content)
219
+ ),
220
+ 'image' => $post_image,
221
+ 'alignment' => $params['image_alignment']
222
+ );
223
+
224
+ return $block;
225
+ }
226
+
227
+ public function getPostAuthor($post = array(), $params = array()) {
228
+ $content = '';
229
+
230
+ if(isset($post['post_author'])) {
231
+ $author_name = get_the_author_meta('display_name', (int)$post['post_author']);
232
+
233
+ // check if the user specified a label to be displayed before the author's name
234
+ if(strlen(trim($params['author_label'])) > 0) {
235
+ $author_name = stripslashes(trim($params['author_label'])).' '.$author_name;
236
+ }
237
+ $content .= $author_name;
238
+ }
239
+
240
+ return $content;
241
+ }
242
+
243
+ public function getPostCategories($post = array(), $params = array()) {
244
+ $content = '';
245
+
246
+ // get categories
247
+ //$categories = get_the_category($post['ID']);
248
+ $helper_wp_tools = WYSIJA::get('wp_tools', 'helper');
249
+ $categories = $helper_wp_tools->get_post_categories($post);
250
+
251
+ if(empty($categories) === false) {
252
+ // check if the user specified a label to be displayed before the author's name
253
+ if(strlen(trim($params['category_label'])) > 0) {
254
+ $content = stripslashes($params['category_label']).' ';
255
+ }
256
+
257
+ $content .= join(', ', $categories);
258
+ }
259
+
260
+ return $content;
261
+ }
262
+
263
+ public function getPostTitle($post = array(), $params = array()) {
264
+ $content = '';
265
+
266
+ if(strlen(trim($post['post_title'])) > 0) {
267
+ // cleanup post title and convert currency signs
268
+ $post_title = trim(str_replace(array('$', '€', '£', '¥'), array('&#36;', '&euro;', '&pound;', '&#165;'), strip_tags($post['post_title'])));
269
+
270
+ // open title tag
271
+ if($params['title_tag'] === 'list') {
272
+ $params['title_tag'] = 'li';
273
+ }
274
+
275
+ $content .= '<'.$params['title_tag'].' class="align-'.$params['title_alignment'].'">';
276
+ // set title link
277
+ $content .= '<a href="'.get_permalink($post['ID']).'" target="_blank">';
278
+ // set title
279
+ $content .= $post_title;
280
+ // close title link
281
+ $content .= '</a>';
282
+ // close title tag
283
+ $content .= '</'.$params['title_tag'].'>';
284
+
285
+ }
286
+
287
+ return $content;
288
+ }
289
+
290
+ function getImage($post) {
291
+ $image_info = null;
292
+ $post_image = null;
293
+
294
+ // check if has_post_thumbnail function exists, if not, include wordpress class
295
+ if(!function_exists('has_post_thumbnail')) {
296
+ require_once(ABSPATH.WPINC.'/post-thumbnail-template.php');
297
+ }
298
+
299
+ // check for post thumbnail
300
+ if(has_post_thumbnail($post['ID'])) {
301
+ $post_thumbnail = get_post_thumbnail_id($post['ID']);
302
+
303
+ // get attachment data (src, width, height)
304
+ $image_info = wp_get_attachment_image_src($post_thumbnail, 'wysija-newsletters-max');
305
+
306
+ // get alt text
307
+ $altText = trim(strip_tags(get_post_meta($post_thumbnail, '_wp_attachment_image_alt', true)));
308
+ if(strlen($altText) === 0) {
309
+ // if the alt text is empty then use the post title
310
+ $altText = trim(strip_tags($post['post_title']));
311
+ }
312
+ }
313
+
314
+ if($image_info !== null) {
315
+ $post_image = array(
316
+ 'src' => $image_info[0],
317
+ 'width' => $image_info[1],
318
+ 'height' => $image_info[2],
319
+ 'alt' => urlencode($altText)
320
+ );
321
+ } else {
322
+ $matches = $matches2 = array();
323
+
324
+ $output = preg_match_all('/<img.+src=['."'".'"]([^'."'".'"]+)['."'".'"].*>/i', $post['post_content'], $matches);
325
+
326
+ if(isset($matches[0][0])){
327
+ preg_match_all('/(src|height|width|alt)="([^"]*)"/i', $matches[0][0], $matches2);
328
+
329
+ if(isset($matches2[1])){
330
+ foreach($matches2[1] as $k2 => $v2) {
331
+ if(in_array($v2, array('src', 'width', 'height', 'alt'))) {
332
+ if($post_image === null) $post_image = array();
333
+
334
+ if($v2 === 'alt') {
335
+ // special case for alt text as it requireds url encoding
336
+ $post_image[$v2] = urlencode($matches2[2][$k2]);
337
+ } else {
338
+ // otherwise simply get the value
339
+ $post_image[$v2] = $matches2[2][$k2];
340
+ }
341
+ }
342
+ }
343
+ }
344
+ }
345
+ }
346
+
347
+ $helper_images = WYSIJA::get('image','helper');
348
+ $post_image = $helper_images->valid_image($post_image);
349
+
350
+ if($post_image===null) return $post_image;
351
+ return array_merge($post_image, array('url' => get_permalink($post['ID'])));
352
+ }
353
+
354
+
355
+
356
+ function convertEmbeddedContent($content = '') {
357
+ // remove embedded video and replace with links
358
+ $content = preg_replace('#<iframe.*?src=\"(.+?)\".*><\/iframe>#', '<a href="$1">'.__('Click here to view media.', WYSIJA).'</a>', $content);
359
+
360
+ // replace youtube links
361
+ $content = preg_replace('#http://www.youtube.com/embed/([a-zA-Z0-9_-]*)#Ui', 'http://www.youtube.com/watch?v=$1', $content);
362
+
363
+ return $content;
364
+ }
365
+
366
+ function field_select_post_type( $params = array() ) {
367
+ if ( array_key_exists( 'value', $params ) ) {
368
+ $value = $params['value'];
369
+ } else {
370
+ return;
371
+ }
372
+
373
+ // make sure value is null if it's an empty string
374
+ if ( $value !== null && strlen( trim( $value ) ) === 0 ){
375
+ $value = null;
376
+ }
377
+
378
+ // get all post types
379
+ $helper_wp_tools = WYSIJA::get( 'wp_tools', 'helper' );
380
+ $post_types = $helper_wp_tools->get_post_types();
381
+
382
+ // build post type selection
383
+ $output = '<select name="post_type" data-placeholder="' . esc_attr__( 'Filter by type', WYSIJA ) . '" class="mailpoet-field-select2-simple" data-minimum-results-for-search="-1" style="margin-right: 5px;" width="150" id="post_type">';
384
+ $output .= '<option></option>'; // This is require because of Select2 placeholding structure
385
+ $output .= '<option value="post"' . ( ( $value === 'post' ) ? ' selected="selected"' : '' ) . '>' . __( 'Posts', WYSIJA ) . '</option>';
386
+ $output .= '<option value="page"' . ( ( $value === 'page' ) ? ' selected="selected"' : '' ) . '>' . __( 'Pages', WYSIJA ) . '</option>';
387
+
388
+ foreach ( $post_types as $key => $object_post_type ) {
389
+ $selected = ($value === $key) ? ' selected="selected"' : '';
390
+ $output .= '<option value="'.$key.'"'.$selected.'>'.$object_post_type->labels->name.'</option>';
391
+ }
392
+ $output .= '</select>';
393
+ return $output;
394
+ }
395
+
396
+ function field_select_terms() {
397
+ return '<input name="post_category" data-placeholder="' . esc_attr__( 'Categories and tags', WYSIJA ) . '" class="mailpoet-field-select2-terms post_category" style="margin-right: 5px; width: 180px" width="180" value="" data-multilple="false" type="hidden">';
398
+ }
399
+
400
+
401
+ function field_select_status( $current_status = 'publish' ) {
402
+ $output = '';
403
+
404
+ $helper_wp_tools = WYSIJA::get( 'wp_tools', 'helper' );
405
+ $statuses = $helper_wp_tools->get_post_statuses();
406
+
407
+ $output .= '<select data-placeholder="' . esc_attr__( 'Filter by status', WYSIJA ) . '" class="mailpoet-field-select2-simple post_status" data-minimum-results-for-search="-1" id="post_status" name="post_status" width="150">';
408
+ $output .= '<option></option>'; // This is require because of Select2 placeholding structure
409
+ foreach ( $statuses as $key => $label ) {
410
+ $is_selected = ( $current_status === $key ) ? 'selected="selected"' : '';
411
+ $output .= '<option value="' . $key . '" ' . $is_selected . '>' . $label . '</option>';
412
+ }
413
+ $output .= '</select>';
414
+ return $output;
415
+ }
416
+ }
trunk/helpers/autonews.php ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_autonews extends WYSIJA_object {
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ }
8
+
9
+ function events($key=false,$get=true,$value_set=array()){
10
+ static $events=array();
11
+ if($get){
12
+ if(!$key){
13
+ return $events;
14
+ }else{
15
+ if(isset($events[$key])) return $events[$key];
16
+ return false;
17
+ }
18
+
19
+ }else{
20
+ if(isset($events[$key])) return false;
21
+ $events[$key]=$value_set;
22
+ }
23
+ }
24
+
25
+ function register($key_event,$event=array()){
26
+ $this->events($key_event,false,$event);
27
+ }
28
+
29
+ function get($fieldKey){
30
+ return $this->events($fieldKey);
31
+ }
32
+
33
+ /**
34
+ * I'm not sure if this function is useful anymore
35
+ * @param type $email
36
+ * @return type
37
+ */
38
+ function _deprecated_nextSend($email=false){
39
+ if(!$email) return;
40
+ $model_email=WYSIJA::get('email','model');
41
+
42
+ if(is_array($email)){
43
+ $email_data=$model_email->getOne(false,array('email_id'=>$email['email_id']));
44
+ }else{
45
+ $email_data=$model_email->getOne(false,array('email_id'=>$email));
46
+ }
47
+ return $model_email->give_birth($email_data);
48
+ }
49
+
50
+ /**
51
+ *
52
+ * @param type $email
53
+ * @return type
54
+ */
55
+ function getNextSend($email) {
56
+ $schedule_at = -1;
57
+
58
+ //this condition makes sure that our $email is a post notification
59
+ if((int)$email['type'] === 2 && isset($email['params']['autonl']['event']) && $email['params']['autonl']['event'] === 'new-articles') {
60
+
61
+ $helper_toolbox = WYSIJA::get('toolbox','helper');
62
+ // get current time
63
+ $now = time();
64
+
65
+
66
+ //local time = site's time set by the administrator of the site in WP's settings
67
+ //server time = time return by PHP functions such as time()
68
+ //nextSend is the time scheduled in the future of the local time
69
+ //so if we compare the current time to the next send value we need to offset only one value and that would be the nextSend
70
+ //this way both values are on server time
71
+ if(!isset($email['params']['autonl']['nextSend']) || $now > $helper_toolbox->localtime_to_servertime($email['params']['autonl']['nextSend'])) {
72
+ switch($email['params']['autonl']['when-article']) {
73
+ case 'immediate':
74
+ break;
75
+ case 'daily':
76
+ // get timestamp of when the newsletter is supposed to be sent
77
+ $schedule_at = strtotime($email['params']['autonl']['time']);
78
+
79
+ // check if the scheduled at time has already passed
80
+ if($helper_toolbox->localtime_to_servertime($schedule_at) < $now) {
81
+ // schedule it for tomorrow
82
+ $schedule_at = strtotime('tomorrow '.$email['params']['autonl']['time']);
83
+ }
84
+ break;
85
+ case 'weekly':
86
+ // get timestamp of when the newsletter is supposed to be sent
87
+ $schedule_at = strtotime(ucfirst($email['params']['autonl']['dayname']).' '.$email['params']['autonl']['time']);
88
+
89
+ // check if the scheduled at time has already passed
90
+ if($helper_toolbox->localtime_to_servertime($schedule_at) < $now) {
91
+ // schedule it for next week
92
+ $schedule_at = strtotime('next '.ucfirst($email['params']['autonl']['dayname']).' '.$email['params']['autonl']['time']);
93
+ }
94
+ break;
95
+ case 'monthly':
96
+ $time_current_day=date('d',$now);
97
+ $time_current_month=date('m',$now);
98
+ $time_current_year=date('y',$now);
99
+
100
+ // we increment the next date to next months in two cases
101
+ // 1 - if we're setting the next date using the interface in step 1 or step 3 of the newsletter edition and the current day is greater to the selected day
102
+ if(isset( $_POST['save-reactivate'] ) || isset( $_POST['submit-send'] ) ){
103
+ //trigger has to be next month
104
+ if($time_current_day > $email['params']['autonl']['daynumber']) {
105
+
106
+ if((int)$time_current_month === 12) {
107
+ //year +1
108
+ $time_current_month=1;
109
+ $time_current_year++;
110
+ }else{
111
+ //current year
112
+ $time_current_month++;
113
+ }
114
+ }
115
+ // 2 - if we're setting the next date automatically and the date is already passed
116
+ }else{
117
+ if($helper_toolbox->localtime_to_servertime($schedule_at) < $now) {
118
+
119
+ if((int)$time_current_month === 12) {
120
+ //year +1
121
+ $time_current_month=1;
122
+ $time_current_year++;
123
+ }else{
124
+ //current year
125
+ $time_current_month++;
126
+ }
127
+ }
128
+ }
129
+
130
+ //3 - otherwise we stay in the same month
131
+
132
+
133
+ $schedule_at=strtotime($time_current_month.'/'.$email['params']['autonl']['daynumber'].'/'.$time_current_year.' '.$email['params']['autonl']['time']);
134
+ break;
135
+ case 'monthlyevery': // monthly every X Day of the week
136
+ $current_day = date('d', $now);
137
+ $current_month = date('m', $now);
138
+ $current_year = date('y', $now);
139
+
140
+ // calculate the timestamp of the Xth day of the week of the current month
141
+ // strtotime('02/01/13 1 Monday 20:00:00') -> this will return the timestamp of the 1st monday of the current month
142
+ $schedule_at = strtotime(
143
+ sprintf('%02d/01/%02d %d %s %s',
144
+ $current_month,
145
+ $current_year,
146
+ $email['params']['autonl']['dayevery'],
147
+ ucfirst($email['params']['autonl']['dayname']),
148
+ $email['params']['autonl']['time']
149
+ ));
150
+
151
+ if($helper_toolbox->localtime_to_servertime($schedule_at) < $now) {
152
+ // get first day timestamp of next month
153
+ $first_day_of_next_month = $this->get_first_day_of_month($schedule_at, 1);
154
+
155
+ // get next month's Xth day of the week
156
+ $schedule_at = strtotime(
157
+ sprintf('%02d/01/%02d %d %s %s',
158
+ date('m', $first_day_of_next_month),
159
+ date('y', $first_day_of_next_month),
160
+ $email['params']['autonl']['dayevery'],
161
+ ucfirst($email['params']['autonl']['dayname']),
162
+ $email['params']['autonl']['time']
163
+ )
164
+ );
165
+ }
166
+ break;
167
+ }
168
+ }
169
+ }
170
+ return $schedule_at;
171
+ }
172
+
173
+ function get_first_day_of_month($time_stamp, $months_to_add = 0) {
174
+ // You can add as many months as you want. mktime will accumulate to the next year.
175
+ $date = getdate($time_stamp); // Covert to Array
176
+ // add number of months
177
+ $date['mon'] = $date['mon'] + (int)$months_to_add;
178
+ // set day to 1
179
+ $date['mday'] = 1;
180
+ // return timestamp
181
+ return mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']);
182
+ }
183
+
184
+ /**
185
+ * get the time of the n dayname of the month
186
+ * @param type $first_day_of_month
187
+ * @param type $day_name
188
+ * @param type $which_number
189
+ * @param type $time_now
190
+ * @return type
191
+ */
192
+ function getNextDay($first_day_of_month,$day_name,$which_number,$time_now){
193
+ $name_first_day = strtolower(date('l', $first_day_of_month));
194
+
195
+ if($name_first_day == strtolower($day_name)) $which_number--;
196
+ for($i=0; $i < $which_number;$i++){
197
+ $first_day_of_month = strtotime('next '.ucfirst($day_name), $first_day_of_month);
198
+ }
199
+ return $first_day_of_month;
200
+ }
201
+
202
+
203
+ /**
204
+ * check if there is post notification needing a child email
205
+ */
206
+ function checkPostNotif(){
207
+ // flag security to make sure that there can't be two checks of the post notif in the same minute
208
+ $current_check = (float)get_option('wysija_check_pn');
209
+
210
+ // there is a check that has been starting to run less than 60 seconds ago
211
+ if(microtime(true) < ($current_check+60)){
212
+ WYSIJA::log('already_running_checkPN', $current_check, 'post_notif');
213
+ return false;
214
+ }
215
+
216
+ // flag is down we process our post notification check and set the start time of the current check
217
+ $current_check=microtime(true);
218
+ WYSIJA::update_option('wysija_check_pn',$current_check);
219
+
220
+ // let's check when do we come here
221
+ WYSIJA::log('check_post_notif_starts', $current_check , 'post_notif');
222
+
223
+ $model_email=WYSIJA::get('email','model');
224
+ $model_email->reset();
225
+ $all_emails=$model_email->get(false,array('type'=>'2','status'=>array('1','3','99')));
226
+
227
+ if($all_emails){
228
+ $helper_toolbox=WYSIJA::get('toolbox','helper');
229
+ foreach($all_emails as $email){
230
+ //post notification make a child newsletter when the timing is immediate otherwise let the cron take care of it
231
+ if($email['params']['autonl']['event']=='new-articles' && $email['params']['autonl']['when-article']!='immediate'){
232
+ //check if the next sending is passed if so then we give birth to one child email
233
+ //IMPORTANT WE COMPARE TO THE OFFSET TIME (time set by the administrator)
234
+ //if the nextSend doesn't exist then we set it
235
+ if(!isset($email['params']['autonl']['nextSend'])){
236
+ WYSIJA::log('check_post_notif_next_send_not_set', $current_check , 'post_notif');
237
+ }else {
238
+ //if the next send is passed we should trigger it
239
+ $time_now_server=time();
240
+ if($time_now_server > $helper_toolbox->localtime_to_servertime($email['params']['autonl']['nextSend'])){
241
+ $how_late=$time_now_server-$helper_toolbox->localtime_to_servertime($email['params']['autonl']['nextSend']);
242
+ //check how late was the previous notification,
243
+ //if it has been more than two hours late then cancel it and change it to the next day
244
+ if(!$this->cancel_late_post_notification($email,$how_late)){
245
+ WYSIJA::log('check_post_notif_before_give_birth', $current_check, 'post_notif');
246
+ //it is not cancel so we can give birth toa a child newsletter
247
+ $model_email->give_birth($email);
248
+ }
249
+ }
250
+ }
251
+ }
252
+ }
253
+ }
254
+ }
255
+
256
+ /**
257
+ * email has a late post notification which needs to be cancelled and postponed
258
+ * @param array $email
259
+ * @param int $how_late
260
+ * @return boolean
261
+ */
262
+ function cancel_late_post_notification($email,$how_late){
263
+ $cancel_it=false;
264
+ switch($email['params']['autonl']['when-article']) {
265
+ case 'daily':
266
+ //cancel a daily notification with more than two hours delay
267
+ if($how_late>(2*3600)){
268
+ $cancel_it=true;
269
+ }
270
+ break;
271
+ case 'weekly':
272
+ //cancel a weekly notification with more than half a day delay
273
+ if($how_late>(12*3600)){
274
+ $cancel_it=true;
275
+ }
276
+ break;
277
+ case 'monthly':
278
+ //cancel a monthly notification with more than a day delay
279
+ if($how_late>(24*3600)){
280
+ $cancel_it=true;
281
+ }
282
+ break;
283
+ case 'monthlyevery':
284
+ //cancel a monthly notification with more than a day delay
285
+ if($how_late>(24*3600)){
286
+ $cancel_it=true;
287
+ }
288
+ break;
289
+ }
290
+ //if the notification is being cancelled then we store the value of that late notification and update the nextSend
291
+ if($cancel_it){
292
+
293
+ $late_send=$email['params']['autonl']['nextSend'];
294
+ WYSIJA::log('cancel_late_post_notification_late_send', $late_send, 'post_notif');
295
+ $next_send=$this->getNextSend($email);
296
+ $email['params']['autonl']['nextSend']=$next_send;
297
+ $email['params']['autonl']['late_send']=$late_send;
298
+
299
+ $model_email=WYSIJA::get('email','model');
300
+ $model_email->reset();
301
+ $model_email->update(array('params'=>$email['params']), array('email_id' => $email['email_id']));
302
+
303
+ return true;
304
+ }
305
+
306
+ return false;
307
+ }
308
+
309
+ /**
310
+ * check if there are any scheduled email not sent yet
311
+ */
312
+ function checkScheduled(){
313
+ $model_email = WYSIJA::get('email','model');
314
+ $helper_toolbox = WYSIJA::get('toolbox','helper');
315
+ $model_email->reset();
316
+
317
+ // select the scheduled emails
318
+ $all_emails = $model_email->get(false,array('type'=>'1','status'=>'4'));
319
+
320
+ if($all_emails){
321
+
322
+ foreach($all_emails as $email){
323
+
324
+ // check if the email is scheduled
325
+ if(isset($email['params']['schedule']['isscheduled'])){
326
+
327
+ $schedule_date = $email['params']['schedule']['day'] . ' ' . $email['params']['schedule']['time'];
328
+ $unix_scheduled_time = strtotime($schedule_date);
329
+
330
+ // if the scheduled time is passed let's send the email
331
+ // we don't compare to the time recorded but to the offset time which is the time set by the user in his time
332
+ if($helper_toolbox->localtime_to_servertime($unix_scheduled_time) < time()){
333
+ $model_email->reset();
334
+ $model_email->send_activate($email);
335
+ }
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ function refresh_automatic_content($email_ids = array()) {
342
+ // TO OPTIMIZE: add a boolean flag for ALP widget being present or not (this way we filter out "static" auto nl)
343
+ $model_email = WYSIJA::get('email', 'model');
344
+
345
+ $conditions = array('type' => 2, 'status' => array(1, 3, 99));
346
+ if(!empty($email_ids)) {
347
+ $conditions['email_id'] = $email_ids;
348
+ }
349
+ // get only the data needed to update an auto nl so we save some resources
350
+ $data_needed = array('campaign_id','email_id','params','wj_styles','wj_data');
351
+ $emails = $model_email->get( $data_needed, $conditions );
352
+
353
+ foreach($emails as $key => $email) {
354
+ if(is_array($email) && isset($email['params']['autonl']['event']) ) {
355
+
356
+ $wj_data = unserialize(base64_decode($email['wj_data']));
357
+ $reload_auto_content = false;
358
+ foreach($wj_data['body'] as $block) {
359
+ if(isset($block['type']) && $block['type'] === 'auto-post') {
360
+ $reload_auto_content = true;
361
+ }
362
+ }
363
+ if(!$reload_auto_content) continue;
364
+
365
+ // we have to regenerate the html rendering of each auto newsletter
366
+ $helper_wj_engine = WYSIJA::get('wj_engine', 'helper');
367
+ $helper_wj_engine->setStyles($email['wj_styles'], true);
368
+ $helper_wj_engine->setData($email['wj_data'], true);
369
+
370
+ // update email data
371
+ $values = array(
372
+ 'email_id' => (int)$email['email_id'],
373
+ 'wj_data' => $helper_wj_engine->getEncoded('data'),
374
+ 'body' => $helper_wj_engine->renderEmail($email)
375
+ );
376
+
377
+ // make sure the modified_at columns get updated
378
+ $model_email->columns['modified_at']['autoup'] = 1;
379
+
380
+ // update data in DB
381
+ $model_email->update($values, array('email_id' => (int)$email['email_id']));
382
+ }
383
+ }
384
+ }
385
+
386
+ // removes any auto-post block
387
+ function remove_autopost_blocks($data = array()) {
388
+ if(empty($data)) {
389
+ return false;
390
+ }
391
+
392
+ // decode data
393
+ $wj_data = unserialize(base64_decode($data));
394
+
395
+ // init updated_wj_data variable with initial wj_data
396
+ $updated_wj_data = $wj_data;
397
+
398
+ foreach($wj_data['body'] as $key => $block) {
399
+ // if we detect an auto-post block, we need to remove it
400
+ if(isset($block['type']) && $block['type'] === 'auto-post') {
401
+ // remove block from updated data
402
+ unset($updated_wj_data['body'][$key]);
403
+ }
404
+ }
405
+ // if the wj_data has not changed, return false
406
+ if($updated_wj_data === $wj_data) {
407
+ return false;
408
+ } else {
409
+ // otherwise return encoded version of updated_wj_data
410
+ return base64_encode(serialize($updated_wj_data));
411
+ }
412
+ }
413
+ }
trunk/helpers/back.php ADDED
@@ -0,0 +1,625 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+
5
+ /**
6
+ * class managing the admin vital part to integrate wordpress
7
+ */
8
+ class WYSIJA_help_back extends WYSIJA_help{
9
+
10
+ function __construct(){
11
+ parent::__construct();
12
+ //check that the application has been installed properly
13
+ $config=WYSIJA::get('config','model');
14
+
15
+ define('WYSIJA_DBG',(int)$config->getValue('debug_new'));
16
+ //by default do not show the errors until we get into the debug file
17
+ if(!defined('WP_DEBUG') || !WP_DEBUG){
18
+ error_reporting(0);
19
+ ini_set('display_errors', '0');
20
+ }
21
+
22
+ add_filter('admin_footer_text', array(&$this, 'admin_footer_text'));
23
+ add_filter('update_footer', array(&$this, 'update_footer'), 15);
24
+
25
+ //the controller is backend is it from our pages or from wordpress?
26
+ //are we pluging-in to wordpress interfaces or doing entirely our own page?
27
+ if(isset($_GET['page']) && substr($_GET['page'],0,7)=='wysija_'){
28
+ define('WYSIJA_ITF',TRUE);
29
+ $this->controller=WYSIJA::get(str_replace('wysija_','',$_GET['page']),'controller');
30
+ }else{//check if we are pluging in wordpress interface
31
+ define('WYSIJA_ITF',FALSE);
32
+ }
33
+
34
+ if( WYSIJA_DBG>0 ) include_once(WYSIJA_INC.'debug.php');
35
+
36
+ if(!function_exists('dbg')) {
37
+ function dbg($mixed,$exit=true){}
38
+ }
39
+
40
+
41
+ //we set up the important hooks for backend: menus js css etc
42
+ if(defined('DOING_AJAX')){
43
+ //difference between frontend and backend
44
+
45
+ add_action( 'after_setup_theme', array($this, 'ajax_setup') );
46
+
47
+ }else{
48
+ if(WYSIJA_ITF) {
49
+ add_action('admin_init', array( $this , 'verify_capability'),1);
50
+ add_action('admin_init', array($this->controller, 'main'));
51
+ add_action('after_setup_theme',array($this,'resolveConflicts'));
52
+ }
53
+ //this is a fix for qtranslate as we were loading translatable string quite early
54
+
55
+
56
+ //somehow if we add caps to one role the user with that role doesnt get its caps updated ...
57
+ add_action('after_setup_theme', array('WYSIJA', 'update_user_caps'),11);
58
+ add_action('admin_menu', array($this, 'define_translated_strings'),98);
59
+ add_action('admin_menu', array($this, 'add_menus'),99);
60
+ add_action('admin_enqueue_scripts',array($this, 'add_js'),10,1);
61
+
62
+
63
+ //add specific page script
64
+ add_action('admin_head-post-new.php',array($this,'addCodeToPagePost'));
65
+ add_action('admin_head-post.php',array($this,'addCodeToPagePost'));
66
+
67
+ //make sure that admin and super admin always have the highest access
68
+ $wptools = WYSIJA::get('wp_tools', 'helper');
69
+ $wptools->set_default_rolecaps();
70
+
71
+ // Hook the warning function for premium.
72
+ add_action( 'admin_init', array(&$this, 'warn_action_on_premium') );
73
+ }
74
+
75
+ //if the comment form option is activated then we add an approval action
76
+ if($config->getValue('commentform')){
77
+ add_action('wp_set_comment_status', array($this,'comment_approved'), 60,2);
78
+ }
79
+ }
80
+
81
+ private function _set_ajax_nonces(){
82
+ if( isset( $_GET['page'] ) && substr( $_GET['page'] ,0 ,7 ) == 'wysija_' ){
83
+
84
+ $ajax_nonces = array(
85
+ 'campaigns' => array(
86
+ 'switch_theme' => WYSIJA_view::secure(array(
87
+ 'controller' => 'wysija_campaigns',
88
+ 'action' => 'switch_theme'
89
+ ), true),
90
+ 'save_editor' => WYSIJA_view::secure(array(
91
+ 'controller' => 'wysija_campaigns',
92
+ 'action' => 'save_editor'
93
+ ), true),
94
+ 'save_styles' => WYSIJA_view::secure(array(
95
+ 'controller' => 'wysija_campaigns',
96
+ 'action' => 'save_styles'
97
+ ), true),
98
+ 'deleteimg' => WYSIJA_view::secure(array(
99
+ 'controller' => 'wysija_campaigns',
100
+ 'action' => 'deleteimg'
101
+ ), true),
102
+ 'deleteTheme' => WYSIJA_view::secure(array(
103
+ 'controller' => 'wysija_campaigns',
104
+ 'action' => 'deleteTheme'
105
+ ), true),
106
+ 'save_IQS' => WYSIJA_view::secure(array(
107
+ 'controller' => 'wysija_campaigns',
108
+ 'action' => 'save_IQS'
109
+ ), true),
110
+ 'send_preview' => WYSIJA_view::secure(array(
111
+ 'controller' => 'wysija_campaigns',
112
+ 'action' => 'send_preview'
113
+ ), true),
114
+ 'send_spamtest' => WYSIJA_view::secure(array(
115
+ 'controller' => 'wysija_campaigns',
116
+ 'action' => 'send_spamtest'
117
+ ), true),
118
+ 'insert_articles' => WYSIJA_view::secure(array(
119
+ 'controller' => 'wysija_campaigns',
120
+ 'action' => 'insert_articles'
121
+ ), true),
122
+ 'set_divider' => WYSIJA_view::secure(array(
123
+ 'controller' => 'wysija_campaigns',
124
+ 'action' => 'set_divider'
125
+ ), true),
126
+ 'generate_social_bookmarks' => WYSIJA_view::secure(array(
127
+ 'controller' => 'wysija_campaigns',
128
+ 'action' => 'generate_social_bookmarks'
129
+ ), true),
130
+ 'install_theme' => WYSIJA_view::secure(array(
131
+ 'controller' => 'wysija_campaigns',
132
+ 'action' => 'install_theme'
133
+ ), true),
134
+ 'setDefaultTheme' => WYSIJA_view::secure(array(
135
+ 'controller' => 'wysija_campaigns',
136
+ 'action' => 'setDefaultTheme'
137
+ ), true),
138
+ 'deleteTheme' => WYSIJA_view::secure(array(
139
+ 'controller' => 'wysija_campaigns',
140
+ 'action' => 'deleteTheme'
141
+ ), true),
142
+ 'save_poll' => WYSIJA_view::secure(array(
143
+ 'controller' => 'wysija_campaigns',
144
+ 'action' => 'save_poll'
145
+ ), true),
146
+ 'sub_delete_image' => WYSIJA_view::secure(array(
147
+ 'controller' => 'wysija_campaigns',
148
+ 'action' => 'sub_delete_image',
149
+ ), true),
150
+
151
+ ),
152
+ 'config' => array(
153
+ 'send_test_mail' => WYSIJA_view::secure(array(
154
+ 'controller' => 'wysija_config',
155
+ 'action' => 'send_test_mail'
156
+ ), true),
157
+ 'send_test_mail_ms' => WYSIJA_view::secure(array(
158
+ 'controller' => 'wysija_config',
159
+ 'action' => 'send_test_mail_ms'
160
+ ), true),
161
+ 'bounce_process' => WYSIJA_view::secure(array(
162
+ 'controller' => 'wysija_config',
163
+ 'action' => 'bounce_process'
164
+ ), true),
165
+ 'share_analytics' => WYSIJA_view::secure(array(
166
+ 'controller' => 'wysija_config',
167
+ 'action' => 'share_analytics'
168
+ ), true),
169
+ 'wysija_form_manage_field' => WYSIJA_view::secure(array(
170
+ 'controller' => 'wysija_config',
171
+ 'action' => 'wysija_form_manage_field'
172
+ ), true),
173
+ 'form_field_delete' => WYSIJA_view::secure(array(
174
+ 'controller' => 'wysija_config',
175
+ 'action' => 'form_field_delete'
176
+ ), true),
177
+ 'form_name_save' => WYSIJA_view::secure(array(
178
+ 'controller' => 'wysija_config',
179
+ 'action' => 'form_name_save'
180
+ ), true),
181
+ 'form_save' => WYSIJA_view::secure(array(
182
+ 'controller' => 'wysija_config',
183
+ 'action' => 'form_save'
184
+ ), true),
185
+ 'validate' => WYSIJA_view::secure(array(
186
+ 'controller' => 'wysija_config',
187
+ 'action' => 'validate'
188
+ ), true),
189
+ 'linkignore' => WYSIJA_view::secure(array(
190
+ 'controller' => 'wysija_config',
191
+ 'action' => 'linkignore'
192
+ ), true),
193
+ )
194
+ );
195
+
196
+ }else{
197
+ $ajax_nonces = array();
198
+ }
199
+
200
+ wp_localize_script('wysija-admin', 'wysijanonces', $ajax_nonces);
201
+ }
202
+
203
+ /**
204
+ * On any of the administration pages related to MailPoet, if the user
205
+ * has the key and doesn't have the premium plugin active a warning will
206
+ * be displayed.
207
+ *
208
+ * @return null
209
+ */
210
+ public function warn_action_on_premium(){
211
+ $mdl_config=WYSIJA::get('config','model');
212
+
213
+ if($mdl_config->getValue('premium_key') && !WYSIJA::is_plugin_active(WJ_Upgrade::$plugins[1])){
214
+ if( file_exists( WPMU_PLUGIN_DIR . DIRECTORY_SEPARATOR . WJ_Upgrade::$plugins[1] ) || file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . WJ_Upgrade::$plugins[1] ) ){
215
+ //send a message to the user so that he activates the premium plugin or try to fetch it directly.
216
+ $this->notice('<p>'.__('You need to activate the MailPoet Premium plugin.', WYSIJA).' <a data-warn="' . esc_attr__( "Confirm activating the MailPoet Premium Plugin?", WYSIJA ) . '" class="button-primary" title="' . esc_attr__( "Activate MailPoet Premium Version", WYSIJA ) . '" href="' . wp_nonce_url('plugins.php?action=activate&amp;plugin=' . urlencode(WJ_Upgrade::$plugins[1]) . '&amp;plugin_status=all', 'activate-plugin_' . WJ_Upgrade::$plugins[1]) . '">'.__('Activate now',WYSIJA).'</a></p>');
217
+ } else {
218
+
219
+ $args = array(
220
+ 'page' => 'wysija_config',
221
+ 'action' => 'packager-switch',
222
+ '_mp_action' => 'install',
223
+ '_wpnonce' => wp_create_nonce('packager-switch'),
224
+ );
225
+ if (WYSIJA::is_beta())
226
+ $args["stable"] = 1;
227
+
228
+ $link = esc_attr(add_query_arg($args, admin_url('admin.php')));
229
+
230
+ //send a message to the user so that he gets the premium plugin or try to fetch it directly.
231
+ $this->notice('<p>'.__('Congrats, your Premium license is active. One last step...', WYSIJA).' <a data-warn="' . esc_attr__( "Confirm installing the MailPoet Premium Plugin?", WYSIJA ) . '" id="install-wjp" class="button-primary" title="' . esc_attr__( "Installing MailPoet Premium Version", WYSIJA ) . '" href="' . esc_url($link) . '">'.__('Download the Premium plugin.',WYSIJA).'</a></p>');
232
+ }
233
+ }
234
+
235
+ return null;
236
+ }
237
+
238
+ function comment_approved($cid,$comment_status){
239
+ //if the comment is approved and the meta wysija_comment_subscribe appears, then we have one subscriber more to add
240
+ $metaresult=get_comment_meta($cid, 'wysija_comment_subscribe', true);
241
+
242
+ if($comment_status=='approve' && get_comment_meta($cid, 'wysija_comment_subscribe', true)){
243
+ $mConfig=WYSIJA::get('config','model');
244
+ $comment = get_comment($cid);
245
+ $userHelper=WYSIJA::get('user','helper');
246
+ $data=array('user'=>array('email'=>$comment->comment_author_email,'firstname'=>$comment->comment_author),'user_list'=>array('list_ids'=>$mConfig->getValue('commentform_lists')));
247
+ $userHelper->addSubscriber($data);
248
+ }
249
+ }
250
+
251
+ function ajax_setup(){
252
+ if(!isset($_REQUEST['adminurl']) && !is_user_logged_in()) add_action('wp_ajax_nopriv_wysija_ajax', array($this, 'ajax'));
253
+ else add_action('wp_ajax_wysija_ajax', array($this, 'ajax'));
254
+ }
255
+
256
+
257
+ /**
258
+ * let's fix all the conflicts that we may have
259
+ */
260
+ function resolveConflicts(){
261
+
262
+ // check conflicting themes
263
+ $possibleConflictiveThemes = $this->controller->get_conflictive_plugins(true);
264
+
265
+ $conflictingTheme = null;
266
+ $currentTheme = strtolower(function_exists( 'wp_get_theme' ) ? wp_get_theme() : get_current_theme());
267
+ foreach($possibleConflictiveThemes as $keyTheme => $conflictTheme) {
268
+ if($keyTheme === $currentTheme) {
269
+ $conflictingTheme = $keyTheme;
270
+ }
271
+ }
272
+
273
+ // if the current theme is known to make troubles, let's resolve this
274
+ if($conflictingTheme !== null) {
275
+ $helperConflicts = WYSIJA::get('conflicts', 'helper');
276
+ $helperConflicts->resolve(array($possibleConflictiveThemes[$conflictingTheme]));
277
+ }
278
+
279
+ // check conflicting plugins
280
+ $possibleConflictivePlugins=$this->controller->get_conflictive_plugins();
281
+
282
+ $conflictingPlugins=array();
283
+ foreach($possibleConflictivePlugins as $keyPlg => $conflictPlug){
284
+ if(WYSIJA::is_plugin_active($conflictPlug['file'])) {
285
+ //plugin is activated
286
+ $conflictingPlugins[$keyPlg]=$conflictPlug;
287
+ }
288
+ }
289
+
290
+ if($conflictingPlugins){
291
+ $helperConflicts=WYSIJA::get('conflicts','helper');
292
+ $helperConflicts->resolve($conflictingPlugins);
293
+ }
294
+ }
295
+
296
+ /**
297
+ * this function will check the role of the user executing the action, if it's called from another
298
+ * WordPress admin page than page.php for instance admin-post.php
299
+ * @return boolean
300
+ */
301
+ function verify_capability(){
302
+ if( isset( $_GET['page'] ) && substr( $_GET['page'] ,0 ,7 ) == 'wysija_' ){
303
+
304
+ switch( $_GET['page'] ){
305
+ case 'wysija_campaigns':
306
+ $role_needed = 'wysija_newsletters';
307
+ break;
308
+ case 'wysija_subscribers':
309
+ $role_needed = 'wysija_subscribers';
310
+ break;
311
+ case 'wysija_config':
312
+ $role_needed = 'wysija_config';
313
+ break;
314
+ case 'wysija_statistics':
315
+ $role_needed = 'wysija_stats_dashboard';
316
+ break;
317
+ default:
318
+ $role_needed = 'switch_themes';
319
+ }
320
+
321
+ if( current_user_can( $role_needed ) ){
322
+ return true;
323
+ } else{
324
+ die( 'You are not allowed here.' );
325
+ }
326
+
327
+ }else{
328
+ // this is not a wysija interface/action we can let it pass
329
+ return true;
330
+ }
331
+ }
332
+
333
+ /**
334
+ * translatable strings need to be not loaded to early, this is why we put them ina separate function
335
+ * @global type $wysija_installing
336
+ */
337
+ function define_translated_strings(){
338
+ $config = WYSIJA::get('config','model');
339
+ $linkcontent = __("It doesn't always work the way we want it to, doesn't it? We have a [link]dedicated support website[/link] with documentation and a ticketing system.",WYSIJA);
340
+ $finds = array('[link]','[/link]');
341
+ $replace = array('<a target="_blank" href="http://support.mailpoet.com" title="support.mailpoet.com">','</a>');
342
+ $truelinkhelp = '<p>'.str_replace($finds,$replace,$linkcontent).'</p>';
343
+ $truelinkhelp .= '<p>'.__('MailPoet Version: ',WYSIJA).'<strong>'.WYSIJA::get_version().'</strong></p>';
344
+
345
+ $this->menus=array(
346
+ 'campaigns'=>array('title'=>'MailPoet'. ' <span class="update-plugins"><span class="update-count">1</span></span>'),
347
+ 'subscribers'=>array('title'=>__('Subscribers',WYSIJA)), // if the key "subscribers" is changed, please change in the filter "wysija_menus" as well.
348
+ 'config'=>array('title'=>__('Settings',WYSIJA)),
349
+ 'premium'=>array('title'=>__('Premium',WYSIJA)),
350
+ 'mp3'=>array('title'=>__('Try MailPoet 3 Now!',WYSIJA))
351
+ );
352
+ $this->menus = apply_filters('wysija_menus', $this->menus);
353
+ $this->menuHelp = $truelinkhelp;
354
+ if($config->getValue('queue_sends_slow')){
355
+ $msg=$config->getValue('ignore_msgs');
356
+ if(!isset($msg['queuesendsslow'])){
357
+ $this->notice(
358
+ __('Tired of waiting more than 48h to send your emails?',WYSIJA).' '. str_replace(array('[link]','[/link]'), array('<a href="http://docs.mailpoet.com/article/48-wp-cron-batch-emails-sending-frequency" target="_blank">','</a>'), __('[link]Find out[/link] how you can improve this.',WYSIJA)).
359
+ ' <a class="linkignore queuesendsslow" href="javascript:;">'.__('Hide!',WYSIJA).'</a>');
360
+ }
361
+ }
362
+
363
+ if(WYSIJA_ITF){
364
+ global $wysija_installing;
365
+ if( !$config->getValue('sending_emails_ok')){
366
+ $msg=$config->getValue('ignore_msgs');
367
+
368
+ $urlsendingmethod='admin.php?page=wysija_config#tab-sendingmethod';
369
+ if($_REQUEST['page'] === 'wysija_config') {
370
+ $urlsendingmethod='#tab-sendingmethod';
371
+ }
372
+
373
+ }
374
+ }
375
+ }
376
+
377
+
378
+ function add_menus(){
379
+ global $menu,$submenu;// WordPress globals be careful there
380
+ $count=0;
381
+
382
+ //anti conflicting menus code to make sure that another plugin is not at the same level as us
383
+ $position=50;
384
+ $positionplus1=$position+1;
385
+
386
+ while(isset($menu[$position]) || isset($menu[$positionplus1])){
387
+ $position++;
388
+ $positionplus1=$position+1;
389
+ //check that there is no menu at our level neither at ourlevel+1 because that will make us disappear in some case :/
390
+ if(!isset($menu[$position]) && isset($menu[$positionplus1])){
391
+ $position=$position+2;
392
+ }
393
+ }
394
+
395
+ global $wysija_installing;
396
+ foreach($this->menus as $action=> $menutemp){
397
+ $actionFull='wysija_'.$action;
398
+ if (!isset($menutemp['subtitle']))
399
+ $menutemp['subtitle'] = $menutemp['title'];
400
+ if ($action == 'campaigns')
401
+ $roleformenu = 'wysija_newsletters';
402
+ elseif ($action == 'subscribers')
403
+ $roleformenu = 'wysija_subscribers';
404
+ elseif ($action == 'statistics')
405
+ $roleformenu = 'wysija_stats_dashboard';
406
+ else
407
+ $roleformenu = 'wysija_config';
408
+
409
+ if($wysija_installing===true){
410
+ if($count==0){
411
+ $parentmenu=$actionFull;
412
+ $hookname = add_menu_page(
413
+ $menutemp['title'],
414
+ $menutemp['subtitle'],
415
+ $roleformenu,
416
+ $actionFull,
417
+ array($this->controller, 'errorInstall'),
418
+ WYSIJA_EDITOR_IMG.'menu-icon.png',
419
+ $position
420
+ );
421
+ }
422
+ }else{
423
+ if($count==0){
424
+ $parentmenu = $actionFull;
425
+ $hookname = add_menu_page(
426
+ $menutemp['title'],
427
+ $menutemp['subtitle'],
428
+ $roleformenu,
429
+ $actionFull ,
430
+ array($this->controller, 'render'),
431
+ WYSIJA_EDITOR_IMG.'menu-icon.png',
432
+ $position
433
+ );
434
+ }else{
435
+ $hookname=add_submenu_page($parentmenu,$menutemp['title'], $menutemp['subtitle'], $roleformenu, $actionFull , array($this->controller, 'render'));
436
+ }
437
+
438
+ //manage wp help tab
439
+ if(WYSIJA_ITF){
440
+ //wp3.3
441
+ if(version_compare(get_bloginfo('version'), '3.3.0')>= 0){
442
+ add_action('load-'.$hookname, array($this,'add_help_tab'));
443
+ }else{
444
+ //wp3.0
445
+ add_contextual_help($hookname, $this->menuHelp);
446
+ }
447
+ }
448
+ }
449
+ $count++;
450
+ }
451
+
452
+ // Correct the text of submenu, in case there is only 1 submenu is enabled
453
+ if(isset($submenu[$parentmenu])) {
454
+ switch ($submenu[$parentmenu][0][2]) {
455
+ case 'wysija_subscribers':
456
+ $textmenu=__('Subscribers',WYSIJA);
457
+ break;
458
+
459
+ case 'wysija_statistics':
460
+ $textmenu=__('Statistics',WYSIJA);
461
+ break;
462
+
463
+ case 'wysija_config':
464
+ $textmenu=__('Settings',WYSIJA);
465
+ break;
466
+
467
+ case 'wysija_campaigns':
468
+ default:
469
+ $textmenu=__('Newsletters',WYSIJA);
470
+ break;
471
+ }
472
+ $submenu[$parentmenu][0][0]=$submenu[$parentmenu][0][3]=$textmenu;
473
+ }
474
+ }
475
+
476
+ function add_help_tab($params){
477
+ $screen = get_current_screen();
478
+
479
+ if(method_exists($screen, "add_help_tab")){
480
+ $screen->add_help_tab(array(
481
+ 'id' => 'wysija_help_tab',
482
+ 'title' => __('Get Help!',WYSIJA),
483
+ 'content'=> $this->menuHelp));
484
+ $tabfunc=true;
485
+ }
486
+ }
487
+
488
+ function add_js($hook) {
489
+ //needed in all the wordpress admin pages including wysija's ones
490
+
491
+ $jstrans=array();
492
+ wp_register_script('wysija-charts', 'https://www.google.com/jsapi', array( 'jquery' ), true);
493
+ wp_register_script('wysija-admin-list', WYSIJA_URL.'js/admin-listing.js', array( 'jquery' ), true, WYSIJA::get_version());
494
+ wp_register_script('wysija-base-script-64', WYSIJA_URL.'js/base-script-64.js', array( 'jquery' ), true, WYSIJA::get_version());
495
+
496
+
497
+ wp_enqueue_style('wysija-admin-css-widget', WYSIJA_URL.'css/admin-widget.css',array(),WYSIJA::get_version());
498
+
499
+ // If Cron enabled sending, send Mixpanel data and reset flag.
500
+ $model_config = WYSIJA::get('config', 'model');
501
+ if ($model_config->getValue('send_analytics_now') == 1) {
502
+ $analytics = new WJ_Analytics();
503
+ $analytics->generate_data();
504
+ $analytics->send();
505
+ // Reset sending flag.
506
+ $model_config->save(array('send_analytics_now' => 0));
507
+ }
508
+
509
+
510
+ //we are in wysija's admin interface
511
+ if(WYSIJA_ITF){
512
+ wp_enqueue_style('wysija-admin-css-global', WYSIJA_URL.'css/admin-global.css',array(),WYSIJA::get_version());
513
+ wp_enqueue_script('wysija-admin-js-global', WYSIJA_URL.'js/admin-wysija-global.js',array(),WYSIJA::get_version());
514
+ $pagename=str_replace('wysija_','',$_REQUEST['page']);
515
+ $backloader=WYSIJA::get('backloader','helper');
516
+ $backloader->init( $this->controller );
517
+
518
+ //$this->controller->jsTrans["ignoremsg"]=__('Are you sure you want to ignore this message?.',WYSIJA);
519
+ $jstrans=$this->controller->jsTrans;
520
+ //if(!in_array('wysija-admin-ajax-proto',$this->controller->js)) $this->controller->js[]='wysija-admin-ajax';
521
+
522
+ $jstrans['gopremium']=__('Go Premium!',WYSIJA);
523
+
524
+ //enqueue all the scripts that have been declared in the controller
525
+ $backloader->parse_js( $this->controller, $pagename, WYSIJA_URL );
526
+
527
+ //this will load automatically existing scripts and stylesheets based on the page and action parameters
528
+ $backloader->load_assets($pagename,WYSIJA_DIR,WYSIJA_URL,$this->controller);
529
+
530
+ //add some translation
531
+ $backloader->localize( $pagename, WYSIJA_DIR, WYSIJA_URL, $this->controller );
532
+
533
+ // add rtl support
534
+ if ( is_rtl() ) {
535
+ wp_enqueue_style('wysija-admin-rtl', WYSIJA_URL.'css/rtl.css',array(),WYSIJA::get_version());
536
+ }
537
+ $this->_set_ajax_nonces();
538
+ }
539
+ $jstrans['newsletters']=__('Newsletters',WYSIJA);
540
+ $jstrans['urlpremium']='admin.php?page=wysija_config#tab-premium';
541
+ $jstrans['premium_activating'] = __('Checking license', WYSIJA);
542
+ if(isset($_REQUEST['page']) && $_REQUEST['page']=='wysija_config'){
543
+ $jstrans['urlpremium']='#tab-premium';
544
+ }
545
+ wp_localize_script('wysija-admin', 'wysijatrans', $jstrans);
546
+ }
547
+
548
+
549
+ /**
550
+ * code only executed in the page or post in admin
551
+ */
552
+ function addCodeToPagePost(){
553
+
554
+ //code to add external buttons to the tmce only if the user has the rights to add the forms
555
+ if(get_user_option('rich_editing') == 'true') {
556
+ add_filter("mce_external_plugins", array($this,"addRichPlugin"));
557
+ add_filter('mce_buttons', array($this,'addRichButton1'),999);
558
+ $myStyleUrl = WYSIJA_URL."css/tmce/style.css";
559
+ add_editor_style($myStyleUrl);
560
+ //add_filter('tiny_mce_before_init', array($this,'TMCEinnercss'),12 );
561
+ wp_enqueue_style('custom_TMCE_admin_css', WYSIJA_URL.'css/tmce/panelbtns.css');
562
+ wp_print_styles('custom_TMCE_admin_css');
563
+
564
+ }
565
+ }
566
+
567
+ function addRichPlugin($plugin_array) {
568
+ global $wp_version;
569
+
570
+ if ( version_compare( $wp_version, '3.9', '<' ) ){
571
+ $suffix = '';
572
+ } else {
573
+ $suffix = '_39';
574
+ }
575
+
576
+ $plugin_array['wysija_register'] = WYSIJA_URL.'mce/wysija_register/editor_plugin'.$suffix.'.js';
577
+
578
+ return $plugin_array;
579
+ }
580
+
581
+ function addRichButton1($buttons) {
582
+ $newButtons=array();
583
+ foreach($buttons as $value) $newButtons[]=$value;
584
+ array_push($newButtons, '|', 'wysija_register');
585
+ return $newButtons;
586
+ }
587
+
588
+ function admin_footer_text($text) {
589
+ $screen = get_current_screen();
590
+ if (strpos($screen->base, 'wysija')===false)
591
+ return $text;
592
+
593
+ return
594
+ "<a target='_blank' href='http://support.mailpoet.com/feedback/?utm_source=wpadmin&utm_campaign=contact_footer'>" . __( 'Contact Support', WYSIJA ) . "</a>" .
595
+ " | " .
596
+ str_replace(
597
+ array('[stars]','[link]','[/link]'),
598
+ array('<a target="_blank" href="http://clicky.me/wp-reviews" >&#9733;&#9733;&#9733;&#9733;&#9733;</a>','<a target="_blank" href="http://clicky.me/wp-reviews" >','</a>'),
599
+ __('Add your [stars] on [link]wordpress.org[/link] and keep this plugin essentially free.',WYSIJA)
600
+ ) .
601
+ "";
602
+ }
603
+
604
+ function update_footer($text){
605
+ $screen = get_current_screen();
606
+ if (strpos($screen->base, 'wysija')===false)
607
+ return $text;
608
+
609
+ $version_link = esc_url(add_query_arg(
610
+ array(
611
+ 'page' => 'wysija_campaigns',
612
+ 'action' => 'whats_new',
613
+ ),
614
+ admin_url('admin.php')
615
+ ));
616
+
617
+ $version_string = "</p>" .
618
+ "<p class='alignright'>" .
619
+ __("MailPoet Version", WYSIJA) . ": <a href='{$version_link}'>" . esc_attr(WYSIJA::get_version()) . "</a>";
620
+
621
+ $version_string = apply_filters('mailpoet_back_footer', $version_string);
622
+ return $version_string;
623
+
624
+ }
625
+ }
trunk/helpers/backloader.php ADDED
@@ -0,0 +1,419 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'WYSIJA' ) or die( 'Restricted access' );
3
+
4
+ /**
5
+ * class managing the admin vital part to integrate wordpress
6
+ */
7
+ class WYSIJA_help_backloader extends WYSIJA_help{
8
+
9
+ var $jsVariables = '';
10
+
11
+ function __construct() {
12
+ parent::__construct();
13
+ }
14
+
15
+ /**
16
+ *
17
+ * @param type $controller
18
+ */
19
+ function init( &$controller ) {
20
+ wp_enqueue_style( 'wysija-admin-css', WYSIJA_URL . 'css/admin.css', array(), WYSIJA::get_version() );
21
+ wp_enqueue_script( 'wysija-admin', WYSIJA_URL . 'js/admin.js', array( 'jquery' ), true, WYSIJA::get_version() );
22
+
23
+ /* default script on all wysija interfaces in admin */
24
+ wp_enqueue_script( 'wysija-admin-if ', WYSIJA_URL . 'js/admin-wysija.js', array( 'jquery' ), WYSIJA::get_version() );
25
+
26
+ // TO IMPROVE: This has NOTHING TO DO HERE. It has to be moved to the subscribers controller
27
+ if ( ! $controller->jsTrans ) {
28
+ $controller->jsTrans['selecmiss'] = __( 'Please make a selection first!', WYSIJA );
29
+ $controller->jsTrans['suredelete'] = __( 'Deleting a list will not delete any subscribers.', WYSIJA );
30
+ }
31
+
32
+ $controller->jsTrans['sure_to_switch_package'] = __( 'Do you want to install that version?', WYSIJA );
33
+ $controller->js[] = 'wysija-admin-ajax';
34
+ $controller->js[] = 'thickbox';
35
+ wp_enqueue_style( 'thickbox' );
36
+ }
37
+
38
+ /**
39
+ * help to automatically loads scripts and stylesheets based on the request
40
+ * @param type $pagename
41
+ * @param type $dirname
42
+ * @param type $urlname
43
+ * @param type $controller
44
+ * @param type $extension
45
+ * @return type
46
+ */
47
+ function load_assets( $pagename, $dirname, $urlname, &$controller, $extension = 'newsletter' ) {
48
+
49
+ if ( isset( $_REQUEST['action'] ) ) {
50
+ $action = $_REQUEST['action'];
51
+
52
+ //add form validators script for add and edit
53
+ if ( ( $action == 'edit' || $action == 'add' ) && is_object( $controller ) ) {
54
+ $controller->js[] = 'wysija-validator';
55
+ }
56
+ } else {
57
+ $action = 'default';
58
+
59
+ //load the listing script
60
+ if ( $pagename != 'config' ) {
61
+ wp_enqueue_script( 'wysija-admin-list' );
62
+ }
63
+ }
64
+ //check for files based on this combinations of parameters pagename or pagename and action
65
+ $possibleParameters = array( array( $pagename ), array( $pagename, $action ) );
66
+ $enqueueFileTypes = array( 'wp_enqueue_script' => array( 'js' => 'js', 'php' => 'js' ), 'wp_enqueue_style' => array( 'css' => 'css' ) );
67
+
68
+ // Files that we have, don't use file_exists if we know which files we have
69
+ $files = (object) array(
70
+ 'css' => array(
71
+ 'add-ons',
72
+ 'admin-campaigns-articles',
73
+ 'admin-campaigns-autopost',
74
+ 'admin-campaigns-bookmarks',
75
+ 'admin-campaigns-dividers',
76
+ 'admin-campaigns-editDetails',
77
+ 'admin-campaigns-editTemplate',
78
+ 'admin-campaigns-medias',
79
+ 'admin-campaigns-themes',
80
+ 'admin-campaigns-viewstats',
81
+ 'admin-campaigns-welcome_new',
82
+ 'admin-campaigns',
83
+ 'admin-global',
84
+ 'admin-premium',
85
+ 'admin-statistics',
86
+ 'admin-subscribers-addlist',
87
+ 'admin-subscribers-edit',
88
+ 'admin-subscribers-export',
89
+ 'admin-subscribers-exportlist',
90
+ 'admin-subscribers-import',
91
+ 'admin-subscribers-importmatch',
92
+ 'admin-subscribers-lists',
93
+ 'admin-widget',
94
+ 'admin-config',
95
+ 'admin-config-form_widget_settings',
96
+ ),
97
+ 'js' => array(
98
+ 'admin-ajax-proto',
99
+ 'admin-ajax',
100
+ 'admin-campaigns-articles',
101
+ 'admin-campaigns-autopost',
102
+ 'admin-campaigns-bookmarks',
103
+ 'admin-campaigns-default',
104
+ 'admin-campaigns-dividers',
105
+ 'admin-campaigns-edit',
106
+ 'admin-campaigns-editAutonl',
107
+ 'admin-campaigns-editDetails',
108
+ 'admin-campaigns-editTemplate',
109
+ 'admin-campaigns-image_data',
110
+ 'admin-campaigns-medias',
111
+ 'admin-campaigns-themes',
112
+ 'admin-campaigns-viewstats',
113
+ 'admin-campaigns-welcome_new',
114
+ 'admin-config-form_widget_settings',
115
+ 'admin-config-settings',
116
+ 'admin-global',
117
+ 'admin-listing',
118
+ 'admin-statistics-filter',
119
+ 'admin-statistics',
120
+ 'admin-subscribers-export',
121
+ 'admin-subscribers-import',
122
+ 'admin-subscribers-importmatch',
123
+ 'admin-subscribers',
124
+ 'admin-tmce',
125
+ 'admin-wysija-global',
126
+ 'admin-wysija',
127
+ )
128
+ );
129
+
130
+ foreach ( $possibleParameters as $params ) {
131
+ foreach ( $enqueueFileTypes as $method => $types ) {
132
+ foreach ( $types as $file_type => $file_ext ){
133
+ $file_slug = 'admin-' . implode( '-', $params );
134
+ if ( in_array( $file_slug, $files->{ $file_ext } ) ) {
135
+ $file_id = "wysija-autoinc-{$extension}-{$file_slug}-{$file_ext}";
136
+ $file_url = "{$urlname}{$file_ext}/{$file_slug}.{$file_ext}";
137
+ call_user_func_array( $method, array( $file_id, $file_url, array(), WYSIJA::get_version() ) );
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ return true;
144
+ }
145
+
146
+ /**
147
+ * enqueue and load dif ferent scripts and style based on one script being requested in the controller
148
+ * @param type $controller
149
+ * @param type $pagename
150
+ * @param string $urlbase
151
+ */
152
+ function parse_js( &$controller, $pagename, $urlbase = WYSIJA_URL ){
153
+
154
+ // find out the name of the plugin based on the urlbase parameter
155
+ $plugin = substr( strrchr( substr( $urlbase, 0, strlen( $urlbase ) - 1 ), '/' ), 1 );
156
+
157
+ /* enqueue all the scripts that have been declared in the controller */
158
+ if ( $controller->js ) {
159
+ foreach ( $controller->js as $kjs => $js ) {
160
+ switch ( $js ) {
161
+ case 'jquery-ui-tabs':
162
+ wp_enqueue_script( $js );
163
+ wp_enqueue_style( 'wysija-tabs-css', WYSIJA_URL . 'css/smoothness/jquery-ui-1.8.20.custom.css', array(), WYSIJA::get_version() );
164
+ break;
165
+
166
+ case 'wysija-validator':
167
+ wp_enqueue_script( 'wysija-validator-lang' );
168
+ wp_enqueue_script( $js );
169
+ wp_enqueue_script( 'wysija-form' );
170
+ wp_enqueue_style( 'validate-engine-css' );
171
+ break;
172
+
173
+ case 'wysija-admin-ajax':
174
+ if ( $plugin != 'wysija-newsletters' ){
175
+ $ajaxvarname = $plugin;
176
+ } else {
177
+ $ajaxvarname = 'wysija';
178
+ }
179
+
180
+ $dataajaxxx = array(
181
+ 'action' => 'wysija_ajax',
182
+ 'controller' => $pagename,
183
+ 'wysijaplugin' => $plugin,
184
+ 'dataType' => 'json',
185
+ 'ajaxurl' => admin_url( 'admin-ajax.php', 'relative' ),
186
+ // 'ajaxurl' => plugins_url( 'wysija-newsletters' ).'/core/ajax.php',
187
+ 'pluginurl' => plugins_url( 'wysija-newsletters' ),
188
+ 'loadingTrans' => __( 'Loading...', WYSIJA )
189
+ );
190
+
191
+ if ( is_user_logged_in() ){
192
+ $dataajaxxx['adminurl'] = admin_url( 'admin.php' );
193
+ }
194
+
195
+ wp_localize_script( 'wysija-admin-ajax', $ajaxvarname.'AJAX',$dataajaxxx );
196
+ wp_enqueue_script( 'jquery-ui-dialog' );
197
+ wp_enqueue_script( $js );
198
+ wp_enqueue_style( 'wysija-tabs-css', WYSIJA_URL . 'css/smoothness/jquery-ui-1.8.20.custom.css', array(), WYSIJA::get_version() );
199
+ break;
200
+
201
+ case 'wysija-admin-ajax-proto':
202
+ wp_enqueue_script( $js );
203
+ break;
204
+
205
+ case 'wysija-edit-autonl':
206
+ wp_enqueue_script( 'wysija-edit-autonl', WYSIJA_URL . 'js/admin-campaigns-editAutonl.js', array( 'jquery' ), WYSIJA::get_version() );
207
+ break;
208
+
209
+ case 'wysija-scriptaculous':
210
+ // include prototypeJS + scriptaculous & addons
211
+ wp_enqueue_script( 'wysija-prototype', WYSIJA_URL . 'js/prototype/prototype.js', array(), WYSIJA::get_version() );
212
+ wp_enqueue_script( 'wysija-proto-scriptaculous', WYSIJA_URL . 'js/prototype/scriptaculous.js', array( 'wysija-prototype' ), WYSIJA::get_version() );
213
+ wp_enqueue_script( 'wysija-proto-dragdrop', WYSIJA_URL . 'js/prototype/dragdrop.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
214
+ wp_enqueue_script( 'wysija-proto-controls', WYSIJA_URL . 'js/prototype/controls.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
215
+ wp_enqueue_script( 'wysija-proto-slider', WYSIJA_URL . 'js/prototype/slider.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
216
+ break;
217
+
218
+ case 'mailpoet-select2':
219
+
220
+ wp_enqueue_script( 'mailpoet-select2', WYSIJA_URL . 'js/select2/select2.min.js', array( 'jquery' ), WYSIJA::get_version() );
221
+ wp_enqueue_script( 'mailpoet-select2-l10n', WYSIJA_URL . 'js/select2/select2-l10n.js', array( 'mailpoet-select2', 'underscore' ), WYSIJA::get_version() );
222
+
223
+ wp_enqueue_style( 'mailpoet-select2', WYSIJA_URL . 'css/select2/select2.css', array(), WYSIJA::get_version() );
224
+
225
+ wp_localize_script(
226
+ 'mailpoet-select2-l10n',
227
+ 'mailpoet_l10n_select2',
228
+ array(
229
+ 'noMatches' => __( 'No Results were found', WYSIJA ),
230
+ 'inputTooShort' => __( 'Please enter <%= chars %> more character<%= plural %>', WYSIJA ),
231
+ 'inputTooLong' => __( 'Please delete <%= chars %> character<%= plural %>', WYSIJA ),
232
+ 'selectionTooBig' => __( 'You can only select <%= chars %> item<%= plural %>', WYSIJA ),
233
+ 'loadMore' => __( 'Loading more Results...', WYSIJA ),
234
+ 'searching' => __( 'Searching...', WYSIJA ),
235
+ )
236
+ );
237
+
238
+ break;
239
+
240
+ case 'mailpoet-field-select2-terms':
241
+ wp_enqueue_script( 'mailpoet-field-select2-terms', WYSIJA_URL . 'js/fields/select2-terms.js', array( 'jquery', 'underscore', 'mailpoet-select2' ), WYSIJA::get_version() );
242
+
243
+ break;
244
+
245
+ case 'mailpoet-field-select2-simple':
246
+ wp_enqueue_script( 'mailpoet-field-select2-simple', WYSIJA_URL . 'js/fields/select2-simple.js', array( 'jquery', 'underscore', 'mailpoet-select2' ), WYSIJA::get_version() );
247
+
248
+ break;
249
+
250
+ case 'wysija-form-editor':
251
+ wp_enqueue_script( 'wysija-prototype', WYSIJA_URL . 'js/prototype/prototype.js', array(), WYSIJA::get_version() );
252
+ wp_enqueue_script( 'wysija-proto-scriptaculous', WYSIJA_URL . 'js/prototype/scriptaculous.js', array( 'wysija-prototype' ), WYSIJA::get_version() );
253
+ wp_enqueue_script( 'wysija-proto-dragdrop', WYSIJA_URL . 'js/prototype/dragdrop.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
254
+ wp_enqueue_script( 'wysija-proto-controls', WYSIJA_URL . 'js/prototype/controls.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
255
+ wp_enqueue_script( 'wysija-proto-slider', WYSIJA_URL . 'js/prototype/slider.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
256
+
257
+ // include form editor
258
+ wp_enqueue_script( $js, WYSIJA_URL . 'js/' . $js . '.js', array(), WYSIJA::get_version() );
259
+
260
+ /* MailPoet form editor i18n */
261
+ wp_localize_script( 'wysija-form-editor', 'Wysija_i18n', $controller->jsTrans );
262
+
263
+ // form editor css
264
+ wp_enqueue_style( 'wysija-form-editor-css', WYSIJA_URL . 'css/wysija-form-editor.css', array(), WYSIJA::get_version() );
265
+ break;
266
+
267
+ case 'wysija-amcharts':
268
+ // MailPoet chart
269
+ wp_enqueue_script( 'amcharts', WYSIJA_URL . 'js/amcharts/amcharts.js', array(), WYSIJA::get_version() );
270
+ wp_enqueue_script( 'wysija-amcharts', WYSIJA_URL . 'js/wysija-charts.js', array(), WYSIJA::get_version() );
271
+ break;
272
+
273
+ case 'wysija-editor':
274
+
275
+ wp_enqueue_script( 'wysija-prototype', WYSIJA_URL . 'js/prototype/prototype.js', array(), WYSIJA::get_version() );
276
+ wp_deregister_script( 'thickbox' );
277
+
278
+ wp_register_script( 'thickbox', WYSIJA_URL . 'js/thickbox/thickbox.js', array( 'jquery' ), WYSIJA::get_version() );
279
+
280
+ wp_localize_script(
281
+ 'thickbox',
282
+ 'thickboxL10n',
283
+ array(
284
+ 'next' => __( 'Next &gt;' ),
285
+ 'prev' => __( '&lt; Prev' ),
286
+ 'image' => __( 'Image' ),
287
+ 'of' => __( 'of' ),
288
+ 'close' => __( 'Close' ),
289
+ 'noif rames' => __( 'This feature requires inline frames. You have iframes disabled or your browser does not support them.' ),
290
+ 'l10n_print_after' => 'try{convertEntities( thickboxL10n );}catch( e ){};',
291
+ )
292
+ );
293
+
294
+ wp_enqueue_script( 'wysija-proto-scriptaculous', WYSIJA_URL . 'js/prototype/scriptaculous.js' , array( 'wysija-prototype' ), WYSIJA::get_version() );
295
+ wp_enqueue_script( 'wysija-proto-dragdrop', WYSIJA_URL . 'js/prototype/dragdrop.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
296
+ wp_enqueue_script( 'wysija-proto-controls', WYSIJA_URL . 'js/prototype/controls.js', array( 'wysija-proto-scriptaculous' ), WYSIJA::get_version() );
297
+ wp_enqueue_script( 'wysija-timer', WYSIJA_URL . 'js/timer.js', array(), WYSIJA::get_version() );
298
+ wp_enqueue_script( $js, WYSIJA_URL . 'js/' . $js . '.js', array(), WYSIJA::get_version() );
299
+ wp_enqueue_script( 'wysija-konami', WYSIJA_URL . 'js/konami.js', array(), WYSIJA::get_version() );
300
+ wp_enqueue_script( 'wysija-tinymce', WYSIJA_URL . 'js/tinymce/tiny_mce.js', array(), WYSIJA::get_version() );
301
+
302
+ wp_enqueue_script( 'wysija-tinymce-init', WYSIJA_URL . 'js/tinymce_init.js', array(), WYSIJA::get_version() );
303
+ wp_enqueue_style( 'wysija-editor-css', WYSIJA_URL . 'css/wysija-editor.css', array(), WYSIJA::get_version() );
304
+ wp_enqueue_script( 'wysija-colorpicker', WYSIJA_URL . 'js/excolor/jquery.modcoder.excolor.js', array(), WYSIJA::get_version() );
305
+
306
+ if ( version_compare( $GLOBALS['wp_version'], '3.9', '>=' ) ){
307
+ wp_enqueue_style( 'mailpoet-tinymce', WYSIJA_URL . 'css/tmce/editor.css', array(), WYSIJA::get_version() );
308
+ }
309
+
310
+ /* MailPoet editor i18n */
311
+ wp_localize_script( 'wysija-editor', 'Wysija_i18n', $controller->jsTrans );
312
+ break;
313
+
314
+ case 'wysija-colorpicker':
315
+ wp_enqueue_script( 'wysija-colorpicker', WYSIJA_URL . 'js/excolor/jquery.modcoder.excolor.js', array(), WYSIJA::get_version() );
316
+ break;
317
+
318
+ case 'wysija-tooltip':
319
+ wp_enqueue_script( 'mailpoet.tooltip', WYSIJA_URL . 'js/vendor/bootstrap.tooltip.js', array( 'jquery' ), WYSIJA::get_version(), true );
320
+ wp_enqueue_style( 'mailpoet.tooltip', WYSIJA_URL . 'css/vendor/bootstrap.tooltip.css', array(), WYSIJA::get_version(), 'screen' );
321
+ break;
322
+
323
+ case 'wysija-import-match':
324
+ wp_enqueue_script('jquery-matchColumn', WYSIJA_URL.'js/jquery/jquery.matchColumn.js', array('jquery'), WYSIJA::get_version());
325
+ wp_enqueue_script('jquery-userStatusMapping', WYSIJA_URL.'js/jquery/jquery.userStatusMapping.js', array('jquery'), WYSIJA::get_version());
326
+ break;
327
+
328
+ default:
329
+ if ( is_string( $kjs ) ) {
330
+ // check if there's a trailing slash in the urlbase
331
+ if ( substr( $urlbase, -1 ) !== '/' ){
332
+ $urlbase .= '/';
333
+ }
334
+ // check if there's already an extension specif ied for the file
335
+ if ( substr( $urlbase, -3 ) !== '.js' ){
336
+ $js .= '.js';
337
+ }
338
+ // enqueue script
339
+
340
+ wp_enqueue_script( $kjs, $urlbase . 'js/' . $js, array(), WYSIJA::get_version() );
341
+ } else {
342
+ wp_enqueue_script( $js );
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ /**
350
+ * add some js defined variable per script
351
+ * @param type $pagename
352
+ * @param type $dirname
353
+ * @param type $urlname
354
+ * @param type $controller
355
+ * @param type $extension
356
+ */
357
+ function localize( $pagename, $dirname, $urlname, &$controller, $extension = 'newsletter' ){
358
+ if ( $controller->jsLoc ){
359
+ foreach ( $controller->jsLoc as $key => $value ){
360
+ foreach ( $value as $kf => $local ){
361
+
362
+ //this function accepts multidimensional array some version like wp3.2.1 couldn't do that
363
+ $this->localizeme( $key, $kf, $local );
364
+ }
365
+ }
366
+ }
367
+ }
368
+
369
+ /**
370
+ * multidimensional array are possible here
371
+ * @param type $handle
372
+ * @param type $object_name
373
+ * @param type $l10n
374
+ */
375
+ function localizeme( $handle, $object_name, $l10n ) {
376
+
377
+ foreach ( ( array ) $l10n as $key => $value ) {
378
+ if ( ! is_scalar( $value ) ){
379
+ continue;
380
+ }
381
+ $l10n[$key] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8' );
382
+ }
383
+
384
+ $this->jsVariables .= "var $object_name = " . json_encode( $l10n ) . ';';
385
+ add_action( 'admin_head', array( $this, 'localize_print' ) );
386
+ }
387
+
388
+ /**
389
+ * load the variables in the html
390
+ */
391
+ function localize_print(){
392
+ echo "<script type='text/javascript' id='mailpoet-localized'>\n"; // CDATA and type='text/javascript' is not needed for HTML 5
393
+ echo "/* <![CDATA[ */\n";
394
+ echo esc_attr( '' ) . $this->jsVariables . "\n"; // To comply with PHP Code Sniffer WordPress Standards before we "hack" the echo
395
+ echo "/* ]]> */\n";
396
+ echo "</script>\n";
397
+ }
398
+
399
+
400
+
401
+ /**
402
+ * this is for backward compatibility and avoid blank screen on older version of the premium plugin
403
+ */
404
+ function loadScriptsStyles( $pagename, $dirname, $urlname, &$controller, $extension = 'newsletter' ) {
405
+ return $this->load_assets( $pagename, $dirname, $urlname, $controller, $extension );
406
+ }
407
+
408
+ /**
409
+ * this is for backward compatibility and avoid blank screen on older version of the premium plugin
410
+ */
411
+ function initLoad( &$controller ){
412
+ return $this->init( $controller );
413
+ }
414
+
415
+ function jsParse( &$controller, $pagename, $urlbase = WYSIJA_URL ){
416
+ $this->parse_js( $controller, $pagename, $urlbase );
417
+ }
418
+
419
+ }
trunk/helpers/bookmarks.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_bookmarks extends WYSIJA_object {
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ }
8
+
9
+ /**
10
+ * Get all bookmarks based on size
11
+ * @param string $size
12
+ * @return array
13
+ */
14
+ function getAll($size = 'medium', $theme = 'default') {
15
+ $theme = basename($theme);
16
+ $fileHelper = WYSIJA::get('file', 'helper');
17
+ $dirHandle = $fileHelper->exists('bookmarks'.DS.$size);
18
+
19
+ if($dirHandle['result'] === FALSE) {
20
+ return array();
21
+ } else {
22
+ $bookmarks = array();
23
+
24
+ // if size is medium and the current theme is not default, load theme's bookmarks
25
+ if($size === 'medium' and $theme !== 'default') {
26
+ $themeIcons = $this->getAllByTheme($theme, 'url');
27
+ if(!empty($themeIcons)) {
28
+ $bookmarks['00'] = $themeIcons;
29
+ }
30
+ }
31
+
32
+ $sourceDir = $dirHandle['file'];
33
+ $iconsets = scandir($sourceDir);
34
+ foreach($iconsets as $iconset) {
35
+ // loop through each iconset
36
+ if(in_array($iconset, array('.', '..', '.DS_Store', 'Thumbs.db')) === FALSE and is_dir($sourceDir.DS.$iconset)) {
37
+
38
+ // get all icons from current iconset
39
+ $icons = scandir($sourceDir.DS.$iconset);
40
+ foreach($icons as $icon) {
41
+ if(in_array($icon, array('.', '..', '.DS_Store', 'Thumbs.db')) === FALSE and strrpos($icon, '.txt') === FALSE) {
42
+ $info = pathinfo($sourceDir.DS.$iconset.DS.$icon);
43
+ $bookmarks[$iconset][basename($icon, '.'.$info['extension'])] = $fileHelper->url($icon, 'bookmarks'.DS.$size.DS.$iconset);
44
+ }
45
+ }
46
+ }
47
+ }
48
+ return $bookmarks;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Get all bookmarks based on size for a given iconset
54
+ * @param string $size
55
+ * @param string $iconset
56
+ * @return array
57
+ */
58
+ function getAllByIconset($size = 'medium', $iconset)
59
+ {
60
+ $iconset = basename($iconset);
61
+ $fileHelper = WYSIJA::get('file', 'helper');
62
+ $dirHandle = $fileHelper->exists('bookmarks'.DS.$size.DS.$iconset);
63
+
64
+ if($dirHandle['result'] === FALSE) {
65
+ return array();
66
+ } else {
67
+ $bookmarks = array();
68
+ $sourceDir = $dirHandle['file'];
69
+ $icons = scandir($sourceDir);
70
+ foreach($icons as $icon) {
71
+ if(in_array($icon, array('.', '..', '.DS_Store', 'Thumbs.db')) === FALSE and strrpos($icon, '.txt') === FALSE) {
72
+ $info = pathinfo($sourceDir.DS.$icon);
73
+ $dimensions = @getimagesize($sourceDir.DS.$icon);
74
+ $bookmarks[basename($icon, '.'.$info['extension'])] = array(
75
+ 'src' => $fileHelper->url($icon, 'bookmarks/'.$size.'/'.$iconset),
76
+ 'width' => $dimensions[0],
77
+ 'height' => $dimensions[1]
78
+ );
79
+ }
80
+ }
81
+ return $bookmarks;
82
+ }
83
+ }
84
+
85
+ function getAllByTheme($theme, $type = 'all')
86
+ {
87
+ $theme = basename($theme);
88
+ $fileHelper = WYSIJA::get('file', 'helper');
89
+ $dirHandle = $fileHelper->exists('themes'.DS.$theme.DS.'bookmarks');
90
+
91
+ if($dirHandle['result'] === FALSE) {
92
+ return array();
93
+ } else {
94
+ $bookmarks = array();
95
+ $sourceDir = $dirHandle['file'];
96
+ $icons = scandir($sourceDir);
97
+ foreach($icons as $icon) {
98
+ if(in_array($icon, array('.', '..', '.DS_Store', 'Thumbs.db')) === FALSE and strrpos($icon, '.txt') === FALSE) {
99
+
100
+ if($type === 'all') {
101
+ $info = pathinfo($sourceDir.DS.$icon);
102
+ $dimensions = @getimagesize($sourceDir.DS.$icon);
103
+ $bookmarks[basename($icon, '.'.$info['extension'])] = array(
104
+ 'src' => $fileHelper->url($icon, 'themes/'.$theme.'/bookmarks'),
105
+ 'width' => $dimensions[0],
106
+ 'height' => $dimensions[1]
107
+ );
108
+ } else if($type === 'url') {
109
+ $info = pathinfo($sourceDir.DS.$icon);
110
+ $bookmarks[basename($icon, '.'.$info['extension'])] = $fileHelper->url($icon, 'themes/'.$theme.'/bookmarks');
111
+ }
112
+ }
113
+ }
114
+ return $bookmarks;
115
+ }
116
+ }
117
+ }
trunk/helpers/bounce.php ADDED
@@ -0,0 +1,1110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+
4
+ class WYSIJA_help_bounce extends WYSIJA_help {
5
+
6
+ var $report = false;
7
+ var $config;
8
+ var $mailer;
9
+ var $mailbox;
10
+ var $_message;
11
+ var $listsubClass;
12
+ var $subClass;
13
+ var $db;
14
+ var $deletedUsers = array();
15
+ var $unsubscribedUsers = array();
16
+ var $addtolistUsers = array();
17
+ var $bounceMessages = array();
18
+ var $listdetails = array();
19
+ var $usepear = false;
20
+ var $detectEmail = '/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@([a-z0-9\-]+\.)+[a-z0-9]{2,8}/i';
21
+ var $messages = array();
22
+ var $record_ms_bounce = false; // only used in multisite scenario
23
+
24
+ function __construct() {
25
+ $this->config = WYSIJA::get('config', 'model');
26
+ $this->mailer = WYSIJA::get('mailer', 'helper');
27
+ $this->rulesClass = WYSIJA::get('rules', 'helper');
28
+ $this->mailer->report = false;
29
+ $this->subClass = WYSIJA::get('user', 'model'); //acymailing_get('class.subscriber');
30
+ $this->listsubClass = WYSIJA::get('user_list', 'model'); //acymailing_get('class.listsub');
31
+ $this->listsubClass->checkAccess = false;
32
+ $this->listsubClass->sendNotif = false;
33
+ $this->listsubClass->sendConf = false;
34
+ $this->historyClass = WYSIJA::get('user_history', 'model');
35
+ }
36
+
37
+ function init($config = false) {
38
+ if ($config) {
39
+ //unset($this->config->values);
40
+ foreach ($config as $key => $val)
41
+ $this->config->values[$key] = $val;
42
+ }
43
+ if ($this->config->getValue('bounce_connection_method') == 'pear') {
44
+ $this->usepear = true;
45
+ include_once(WYSIJA_INC . 'pear' . DS . 'pop3.php');
46
+ return true;
47
+ }
48
+
49
+ if (extension_loaded('imap') OR function_exists('imap_open'))
50
+ return true;
51
+
52
+ $prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
53
+ $EXTENSION = $prefix . 'imap.' . PHP_SHLIB_SUFFIX;
54
+
55
+ if (function_exists('dl')) {
56
+ //We will try to load it on the fly
57
+ $fatalMessage = 'The system tried to load dynamically the ' . $EXTENSION . ' extension';
58
+ $fatalMessage .= '<br/>If you see this message, that means the system could not load this PHP extension';
59
+ $fatalMessage .= '<br/>Please enable the PHP Extension ' . $EXTENSION;
60
+ ob_start();
61
+ echo $fatalMessage;
62
+ //This method could cause a fatal error, but we will still display some messages in that case.
63
+ dl($EXTENSION);
64
+ $warnings = str_replace($fatalMessage, '', ob_get_clean());
65
+ if (extension_loaded('imap') OR function_exists('imap_open'))
66
+ return true;
67
+ }
68
+
69
+ if ($this->report) {
70
+ $this->error('The extension "' . $EXTENSION . '" could not be loaded, please change your PHP configuration to enable it or use the pop3 method without imap extension', true);
71
+ if (!empty($warnings))
72
+ $this->error($warnings, true);
73
+ }
74
+
75
+ return false;
76
+ }
77
+
78
+ function connect() {
79
+ if ($this->usepear)
80
+ return $this->_connectpear();
81
+ return $this->_connectimap();
82
+ }
83
+
84
+ function _connectpear() {
85
+ ob_start();
86
+ $this->mailbox = new Net_POP3();
87
+
88
+ $timeout = $this->config->getValue('bounce_timeout');
89
+ if (!empty($timeout))
90
+ $this->mailbox->setTimeOut($timeout);
91
+
92
+ $port = intval($this->config->getValue('bounce_port', ''));
93
+ if (empty($port))
94
+ $port = '110/pop3/notls';
95
+
96
+ $serverName = $this->config->getValue('bounce_host');
97
+ $secure = $this->config->getValue('bounce_connection_secure', '');
98
+ //We don't add back the ssl:// or tls:// if it's already there
99
+ if (!empty($secure) AND !strpos($serverName, '://'))
100
+ $serverName = $secure . '://' . $serverName;
101
+
102
+ if (!$this->mailbox->connect($serverName, $port)) {
103
+ $warnings = ob_get_clean();
104
+ if ($this->report) {
105
+ $this->error('Error connecting to the server ' . $this->config->getValue('bounce_host') . ' : ' . $port, true);
106
+ return false;
107
+ }
108
+ if (!empty($warnings) AND $this->report)
109
+ $this->error($warnings, true);
110
+ return false;
111
+ }
112
+
113
+ $login = $this->mailbox->login(trim($this->config->getValue('bounce_login')), trim($this->config->getValue('bounce_password')), 'USER');
114
+ if (empty($login) OR isset($login->code)) {
115
+ $warnings = ob_get_clean();
116
+ if ($this->report) {
117
+ $this->error('Identication error ' . $this->config->getValue('bounce_login') . ':' . $this->config->getValue('bounce_password'), true);
118
+ return false;
119
+ }
120
+ if (!empty($warnings) AND $this->report)
121
+ $this->error($warnings, true);
122
+ return false;
123
+ }
124
+
125
+ ob_clean();
126
+
127
+ return true;
128
+ }
129
+
130
+ function _connectimap() {
131
+ ob_start();
132
+ //First we reset the buffer or errors and warnings
133
+ $buff = imap_alerts();
134
+ $buff = imap_errors();
135
+
136
+ $timeout = $this->config->getValue('bounce_timeout');
137
+ if (!empty($timeout))
138
+ imap_timeout(IMAP_OPENTIMEOUT, $timeout);
139
+
140
+ $port = $this->config->getValue('bounce_port', '');
141
+ $secure = $this->config->getValue('bounce_connection_secure', '');
142
+ $protocol = $this->config->getValue('bounce_connection_method', '');
143
+ $serverName = '{' . $this->config->getValue('bounce_host');
144
+ if (empty($port)) {
145
+ if ($secure == 'ssl' && $protocol == 'imap')
146
+ $port = '993';
147
+ elseif ($protocol == 'imap')
148
+ $port = '143';
149
+ elseif ($protocol == 'pop3')
150
+ $port = '110';
151
+ }
152
+
153
+
154
+ if (!empty($port))
155
+ $serverName .= ':' . $port;
156
+ //Add the secure protocol (TLS or SSL)
157
+ if (!empty($secure))
158
+ $serverName .= '/' . $secure;
159
+ if ($this->config->getValue('bounce_selfsigned', false))
160
+ $serverName .= '/novalidate-cert';
161
+ //Add the method (imap by default) ex : pop3
162
+ if (!empty($protocol))
163
+ $serverName .='/service=' . $protocol;
164
+ $serverName .= '}';
165
+ $this->mailbox = imap_open($serverName, trim($this->config->getValue('bounce_login')), trim($this->config->getValue('bounce_password')));
166
+ $warnings = ob_get_clean();
167
+
168
+ if ($this->report) {
169
+ if (!$this->mailbox) {
170
+ $this->error('Error connecting to ' . $serverName, true);
171
+ }
172
+ if (!empty($warnings)) {
173
+ $this->error($warnings, true);
174
+ }
175
+ }
176
+
177
+
178
+ return $this->mailbox ? true : false;
179
+ }
180
+
181
+ function getNBMessages() {
182
+ if ($this->usepear) {
183
+ $this->nbMessages = $this->mailbox->numMsg();
184
+ } else {
185
+ $this->nbMessages = imap_num_msg($this->mailbox);
186
+ }
187
+
188
+ return $this->nbMessages;
189
+ }
190
+
191
+ function getMessage($msgNB) {
192
+ if ($this->usepear) {
193
+ $message = new \stdClass;
194
+ $message->headerString = $this->mailbox->getRawHeaders($msgNB);
195
+ if (empty($message->headerString))
196
+ return false;
197
+ }else {
198
+ $message = imap_headerinfo($this->mailbox, $msgNB);
199
+ }
200
+
201
+ return $message;
202
+ }
203
+
204
+ function deleteMessage($msgNB) {
205
+ if ($this->usepear) {
206
+ $this->mailbox->deleteMsg($msgNB);
207
+ } else {
208
+ imap_delete($this->mailbox, $msgNB);
209
+ imap_expunge($this->mailbox);
210
+ }
211
+ }
212
+
213
+ function close() {
214
+ if ($this->usepear) {
215
+ $this->mailbox->disconnect();
216
+ } else {
217
+ imap_close($this->mailbox);
218
+ }
219
+ }
220
+
221
+ function decodeMessage() {
222
+ if ($this->usepear) {
223
+ return $this->_decodeMessagepear();
224
+ } else {
225
+ return $this->_decodeMessageimap();
226
+ }
227
+ }
228
+
229
+ function _decodeMessagepear() {
230
+ $this->_message->headerinfo = $this->mailbox->getParsedHeaders($this->_message->messageNB);
231
+
232
+ if (empty($this->_message->headerinfo['subject']))
233
+ return false;
234
+ $this->_message->text = '';
235
+ $this->_message->html = $this->mailbox->getBody($this->_message->messageNB);
236
+ $this->_message->subject = $this->_decodeHeader($this->_message->headerinfo['subject']);
237
+ $this->_message->header->sender_email = (isset($this->_message->headerinfo['return-path'])) ? $this->_message->headerinfo['return-path'] : '';
238
+ if (is_array($this->_message->header->sender_email))
239
+ $this->_message->header->sender_email = reset($this->_message->header->sender_email);
240
+ if (preg_match($this->detectEmail, $this->_message->header->sender_email, $results)) {
241
+ $this->_message->header->sender_email = $results[0];
242
+ }
243
+ $this->_message->header->sender_name = (isset($this->_message->headerinfo['from'])) ? strip_tags(@$this->_message->headerinfo['from']) : '';
244
+ $this->_message->header->reply_to_email = $this->_message->header->sender_email;
245
+ $this->_message->header->reply_to_name = (property_exists($this->_message->header, 'sender_name')) ? $this->_message->header->sender_name : '';
246
+ $this->_message->header->from_email = $this->_message->header->sender_email;
247
+ $this->_message->header->from_name = $this->_message->header->reply_to_name;
248
+
249
+ return true;
250
+ }
251
+
252
+ function _decodeMessageimap() {
253
+ $this->_message->structure = imap_fetchstructure($this->mailbox, $this->_message->messageNB);
254
+ if (empty($this->_message->structure))
255
+ return false;
256
+ $this->_message->headerinfo = imap_fetchheader($this->mailbox, $this->_message->messageNB);
257
+ $this->_message->html = '';
258
+ $this->_message->text = '';
259
+
260
+ //Multipart message : type == 1
261
+ if ($this->_message->structure->type == 1) {
262
+ $this->_message->contentType = 2;
263
+ $allParts = $this->_explodeBody($this->_message->structure);
264
+
265
+ $this->_message->text = '';
266
+ foreach ($allParts as $num => $onePart) {
267
+ $charset = $this->_getMailParam($onePart, 'charset');
268
+ if ($onePart->subtype == 'HTML') {
269
+ $this->_message->html = $this->_decodeContent(imap_fetchbody($this->mailbox, $this->_message->messageNB, $num), $onePart);
270
+ } else {
271
+ $this->_message->text .= $this->_decodeContent(imap_fetchbody($this->mailbox, $this->_message->messageNB, $num), $onePart) . "\n\n- - -\n\n";
272
+ }
273
+ }
274
+ } else {
275
+ $charset = $this->_getMailParam($this->_message->structure, 'charset');
276
+ if ($this->_message->structure->subtype == 'HTML') {
277
+ $this->_message->contentType = 1;
278
+ $this->_message->html = $this->_decodeContent(imap_body($this->mailbox, $this->_message->messageNB), $this->_message->structure);
279
+ } else {
280
+ $this->_message->contentType = 0;
281
+ $this->_message->text = $this->_decodeContent(imap_body($this->mailbox, $this->_message->messageNB), $this->_message->structure);
282
+ }
283
+ }
284
+
285
+ //Decode the subject
286
+ $this->_message->subject = $this->_decodeHeader($this->_message->subject);
287
+
288
+ $this->_decodeAddressimap('sender');
289
+ $this->_decodeAddressimap('from');
290
+ $this->_decodeAddressimap('reply_to');
291
+ $this->_decodeAddressimap('to');
292
+ return true;
293
+ }
294
+
295
+ function handleMessages() {
296
+ $model_list = WYSIJA::get('list', 'model');
297
+
298
+ $listdetails = $model_list->getRows(array('name', 'list_id'));
299
+
300
+ foreach ($listdetails as $listinfo) {
301
+ $this->listdetails[$listinfo['list_id']] = $listinfo['name'];
302
+ }
303
+ $maxMessages = min($this->nbMessages, $this->config->getValue('bounce_max', 100));
304
+ if (empty($maxMessages))
305
+ $maxMessages = $this->nbMessages;
306
+
307
+ // we need a report when we are handling the bounce manually through the settings
308
+ if ($this->report) {
309
+ // If we display informations, we directy flush so that we can display in real time!
310
+ if (!headers_sent() AND ob_get_level() > 0) {
311
+ ob_end_flush();
312
+ }
313
+
314
+ // We prepare the area where we will add informations...
315
+ $disp = '<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" />';
316
+ $disp .= '<title>' . addslashes(__('Bounce Handling', WYSIJA)) . '</title>';
317
+ $disp .= '<style>body{font-size:12px;font-family: Arial,Helvetica,sans-serif;} strong{color: black;}</style></head><body>';
318
+ $disp .= "<div style='position:relative; top:3px;left:3px;'>";
319
+ $disp .= __("Bounce Handling", WYSIJA);
320
+ $disp .= ': <span id="counter"/>0</span> / ' . $maxMessages;
321
+ $disp .= '</div>';
322
+ $disp .= '<br/>';
323
+ $disp .= '<script type="text/javascript" language="javascript">';
324
+ $disp .= 'var mycounter = document.getElementById("counter");';
325
+ $disp .= 'function setCounter(val){ mycounter.innerHTML=val;}';
326
+ $disp .= '</script>';
327
+ echo $disp;
328
+ if (function_exists('ob_flush'))
329
+ @ob_flush();
330
+ @flush();
331
+ }
332
+
333
+ //We load all published the rules
334
+ $rules = $this->rulesClass->getRules();
335
+
336
+ $msgNB = $maxMessages;
337
+ $listClass = WYSIJA::get('list', 'model');
338
+ $this->allLists = $listClass->getRows();
339
+
340
+ while (($msgNB > 0) && ($this->_message = $this->getMessage($msgNB))) {
341
+ if ($this->report) {
342
+ echo '<script type="text/javascript" language="javascript">setCounter(' . ($maxMessages - $msgNB + 1) . ')</script>';
343
+ if (function_exists('ob_flush'))
344
+ @ob_flush();
345
+ @flush();
346
+ }
347
+ $this->_message->messageNB = $msgNB;
348
+ $this->decodeMessage();
349
+
350
+ $msgNB--;
351
+ if (empty($this->_message->subject))
352
+ continue;
353
+
354
+ $this->_message->analyseText = $this->_message->html . ' ' . $this->_message->text;
355
+ $this->_display('<strong>' . __('Subject', WYSIJA) . ' : ' . strip_tags($this->_message->subject) . '</strong>', false, $maxMessages - $this->_message->messageNB + 1);
356
+
357
+ // Identify the user and the e-mail... there is not the same info when it is a multisite or not
358
+ $email_identifiers = array();
359
+ if ($this->record_ms_bounce) {
360
+ preg_match('#WY([0-9]+)SI([0-9]+)JA([0-9]+)MS#i', $this->_message->analyseText, $email_identifiers);
361
+ if (!empty($email_identifiers[1]))
362
+ $this->_message->user_id = $email_identifiers[1];
363
+ if (!empty($email_identifiers[2]))
364
+ $this->_message->email_id = $email_identifiers[2];
365
+ if (!empty($email_identifiers[3]))
366
+ $this->_message->site_id = $email_identifiers[3];
367
+ }else {
368
+ preg_match('#WY([0-9]+)SI([0-9]+)JA#i', $this->_message->analyseText, $email_identifiers);
369
+ if (!empty($email_identifiers[1]))
370
+ $this->_message->user_id = $email_identifiers[1];
371
+ if (!empty($email_identifiers[2]))
372
+ $this->_message->email_id = $email_identifiers[2];
373
+ }
374
+
375
+ // if we don't have the user_id set then we need to find the user_id differently
376
+ if (empty($this->_message->user_id)) {
377
+ // We will need the e-mail itself in that case... :p
378
+ $emails_detected_in_the_email = array();
379
+ preg_match_all($this->detectEmail, $this->_message->analyseText, $emails_detected_in_the_email);
380
+ $reply_email = $this->config->getValue('reply_email');
381
+ $from_email = $this->config->getValue('from_email');
382
+ $bounce_email = $this->config->getValue('bounce_email');
383
+ $remove_emails = '#(' . str_replace(array('%'), array('@'), $this->config->getValue('bounce_login'));
384
+ if (!empty($bounce_email))
385
+ $remove_emails .= '|' . $bounce_email;
386
+ if (!empty($from_email))
387
+ $remove_emails .= '|' . $from_email;
388
+ if (!empty($reply_email))
389
+ $remove_emails .= '|' . $reply_email;
390
+ $remove_emails .= ')#i';
391
+ if (!empty($emails_detected_in_the_email[0])) {
392
+ $email_already_checked = array();
393
+ foreach ($emails_detected_in_the_email[0] as $detected_email) {
394
+ // We will find the e-mail if it's not in the list of incorrect e-mail addresses
395
+ if (!preg_match($remove_emails, $detected_email)) {
396
+ // We will keep this one, so we make sure it's strtolower
397
+ $this->_message->subemail = strtolower($detected_email);
398
+ // We already checked this e-mail address... no need to try it a second time
399
+ if (!empty($email_already_checked[$this->_message->subemail]))
400
+ continue;
401
+ $this->subClass->getFormat = OBJECT;
402
+ $result = $this->subClass->getOne(array('user_id'), array('email' => $this->_message->subemail));
403
+
404
+ $this->_message->user_id = $result->user_id;
405
+ $email_already_checked[$this->_message->subemail] = true;
406
+ if (!empty($this->_message->user_id))
407
+ break;
408
+ }
409
+ }
410
+ }
411
+ }
412
+
413
+ // get the email_id if it is not set and the user_id has been found
414
+ if (empty($this->_message->email_id) && !empty($this->_message->user_id)) {
415
+ // We can check if we have a user and only one e-mail sent for this user, it's obviously the e-mail we just sent!!
416
+ $modelEUS = WYSIJA::get('email_user_stat', 'model');
417
+ $emailres = $modelEUS->query('get_row', 'SELECT `email_id` FROM [wysija]' . $modelEUS->table_name . ' WHERE `user_id` = ' . (int) $this->_message->user_id . ' ORDER BY `sent_at` DESC LIMIT 1');
418
+ $this->_message->email_id = $emailres['email_id'];
419
+ //$this->_message->email_id = $this->db->loadResult();
420
+ }
421
+
422
+ foreach ($rules as $one_rule) {
423
+ //We stop as soon as we find a good rule...
424
+ if ($this->_handleRule($one_rule))
425
+ break;
426
+ }
427
+
428
+
429
+ if ($msgNB % 50 == 0){
430
+ if(!$this->record_ms_bounce) $this->_sub_actions();
431
+ }
432
+ }
433
+
434
+ if(!$this->record_ms_bounce) $this->_sub_actions();
435
+
436
+ if ($this->report) {
437
+ //We need to finish the current page properly
438
+ echo '</body></html>';
439
+ }
440
+ }
441
+
442
+
443
+ /**
444
+ * take action on the subscribers based on what data we gathered in the processing part earlier
445
+ */
446
+ function _sub_actions() {
447
+
448
+ // the action is about deleting users
449
+ if (!empty($this->deletedUsers)) {
450
+ $this->subClass->testdelete = true;
451
+ $helper_user = WYSIJA::get('user','helper');
452
+ $helper_user->delete($this->deletedUsers);
453
+ $this->deletedUsers = array();
454
+ }
455
+
456
+ if (!empty($this->unsubscribedUsers)) {
457
+ //unsubscribe user
458
+ $user_helper = WYSIJA::get('user', 'helper');
459
+ if (!is_array($this->unsubscribedUsers)) $this->unsubscribedUsers=array($this->unsubscribedUsers);
460
+
461
+ foreach ($this->unsubscribedUsers as $unsub_user_id) {
462
+ $user_helper->unsubscribe($unsub_user_id, true);
463
+ }
464
+
465
+ $this->unsubscribedUsers = array();
466
+ }
467
+
468
+ if (!empty($this->addtolistUsers)) {
469
+ //unsubscribe user
470
+ $user_helper = WYSIJA::get('user', 'helper');
471
+ foreach ($this->addtolistUsers as $listid => $user_ids) {
472
+ $user_helper->addToList($listid, $user_ids);
473
+ }
474
+
475
+ $this->addtolistUsers = array();
476
+ }
477
+
478
+ if (!empty($this->bounceMessages)) {
479
+ foreach ($this->bounceMessages as $email_id => $bouncedata) {
480
+ if (!empty($bouncedata['user_id'])) {
481
+ //flag email has bounced
482
+ $modelEUS = WYSIJA::get('email_user_stat', 'model');
483
+ $modelEUS->update(array('status' => -1), array('user_id' => $bouncedata['user_id'], 'email_id' => (int) $email_id));
484
+ /* $this->db->setQuery('UPDATE '.acymailing_table('userstats').' SET `bounce` = `bounce` + 1 WHERE `user_id` IN ('.implode(',',$bouncedata['user_id']).') AND `email_id` = '.(int) $email_id);
485
+ $this->db->query(); */
486
+ }
487
+ }
488
+ $this->bounceMessages = array();
489
+ }
490
+ }
491
+
492
+
493
+
494
+
495
+ function _handleRule(&$one_rule) {
496
+
497
+ $regex = $one_rule['regex'];
498
+ if (empty($regex))
499
+ return false;
500
+
501
+ //Do it based on the config of the rule...
502
+
503
+ $analyse_text = '';
504
+ if (isset($one_rule['executed_on']['senderinfo']))
505
+ $analyse_text .= ' ' . $this->_message->header->sender_name . $this->_message->header->sender_email;
506
+ if (isset($one_rule['executed_on']['subject']))
507
+ $analyse_text .= ' ' . $this->_message->subject;
508
+ if (isset($one_rule['executed_on']['body'])) {
509
+ if (!empty($this->_message->html))
510
+ $analyse_text .= ' ' . $this->_message->html;
511
+ if (!empty($this->_message->text))
512
+ $analyse_text .= ' ' . $this->_message->text;
513
+ }
514
+
515
+ //regex multilines
516
+ if (!preg_match('#' . $regex . '#is', $analyse_text))
517
+ return false;
518
+
519
+ $message = $one_rule['name'];
520
+
521
+ if($this->record_ms_bounce) {
522
+ // no need for user action in multisite because we'll do it per site in a second process
523
+ $message .= $this->_action_message_ms($one_rule);
524
+ }else{
525
+ $message .= $this->_action_user($one_rule);
526
+ $message .= $this->_action_message($one_rule);
527
+ }
528
+
529
+
530
+ $this->_display($message, true);
531
+
532
+ return true;
533
+ }
534
+
535
+ function _action_user(&$one_rule) {
536
+ $message = '';
537
+
538
+ if (empty($this->_message->user_id)) {
539
+ $message .= 'user not identified';
540
+ if (!empty($this->_message->subemail))
541
+ $message .= ' ( ' . $this->_message->subemail . ' ) ';
542
+ return $message;
543
+ }
544
+
545
+ if (isset($one_rule['action_user']) && in_array($one_rule['action_user'], array('unsub'))) {
546
+ if (empty($this->_message->subemail)) {
547
+ $currentUser = $this->subClass->getObject($this->_message->user_id);
548
+ if (!empty($currentUser->email))
549
+ $this->_message->subemail = $currentUser->email;
550
+ }
551
+ }
552
+
553
+ if (empty($this->_message->subemail))
554
+ $this->_message->subemail = $this->_message->user_id;
555
+
556
+ //let's handle some actions on the subscriber first
557
+ if (isset($one_rule['action_user_stats'])) {
558
+ //handle this rule in the stats
559
+ if (!empty($this->_message->email_id)) {
560
+ if (empty($this->bounceMessages[$this->_message->email_id]['nbbounces'])) {
561
+ $this->bounceMessages[$this->_message->email_id] = array();
562
+ $this->bounceMessages[$this->_message->email_id]['nbbounces'] = 1;
563
+ } else {
564
+ $this->bounceMessages[$this->_message->email_id]['nbbounces']++;
565
+ }
566
+
567
+ if (!empty($this->_message->user_id) AND ((isset($one_rule['action_user']) && $one_rule['action_user'] != 'delete') || !isset($one_rule['action_user']) )) {
568
+ //Increment the bounce number in the user stat table but only if we don't delete the subscriber
569
+ $this->bounceMessages[$this->_message->email_id]['user_id'][] = intval($this->_message->user_id);
570
+ }
571
+ }
572
+ }
573
+
574
+
575
+ //Make sure we have enough messages to really execute this
576
+ if (!empty($one_rule['action_user_min']) && $one_rule['action_user_min'] > 1) {
577
+ //Let's load the number of bounces the user has and then exit or not...
578
+ $modelEUS = WYSIJA::get('email_user_stat', 'model');
579
+ $res = $modelEUS->query('get_row', 'SELECT COUNT(email_id) as count FROM [wysija]' . $modelEUS->table_name . ' WHERE status = -1 AND user_id = ' . $this->_message->user_id);
580
+ $nb = intval($res['count']) + 1;
581
+
582
+ if ($nb < $one_rule['action_user_min']) {
583
+ $message .= ', ' . sprintf(__('We received %1$s messages from the user %2$s', WYSIJA), $nb, $this->_message->subemail) . ', ' . sprintf(__('Actions will be executed after %1$s messages', WYSIJA), $one_rule['action_user_min']);
584
+ return $message;
585
+ }
586
+ }
587
+
588
+ //IN WYSIJA THERE ARE 3 POSSIBILITIES
589
+ //1-Delete user
590
+ //2-Unsubscribe user
591
+ //3-Unsubscribe and attach to list "xxx"
592
+ if (isset($one_rule['action_user'])) {
593
+ switch ($one_rule['action_user']) {
594
+ case 'delete'://1 -Delete user
595
+ $message .= ', user ' . $this->_message->subemail . ' deleted';
596
+ $this->deletedUsers[] = intval($this->_message->user_id);
597
+
598
+ break;
599
+ case 'unsub'://2-Unsubscribe user
600
+ //when we unsubscribe somebody automatically we set the status to -2 instead of -1 to make the difference
601
+ $message .= ', user ' . $this->_message->subemail . ' unsubscribed';
602
+ $this->unsubscribedUsers[] = $this->_message->user_id;
603
+
604
+ break;
605
+ default:
606
+ //3 - Unsubscribe user and add to list
607
+ if (strpos($one_rule['action_user'], 'unsub_') !== false) {
608
+ $listid = (int) str_replace('unsub_', '', $one_rule['action_user']);
609
+ $message .= ', user ' . $this->_message->subemail . ' unsubscribed';
610
+ $this->unsubscribedUsers[] = $this->_message->user_id;
611
+ $this->addtolistUsers[$listid][] = $this->_message->user_id;
612
+ $message .= ', user ' . $this->_message->subemail . ' added to list "' . $this->listdetails[$listid] . '"';
613
+ }
614
+ }
615
+ }
616
+
617
+
618
+
619
+
620
+
621
+ return $message;
622
+ }
623
+
624
+ function _action_message(&$one_rule) {
625
+
626
+ $message = '';
627
+
628
+ //Handle actions on the message itself
629
+
630
+ if (isset($one_rule['action_message']['save']) && !empty($this->_message->user_id)) {
631
+ //We have a user_id, should we save the message in the database?
632
+ $data = array();
633
+ $data[] = 'SUBJECT::' . $this->_message->subject;
634
+
635
+ if (!empty($this->_message->html))
636
+ $data[] = 'HTML_VERSION::' . htmlentities($this->_message->html);
637
+ if (!empty($this->_message->text))
638
+ $data[] = 'TEXT_VERSION::' . nl2br(htmlentities($this->_message->text));
639
+ $this->_message->header->reply_to_name = (property_exists($this->_message->header, 'reply_to_name')) ? $this->_message->header->reply_to_name : '';
640
+ $this->_message->header->from_name = (property_exists($this->_message->header, 'from_name')) ? $this->_message->header->from_name : '';
641
+ $data[] = 'REPLYTO_ADDRESS::' . $this->_message->header->reply_to_name . ' ( ' . $this->_message->header->reply_to_email . ' )';
642
+ $data[] = 'FROM_ADDRESS::' . $this->_message->header->from_name . ' ( ' . $this->_message->header->from_email . ' )';
643
+ $data[] = print_r($this->_message->headerinfo, true);
644
+ $this->historyClass->insert($this->_message->user_id, 'bounce', $data, @$this->_message->email_id);
645
+ $message .= ', message saved (user ' . $this->_message->user_id . ')';
646
+ }
647
+
648
+ if (isset($one_rule['forward'])) {
649
+ if (isset($one_rule['action_message_forwardto']) && !empty($one_rule['action_message_forwardto']) && trim($one_rule['action_message_forwardto']) != trim($this->config->getValue('bounce_email'))) {
650
+ //Get the forward address :
651
+ $this->mailer->clearAll();
652
+ $this->mailer->Subject = 'BOUNCE FORWARD : ' . $this->_message->subject;
653
+ $this->mailer->AddAddress($one_rule['action_message_forwardto']);
654
+ if (!empty($this->_message->html)) {
655
+ $this->mailer->IsHTML(true);
656
+ $this->mailer->Body = $this->_message->html;
657
+ if (!empty($this->_message->text))
658
+ $this->mailer->Body .= '<br/><br/>-------<br/>' . nl2br($this->_message->text);
659
+ }else {
660
+ $this->mailer->IsHTML(false);
661
+ $this->mailer->Body = $this->_message->text;
662
+ }
663
+
664
+ //We add all other extra information just in case of we could use them...
665
+ //original-rcpt-to ? http://tools.ietf.org/html/rfc5965
666
+ $this->mailer->Body .= print_r($this->_message->headerinfo, true);
667
+ $this->_message->header->reply_to_name = (property_exists($this->_message->header, 'reply_to_name')) ? $this->_message->header->reply_to_name : '';
668
+ $this->_message->header->from_name = (property_exists($this->_message->header, 'from_name')) ? $this->_message->header->from_name : '';
669
+ $this->mailer->AddReplyTo($this->_message->header->reply_to_email, $this->_message->header->reply_to_name);
670
+ $this->mailer->setFrom($this->_message->header->from_email, $this->_message->header->from_name);
671
+ if ($this->mailer->send()) {
672
+ $message .= ', forwarded to ' . $one_rule['action_message_forwardto'];
673
+ } else {
674
+ $message .= ', error forwarding to ' . $one_rule['action_message_forwardto'];
675
+ }
676
+
677
+ } else {
678
+ //we dont delete the email if the forward email is not specified or if the bounce email is the same as the forward email
679
+ unset($one_rule['action_message']['delete']);
680
+ }
681
+ }
682
+
683
+ if (isset($one_rule['action_message']['delete'])) {
684
+ $message .= ', message deleted';
685
+ $this->deleteMessage($this->_message->messageNB);
686
+ }
687
+
688
+ return $message;
689
+ }
690
+
691
+ function _decodeAddressimap($type) {
692
+ $address = $type . 'address';
693
+ $name = $type . '_name';
694
+ $email = $type . '_email';
695
+ if (empty($this->_message->$type))
696
+ return false;
697
+
698
+ $var = $this->_message->$type;
699
+
700
+ if (!empty($this->_message->$address)) {
701
+ if(!isset($this->_message->header) || is_null($this->_message->header)){
702
+ $this->_message->header = new stdClass();
703
+ }
704
+ } else {
705
+ $this->_message->header->$name = $var[0]->personal;
706
+ }
707
+
708
+ $this->_message->header->$email = $var[0]->mailbox . '@' . @$var[0]->host;
709
+ return true;
710
+ }
711
+
712
+ /**
713
+ * If num is empty then it's a message otherwise it's a send statrus
714
+ */
715
+ function _display($message, $status = '', $num = '') {
716
+ $this->messages[] = $message;
717
+
718
+ if (!$this->report)
719
+ return;
720
+
721
+ $color = $status ? 'black' : 'blue';
722
+ if (!empty($num))
723
+ echo '<br/>' . $num . ' : ';
724
+ else
725
+ echo '<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
726
+
727
+ echo '<font style="font-family: Arial;" color="' . $color . '">' . $message . '</font>';
728
+ if (function_exists('ob_flush'))
729
+ @ob_flush();
730
+ @flush();
731
+ }
732
+
733
+ function _decodeHeader($input) {
734
+ // Remove white space between encoded-words
735
+ $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
736
+ $this->charset = false;
737
+
738
+ // For each encoded-word...
739
+ while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
740
+
741
+ $encoded = $matches[1];
742
+ $charset = $matches[2];
743
+ $encoding = $matches[3];
744
+ $text = $matches[4];
745
+
746
+ switch (strtolower($encoding)) {
747
+ case 'b':
748
+ $text = base64_decode($text);
749
+ break;
750
+
751
+ case 'q':
752
+ $text = str_replace('_', ' ', $text);
753
+ preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
754
+ foreach ($matches[1] as $value)
755
+ $text = str_replace('=' . $value, chr(hexdec($value)), $text);
756
+ break;
757
+ }
758
+ $this->charset = $charset;
759
+ $input = str_replace($encoded, $text, $input);
760
+ }
761
+
762
+ return $input;
763
+ }
764
+
765
+ function _explodeBody($struct, $path = "0", $inline = 0) {
766
+ $allParts = array();
767
+
768
+ if (empty($struct->parts))
769
+ return $allParts;
770
+
771
+ $c = 0; //counts real content
772
+ foreach ($struct->parts as $part) {
773
+ if ($part->type == 1) {
774
+ //There are more parts....:
775
+ if ($part->subtype == "MIXED") { //Mixed:
776
+ $path = $this->_incPath($path, 1); //refreshing current path
777
+ $newpath = $path . ".0"; //create a new path-id (ex.:2.0)
778
+ $allParts = array_merge($this->_explodeBody($part, $newpath), $allParts); //fetch new parts
779
+ } else { //Alternativ / rfc / signed
780
+ $newpath = $this->_incPath($path, 1);
781
+ $path = $this->_incPath($path, 1);
782
+ $allParts = array_merge($this->_explodeBody($part, $newpath, 1), $allParts);
783
+ }
784
+ } else {
785
+ $c++;
786
+ //creating new tree if this is part of a alternativ or rfc message:
787
+ if ($c == 1 && $inline) {
788
+ $path = $path . ".0";
789
+ }
790
+ //saving content:
791
+ $path = $this->_incPath($path, 1);
792
+ //print "<br> Content ".$path."<br>"; //debug information
793
+ $allParts[$path] = $part;
794
+ }
795
+ }
796
+
797
+ return $allParts;
798
+ }
799
+
800
+ //Increases the Path to the parts:
801
+ function _incPath($path, $inc) {
802
+ $newpath = "";
803
+ $path_elements = explode(".", $path);
804
+ $limit = count($path_elements);
805
+ for ($i = 0; $i < $limit; $i++) {
806
+ if ($i == $limit - 1) { //last element
807
+ $newpath .= $path_elements[$i] + $inc; // new Part-Number
808
+ } else {
809
+ $newpath .= $path_elements[$i] . "."; //rebuild "1.2.2"-Chronology
810
+ }
811
+ }
812
+ return $newpath;
813
+ }
814
+
815
+ function _decodeContent($content, $structure) {
816
+ $encoding = $structure->encoding;
817
+
818
+ //First we decode the content properly
819
+ if ($encoding == 2)
820
+ $content = imap_binary($content);
821
+ elseif ($encoding == 3)
822
+ $content = imap_base64($content);
823
+ elseif ($encoding == 4)
824
+ $content = imap_qprint($content);
825
+ //Other cases??
826
+ //added for a client who had issue when message was base64
827
+ if(base64_decode($content,true)!==FALSE)
828
+ $content = base64_decode($content);
829
+
830
+ //Now we convert into utf-8!
831
+ //$charset = $this->_getMailParam($structure,'charset');
832
+ // removes attachment to prevent bounce handling timeout
833
+ // 100 000 characters is plenty
834
+ return substr($content, 0, 100000);
835
+ }
836
+
837
+ function _getMailParam($params, $name) {
838
+ $searchIn = array();
839
+
840
+ if ($params->ifparameters)
841
+ $searchIn = array_merge($searchIn, $params->parameters);
842
+ if ($params->ifdparameters)
843
+ $searchIn = array_merge($searchIn, $params->dparameters);
844
+
845
+ if (empty($searchIn))
846
+ return false;
847
+
848
+ foreach ($searchIn as $num => $values) {
849
+ if (strtolower($values->attribute) == $name) {
850
+ return $values->value;
851
+ }
852
+ }
853
+ }
854
+
855
+ function getErrors() {
856
+ $return = array();
857
+ if ($this->usepear) {
858
+ //TODO : get some errors from the pear interface?
859
+ } else {
860
+ $alerts = imap_alerts();
861
+ $errors = imap_errors();
862
+ if (!empty($alerts))
863
+ $return = array_merge($return, $alerts);
864
+ if (!empty($errors))
865
+ $return = array_merge($return, $errors);
866
+ }
867
+
868
+ return $return;
869
+ }
870
+
871
+
872
+
873
+ /**
874
+ * simple function that launch a bounce process
875
+ * @return boolean
876
+ */
877
+ function process_bounce() {
878
+
879
+ @ini_set('max_execution_time', 0);
880
+
881
+ $model_config = WYSIJA::get('config', 'model');
882
+
883
+ $this->report = true;
884
+ if (!$this->init()) {
885
+ $res['result'] = false;
886
+ return $res;
887
+ }
888
+ if (!$this->connect()) {
889
+ $this->error($this->getErrors());
890
+ $res['result'] = false;
891
+ return $res;
892
+ }
893
+ $this->notice(sprintf(__('Successfully connected to %1$s'), $model_config->getValue('bounce_login')));
894
+ $nbMessages = $this->getNBMessages();
895
+
896
+
897
+ if (empty($nbMessages)) {
898
+ $this->error(__('There are no messages'), true);
899
+ $res['result'] = false;
900
+ return $res;
901
+ } else {
902
+ $this->notice(sprintf(__('There are %1$s messages in your mailbox'), $nbMessages));
903
+ }
904
+
905
+ $this->handleMessages();
906
+
907
+ $this->close();
908
+
909
+ $res['result'] = true;
910
+
911
+ return $res;
912
+ }
913
+
914
+
915
+ /**
916
+ * record the bounce into the bounce table on a multisite
917
+ * @return type
918
+ */
919
+ function record_bounce_ms() {
920
+ // make sure that the bounce recording is not already being processed on another child site
921
+ if (get_site_option('wysija_bounce_being_recorded'))
922
+ return;
923
+
924
+ // flag the current recording
925
+ WYSIJA::update_option('wysija_bounce_being_recorded', true);
926
+
927
+ // set the flag to indicate we are processing the bounce in a multisite manner right now
928
+ $this->record_ms_bounce = true;
929
+
930
+ // will record the bounce in the ms table
931
+ $result = $this->process_bounce();
932
+
933
+ // lower the flag we can process the bounce again
934
+ WYSIJA::update_option('wysija_bounce_being_recorded', false);
935
+
936
+ return $result;
937
+ }
938
+ /**
939
+ * base on the records we have in the bounce table we will take action
940
+ * @return boolean
941
+ */
942
+ function process_bounce_ms() {
943
+
944
+ @ini_set('max_execution_time', 0);
945
+ global $blog_id;
946
+ $main_site_prefix = $this->subClass->get_site_prefix();
947
+ // make a query that will handle the bounce delete for all of the emails recorded in the bounce table for that site
948
+ // join the table bounce and user to make sure the ID's exist get 200 of them
949
+
950
+ // we will delete one by one all of the data from the users that need to be removed
951
+ $tables = array(
952
+ 'user_history',
953
+ 'email_user_url',
954
+ 'email_user_stat',
955
+ 'user_list',
956
+ 'queue',
957
+ );
958
+
959
+ // central query to fetch the id of the bounced emails of the delete action
960
+ $query_join_bounce = 'SELECT B.user_id from '.$main_site_prefix.'bounce as A JOIN [wysija]user as B on A.email = B.email WHERE A.action_taken = "delete"';
961
+
962
+ try{
963
+ foreach ($tables as $table_name){
964
+ $query_delete = 'DELETE FROM [wysija]' . $table_name . ' WHERE user_id IN (' . $query_join_bounce . ')';
965
+ $this->subClass->query($query_delete);
966
+ }
967
+ }catch(Exception $e){
968
+ return false;
969
+ }
970
+
971
+ // delete process from the user table needs to be made through a join since we cannot nest select from the same table we delete from
972
+ $query_delete_user = 'DELETE A.* FROM [wysija]user as A JOIN '.$main_site_prefix.'bounce as B on A.email = B.email WHERE B.action_taken = "delete"';
973
+ $this->subClass->query($query_delete_user);
974
+
975
+ // central query to fetch the id of the bounced emails of the unsubscribe action
976
+ $query_join_bounce = 'SELECT B.user_id from '.$main_site_prefix.'bounce as A JOIN [wysija]user as B on A.email = B.email WHERE A.action_taken = "unsubscribe"';
977
+
978
+ // query to update the status to unsubscribe
979
+ $query_update_user = 'UPDATE [wysija]user as A JOIN '.$main_site_prefix.'bounce as B on A.email = B.email SET A.`status` = -1 WHERE A.`status` != -1';
980
+ //$query_update_user = 'UPDATE [wysija]user SET `status` = -1 WHERE user_id IN (' . $query_join_bounce . ')';
981
+
982
+ $query_update_user_list = 'UPDATE [wysija]user_list as A JOIN [wysija]user as B on A.user_id = B.user_id JOIN '.$main_site_prefix.'bounce as C on B.email = C.email SET A.`unsub_date` = '.time().' , A.`sub_date` = 0 WHERE B.`status` != -1';
983
+ //$query_update_user_list = 'UPDATE [wysija]user_list SET `unsub_date` = '.time().' , `sub_date` = 0 WHERE user_id IN (' . $query_join_bounce . ')';
984
+
985
+ $this->subClass->getResults($query_update_user);
986
+ $this->subClass->getResults($query_update_user_list);
987
+
988
+ // delete what's in the queue for those subscribers
989
+ $query_delete = 'DELETE FROM [wysija]queue WHERE user_id IN (' . $query_join_bounce . ')';
990
+
991
+ $this->subClass->getResults($query_delete);
992
+
993
+ // query to set the boucne value in the email table
994
+ $query_update_email_user_status = 'UPDATE [wysija]email_user_stat as A JOIN '.$main_site_prefix.'bounce as C on (A.user_id = C.user_id AND A.email_id = C.email_id) SET A.`status` = -1 WHERE C.site_id='.$blog_id;
995
+ $this->subClass->getResults($query_update_email_user_status);
996
+
997
+ $res['result'] = true;
998
+
999
+ return $res;
1000
+ }
1001
+
1002
+ /**
1003
+ * take action on the subscribers for multisites processing we don't delete or unsubscribe the users, we just record the action to be taken in the db
1004
+ */
1005
+ function _sub_actions_ms() {
1006
+
1007
+ // the action is about deleting users
1008
+ if (!empty($this->deletedUsers)) {
1009
+ $this->subClass->testdelete = true;
1010
+
1011
+ $this->deletedUsers = array();
1012
+ }
1013
+
1014
+ if (!empty($this->unsubscribedUsers)) {
1015
+
1016
+ $this->unsubscribedUsers = array();
1017
+ }
1018
+ }
1019
+
1020
+ function _action_message_ms(&$one_rule) {
1021
+
1022
+ $email_copy = $message = '';
1023
+
1024
+ //Handle actions on the message itself
1025
+
1026
+ if (isset($one_rule['action_message']['save']) && !empty($this->_message->user_id)) {
1027
+ //We have a user_id, should we save the message in the database?
1028
+ $email_saved_as_array = array();
1029
+ $email_saved_as_array[] = 'SUBJECT::' . $this->_message->subject;
1030
+
1031
+ if (!empty($this->_message->html))
1032
+ $email_saved_as_array[] = 'HTML_VERSION::' . htmlentities($this->_message->html);
1033
+ if (!empty($this->_message->text))
1034
+ $email_saved_as_array[] = 'TEXT_VERSION::' . nl2br(htmlentities($this->_message->text));
1035
+ $this->_message->header->reply_to_name = (property_exists($this->_message->header, 'reply_to_name')) ? $this->_message->header->reply_to_name : '';
1036
+ $this->_message->header->from_name = (property_exists($this->_message->header, 'from_name')) ? $this->_message->header->from_name : '';
1037
+ $email_saved_as_array[] = 'REPLYTO_ADDRESS::' . $this->_message->header->reply_to_name . ' ( ' . $this->_message->header->reply_to_email . ' )';
1038
+ $email_saved_as_array[] = 'FROM_ADDRESS::' . $this->_message->header->from_name . ' ( ' . $this->_message->header->from_email . ' )';
1039
+ $email_saved_as_array[] = print_r($this->_message->headerinfo, true);
1040
+ $email_copy = implode("\n",$email_saved_as_array);
1041
+
1042
+ $message .= ', message saved (user ' . $this->_message->user_id . ')';
1043
+
1044
+ }
1045
+
1046
+ if (isset($one_rule['forward'])) {
1047
+ if (isset($one_rule['action_message_forwardto']) && !empty($one_rule['action_message_forwardto']) && trim($one_rule['action_message_forwardto']) != trim($this->config->getValue('bounce_email'))) {
1048
+ //Get the forward address :
1049
+ $this->mailer->clearAll();
1050
+ $this->mailer->Subject = 'BOUNCE FORWARD : ' . $this->_message->subject;
1051
+ $this->mailer->AddAddress($one_rule['action_message_forwardto']);
1052
+ if (!empty($this->_message->html)) {
1053
+ $this->mailer->IsHTML(true);
1054
+ $this->mailer->Body = $this->_message->html;
1055
+ if (!empty($this->_message->text))
1056
+ $this->mailer->Body .= '<br/><br/>-------<br/>' . nl2br($this->_message->text);
1057
+ }else {
1058
+ $this->mailer->IsHTML(false);
1059
+ $this->mailer->Body = $this->_message->text;
1060
+ }
1061
+
1062
+ //We add all other extra information just in case of we could use them...
1063
+ //original-rcpt-to ? http://tools.ietf.org/html/rfc5965
1064
+ $this->mailer->Body .= print_r($this->_message->headerinfo, true);
1065
+ $this->_message->header->reply_to_name = (property_exists($this->_message->header, 'reply_to_name')) ? $this->_message->header->reply_to_name : '';
1066
+ $this->_message->header->from_name = (property_exists($this->_message->header, 'from_name')) ? $this->_message->header->from_name : '';
1067
+ $this->mailer->AddReplyTo($this->_message->header->reply_to_email, $this->_message->header->reply_to_name);
1068
+ $this->mailer->setFrom($this->_message->header->from_email, $this->_message->header->from_name);
1069
+ if ($this->mailer->send()) {
1070
+ $message .= ', forwarded to ' . $one_rule['action_message_forwardto'];
1071
+ } else {
1072
+ $message .= ', error forwarding to ' . $one_rule['action_message_forwardto'];
1073
+ }
1074
+
1075
+ } else {
1076
+ //we dont delete the email if the forward email is not specified or if the bounce email is the same as the forward email
1077
+ unset($one_rule['action_message']['delete']);
1078
+ }
1079
+ }
1080
+
1081
+ // insert the message or just the action taken on that message in the main bounce table
1082
+
1083
+ // get the prefix of the current child site
1084
+ $bounced_site_prefix = $this->subClass->get_site_prefix($this->_message->site_id);
1085
+ // get the email of the bounced message based on the user_id and the site_id
1086
+ $query = 'SELECT email FROM `'.$bounced_site_prefix.'user` WHERE user_id='.(int)$this->_message->user_id.' LIMIT 0 , 1';
1087
+ $result_subscriber = $this->subClass->query('get_res',$query,OBJECT);
1088
+
1089
+ $this->subClass->reset();
1090
+
1091
+ if(strpos($one_rule['action_user'], 'unsub')!==false) $action_taken='unsubscribe';
1092
+ elseif($one_rule['action_user']!='') $action_taken='delete';
1093
+
1094
+ if(!empty($result_subscriber[0]->email)){
1095
+ $main_site_prefix = $this->subClass->get_site_prefix();
1096
+ $query_insert_bounce_ms = 'INSERT IGNORE INTO `'.$main_site_prefix.'bounce` (`email`,`site_id`,`user_id`,`email_id`,`action_taken`,`case`,`message`,`created_at`)';
1097
+ $query_insert_bounce_ms .= " VALUES ('".$result_subscriber[0]->email."','".(int)$this->_message->site_id."','".(int)$this->_message->user_id."','".(int)$this->_message->email_id."','".$action_taken."', '".$one_rule['key']."', '". esc_sql($email_copy)."', '".time()."')";
1098
+
1099
+ $this->subClass->query($query_insert_bounce_ms);
1100
+ }
1101
+
1102
+ if (isset($one_rule['action_message']['delete'])) {
1103
+ $message .= ', message deleted';
1104
+ $this->deleteMessage($this->_message->messageNB);
1105
+ }
1106
+
1107
+ return $message;
1108
+ }
1109
+
1110
+ }
trunk/helpers/campaigns.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ add_action( 'wp_ajax_mailpoet.search_terms', 'WYSIJA_help_campaigns::ajax_search_terms' );
5
+
6
+
7
+ */
8
+ defined('WYSIJA') or die('Restricted access');
9
+ class WYSIJA_help_campaigns extends WYSIJA_object{
10
+
11
+ function __construct(){
12
+ parent::__construct();
13
+ }
14
+
15
+ function saveParameters($email_id, $key, $value)
16
+ {
17
+ // 1. get params field for given campaign
18
+ $modelEmail = WYSIJA::get('email', 'model');
19
+ $email = $modelEmail->getOne('params', array('email_id' => $email_id));
20
+ $params = $email['params'];
21
+
22
+ if(!is_array($params)) {
23
+ $params = array();
24
+ }
25
+
26
+ // 2 update data for given key
27
+ if(array_key_exists($key, $params)) {
28
+ $params[$key] = $value;
29
+ } else {
30
+ $params = array_merge($params, array($key => $value));
31
+ }
32
+
33
+ // 3. update campaign
34
+ return $modelEmail->update(array('params' => $params), array('email_id' => $email_id));
35
+ }
36
+
37
+ function getParameters($email_id, $key = null) {
38
+ // 1. get params field for given campaign
39
+ $modelEmail = WYSIJA::get('email', 'model');
40
+ $email = $modelEmail->getOne('params', array('email_id' => $email_id));
41
+ $params = $email['params'];
42
+
43
+ if($key === null) {
44
+ return $params;
45
+ } else {
46
+ if(!is_array($params) or array_key_exists($key, $params) === false) {
47
+ return false;
48
+ } else {
49
+ return $params[$key];
50
+ }
51
+ }
52
+ }
53
+ }
trunk/helpers/charts.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_charts extends WYSIJA_object {
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ }
8
+
9
+ function pieChart($id, $options = array()) {
10
+ return $this->generateChart('pie', $id, $options);
11
+ }
12
+
13
+ function serialChart($id, $options = array()) {
14
+ return $this->generateChart('serial', $id, $options);
15
+ }
16
+
17
+ function generateChart($type = 'serial', $id, $options = array()) {
18
+ // format id
19
+ $id = str_replace(' ', '-', $id);
20
+ // chart dimensions
21
+ $width = (isset($options['width'])) ? (int)$options['width'] : 400;
22
+ $height = (isset($options['height'])) ? (int)$options['height'] : 225;
23
+
24
+ // chart title
25
+ $title = (isset($options['title'])) ? $options['title'] : null;
26
+
27
+ // data
28
+ $data = (isset($options['data'])) ? $options['data'] : null;
29
+
30
+ // generate JS code
31
+ $content = '<div id="wysija-chart-'.$id.'" class="wysija-chart" style="width:'.$width.'px;height:'.$height.'px;"></div>';
32
+ $content .= '<script type="text/javascript">';
33
+ $content .= 'AmCharts.ready(function () {';
34
+ $content .= 'WysijaCharts.generateChart("'.$type.'", "wysija-chart-'.$id.'", {';
35
+ // set chart title
36
+ $content .= 'title: "'.$title.'",';
37
+ // set data
38
+ $content .= 'data: '.json_encode($data).',';
39
+
40
+ switch ($type) {
41
+ case 'serial':
42
+ // axes data
43
+ $axes = (isset($options['axes'])) ? $options['axes'] : null;
44
+ // category (the field used to sort by)
45
+ $category = (isset($options['category'])) ? $options['category'] : null;
46
+
47
+ $content .= 'axes: '.json_encode($axes).',';
48
+ $content .= 'category: "'.$category.'"';
49
+ break;
50
+ case 'pie':
51
+ // title and value fields
52
+ $titleField = (isset($options['titleField'])) ? $options['titleField'] : null;
53
+ $valueField = (isset($options['valueField'])) ? $options['valueField'] : null;
54
+
55
+ $content .= 'titleField: "'.$titleField.'",';
56
+ $content .= 'valueField: "'.$valueField.'"';
57
+
58
+ break;
59
+ }
60
+
61
+ $content .= '});';
62
+ $content .= '});';
63
+ $content .= '</script>';
64
+ return $content;
65
+ }
66
+ }
trunk/helpers/conflicts.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_conflicts extends WYSIJA_object{
4
+ var $cleanHooks=array();
5
+
6
+ function __construct(){
7
+ parent::__construct();
8
+ }
9
+
10
+ /**
11
+ * try to remove hook from plugins inviting themselves onto our interfaces
12
+ * @param type $conflictingPlugins
13
+ */
14
+ function resolve($conflictingPlugins){
15
+
16
+ $this->whatToClean=array();
17
+ foreach($conflictingPlugins as $keyPlg =>$plugin){
18
+ foreach($plugin['clean'] as $action => $details){
19
+ foreach($details as $priority =>$info){
20
+ $this->cleanHooks[$action][$priority][]=$info;
21
+ }
22
+ }
23
+ }
24
+ foreach($this->cleanHooks as $hookToclean => $info){
25
+
26
+ switch($hookToclean){
27
+ case 'admin_head':
28
+ add_action('init', array($this, 'remove_admin_head'), 999);
29
+ break;
30
+ case 'admin_print_scripts':
31
+ add_action('admin_menu', array($this, 'remove_admin_print_scripts'), 999);
32
+ break;
33
+ case 'wp_enqueue_scripts':
34
+ add_action('admin_menu', array($this, 'remove_wp_enqueue_scripts'), 999);
35
+ break;
36
+ case 'admin_enqueue_scripts':
37
+ add_action('admin_menu', array($this, 'remove_admin_enqueue_scripts'), 999);
38
+ break;
39
+ case 'init':
40
+ add_action('after_setup_theme', array($this, 'remove_init'), 999);
41
+ break;
42
+ default:
43
+ add_action('admin_footer', array($this, 'remove_default'), 999);
44
+ }
45
+ }
46
+ }
47
+ function remove_init(){
48
+ global $wp_filter;
49
+ $this->remove_actions('init');
50
+ }
51
+
52
+ function remove_default() {
53
+ $this->remove_actions('admin_init');
54
+ }
55
+
56
+ function remove_admin_head(){
57
+ $this->remove_actions('admin_head');
58
+ }
59
+ function remove_admin_print_scripts(){
60
+ $this->remove_actions('admin_print_scripts');
61
+ }
62
+
63
+ function remove_wp_enqueue_scripts() {
64
+ $this->remove_actions('wp_enqueue_scripts');
65
+ }
66
+
67
+ function remove_admin_enqueue_scripts() {
68
+ $this->remove_actions('admin_enqueue_scripts');
69
+ }
70
+
71
+
72
+
73
+ function remove_actions($actionsToClear){
74
+ global $wp_filter;
75
+
76
+ if (!isset($wp_filter[$actionsToClear])) return;
77
+
78
+ foreach($wp_filter[$actionsToClear] as $priority => $callbacks) {
79
+ if(!isset($this->cleanHooks[$actionsToClear][$priority])) continue;
80
+
81
+ foreach($callbacks as $identifier => $arrayInfo){
82
+ if(is_array($arrayInfo['function'])){
83
+ foreach($arrayInfo['function'] as $id => $myobject){
84
+ foreach($this->cleanHooks[$actionsToClear][$priority] as $infoClear) {
85
+ if(isset($infoClear['objects']) && is_object($myobject) && in_array(get_class($myobject),$infoClear['objects'])){
86
+ remove_action( $actionsToClear, $infoClear['function'], $priority, $arrayInfo['accepted_args'] );
87
+ }
88
+ }
89
+ }
90
+ } else {
91
+ foreach($this->cleanHooks[$actionsToClear][$priority] as $infoClear){
92
+ // if there is more than one function specified (key: functions, type: array)
93
+ if(isset($infoClear["functions"]) && function_exists($arrayInfo['function']) && in_array($arrayInfo['function'],$infoClear["functions"])){
94
+ foreach($infoClear['functions'] as $function) {
95
+ remove_action( $actionsToClear, $function, $priority, $arrayInfo['accepted_args'] );
96
+ }
97
+ // if there is only one function to remove (key: function, type: string)
98
+ } else if(array_key_exists('function', $infoClear) && $infoClear['function'] === $arrayInfo['function']) {
99
+ remove_action( $actionsToClear, $infoClear['function'], $priority, $arrayInfo['accepted_args'] );
100
+ }
101
+ }
102
+
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
trunk/helpers/cron.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_cron extends WYSIJA_object{
4
+
5
+ var $report=false;
6
+
7
+ function __construct(){
8
+ parent::__construct();
9
+ }
10
+
11
+ /**
12
+ * the cron tasks are being run for a certain number of processes (all queue, bounce etc..)
13
+ * @return void
14
+ */
15
+ function run() {
16
+ @ini_set('max_execution_time',0);
17
+ $model_config = WYSIJA::get('config','model');
18
+ $running = false;
19
+ if(!$model_config->getValue('cron_manual')){
20
+ return;
21
+ }
22
+ // get the param from where you want
23
+ $report = $process = false;
24
+ if(isset($_REQUEST['process']) && $_REQUEST['process']){
25
+ $process = $_REQUEST['process'];
26
+ }elseif(!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SHELL']) && isset($_SERVER['argv'][2]) && $_SERVER['argv'][2]){
27
+ $process = $_SERVER['argv'][2];
28
+ }
29
+
30
+ if(isset($_REQUEST['report']) && $_REQUEST['report']){
31
+ $this->report = $_REQUEST['report'];
32
+ }elseif(!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SHELL']) && isset($_SERVER['argv'][3]) && $_SERVER['argv'][3]){
33
+ $this->report = $_SERVER['argv'][3];
34
+ }
35
+
36
+ if( !empty($process) ){
37
+ //include the needed parts of wp plus wysija
38
+ if(isset($_REQUEST[WYSIJA_CRON]) || ( isset($_SERVER['argv'][1]) && $_SERVER['argv'][1]==WYSIJA_CRON )) echo '';
39
+ else{
40
+ wp_die("<h2>" . 'Invalid token' . "</h2>", "MailPoet CRON error", array(
41
+ 'response' => 404,
42
+ 'back_link' => false
43
+ ));
44
+ }
45
+ $cron_schedules = get_option('wysija_schedules');
46
+
47
+ $processes = array();
48
+ if(strpos($process, ',')!==false){
49
+ $processes = explode(',', $process);
50
+ }else $processes[] = $process;
51
+
52
+ $allProcesses = array('queue','bounce','daily','weekly','monthly');
53
+ foreach($processes as $scheduleprocess){
54
+ if($scheduleprocess!='all'){
55
+ if( in_array( $scheduleprocess, $allProcesses ) ){
56
+ $this->check_scheduled_task($cron_schedules,$scheduleprocess);
57
+ }else{
58
+ wp_die("<h2>" . 'Invalid process' . "</h2>", "MailPoet CRON error", array(
59
+ 'response' => 404,
60
+ 'back_link' => false
61
+ ));
62
+ }
63
+ }else{
64
+ foreach($allProcesses as $processNK){
65
+ $this->check_scheduled_task($cron_schedules,$processNK);
66
+ }
67
+ if($this->report) echo 'processed : All<br/>';
68
+ if(!isset($_REQUEST['silent'])) echo 'MailPoet\'s cron is ready. Simply setup a CRON job on your server (cpanel or other) to trigger this page.';
69
+ exit;
70
+ }
71
+ }
72
+ }else{
73
+ wp_die("<h2>" . 'Missing process' . "</h2>", "MailPoet CRON error", array(
74
+ 'response' => 404,
75
+ 'back_link' => false
76
+ ));
77
+ }
78
+ if(!isset($_REQUEST['silent'])) echo '"MailPoet\'s cron is ready. Simply setup a CRON job on your server (cpanel or other) to trigger this page.' ;
79
+ if($process) exit;
80
+ }
81
+
82
+ /**
83
+ * check that one scheduled task is ready to be executed
84
+ * @param type $cron_schedules list of recorded cron schedules
85
+ * @param type $processNK what to process queue, bounce etc...
86
+ */
87
+ function check_scheduled_task($cron_schedules,$processNK){
88
+ $helper_toolbox = WYSIJA::get('toolbox','helper');
89
+ $time_passed = $time_left = 0;
90
+ $run_scheduled = true;
91
+ $extra_text = $multisite_prefix = '';
92
+ // this is to display a different message whether we're dealing with bounce or not.
93
+ if($processNK == 'bounce'){
94
+ $model_config = WYSIJA::get( 'config' , 'model' );
95
+ // if premium is activated we launch the premium function
96
+ $multisite_prefix = '';
97
+ if(is_multisite()){
98
+ $multisite_prefix = 'ms_';
99
+ }
100
+
101
+ // we don't process the bounce automatically unless the option is ticked
102
+ if(!(defined('WYSIJANLP') && $model_config->getValue( $multisite_prefix . 'bounce_process_auto' )) ){
103
+ $extra_text = ' (bounce handling not activated)';
104
+ $run_scheduled=false;
105
+ }
106
+
107
+ }
108
+
109
+ // calculate the time passed processing a scheduled task
110
+ if(!empty($cron_schedules[$processNK]['running'])){
111
+ $time_passed = time()- $cron_schedules[$processNK]['running'];
112
+ $time_passed = $helper_toolbox->duration_string($time_passed,true,2,5);
113
+ }else{
114
+ $time_left = $cron_schedules[$processNK]['next_schedule'] - time();
115
+ $time_left = $helper_toolbox->duration_string($time_left,true,2,5);
116
+ }
117
+
118
+ if($run_scheduled && $cron_schedules[$processNK]['next_schedule'] < time() && !$cron_schedules[$processNK]['running']){
119
+ if($this->report) echo 'exec process '.$processNK.'<br/>';
120
+ $this->run_scheduled_task($processNK);
121
+ }else{
122
+ if($this->report){
123
+ if($time_passed) $text_time = ' running since : '.$time_passed;
124
+ else $text_time = ' next run : '.$time_left;
125
+ if(!empty($extra_text)) $text_time = $extra_text;
126
+ echo 'skip process <strong>'.$processNK.'</strong>'.$text_time.'<br/>';
127
+ }
128
+ }
129
+ }
130
+
131
+ /**
132
+ * run process if it's not detected as already running
133
+ * @param type $process
134
+ * @return type
135
+ */
136
+ function run_scheduled_task($process = 'queue'){
137
+ //first let's make sure that the process asked to be run is not already running
138
+ $scheduled_times = WYSIJA::get_cron_schedule($process);
139
+ $processes = WYSIJA::get_cron_frequencies();
140
+ $process_frequency = $processes[$process];
141
+
142
+ // check if the scheduled task is already being processed,
143
+ // we consider it timed out once the started running time plus the frequency has been passed
144
+ if(!empty($scheduled_times['running']) && ($scheduled_times['running'] + $process_frequency) > time()){
145
+ if($this->report) echo 'already running : '.$process.'<br/>';
146
+ return;
147
+ }
148
+
149
+ // set schedule as running
150
+ WYSIJA::set_cron_schedule($process,0,time());
151
+
152
+ // execute schedule
153
+ switch($process){
154
+ case 'queue':
155
+ // check if there are any scheduled newsletters ready for action
156
+ WYSIJA::check_scheduled_newsletters();
157
+
158
+ // if premium is activated we execute the premium cron process
159
+ if(defined('WYSIJANLP')){
160
+ $helper_premium = WYSIJA::get('premium', 'helper', false, WYSIJANLP);
161
+ $helper_premium->croned_queue_process();
162
+ }else{
163
+ // run the standard queue process no scheduled tasks will be check since it has already been checked above
164
+ WYSIJA::croned_queue(false);
165
+ }
166
+ break;
167
+ case 'bounce':
168
+ $helper_premium = WYSIJA::get('premium', 'helper', false, WYSIJANLP);
169
+ $model_config = WYSIJA::get( 'config' , 'model' );
170
+ // if premium is activated we launch the premium function
171
+ if(is_multisite()){
172
+ $multisite_prefix='ms_';
173
+ }
174
+
175
+ // we don't process the bounce automatically unless the option is ticked
176
+ if(defined('WYSIJANLP') && $model_config->getValue( $multisite_prefix . 'bounce_process_auto' )){
177
+ $helper_premium->croned_bounce();
178
+ }else{
179
+ $process .= ' (bounce handling not activated)';
180
+ }
181
+
182
+ break;
183
+ case 'daily':
184
+ WYSIJA::croned_daily();
185
+ break;
186
+ case 'weekly':
187
+ if(defined('WYSIJANLP')){
188
+ $helper_premium = WYSIJA::get('premium', 'helper', false, WYSIJANLP);
189
+ $helper_premium->croned_weekly();
190
+ }
191
+ WYSIJA::croned_weekly();
192
+ break;
193
+ case 'monthly':
194
+ WYSIJA::croned_monthly();
195
+ break;
196
+ }
197
+ // set next_schedule details
198
+ WYSIJA::set_cron_schedule($process);
199
+ if($this->report) echo 'processed : '.$process.'<br/>';
200
+ }
201
+ }
trunk/helpers/dividers.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_dividers extends WYSIJA_object {
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ }
8
+
9
+ /**
10
+ * Returns all dividers
11
+ * @return array
12
+ */
13
+ function getAll() {
14
+ $fileHelper = WYSIJA::get('file', 'helper');
15
+ $dirHandle = $fileHelper->exists('dividers');
16
+
17
+ if($dirHandle['result'] === FALSE) {
18
+ return array();
19
+ } else {
20
+ $dividers = array();
21
+ $files = scandir($dirHandle['file']);
22
+ foreach($files as $filename) {
23
+ // don't add meta files
24
+ if(in_array($filename, array('.', '..', '.DS_Store', 'Thumbs.db')) === FALSE) {
25
+ // get dimensions of image
26
+ $dimensions = @getimagesize($dirHandle['file'].DS.$filename);
27
+ if($dimensions !== FALSE) {
28
+ $width = (int)$dimensions[0];
29
+ $height = (int)$dimensions[1];
30
+ } else {
31
+ $width = 564;
32
+ $height = 1;
33
+ }
34
+
35
+ // only add divider if height is superior to 0
36
+ if($height > 0) {
37
+ $ratio = round(($width / $height) * 1000) / 1000;
38
+ $width = min($width, 564);
39
+ $height = (int)($width / $ratio);
40
+
41
+ $dividers[] = array(
42
+ 'src' => $fileHelper->url($filename, 'dividers'),
43
+ 'width' => $width,
44
+ 'height' => $height
45
+ );
46
+ }
47
+ }
48
+ }
49
+ return $dividers;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Get default divider
55
+ * @return array
56
+ */
57
+ function getDefault() {
58
+ $fileHelper = WYSIJA::get('file', 'helper');
59
+ return array(
60
+ 'src' => $fileHelper->url('solid.jpg', 'dividers'),
61
+ 'width' => 564,
62
+ 'height' => 1
63
+ );
64
+ }
65
+ }
trunk/helpers/email.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_email extends WYSIJA_object{
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ }
8
+
9
+ /**
10
+ * used to strip the unsubscribe links and the view in browser links from an email html
11
+ * @param type $content
12
+ * @return type
13
+ */
14
+ function stripPersonalLinks($content){
15
+
16
+ //delete the view in browser span
17
+ $content = preg_replace('#<td id="wysija_viewbrowser_content"[^>]*>(.*)</td>#Uis','',$content);
18
+ $content = preg_replace('#<p *class="wysija_viewbrowser_container"[^>]*>(.*)</p>#Uis','',$content);
19
+
20
+ //delete the unsubscribe td
21
+ $content = preg_replace('#<td id="wysija_unsubscribe_content"[^>]*>(.*)</td>#Uis','',$content);
22
+ $content = preg_replace('#<p *class="wysija_unsubscribe_container"[^>]*>(.*)</p>#Uis','',$content);
23
+
24
+ return $content;
25
+
26
+ }
27
+
28
+ /**
29
+ *
30
+ * @param array $values configuration form's current values
31
+ * @param boolean $testMultisite test the multisite configuration
32
+ * @return boolean
33
+ */
34
+ function send_test_mail($values,$testMultisite=false){
35
+ $content_email=__('Yup, it works. You can start blasting away emails to the moon.',WYSIJA);
36
+
37
+ $options=array(
38
+ 'sending_method'=>'sending_method',
39
+ 'sending_emails_site_method'=>'sending_emails_site_method',
40
+ 'sendmail_path'=>'sendmail_path',
41
+ 'smtp_rest'=>'smtp_rest',
42
+ 'smtp_host'=>'smtp_host',
43
+ 'smtp_port'=>'smtp_port',
44
+ 'smtp_secure'=>'smtp_secure',
45
+ 'smtp_auth'=>'smtp_auth',
46
+ );
47
+
48
+ if($testMultisite){
49
+ $is_multisite=is_multisite();
50
+
51
+ //$is_multisite=true;//PROD comment that line
52
+ if(!$is_multisite) return false;
53
+ }
54
+
55
+ switch($values[$options['sending_method']]){
56
+ case 'network':
57
+ case 'site':
58
+ if($values[$options['sending_emails_site_method']]=='phpmail'){
59
+ $send_method='PHP Mail';
60
+ }else{
61
+ $send_method='Sendmail';
62
+ $sendmail_path=$_POST['data']['wysija[config]['.$options['sendmail_path'].']'];
63
+ }
64
+ break;
65
+ case 'smtp':
66
+ $smtp=array();
67
+ $send_method='SMTP';
68
+ $config=WYSIJA::get('config','model');
69
+ if(!isset($values[$options['smtp_rest']])) unset($config->values[$options['smtp_rest']]);
70
+ break;
71
+ case 'gmail':
72
+ $send_method='Gmail';
73
+
74
+ $values[$options['smtp_host']]='smtp.gmail.com';
75
+ $values[$options['smtp_port']]='465';
76
+ $values[$options['smtp_secure']]='ssl';
77
+ $values[$options['smtp_auth']]=true;
78
+
79
+ $content_email=__('You\'re all setup! You\'ve successfully sent with Gmail.',WYSIJA).'<br/><br/>';
80
+ $content_email.=str_replace(
81
+ array('[link]','[/link]'),
82
+ array('<a href="http://support.mailpoet.com/knowledgebase/send-with-smtp-when-using-a-professional-sending-provider/?utm_source=wpadmin&utm_campaign=test_email_result" target="_blank" title="SendGrid partnership">','</a>'),
83
+ __('Looking for a faster method to send? [link]Read more[/link] on sending with a professional SMTP.',WYSIJA));
84
+ break;
85
+ }
86
+
87
+ $mailer=WYSIJA::get('mailer','helper');
88
+ $mailer->__construct('',$values,$testMultisite);
89
+
90
+ $current_user=WYSIJA::wp_get_userdata();
91
+ $mailer->testemail=true;
92
+ $mailer->wp_user=&$current_user->data;
93
+ // If users enter a custom email, let's send to that address
94
+ if (isset($values['test_mails']) && trim($values['test_mails']) != '') {
95
+ $current_user->data->user_email = $values['test_mails'];
96
+ }
97
+
98
+ $res=$mailer->sendSimple($current_user->data->user_email,str_replace('[send_method]',$send_method,__('[send_method] works with MailPoet',WYSIJA)),$content_email);
99
+
100
+ if($res){
101
+ $this->notice(sprintf(__('Test email successfully sent to %s',WYSIJA),'<b><i>'.$current_user->data->user_email.'</i></b>'));
102
+ return true;
103
+ }else{
104
+ $config=WYSIJA::get('config','model');
105
+ $bounce = $config->getValue('bounce_email');
106
+ if(in_array($config->getValue('sending_method'),array('smtp','gmail')) && $config->getValue('smtp_secure')=='ssl' && !function_exists('openssl_sign')){
107
+ $this->error(__('The PHP Extension openssl is not enabled on your server. Ask your host to enable it if you want to use an SSL connection.',WYSIJA));
108
+ }elseif(!empty($bounce) AND !in_array($config->getValue('sending_method'),array('smtp_com','elasticemail'))){
109
+ $this->error(sprintf(__('The bounce email address "%1$s" might actually cause the problem. Leave the field empty and try again.',WYSIJA),$bounce));
110
+ //Case 2 : you are using SMTP but you didn't add an authentication
111
+ }elseif(in_array($config->getValue('sending_method'),array('smtp','gmail')) AND !$config->getValue('smtp_auth') AND strlen($config->getValue('smtp_password')) > 1){
112
+ $this->error(__('You specified an SMTP password but you don\'t require an authentication, you might want to turn the SMTP authentication ON.',WYSIJA));
113
+ //Case 3 : you are on localhost!
114
+ }elseif((strpos(WYSIJA_URL,'localhost') || strpos(WYSIJA_URL,'127.0.0.1')) && in_array($config->getValue('sending_method'),array('sendmail','qmail','mail'))){
115
+ $this->error(__('Your localhost may not have a mail server. To verify, please log out and click on the "Lost your password?" link on the login page. Do you receive the reset password email from your WordPress?',WYSIJA));
116
+ }
117
+
118
+ $this->error($mailer->reportMessage);
119
+ return false;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * get view in browser link
125
+ * @param array/stdClass $data_email
126
+ * @return string url
127
+ */
128
+ function getVIB($data_email){
129
+ if (!is_array($data_email) && is_object($data_email))
130
+ $data_email = (array) $data_email;
131
+ if(false && isset($data_email['params']['vib_id'])) return WYSIJA::get_permalink($data_email['params']['vib_id'],false);
132
+ else{
133
+ $paramsurl=array(
134
+ 'wysija-page'=>1,
135
+ 'controller'=>'email',
136
+ 'action'=>'view',
137
+ 'email_id'=>$data_email['email_id']
138
+ );
139
+
140
+ $modelConf=WYSIJA::get('config','model');
141
+ return WYSIJA::get_permalink($modelConf->getValue('confirm_email_link'),$paramsurl);
142
+ }
143
+ }
144
+
145
+ /**
146
+ * return an array of active follow_ups
147
+ * @param type $data
148
+ * @param boolean $delay calculate delay and add it to the result
149
+ */
150
+ function get_active_follow_ups($data=array('subject','params'),$delay=false){
151
+ if($delay) $model_queue=WYSIJA::get('queue','model');
152
+
153
+ $model_email=WYSIJA::get('email','model');
154
+ $model_email->setConditions(array('type'=>2,'status'=>99));
155
+ $automatic_emails=$model_email->getRows($data);
156
+
157
+ $follow_ups_per_list=array();
158
+ foreach($automatic_emails as &$auto_email){
159
+ $model_email->getParams($auto_email);
160
+ if($delay) $auto_email['delay']=$model_queue->calculate_delay($auto_email['params']['autonl']);
161
+ if(isset($auto_email['params']['autonl']['event']) && $auto_email['params']['autonl']['event']=='subs-2-nl'){
162
+ if(!isset($follow_ups_per_list[$auto_email['params']['autonl']['subscribetolist']])) $follow_ups_per_list[$auto_email['params']['autonl']['subscribetolist']]=array();
163
+ $follow_ups_per_list[$auto_email['params']['autonl']['subscribetolist']][]=$auto_email;
164
+ }
165
+ }
166
+
167
+ return $follow_ups_per_list;
168
+ }
169
+
170
+ }
trunk/helpers/encoding.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_encoding{
4
+ function change($data,$input,$output){
5
+ $input = strtoupper(trim($input));
6
+ $output = strtoupper(trim($output));
7
+ if($input == $output) return $data;
8
+ if ($input == 'UTF-8' && $output == 'ISO-8859-1'){
9
+ $data = str_replace(array('€','„','“'),array('EUR','"','"'),$data);
10
+ }
11
+ if (function_exists('iconv')){
12
+ set_error_handler('acymailing_error_handler_encoding');
13
+ $encodedData = iconv($input, $output."//IGNORE", $data);
14
+ restore_error_handler();
15
+ if(!acymailing_error_handler_encoding('result')){
16
+ return $encodedData;
17
+ }
18
+ }
19
+ if (function_exists('mb_convert_encoding')){
20
+ return mb_convert_encoding($data, $output, $input);
21
+ }
22
+ if ($input == 'UTF-8' && $output == 'ISO-8859-1'){
23
+ return utf8_decode($data);
24
+ }
25
+ if ($input == 'ISO-8859-1' && $output == 'UTF-8'){
26
+ return utf8_encode($data);
27
+ }
28
+ return $data;
29
+ }
30
+ }//endclass
31
+ function acymailing_error_handler_encoding($errno,$errstr=''){
32
+ static $error = false;
33
+ if(is_string($errno) && $errno=='result'){
34
+ $currentError = $error;
35
+ $error = false;
36
+ return $currentError;
37
+ }
38
+ $error = true;
39
+ return true;
40
+ }
trunk/helpers/file.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ class WYSIJA_help_file extends WYSIJA_object{
4
+
5
+ function __construct(){
6
+ parent::__construct();
7
+ }
8
+
9
+ /**
10
+ * Get the full path of a file
11
+ * @param type $csvfilename
12
+ * @param type $folder
13
+ * @return boolean
14
+ */
15
+ function exists($fileFolder=false){
16
+ $upload_base_dir = $this->getUploadBaseDir();
17
+
18
+ $filename=str_replace('/',DS,$upload_base_dir).DS.'wysija'.DS.$fileFolder;
19
+ if(!file_exists($filename)){
20
+ return array('result'=>false,'file'=>$filename);
21
+ }
22
+
23
+ return array('result'=>true,'file'=>$filename);
24
+ }
25
+
26
+ /**
27
+ * Get the full path of a file
28
+ * @param type $csvfilename
29
+ * @param type $folder
30
+ * @return boolean
31
+ */
32
+ function get($csvfilename,$folder='temp'){
33
+ $upload_base_dir = $this->getUploadBaseDir();
34
+
35
+ $filename=$upload_base_dir.DS.'wysija'.DS.$folder.DS.$csvfilename;
36
+ if(!file_exists($filename)){
37
+ $filename=$upload_base_dir.DS.$csvfilename;
38
+ if(!file_exists($filename)) $filename=false;
39
+ }
40
+
41
+ return $filename;
42
+ }
43
+
44
+ // Description: create a directory recursively if possible
45
+ // Parameters: (Name of the directory, permissions)
46
+ // Returns: Directory path. False if impossible to create folder.
47
+ function makeDir($folder='temp',$mode=0755){
48
+ $upload_base_dir = $this->getUploadBaseDir();
49
+
50
+ if(strpos(str_replace('/',DS,$folder),str_replace('/',DS,$upload_base_dir))!==false){
51
+ $dirname=$folder;
52
+ }else{
53
+ $dirname=$upload_base_dir.DS.'wysija'.DS.$folder.DS;
54
+ }
55
+ if(!file_exists($dirname)){
56
+ if(!mkdir($dirname, $mode,true)){
57
+ $this->error('Cannot create folder '.$dirname.' try to create the folder manually');
58
+ return false;
59
+ }
60
+ chmod($dirname,$mode);
61
+ }
62
+ return $dirname;
63
+ }
64
+
65
+
66
+ function getUploadDir($folder=false){
67
+ $upload_base_dir = $this->getUploadBaseDir();
68
+
69
+ $dirname=$upload_base_dir.DS.'wysija'.DS;
70
+ if($folder) $dirname.=$folder.DS;
71
+ if(file_exists($dirname)) return $dirname;
72
+ return false;
73
+ }
74
+
75
+ function getUploadBaseDir(){
76
+ $upload_dir = wp_upload_dir();
77
+
78
+ if(!isset($upload_dir['basedir'])){
79
+ if(isset($upload_dir['error'])) $this->wp_error('<b>WordPress error</b> : '.$upload_dir['error'],1);
80
+ return false;
81
+ }
82
+
83
+ //having .. in a path is not safe as it can lead to some parent path where we don't have control
84
+ if(strpos($upload_dir['basedir'], '..')!==false){
85
+ $pathsections=$pathsectionsc=explode(DS, $upload_dir['basedir']);
86
+
87
+ while($key = array_search('..', $pathsections)){
88
+ unset($pathsections[$key]);
89
+ unset($pathsections[$key-1]);
90
+ $newpatharray=array();
91
+ foreach($pathsections as $ky=>$vy){
92
+ $newpatharray[]=$vy;
93
+ }
94
+ $pathsections=$newpatharray;
95
+ }
96
+ $cleanBaseDir=implode(DS, $pathsections);
97
+
98
+ if(file_exists($cleanBaseDir)){
99
+ $upload_dir['basedir']=$cleanBaseDir;
100
+ }
101
+ }
102
+
103
+
104
+ return $upload_dir['basedir'];
105
+ }
106
+
107
+ /**
108
+ * make a temporary file
109
+ * @param type $content
110
+ * @param type $key
111
+ * @param type $format
112
+ * @return type
113
+ */
114
+ function temp($content,$key='temp',$format='.tmp'){
115
+ $tempDir=$this->makeDir();
116
+
117
+ if(!$tempDir) return false;
118
+
119
+ $time_created = substr( md5(rand()), 0, 20);
120
+ $file_name = $key.'-'.$time_created.$format;
121
+
122
+ $handle=fopen($tempDir.$file_name, 'w');
123
+ fwrite($handle, $content);
124
+ fclose($handle);
125
+
126
+ return array('path'=>$tempDir.$file_name,'name'=>$file_name, 'url'=>$this->url($file_name,'temp'));
127
+ }
128
+
129
+ /**
130
+ * Get the url of a wysija file based on the filename and the wysija folder
131
+ * @param type $filename
132
+ * @param type $folder
133
+ * @return string
134
+ */
135
+ function url($filename,$folder='temp'){
136
+ $upload_dir = wp_upload_dir();
137
+
138
+ if(file_exists($upload_dir['basedir'].DS.'wysija')){
139
+ $url=$upload_dir['baseurl'].'/wysija/'.$folder.'/'.$filename;
140
+ }else{
141
+ $url=$upload_dir['baseurl'].'/'.$filename;
142
+ }
143
+
144
+ return str_replace(DS,'/',$url);
145
+ }
146
+
147
+ /*
148
+ *
149
+ */
150
+ function clear(){
151
+ $folders_to_clear = array("import","temp");
152
+ $filename_removal = array("import-","export-", 'export_userids-');
153
+ $deleted=array();
154
+ foreach($folders_to_clear as $folder){
155
+ $path=$this->getUploadDir($folder);
156
+ /* get a list of files from this folder and clear them */
157
+ if(!$path) continue;
158
+ $files = scandir($path);
159
+ foreach($files as $filename){
160
+ if(!in_array($filename, array('.','..',".DS_Store","Thumbs.db"))){
161
+ if(preg_match('/('.implode($filename_removal,'|').')[a-f0-9]*\.(csv|txt)/',$filename,$match)){
162
+ $deleted[]=$path.$filename;
163
+ }
164
+ }
165
+ }
166
+ }
167
+ foreach($deleted as $filename){
168
+ if(file_exists($filename)){
169
+ $filename=str_replace('/',DS,$filename);
170
+ unlink($filename);
171
+ }
172
+ }
173
+
174
+ }
175
+
176
+ function rrmdir($dir) {
177
+ if(strpos($dir, '..')!==false){
178
+ $this->error('Path is not safe, cannot contain ..');
179
+ return false;
180
+ }
181
+ if (is_dir($dir)) {
182
+ $files = scandir($dir);
183
+ foreach ($files as $file){
184
+ if ($file != "." && $file != "..") $this->rrmdir("$dir".DS."$file");
185
+ }
186
+
187
+ if(!rmdir($dir)){
188
+ chmod($dir, 0777);
189
+ rmdir($dir);
190
+ }
191
+
192
+
193
+ }
194
+ else if (file_exists($dir)) {
195
+ $dir=str_replace('/',DS,$dir);
196
+ unlink($dir);
197
+ }
198
+ }
199
+
200
+ function rcopy($src, $dst) {
201
+ if(strpos($src, '..')!==false || strpos($dst, '..')!==false){
202
+ $this->error('src : '.$src);
203
+ $this->error('dst : '.$dst);
204
+ $this->error('Path is not safe, cannot contain ..');
205
+ return false;
206
+ }else{
207
+ if (file_exists($dst)) $this->rrmdir($dst);
208
+ }
209
+
210
+ if (is_dir($src)) {
211
+ mkdir($dst);
212
+ $files = scandir($src);
213
+ foreach ($files as $file){
214
+ if ($file != "." && $file != "..") $this->rcopy("$src/$file", "$dst/$file");
215
+ }
216
+
217
+ }
218
+ else if (file_exists($src)) {
219
+ copy(str_replace('/',DS,$src), str_replace('/',DS,$dst));
220
+ }
221
+ }
222
+ }
223
+
trunk/helpers/form_engine.php ADDED
@@ -0,0 +1,843 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /**
4
+ * @class Wysija Engine Helper (PHP5 version)
5
+ */
6
+ class WYSIJA_help_form_engine extends WYSIJA_object {
7
+ // debug mode
8
+ private $_debug = false;
9
+
10
+ // rendering context (editor, web)
11
+ private $_context = 'editor';
12
+ // rendering mode (live, preview)
13
+ private $_mode = 'live';
14
+
15
+ // data holders
16
+ private $_data = null;
17
+ private $_styles = null;
18
+ private $_lists = null;
19
+ private $_fields = null;
20
+
21
+ // static form fields
22
+ private $_static_fields = array('email', 'submit');
23
+
24
+ // unique form fields
25
+ private $_unique_fields = array('firstname', 'lastname', 'list');
26
+
27
+ // constructor
28
+ function __construct(){
29
+ parent::__construct();
30
+ }
31
+
32
+
33
+ // i18n methods
34
+ public function get_translations() {
35
+ return array(
36
+ 'savingnl' => __('Saving form...', WYSIJA),
37
+ 'save' => __('Save', WYSIJA),
38
+ 'edit_settings' => __('Edit display', WYSIJA),
39
+ 'list_cannot_be_empty' => __('You have to select at least 1 list', WYSIJA),
40
+ 'not_enough_options' => __('Your subscriber needs at least 2 options to select from', WYSIJA),
41
+ 'missing_checkbox_label' => __('You need to specify a value for your checkbox', WYSIJA),
42
+ 'add_field' => __('Add new field', WYSIJA),
43
+ 'edit_field' => __('Edit custom field', WYSIJA),
44
+ 'delete_field_confirmation' => __('Are you sure you want to delete this custom field?', WYSIJA),
45
+ 'date_select_year' => __('Year', WYSIJA),
46
+ 'date_select_month' => __('Month', WYSIJA),
47
+ 'date_select_day' => __('Day', WYSIJA)
48
+ );
49
+ }
50
+
51
+ public function get_months($options = array()) {
52
+
53
+ $defaults = array(
54
+ 'selected' => null
55
+ );
56
+ // is default today
57
+ if(isset($options['params']['is_default_today']) && (bool)$options['params']['is_default_today'] === true) {
58
+ $defaults['selected'] = (int)strftime('%m');
59
+ }
60
+
61
+ // merge options with defaults
62
+ $options = array_merge($defaults, $options);
63
+
64
+ $month_names = array(
65
+ __('January', WYSIJA),
66
+ __('February', WYSIJA),
67
+ __('March', WYSIJA),
68
+ __('April', WYSIJA),
69
+ __('May', WYSIJA),
70
+ __('June', WYSIJA),
71
+ __('July', WYSIJA),
72
+ __('August', WYSIJA),
73
+ __('September', WYSIJA),
74
+ __('October', WYSIJA),
75
+ __('November', WYSIJA),
76
+ __('December', WYSIJA)
77
+ );
78
+
79
+ $months = array();
80
+ for($i = 0; $i < 12; $i++) {
81
+ $months[] = array(
82
+ 'month' => ($i + 1),
83
+ 'month_name' => $month_names[$i],
84
+ 'is_selected' => (($i + 1) === $options['selected'])
85
+ );
86
+ }
87
+
88
+ return $months;
89
+ }
90
+
91
+ public function get_years($options = array()) {
92
+ $defaults = array(
93
+ 'selected' => null,
94
+ 'from' => (int)strftime('%Y') - 100,
95
+ 'to' => (int)strftime('%Y')
96
+ );
97
+ // is default today
98
+ if(isset($options['params']['is_default_today']) && (bool)$options['params']['is_default_today'] === true) {
99
+ $defaults['selected'] = (int)strftime('%Y');
100
+ }
101
+
102
+ // merge options with defaults
103
+ $options = array_merge($defaults, $options);
104
+
105
+ $years = array();
106
+
107
+ // return years as an array
108
+ for($i = (int)$options['from']; $i < (int)($options['to'] + 1); $i++) {
109
+ $years[] = array(
110
+ 'year' => $i,
111
+ 'is_selected' => ($i === $options['selected'])
112
+ );
113
+ }
114
+
115
+ return array_reverse($years);
116
+ }
117
+
118
+ public function get_days($options = array()) {
119
+ $defaults = array(
120
+ 'selected' => null
121
+ );
122
+ // is default today
123
+ if(isset($options['params']['is_default_today']) && (bool)$options['params']['is_default_today'] === true) {
124
+ $defaults['selected'] = (int)strftime('%d');
125
+ }
126
+
127
+ // merge options with defaults
128
+ $options = array_merge($defaults, $options);
129
+
130
+ $days = array();
131
+
132
+ // return days as an array
133
+ for($i = 1; $i < 32; $i++) {
134
+ $days[] = array(
135
+ 'day' => $i,
136
+ 'is_selected' => ($i === $options['selected'])
137
+ );
138
+ }
139
+
140
+ return $days;
141
+ }
142
+
143
+ // getters/setters
144
+ public function get_data($type = null) {
145
+ if($type !== null) {
146
+ if(array_key_exists($type, $this->_data)) {
147
+ return $this->_data[$type];
148
+ } else {
149
+ // return default value
150
+ $defaults = $this->get_default_data();
151
+ return $defaults[$type];
152
+ }
153
+ }
154
+ return $this->_data;
155
+ }
156
+
157
+ public function set_data($value = null, $decode = false) {
158
+ if(!$value) {
159
+ $this->_data = $this->get_default_data();
160
+ } else {
161
+ $this->_data = $value;
162
+ if($decode) {
163
+ $this->_data = $this->get_decoded('data');
164
+ }
165
+ }
166
+ }
167
+
168
+ public function set_lists($lists = array()) {
169
+ $this->_lists = $lists;
170
+ }
171
+
172
+ public function get_formatted_lists() {
173
+
174
+ $lists = $this->get_lists();
175
+ $formatted_lists = array();
176
+
177
+ foreach($lists as $list) {
178
+ $formatted_lists[$list['list_id']] = $list['name'];
179
+ }
180
+ return $formatted_lists;
181
+ }
182
+
183
+ public function get_lists() {
184
+ if($this->_lists === null) {
185
+ // get available lists which users can subscribe to
186
+ $model_list = WYSIJA::get('list','model');
187
+
188
+ // get lists users can subscribe to (aka "enabled list")
189
+ $lists = $model_list->get(array('name', 'list_id', 'is_public'), array('is_enabled' => 1));
190
+
191
+ $this->set_lists($lists);
192
+ }
193
+ return $this->_lists;
194
+ }
195
+
196
+ private function get_context() {
197
+ return $this->_context;
198
+ }
199
+
200
+ private function set_context($value = null) {
201
+ if($value !== null) $this->_context = $value;
202
+ }
203
+
204
+ public function set_mode($value = null) {
205
+ if($value !== null) $this->_mode = $value;
206
+ }
207
+
208
+ private function get_mode() {
209
+ return $this->_mode;
210
+ }
211
+
212
+ public function get_encoded($type = 'data') {
213
+ return base64_encode(serialize($this->{'get_'.$type}()));
214
+ }
215
+
216
+ public function get_decoded($type = 'data') {
217
+ return unserialize(base64_decode($this->{'get_'.$type}()));
218
+ }
219
+
220
+ private function get_default_data() {
221
+
222
+ $lists = $this->get_lists();
223
+
224
+ // select default list
225
+ $default_list = array();
226
+ if(!empty($lists)) {
227
+ $default_list[] = $lists[0]['list_id'];
228
+ }
229
+
230
+ return array(
231
+ 'version' => '0.4',
232
+ 'settings' => array(
233
+ 'on_success' => 'message',
234
+ 'success_message' => __('Check your inbox or spam folder now to confirm your subscription.', WYSIJA),
235
+ 'lists' => $default_list,
236
+ 'lists_selected_by' => 'admin'
237
+ ),
238
+ 'body' => array(
239
+ array(
240
+ 'name' => __('Email', WYSIJA),
241
+ 'type' => 'input',
242
+ 'field' => 'email',
243
+ 'params' => array(
244
+ 'label' => __('Email', WYSIJA),
245
+ 'required' => true
246
+ )
247
+ ),
248
+ array(
249
+ 'name' => __('Submit', WYSIJA),
250
+ 'type' => 'submit',
251
+ 'field' => 'submit',
252
+ 'params' => array(
253
+ 'label' => __('Subscribe!', WYSIJA)
254
+ )
255
+ )
256
+ )
257
+ );
258
+ }
259
+
260
+ public function get_setting($key = null) {
261
+ if($key === null) return null;
262
+
263
+ if($this->is_data_valid() === true) {
264
+ $settings = $this->get_data('settings');
265
+ if(array_key_exists($key, $settings)) {
266
+ // otherwise, simply return the value
267
+ return $settings[$key];
268
+ } else {
269
+ return null;
270
+ }
271
+ }
272
+ }
273
+
274
+ // common methods
275
+ private function is_debug() {
276
+ return ($this->_debug === true);
277
+ }
278
+
279
+ private function is_data_valid() {
280
+ return ($this->get_data() !== null);
281
+ }
282
+
283
+ public function get_custom_fields() {
284
+ if($this->_fields === null) {
285
+ // get available custom fields
286
+ $custom_fields = WJ_Field::get_all(array('order_by' => 'name ASC'));
287
+ $user_fields = array();
288
+
289
+ if(!empty($custom_fields)) {
290
+ foreach($custom_fields as $custom_field) {
291
+ $user_fields[] = array(
292
+ 'field_id' => $custom_field->id,
293
+ 'name' => $custom_field->name,
294
+ 'column_name' => $custom_field->user_column_name(),
295
+ 'column_type' => $custom_field->type,
296
+ 'params' => $custom_field->settings
297
+ );
298
+ }
299
+ }
300
+
301
+ // we need to figure out the default list for the "List selection" widget
302
+ $lists = $this->get_lists();
303
+
304
+ // select default list
305
+ $default_list = array();
306
+ if(!empty($lists)) {
307
+ $default_list[] = array(
308
+ 'list_id' => $lists[0]['list_id'],
309
+ 'is_checked' => 0
310
+ );
311
+ }
312
+
313
+ // extra widgets that can be added more than once
314
+ $extra_fields = array(
315
+ array(
316
+ 'name' => __('Divider', WYSIJA),
317
+ 'column_name' => 'divider',
318
+ 'column_type' => 'divider'
319
+ ),
320
+ array(
321
+ 'name' => __('First name', WYSIJA),
322
+ 'column_name' => 'firstname',
323
+ 'column_type' => 'input'
324
+ ),
325
+ array(
326
+ 'name' => __('Last name',WYSIJA),
327
+ 'column_name' => 'lastname',
328
+ 'column_type' => 'input'
329
+ ),
330
+ array(
331
+ 'name' => __('List selection', WYSIJA),
332
+ 'column_name' => 'list',
333
+ 'column_type' => 'list',
334
+ 'params' => array(
335
+ 'label' => __('Select list(s):', WYSIJA),
336
+ 'values' => $default_list
337
+ )
338
+ ),
339
+ array(
340
+ 'name' => __('Random text or HTML', WYSIJA),
341
+ 'column_name' => 'html',
342
+ 'column_type' => 'html',
343
+ 'params' => array(
344
+ 'text' => __('Subscribe to our newsletter and join our [total_subscribers] subscribers.', WYSIJA)
345
+ )
346
+ )
347
+ );
348
+
349
+ // set data to be passed to the view
350
+ $this->_fields = array_merge($user_fields, $extra_fields);
351
+ }
352
+
353
+ return $this->_fields;
354
+ }
355
+
356
+ // editor rendering methods
357
+ public function render_editor_toolbar() {
358
+
359
+ // get custom fields
360
+ $fields = $this->get_custom_fields();
361
+
362
+ $output = '';
363
+ $output .= '<li style="text-align:center;"><a id="wysija-add-field" class="button" href="javascript:;" href2="admin.php?page=wysija_config&action=form_widget_settings&field_id=0">'.__('Add New Field',WYSIJA).'</a></li>';
364
+
365
+ foreach($fields as $field) {
366
+ // get field type or defaults to "input"
367
+ $type = (isset($field['column_type'])) ? $field['column_type'] : 'input';
368
+
369
+ // set unique if the field type matches the unique_fields OR is a custom field
370
+ $is_unique = (bool)(in_array($field['column_name'], $this->_unique_fields) or isset($field['field_id']));
371
+
372
+ // check whether it's an actual custom field
373
+ $is_custom_field = $this->is_custom_field($field);
374
+
375
+ // actions
376
+ $actions = '';
377
+ if($is_custom_field) {
378
+ $actions = '<a class="wysija_form_item_settings settings" title="'.__('Edit field', WYSIJA).'" href="javascript:;" href2="admin.php?page=wysija_config&action=form_widget_settings&field_id='.((int)$field['field_id']).'" data-field-id="'.((int)$field['field_id']).'"><span class="dashicons dashicons-admin-generic"></span></a>';
379
+ $actions .= '<a class="wysija_form_item_delete delete" title="'.__('Delete field', WYSIJA).'" href="javascript:;" data-field-id="'.((int)$field['field_id']).'"><span class="dashicons dashicons-dismiss"></span></a>';
380
+ }
381
+
382
+ // generate html for toolbar item
383
+ $output .= '<li><a class="wysija_form_item" id="'.$field['column_name'].'" wysija_field="'.$field['column_name'].'" wysija_name="'.$field['name'].'" wysija_unique="'.$is_unique.'" wysija_type="'.$type.'">'.$field['name'].'</a>'.$actions.'</li>';
384
+ }
385
+
386
+ return $output;
387
+ }
388
+
389
+ // renders all widgets' templates
390
+ function render_editor_templates() {
391
+ $this->set_context('editor');
392
+
393
+ // get custom fields
394
+ $fields = $this->get_custom_fields();
395
+
396
+ // get parser helper
397
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
398
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
399
+
400
+ // define html output string
401
+ $output = '';
402
+
403
+ foreach($fields as $field) {
404
+ // get field type or defaults to "input"
405
+ $type = (isset($field['column_type'])) ? $field['column_type'] : 'input';
406
+
407
+ // get label from params, defaults to field name
408
+ $label = (isset($field['params']['label'])) ? $field['params']['label'] : $field['name'];
409
+
410
+ // build field data in order to pass it to the widget template
411
+ $block = array(
412
+ 'field' => $field['column_name'],
413
+ 'type' => $type,
414
+ 'name' => $field['name'],
415
+ 'unique' => (in_array($field['column_name'], $this->_unique_fields)),
416
+ 'static' => (in_array($field['column_name'], $this->_static_fields)),
417
+ 'params' => array(
418
+ 'label' => $label
419
+ ),
420
+ 'i18n' => $this->get_translations()
421
+ );
422
+
423
+ // get field extra params if specified
424
+ if(isset($field['params'])) {
425
+ // merge the params
426
+ $block['params'] = array_merge($field['params'], $block['params']);
427
+ }
428
+
429
+ // get extra data depending on field type
430
+ $block = $this->_get_extra_data($block);
431
+
432
+ // render widget templates
433
+ $output .= $helper_render_engine->render($block, 'templates/form/editor/widgets/template.html');
434
+ }
435
+ return $output;
436
+ }
437
+
438
+ private function set_lists_names($block = array()) {
439
+ // get lists using each list id as key
440
+ $lists = $this->get_formatted_lists();
441
+
442
+ if($this->get_context() === 'editor') {
443
+ $block['lists'] = $lists;
444
+ } else {
445
+ // if the block has no list, then simply return the block
446
+ if(!isset($block['params']['values']) or empty($block['params']['values'])) return $block;
447
+
448
+ $values = array();
449
+
450
+ foreach($block['params']['values'] as $list) {
451
+ // check if the list id exists in the lists
452
+ if(isset($lists[$list['list_id']])) {
453
+ $is_checked = (isset($list['is_checked']) ? (int)$list['is_checked'] : 0);
454
+ $values[] = array('name' => $lists[$list['list_id']], 'list_id' => $list['list_id'], 'is_checked' => $is_checked);
455
+ }
456
+ }
457
+
458
+ $block['params']['values'] = $values;
459
+ }
460
+
461
+ return $block;
462
+ }
463
+
464
+ // renders a single widget's template
465
+ public function render_editor_template($block = array()) {
466
+ $this->set_context('editor');
467
+
468
+ if(empty($block)) return null;
469
+
470
+ // get parser helper
471
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
472
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
473
+
474
+ // get extra data depending on field type
475
+ $block = $this->_get_extra_data($block);
476
+
477
+ $block = array_merge($block, array(
478
+ 'unique' => (in_array($block['field'], $this->_unique_fields)),
479
+ 'static' => (in_array($block['field'], $this->_static_fields)),
480
+ 'i18n' => $this->get_translations()
481
+ ));
482
+
483
+ // render widget templates
484
+ return $helper_render_engine->render($block, 'templates/form/editor/widgets/template.html');
485
+ }
486
+
487
+ public function refresh_custom_field($form_id = null, $field = array()) {
488
+ if($form_id === null or empty($field)) return null;
489
+
490
+ // check if refreshing the field is necessary
491
+ if($this->is_custom_field($field)) {
492
+ // get all forms
493
+ $model_forms = WYSIJA::get('forms', 'model');
494
+ $forms = $model_forms->getRows();
495
+
496
+ $updated_block = null;
497
+
498
+ // check if there's at least one form otherwise it's kinda pointless
499
+ if(is_array($forms) && count($forms) > 0) {
500
+ // loop over each form
501
+ foreach ($forms as $i => $form) {
502
+ $requires_update = false;
503
+
504
+ // decode form data
505
+ $data = unserialize(base64_decode($form['data']));
506
+
507
+ // loop through each block
508
+ foreach ($data['body'] as $j => $block) {
509
+ // in case we find an instance of the custom field that needs to be updated
510
+ if($block['field'] === $field['field']) {
511
+ $updated_params = $field['settings'];
512
+ $display_fields = array('label', 'label_within', 'lines');
513
+
514
+ // apply block display options
515
+ foreach($display_fields as $display_field) {
516
+ if(array_key_exists($display_field, $block['params'])) {
517
+ $updated_params[$display_field] = $block['params'][$display_field];
518
+ }
519
+ }
520
+
521
+ // apply new parameters
522
+ $data['body'][$j]['params'] = $updated_params;
523
+ // set flag in order to save changes
524
+ $requires_update = true;
525
+
526
+ // if it's in the current form, we need to return an updated version of this block
527
+ if((int)$form['form_id'] === $form_id) {
528
+ $updated_block = $data['body'][$j];
529
+ }
530
+ }
531
+ }
532
+
533
+ // if the form requires update, let's do it
534
+ if($requires_update === true) {
535
+ $model_forms->reset();
536
+ $model_forms->update(array('data' => base64_encode(serialize($data))), array('form_id' => (int)$form['form_id']));
537
+ }
538
+ }
539
+ }
540
+
541
+ // return false if there's no need to update any block in the current form
542
+ return $updated_block;
543
+ }
544
+ }
545
+
546
+ private function _get_extra_data($block = array()) {
547
+ // special case for lists
548
+ if($block['field'] === 'list') {
549
+ $block = $this->set_lists_names($block);
550
+ }
551
+
552
+ // special case for "date" types
553
+ if($block['type'] === 'date') {
554
+ $block['days'] = $this->get_days($block);
555
+ $block['months'] = $this->get_months($block);
556
+ $block['years'] = $this->get_years($block);
557
+
558
+ $display_date_fields = explode('_', $block['params']['date_type']);
559
+
560
+ // date order
561
+ $date_orders = array(
562
+ 'year_month_day' => array('mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy/mm/dd'),
563
+ 'year_month' => array('mm/yyyy', 'yyyy/mm'),
564
+ 'year' => array('yyyy'),
565
+ 'month' => array('mm')
566
+ );
567
+
568
+ if(isset($block['params']['date_order']) && in_array($block['params']['date_order'], $date_orders[$block['params']['date_type']])) {
569
+ $fields = explode('/', $block['params']['date_order']);
570
+ } else {
571
+ $fields = explode('/', $date_orders[$block['params']['date_type']][0]);
572
+ }
573
+ $block['date_fields'] = $fields;
574
+ }
575
+
576
+ return $block;
577
+ }
578
+
579
+ // renders the editor
580
+ function render_editor() {
581
+ $this->set_context('editor');
582
+
583
+ if($this->is_data_valid() === false) {
584
+ throw new Exception('data is not valid');
585
+ } else {
586
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
587
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
588
+
589
+ $data = array(
590
+ 'body' => $this->render_editor_body(),
591
+ 'is_debug' => $this->is_debug(),
592
+ 'i18n' => $this->get_translations()
593
+ );
594
+
595
+ return $helper_render_engine->render($data, 'templates/form/editor/template.html');
596
+ }
597
+ }
598
+
599
+ // renders editor's body
600
+ function render_editor_body() {
601
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
602
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
603
+
604
+ $blocks = $this->get_data('body');
605
+ if(empty($blocks)) return '';
606
+
607
+ $body = '';
608
+ foreach($blocks as $block) {
609
+ // get extra data depending on field type
610
+ $block = $this->_get_extra_data($block);
611
+
612
+ // generate block template
613
+ $data = array_merge($block, array(
614
+ 'unique' => (in_array($block['field'], $this->_unique_fields)),
615
+ 'static' => (in_array($block['field'], $this->_static_fields)),
616
+ 'i18n' => $this->get_translations())
617
+ );
618
+
619
+ $body .= $helper_render_engine->render($data, 'templates/form/editor/widgets/template.html');
620
+ }
621
+
622
+ return $body;
623
+ }
624
+
625
+ // web rendering methods
626
+ public function render_web($data = array()) {
627
+ $this->set_context('web');
628
+
629
+ if($this->is_data_valid() === false) {
630
+ throw new Exception('data is not valid');
631
+ } else {
632
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
633
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
634
+
635
+ $data = array(
636
+ 'preview' => ($this->get_mode() === 'preview'),
637
+ 'settings' => $this->get_data('settings'),
638
+ 'body' => $this->render_web_body()
639
+ );
640
+
641
+ // in live mode, we need to specify the form id
642
+ if($this->get_mode() === 'live') {
643
+ $data['form_id'] = (int)$this->get_data('form_id');
644
+ }
645
+
646
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
647
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
648
+
649
+ // make sure we get the messages
650
+ $output = '';
651
+
652
+ $posted_form = (isset($_POST['form_id']) && (int)$_POST['form_id'] > 0) ? (int)$_POST['form_id'] : 0;
653
+
654
+ /* if($data['form_id'] === $posted_form) {
655
+ $view = WYSIJA::get('widget_nl','view','front');
656
+ if(count($view->getMsgs()) > 0) {
657
+ $output .= $view->messages();
658
+ }
659
+ }*/
660
+
661
+ try {
662
+ $output .= $helper_render_engine->render($data, 'templates/form/web/template.html');
663
+ return $output;
664
+ } catch(Exception $e) {
665
+ return '';
666
+ }
667
+ }
668
+ }
669
+
670
+ protected function get_validation_class($block) {
671
+ $rules = array();
672
+
673
+ // if it's the email field, it's mandatory and needs to be valid
674
+ if($block['field'] === 'email') {
675
+ $rules[] = 'required';
676
+ $rules[] = 'custom[email]';
677
+ }
678
+
679
+ // if it's the list field, at least one option needs to be selected
680
+ if($block['field'] === 'list') {
681
+ $rules[] = 'required';
682
+ }
683
+
684
+ // check if the field is required
685
+ if(isset($block['params']['required']) && (bool)$block['params']['required'] === true) {
686
+ $rules[] = 'required';
687
+ }
688
+
689
+ // check for validation rules
690
+ if(isset($block['params']['validate'])) {
691
+ if(is_array($block['params']['validate'])) {
692
+ // handle multiple validation rules
693
+ foreach($block['params']['validate'] as $rule) {
694
+ $rules[] = 'custom['.$rule.']';
695
+ }
696
+ } else if(strlen(trim($block['params']['validate'])) > 0) {
697
+ // handle single validation rule
698
+ $rules[] = 'custom['.$block['params']['validate'].']';
699
+ }
700
+ }
701
+
702
+ // generate string if there is at least one rule to validate against
703
+ if(empty($rules)) {
704
+ return '';
705
+ } else {
706
+ // make sure rules are not duplicated
707
+ $rules = array_unique($rules);
708
+ return 'validate['.join(',', $rules).']';
709
+ }
710
+ }
711
+
712
+ protected function render_web_body() {
713
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
714
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
715
+
716
+ $blocks = $this->get_data('body');
717
+
718
+ if(empty($blocks)) return '';
719
+
720
+ $body = '';
721
+ foreach($blocks as $key => $block) {
722
+ // get extra data depending on field type
723
+ $block = $this->_get_extra_data($block);
724
+
725
+ // special case for email widget
726
+ if($block['field'] === 'email') {
727
+ $user_email = WYSIJA::wp_get_userdata('user_email');
728
+
729
+ if($user_email && is_string($user_email) && is_user_logged_in() && !current_user_can('switch_themes') && !is_admin()) {
730
+ $block['value'] = $user_email;
731
+ }
732
+ }
733
+
734
+ // set field name 'prefix' depending whether it's a custom field or not
735
+ if($this->is_custom_field($block)) {
736
+ $field_prefix = 'wysija[field]';
737
+ } else {
738
+ $field_prefix = 'wysija[user]';
739
+ }
740
+
741
+ // generate block template
742
+ $data = array_merge($block, array(
743
+ 'field_prefix' => $field_prefix,
744
+ 'preview' => ($this->get_mode() === 'preview'),
745
+ 'i18n' => $this->get_translations(),
746
+ 'validation' => $this->get_validation_class($block)
747
+ ));
748
+ $body .= $helper_render_engine->render($data, 'templates/form/web/widgets/template.html');
749
+ }
750
+
751
+ return $body;
752
+ }
753
+
754
+ public function is_custom_field($field = array()) {
755
+ return (bool)(isset($field['field_id']) || (isset($field['field']) && strpos($field['field'], 'cf_') === 0));
756
+ }
757
+
758
+ public function get_exports($form_id) {
759
+ return array(
760
+ 'iframe' => base64_encode($this->export($form_id, 'iframe')),
761
+ 'php' => base64_encode($this->export($form_id, 'php')),
762
+ 'html' => base64_encode($this->export($form_id, 'html'))
763
+ );
764
+ }
765
+
766
+ public function render_editor_export($form_id) {
767
+ $helper_render_engine = WYSIJA::get('render_engine', 'helper');
768
+ $helper_render_engine->setTemplatePath(WYSIJA_EDITOR_TOOLS);
769
+
770
+ $data = array(
771
+ 'types' => array(
772
+ 'iframe' => $this->export($form_id, 'iframe'),
773
+ 'php' => $this->export($form_id, 'php'),
774
+ 'html' => $this->export($form_id, 'html'),
775
+ 'shortcode' => $this->export($form_id, 'shortcode')
776
+ )
777
+ );
778
+
779
+ return $helper_render_engine->render($data, 'templates/form/web/export.html');
780
+ }
781
+
782
+ public function export($form_id, $type) {
783
+ switch($type) {
784
+ case 'iframe':
785
+ $url_params = array(
786
+ 'wysija-page' => 1,
787
+ 'controller' => 'subscribers',
788
+ 'action' => 'wysija_outter',
789
+ 'wysija_form' => $form_id
790
+ );
791
+
792
+ $url_params['external_site'] = 1;
793
+
794
+ $model_config = WYSIJA::get('config','model');
795
+ $source_url = WYSIJA::get_permalink($model_config->getValue('confirm_email_link'), $url_params, true);
796
+
797
+ return '<iframe width="100%" scrolling="no" frameborder="0" src="'.$source_url.'" class="iframe-wysija" vspace="0" tabindex="0" style="position: static; top: 0pt; margin: 0px; border-style: none; height: 330px; left: 0pt; visibility: visible;" marginwidth="0" marginheight="0" hspace="0" allowtransparency="true" title="'.__('Subscription MailPoet',WYSIJA).'"></iframe>';
798
+ break;
799
+ case 'php':
800
+ $output = array(
801
+ '$widgetNL = new WYSIJA_NL_Widget(true);',
802
+ 'echo $widgetNL->widget(array(\'form\' => '.(int)$form_id.', \'form_type\' => \'php\'));'
803
+ );
804
+ return join("\n", $output);
805
+ break;
806
+ case 'html':
807
+ //need some language for the validation
808
+ $helper_toolbox = WYSIJA::get('toolbox','helper');
809
+ $wp_language_code = $helper_toolbox->get_language_code();
810
+
811
+ $wysija_version = WYSIJA::get_version();
812
+ $scripts_to_include = '<!--START Scripts : this is the script part you can add to the header of your theme-->'."\n";
813
+ $scripts_to_include .= '<script type="text/javascript" src="'.includes_url().'js/jquery/jquery.js'.'?ver='.$wysija_version.'"></script>'."\n";
814
+ if(file_exists(WYSIJA_DIR.'js'.DS.'validate'.DS.'languages'.DS.'jquery.validationEngine-'.$wp_language_code.'.js')){
815
+ $scripts_to_include .= '<script type="text/javascript" src="'.WYSIJA_URL.'js/validate/languages/jquery.validationEngine-'.$wp_language_code.'.js'.'?ver='.$wysija_version.'"></script>'."\n";
816
+ }else{
817
+ $scripts_to_include .= '<script type="text/javascript" src="'.WYSIJA_URL.'js/validate/languages/jquery.validationEngine-en.js'.'?ver='.$wysija_version.'"></script>'."\n";
818
+ }
819
+ $scripts_to_include .= '<script type="text/javascript" src="'.WYSIJA_URL.'js/validate/jquery.validationEngine.js'.'?ver='.$wysija_version.'"></script>'."\n";
820
+ $scripts_to_include .= '<script type="text/javascript" src="'.WYSIJA_URL.'js/front-subscribers.js'.'?ver='.$wysija_version.'"></script>'."\n";
821
+ $scripts_to_include .= '<script type="text/javascript">
822
+ /* <![CDATA[ */
823
+ var wysijaAJAX = {"action":"wysija_ajax","controller":"subscribers","ajaxurl":"'.admin_url('admin-ajax.php','absolute').'","loadingTrans":"'.__('Loading...',WYSIJA).'"};
824
+ /* ]]> */
825
+ </script>';
826
+ $scripts_to_include .= '<script type="text/javascript" src="'.WYSIJA_URL.'js/front-subscribers.js?ver='.$wysija_version.'"></script>'."\n";
827
+ $scripts_to_include .= '<!--END Scripts-->'."\n"."\n";
828
+
829
+ //enqueue the scripts
830
+ $html_result = $scripts_to_include;
831
+
832
+ // add the html for the form
833
+ $widget_NL = new WYSIJA_NL_Widget(true);
834
+ $html_result .= $widget_NL->widget(array('form' => (int)$form_id, 'form_type' => 'html'));
835
+
836
+ return $html_result;
837
+ break;
838
+ case 'shortcode':
839
+ return '[wysija_form id="'.(int)$form_id.'"]';
840
+ break;
841
+ }
842
+ }
843
+ }
trunk/helpers/forms.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('WYSIJA') or die('Restricted access');
3
+ /* some Functions are based on Codeigniter's Form Helper Class (http://www.codeigniter.com) */
4
+ class WYSIJA_help_forms{
5
+ var $eachValues = array();
6
+ var $eachValuesSec = array();
7
+
8
+ function __construct(){
9
+ // I believe this is for translation purpose, making sure the correct language is loaded
10
+ add_action( 'init', array( $this, 'apply_filters' ), 20 );
11
+
12
+ $this->eachValues = array(
13
+ 'one_min' => __( 'every minute', WYSIJA ),
14
+ 'two_min' => __( 'every 2 minutes', WYSIJA ),
15
+ 'five_min' => __( 'every 5 minutes', WYSIJA ),
16
+ 'ten_min' => __( 'every 10 minutes', WYSIJA ),
17
+ 'fifteen_min' => __( 'every 15 minutes', WYSIJA ),
18
+ 'thirty_min' => __( 'every 30 minutes', WYSIJA ),
19
+ 'hourly' => __( 'every hour', WYSIJA ),
20
+ 'two_hours' => __( 'every 2 hours', WYSIJA )
21
+ );
22
+
23
+ $this->eachValuesSec = array(
24
+ 'one_min' => '60',
25
+ 'two_min' => '120',
26
+ 'five_min' => '300',
27
+ 'ten_min' => '600',
28
+ 'fifteen_min' => '900',
29
+ 'thirty_min' => '1800',
30
+ 'hourly' => '3600',
31
+ 'two_hours' => '7200',
32
+ 'twicedaily' => '43200',
33
+ 'daily' => '86400',
34
+ );
35
+ }
36
+
37
+ function apply_filters() {
38
+ $this->eachValues = apply_filters( 'mpoet_sending_frequency', $this->eachValues );
39
+ $this->eachValuesSec = apply_filters( 'mpoet_sending_frequency_sec', $this->eachValuesSec );
40
+ }
41
+
42
+ function input($data = '', $value = '', $extra = '') {
43
+ $defaults = array('type' => 'text', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value);
44
+ $content="<input ".$this->setAttrib($data, $defaults).$extra." />";
45
+ return $content;
46
+ }
47
+ function password($data = '', $value = '', $extra = '') {
48
+ $defaults = array('type' => 'password', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value);
49
+ $content="<input ".$this->setAttrib($data, $defaults).$extra." />";
50
+ return $content;
51
+ }
52
+
53
+ function hidden($data = '', $value = '', $extra = '') {
54
+ $defaults = array('type' => 'hidden', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value);
55
+ $content="<input ".$this->setAttrib($data, $defaults).$extra." />";
56
+ return $content;
57
+ }
58
+
59
+ function textarea($data = '', $value = '', $extra = '') {
60
+ $defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'cols' => '90', 'rows' => '12');
61
+
62
+ if ( ! is_array($data) OR ! isset($data['value'])) {
63
+ $val = $value;
64
+ } else {
65
+ $val = $data['value'];
66
+ unset($data['value']);
67
+ }
68
+
69
+ return '<textarea '.$this->setAttrib($data, $defaults).$extra.'>'.esc_textarea($val).'</textarea>';
70
+ }
71
+
72
+
73
+ function tinymce($idName = '', $content = '') {
74
+ $this->the_editor(stripslashes($content), $idName,'title',false);
75
+ }
76
+
77
+ function checkbox($data = '', $value = '', $checked = FALSE, $extra = '') {
78
+ $defaults = array('type' => 'checkbox', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value);
79
+
80
+ if (is_array($data) AND array_key_exists('checked', $data)) {
81
+ $checked = $data['checked'];
82
+
83
+ if ($checked == FALSE) unset($data['checked']);
84
+ else $data['checked'] = 'checked';
85
+ }
86
+
87
+ if ($checked == TRUE) $defaults['checked'] = 'checked';
88
+ else unset($defaults['checked']);
89
+
90
+ return "<input ".$this->setAttrib($data, $defaults).$extra." />";
91
+ }
92
+
93
+ function checkboxes($data = '', $values = array(), $value = '', $extra = '') {
94
+ $html='';
95
+ foreach($values as $val => $valtitle){
96
+ $checked=false;
97
+ $data2=$data;
98
+ $data2['id'].="-".$val;
99
+ if($val==$value)$checked=true;
100
+ $html.='<label for="'.$data2['id'].'">'.$this->checkbox($data2, $val, $checked, $extra).$valtitle."</label>";
101
+ }
102
+
103
+ return $html;
104
+ }
105
+
106
+ function radios($data = '', $values = array(), $value = '', $extra = '') {
107
+ $html='';
108
+ foreach($values as $val => $valtitle){
109
+ $checked=false;
110
+ $data2=$data;
111
+ $data2['id'].="-".$val;
112
+ if($val==$value)$checked=true;
113
+ $html.='<label for="'.$data2['id'].'">'.$this->radio($data2, $val, $checked, $extra).$valtitle."</label>";
114
+ }
115
+
116
+ return $html;
117
+ }
118
+
119
+ function radio($data = '', $value = '', $checked = FALSE, $extra = '') {
120
+ if ( ! is_array($data)) {
121
+ $data = array('name' => $data);
122
+ }
123
+
124
+ $data['type'] = 'radio';
125
+ return $this->checkbox($data, $value, $checked, $extra);
126
+ }
127
+
128
+
129
+ function the_editor($content, $id = 'content', $prev_id = 'title', $media_buttons = true, $tab_index = 2){
130
+ $rows = get_option('default_post_edit_rows');
131
+ if (($rows < 3) || ($rows > 100))
132
+ $rows = 12;
133
+
134
+ if ( !current_user_can( 'upload_files' ) )
135
+ $media_buttons = false;
136
+
137
+ $richedit = user_can_richedit();
138
+ $class = '';
139
+
140
+ if ( $richedit || $media_buttons ) { ?>
141
+ <div id="editor-toolbar">
142
+ <?php
143
+ if ( $richedit ) {
144
+ $wp_default_editor=tap_get_option("visual_ed_disable");
145
+ ?>
146
+ <div class="zerosize"><input accesskey="e" type="button" onclick="switchEditors.go('<?php echo $id; ?>')" /></div>
147
+ <?php if ( $wp_default_editor ) {
148
+ add_filter('the_editor_content', 'wp_htmledit_pre'); ?>
149
+ <a id="edButtonHTML" class="edButtonHTML active hide-if-no-js" onclick="switchEditors.go('<?php echo $id; ?>', 'html');"><?php _e('HTML'); ?></a>
150
+ <a id="edButtonPreview" class="edButtonPreview hide-if-no-js" onclick="switchEditors.go('<?php echo $id; ?>', 'tinymce');"><?php _e('Visual'); ?></a>
151
+ <?php } else {
152
+ $class = " class='theEditor'";
153
+ add_filter('the_editor_content', 'wp_richedit_pre'); ?>
154
+ <a id="edButtonHTML" class="edButtonHTML hide-if-no-js" onclick="switchEditors.go('<?php echo $id; ?>', 'html');"><?php _e('HTML'); ?></a>
155
+ <a id="edButtonPreview" class="edButtonPreview active hide-if-no-js" onclick="switchEditors.go('<?php echo $id; ?>', 'tinymce');"><?php _e('Visual'); ?></a>
156
+ <?php }
157
+ }
158
+ ?><div id="media-buttons" class="hide-if-no-js"><?php
159
+ if ( $media_buttons ) { ?>
160
+
161
+ <?php do_action( 'media_buttons' ); ?>
162
+
163
+ <?php
164
+ } ?>
165
+ </div>
166
+ </div>
167
+ <?php
168
+ }
169
+ ?>
170
+ <div id="quicktags"><?php
171
+ wp_print_scripts( 'quicktags' ); ?>
172
+ </div>
173
+
174
+ <?php
175
+ $the_editor = apply_filters('the_editor', "<div id='editorcontainer'><textarea rows='$rows'$class cols='40' name='$id' tabindex='$tab_index' id='$id'>%s</textarea></div>\n");
176
+ $the_editor_content = apply_filters('the_editor_content', $content);
177
+
178
+ printf($the_editor, $the_editor_content);
179
+
180
+ }
181
+
182
+ function titleh($idName = '', $selected = '') {
183
+ $options=array("default"=>"default","h2"=>"h2","h3"=>"h3","h4"=>"h4");
184
+ echo $this->dropdown($idName,$options,$selected);
185
+ }
186
+
187
+ function enabled($idName = '', $selected = '') {
188
+ $options=array(0=>"disabled",1=>"enabled");
189
+ echo $this->dropdown($idName,$options,$selected);
190
+ }
191
+
192
+ function dropdown($data = '', $options = array(), $selected = array(), $extra = '') {
193
+ if ( ! is_array($selected)) {
194
+ $selected = array($selected);
195
+ }
196
+
197
+ if ( empty($options) ) {
198
+ return false;
199
+ }
200
+
201
+ $defaults = array('name' => (( ! is_array($data)) ? $data : ''));
202
+
203
+ /* buggy lines
204
+ * if (count($selected) === 0) {
205
+ if (isset($_POST[$name])) $selected = array($_POST[$name]);
206
+ }*/
207
+
208
+ if ($extra != '') $extra = ' '.$extra;
209
+
210
+ $multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
211
+ $form = '<select '.$this->setAttrib($data, $defaults).$extra.$multiple.">\n";
212
+
213
+ foreach ($options as $key => $val) {
214
+ $key = (string) $key;
215
+ if (is_array($val)) {
216
+ $form .= '<optgroup label="'.$key.'">'."\n";
217
+ foreach ($val as $optgroup_key => $optgroup_val) {
218
+ $sel = (in_array($optgroup_key, $selected)) ? ' selected="selected"' : '';
219
+ $form .= '<option value="'.esc_attr($optgroup_key).'"'.$sel.'>'.(string) $optgroup_val."</option>\n";
220
+ }
221
+ $form .= '</optgroup>'."\n";
222
+ } else {
223
+ $sel = (in_array($key, $selected)) ? ' selected="selected"' : '';
224
+ $form .= '<option value="'.esc_attr($key).'"'.$sel.'>'.(string) $val."</option>\n";
225
+ }
226
+ }
227
+ $form .= '</select>';
228
+ return $form;
229
+ }
230
+
231
+
232
+ function setAttrib($attributes, $default) {
233
+ if (is_array($attributes)) {
234
+ foreach ($default as $key => $val) {
235
+ if (isset($attributes[$key])) {
236
+ $default[$key] = $attributes[$key];
237
+ unset($attributes[$key]);
238
+ }
239
+ }
240
+ if(isset($attributes["default"])){
241
+
242
+ $attributes["onBlur"]="if(this.value=='') {