/includes/admin/settings/settings-api.php

  1. <?php 
  2. /** 
  3. * Settings API for the Tracking Tab 
  4. * 
  5. * @since 6.0.0 
  6. * 
  7. * @package MonsterInsights 
  8. * @subpackage Settings API 
  9. * @author Chris Christoff 
  10. */ 
  11.  
  12. // Exit if accessed directly 
  13. if ( !defined( 'ABSPATH' ) ) exit; 
  14.  
  15. /** 
  16. * Get the settings for a section 
  17. * 
  18. * @since 6.0.0 
  19. * @return void 
  20. */ 
  21. function monsterinsights_get_section_settings( $section, $page = 'tracking' ) { 
  22. $output = ''; 
  23. $settings = monsterinsights_get_registered_settings(); 
  24. if ( is_array( $settings ) && ! empty( $settings[$section] ) && is_array( $settings[$section] ) ) { 
  25. foreach ( $settings[$section] as $setting ) { 
  26. $args = wp_parse_args( $setting, array( 
  27. 'id' => null,  
  28. 'desc' => '',  
  29. 'name' => '',  
  30. 'size' => null,  
  31. 'options' => '',  
  32. 'std' => '',  
  33. 'min' => null,  
  34. 'max' => null,  
  35. 'step' => null,  
  36. 'select2' => null,  
  37. 'placeholder' => null,  
  38. 'allow_blank' => true,  
  39. 'readonly' => false,  
  40. 'faux' => false,  
  41. 'tooltip_title' => false,  
  42. 'tooltip_desc' => false,  
  43. 'field_class' => '',  
  44. 'multiple' => false,  
  45. 'allowclear' => true,  
  46. 'notice_type' => 'info',  
  47. ) ); 
  48. $output .= monsterinsights_render_field( $args ); 
  49. return $output; 
  50.  
  51. /** 
  52. * Saves Settings 
  53. * 
  54. * @since 6.0.0 
  55. * @access public 
  56. * 
  57. * @return null Return early if not fixing the broken migration 
  58. */ 
  59. function monsterinsights_save_settings() { 
  60.  
  61. // Check if user pressed the 'Update' button and nonce is valid 
  62. if ( ! isset( $_POST['monsterinsights-settings-submit'] ) ) { 
  63. return; 
  64.  
  65. if ( ! wp_verify_nonce( $_POST['monsterinsights-settings-nonce'], 'monsterinsights-settings-nonce' ) ) { 
  66. return; 
  67.  
  68. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  69. return; 
  70.  
  71. if ( empty( $_POST['monsterinsights_settings_tab'] ) || empty( $_POST['monsterinsights_settings_sub_tab'] ) || $_POST['monsterinsights_settings_tab'] !== 'tracking' ) { 
  72. return; 
  73.  
  74. // get subtab 
  75. $settings = monsterinsights_get_registered_settings(); 
  76. $tab = $_POST['monsterinsights_settings_sub_tab']; 
  77. if ( empty( $settings ) || !is_array( $settings ) || empty( $settings[ $tab ] ) || ! is_array( $settings[ $tab ] ) ) { 
  78. return; 
  79.  
  80. // Okay we're good to sanitize, validate, and save this section's settings 
  81.  
  82. // We only care about this sections's settings 
  83. $settings = $settings[ $tab ];  
  84.  
  85. // Run a general sanitization for the tab for special fields 
  86. $input = ! empty( $_POST['monsterinsights_settings'] ) ? $_POST['monsterinsights_settings'] : array(); 
  87. $input = apply_filters( 'monsterinsights_settings_' . $tab . '_sanitize', $input ); 
  88.  
  89. foreach( $settings as $id => $setting ) { 
  90.  
  91. // If the value wasn't passed in, set to false, which will delete the option 
  92. $value = isset( $input[ $id ] ) ? $input[ $id ] : false; 
  93. $previous_value = monsterinsights_get_option( $id, false ); 
  94.  
  95. // Sanitize/Validate 
  96. if ( empty( $setting['type'] ) ) { 
  97. continue; 
  98.  
  99. // Some setting types are not actually settings, just keep moving along here 
  100. $non_setting_types = monsterinsights_get_non_setting_types(); 
  101. $type = $setting['type']; 
  102.  
  103. if ( in_array( $type, $non_setting_types ) ) { 
  104. continue; 
  105.  
  106. $args = wp_parse_args( $setting, array( 
  107. 'id' => null,  
  108. 'desc' => '',  
  109. 'name' => '',  
  110. 'size' => null,  
  111. 'options' => '',  
  112. 'std' => '',  
  113. 'min' => null,  
  114. 'max' => null,  
  115. 'step' => null,  
  116. 'select2' => null,  
  117. 'placeholder' => null,  
  118. 'allow_blank' => true,  
  119. 'readonly' => false,  
  120. 'faux' => false,  
  121. 'tooltip_title' => false,  
  122. 'tooltip_desc' => false,  
  123. 'field_class' => '',  
  124. 'multiple' => false,  
  125. 'allowclear' => true,  
  126. 'notice_type' => 'info',  
  127. ) ); 
  128.  
  129. // Sanitize settings 
  130. $value = apply_filters( 'monsterinsights_settings_sanitize_' . $id , $value, $id, $args, $previous_value ); 
  131. $value = apply_filters( 'monsterinsights_settings_sanitize_' . $type, $value, $id, $args, $previous_value ); 
  132. $value = apply_filters( 'monsterinsights_settings_sanitize' , $value, $id, $args, $previous_value ); 
  133.  
  134. // Save 
  135. do_action( 'monsterinsights_settings_save_' . $args['type'], $value, $id, $args, $previous_value ); 
  136. if ( ! has_action( 'monsterinsights_settings_save_' . $args['type'] ) ) { 
  137. monsterinsights_update_option( $id, $value ); 
  138. add_action( 'monsterinsights_tracking_' . $tab . '_tab_notice', 'monsterinsights_updated_settings' ); 
  139. add_action( 'current_screen', 'monsterinsights_save_settings' ); 
  140.  
  141. /** 
  142. * Flattens the set of registered settings and their type so we can easily sanitize all the settings 
  143. * in a much cleaner set of logic in monsterinsights_settings_sanitize 
  144. * 
  145. * @since 6.0.0 
  146. * @return array Key is the setting ID, value is the type of setting it is registered as 
  147. */ 
  148. function monsterinsights_get_registered_settings_types( $section = '' ) { 
  149. $settings = monsterinsights_get_registered_settings(); 
  150. $setting_types = array(); 
  151. if ( ! empty( $section ) ) { 
  152. if ( ! empty( $settings[$section] ) ) { 
  153. foreach ( $settings[$section] as $setting ) { 
  154. if ( is_array( $setting ) && array_key_exists( 'type', $setting ) ) { 
  155. $setting_types[ $setting['id'] ] = $setting['type']; 
  156. } else { 
  157. foreach ( $settings as $tab ) { 
  158. foreach ( $tab as $setting ) { 
  159. if ( is_array( $setting ) && array_key_exists( 'type', $setting ) ) { 
  160. $setting_types[ $setting['id'] ] = $setting['type']; 
  161. return $setting_types; 
  162.  
  163. /** 
  164. * Sanitize rich editor fields 
  165. * 
  166. * @since 6.0.0 
  167. * @param array $input The field value 
  168. * @return string $input Sanitizied value 
  169. */ 
  170. function monsterinsights_sanitize_rich_editor_field( $input ) { 
  171. $tags = array( 
  172. 'p' => array( 
  173. 'class' => array(),  
  174. 'id' => array(),  
  175. ),  
  176. 'span' => array( 
  177. 'class' => array(),  
  178. 'id' => array(),  
  179. ),  
  180. 'a' => array( 
  181. 'href' => array(),  
  182. 'title' => array(),  
  183. 'class' => array(),  
  184. 'title' => array(),  
  185. 'id' => array(),  
  186. ),  
  187. 'strong' => array(),  
  188. 'em' => array(),  
  189. 'br' => array(),  
  190. 'img' => array( 
  191. 'src' => array(),  
  192. 'title' => array(),  
  193. 'alt' => array(),  
  194. 'id' => array(),  
  195. ),  
  196. 'div' => array( 
  197. 'class' => array(),  
  198. 'id' => array(),  
  199. ),  
  200. 'ul' => array( 
  201. 'class' => array(),  
  202. 'id' => array(),  
  203. ),  
  204. 'li' => array( 
  205. 'class' => array(),  
  206. 'id' => array(),  
  207. ); 
  208.  
  209. //$allowed_tags = apply_filters( 'monsterinsights_allowed_html_tags', $tags ); 
  210.  
  211. return trim( wp_kses( $input, $allowed_tags ) ); 
  212. add_filter( 'monsterinsights_settings_sanitize_rich_editor', 'monsterinsights_sanitize_rich_editor_field' ); 
  213.  
  214. if ( ! function_exists( 'sanitize_textarea_field' ) ) { 
  215. function sanitize_textarea_field( $str ) { 
  216. $filtered = _sanitize_text_fields( $str, true ); 
  217. return apply_filters( 'sanitize_textarea_field', $filtered, $str ); 
  218.  
  219. if ( ! function_exists( 'sanitize_textarea_field' ) ) { 
  220. function _sanitize_text_fields( $str, $keep_newlines = false ) { 
  221. $filtered = wp_check_invalid_utf8( $str ); 
  222.  
  223. if ( strpos($filtered, '<') !== false ) { 
  224. $filtered = wp_pre_kses_less_than( $filtered ); 
  225. // This will strip extra whitespace for us. 
  226. $filtered = wp_strip_all_tags( $filtered, false ); 
  227.  
  228. // Use html entities in a special case to make sure no later 
  229. // newline stripping stage could lead to a functional tag 
  230. $filtered = str_replace("<\n", "<\n", $filtered); 
  231.  
  232. if ( ! $keep_newlines ) { 
  233. $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered ); 
  234. $filtered = trim( $filtered ); 
  235.  
  236. $found = false; 
  237. while ( preg_match('/%[a-f0-9]{2}/i', $filtered, $match) ) { 
  238. $filtered = str_replace($match[0], '', $filtered); 
  239. $found = true; 
  240.  
  241. if ( $found ) { 
  242. // Strip out the whitespace that may now exist after removing the octets. 
  243. $filtered = trim( preg_replace('/ +/', ' ', $filtered) ); 
  244.  
  245. return $filtered; 
  246.  
  247. /** 
  248. * Sanitize textarea fields 
  249. * 
  250. * @since 6.0.0 
  251. * @todo docbloc 
  252. */ 
  253. function monsterinsights_sanitize_textarea_field( $value, $id, $setting, $previous_value ) { 
  254. return sanitize_textarea_field( $value ); 
  255. add_filter( 'monsterinsights_settings_sanitize_textarea', 'monsterinsights_sanitize_textarea_field', 10, 4 ); 
  256.  
  257. /** 
  258. * Sanitize checkbox fields 
  259. * 
  260. * @since 6.0.0 
  261. * @todo docbloc 
  262. */ 
  263. function monsterinsights_sanitize_checkbox_field( $value, $id, $setting, $previous_value ) { 
  264. return (bool) $value; 
  265. add_filter( 'monsterinsights_settings_sanitize_checkbox', 'monsterinsights_sanitize_checkbox_field', 10, 4 ); 
  266.  
  267. /** 
  268. * Sanitize multicheck fields 
  269. * 
  270. * @since 6.0.0 
  271. * @todo docbloc 
  272. */ 
  273. function monsterinsights_sanitize_multicheck_field( $value, $id, $setting, $previous_value ) { 
  274. $save_value = array(); 
  275. if ( ! empty( $value ) && is_array( $value ) ) { 
  276. foreach( $setting['options'] as $key => $option ) { 
  277. if ( in_array( $key, $value ) ) { 
  278. $save_value[] = $key; 
  279. return $save_value; 
  280. add_filter( 'monsterinsights_settings_sanitize_multicheck', 'monsterinsights_sanitize_multicheck_field', 10, 4 ); 
  281.  
  282. /** 
  283. * Sanitize select fields 
  284. * 
  285. * @since 6.0.0 
  286. * @todo docbloc 
  287. */ 
  288. function monsterinsights_sanitize_select_field( $value, $id, $setting, $previous_value ) { 
  289. if ( ! empty( $setting['multiple'] ) && $setting['multiple'] ) { 
  290. $save_value = array(); 
  291. } else { 
  292. $save_value = ''; 
  293. if ( ! empty( $value ) && is_array( $value ) ) { 
  294. if ( $setting['multiple'] ) { 
  295. foreach ( $value as $vid => $vname ) { 
  296. foreach( $setting['options'] as $key => $option ) { 
  297. if ( $key === $vname ) { 
  298. $save_value[] = $key; 
  299. break; 
  300. } else { 
  301. foreach( $setting['options'] as $key => $option ) { 
  302. if ( is_array( $value ) && in_array( $key, $value ) ) { 
  303. $save_value = $key; 
  304. break; 
  305. } else if ( is_string( $value ) && $key === $value ) { 
  306. $save_value = $key; 
  307. break; 
  308. return $save_value; 
  309. add_filter( 'monsterinsights_settings_sanitize_select', 'monsterinsights_sanitize_select_field', 10, 4 ); 
  310.  
  311.  
  312. /** 
  313. * Sanitize radio fields 
  314. * 
  315. * @since 6.0.0 
  316. * @todo docbloc 
  317. */ 
  318. function monsterinsights_sanitize_radio_field( $value, $id, $setting, $previous_value ) { 
  319. $save_value = ''; 
  320. if ( ! empty( $value ) ) { 
  321. foreach( $setting['options'] as $key => $option ) { 
  322. if ( $key === $value ) { 
  323. $save_value = $key; 
  324. return $save_value; 
  325. add_filter( 'monsterinsights_settings_sanitize_radio', 'monsterinsights_sanitize_radio_field', 10, 4 ); 
  326.  
  327. /** 
  328. * Sanitize text fields 
  329. * 
  330. * @since 6.0.0 
  331. * @todo docbloc 
  332. */ 
  333. function monsterinsights_sanitize_text_field( $value, $id, $setting, $previous_value ) { 
  334. return sanitize_text_field( $value ); 
  335. add_filter( 'monsterinsights_settings_sanitize_text', 'monsterinsights_sanitize_text_field', 10, 4 ); 
  336.  
  337. /** 
  338. * Sanitize password fields 
  339. * 
  340. * @since 6.0.0 
  341. * @todo docbloc 
  342. */ 
  343. function monsterinsights_sanitize_password_field( $value, $id, $setting, $previous_value ) { 
  344. return sanitize_text_field( $value ); 
  345. add_filter( 'monsterinsights_settings_sanitize_password', 'monsterinsights_sanitize_password_field', 10, 4 ); 
  346.  
  347. /** 
  348. * Sanitize number fields 
  349. * 
  350. * @since 6.0.0 
  351. * @todo docbloc 
  352. */ 
  353. function monsterinsights_sanitize_number_field( $value, $id, $setting, $previous_value ) { 
  354. if ( is_int( (int) $value ) ) { 
  355. return $int; 
  356. } else if ( is_int( $previous_value ) ) { 
  357. return $previous_value; 
  358. } else { 
  359. return 0; 
  360. add_filter( 'monsterinsights_settings_sanitize_number', 'monsterinsights_sanitize_number_field', 10, 4 ); 
  361.  
  362. /** 
  363. * Sanitize unfiltered textarea fields 
  364. * 
  365. * @since 6.0.0 
  366. * @todo docbloc 
  367. */ 
  368. function monsterinsights_sanitize_unfiltered_textarea_field( $value, $id, $setting, $previous_value ) { 
  369. if ( current_user_can( 'unfiltered_html' ) || current_user_can( 'monsterinsights_unfiltered_html' ) ) { 
  370. return $value; 
  371. } else { 
  372. return $previous_value; 
  373. add_filter( 'monsterinsights_settings_unfiltered_textarea_number', 'monsterinsights_sanitize_unfiltered_textarea_field', 10, 4 ); 
  374.  
  375. /** 
  376. * Sanitizes a string key for MonsterInsights Settings 
  377. * 
  378. * Keys are used as internal identifiers. Alphanumeric characters, dashes, underscores, stops, colons and slashes are allowed 
  379. * 
  380. * @since 6.0.0 
  381. * @param string $key String key 
  382. * @return string Sanitized key 
  383. */ 
  384. function monsterinsights_sanitize_key( $key ) { 
  385. $raw_key = $key; 
  386. $key = preg_replace( '/[^a-zA-Z0-9_\-\.\:\/]/', '', $key ); 
  387. /** 
  388. * Filter a sanitized key string. 
  389. * 
  390. * @since 6.0.0 
  391. * @param string $key Sanitized key. 
  392. * @param string $raw_key The key prior to sanitization. 
  393. */ 
  394. return apply_filters( 'monsterinsights_sanitize_key', $key, $raw_key ); 
  395.  
  396. /** 
  397. * Sanitize HTML Class Names 
  398. * 
  399. * @since 6.0.0 
  400. * @param string|array $class HTML Class Name(s) 
  401. * @return string $class 
  402. */ 
  403. function monsterinsights_sanitize_html_class( $class = '' ) { 
  404.  
  405. if ( is_string( $class ) ) { 
  406. $class = sanitize_html_class( $class ); 
  407. } else if ( is_array( $class ) ) { 
  408. $class = array_values( array_map( 'sanitize_html_class', $class ) ); 
  409. $class = implode( ' ', array_unique( $class ) ); 
  410.  
  411. return $class; 
  412.  
  413.  
  414. /** 
  415. * Retrieve a list of all published pages 
  416. * 
  417. * On large sites this can be expensive, so only load if on the settings page or $force is set to true 
  418. * 
  419. * @since 6.0.0 
  420. * @param bool $force Force the pages to be loaded even if not on settings 
  421. * @return array $pages_options An array of the pages 
  422. */ 
  423. function monsterinsights_get_pages( $force = false ) { 
  424. $pages_options = array( '' => '' ); // Blank option 
  425. if( ( ! isset( $_GET['page'] ) || 'monsterinsights_settings' != $_GET['page'] ) && ! $force ) { 
  426. return $pages_options; 
  427.  
  428. $pages = get_pages(); 
  429. if ( $pages ) { 
  430. foreach ( $pages as $page ) { 
  431. $pages_options[ $page->ID ] = $page->post_title; 
  432.  
  433. return $pages_options; 
  434.  
  435. /** 
  436. * Checkbox Callback 
  437. * 
  438. * Renders checkboxes. 
  439. * 
  440. * @since 6.0.0 
  441. * @param array $args Arguments passed by the setting 
  442. * 
  443. * @return void 
  444. */ 
  445. function monsterinsights_checkbox_callback( $args ) { 
  446. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  447.  
  448. if ( isset( $args['faux'] ) && true === $args['faux'] ) { 
  449. $name = ''; 
  450. } else { 
  451. $name = 'name="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']"'; 
  452.  
  453. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  454.  
  455. $checked = ! empty( $monsterinsights_option ) ? checked( 1, $monsterinsights_option, false ) : ''; 
  456. $html = '<input type="checkbox" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']"' . $name . ' value="1" ' . $checked . ' class="' . $class . '"/>'; 
  457. $html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>'; 
  458.  
  459. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  460.  
  461. /** 
  462. * Multicheck Callback 
  463. * 
  464. * Renders multiple checkboxes. 
  465. * 
  466. * @since 6.0.0 
  467. * @param array $args Arguments passed by the setting 
  468. * 
  469. * @return void 
  470. */ 
  471. function monsterinsights_multicheck_callback( $args ) { 
  472. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  473.  
  474. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  475.  
  476. $html = ''; 
  477. if ( ! empty( $args['options'] ) ) { 
  478. foreach( $args['options'] as $key => $option ): 
  479. if( isset( $monsterinsights_option[ $key ] ) ) { $enabled = $option; } else { $enabled = NULL; } 
  480. $html .= '<input name="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . '][' . monsterinsights_sanitize_key( $key ) . ']" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . '][' . monsterinsights_sanitize_key( $key ) . ']" class="' . $class . '" type="checkbox" value="' . esc_attr( $option ) . '" ' . checked($option, $enabled, false) . '/> '; 
  481. $html .= '<label for="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . '][' . monsterinsights_sanitize_key( $key ) . ']">' . wp_kses_post( $option ) . '</label><br/>'; 
  482. endforeach; 
  483. $html .= '<p class="description">' . $args['desc'] . '</p>'; 
  484.  
  485. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  486.  
  487.  
  488. /** 
  489. * Radio Callback 
  490. * 
  491. * Renders radio boxes. 
  492. * 
  493. * @since 6.0.0 
  494. * @param array $args Arguments passed by the setting 
  495. * 
  496. * @return void 
  497. */ 
  498. function monsterinsights_radio_callback( $args ) { 
  499. $monsterinsights_options = monsterinsights_get_option( $args['id'] ); 
  500.  
  501. $html = ''; 
  502.  
  503. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  504.  
  505. foreach ( $args['options'] as $key => $option ) : 
  506. $checked = false; 
  507.  
  508. if ( $monsterinsights_options && $monsterinsights_options == $key ) { 
  509. $checked = true; 
  510. } else if( isset( $args['std'] ) && $args['std'] == $key && ! $monsterinsights_options ) { 
  511. $checked = true; 
  512.  
  513. $html .= '<label for="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . '][' . monsterinsights_sanitize_key( $key ) . ']">'; 
  514. $html .= '<input name="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . '][' . monsterinsights_sanitize_key( $key ) . ']" class="' . $class . '" type="radio" value="' . monsterinsights_sanitize_key( $key ) . '" ' . checked(true, $checked, false) . '/> '; 
  515. $html .= esc_html( $option ) . '</label>'; 
  516. endforeach; 
  517.  
  518. $html .= '<p class="description">' . apply_filters( 'monsterinsights_after_setting_output', wp_kses_post( $args['desc'] ), $args ) . '</p>'; 
  519.  
  520. return $html; 
  521.  
  522. /** 
  523. * Text Callback 
  524. * 
  525. * Renders text fields. 
  526. * 
  527. * @since 6.0.0 
  528. * @param array $args Arguments passed by the setting 
  529. * 
  530. * @return void 
  531. */ 
  532. function monsterinsights_text_callback( $args ) { 
  533. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  534.  
  535. if ( $monsterinsights_option ) { 
  536. $value = $monsterinsights_option; 
  537. } elseif( ! empty( $args['allow_blank'] ) && empty( $monsterinsights_option ) ) { 
  538. $value = ''; 
  539. } else { 
  540. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  541.  
  542. if ( isset( $args['faux'] ) && true === $args['faux'] ) { 
  543. $args['readonly'] = true; 
  544. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  545. $name = ''; 
  546. } else { 
  547. $name = 'name="monsterinsights_settings[' . esc_attr( $args['id'] ) . ']"'; 
  548.  
  549. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  550.  
  551. $disabled = ! empty( $args['disabled'] ) ? ' disabled="disabled"' : ''; 
  552. $readonly = $args['readonly'] === true ? ' readonly="readonly"' : ''; 
  553. $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular'; 
  554. $html = '<input type="text" class="' . $class . ' ' . sanitize_html_class( $size ) . '-text" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']" ' . $name . ' value="' . esc_attr( stripslashes( $value ) ) . '"' . $readonly . $disabled . ' placeholder="' . esc_attr( $args['placeholder'] ) . '"/>'; 
  555. $html .= '<p class="description"> ' . wp_kses_post( $args['desc'] ) . '</p>'; 
  556.  
  557. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  558.  
  559. /** 
  560. * Number Callback 
  561. * 
  562. * Renders number fields. 
  563. * 
  564. * @since 6.0.0 
  565. * @param array $args Arguments passed by the setting 
  566. * 
  567. * @return void 
  568. */ 
  569. function monsterinsights_number_callback( $args ) { 
  570. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  571.  
  572. if ( $monsterinsights_option ) { 
  573. $value = $monsterinsights_option; 
  574. } else { 
  575. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  576.  
  577. if ( isset( $args['faux'] ) && true === $args['faux'] ) { 
  578. $args['readonly'] = true; 
  579. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  580. $name = ''; 
  581. } else { 
  582. $name = 'name="monsterinsights_settings[' . esc_attr( $args['id'] ) . ']"'; 
  583.  
  584. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  585.  
  586. $max = isset( $args['max'] ) ? $args['max'] : 999999; 
  587. $min = isset( $args['min'] ) ? $args['min'] : 0; 
  588. $step = isset( $args['step'] ) ? $args['step'] : 1; 
  589.  
  590. $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular'; 
  591. $html = '<input type="number" step="' . esc_attr( $step ) . '" max="' . esc_attr( $max ) . '" min="' . esc_attr( $min ) . '" class="' . $class . ' ' . sanitize_html_class( $size ) . '-text" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']" ' . $name . ' value="' . esc_attr( stripslashes( $value ) ) . '"/>'; 
  592. $html .= '<p class="description"> ' . wp_kses_post( $args['desc'] ) . '</p>'; 
  593.  
  594. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  595.  
  596. /** 
  597. * Textarea Callback 
  598. * 
  599. * Renders textarea fields. 
  600. * 
  601. * @since 6.0.0 
  602. * @param array $args Arguments passed by the setting 
  603. * 
  604. * @return void 
  605. */ 
  606. function monsterinsights_textarea_callback( $args ) { 
  607. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  608.  
  609. if ( $monsterinsights_option ) { 
  610. $value = $monsterinsights_option; 
  611. } else { 
  612. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  613.  
  614. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  615.  
  616. $html = '<textarea class="' . $class . ' large-text" cols="50" rows="5" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']" name="monsterinsights_settings[' . esc_attr( $args['id'] ) . ']">' . esc_textarea( stripslashes( $value ) ) . '</textarea>'; 
  617. $html .= '<p class="description"> ' . wp_kses_post( $args['desc'] ) . '</p>'; 
  618.  
  619. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  620.  
  621.  
  622. /** 
  623. * Unfiltered Textarea Callback 
  624. * 
  625. * Renders unfiltered textarea fields. 
  626. * 
  627. * @since 6.0.0 
  628. * @param array $args Arguments passed by the setting 
  629. * 
  630. * @return void 
  631. */ 
  632. function monsterinsights_unfiltered_textarea_callback( $args ) { 
  633.  
  634. if ( current_user_can( 'unfiltered_html' ) || current_user_can( 'monsterinsights_unfiltered_html' ) ) { 
  635. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  636.  
  637. if ( $monsterinsights_option ) { 
  638. $value = $monsterinsights_option; 
  639. } else { 
  640. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  641.  
  642. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  643.  
  644. $html = '<textarea class="' . $class . ' large-text" cols="50" rows="5" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']" name="monsterinsights_settings[' . esc_attr( $args['id'] ) . ']">' . stripslashes( $value ) . '</textarea>'; 
  645. $html .= '<p class="description"> ' . wp_kses_post( $args['desc'] ) . '</p>'; 
  646. } else { 
  647. $html .= sprintf( esc_html__( 'You must have the %s capability to view/edit this setting', 'google-analytics-for-wordpress' ), '"unfiltered_html"' ); 
  648.  
  649. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  650.  
  651. /** 
  652. * Password Callback 
  653. * 
  654. * Renders password fields. 
  655. * 
  656. * @since 6.0.0 
  657. * @param array $args Arguments passed by the setting 
  658. * 
  659. * @return void 
  660. */ 
  661. function monsterinsights_password_callback( $args ) { 
  662. $monsterinsights_options = monsterinsights_get_option( $args['id'] ); 
  663.  
  664. if ( $monsterinsights_options ) { 
  665. $value = $monsterinsights_options; 
  666. } else { 
  667. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  668.  
  669. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  670.  
  671. $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular'; 
  672. $html = '<input type="password" class="' . $class . ' ' . sanitize_html_class( $size ) . '-text" id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']" name="monsterinsights_settings[' . esc_attr( $args['id'] ) . ']" value="' . esc_attr( $value ) . '"/>'; 
  673. $html .= '<p class="description"> ' . wp_kses_post( $args['desc'] ) . '</p>'; 
  674.  
  675. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  676.  
  677. /** 
  678. * Select Callback 
  679. * 
  680. * Renders select fields. 
  681. * 
  682. * @since 6.0.0 
  683. * @param array $args Arguments passed by the setting 
  684. * 
  685. * @return void 
  686. */ 
  687. function monsterinsights_select_callback($args) { 
  688. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  689.  
  690. if ( $monsterinsights_option ) { 
  691. $value = $monsterinsights_option; 
  692. } else { 
  693. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  694.  
  695. if ( isset( $args['placeholder'] ) ) { 
  696. $placeholder = $args['placeholder']; 
  697. } else { 
  698. $placeholder = ''; 
  699.  
  700. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  701.  
  702. if ( isset( $args['select2'] ) ) { 
  703. $class .= ' monsterinsights-select300'; 
  704.  
  705. $allowclear = isset( $args['allowclear'] ) ? (bool) $args['allowclear'] : false; 
  706. $multiple = isset( $args['multiple'] ) ? (bool) $args['multiple'] : false; 
  707. $multiple = $multiple ? 'multiple="multiple"' : ''; 
  708. $multiple_arg = $multiple ? '[]' : ''; 
  709.  
  710. $html = '<select id="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']" name="monsterinsights_settings[' . esc_attr( $args['id'] ) . ']' . $multiple_arg .'" class="' . $class . '" data-placeholder="' . esc_html( $placeholder ) . '" data-allow-clear="' . $allowclear . '" ' . $multiple . ' />'; 
  711.  
  712. foreach ( $args['options'] as $option => $name ) { 
  713. $selected = ! empty( $value ) && is_array( $value ) ? in_array( $option, $value ) : $value === $option; 
  714. $selected = selected( true, $selected, false ); 
  715. $html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( $name ) . '</option>'; 
  716.  
  717. $html .= '</select>'; 
  718. $html .= '<p class="description"> ' . wp_kses_post( $args['desc'] ) . '</p>'; 
  719.  
  720. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  721.  
  722. /** 
  723. * Rich Editor Callback 
  724. * 
  725. * Renders rich editor fields. 
  726. * 
  727. * @since 6.0.0 
  728. * @param array $args Arguments passed by the setting 
  729. */ 
  730. function monsterinsights_rich_editor_callback( $args ) { 
  731. $monsterinsights_option = monsterinsights_get_option( $args['id'] ); 
  732.  
  733. if ( $monsterinsights_option ) { 
  734. $value = $monsterinsights_option; 
  735. } else { 
  736. if( ! empty( $args['allow_blank'] ) && empty( $monsterinsights_option ) ) { 
  737. $value = ''; 
  738. } else { 
  739. $value = isset( $args['std'] ) ? $args['std'] : ''; 
  740.  
  741. $rows = isset( $args['size'] ) ? $args['size'] : 20; 
  742.  
  743. $class = monsterinsights_sanitize_html_class( $args['field_class'] ); 
  744.  
  745. ob_start(); 
  746. wp_editor( stripslashes( $value ), 'monsterinsights_settings_' . esc_attr( $args['id'] ), array( 'textarea_name' => 'monsterinsights_settings[' . esc_attr( $args['id'] ) . ']', 'textarea_rows' => absint( $rows ), 'editor_class' => $class ) ); 
  747. $html = ob_get_clean(); 
  748.  
  749. $html .= '<br/><p class="description"> ' . wp_kses_post( $args['desc'] ) . '</p>'; 
  750.  
  751. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  752.  
  753. /** 
  754. * Descriptive text callback. 
  755. * 
  756. * Renders descriptive text onto the settings field. 
  757. * 
  758. * @since 6.0.0 
  759. * @param array $args Arguments passed by the setting 
  760. * @return void 
  761. */ 
  762. function monsterinsights_descriptive_text_callback( $args ) { 
  763. $html = wp_kses_post( $args['desc'] ); 
  764. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  765.  
  766. /** 
  767. * Notice Callback 
  768. * 
  769. * Renders notice fields. 
  770. * 
  771. * @since 6.0.0 
  772. * @param array $args Arguments passed by the setting 
  773. * 
  774. * @return void 
  775. */ 
  776. function monsterinsights_notice_callback( $args ) { 
  777. $html = monsterinsights_get_message( $args['notice_type'], $args['desc'] ); 
  778. return apply_filters( 'monsterinsights_after_setting_output', $html, $args ); 
  779.  
  780. /** 
  781. * Upgrade Notice Callback 
  782. * 
  783. * Renders upgrade notice fields. 
  784. * 
  785. * @since 6.1.7 
  786. * @param array $args Arguments passed by the setting 
  787. * 
  788. * @return void 
  789. */ 
  790. function monsterinsights_upgrade_notice_callback( $args ) { 
  791. $html = '<div class="monsterinsights-upsell-box"><h2>' . esc_html( $args['name' ] ) . '</h2>' 
  792. . '<p class="upsell-lite">' . $args['desc'] . '</p>' 
  793. . '</div>'; 
  794. return apply_filters( 'monsterinsights_after_setting_output', $html, $args );  
  795.  
  796. /** 
  797. * Hook Callback 
  798. * 
  799. * Adds a do_action() hook in place of the field 
  800. * 
  801. * @since 6.0.0 
  802. * @param array $args Arguments passed by the setting 
  803. * @return void 
  804. */ 
  805. function monsterinsights_hook_callback( $args ) { 
  806. do_action( 'monsterinsights_' . $args['id'], $args ); 
  807. return ''; 
  808.  
  809. /** 
  810. * Missing Callback 
  811. * 
  812. * If a function is missing for settings callbacks alert the user. 
  813. * 
  814. * @since 6.0.0 
  815. * @param array $args Arguments passed by the setting 
  816. * @return void 
  817. */ 
  818. function monsterinsights_missing_callback($args) { 
  819. return sprintf( 
  820. __( 'The callback function used for the %s setting is missing.', 'google-analytics-for-wordpress' ),  
  821. '<strong>' . $args['id'] . '</strong>' 
  822. ); 
  823.  
  824. /** 
  825. * Render Submit Button 
  826. * 
  827. * If there's a saveable field on the page, show save button. 
  828. * 
  829. * @since 6.0.0 
  830. * @param array $args Arguments passed by the setting 
  831. * @return void 
  832. */ 
  833. function monsterinsights_render_submit_field( $section, $page = 'tracking' ) { 
  834. $html = ''; 
  835. $settings = monsterinsights_get_registered_settings(); 
  836. if ( is_array( $settings ) && ! empty( $settings[$section] ) && is_array( $settings[$section] ) ) { 
  837. $non_setting_types = monsterinsights_get_non_setting_types(); 
  838. $submit_button = false; 
  839. foreach ( $settings[$section] as $setting ) { 
  840. if ( ! empty( $non_setting_types ) && ! empty( $setting['type'] ) && ! in_array( $setting['type'], $non_setting_types ) ) { 
  841. $submit_button = true; 
  842. break; 
  843. if ( $submit_button ) { 
  844. $html .= '<input type="hidden" name="monsterinsights_settings_tab" value="' . esc_attr( $page ). '"/>'; 
  845. $html .= '<input type="hidden" name="monsterinsights_settings_sub_tab" value="' . esc_attr( $section ) . '"/>'; 
  846. $html .= wp_nonce_field( 'monsterinsights-settings-nonce', 'monsterinsights-settings-nonce', true, false ); 
  847. $html .= get_submit_button( esc_html__( 'Save Changes', 'google-analytics-for-wordpress' ), 'primary', 'monsterinsights-settings-submit', false ); 
  848. return $html; 
  849.  
  850. /**  
  851. * @todo docbloc 
  852. */ 
  853. function monsterinsights_render_field( $args ) { 
  854. $output = ''; 
  855. $output .='<tr id="monsterinsights-input-' . monsterinsights_sanitize_key( $args['id'] ) .'">'; 
  856. if ( ! empty( $args['name'] ) ) { 
  857. $output .= '<th scope="row">'; 
  858. $output .='<label for="monsterinsights_settings[' . monsterinsights_sanitize_key( $args['id'] ) . ']">' . esc_html( $args["name"] ) . '</label>'; 
  859. $output .= '</th>'; 
  860. $output .= '<td>'; 
  861. $render = ! empty( $args['type'] ) && function_exists( 'monsterinsights_' . $args['type'] . '_callback' ) ? 'monsterinsights_' . $args['type'] . '_callback' : 'monsterinsights_missing_callback'; 
  862. $output .= call_user_func( $render, $args ); 
  863. $output .= '</td>'; 
  864. $output .= '</tr>'; 
  865. return $output; 
  866.  
  867. /**  
  868. * @todo docbloc 
  869. */ 
  870. function monsterinsights_add_setting_tooltip( $html, $args ) { // @todo: enqueue tooltips 
  871.  
  872. if ( ! empty( $args['tooltip_title'] ) && ! empty( $args['tooltip_desc'] ) ) { 
  873. $tooltip = '<span alt="f223" class="monsterinsights-help-tip dashicons dashicons-editor-help" title="<strong>' . $args['tooltip_title'] . '</strong>: ' . $args['tooltip_desc'] . '"></span>'; 
  874. $html .= $tooltip; 
  875.  
  876. return $html; 
  877. add_filter( 'monsterinsights_after_setting_output', 'monsterinsights_add_setting_tooltip', 10, 2 ); 
  878.  
  879. /**  
  880. * @todo docbloc 
  881. */ 
  882. function monsterinsights_get_settings_notices( $delete_on_retrieve = true ) { 
  883. $notices = get_transient( 'monsterinsights_settings_notices' ); 
  884. if ( $delete_on_retrieve ) { 
  885. delete_transient( 'monsterinsights_settings_notices' ); 
  886. return $notices; 
  887.  
  888. /**  
  889. * @todo docbloc 
  890. */ 
  891. function monsterinsights_add_settings_notice( $name, $type = 'success', $message = '' ) { 
  892. $notices = get_transient( 'monsterinsights_settings_notices' ); 
  893. if ( empty( $notices ) ) { 
  894. $notices = array(); 
  895. $notices[ $name ] = array( "type" => $type, "message" => $message ); 
  896. } else { 
  897. $notices[ $name ] = array( "type" => $type, "message" => $message ); 
  898. set_transient( 'monsterinsights_settings_notices', $notices ); 
  899.  
  900. /**  
  901. * @todo docbloc 
  902. */ 
  903. function monsterinsights_remove_settings_notice( $name ) { 
  904. $notices = get_transient( 'monsterinsights_settings_notices' ); 
  905. $found = false; 
  906. if ( ! empty( $notices ) ) { 
  907. if ( isset( $notices[ $name] ) ) { 
  908. unset( $notices[ $name] ); 
  909. set_transient( 'monsterinsights_settings_notices', $notices ); 
  910. $found = true; 
  911. } else { 
  912. set_transient( 'monsterinsights_settings_notices', $notices ); 
  913. return $found; 
  914.  
  915. /**  
  916. * @todo docbloc 
  917. */ 
  918. function monsterinsights_get_non_setting_types() { 
  919. return apply_filters( 'monsterinsights_non_setting_types', array( 'descriptive_text', 'hook', 'upgrade_notice', 'install_notice', 'notice' ) ); 
.