PageRenderTime 47ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/class-wp-customize-setting.php

https://gitlab.com/Blueprint-Marketing/WordPress-1
PHP | 439 lines | 195 code | 58 blank | 186 comment | 37 complexity | bff766d2d4ac6a408e90e5860db59dcd MD5 | raw file
  1. <?php
  2. /**
  3. * Customize Setting Class.
  4. *
  5. * @package WordPress
  6. * @subpackage Customize
  7. * @since 3.4.0
  8. */
  9. class WP_Customize_Setting {
  10. public $manager;
  11. public $id;
  12. public $type = 'theme_mod';
  13. public $capability = 'edit_theme_options';
  14. public $theme_supports = '';
  15. public $default = '';
  16. public $transport = 'refresh';
  17. public $sanitize_callback = '';
  18. public $sanitize_js_callback = '';
  19. protected $id_data = array();
  20. private $_post_value; // Cached, sanitized $_POST value.
  21. /**
  22. * Constructor.
  23. *
  24. * @since 3.4.0
  25. *
  26. * @param WP_Customize_Manager $manager
  27. * @param string $id An specific ID of the setting. Can be a
  28. * theme mod or option name.
  29. * @param array $args Setting arguments.
  30. * @return WP_Customize_Setting
  31. */
  32. function __construct( $manager, $id, $args = array() ) {
  33. $keys = array_keys( get_class_vars( __CLASS__ ) );
  34. foreach ( $keys as $key ) {
  35. if ( isset( $args[ $key ] ) )
  36. $this->$key = $args[ $key ];
  37. }
  38. $this->manager = $manager;
  39. $this->id = $id;
  40. // Parse the ID for array keys.
  41. $this->id_data[ 'keys' ] = preg_split( '/\[/', str_replace( ']', '', $this->id ) );
  42. $this->id_data[ 'base' ] = array_shift( $this->id_data[ 'keys' ] );
  43. // Rebuild the ID.
  44. $this->id = $this->id_data[ 'base' ];
  45. if ( ! empty( $this->id_data[ 'keys' ] ) )
  46. $this->id .= '[' . implode( '][', $this->id_data[ 'keys' ] ) . ']';
  47. if ( $this->sanitize_callback )
  48. add_filter( "customize_sanitize_{$this->id}", $this->sanitize_callback, 10, 2 );
  49. if ( $this->sanitize_js_callback )
  50. add_filter( "customize_sanitize_js_{$this->id}", $this->sanitize_js_callback, 10, 2 );
  51. return $this;
  52. }
  53. /**
  54. * Handle previewing the setting.
  55. *
  56. * @since 3.4.0
  57. */
  58. public function preview() {
  59. switch( $this->type ) {
  60. case 'theme_mod' :
  61. add_filter( 'theme_mod_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) );
  62. break;
  63. case 'option' :
  64. if ( empty( $this->id_data[ 'keys' ] ) )
  65. add_filter( 'pre_option_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) );
  66. else {
  67. add_filter( 'option_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) );
  68. add_filter( 'default_option_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) );
  69. }
  70. break;
  71. default :
  72. do_action( 'customize_preview_' . $this->id );
  73. }
  74. }
  75. /**
  76. * Callback function to filter the theme mods and options.
  77. *
  78. * @since 3.4.0
  79. * @uses WP_Customize_Setting::multidimensional_replace()
  80. *
  81. * @param mixed $original Old value.
  82. * @return mixed New or old value.
  83. */
  84. public function _preview_filter( $original ) {
  85. return $this->multidimensional_replace( $original, $this->id_data[ 'keys' ], $this->post_value() );
  86. }
  87. /**
  88. * Set the value of the parameter for a specific theme.
  89. *
  90. * @since 3.4.0
  91. *
  92. * @return bool False if cap check fails or value isn't set.
  93. */
  94. public final function save() {
  95. $value = $this->post_value();
  96. if ( ! $this->check_capabilities() || ! isset( $value ) )
  97. return false;
  98. do_action( 'customize_save_' . $this->id_data[ 'base' ] );
  99. $this->update( $value );
  100. }
  101. /**
  102. * Fetches, validates, and sanitizes the $_POST value.
  103. *
  104. * @since 3.4.0
  105. *
  106. * @param mixed $default A default value which is used as a fallback. Default is null.
  107. * @return mixed The default value on failure, otherwise the sanitized value.
  108. */
  109. public final function post_value( $default = null ) {
  110. if ( isset( $this->_post_value ) )
  111. return $this->_post_value;
  112. $result = $this->manager->post_value( $this );
  113. if ( isset( $result ) )
  114. return $this->_post_value = $result;
  115. else
  116. return $default;
  117. }
  118. /**
  119. * Sanitize an input.
  120. *
  121. * @since 3.4.0
  122. *
  123. * @param mixed $value The value to sanitize.
  124. * @return mixed Null if an input isn't valid, otherwise the sanitized value.
  125. */
  126. public function sanitize( $value ) {
  127. $value = wp_unslash( $value );
  128. return apply_filters( "customize_sanitize_{$this->id}", $value, $this );
  129. }
  130. /**
  131. * Set the value of the parameter for a specific theme.
  132. *
  133. * @since 3.4.0
  134. *
  135. * @param mixed $value The value to update.
  136. * @return mixed The result of saving the value.
  137. */
  138. protected function update( $value ) {
  139. switch( $this->type ) {
  140. case 'theme_mod' :
  141. return $this->_update_theme_mod( $value );
  142. break;
  143. case 'option' :
  144. return $this->_update_option( $value );
  145. break;
  146. default :
  147. return do_action( 'customize_update_' . $this->type, $value );
  148. }
  149. }
  150. /**
  151. * Update the theme mod from the value of the parameter.
  152. *
  153. * @since 3.4.0
  154. *
  155. * @param mixed $value The value to update.
  156. * @return mixed The result of saving the value.
  157. */
  158. protected function _update_theme_mod( $value ) {
  159. // Handle non-array theme mod.
  160. if ( empty( $this->id_data[ 'keys' ] ) )
  161. return set_theme_mod( $this->id_data[ 'base' ], $value );
  162. // Handle array-based theme mod.
  163. $mods = get_theme_mod( $this->id_data[ 'base' ] );
  164. $mods = $this->multidimensional_replace( $mods, $this->id_data[ 'keys' ], $value );
  165. if ( isset( $mods ) )
  166. return set_theme_mod( $this->id_data[ 'base' ], $mods );
  167. }
  168. /**
  169. * Update the theme mod from the value of the parameter.
  170. *
  171. * @since 3.4.0
  172. *
  173. * @param mixed $value The value to update.
  174. * @return mixed The result of saving the value.
  175. */
  176. protected function _update_option( $value ) {
  177. // Handle non-array option.
  178. if ( empty( $this->id_data[ 'keys' ] ) )
  179. return update_option( $this->id_data[ 'base' ], $value );
  180. // Handle array-based options.
  181. $options = get_option( $this->id_data[ 'base' ] );
  182. $options = $this->multidimensional_replace( $options, $this->id_data[ 'keys' ], $value );
  183. if ( isset( $options ) )
  184. return update_option( $this->id_data[ 'base' ], $options );
  185. }
  186. /**
  187. * Fetch the value of the parameter for a specific theme.
  188. *
  189. * @since 3.4.0
  190. *
  191. * @return mixed The requested value.
  192. */
  193. public function value() {
  194. switch( $this->type ) {
  195. case 'theme_mod' :
  196. $function = 'get_theme_mod';
  197. break;
  198. case 'option' :
  199. $function = 'get_option';
  200. break;
  201. default :
  202. return apply_filters( 'customize_value_' . $this->id_data[ 'base' ], $this->default );
  203. }
  204. // Handle non-array value
  205. if ( empty( $this->id_data[ 'keys' ] ) )
  206. return $function( $this->id_data[ 'base' ], $this->default );
  207. // Handle array-based value
  208. $values = $function( $this->id_data[ 'base' ] );
  209. return $this->multidimensional_get( $values, $this->id_data[ 'keys' ], $this->default );
  210. }
  211. /**
  212. * Escape the parameter's value for use in JavaScript.
  213. *
  214. * @since 3.4.0
  215. *
  216. * @return mixed The requested escaped value.
  217. */
  218. public function js_value() {
  219. $value = apply_filters( "customize_sanitize_js_{$this->id}", $this->value(), $this );
  220. if ( is_string( $value ) )
  221. return html_entity_decode( $value, ENT_QUOTES, 'UTF-8');
  222. return $value;
  223. }
  224. /**
  225. * Check if the theme supports the setting and check user capabilities.
  226. *
  227. * @since 3.4.0
  228. *
  229. * @return bool False if theme doesn't support the setting or user can't change setting, otherwise true.
  230. */
  231. public final function check_capabilities() {
  232. if ( $this->capability && ! call_user_func_array( 'current_user_can', (array) $this->capability ) )
  233. return false;
  234. if ( $this->theme_supports && ! call_user_func_array( 'current_theme_supports', (array) $this->theme_supports ) )
  235. return false;
  236. return true;
  237. }
  238. /**
  239. * Multidimensional helper function.
  240. *
  241. * @since 3.4.0
  242. *
  243. * @param $root
  244. * @param $keys
  245. * @param bool $create Default is false.
  246. * @return null|array Keys are 'root', 'node', and 'key'.
  247. */
  248. final protected function multidimensional( &$root, $keys, $create = false ) {
  249. if ( $create && empty( $root ) )
  250. $root = array();
  251. if ( ! isset( $root ) || empty( $keys ) )
  252. return;
  253. $last = array_pop( $keys );
  254. $node = &$root;
  255. foreach ( $keys as $key ) {
  256. if ( $create && ! isset( $node[ $key ] ) )
  257. $node[ $key ] = array();
  258. if ( ! is_array( $node ) || ! isset( $node[ $key ] ) )
  259. return;
  260. $node = &$node[ $key ];
  261. }
  262. if ( $create && ! isset( $node[ $last ] ) )
  263. $node[ $last ] = array();
  264. if ( ! isset( $node[ $last ] ) )
  265. return;
  266. return array(
  267. 'root' => &$root,
  268. 'node' => &$node,
  269. 'key' => $last,
  270. );
  271. }
  272. /**
  273. * Will attempt to replace a specific value in a multidimensional array.
  274. *
  275. * @since 3.4.0
  276. *
  277. * @param $root
  278. * @param $keys
  279. * @param mixed $value The value to update.
  280. * @return
  281. */
  282. final protected function multidimensional_replace( $root, $keys, $value ) {
  283. if ( ! isset( $value ) )
  284. return $root;
  285. elseif ( empty( $keys ) ) // If there are no keys, we're replacing the root.
  286. return $value;
  287. $result = $this->multidimensional( $root, $keys, true );
  288. if ( isset( $result ) )
  289. $result['node'][ $result['key'] ] = $value;
  290. return $root;
  291. }
  292. /**
  293. * Will attempt to fetch a specific value from a multidimensional array.
  294. *
  295. * @since 3.4.0
  296. *
  297. * @param $root
  298. * @param $keys
  299. * @param $default A default value which is used as a fallback. Default is null.
  300. * @return mixed The requested value or the default value.
  301. */
  302. final protected function multidimensional_get( $root, $keys, $default = null ) {
  303. if ( empty( $keys ) ) // If there are no keys, test the root.
  304. return isset( $root ) ? $root : $default;
  305. $result = $this->multidimensional( $root, $keys );
  306. return isset( $result ) ? $result['node'][ $result['key'] ] : $default;
  307. }
  308. /**
  309. * Will attempt to check if a specific value in a multidimensional array is set.
  310. *
  311. * @since 3.4.0
  312. *
  313. * @param $root
  314. * @param $keys
  315. * @return bool True if value is set, false if not.
  316. */
  317. final protected function multidimensional_isset( $root, $keys ) {
  318. $result = $this->multidimensional_get( $root, $keys );
  319. return isset( $result );
  320. }
  321. }
  322. /**
  323. * A setting that is used to filter a value, but will not save the results.
  324. *
  325. * Results should be properly handled using another setting or callback.
  326. *
  327. * @package WordPress
  328. * @subpackage Customize
  329. * @since 3.4.0
  330. */
  331. class WP_Customize_Filter_Setting extends WP_Customize_Setting {
  332. /**
  333. * @since 3.4.0
  334. */
  335. public function update( $value ) {}
  336. }
  337. /**
  338. * A setting that is used to filter a value, but will not save the results.
  339. *
  340. * Results should be properly handled using another setting or callback.
  341. *
  342. * @package WordPress
  343. * @subpackage Customize
  344. * @since 3.4.0
  345. */
  346. final class WP_Customize_Header_Image_Setting extends WP_Customize_Setting {
  347. public $id = 'header_image_data';
  348. /**
  349. * @since 3.4.0
  350. *
  351. * @param $value
  352. */
  353. public function update( $value ) {
  354. global $custom_image_header;
  355. // If the value doesn't exist (removed or random),
  356. // use the header_image value.
  357. if ( ! $value )
  358. $value = $this->manager->get_setting('header_image')->post_value();
  359. if ( is_array( $value ) && isset( $value['choice'] ) )
  360. $custom_image_header->set_header_image( $value['choice'] );
  361. else
  362. $custom_image_header->set_header_image( $value );
  363. }
  364. }
  365. /**
  366. * @package WordPress
  367. * @subpackage Customize
  368. * @since 3.4.0
  369. */
  370. final class WP_Customize_Background_Image_Setting extends WP_Customize_Setting {
  371. public $id = 'background_image_thumb';
  372. /**
  373. * @since 3.4.0
  374. * @uses remove_theme_mod()
  375. *
  376. * @param $value
  377. */
  378. public function update( $value ) {
  379. remove_theme_mod( 'background_image_thumb' );
  380. }
  381. }