/wp-admin/includes/misc.php

  1. <?php 
  2. /** 
  3. * Misc WordPress Administration API. 
  4. * 
  5. * @package WordPress 
  6. * @subpackage Administration 
  7. */ 
  8.  
  9. /** 
  10. * Returns whether the server is running Apache with the mod_rewrite module loaded. 
  11. * 
  12. * @since 2.0.0 
  13. * 
  14. * @return bool 
  15. */ 
  16. function got_mod_rewrite() { 
  17. $got_rewrite = apache_mod_loaded('mod_rewrite', true); 
  18.  
  19. /** 
  20. * Filters whether Apache and mod_rewrite are present. 
  21. * 
  22. * This filter was previously used to force URL rewriting for other servers,  
  23. * like nginx. Use the {@see 'got_url_rewrite'} filter in got_url_rewrite() instead. 
  24. * 
  25. * @since 2.5.0 
  26. * 
  27. * @see got_url_rewrite() 
  28. * 
  29. * @param bool $got_rewrite Whether Apache and mod_rewrite are present. 
  30. */ 
  31. return apply_filters( 'got_rewrite', $got_rewrite ); 
  32.  
  33. /** 
  34. * Returns whether the server supports URL rewriting. 
  35. * 
  36. * Detects Apache's mod_rewrite, IIS 7.0+ permalink support, and nginx. 
  37. * 
  38. * @since 3.7.0 
  39. * 
  40. * @global bool $is_nginx 
  41. * 
  42. * @return bool Whether the server supports URL rewriting. 
  43. */ 
  44. function got_url_rewrite() { 
  45. $got_url_rewrite = ( got_mod_rewrite() || $GLOBALS['is_nginx'] || iis7_supports_permalinks() ); 
  46.  
  47. /** 
  48. * Filters whether URL rewriting is available. 
  49. * 
  50. * @since 3.7.0 
  51. * 
  52. * @param bool $got_url_rewrite Whether URL rewriting is available. 
  53. */ 
  54. return apply_filters( 'got_url_rewrite', $got_url_rewrite ); 
  55.  
  56. /** 
  57. * Extracts strings from between the BEGIN and END markers in the .htaccess file. 
  58. * 
  59. * @since 1.5.0 
  60. * 
  61. * @param string $filename 
  62. * @param string $marker 
  63. * @return array An array of strings from a file (.htaccess ) from between BEGIN and END markers. 
  64. */ 
  65. function extract_from_markers( $filename, $marker ) { 
  66. $result = array (); 
  67.  
  68. if (!file_exists( $filename ) ) { 
  69. return $result; 
  70.  
  71. if ( $markerdata = explode( "\n", implode( '', file( $filename ) ) )); 
  72. $state = false; 
  73. foreach ( $markerdata as $markerline ) { 
  74. if (strpos($markerline, '# END ' . $marker) !== false) 
  75. $state = false; 
  76. if ( $state ) 
  77. $result[] = $markerline; 
  78. if (strpos($markerline, '# BEGIN ' . $marker) !== false) 
  79. $state = true; 
  80.  
  81. return $result; 
  82.  
  83. /** 
  84. * Inserts an array of strings into a file (.htaccess ), placing it between 
  85. * BEGIN and END markers. 
  86. * 
  87. * Replaces existing marked info. Retains surrounding 
  88. * data. Creates file if none exists. 
  89. * 
  90. * @since 1.5.0 
  91. * 
  92. * @param string $filename Filename to alter. 
  93. * @param string $marker The marker to alter. 
  94. * @param array|string $insertion The new content to insert. 
  95. * @return bool True on write success, false on failure. 
  96. */ 
  97. function insert_with_markers( $filename, $marker, $insertion ) { 
  98. if ( ! file_exists( $filename ) ) { 
  99. if ( ! is_writable( dirname( $filename ) ) ) { 
  100. return false; 
  101. if ( ! touch( $filename ) ) { 
  102. return false; 
  103. } elseif ( ! is_writeable( $filename ) ) { 
  104. return false; 
  105.  
  106. if ( ! is_array( $insertion ) ) { 
  107. $insertion = explode( "\n", $insertion ); 
  108.  
  109. $start_marker = "# BEGIN {$marker}"; 
  110. $end_marker = "# END {$marker}"; 
  111.  
  112. $fp = fopen( $filename, 'r+' ); 
  113. if ( ! $fp ) { 
  114. return false; 
  115.  
  116. // Attempt to get a lock. If the filesystem supports locking, this will block until the lock is acquired. 
  117. flock( $fp, LOCK_EX ); 
  118.  
  119. $lines = array(); 
  120. while ( ! feof( $fp ) ) { 
  121. $lines[] = rtrim( fgets( $fp ), "\r\n" ); 
  122.  
  123. // Split out the existing file into the preceding lines, and those that appear after the marker 
  124. $pre_lines = $post_lines = $existing_lines = array(); 
  125. $found_marker = $found_end_marker = false; 
  126. foreach ( $lines as $line ) { 
  127. if ( ! $found_marker && false !== strpos( $line, $start_marker ) ) { 
  128. $found_marker = true; 
  129. continue; 
  130. } elseif ( ! $found_end_marker && false !== strpos( $line, $end_marker ) ) { 
  131. $found_end_marker = true; 
  132. continue; 
  133. if ( ! $found_marker ) { 
  134. $pre_lines[] = $line; 
  135. } elseif ( $found_marker && $found_end_marker ) { 
  136. $post_lines[] = $line; 
  137. } else { 
  138. $existing_lines[] = $line; 
  139.  
  140. // Check to see if there was a change 
  141. if ( $existing_lines === $insertion ) { 
  142. flock( $fp, LOCK_UN ); 
  143. fclose( $fp ); 
  144.  
  145. return true; 
  146.  
  147. // Generate the new file data 
  148. $new_file_data = implode( "\n", array_merge( 
  149. $pre_lines,  
  150. array( $start_marker ),  
  151. $insertion,  
  152. array( $end_marker ),  
  153. $post_lines 
  154. ) ); 
  155.  
  156. // Write to the start of the file, and truncate it to that length 
  157. fseek( $fp, 0 ); 
  158. $bytes = fwrite( $fp, $new_file_data ); 
  159. if ( $bytes ) { 
  160. ftruncate( $fp, ftell( $fp ) ); 
  161. fflush( $fp ); 
  162. flock( $fp, LOCK_UN ); 
  163. fclose( $fp ); 
  164.  
  165. return (bool) $bytes; 
  166.  
  167. /** 
  168. * Updates the htaccess file with the current rules if it is writable. 
  169. * 
  170. * Always writes to the file if it exists and is writable to ensure that we 
  171. * blank out old rules. 
  172. * 
  173. * @since 1.5.0 
  174. * 
  175. * @global WP_Rewrite $wp_rewrite 
  176. */ 
  177. function save_mod_rewrite_rules() { 
  178. if ( is_multisite() ) 
  179. return; 
  180.  
  181. global $wp_rewrite; 
  182.  
  183. $home_path = get_home_path(); 
  184. $htaccess_file = $home_path.'.htaccess'; 
  185.  
  186. /** 
  187. * If the file doesn't already exist check for write access to the directory 
  188. * and whether we have some rules. Else check for write access to the file. 
  189. */ 
  190. if ((!file_exists($htaccess_file) && is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks()) || is_writable($htaccess_file)) { 
  191. if ( got_mod_rewrite() ) { 
  192. $rules = explode( "\n", $wp_rewrite->mod_rewrite_rules() ); 
  193. return insert_with_markers( $htaccess_file, 'WordPress', $rules ); 
  194.  
  195. return false; 
  196.  
  197. /** 
  198. * Updates the IIS web.config file with the current rules if it is writable. 
  199. * If the permalinks do not require rewrite rules then the rules are deleted from the web.config file. 
  200. * 
  201. * @since 2.8.0 
  202. * 
  203. * @global WP_Rewrite $wp_rewrite 
  204. * 
  205. * @return bool True if web.config was updated successfully 
  206. */ 
  207. function iis7_save_url_rewrite_rules() { 
  208. if ( is_multisite() ) 
  209. return; 
  210.  
  211. global $wp_rewrite; 
  212.  
  213. $home_path = get_home_path(); 
  214. $web_config_file = $home_path . 'web.config'; 
  215.  
  216. // Using win_is_writable() instead of is_writable() because of a bug in Windows PHP 
  217. if ( iis7_supports_permalinks() && ( ( ! file_exists($web_config_file) && win_is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks() ) || win_is_writable($web_config_file) ) ) { 
  218. $rule = $wp_rewrite->iis7_url_rewrite_rules(false, '', ''); 
  219. if ( ! empty($rule) ) { 
  220. return iis7_add_rewrite_rule($web_config_file, $rule); 
  221. } else { 
  222. return iis7_delete_rewrite_rule($web_config_file); 
  223. return false; 
  224.  
  225. /** 
  226. * Update the "recently-edited" file for the plugin or theme editor. 
  227. * 
  228. * @since 1.5.0 
  229. * 
  230. * @param string $file 
  231. */ 
  232. function update_recently_edited( $file ) { 
  233. $oldfiles = (array ) get_option( 'recently_edited' ); 
  234. if ( $oldfiles ) { 
  235. $oldfiles = array_reverse( $oldfiles ); 
  236. $oldfiles[] = $file; 
  237. $oldfiles = array_reverse( $oldfiles ); 
  238. $oldfiles = array_unique( $oldfiles ); 
  239. if ( 5 < count( $oldfiles )) 
  240. array_pop( $oldfiles ); 
  241. } else { 
  242. $oldfiles[] = $file; 
  243. update_option( 'recently_edited', $oldfiles ); 
  244.  
  245. /** 
  246. * Flushes rewrite rules if siteurl, home or page_on_front changed. 
  247. * 
  248. * @since 2.1.0 
  249. * 
  250. * @param string $old_value 
  251. * @param string $value 
  252. */ 
  253. function update_home_siteurl( $old_value, $value ) { 
  254. if ( wp_installing() ) 
  255. return; 
  256.  
  257. if ( is_multisite() && ms_is_switched() ) { 
  258. delete_option( 'rewrite_rules' ); 
  259. } else { 
  260. flush_rewrite_rules(); 
  261.  
  262.  
  263. /** 
  264. * Resets global variables based on $_GET and $_POST 
  265. * 
  266. * This function resets global variables based on the names passed 
  267. * in the $vars array to the value of $_POST[$var] or $_GET[$var] or '' 
  268. * if neither is defined. 
  269. * 
  270. * @since 2.0.0 
  271. * 
  272. * @param array $vars An array of globals to reset. 
  273. */ 
  274. function wp_reset_vars( $vars ) { 
  275. foreach ( $vars as $var ) { 
  276. if ( empty( $_POST[ $var ] ) ) { 
  277. if ( empty( $_GET[ $var ] ) ) { 
  278. $GLOBALS[ $var ] = ''; 
  279. } else { 
  280. $GLOBALS[ $var ] = $_GET[ $var ]; 
  281. } else { 
  282. $GLOBALS[ $var ] = $_POST[ $var ]; 
  283.  
  284. /** 
  285. * Displays the given administration message. 
  286. * 
  287. * @since 2.1.0 
  288. * 
  289. * @param string|WP_Error $message 
  290. */ 
  291. function show_message($message) { 
  292. if ( is_wp_error($message) ) { 
  293. if ( $message->get_error_data() && is_string( $message->get_error_data() ) ) 
  294. $message = $message->get_error_message() . ': ' . $message->get_error_data(); 
  295. else 
  296. $message = $message->get_error_message(); 
  297. echo "<p>$message</p>\n"; 
  298. wp_ob_end_flush_all(); 
  299. flush(); 
  300.  
  301. /** 
  302. * @since 2.8.0 
  303. * 
  304. * @param string $content 
  305. * @return array 
  306. */ 
  307. function wp_doc_link_parse( $content ) { 
  308. if ( !is_string( $content ) || empty( $content ) ) 
  309. return array(); 
  310.  
  311. if ( !function_exists('token_get_all') ) 
  312. return array(); 
  313.  
  314. $tokens = token_get_all( $content ); 
  315. $count = count( $tokens ); 
  316. $functions = array(); 
  317. $ignore_functions = array(); 
  318. for ( $t = 0; $t < $count - 2; $t++ ) { 
  319. if ( ! is_array( $tokens[ $t ] ) ) { 
  320. continue; 
  321.  
  322. if ( T_STRING == $tokens[ $t ][0] && ( '(' == $tokens[ $t + 1 ] || '(' == $tokens[ $t + 2 ] ) ) { 
  323. // If it's a function or class defined locally, there's not going to be any docs available 
  324. if ( ( isset( $tokens[ $t - 2 ][1] ) && in_array( $tokens[ $t - 2 ][1], array( 'function', 'class' ) ) ) || ( isset( $tokens[ $t - 2 ][0] ) && T_OBJECT_OPERATOR == $tokens[ $t - 1 ][0] ) ) { 
  325. $ignore_functions[] = $tokens[$t][1]; 
  326. // Add this to our stack of unique references 
  327. $functions[] = $tokens[$t][1]; 
  328.  
  329. $functions = array_unique( $functions ); 
  330. sort( $functions ); 
  331.  
  332. /** 
  333. * Filters the list of functions and classes to be ignored from the documentation lookup. 
  334. * 
  335. * @since 2.8.0 
  336. * 
  337. * @param array $ignore_functions Functions and classes to be ignored. 
  338. */ 
  339. $ignore_functions = apply_filters( 'documentation_ignore_functions', $ignore_functions ); 
  340.  
  341. $ignore_functions = array_unique( $ignore_functions ); 
  342.  
  343. $out = array(); 
  344. foreach ( $functions as $function ) { 
  345. if ( in_array( $function, $ignore_functions ) ) 
  346. continue; 
  347. $out[] = $function; 
  348.  
  349. return $out; 
  350.  
  351. /** 
  352. * Saves option for number of rows when listing posts, pages, comments, etc. 
  353. * 
  354. * @since 2.8.0 
  355. */ 
  356. function set_screen_options() { 
  357.  
  358. if ( isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options']) ) { 
  359. check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' ); 
  360.  
  361. if ( !$user = wp_get_current_user() ) 
  362. return; 
  363. $option = $_POST['wp_screen_options']['option']; 
  364. $value = $_POST['wp_screen_options']['value']; 
  365.  
  366. if ( $option != sanitize_key( $option ) ) 
  367. return; 
  368.  
  369. $map_option = $option; 
  370. $type = str_replace('edit_', '', $map_option); 
  371. $type = str_replace('_per_page', '', $type); 
  372. if ( in_array( $type, get_taxonomies() ) ) 
  373. $map_option = 'edit_tags_per_page'; 
  374. elseif ( in_array( $type, get_post_types() ) ) 
  375. $map_option = 'edit_per_page'; 
  376. else 
  377. $option = str_replace('-', '_', $option); 
  378.  
  379. switch ( $map_option ) { 
  380. case 'edit_per_page': 
  381. case 'users_per_page': 
  382. case 'edit_comments_per_page': 
  383. case 'upload_per_page': 
  384. case 'edit_tags_per_page': 
  385. case 'plugins_per_page': 
  386. // Network admin 
  387. case 'sites_network_per_page': 
  388. case 'users_network_per_page': 
  389. case 'site_users_network_per_page': 
  390. case 'plugins_network_per_page': 
  391. case 'themes_network_per_page': 
  392. case 'site_themes_network_per_page': 
  393. $value = (int) $value; 
  394. if ( $value < 1 || $value > 999 ) 
  395. return; 
  396. break; 
  397. default: 
  398.  
  399. /** 
  400. * Filters a screen option value before it is set. 
  401. * 
  402. * The filter can also be used to modify non-standard [items]_per_page 
  403. * settings. See the parent function for a full list of standard options. 
  404. * 
  405. * Returning false to the filter will skip saving the current option. 
  406. * 
  407. * @since 2.8.0 
  408. * 
  409. * @see set_screen_options() 
  410. * 
  411. * @param bool|int $value Screen option value. Default false to skip. 
  412. * @param string $option The option name. 
  413. * @param int $value The number of rows to use. 
  414. */ 
  415. $value = apply_filters( 'set-screen-option', false, $option, $value ); 
  416.  
  417. if ( false === $value ) 
  418. return; 
  419. break; 
  420.  
  421. update_user_meta($user->ID, $option, $value); 
  422.  
  423. $url = remove_query_arg( array( 'pagenum', 'apage', 'paged' ), wp_get_referer() ); 
  424. if ( isset( $_POST['mode'] ) ) { 
  425. $url = add_query_arg( array( 'mode' => $_POST['mode'] ), $url ); 
  426.  
  427. wp_safe_redirect( $url ); 
  428. exit; 
  429.  
  430. /** 
  431. * Check if rewrite rule for WordPress already exists in the IIS 7+ configuration file 
  432. * 
  433. * @since 2.8.0 
  434. * 
  435. * @return bool 
  436. * @param string $filename The file path to the configuration file 
  437. */ 
  438. function iis7_rewrite_rule_exists($filename) { 
  439. if ( ! file_exists($filename) ) 
  440. return false; 
  441. if ( ! class_exists( 'DOMDocument', false ) ) { 
  442. return false; 
  443.  
  444. $doc = new DOMDocument(); 
  445. if ( $doc->load($filename) === false ) 
  446. return false; 
  447. $xpath = new DOMXPath($doc); 
  448. $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name, \'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name, \'WordPress\')]'); 
  449. if ( $rules->length == 0 ) 
  450. return false; 
  451. else 
  452. return true; 
  453.  
  454. /** 
  455. * Delete WordPress rewrite rule from web.config file if it exists there 
  456. * 
  457. * @since 2.8.0 
  458. * 
  459. * @param string $filename Name of the configuration file 
  460. * @return bool 
  461. */ 
  462. function iis7_delete_rewrite_rule($filename) { 
  463. // If configuration file does not exist then rules also do not exist so there is nothing to delete 
  464. if ( ! file_exists($filename) ) 
  465. return true; 
  466.  
  467. if ( ! class_exists( 'DOMDocument', false ) ) { 
  468. return false; 
  469.  
  470. $doc = new DOMDocument(); 
  471. $doc->preserveWhiteSpace = false; 
  472.  
  473. if ( $doc -> load($filename) === false ) 
  474. return false; 
  475. $xpath = new DOMXPath($doc); 
  476. $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name, \'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name, \'WordPress\')]'); 
  477. if ( $rules->length > 0 ) { 
  478. $child = $rules->item(0); 
  479. $parent = $child->parentNode; 
  480. $parent->removeChild($child); 
  481. $doc->formatOutput = true; 
  482. saveDomDocument($doc, $filename); 
  483. return true; 
  484.  
  485. /** 
  486. * Add WordPress rewrite rule to the IIS 7+ configuration file. 
  487. * 
  488. * @since 2.8.0 
  489. * 
  490. * @param string $filename The file path to the configuration file 
  491. * @param string $rewrite_rule The XML fragment with URL Rewrite rule 
  492. * @return bool 
  493. */ 
  494. function iis7_add_rewrite_rule($filename, $rewrite_rule) { 
  495. if ( ! class_exists( 'DOMDocument', false ) ) { 
  496. return false; 
  497.  
  498. // If configuration file does not exist then we create one. 
  499. if ( ! file_exists($filename) ) { 
  500. $fp = fopen( $filename, 'w'); 
  501. fwrite($fp, '<configuration/>'); 
  502. fclose($fp); 
  503.  
  504. $doc = new DOMDocument(); 
  505. $doc->preserveWhiteSpace = false; 
  506.  
  507. if ( $doc->load($filename) === false ) 
  508. return false; 
  509.  
  510. $xpath = new DOMXPath($doc); 
  511.  
  512. // First check if the rule already exists as in that case there is no need to re-add it 
  513. $wordpress_rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name, \'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name, \'WordPress\')]'); 
  514. if ( $wordpress_rules->length > 0 ) 
  515. return true; 
  516.  
  517. // Check the XPath to the rewrite rule and create XML nodes if they do not exist 
  518. $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite/rules'); 
  519. if ( $xmlnodes->length > 0 ) { 
  520. $rules_node = $xmlnodes->item(0); 
  521. } else { 
  522. $rules_node = $doc->createElement('rules'); 
  523.  
  524. $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite'); 
  525. if ( $xmlnodes->length > 0 ) { 
  526. $rewrite_node = $xmlnodes->item(0); 
  527. $rewrite_node->appendChild($rules_node); 
  528. } else { 
  529. $rewrite_node = $doc->createElement('rewrite'); 
  530. $rewrite_node->appendChild($rules_node); 
  531.  
  532. $xmlnodes = $xpath->query('/configuration/system.webServer'); 
  533. if ( $xmlnodes->length > 0 ) { 
  534. $system_webServer_node = $xmlnodes->item(0); 
  535. $system_webServer_node->appendChild($rewrite_node); 
  536. } else { 
  537. $system_webServer_node = $doc->createElement('system.webServer'); 
  538. $system_webServer_node->appendChild($rewrite_node); 
  539.  
  540. $xmlnodes = $xpath->query('/configuration'); 
  541. if ( $xmlnodes->length > 0 ) { 
  542. $config_node = $xmlnodes->item(0); 
  543. $config_node->appendChild($system_webServer_node); 
  544. } else { 
  545. $config_node = $doc->createElement('configuration'); 
  546. $doc->appendChild($config_node); 
  547. $config_node->appendChild($system_webServer_node); 
  548.  
  549. $rule_fragment = $doc->createDocumentFragment(); 
  550. $rule_fragment->appendXML($rewrite_rule); 
  551. $rules_node->appendChild($rule_fragment); 
  552.  
  553. $doc->encoding = "UTF-8"; 
  554. $doc->formatOutput = true; 
  555. saveDomDocument($doc, $filename); 
  556.  
  557. return true; 
  558.  
  559. /** 
  560. * Saves the XML document into a file 
  561. * 
  562. * @since 2.8.0 
  563. * 
  564. * @param DOMDocument $doc 
  565. * @param string $filename 
  566. */ 
  567. function saveDomDocument($doc, $filename) { 
  568. $config = $doc->saveXML(); 
  569. $config = preg_replace("/([^\r])\n/", "$1\r\n", $config); 
  570. $fp = fopen($filename, 'w'); 
  571. fwrite($fp, $config); 
  572. fclose($fp); 
  573.  
  574. /** 
  575. * Display the default admin color scheme picker (Used in user-edit.php) 
  576. * 
  577. * @since 3.0.0 
  578. * 
  579. * @global array $_wp_admin_css_colors 
  580. * 
  581. * @param int $user_id User ID. 
  582. */ 
  583. function admin_color_scheme_picker( $user_id ) { 
  584. global $_wp_admin_css_colors; 
  585.  
  586. ksort( $_wp_admin_css_colors ); 
  587.  
  588. if ( isset( $_wp_admin_css_colors['fresh'] ) ) { 
  589. // Set Default ('fresh') and Light should go first. 
  590. $_wp_admin_css_colors = array_filter( array_merge( array( 'fresh' => '', 'light' => '' ), $_wp_admin_css_colors ) ); 
  591.  
  592. $current_color = get_user_option( 'admin_color', $user_id ); 
  593.  
  594. if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) { 
  595. $current_color = 'fresh'; 
  596.  
  597. ?> 
  598. <fieldset id="color-picker" class="scheme-list"> 
  599. <legend class="screen-reader-text"><span><?php _e( 'Admin Color Scheme' ); ?></span></legend> 
  600. <?php 
  601. wp_nonce_field( 'save-color-scheme', 'color-nonce', false ); 
  602. foreach ( $_wp_admin_css_colors as $color => $color_info ) : 
  603.  
  604. ?> 
  605. <div class="color-option <?php echo ( $color == $current_color ) ? 'selected' : ''; ?>"> 
  606. <input name="admin_color" id="admin_color_<?php echo esc_attr( $color ); ?>" type="radio" value="<?php echo esc_attr( $color ); ?>" class="tog" <?php checked( $color, $current_color ); ?> /> 
  607. <input type="hidden" class="css_url" value="<?php echo esc_url( $color_info->url ); ?>" /> 
  608. <input type="hidden" class="icon_colors" value="<?php echo esc_attr( wp_json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" /> 
  609. <label for="admin_color_<?php echo esc_attr( $color ); ?>"><?php echo esc_html( $color_info->name ); ?></label> 
  610. <table class="color-palette"> 
  611. <tr> 
  612. <?php 
  613.  
  614. foreach ( $color_info->colors as $html_color ) { 
  615. ?> 
  616. <td style="background-color: <?php echo esc_attr( $html_color ); ?>"> </td> 
  617. <?php 
  618.  
  619. ?> 
  620. </tr> 
  621. </table> 
  622. </div> 
  623. <?php 
  624.  
  625. endforeach; 
  626.  
  627. ?> 
  628. </fieldset> 
  629. <?php 
  630.  
  631. /** 
  632. * 
  633. * @global array $_wp_admin_css_colors 
  634. */ 
  635. function wp_color_scheme_settings() { 
  636. global $_wp_admin_css_colors; 
  637.  
  638. $color_scheme = get_user_option( 'admin_color' ); 
  639.  
  640. // It's possible to have a color scheme set that is no longer registered. 
  641. if ( empty( $_wp_admin_css_colors[ $color_scheme ] ) ) { 
  642. $color_scheme = 'fresh'; 
  643.  
  644. if ( ! empty( $_wp_admin_css_colors[ $color_scheme ]->icon_colors ) ) { 
  645. $icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors; 
  646. } elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) { 
  647. $icon_colors = $_wp_admin_css_colors['fresh']->icon_colors; 
  648. } else { 
  649. // Fall back to the default set of icon colors if the default scheme is missing. 
  650. $icon_colors = array( 'base' => '#82878c', 'focus' => '#00a0d2', 'current' => '#fff' ); 
  651.  
  652. echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n"; 
  653.  
  654. /** 
  655. * @since 3.3.0 
  656. */ 
  657. function _ipad_meta() { 
  658. if ( wp_is_mobile() ) { 
  659. ?> 
  660. <meta name="viewport" id="viewport-meta" content="width=device-width, initial-scale=1"> 
  661. <?php 
  662.  
  663. /** 
  664. * Check lock status for posts displayed on the Posts screen 
  665. * 
  666. * @since 3.6.0 
  667. * 
  668. * @param array $response The Heartbeat response. 
  669. * @param array $data The $_POST data sent. 
  670. * @param string $screen_id The screen id. 
  671. * @return array The Heartbeat response. 
  672. */ 
  673. function wp_check_locked_posts( $response, $data, $screen_id ) { 
  674. $checked = array(); 
  675.  
  676. if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) { 
  677. foreach ( $data['wp-check-locked-posts'] as $key ) { 
  678. if ( ! $post_id = absint( substr( $key, 5 ) ) ) 
  679. continue; 
  680.  
  681. if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) && current_user_can( 'edit_post', $post_id ) ) { 
  682. $send = array( 'text' => sprintf( __( '%s is currently editing' ), $user->display_name ) ); 
  683.  
  684. if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) 
  685. $send['avatar_src'] = $matches[1]; 
  686.  
  687. $checked[$key] = $send; 
  688.  
  689. if ( ! empty( $checked ) ) 
  690. $response['wp-check-locked-posts'] = $checked; 
  691.  
  692. return $response; 
  693.  
  694. /** 
  695. * Check lock status on the New/Edit Post screen and refresh the lock 
  696. * 
  697. * @since 3.6.0 
  698. * 
  699. * @param array $response The Heartbeat response. 
  700. * @param array $data The $_POST data sent. 
  701. * @param string $screen_id The screen id. 
  702. * @return array The Heartbeat response. 
  703. */ 
  704. function wp_refresh_post_lock( $response, $data, $screen_id ) { 
  705. if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) { 
  706. $received = $data['wp-refresh-post-lock']; 
  707. $send = array(); 
  708.  
  709. if ( ! $post_id = absint( $received['post_id'] ) ) 
  710. return $response; 
  711.  
  712. if ( ! current_user_can('edit_post', $post_id) ) 
  713. return $response; 
  714.  
  715. if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) ) { 
  716. $error = array( 
  717. 'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name ) 
  718. ); 
  719.  
  720. if ( $avatar = get_avatar( $user->ID, 64 ) ) { 
  721. if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) 
  722. $error['avatar_src'] = $matches[1]; 
  723.  
  724. $send['lock_error'] = $error; 
  725. } else { 
  726. if ( $new_lock = wp_set_post_lock( $post_id ) ) 
  727. $send['new_lock'] = implode( ':', $new_lock ); 
  728.  
  729. $response['wp-refresh-post-lock'] = $send; 
  730.  
  731. return $response; 
  732.  
  733. /** 
  734. * Check nonce expiration on the New/Edit Post screen and refresh if needed 
  735. * 
  736. * @since 3.6.0 
  737. * 
  738. * @param array $response The Heartbeat response. 
  739. * @param array $data The $_POST data sent. 
  740. * @param string $screen_id The screen id. 
  741. * @return array The Heartbeat response. 
  742. */ 
  743. function wp_refresh_post_nonces( $response, $data, $screen_id ) { 
  744. if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) { 
  745. $received = $data['wp-refresh-post-nonces']; 
  746. $response['wp-refresh-post-nonces'] = array( 'check' => 1 ); 
  747.  
  748. if ( ! $post_id = absint( $received['post_id'] ) ) { 
  749. return $response; 
  750.  
  751. if ( ! current_user_can( 'edit_post', $post_id ) ) { 
  752. return $response; 
  753.  
  754. $response['wp-refresh-post-nonces'] = array( 
  755. 'replace' => array( 
  756. 'getpermalinknonce' => wp_create_nonce('getpermalink'),  
  757. 'samplepermalinknonce' => wp_create_nonce('samplepermalink'),  
  758. 'closedpostboxesnonce' => wp_create_nonce('closedpostboxes'),  
  759. '_ajax_linking_nonce' => wp_create_nonce( 'internal-linking' ),  
  760. '_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ),  
  761. ),  
  762. 'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ),  
  763. ); 
  764.  
  765. return $response; 
  766.  
  767. /** 
  768. * Disable suspension of Heartbeat on the Add/Edit Post screens. 
  769. * 
  770. * @since 3.8.0 
  771. * 
  772. * @global string $pagenow 
  773. * 
  774. * @param array $settings An array of Heartbeat settings. 
  775. * @return array Filtered Heartbeat settings. 
  776. */ 
  777. function wp_heartbeat_set_suspension( $settings ) { 
  778. global $pagenow; 
  779.  
  780. if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) { 
  781. $settings['suspension'] = 'disable'; 
  782.  
  783. return $settings; 
  784.  
  785. /** 
  786. * Autosave with heartbeat 
  787. * 
  788. * @since 3.9.0 
  789. * 
  790. * @param array $response The Heartbeat response. 
  791. * @param array $data The $_POST data sent. 
  792. * @return array The Heartbeat response. 
  793. */ 
  794. function heartbeat_autosave( $response, $data ) { 
  795. if ( ! empty( $data['wp_autosave'] ) ) { 
  796. $saved = wp_autosave( $data['wp_autosave'] ); 
  797.  
  798. if ( is_wp_error( $saved ) ) { 
  799. $response['wp_autosave'] = array( 'success' => false, 'message' => $saved->get_error_message() ); 
  800. } elseif ( empty( $saved ) ) { 
  801. $response['wp_autosave'] = array( 'success' => false, 'message' => __( 'Error while saving.' ) ); 
  802. } else { 
  803. /** translators: draft saved date format, see https://secure.php.net/date */ 
  804. $draft_saved_date_format = __( 'g:i:s a' ); 
  805. /** translators: %s: date and time */ 
  806. $response['wp_autosave'] = array( 'success' => true, 'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ) ); 
  807.  
  808. return $response; 
  809.  
  810. /** 
  811. * Remove single-use URL parameters and create canonical link based on new URL. 
  812. * 
  813. * Remove specific query string parameters from a URL, create the canonical link,  
  814. * put it in the admin header, and change the current URL to match. 
  815. * 
  816. * @since 4.2.0 
  817. */ 
  818. function wp_admin_canonical_url() { 
  819. $removable_query_args = wp_removable_query_args(); 
  820.  
  821. if ( empty( $removable_query_args ) ) { 
  822. return; 
  823.  
  824. // Ensure we're using an absolute URL. 
  825. $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); 
  826. $filtered_url = remove_query_arg( $removable_query_args, $current_url ); 
  827. ?> 
  828. <link id="wp-admin-canonical" rel="canonical" href="<?php echo esc_url( $filtered_url ); ?>" /> 
  829. <script> 
  830. if ( window.history.replaceState ) { 
  831. window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash ); 
  832. </script> 
  833. <?php 
  834.  
  835. /** 
  836. * Outputs JS that reloads the page if the user navigated to it with the Back or Forward button. 
  837. * 
  838. * Used on the Edit Post and Add New Post screens. Needed to ensure the page is not loaded from browser cache,  
  839. * so the post title and editor content are the last saved versions. Ideally this script should run first in the head. 
  840. * 
  841. * @since 4.6.0 
  842. */ 
  843. function wp_page_reload_on_back_button_js() { 
  844. ?> 
  845. <script> 
  846. if ( typeof performance !== 'undefined' && performance.navigation && performance.navigation.type === 2 ) { 
  847. document.location.reload( true ); 
  848. </script> 
  849. <?php 
.