controls.php 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684
  1. <?php
  2. defined('ABSPATH') || exit;
  3. include_once __DIR__ . '/fields.php';
  4. class NewsletterControls {
  5. var $data;
  6. var $action = false;
  7. var $button_data = '';
  8. var $errors = '';
  9. var $messages = '';
  10. var $warnings = array();
  11. var $countries = array(
  12. 'AF' => 'Afghanistan',
  13. 'AX' => 'Aland Islands',
  14. 'AL' => 'Albania',
  15. 'DZ' => 'Algeria',
  16. 'AS' => 'American Samoa',
  17. 'AD' => 'Andorra',
  18. 'AO' => 'Angola',
  19. 'AI' => 'Anguilla',
  20. 'AQ' => 'Antarctica',
  21. 'AG' => 'Antigua And Barbuda',
  22. 'AR' => 'Argentina',
  23. 'AM' => 'Armenia',
  24. 'AW' => 'Aruba',
  25. 'AU' => 'Australia',
  26. 'AT' => 'Austria',
  27. 'AZ' => 'Azerbaijan',
  28. 'BS' => 'Bahamas',
  29. 'BH' => 'Bahrain',
  30. 'BD' => 'Bangladesh',
  31. 'BB' => 'Barbados',
  32. 'BY' => 'Belarus',
  33. 'BE' => 'Belgium',
  34. 'BZ' => 'Belize',
  35. 'BJ' => 'Benin',
  36. 'BM' => 'Bermuda',
  37. 'BT' => 'Bhutan',
  38. 'BO' => 'Bolivia',
  39. 'BA' => 'Bosnia And Herzegovina',
  40. 'BW' => 'Botswana',
  41. 'BV' => 'Bouvet Island',
  42. 'BR' => 'Brazil',
  43. 'IO' => 'British Indian Ocean Territory',
  44. 'BN' => 'Brunei Darussalam',
  45. 'BG' => 'Bulgaria',
  46. 'BF' => 'Burkina Faso',
  47. 'BI' => 'Burundi',
  48. 'KH' => 'Cambodia',
  49. 'CM' => 'Cameroon',
  50. 'CA' => 'Canada',
  51. 'CV' => 'Cape Verde',
  52. 'KY' => 'Cayman Islands',
  53. 'CF' => 'Central African Republic',
  54. 'TD' => 'Chad',
  55. 'CL' => 'Chile',
  56. 'CN' => 'China',
  57. 'CX' => 'Christmas Island',
  58. 'CC' => 'Cocos (Keeling) Islands',
  59. 'CO' => 'Colombia',
  60. 'KM' => 'Comoros',
  61. 'CG' => 'Congo',
  62. 'CD' => 'Congo, Democratic Republic',
  63. 'CK' => 'Cook Islands',
  64. 'CR' => 'Costa Rica',
  65. 'CI' => 'Cote D\'Ivoire',
  66. 'HR' => 'Croatia',
  67. 'CU' => 'Cuba',
  68. 'CY' => 'Cyprus',
  69. 'CZ' => 'Czech Republic',
  70. 'DK' => 'Denmark',
  71. 'DJ' => 'Djibouti',
  72. 'DM' => 'Dominica',
  73. 'DO' => 'Dominican Republic',
  74. 'EC' => 'Ecuador',
  75. 'EG' => 'Egypt',
  76. 'SV' => 'El Salvador',
  77. 'GQ' => 'Equatorial Guinea',
  78. 'ER' => 'Eritrea',
  79. 'EE' => 'Estonia',
  80. 'ET' => 'Ethiopia',
  81. 'FK' => 'Falkland Islands (Malvinas)',
  82. 'FO' => 'Faroe Islands',
  83. 'FJ' => 'Fiji',
  84. 'FI' => 'Finland',
  85. 'FR' => 'France',
  86. 'GF' => 'French Guiana',
  87. 'PF' => 'French Polynesia',
  88. 'TF' => 'French Southern Territories',
  89. 'GA' => 'Gabon',
  90. 'GM' => 'Gambia',
  91. 'GE' => 'Georgia',
  92. 'DE' => 'Germany',
  93. 'GH' => 'Ghana',
  94. 'GI' => 'Gibraltar',
  95. 'GR' => 'Greece',
  96. 'GL' => 'Greenland',
  97. 'GD' => 'Grenada',
  98. 'GP' => 'Guadeloupe',
  99. 'GU' => 'Guam',
  100. 'GT' => 'Guatemala',
  101. 'GG' => 'Guernsey',
  102. 'GN' => 'Guinea',
  103. 'GW' => 'Guinea-Bissau',
  104. 'GY' => 'Guyana',
  105. 'HT' => 'Haiti',
  106. 'HM' => 'Heard Island & Mcdonald Islands',
  107. 'VA' => 'Holy See (Vatican City State)',
  108. 'HN' => 'Honduras',
  109. 'HK' => 'Hong Kong',
  110. 'HU' => 'Hungary',
  111. 'IS' => 'Iceland',
  112. 'IN' => 'India',
  113. 'ID' => 'Indonesia',
  114. 'IR' => 'Iran, Islamic Republic Of',
  115. 'IQ' => 'Iraq',
  116. 'IE' => 'Ireland',
  117. 'IM' => 'Isle Of Man',
  118. 'IL' => 'Israel',
  119. 'IT' => 'Italy',
  120. 'JM' => 'Jamaica',
  121. 'JP' => 'Japan',
  122. 'JE' => 'Jersey',
  123. 'JO' => 'Jordan',
  124. 'KZ' => 'Kazakhstan',
  125. 'KE' => 'Kenya',
  126. 'KI' => 'Kiribati',
  127. 'KR' => 'Korea',
  128. 'KW' => 'Kuwait',
  129. 'KG' => 'Kyrgyzstan',
  130. 'LA' => 'Lao People\'s Democratic Republic',
  131. 'LV' => 'Latvia',
  132. 'LB' => 'Lebanon',
  133. 'LS' => 'Lesotho',
  134. 'LR' => 'Liberia',
  135. 'LY' => 'Libyan Arab Jamahiriya',
  136. 'LI' => 'Liechtenstein',
  137. 'LT' => 'Lithuania',
  138. 'LU' => 'Luxembourg',
  139. 'MO' => 'Macao',
  140. 'MK' => 'Macedonia',
  141. 'MG' => 'Madagascar',
  142. 'MW' => 'Malawi',
  143. 'MY' => 'Malaysia',
  144. 'MV' => 'Maldives',
  145. 'ML' => 'Mali',
  146. 'MT' => 'Malta',
  147. 'MH' => 'Marshall Islands',
  148. 'MQ' => 'Martinique',
  149. 'MR' => 'Mauritania',
  150. 'MU' => 'Mauritius',
  151. 'YT' => 'Mayotte',
  152. 'MX' => 'Mexico',
  153. 'FM' => 'Micronesia, Federated States Of',
  154. 'MD' => 'Moldova',
  155. 'MC' => 'Monaco',
  156. 'MN' => 'Mongolia',
  157. 'ME' => 'Montenegro',
  158. 'MS' => 'Montserrat',
  159. 'MA' => 'Morocco',
  160. 'MZ' => 'Mozambique',
  161. 'MM' => 'Myanmar',
  162. 'NA' => 'Namibia',
  163. 'NR' => 'Nauru',
  164. 'NP' => 'Nepal',
  165. 'NL' => 'Netherlands',
  166. 'AN' => 'Netherlands Antilles',
  167. 'NC' => 'New Caledonia',
  168. 'NZ' => 'New Zealand',
  169. 'NI' => 'Nicaragua',
  170. 'NE' => 'Niger',
  171. 'NG' => 'Nigeria',
  172. 'NU' => 'Niue',
  173. 'NF' => 'Norfolk Island',
  174. 'MP' => 'Northern Mariana Islands',
  175. 'NO' => 'Norway',
  176. 'OM' => 'Oman',
  177. 'PK' => 'Pakistan',
  178. 'PW' => 'Palau',
  179. 'PS' => 'Palestinian Territory, Occupied',
  180. 'PA' => 'Panama',
  181. 'PG' => 'Papua New Guinea',
  182. 'PY' => 'Paraguay',
  183. 'PE' => 'Peru',
  184. 'PH' => 'Philippines',
  185. 'PN' => 'Pitcairn',
  186. 'PL' => 'Poland',
  187. 'PT' => 'Portugal',
  188. 'PR' => 'Puerto Rico',
  189. 'QA' => 'Qatar',
  190. 'RE' => 'Reunion',
  191. 'RO' => 'Romania',
  192. 'RU' => 'Russian Federation',
  193. 'RW' => 'Rwanda',
  194. 'BL' => 'Saint Barthelemy',
  195. 'SH' => 'Saint Helena',
  196. 'KN' => 'Saint Kitts And Nevis',
  197. 'LC' => 'Saint Lucia',
  198. 'MF' => 'Saint Martin',
  199. 'PM' => 'Saint Pierre And Miquelon',
  200. 'VC' => 'Saint Vincent And Grenadines',
  201. 'WS' => 'Samoa',
  202. 'SM' => 'San Marino',
  203. 'ST' => 'Sao Tome And Principe',
  204. 'SA' => 'Saudi Arabia',
  205. 'SN' => 'Senegal',
  206. 'RS' => 'Serbia',
  207. 'SC' => 'Seychelles',
  208. 'SL' => 'Sierra Leone',
  209. 'SG' => 'Singapore',
  210. 'SK' => 'Slovakia',
  211. 'SI' => 'Slovenia',
  212. 'SB' => 'Solomon Islands',
  213. 'SO' => 'Somalia',
  214. 'ZA' => 'South Africa',
  215. 'GS' => 'South Georgia And Sandwich Isl.',
  216. 'ES' => 'Spain',
  217. 'LK' => 'Sri Lanka',
  218. 'SD' => 'Sudan',
  219. 'SR' => 'Suriname',
  220. 'SJ' => 'Svalbard And Jan Mayen',
  221. 'SZ' => 'Swaziland',
  222. 'SE' => 'Sweden',
  223. 'CH' => 'Switzerland',
  224. 'SY' => 'Syrian Arab Republic',
  225. 'TW' => 'Taiwan',
  226. 'TJ' => 'Tajikistan',
  227. 'TZ' => 'Tanzania',
  228. 'TH' => 'Thailand',
  229. 'TL' => 'Timor-Leste',
  230. 'TG' => 'Togo',
  231. 'TK' => 'Tokelau',
  232. 'TO' => 'Tonga',
  233. 'TT' => 'Trinidad And Tobago',
  234. 'TN' => 'Tunisia',
  235. 'TR' => 'Turkey',
  236. 'TM' => 'Turkmenistan',
  237. 'TC' => 'Turks And Caicos Islands',
  238. 'TV' => 'Tuvalu',
  239. 'UG' => 'Uganda',
  240. 'UA' => 'Ukraine',
  241. 'AE' => 'United Arab Emirates',
  242. 'GB' => 'United Kingdom',
  243. 'US' => 'United States',
  244. 'UM' => 'United States Outlying Islands',
  245. 'UY' => 'Uruguay',
  246. 'UZ' => 'Uzbekistan',
  247. 'VU' => 'Vanuatu',
  248. 'VE' => 'Venezuela',
  249. 'VN' => 'Viet Nam',
  250. 'VG' => 'Virgin Islands, British',
  251. 'VI' => 'Virgin Islands, U.S.',
  252. 'WF' => 'Wallis And Futuna',
  253. 'EH' => 'Western Sahara',
  254. 'YE' => 'Yemen',
  255. 'ZM' => 'Zambia',
  256. 'ZW' => 'Zimbabwe',
  257. 'XX' => 'Undefined',
  258. 'CW' => 'Curaçao',
  259. 'SS' => 'South Sudan',
  260. 'EU' => 'Europe (generic)',
  261. 'A1' => 'Anonymous IP',
  262. 'A2' => 'Satellite IP'
  263. );
  264. function __construct($options = null) {
  265. if ($options == null) {
  266. if (isset($_POST['options'])) {
  267. $this->data = stripslashes_deep($_POST['options']);
  268. }
  269. } else {
  270. $this->data = $options;
  271. }
  272. if (isset($_REQUEST['act'])) {
  273. $this->action = $_REQUEST['act'];
  274. }
  275. if (isset($_REQUEST['btn'])) {
  276. $this->button_data = $_REQUEST['btn'];
  277. }
  278. // Fields analysis
  279. if (isset($_REQUEST['fields'])) {
  280. $fields = $_REQUEST['fields'];
  281. if (is_array($fields)) {
  282. foreach ($fields as $name => $type) {
  283. if ($type == 'datetime') {
  284. // Ex. The user insert 01/07/2012 14:30 and it set the time zone to +2. We cannot use the
  285. // mktime, since it uses the time zone of the machine. We create the time as if we are on
  286. // GMT 0 and then we subtract the GMT offset (the example date and time on GMT+2 happens
  287. // "before").
  288. $time = gmmktime($_REQUEST[$name . '_hour'], 0, 0, $_REQUEST[$name . '_month'], $_REQUEST[$name . '_day'], $_REQUEST[$name . '_year']);
  289. $time -= get_option('gmt_offset') * 3600;
  290. $this->data[$name] = $time;
  291. }
  292. }
  293. }
  294. }
  295. }
  296. function merge($options) {
  297. if (!is_array($options))
  298. return;
  299. if ($this->data == null)
  300. $this->data = array();
  301. $this->data = array_merge($this->data, $options);
  302. }
  303. function merge_defaults($defaults) {
  304. if ($this->data == null)
  305. $this->data = $defaults;
  306. else
  307. $this->data = array_merge($defaults, $this->data);
  308. }
  309. /**
  310. * Return true is there in an asked action is no action name is specified or
  311. * true is the requested action matches the passed action.
  312. * Dies if it is not a safe call.
  313. */
  314. function is_action($action = null) {
  315. if ($action == null)
  316. return $this->action != null;
  317. if ($this->action == null)
  318. return false;
  319. if ($this->action != $action)
  320. return false;
  321. if (check_admin_referer('save'))
  322. return true;
  323. die('Invalid call');
  324. }
  325. function get_value($name) {
  326. if (!isset($this->data[$name]))
  327. return null;
  328. return $this->data[$name];
  329. }
  330. function get_value_array($name) {
  331. if (!isset($this->data[$name]) || !is_array($this->data[$name]))
  332. return array();
  333. return $this->data[$name];
  334. }
  335. /**
  336. * Show the errors and messages.
  337. */
  338. function show() {
  339. static $shown = false;
  340. if ($shown) {
  341. return;
  342. }
  343. $shown = true;
  344. if (!empty($this->errors)) {
  345. echo '<div class="tnp-error">';
  346. echo $this->errors;
  347. echo '</div>';
  348. }
  349. if (!empty($this->warnings)) {
  350. foreach ((array) $this->warnings as $warning) {
  351. echo '<div class="tnp-warning">';
  352. echo $warning;
  353. echo '</div>';
  354. }
  355. }
  356. if (!empty($this->messages)) {
  357. echo '<div class="tnp-message">';
  358. echo $this->messages;
  359. echo '</div>';
  360. }
  361. }
  362. function add_message_saved() {
  363. if (!empty($this->messages)) {
  364. $this->messages .= '<br><br>';
  365. }
  366. $this->messages .= __('Saved.', 'newsletter');
  367. }
  368. function add_message_deleted() {
  369. if (!empty($this->messages)) {
  370. $this->messages .= '<br><br>';
  371. }
  372. $this->messages .= __('Deleted.', 'newsletter');
  373. }
  374. function add_message_reset() {
  375. if (!empty($this->messages)) {
  376. $this->messages .= '<br><br>';
  377. }
  378. $this->messages .= __('Options reset.', 'newsletter');
  379. }
  380. function add_message_done() {
  381. if (!empty($this->messages)) {
  382. $this->messages .= '<br><br>';
  383. }
  384. $this->messages .= __('Done.', 'newsletter');
  385. }
  386. function add_language_warning() {
  387. $newsletter = Newsletter::instance();
  388. $current_language = $newsletter->get_current_language();
  389. if (!$current_language) {
  390. return;
  391. }
  392. $this->warnings[] = 'You are configuring the language <strong>' . $newsletter->get_language_label($current_language) . '</strong>. Switch to "all languages" to see every options.';
  393. }
  394. function hint($text, $url = '') {
  395. echo '<div class="hints">';
  396. // Do not escape that, it can be formatted
  397. echo $text;
  398. if (!empty($url)) {
  399. echo ' <a href="' . esc_attr($url) . '" target="_blank">Read more</a>.';
  400. }
  401. echo '</div>';
  402. }
  403. function yesno($name) {
  404. $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
  405. echo '<select style="width: 60px" name="options[' . esc_attr($name) . ']">';
  406. echo '<option value="0"';
  407. if ($value == 0) {
  408. echo ' selected';
  409. }
  410. echo '>', __('No', 'newsletter'), '</option>';
  411. echo '<option value="1"';
  412. if ($value == 1) {
  413. echo ' selected';
  414. }
  415. echo '>', __('Yes', 'newsletter'), '</option>';
  416. echo '</select>&nbsp;&nbsp;&nbsp;';
  417. }
  418. function enabled($name = 'enabled') {
  419. $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
  420. echo '<select style="width: 100px" name="options[' . esc_attr($name) . ']">';
  421. echo '<option value="0"';
  422. if ($value == 0) {
  423. echo ' selected';
  424. }
  425. echo '>', __('Disabled', 'newsletter'), '</option>';
  426. echo '<option value="1"';
  427. if ($value == 1) {
  428. echo ' selected';
  429. }
  430. echo '>', __('Enabled', 'newsletter'), '</option>';
  431. echo '</select>';
  432. }
  433. function disabled($name) {
  434. $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
  435. echo '<select style="width: 100px" name="options[' . esc_attr($name) . ']">';
  436. echo '<option value="0"';
  437. if ($value == 0) {
  438. echo ' selected';
  439. }
  440. echo '>Enabled</option>';
  441. echo '<option value="1"';
  442. if ($value == 1) {
  443. echo ' selected';
  444. }
  445. echo '>Disabled</option>';
  446. echo '</select>';
  447. }
  448. /**
  449. * Creates a set of checkbox all named as $name with values and labels extracted from
  450. * $values_labels. A checkbox will be checked if internal data under key $name is an array
  451. * and contains the value of the current (echoing) checkbox.
  452. *
  453. * On submit it produces an array under the name $name IF at least one checkbox has
  454. * been checked. Otherwise the key won't be present.
  455. *
  456. * @param array $values
  457. * @param string $name
  458. * @param array $values_labels
  459. */
  460. function checkboxes_group($name, $values_labels) {
  461. $value_array = $this->get_value_array($name);
  462. echo "<div class='newsletter-checkboxes-group'>";
  463. foreach ($values_labels as $value => $label) {
  464. echo "<div class='newsletter-checkboxes-item'>";
  465. echo '<label><input type="checkbox" id="' . esc_attr($name) . '" name="options[' . esc_attr($name) . '][]" value="' . esc_attr($value) . '"';
  466. if (array_search($value, $value_array) !== false) {
  467. echo ' checked';
  468. }
  469. echo '>';
  470. if ($label != '') {
  471. echo esc_html($label);
  472. }
  473. echo "</label></div>";
  474. }
  475. echo "</div><div style='clear: both'></div>";
  476. }
  477. /** Creates a checkbox group with all public post types.
  478. */
  479. function post_types($name = 'post_types') {
  480. $list = array();
  481. $post_types = get_post_types(array('public' => true), 'objects', 'and');
  482. foreach ($post_types as $post_type) {
  483. $list[$post_type->name] = $post_type->labels->name;
  484. }
  485. $this->checkboxes_group($name, $list);
  486. }
  487. function posts_select($name, $max = 20, $args = array()) {
  488. $args = array_merge(array(
  489. 'posts_per_page' => 5,
  490. 'offset' => 0,
  491. 'category' => '',
  492. 'category_name' => '',
  493. 'orderby' => 'date',
  494. 'order' => 'DESC',
  495. 'include' => '',
  496. 'exclude' => '',
  497. 'meta_key' => '',
  498. 'meta_value' => '',
  499. 'post_type' => 'post',
  500. 'post_mime_type' => '',
  501. 'post_parent' => '',
  502. 'author' => '',
  503. 'author_name' => '',
  504. 'post_status' => 'publish',
  505. 'suppress_filters' => true
  506. ), $args);
  507. $args['posts_per_page'] = $max;
  508. $posts = get_posts($args);
  509. $options = array();
  510. foreach ($posts as $post) {
  511. $options['' . $post->ID] = $post->post_title;
  512. }
  513. $this->select($name, $options);
  514. }
  515. function select_number($name, $min, $max) {
  516. $options = array();
  517. for ($i = $min; $i <= $max; $i++) {
  518. $options['' . $i] = $i;
  519. }
  520. $this->select($name, $options);
  521. }
  522. function page($name = 'page', $first = null, $language = '', $show_id = false) {
  523. $args = array(
  524. 'post_type' => 'page',
  525. 'posts_per_page' => 1000,
  526. 'offset' => 0,
  527. 'orderby' => 'post_title',
  528. 'post_status' => 'any',
  529. 'suppress_filters' => true
  530. );
  531. $pages = get_posts($args);
  532. //$pages = get_pages();
  533. $options = array();
  534. foreach ($pages as $page) {
  535. /* @var $page WP_Post */
  536. $label = $page->post_title;
  537. if ($page->post_status != 'publish') {
  538. $label .= ' (' . $page->post_status . ')';
  539. }
  540. if ($show_id) {
  541. $label .= ' [' . $page->ID . ']';
  542. }
  543. $options[$page->ID] = $label;
  544. }
  545. $this->select($name, $options, $first);
  546. }
  547. /** Used to create a select which is part of a group of controls identified by $name that will
  548. * produce an array of values as $_REQUEST['name'].
  549. * @param string $name
  550. * @param array $options Associative array
  551. */
  552. function select_group($name, $options) {
  553. $value_array = $this->get_value_array($name);
  554. echo '<select name="options[' . esc_attr($name) . '][]">';
  555. foreach ($options as $key => $label) {
  556. echo '<option value="' . esc_attr($key) . '"';
  557. if (array_search($key, $value_array) !== false) {
  558. echo ' selected';
  559. }
  560. echo '>' . esc_html($label) . '</option>';
  561. }
  562. echo '</select>';
  563. }
  564. function select($name, $options, $first = null) {
  565. $value = $this->get_value($name);
  566. echo '<select id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']">';
  567. if (!empty($first)) {
  568. echo '<option value="">' . esc_html($first) . '</option>';
  569. }
  570. foreach ($options as $key => $label) {
  571. echo '<option value="' . esc_attr($key) . '"';
  572. if ($value == $key)
  573. echo ' selected';
  574. echo '>' . esc_html($label) . '</option>';
  575. }
  576. echo '</select>';
  577. }
  578. function select_images($name, $options, $first = null) {
  579. $value = $this->get_value($name);
  580. echo '<select id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']" style="min-width: 200px">';
  581. if (!empty($first)) {
  582. echo '<option value="">' . esc_html($first) . '</option>';
  583. } else {
  584. // if (empty($value)) {
  585. // $keys = array_keys($options);
  586. // $value = $keys[0];
  587. // }
  588. }
  589. foreach ($options as $key => $data) {
  590. echo '<option value="' . esc_attr($key) . '" image="' . esc_attr($data['image']) . '"';
  591. if ($value == $key)
  592. echo ' selected';
  593. echo '>' . esc_html($data['label']) . '</option>';
  594. }
  595. echo '</select>';
  596. echo '<script>jQuery("#options-' . esc_attr($name) . '").select2({templateResult: tnp_select_images, templateSelection: tnp_select_images_selection});</script>';
  597. }
  598. function select2($name, $options, $first = null, $multiple = false, $style = null, $placeholder = '') {
  599. if ($multiple) {
  600. $option_name = "options[" . esc_attr($name) . "][]";
  601. } else {
  602. $option_name = "options[" . esc_attr($name) . "]";
  603. }
  604. if (is_null($style)) {
  605. $style = 'width: 100%';
  606. }
  607. $value = $this->get_value($name);
  608. echo '<select id="options-', esc_attr($name), '" name="', $option_name, '" style="', $style, '"',
  609. ($multiple ? ' multiple' : ''), '>';
  610. if (!empty($first)) {
  611. echo '<option value="">' . esc_html($first) . '</option>';
  612. }
  613. foreach ($options as $key => $data) {
  614. echo '<option value="' . esc_attr($key) . '"';
  615. if (is_array($value) && in_array($key, $value) || $value == $key)
  616. echo ' selected';
  617. echo '>' . esc_html($data) . '</option>';
  618. }
  619. echo '</select>';
  620. echo '<script>jQuery("#options-' . esc_attr($name) . '").select2({placeholder: "', esc_js($placeholder), '"});</script>';
  621. }
  622. function select_grouped($name, $groups) {
  623. $value = $this->get_value($name);
  624. echo '<select name="options[' . $name . ']">';
  625. foreach ($groups as $group) {
  626. echo '<optgroup label="' . esc_attr($group['']) . '">';
  627. if (!empty($group)) {
  628. foreach ($group as $key => $label) {
  629. if ($key == '') {
  630. continue;
  631. }
  632. echo '<option value="' . esc_attr($key) . '"';
  633. if ($value == $key) {
  634. echo ' selected';
  635. }
  636. echo '>' . esc_html($label) . '</option>';
  637. }
  638. }
  639. echo '</optgroup>';
  640. }
  641. echo '</select>';
  642. }
  643. /**
  644. * Generated a select control with all available templates. From version 3 there are
  645. * only on kind of templates, they are no more separated by type.
  646. */
  647. function themes($name, $themes, $submit_on_click = true) {
  648. foreach ($themes as $key => $data) {
  649. echo '<label style="display: block; float: left; text-align: center; margin-right: 10px;">';
  650. echo esc_html($key) . '<br>';
  651. echo '<img src="' . esc_attr($data['screenshot']) . '" width="100" height="100" style="border: 1px solid #666; padding: 5px"><br>';
  652. echo '<input style="position: relative; top: -40px" type="radio" onchange="this.form.act.value=\'theme\';this.form.submit()" name="options[' . esc_attr($name) . ']" value="' . esc_attr($key) . '"';
  653. if ($this->data[$name] == $key) {
  654. echo ' checked';
  655. }
  656. echo '>';
  657. echo '</label>';
  658. }
  659. echo '<div style="clear: both"></div>';
  660. }
  661. function value($name) {
  662. echo htmlspecialchars($this->data[$name]);
  663. }
  664. function value_date($name, $show_remaining = true) {
  665. $time = $this->get_value($name);
  666. echo gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600);
  667. $delta = $time - time();
  668. if ($show_remaining && $delta > 0) {
  669. echo 'Remaining: ';
  670. $delta = $time - time();
  671. $days = floor($delta / (24 * 3600));
  672. $delta = $delta - $days * 24 * 3600;
  673. $hours = floor($delta / 3600);
  674. $delta = $delta - $hours * 3600;
  675. $minutes = floor($delta / 60);
  676. if ($days > 0)
  677. echo $days . ' days ';
  678. echo $hours . ' hours ';
  679. echo $minutes . ' minutes ';
  680. }
  681. }
  682. function text($name, $size = 20, $placeholder = '') {
  683. $value = $this->get_value($name);
  684. echo '<input id="options-', esc_attr($name), '" placeholder="' . esc_attr($placeholder) . '" name="options[' . $name . ']" type="text" ';
  685. if (!empty($size)) {
  686. echo 'size="' . $size . '" ';
  687. }
  688. echo 'value="', esc_attr($value), '">';
  689. }
  690. function text_email($name, $size = 40) {
  691. $value = $this->get_value($name);
  692. echo '<input name="options[' . esc_attr($name) . ']" type="email" placeholder="';
  693. echo esc_attr__('Valid email address', 'newsletter');
  694. echo '" size="' . esc_attr($size) . '" value="';
  695. echo esc_attr($value);
  696. echo '">';
  697. }
  698. function text_url($name, $size = 40) {
  699. $value = $this->get_value($name);
  700. echo '<input name="options[' . esc_attr($name) . ']" type="url" placeholder="http://..." size="' . esc_attr($size) . '" value="';
  701. echo esc_attr($value);
  702. echo '"/>';
  703. }
  704. function hidden($name) {
  705. $value = $this->get_value($name);
  706. echo '<input name="options[', esc_attr($name), ']" id="options-', esc_attr($name), '" type="hidden" value="', esc_attr($value), '">';
  707. }
  708. function button($action, $label, $function = null) {
  709. if ($function != null) {
  710. echo '<input class="button-secondary" type="button" value="' . esc_attr($label) . '" onclick="this.form.act.value=\'' . esc_attr($action) . '\';' . esc_html($function) . '"/>';
  711. } else {
  712. echo '<input class="button-secondary" type="submit" value="' . esc_attr($label) . '" onclick="this.form.act.value=\'' . esc_attr($action) . '\';return true;"/>';
  713. }
  714. }
  715. /**
  716. * With translated "Save" label.
  717. */
  718. function button_save($function = null) {
  719. $this->button_primary('save', '<i class="fa fa-save"></i> ' . __('Save', 'newsletter'), $function);
  720. }
  721. function button_reset($data = '') {
  722. echo '<button class="button-secondary" onclick="this.form.btn.value=\'' . esc_attr($data) . '\';this.form.act.value=\'reset\';if (!confirm(\'';
  723. echo esc_attr(esc_js(__('Proceed?', 'newsletter')));
  724. echo '\')) return false;">';
  725. echo '<i class="fa fa-reply"></i> ';
  726. echo esc_html(__('Reset', 'newsletter'));
  727. echo '</button>';
  728. }
  729. function button_link($url, $label) {
  730. echo '<a href="', esc_attr($url), '" class="button-primary">', $label, '</a>';
  731. }
  732. function button_configure($url) {
  733. echo '<a href="', esc_attr($url), '" class="button-primary"><i class="fa fa-cog"></i>', _e('Configure', 'newsletter'), '</a>';
  734. }
  735. function button_back($url) {
  736. echo '<a href="';
  737. echo esc_attr($url);
  738. echo '" class="button-primary"><i class="fa fa-chevron-left"></i>&nbsp;';
  739. _e('Back', 'newsletter');
  740. echo '</a>';
  741. }
  742. /**
  743. * Creates a button with "copy" action.
  744. * @param type $data
  745. */
  746. function button_copy($data = '') {
  747. echo '<button class="button-secondary" onclick="this.form.btn.value=\'' . esc_attr($data) . '\';this.form.act.value=\'copy\';if (!confirm(\'';
  748. echo esc_attr(esc_js(__('Proceed?', 'newsletter')));
  749. echo '\')) return false;">';
  750. echo '<i class="fa fa-copy"></i> ';
  751. echo esc_html(__('Duplicate', 'newsletter'));
  752. echo '</button>';
  753. }
  754. /**
  755. * Creates a button wirh "delete" action.
  756. * @param type $data
  757. */
  758. function button_delete($data = '') {
  759. echo '<button class="button-secondary" onclick="this.form.btn.value=\'' . esc_attr($data) . '\';this.form.act.value=\'delete\';if (!confirm(\'';
  760. echo esc_attr(esc_js(__('Proceed?', 'newsletter')));
  761. echo '\')) return false;">';
  762. echo '<i class="fa fa-times"></i> ';
  763. echo esc_html(__('Delete', 'newsletter'));
  764. echo '</button>';
  765. }
  766. function button_primary($action, $label, $function = null) {
  767. if ($function != null) {
  768. echo '<button class="button-primary" onclick="this.form.act.value=\'' . esc_attr($action) . '\';' . esc_attr($function) . '">', $label, '</button>';
  769. } else {
  770. echo '<button class="button-primary" onclick="this.form.act.value=\'' . esc_attr($action) . '\'; return true;"/>', $label, '</button>';
  771. }
  772. }
  773. function button_confirm($action, $label, $message = '', $data = '') {
  774. if (empty($message)) {
  775. $message = __('Are you sure?', 'newsletter');
  776. }
  777. echo '<input class="button-primary" type="button" value="' . esc_attr($label) . '" onclick="this.form.btn.value=\'' . esc_attr($data) . '\';this.form.act.value=\'' . esc_attr($action) . '\';if (confirm(\'' .
  778. esc_attr(esc_js($message)) . '\')) this.form.submit()"/>';
  779. }
  780. function editor($name, $rows = 5, $cols = 75) {
  781. echo '<textarea class="visual" name="options[' . esc_attr($name) . ']" style="width: 100%" wrap="off" rows="' . esc_attr($rows) . '">';
  782. echo esc_html($this->get_value($name));
  783. echo '</textarea>';
  784. }
  785. function wp_editor($name, $settings = array()) {
  786. $value = $this->get_value($name);
  787. wp_editor($value, $name, array_merge(array(
  788. 'tinymce' => array('content_css' => plugins_url('newsletter') . '/css/wp-editor.css?ver=' . filemtime(NEWSLETTER_DIR . '/css/wp-editor.css')),
  789. 'textarea_name' => 'options[' . esc_attr($name) . ']',
  790. 'wpautop' => false
  791. ), $settings));
  792. //echo '<p class="description">You can install <a href="https://wordpress.org/plugins/tinymce-advanced/" target="_blank">TinyMCE Advanced</a> for advanced editing features</p>';
  793. }
  794. function textarea($name, $width = '100%', $height = '50') {
  795. $value = $this->get_value($name);
  796. if (is_array($value)) {
  797. $value = implode("\n", $value);
  798. }
  799. echo '<textarea id="options-' . esc_attr($name) . '" class="dynamic" name="options[' . esc_attr($name) . ']" wrap="off" style="width:' . esc_attr($width) . ';height:' . esc_attr($height) . '">';
  800. echo esc_html($value);
  801. echo '</textarea>';
  802. }
  803. function textarea_fixed($name, $width = '100%', $height = '200') {
  804. $value = $this->get_value($name);
  805. echo '<textarea id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']" wrap="off" style="width:' . esc_attr($width) . ';height:' . esc_attr($height) . 'px">';
  806. echo esc_html($value);
  807. echo '</textarea>';
  808. }
  809. function textarea_preview($name, $width = '100%', $height = '200', $header = '', $footer = '', $switch_button = true) {
  810. $value = $this->get_value($name);
  811. //do_action('newsletter_controls_textarea_preview', $name);
  812. if ($switch_button) {
  813. echo '<input class="button-primary" type="button" onclick="newsletter_textarea_preview(\'options-' . esc_attr($name) . '\', \'\', \'\')" value="Switch editor/preview">';
  814. echo '<br><br>';
  815. }
  816. echo '<div style="box-sizing: border-box; position: relative; margin: 0; padding: 0; width:' . esc_attr($width) . '; height:' . esc_attr($height) . '">';
  817. echo '<textarea id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']" wrap="off" style="width:' . esc_attr($width) . ';height:' . esc_attr($height) . 'px">';
  818. echo esc_html($value);
  819. echo '</textarea>';
  820. echo '<div id="options-' . esc_attr($name) . '-preview" style="box-sizing: border-box; background-color: #eee; border: 1px solid #bbb; padding: 15px; width: auto; position: absolute; top: 20px; left: 20px; box-shadow: 0 0 20px #777; z-index: 10000; display: none">';
  821. echo '<iframe id="options-' . esc_attr($name) . '-iframe" class="tnp-editor-preview-desktop"></iframe>';
  822. echo '<iframe id="options-' . esc_attr($name) . '-iframe-phone" class="tnp-editor-preview-mobile"></iframe>';
  823. echo '</div>';
  824. echo '</div>';
  825. }
  826. function email($prefix, $editor = null, $disable_option = false, $settings = array()) {
  827. if ($disable_option) {
  828. $this->disabled($prefix . '_disabled');
  829. echo '<br>';
  830. }
  831. $this->text($prefix . '_subject', 90, 'Subject');
  832. echo '<br><br>';
  833. if ($editor == 'wordpress') {
  834. $this->wp_editor($prefix . '_message', $settings);
  835. } else if ($editor == 'textarea') {
  836. $this->textarea($prefix . '_message');
  837. } else {
  838. $this->editor($prefix . '_message');
  839. }
  840. }
  841. function checkbox($name, $label = '') {
  842. if ($label != '') {
  843. echo '<label>';
  844. }
  845. echo '<input type="checkbox" id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']" value="1"';
  846. if (!empty($this->data[$name])) {
  847. echo ' checked';
  848. }
  849. echo '>';
  850. if ($label != '') {
  851. echo '&nbsp;' . esc_html($label) . '</label>';
  852. }
  853. }
  854. function checkbox2($name, $label = '') {
  855. if ($label != '') {
  856. echo '<label>';
  857. }
  858. echo '<input type="checkbox" id="' . esc_attr($name) . '" onchange="document.getElementById(\'' . esc_attr($name) . '_hidden\').value=this.checked?\'1\':\'0\'"';
  859. if (!empty($this->data[$name])) {
  860. echo ' checked="checked"';
  861. }
  862. echo '>';
  863. if ($label != '') {
  864. echo '&nbsp;' . esc_html($label) . '</label>';
  865. }
  866. echo '<input type="hidden" id="' . esc_attr($name) . '_hidden" name="options[' . esc_attr($name) . ']" value="';
  867. echo empty($this->data[$name]) ? '0' : '1';
  868. echo '">';
  869. }
  870. function radio($name, $value, $label = '') {
  871. if ($label != '') {
  872. echo '<label>';
  873. }
  874. echo '<input type="radio" id="' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']" value="' . esc_attr($value) . '"';
  875. $v = $this->get_value($name);
  876. if ($v == $value) {
  877. echo ' checked="checked"';
  878. }
  879. echo '>';
  880. if ($label != '') {
  881. echo '&nbsp;' . esc_html($label) . '</label>';
  882. }
  883. }
  884. /**
  885. * Creates a checkbox named $name and checked if the internal data contains under
  886. * the key $name an array containig the passed value.
  887. */
  888. function checkbox_group($name, $value, $label = '') {
  889. echo '<label><input type="checkbox" id="' . esc_attr($name) . '" name="options[' . esc_attr($name) . '][]" value="' . esc_attr($value) . '"';
  890. if (isset($this->data[$name]) && is_array($this->data[$name]) && array_search($value, $this->data[$name]) !== false) {
  891. echo ' checked';
  892. }
  893. echo '>';
  894. if ($label != '') {
  895. echo esc_html($label);
  896. }
  897. echo '</label>';
  898. }
  899. function checkboxes($name, $options) {
  900. echo '<div class="tnp-checkboxes">';
  901. foreach ($options as $value => $label) {
  902. $this->checkbox_group($name, $value, $label);
  903. }
  904. echo '<div style="clear: both"></div>';
  905. echo '</div>';
  906. }
  907. function color($name) {
  908. $value = $this->get_value($name);
  909. //echo '<input id="options-', esc_attr($name), '" class="tnp-controls-color" name="options[' . $name . ']" type="text" value="';
  910. echo '<input id="options-', esc_attr($name), '" name="options[' . $name . ']" type="color" value="';
  911. echo esc_attr($value);
  912. echo '">';
  913. }
  914. /** Creates a set of checkbox named $name_[category id] (so they are posted with distinct names).
  915. */
  916. function categories($name = 'category') {
  917. $categories = get_categories();
  918. echo '<div class="newsletter-checkboxes-group">';
  919. foreach ($categories as $c) {
  920. echo '<div class="newsletter-checkboxes-item">';
  921. $this->checkbox($name . '_' . $c->cat_ID, esc_html($c->cat_name));
  922. echo '</div>';
  923. }
  924. echo '<div style="clear: both"></div>';
  925. echo '</div>';
  926. }
  927. /**
  928. * Creates a set of checkbox to activate the profile preferences. Every checkbox has a DIV around to
  929. * be formatted.
  930. */
  931. function categories_group($name, $show_mode = false) {
  932. $categories = get_categories();
  933. if ($show_mode) {
  934. $this->select($name . '_mode', array('include' => 'To be included', 'exclude' => 'To be excluded'));
  935. }
  936. echo '<div class="newsletter-checkboxes-group">';
  937. foreach ($categories as &$c) {
  938. echo '<div class="newsletter-checkboxes-item">';
  939. $this->checkbox_group($name, $c->cat_ID, esc_html($c->cat_name));
  940. echo '</div>';
  941. }
  942. echo '<div style="clear: both"></div>';
  943. echo '</div>';
  944. }
  945. /**
  946. * Creates a set of checkboxes named $name_[preference number] (so they are
  947. * distinct fields).
  948. * Empty preferences are skipped.
  949. */
  950. function preferences($name = 'preferences') {
  951. $lists = Newsletter::instance()->get_lists();
  952. echo '<div class="newsletter-preferences-group">';
  953. foreach ($lists as $list) {
  954. echo '<div class="newsletter-preferences-item">';
  955. $this->checkbox2($name . '_' . $list->id, esc_html($list->name));
  956. echo '</div>';
  957. }
  958. }
  959. function lists_checkboxes($name = 'lists') {
  960. $this->preferences_group($name);
  961. }
  962. /**
  963. * Creates a set of checkboxes all names $name[] and the preference number as value
  964. * so the selected checkboxes are retrieved as an array of values ($REQUEST[$name]
  965. * will be an array if at east one preference is checked).
  966. */
  967. function preferences_group($name = 'preferences') {
  968. $lists = Newsletter::instance()->get_lists();
  969. echo '<div class="newsletter-preferences-group">';
  970. foreach ($lists as $list) {
  971. echo '<div class="newsletter-preferences-item">';
  972. $this->checkbox_group($name, $list->id, '(' . $list->id . ') ' . esc_html($list->name));
  973. echo '</div>';
  974. }
  975. echo '<div style="clear: both"></div>';
  976. echo '<a href="https://www.thenewsletterplugin.com/documentation/newsletter-lists" target="_blank">'
  977. . 'Click here to read more about lists.'
  978. . '</a>';
  979. echo '</div>';
  980. }
  981. /** Creates as many selects as the active preferences with the three values
  982. * 'any', 'yes', 'no' corresponding to the values 0, 1, 2.
  983. */
  984. function preferences_selects($name = 'preferences', $skip_empty = false) {
  985. $lists = Newsletter::instance()->get_lists();
  986. echo '<div class="newsletter-preferences-group">';
  987. foreach ($lists as $list) {
  988. echo '<div class="newsletter-preferences-item">';
  989. $this->select($name . '_' . $list->id, array(0 => 'Any', 1 => 'Yes', 2 => 'No'));
  990. echo '(' . $list->id . ') ' . esc_html($list->name);
  991. echo '</div>';
  992. }
  993. echo '<div style="clear: both"></div>';
  994. echo '<a href="https://www.thenewsletterplugin.com/plugins/newsletter/newsletter-preferences" target="_blank">Click here know more about preferences.</a> They can be configured on Subscription/Form field panel.';
  995. echo '</div>';
  996. }
  997. /**
  998. * Creates a single select with the active preferences.
  999. */
  1000. function preferences_select($name = 'preference', $empty_label = null) {
  1001. $lists = $this->get_list_options($empty_label);
  1002. $this->select($name, $lists);
  1003. echo ' <a href="admin.php?page=newsletter_subscription_lists" target="_blank"><i class="fa fa-edit"></i></a>';
  1004. }
  1005. function lists_select($name = 'list', $empty_label = null) {
  1006. $lists = $this->get_list_options($empty_label);
  1007. $this->select($name, $lists);
  1008. }
  1009. /**
  1010. * Generates an associative array with the active lists to be used in a select.
  1011. * @param string $empty_label
  1012. * @return array
  1013. */
  1014. function get_list_options($empty_label = null) {
  1015. $objs = Newsletter::instance()->get_lists();
  1016. $lists = array();
  1017. if ($empty_label) {
  1018. $lists[''] = $empty_label;
  1019. }
  1020. foreach ($objs as $list) {
  1021. $lists['' . $list->id] = '(' . $list->id . ') ' . esc_html($list->name);
  1022. }
  1023. return $lists;
  1024. }
  1025. function date($name) {
  1026. $this->hidden($name);
  1027. $year = date('Y', $this->data[$name]);
  1028. $day = date('j', $this->data[$name]);
  1029. $month = date('m', $this->data[$name]);
  1030. $onchange = "this.form.elements['options[" . esc_attr($name) . "]'].value = new Date(document.getElementById('" . esc_attr($name) . "_year').value, document.getElementById('" . esc_attr($name) . "_month').value, document.getElementById('" . esc_attr($name) . "_day').value, 12, 0, 0).getTime()/1000";
  1031. echo '<select id="' . $name . '_month" onchange="' . esc_attr($onchange) . '">';
  1032. for ($i = 0; $i < 12; $i++) {
  1033. echo '<option value="' . $i . '"';
  1034. if ($month - 1 == $i) {
  1035. echo ' selected';
  1036. }
  1037. echo '>' . date('F', mktime(0, 0, 0, $i + 1, 1, 2000)) . '</option>';
  1038. }
  1039. echo '</select>';
  1040. echo '<select id="' . esc_attr($name) . '_day" onchange="' . esc_attr($onchange) . '">';
  1041. for ($i = 1; $i <= 31; $i++) {
  1042. echo '<option value="' . $i . '"';
  1043. if ($day == $i) {
  1044. echo ' selected';
  1045. }
  1046. echo '>' . $i . '</option>';
  1047. }
  1048. echo '</select>';
  1049. echo '<select id="' . esc_attr($name) . '_year" onchange="' . esc_attr($onchange) . '">';
  1050. for ($i = 2011; $i <= 2021; $i++) {
  1051. echo '<option value="' . $i . '"';
  1052. if ($year == $i) {
  1053. echo ' selected';
  1054. }
  1055. echo '>' . $i . '</option>';
  1056. }
  1057. echo '</select>';
  1058. }
  1059. /**
  1060. * Date and time (hour) selector. Timestamp stored.
  1061. */
  1062. function datetime($name) {
  1063. echo '<input type="hidden" name="fields[' . esc_attr($name) . ']" value="datetime">';
  1064. $time = $this->data[$name] + get_option('gmt_offset') * 3600;
  1065. $year = gmdate('Y', $time);
  1066. $day = gmdate('j', $time);
  1067. $month = gmdate('m', $time);
  1068. $hour = gmdate('H', $time);
  1069. echo '<select name="' . esc_attr($name) . '_month">';
  1070. for ($i = 1; $i <= 12; $i++) {
  1071. echo '<option value="' . $i . '"';
  1072. if ($month == $i) {
  1073. echo ' selected';
  1074. }
  1075. echo '>' . date('F', mktime(0, 0, 0, $i, 1, 2000)) . '</option>';
  1076. }
  1077. echo '</select>';
  1078. echo '<select name="' . esc_attr($name) . '_day">';
  1079. for ($i = 1; $i <= 31; $i++) {
  1080. echo '<option value="' . $i . '"';
  1081. if ($day == $i) {
  1082. echo ' selected';
  1083. }
  1084. echo '>' . $i . '</option>';
  1085. }
  1086. echo '</select>';
  1087. echo '<select name="' . esc_attr($name) . '_year">';
  1088. for ($i = 2011; $i <= 2021; $i++) {
  1089. echo '<option value="' . $i . '"';
  1090. if ($year == $i) {
  1091. echo ' selected';
  1092. }
  1093. echo '>' . $i . '</option>';
  1094. }
  1095. echo '</select>';
  1096. echo '<select name="' . esc_attr($name) . '_hour">';
  1097. for ($i = 0; $i <= 23; $i++) {
  1098. echo '<option value="' . $i . '"';
  1099. if ($hour == $i) {
  1100. echo ' selected';
  1101. }
  1102. echo '>' . $i . ':00</option>';
  1103. }
  1104. echo '</select>';
  1105. }
  1106. function hours($name) {
  1107. $hours = array();
  1108. for ($i = 0; $i < 24; $i++) {
  1109. $hours['' . $i] = sprintf('%02d', $i) . ':00';
  1110. }
  1111. $this->select($name, $hours);
  1112. }
  1113. function days($name) {
  1114. $days = array(0 => 'Every day', 1 => 'Monday', 2 => 'Tuesday', 3 => 'Wednesday', 4 => 'Thursday', 5 => 'Friday', 6 => 'Saturday', 7 => 'Sunday');
  1115. $this->select($name, $days);
  1116. }
  1117. function init($options = array()) {
  1118. $cookie_name = 'newsletter_tab';
  1119. if (isset($options['cookie_name'])) {
  1120. $cookie_name = $options['cookie_name'];
  1121. }
  1122. echo '<script type="text/javascript">
  1123. jQuery(document).ready(function(){
  1124. jQuery("textarea.dynamic").focus(function() {
  1125. jQuery("textarea.dynamic").css("height", "50px");
  1126. jQuery(this).css("height", "400px");
  1127. });
  1128. tabs = jQuery("#tabs").tabs({
  1129. active : jQuery.cookie("' . $cookie_name . '"),
  1130. activate : function( event, ui ){
  1131. jQuery.cookie("' . $cookie_name . '", ui.newTab.index(),{expires: 1});
  1132. }
  1133. });
  1134. });
  1135. function newsletter_media(name) {
  1136. var tnp_uploader = wp.media({
  1137. title: "Select an image",
  1138. button: {
  1139. text: "Select"
  1140. },
  1141. multiple: false
  1142. }).on("select", function() {
  1143. var media = tnp_uploader.state().get("selection").first();
  1144. document.getElementById(name + "_id").value = media.id;
  1145. jQuery("#" + name + "_id").trigger("change");
  1146. //alert(media.attributes.url);
  1147. if (media.attributes.url.substring(0, 0) == "/") {
  1148. media.attributes.url = "' . site_url('/') . '" + media.attributes.url;
  1149. }
  1150. document.getElementById(name + "_url").value = media.attributes.url;
  1151. var img_url = media.attributes.url;
  1152. if (typeof media.attributes.sizes.medium !== "undefined") img_url = media.attributes.sizes.medium.url;
  1153. if (img_url.substring(0, 0) == "/") {
  1154. img_url = "' . site_url('/') . '" + img_url;
  1155. }
  1156. document.getElementById(name + "_img").src = img_url;
  1157. }).open();
  1158. }
  1159. function newsletter_media_remove(name) {
  1160. if (confirm("Are you sure?")) {
  1161. document.getElementById(name + "_id").value = "";
  1162. document.getElementById(name + "_url").value = "";
  1163. document.getElementById(name + "_img").src = "' . plugins_url('newsletter') . '/images/nomedia.png";
  1164. }
  1165. }
  1166. function newsletter_textarea_preview(id, header, footer) {
  1167. var d = document.getElementById(id + "-iframe").contentWindow.document;
  1168. d.open();
  1169. if (templateEditor) {
  1170. d.write(templateEditor.getValue());
  1171. } else {
  1172. d.write(header + document.getElementById(id).value + footer);
  1173. }
  1174. d.close();
  1175. var d = document.getElementById(id + "-iframe-phone").contentWindow.document;
  1176. d.open();
  1177. if (templateEditor) {
  1178. d.write(templateEditor.getValue());
  1179. } else {
  1180. d.write(header + document.getElementById(id).value + footer);
  1181. }
  1182. d.close();
  1183. //jQuery("#" + id + "-iframe-phone").toggle();
  1184. jQuery("#" + id + "-preview").toggle();
  1185. }
  1186. function tnp_select_images(state) {
  1187. if (!state.id) { return state.text; }
  1188. var $state = jQuery("<span class=\"tnp-select2-option\"><img style=\"height: 20px!important; position: relative; top: 5px\" src=\"" + state.element.getAttribute("image") + "\"> " + state.text + "</span>");
  1189. return $state;
  1190. }
  1191. function tnp_select_images_selection(state) {
  1192. if (!state.id) { return state.text; }
  1193. var $state = jQuery("<span class=\"tnp-select2-option\"><img style=\"height: 20px!important; position: relative; top: 5px\" src=\"" + state.element.getAttribute("image") + "\"> " + state.text + "</span>");
  1194. return $state;
  1195. }
  1196. </script>
  1197. ';
  1198. echo '<input name="act" type="hidden" value=""/>';
  1199. echo '<input name="btn" type="hidden" value=""/>';
  1200. wp_nonce_field('save');
  1201. }
  1202. function log_level($name = 'log_level') {
  1203. $this->select($name, array(0 => 'None', 2 => 'Error', 3 => 'Normal', 4 => 'Debug'));
  1204. }
  1205. function update_option($name, $data = null) {
  1206. if ($data == null) {
  1207. $data = $this->data;
  1208. }
  1209. update_option($name, $data);
  1210. if (isset($data['log_level'])) {
  1211. update_option($name . '_log_level', $data['log_level']);
  1212. }
  1213. }
  1214. function js_redirect($url) {
  1215. echo '<script>';
  1216. echo 'location.href="' . $url . '"';
  1217. echo '</script>';
  1218. }
  1219. /**
  1220. * @deprecated
  1221. */
  1222. function get_test_subscribers() {
  1223. return NewsletterUsers::instance()->get_test_users();
  1224. }
  1225. /**
  1226. * Attributes:
  1227. * weight: [true|false]
  1228. * color: [true|false]
  1229. *
  1230. * @param string $name
  1231. * @param array $attrs
  1232. */
  1233. function css_font($name = 'font', $attrs = array()) {
  1234. $default = array('color' => true, 'weight' => true);
  1235. $attrs = array_merge($default, $attrs);
  1236. $this->css_font_family($name . '_family');
  1237. $this->css_font_size($name . '_size');
  1238. if ($attrs['weight']) {
  1239. $this->css_font_weight($name . '_weight');
  1240. }
  1241. if ($attrs['color']) {
  1242. $this->color($name . '_color');
  1243. }
  1244. }
  1245. function css_font_size($name = 'font_size') {
  1246. $value = $this->get_value($name);
  1247. echo '<select id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']">';
  1248. for ($i = 8; $i < 50; $i++) {
  1249. echo '<option value="' . $i . '"';
  1250. if ($value == $i) {
  1251. echo ' selected';
  1252. }
  1253. echo '>' . $i . '</option>';
  1254. }
  1255. echo '</select>';
  1256. }
  1257. function css_font_weight($name = 'font_weight') {
  1258. $value = $this->get_value($name);
  1259. $fonts = array('normal' => 'Normal', 'bold' => 'Bold');
  1260. echo '<select id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']">';
  1261. foreach ($fonts as $key => $font) {
  1262. echo '<option value="', esc_attr($key), '"';
  1263. if ($value == $font) {
  1264. echo ' selected';
  1265. }
  1266. echo '>', esc_html($font), '</option>';
  1267. }
  1268. echo '</select>';
  1269. }
  1270. function css_font_family($name = 'font_family') {
  1271. $value = $this->get_value($name);
  1272. $fonts = array('Helvetica, Arial, sans-serif', 'Arial Black, Gadget, sans-serif', 'Garamond, serif', 'Courier, monospace', 'Comic Sans MS, cursive', 'Impact, Charcoal, sans-serif',
  1273. 'Tahoma, Geneva, sans-serif', 'Times New Roman, Times, serif', 'Verdana, Geneva, sans-serif');
  1274. echo '<select id="options-' . esc_attr($name) . '" name="options[' . esc_attr($name) . ']">';
  1275. foreach ($fonts as $font) {
  1276. echo '<option value="', esc_attr($font), '"';
  1277. if ($value == $font) {
  1278. echo ' selected';
  1279. }
  1280. echo '>', esc_html($font), '</option>';
  1281. }
  1282. echo '</select>';
  1283. }
  1284. function css_text_align($name) {
  1285. $options = array('left' => __('Left', 'newsletter'), 'right' => __('Right', 'newsletter'),
  1286. 'center' => __('Center', 'newsletter'));
  1287. $this->select($name, $options);
  1288. }
  1289. function css_border($name) {
  1290. $value = $this->get_value($name . '_width');
  1291. echo 'width&nbsp;<select id="options-' . esc_attr($name) . '-width" name="options[' . esc_attr($name) . '_width]">';
  1292. for ($i = 0; $i < 10; $i++) {
  1293. echo '<option value="' . $i . '"';
  1294. if ($value == $i) {
  1295. echo ' selected';
  1296. }
  1297. echo '>' . $i . '</option>';
  1298. }
  1299. echo '</select>&nbsp;px&nbsp;&nbsp;';
  1300. $this->select($name . '_type', array('solid' => 'Solid', 'dashed' => 'Dashed'));
  1301. $this->color($name . '_color');
  1302. $value = $this->get_value($name . '_radius');
  1303. echo '&nbsp;&nbsp;radius&nbsp;<select id="options-' . esc_attr($name) . '-radius" name="options[' . esc_attr($name) . '_radius]">';
  1304. for ($i = 0; $i < 10; $i++) {
  1305. echo '<option value="' . $i . '"';
  1306. if ($value == $i) {
  1307. echo ' selected';
  1308. }
  1309. echo '>' . $i . '</option>';
  1310. }
  1311. echo '</select>&nbsp;px';
  1312. }
  1313. /**
  1314. * Media selector using the media library of WP. Produces a field which values is an array containing 'id' and 'url'.
  1315. *
  1316. * @param string $name
  1317. */
  1318. function media($name) {
  1319. if (isset($this->data[$name]['id'])) {
  1320. $media_id = (int) $this->data[$name]['id'];
  1321. $media = wp_get_attachment_image_src($media_id, 'medium');
  1322. $media_full = wp_get_attachment_image_src($media_id, 'full');
  1323. } else {
  1324. $media = false;
  1325. }
  1326. echo '<div style="position: relative">';
  1327. echo '<a style="position: absolute; top: 5px; right: 5px; background-color: none; color: #000; padding: 0px 5px 6px 5px; font-size: 24px; display: block; text-decoration: none" href="#" onclick="newsletter_media_remove(\'' . esc_attr($name) . '\'); return false">&times;</a>';
  1328. if ($media === false) {
  1329. $media = array('', '', '');
  1330. $media_full = array('', '', '');
  1331. $media_id = 0;
  1332. echo '<img style="max-width: 200px; max-height: 200px; width: 100px;" id="' . esc_attr($name) . '_img" src="' . plugins_url('newsletter') . '/images/nomedia.png" onclick="newsletter_media(\'' . esc_attr($name) . '\')">';
  1333. } else {
  1334. echo '<img style="max-width: 200px; max-height: 200px;" id="' . esc_attr($name) . '_img" src="' . esc_attr($media[0]) . '" onclick="newsletter_media(\'' . esc_attr($name) . '\')">';
  1335. }
  1336. echo '</div>';
  1337. echo '<input type="hidden" id="' . esc_attr($name) . '_id" name="options[' . esc_attr($name) . '][id]" value="' . esc_attr($media_id) . '" size="5">';
  1338. echo '<input type="hidden" id="' . esc_attr($name) . '_url" name="options[' . esc_attr($name) . '][url]" value="' . esc_attr($media_full[0]) . '" size="50">';
  1339. }
  1340. function media_input($option, $name, $label) {
  1341. if (!empty($label)) {
  1342. $output = '<label class="select" for="tnp_' . esc_attr($name) . '">' . esc_html($label) . ':</label>';
  1343. }
  1344. $output .= '<input id="tnp_' . esc_attr($name) . '" type="text" size="36" name="' . esc_attr($option) . '[' . esc_attr($name) . ']" value="' . esc_attr($val) . '" />';
  1345. $output .= '<input id="tnp_' . esc_attr($name) . '_button" class="button-primary" type="button" value="Select Image" />';
  1346. $output .= '<br class="clear"/>';
  1347. echo $output;
  1348. }
  1349. function language($name = 'language', $empty_label = 'All') {
  1350. if (!class_exists('SitePress') && !function_exists('pll_default_language') && !class_exists('TRP_Translate_Press')) {
  1351. echo __('Install a multilanguage plugin.', 'newsletter');
  1352. echo ' <a href="https://www.thenewsletterplugin.com/documentation/multilanguage" target="_blank">', __('Read more', 'newsletter'), '</a>';
  1353. return;
  1354. }
  1355. $languages = Newsletter::instance()->get_languages();
  1356. if (!empty($empty_label)) {
  1357. $languages = array_merge(array('' => $empty_label), $languages);
  1358. }
  1359. $this->select($name, $languages);
  1360. }
  1361. function is_multilanguage() {
  1362. return Newsletter::instance()->is_multilanguage();
  1363. }
  1364. /**
  1365. * Creates a checkbox group with all active languages. Each checkbox is named
  1366. * $name[] and values with the relative language code.
  1367. *
  1368. * @param string $name
  1369. */
  1370. function languages($name = 'languages') {
  1371. if (!$this->is_multilanguage()) {
  1372. echo __('Install WPML or Polylang for multilanguage support', 'newsletter');
  1373. return;
  1374. }
  1375. $language_options = Newsletter::instance()->get_languages();
  1376. if (empty($language_options)) {
  1377. echo __('Your multilanguage plugin is not supported or there are no languages defined', 'newsletter');
  1378. return;
  1379. }
  1380. $this->checkboxes_group($name, $language_options);
  1381. }
  1382. /**
  1383. * Prints a formatted date using the formats and timezone of WP, including the current date and time and the
  1384. * time left to the passed time.
  1385. *
  1386. * @param int $time
  1387. * @param int $now
  1388. * @param bool $left
  1389. * @return string
  1390. */
  1391. static function print_date($time = null, $now = false, $left = false) {
  1392. if (is_null($time)) {
  1393. $time = time();
  1394. }
  1395. if ($time == false) {
  1396. $buffer = 'none';
  1397. } else {
  1398. $buffer = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600);
  1399. }
  1400. if ($now) {
  1401. $buffer .= ' (now: ' . gmdate(get_option('date_format') . ' ' .
  1402. get_option('time_format'), time() + get_option('gmt_offset') * 3600);
  1403. $buffer .= ')';
  1404. }
  1405. if ($left) {
  1406. if ($time - time() < 0) {
  1407. $buffer .= ', ' . (time() - $time) . ' seconds late';
  1408. } else {
  1409. $buffer .= ', ' . gmdate('H:i:s', $time - time()) . ' left';
  1410. }
  1411. }
  1412. return $buffer;
  1413. }
  1414. /**
  1415. * Prints the help button near a form field. The label is used as icon title.
  1416. *
  1417. * @param string $url
  1418. * @param string $label
  1419. */
  1420. static function help($url, $label = '') {
  1421. echo '<a href="', $url, '" target="_blank" title="', esc_attr($label), '"><i class="fa fa-question-circle-o"></i></a>';
  1422. }
  1423. static function idea($url, $label = '') {
  1424. echo '<a href="', $url, '" target="_blank" title="', esc_attr($label), '"><i class="fa fa-lightbulb-o"></i></a>';
  1425. }
  1426. static function field_help($url, $text = '') {
  1427. echo '<a href="', $url, '" target="_blank" style="text-decoration: none" title="' . esc_attr(__('Read more', 'newsletter')) . '"><i class="fa fa-question-circle"></i>&nbsp;', $text, '</a>';
  1428. }
  1429. /**
  1430. * Prints a panel link to the documentation.
  1431. *
  1432. * @param type $url
  1433. * @param type $text
  1434. */
  1435. static function panel_help($url, $text = '') {
  1436. if (empty($text))
  1437. $text = __('Need help?', 'newsletter');
  1438. echo '<span class="tnp-panel-help"><a href="', $url, '" target="_blank">', $text, '</a></span>';
  1439. }
  1440. /**
  1441. * Prints an administration page link to the documentation (just under the administration page title.
  1442. * @param type $url
  1443. * @param type $text
  1444. */
  1445. static function page_help($url, $text = '') {
  1446. if (empty($text))
  1447. $text = __('Need help?', 'newsletter');
  1448. echo '<div class="tnp-page-help"><a href="', $url, '" target="_blank">', $text, '</a></div>';
  1449. }
  1450. static function print_truncated($text, $size = 50) {
  1451. if (mb_strlen($text) < $size)
  1452. return esc_html($text);
  1453. $sub = mb_substr($text, 0, $size);
  1454. echo '<span title="', esc_attr($text), '">', esc_html($sub), '...</span>';
  1455. }
  1456. function block_background($name = 'block_background') {
  1457. $this->color($name);
  1458. }
  1459. function block_padding($name = 'block_padding', $options = array()) {
  1460. echo '<div style="text-align: center; width: 250px;">';
  1461. $this->text($name . '_top', 5);
  1462. echo '<br>';
  1463. $this->text($name . '_left', 5);
  1464. echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
  1465. $this->text($name . '_right', 5);
  1466. echo '<br>';
  1467. $this->text($name . '_bottom', 5);
  1468. echo '</div>';
  1469. }
  1470. function composer_fields($name = 'body') {
  1471. // body
  1472. $value = $this->get_value($name);
  1473. // Extracts only the body part
  1474. $x = strpos($value, '<body');
  1475. if ($x) {
  1476. $x = strpos($value, '>', $x);
  1477. $y = strpos($value, '</body>');
  1478. $value = substr($value, $x + 1, $y - $x - 1);
  1479. }
  1480. /* Cleans up uncorrectly stored newsletter bodies */
  1481. $value = preg_replace('/<style\s+.*?>.*?<\\/style>/is', '', $value);
  1482. $value = preg_replace('/<meta.*?>/', '', $value);
  1483. $value = preg_replace('/<title\s+.*?>.*?<\\/title>/i', '', $value);
  1484. $value = trim($value);
  1485. // Required since esc_html DOES NOT escape the HTML entities (apparently)
  1486. $value = str_replace('&', '&amp;', $value);
  1487. $value = str_replace('"', '&quot;', $value);
  1488. $value = str_replace('<', '&lt;', $value);
  1489. $value = str_replace('>', '&gt;', $value);
  1490. echo '<input type="hidden" name="options[', esc_attr($name), ']" id="options-', esc_attr($name), '" value="', esc_attr($value), '">';
  1491. // Used by composer to rebuild the full HTML
  1492. $css = NewsletterEmails::instance()->get_composer_css();
  1493. echo '<input type="hidden" name="options[css]" id="options-css" value="', esc_attr($css), '">';
  1494. // subject
  1495. $value = $this->get_value('subject');
  1496. echo '<input type="hidden" name="options[subject]" id="options-subject" value="', esc_attr($value), '">';
  1497. }
  1498. function composer_load($name = 'body', $show_subject = false, $show_test = true, $context_type = '') {
  1499. global $controls;
  1500. global $tnpc_show_subject;
  1501. $tnpc_show_subject = $show_subject;
  1502. wp_enqueue_style('tnpc-style', plugins_url('newsletter') . '/emails/tnp-composer/_css/newsletter-builder.css', array(), time());
  1503. include NEWSLETTER_DIR . '/emails/tnp-composer/index.php';
  1504. }
  1505. }