8 require( ABSPATH . WPINC . '/option.php' );
11 * Convert given date string into a different format.
13 * $format should be either a PHP date format string, e.g. 'U' for a Unix
14 * timestamp, or 'G' for a Unix timestamp assuming that $date is GMT.
16 * If $translate is true then the given date and format string will
17 * be passed to date_i18n() for translation.
21 * @param string $format Format of the date to return.
22 * @param string $date Date string to convert.
23 * @param bool $translate Whether the return date should be translated. Default true.
24 * @return string|int|bool Formatted date string or Unix timestamp. False if $date is empty.
26 function mysql2date( $format, $date, $translate = true ) {
31 return strtotime( $date . ' +0000' );
33 $i = strtotime( $date );
39 return date_i18n( $format, $i );
41 return date( $format, $i );
45 * Retrieve the current time based on specified type.
47 * The 'mysql' type will return the time in the format for MySQL DATETIME field.
48 * The 'timestamp' type will return the current timestamp.
49 * Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d').
51 * If $gmt is set to either '1' or 'true', then both types will use GMT time.
52 * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
56 * @param string $type Type of time to retrieve. Accepts 'mysql', 'timestamp', or PHP date
57 * format string (e.g. 'Y-m-d').
58 * @param int|bool $gmt Optional. Whether to use GMT timezone. Default false.
59 * @return int|string Integer if $type is 'timestamp', string otherwise.
61 function current_time( $type, $gmt = 0 ) {
64 return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ) );
66 return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
68 return ( $gmt ) ? date( $type ) : date( $type, time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
73 * Retrieve the date in localized format, based on timestamp.
75 * If the locale specifies the locale month and weekday, then the locale will
76 * take over the format for the date. If it isn't, then the date format string
77 * will be used instead.
81 * @global WP_Locale $wp_locale
83 * @param string $dateformatstring Format to display the date.
84 * @param bool|int $unixtimestamp Optional. Unix timestamp. Default false.
85 * @param bool $gmt Optional. Whether to use GMT timezone. Default false.
87 * @return string The date, translated if locale specifies it.
89 function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
95 $i = current_time( 'timestamp' );
98 // we should not let date() interfere with our
99 // specially computed timestamp
104 * Store original value for language with untypical grammars.
105 * See https://core.trac.wordpress.org/ticket/9396
107 $req_format = $dateformatstring;
109 $datefunc = $gmt? 'gmdate' : 'date';
111 if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
112 $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
113 $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
114 $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
115 $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
116 $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
117 $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
118 $dateformatstring = ' '.$dateformatstring;
119 $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
120 $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
121 $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
122 $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
123 $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
124 $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
126 $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
128 $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
129 $timezone_formats_re = implode( '|', $timezone_formats );
130 if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
131 $timezone_string = get_option( 'timezone_string' );
132 if ( $timezone_string ) {
133 $timezone_object = timezone_open( $timezone_string );
134 $date_object = date_create( null, $timezone_object );
135 foreach( $timezone_formats as $timezone_format ) {
136 if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
137 $formatted = date_format( $date_object, $timezone_format );
138 $dateformatstring = ' '.$dateformatstring;
139 $dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
140 $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
145 $j = @$datefunc( $dateformatstring, $i );
148 * Filter the date formatted based on the locale.
152 * @param string $j Formatted date string.
153 * @param string $req_format Format to display the date.
154 * @param int $i Unix timestamp.
155 * @param bool $gmt Whether to convert to GMT for time. Default false.
157 $j = apply_filters( 'date_i18n', $j, $req_format, $i, $gmt );
162 * Convert integer number to format based on the locale.
166 * @global WP_Locale $wp_locale
168 * @param int $number The number to convert based on locale.
169 * @param int $decimals Optional. Precision of the number of decimal places. Default 0.
170 * @return string Converted number in string format.
172 function number_format_i18n( $number, $decimals = 0 ) {
174 $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
177 * Filter the number formatted based on the locale.
181 * @param string $formatted Converted number in string format.
183 return apply_filters( 'number_format_i18n', $formatted );
187 * Convert number of bytes largest unit bytes will fit into.
189 * It is easier to read 1 kB than 1024 bytes and 1 MB than 1048576 bytes. Converts
190 * number of bytes to human readable number by taking the number of that unit
191 * that the bytes will go into it. Supports TB value.
193 * Please note that integers in PHP are limited to 32 bits, unless they are on
194 * 64 bit architecture, then they have 64 bit size. If you need to place the
195 * larger size then what PHP integer type will hold, then use a string. It will
196 * be converted to a double, which should always have 64 bit length.
198 * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
202 * @param int|string $bytes Number of bytes. Note max integer size for integers.
203 * @param int $decimals Optional. Precision of number of decimal places. Default 0.
204 * @return string|false False on failure. Number string on success.
206 function size_format( $bytes, $decimals = 0 ) {
208 // ========================= Origin ====
209 'TB' => 1099511627776, // pow( 1024, 4)
210 'GB' => 1073741824, // pow( 1024, 3)
211 'MB' => 1048576, // pow( 1024, 2)
212 'kB' => 1024, // pow( 1024, 1)
213 'B' => 1, // pow( 1024, 0)
216 foreach ( $quant as $unit => $mag ) {
217 if ( doubleval( $bytes ) >= $mag ) {
218 return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
226 * Get the week start and end from the datetime or date string from MySQL.
230 * @param string $mysqlstring Date or datetime field type from MySQL.
231 * @param int|string $start_of_week Optional. Start of the week as an integer. Default empty string.
232 * @return array Keys are 'start' and 'end'.
234 function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
235 // MySQL string year.
236 $my = substr( $mysqlstring, 0, 4 );
238 // MySQL string month.
239 $mm = substr( $mysqlstring, 8, 2 );
242 $md = substr( $mysqlstring, 5, 2 );
244 // The timestamp for MySQL string day.
245 $day = mktime( 0, 0, 0, $md, $mm, $my );
247 // The day of the week from the timestamp.
248 $weekday = date( 'w', $day );
250 if ( !is_numeric($start_of_week) )
251 $start_of_week = get_option( 'start_of_week' );
253 if ( $weekday < $start_of_week )
256 // The most recent week start day on or before $day.
257 $start = $day - DAY_IN_SECONDS * ( $weekday - $start_of_week );
259 // $start + 7 days - 1 second.
260 $end = $start + 7 * DAY_IN_SECONDS - 1;
261 return compact( 'start', 'end' );
265 * Unserialize value only if it was serialized.
269 * @param string $original Maybe unserialized original, if is needed.
270 * @return mixed Unserialized data can be any type.
272 function maybe_unserialize( $original ) {
273 if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
274 return @unserialize( $original );
279 * Check value to find if it was serialized.
281 * If $data is not an string, then returned value will always be false.
282 * Serialized data is always a string.
286 * @param string $data Value to check to see if was serialized.
287 * @param bool $strict Optional. Whether to be strict about the end of the string. Default true.
288 * @return bool False if not serialized and true if it was.
290 function is_serialized( $data, $strict = true ) {
291 // if it isn't a string, it isn't serialized.
292 if ( ! is_string( $data ) ) {
295 $data = trim( $data );
296 if ( 'N;' == $data ) {
299 if ( strlen( $data ) < 4 ) {
302 if ( ':' !== $data[1] ) {
306 $lastc = substr( $data, -1 );
307 if ( ';' !== $lastc && '}' !== $lastc ) {
311 $semicolon = strpos( $data, ';' );
312 $brace = strpos( $data, '}' );
313 // Either ; or } must exist.
314 if ( false === $semicolon && false === $brace )
316 // But neither must be in the first X characters.
317 if ( false !== $semicolon && $semicolon < 3 )
319 if ( false !== $brace && $brace < 4 )
326 if ( '"' !== substr( $data, -2, 1 ) ) {
329 } elseif ( false === strpos( $data, '"' ) ) {
332 // or else fall through
335 return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
339 $end = $strict ? '$' : '';
340 return (bool) preg_match( "/^{$token}:[0-9.E-]+;$end/", $data );
346 * Check whether serialized data is of string type.
350 * @param string $data Serialized data.
351 * @return bool False if not a serialized string, true if it is.
353 function is_serialized_string( $data ) {
354 // if it isn't a string, it isn't a serialized string.
355 if ( ! is_string( $data ) ) {
358 $data = trim( $data );
359 if ( strlen( $data ) < 4 ) {
361 } elseif ( ':' !== $data[1] ) {
363 } elseif ( ';' !== substr( $data, -1 ) ) {
365 } elseif ( $data[0] !== 's' ) {
367 } elseif ( '"' !== substr( $data, -2, 1 ) ) {
375 * Serialize data, if needed.
379 * @param string|array|object $data Data that might be serialized.
380 * @return mixed A scalar data
382 function maybe_serialize( $data ) {
383 if ( is_array( $data ) || is_object( $data ) )
384 return serialize( $data );
386 // Double serialization is required for backward compatibility.
387 // See https://core.trac.wordpress.org/ticket/12930
388 // Also the world will end. See WP 3.6.1.
389 if ( is_serialized( $data, false ) )
390 return serialize( $data );
396 * Retrieve post title from XMLRPC XML.
398 * If the title element is not part of the XML, then the default post title from
399 * the $post_default_title will be used instead.
403 * @global string $post_default_title Default XML-RPC post title.
405 * @param string $content XMLRPC XML Request content
406 * @return string Post title
408 function xmlrpc_getposttitle( $content ) {
409 global $post_default_title;
410 if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
411 $post_title = $matchtitle[1];
413 $post_title = $post_default_title;
419 * Retrieve the post category or categories from XMLRPC XML.
421 * If the category element is not found, then the default post category will be
422 * used. The return type then would be what $post_default_category. If the
423 * category is found, then it will always be an array.
427 * @global string $post_default_category Default XML-RPC post category.
429 * @param string $content XMLRPC XML Request content
430 * @return string|array List of categories or category name.
432 function xmlrpc_getpostcategory( $content ) {
433 global $post_default_category;
434 if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
435 $post_category = trim( $matchcat[1], ',' );
436 $post_category = explode( ',', $post_category );
438 $post_category = $post_default_category;
440 return $post_category;
444 * XMLRPC XML content without title and category elements.
448 * @param string $content XML-RPC XML Request content.
449 * @return string XMLRPC XML Request content without title and category elements.
451 function xmlrpc_removepostdata( $content ) {
452 $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
453 $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
454 $content = trim( $content );
459 * Use RegEx to extract URLs from arbitrary content.
463 * @param string $content Content to extract URLs from.
464 * @return array URLs found in passed string.
466 function wp_extract_urls( $content ) {
469 . "(?:([\w-]+:)?//?)"
475 . "[^`!()\[\]{};:'\".,<>«»“”‘’\s]|"
484 $post_links = array_unique( array_map( 'html_entity_decode', $post_links[2] ) );
486 return array_values( $post_links );
490 * Check content for video and audio links to add as enclosures.
492 * Will not add enclosures that have already been added and will
493 * remove enclosures that are no longer in the post. This is called as
494 * pingbacks and trackbacks.
500 * @param string $content Post Content.
501 * @param int $post_ID Post ID.
503 function do_enclose( $content, $post_ID ) {
506 //TODO: Tidy this ghetto code up and make the debug code optional
507 include_once( ABSPATH . WPINC . '/class-IXR.php' );
509 $post_links = array();
511 $pung = get_enclosed( $post_ID );
513 $post_links_temp = wp_extract_urls( $content );
515 foreach ( $pung as $link_test ) {
516 if ( ! in_array( $link_test, $post_links_temp ) ) { // link no longer in post
517 $mids = $wpdb->get_col( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post_ID, $wpdb->esc_like( $link_test ) . '%') );
518 foreach ( $mids as $mid )
519 delete_metadata_by_mid( 'post', $mid );
523 foreach ( (array) $post_links_temp as $link_test ) {
524 if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
525 $test = @parse_url( $link_test );
526 if ( false === $test )
528 if ( isset( $test['query'] ) )
529 $post_links[] = $link_test;
530 elseif ( isset($test['path']) && ( $test['path'] != '/' ) && ($test['path'] != '' ) )
531 $post_links[] = $link_test;
535 foreach ( (array) $post_links as $url ) {
536 if ( $url != '' && !$wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post_ID, $wpdb->esc_like( $url ) . '%' ) ) ) {
538 if ( $headers = wp_get_http_headers( $url) ) {
539 $len = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
540 $type = isset( $headers['content-type'] ) ? $headers['content-type'] : '';
541 $allowed_types = array( 'video', 'audio' );
543 // Check to see if we can figure out the mime type from
545 $url_parts = @parse_url( $url );
546 if ( false !== $url_parts ) {
547 $extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );
548 if ( !empty( $extension ) ) {
549 foreach ( wp_get_mime_types() as $exts => $mime ) {
550 if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
558 if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
559 add_post_meta( $post_ID, 'enclosure', "$url\n$len\n$mime\n" );
567 * Perform a HTTP HEAD or GET request.
569 * If $file_path is a writable filename, this will do a GET request and write
570 * the file to that path.
574 * @param string $url URL to fetch.
575 * @param string|bool $file_path Optional. File path to write request to. Default false.
576 * @param int $red Optional. The number of Redirects followed, Upon 5 being hit,
577 * returns false. Default 1.
578 * @return bool|string False on failure and string of headers if HEAD request.
580 function wp_get_http( $url, $file_path = false, $red = 1 ) {
581 @set_time_limit( 60 );
587 $options['redirection'] = 5;
589 if ( false == $file_path )
590 $options['method'] = 'HEAD';
592 $options['method'] = 'GET';
594 $response = wp_safe_remote_request( $url, $options );
596 if ( is_wp_error( $response ) )
599 $headers = wp_remote_retrieve_headers( $response );
600 $headers['response'] = wp_remote_retrieve_response_code( $response );
602 // WP_HTTP no longer follows redirects for HEAD requests.
603 if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
604 return wp_get_http( $headers['location'], $file_path, ++$red );
607 if ( false == $file_path )
610 // GET request - write it to the supplied filename
611 $out_fp = fopen($file_path, 'w');
615 fwrite( $out_fp, wp_remote_retrieve_body( $response ) );
623 * Retrieve HTTP Headers from URL.
627 * @param string $url URL to retrieve HTTP headers from.
628 * @param bool $deprecated Not Used.
629 * @return bool|string False on failure, headers on success.
631 function wp_get_http_headers( $url, $deprecated = false ) {
632 if ( !empty( $deprecated ) )
633 _deprecated_argument( __FUNCTION__, '2.7' );
635 $response = wp_safe_remote_head( $url );
637 if ( is_wp_error( $response ) )
640 return wp_remote_retrieve_headers( $response );
644 * Whether the publish date of the current post in the loop is different from the
645 * publish date of the previous post in the loop.
649 * @global string $currentday The day of the current post in the loop.
650 * @global string $previousday The day of the previous post in the loop.
652 * @return int 1 when new day, 0 if not a new day.
654 function is_new_day() {
655 global $currentday, $previousday;
656 if ( $currentday != $previousday )
663 * Build URL query based on an associative and, or indexed array.
665 * This is a convenient function for easily building url queries. It sets the
666 * separator to '&' and uses _http_build_query() function.
670 * @see _http_build_query() Used to build the query
671 * @see http://us2.php.net/manual/en/function.http-build-query.php for more on what
672 * http_build_query() does.
674 * @param array $data URL-encode key/value pairs.
675 * @return string URL-encoded string.
677 function build_query( $data ) {
678 return _http_build_query( $data, null, '&', '', false );
682 * From php.net (modified by Mark Jaquith to behave like the native PHP5 function).
687 * @see http://us1.php.net/manual/en/function.http-build-query.php
689 * @param array|object $data An array or object of data. Converted to array.
690 * @param string $prefix Optional. Numeric index. If set, start parameter numbering with it.
692 * @param string $sep Optional. Argument separator; defaults to 'arg_separator.output'.
694 * @param string $key Optional. Used to prefix key name. Default empty.
695 * @param bool $urlencode Optional. Whether to use urlencode() in the result. Default true.
697 * @return string The query string.
699 function _http_build_query( $data, $prefix = null, $sep = null, $key = '', $urlencode = true ) {
702 foreach ( (array) $data as $k => $v ) {
705 if ( is_int($k) && $prefix != null )
708 $k = $key . '%5B' . $k . '%5D';
711 elseif ( $v === false )
714 if ( is_array($v) || is_object($v) )
715 array_push($ret,_http_build_query($v, '', $sep, $k, $urlencode));
716 elseif ( $urlencode )
717 array_push($ret, $k.'='.urlencode($v));
719 array_push($ret, $k.'='.$v);
723 $sep = ini_get('arg_separator.output');
725 return implode($sep, $ret);
729 * Retrieve a modified URL query string.
731 * You can rebuild the URL and append a new query variable to the URL query by
732 * using this function. You can also retrieve the full URL with query data.
734 * Adding a single key & value or an associative array. Setting a key value to
735 * an empty string removes the key. Omitting oldquery_or_uri uses the $_SERVER
736 * value. Additional values provided are expected to be encoded appropriately
737 * with urlencode() or rawurlencode().
741 * @param string|array $param1 Either newkey or an associative_array.
742 * @param string $param2 Either newvalue or oldquery or URI.
743 * @param string $param3 Optional. Old query or URI.
744 * @return string New URL query string.
746 function add_query_arg() {
747 $args = func_get_args();
748 if ( is_array( $args[0] ) ) {
749 if ( count( $args ) < 2 || false === $args[1] )
750 $uri = $_SERVER['REQUEST_URI'];
754 if ( count( $args ) < 3 || false === $args[2] )
755 $uri = $_SERVER['REQUEST_URI'];
760 if ( $frag = strstr( $uri, '#' ) )
761 $uri = substr( $uri, 0, -strlen( $frag ) );
765 if ( 0 === stripos( $uri, 'http://' ) ) {
766 $protocol = 'http://';
767 $uri = substr( $uri, 7 );
768 } elseif ( 0 === stripos( $uri, 'https://' ) ) {
769 $protocol = 'https://';
770 $uri = substr( $uri, 8 );
775 if ( strpos( $uri, '?' ) !== false ) {
776 list( $base, $query ) = explode( '?', $uri, 2 );
778 } elseif ( $protocol || strpos( $uri, '=' ) === false ) {
786 wp_parse_str( $query, $qs );
787 $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
788 if ( is_array( $args[0] ) ) {
789 foreach ( $args[0] as $k => $v ) {
793 $qs[ $args[0] ] = $args[1];
796 foreach ( $qs as $k => $v ) {
801 $ret = build_query( $qs );
802 $ret = trim( $ret, '?' );
803 $ret = preg_replace( '#=(&|$)#', '$1', $ret );
804 $ret = $protocol . $base . $ret . $frag;
805 $ret = rtrim( $ret, '?' );
810 * Removes an item or list from the query string.
814 * @param string|array $key Query key or keys to remove.
815 * @param bool|string $query Optional. When false uses the $_SERVER value. Default false.
816 * @return string New URL query string.
818 function remove_query_arg( $key, $query = false ) {
819 if ( is_array( $key ) ) { // removing multiple keys
820 foreach ( $key as $k )
821 $query = add_query_arg( $k, false, $query );
824 return add_query_arg( $key, false, $query );
828 * Walks the array while sanitizing the contents.
832 * @param array $array Array to walk while sanitizing contents.
833 * @return array Sanitized $array.
835 function add_magic_quotes( $array ) {
836 foreach ( (array) $array as $k => $v ) {
837 if ( is_array( $v ) ) {
838 $array[$k] = add_magic_quotes( $v );
840 $array[$k] = addslashes( $v );
847 * HTTP request for URI to retrieve content.
851 * @see wp_safe_remote_get()
853 * @param string $uri URI/URL of web page to retrieve.
854 * @return false|string HTTP content. False on failure.
856 function wp_remote_fopen( $uri ) {
857 $parsed_url = @parse_url( $uri );
859 if ( !$parsed_url || !is_array( $parsed_url ) )
863 $options['timeout'] = 10;
865 $response = wp_safe_remote_get( $uri, $options );
867 if ( is_wp_error( $response ) )
870 return wp_remote_retrieve_body( $response );
874 * Set up the WordPress query.
878 * @global WP $wp_locale
879 * @global WP_Query $wp_query
880 * @global WP_Query $wp_the_query
882 * @param string|array $query_vars Default WP_Query arguments.
884 function wp( $query_vars = '' ) {
885 global $wp, $wp_query, $wp_the_query;
886 $wp->main( $query_vars );
888 if ( !isset($wp_the_query) )
889 $wp_the_query = $wp_query;
893 * Retrieve the description for the HTTP status.
897 * @global array $wp_header_to_desc
899 * @param int $code HTTP status code.
900 * @return string Empty string if not found, or description if found.
902 function get_status_header_desc( $code ) {
903 global $wp_header_to_desc;
905 $code = absint( $code );
907 if ( !isset( $wp_header_to_desc ) ) {
908 $wp_header_to_desc = array(
910 101 => 'Switching Protocols',
916 203 => 'Non-Authoritative Information',
918 205 => 'Reset Content',
919 206 => 'Partial Content',
920 207 => 'Multi-Status',
923 300 => 'Multiple Choices',
924 301 => 'Moved Permanently',
927 304 => 'Not Modified',
930 307 => 'Temporary Redirect',
932 400 => 'Bad Request',
933 401 => 'Unauthorized',
934 402 => 'Payment Required',
937 405 => 'Method Not Allowed',
938 406 => 'Not Acceptable',
939 407 => 'Proxy Authentication Required',
940 408 => 'Request Timeout',
943 411 => 'Length Required',
944 412 => 'Precondition Failed',
945 413 => 'Request Entity Too Large',
946 414 => 'Request-URI Too Long',
947 415 => 'Unsupported Media Type',
948 416 => 'Requested Range Not Satisfiable',
949 417 => 'Expectation Failed',
950 418 => 'I\'m a teapot',
951 422 => 'Unprocessable Entity',
953 424 => 'Failed Dependency',
954 426 => 'Upgrade Required',
955 428 => 'Precondition Required',
956 429 => 'Too Many Requests',
957 431 => 'Request Header Fields Too Large',
959 500 => 'Internal Server Error',
960 501 => 'Not Implemented',
961 502 => 'Bad Gateway',
962 503 => 'Service Unavailable',
963 504 => 'Gateway Timeout',
964 505 => 'HTTP Version Not Supported',
965 506 => 'Variant Also Negotiates',
966 507 => 'Insufficient Storage',
967 510 => 'Not Extended',
968 511 => 'Network Authentication Required',
972 if ( isset( $wp_header_to_desc[$code] ) )
973 return $wp_header_to_desc[$code];
979 * Set HTTP status header.
983 * @see get_status_header_desc()
985 * @param int $code HTTP status code.
987 function status_header( $code ) {
988 $description = get_status_header_desc( $code );
990 if ( empty( $description ) )
993 $protocol = $_SERVER['SERVER_PROTOCOL'];
994 if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
995 $protocol = 'HTTP/1.0';
996 $status_header = "$protocol $code $description";
997 if ( function_exists( 'apply_filters' ) )
1000 * Filter an HTTP status header.
1004 * @param string $status_header HTTP status header.
1005 * @param int $code HTTP status code.
1006 * @param string $description Description for the status code.
1007 * @param string $protocol Server protocol.
1009 $status_header = apply_filters( 'status_header', $status_header, $code, $description, $protocol );
1011 @header( $status_header, true, $code );
1015 * Get the header information to prevent caching.
1017 * The several different headers cover the different ways cache prevention
1018 * is handled by different browsers
1022 * @return array The associative array of header names and field values.
1024 function wp_get_nocache_headers() {
1026 'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
1027 'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
1028 'Pragma' => 'no-cache',
1031 if ( function_exists('apply_filters') ) {
1033 * Filter the cache-controlling headers.
1037 * @see wp_get_nocache_headers()
1039 * @param array $headers {
1040 * Header names and field values.
1042 * @type string $Expires Expires header.
1043 * @type string $Cache-Control Cache-Control header.
1044 * @type string $Pragma Pragma header.
1047 $headers = (array) apply_filters( 'nocache_headers', $headers );
1049 $headers['Last-Modified'] = false;
1054 * Set the headers to prevent caching for the different browsers.
1056 * Different browsers support different nocache headers, so several
1057 * headers must be sent so that all of them get the point that no
1058 * caching should occur.
1062 * @see wp_get_nocache_headers()
1064 function nocache_headers() {
1065 $headers = wp_get_nocache_headers();
1067 unset( $headers['Last-Modified'] );
1069 // In PHP 5.3+, make sure we are not sending a Last-Modified header.
1070 if ( function_exists( 'header_remove' ) ) {
1071 @header_remove( 'Last-Modified' );
1073 // In PHP 5.2, send an empty Last-Modified header, but only as a
1074 // last resort to override a header already sent. #WP23021
1075 foreach ( headers_list() as $header ) {
1076 if ( 0 === stripos( $header, 'Last-Modified' ) ) {
1077 $headers['Last-Modified'] = '';
1083 foreach( $headers as $name => $field_value )
1084 @header("{$name}: {$field_value}");
1088 * Set the headers for caching for 10 days with JavaScript content type.
1092 function cache_javascript_headers() {
1093 $expiresOffset = 10 * DAY_IN_SECONDS;
1095 header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
1096 header( "Vary: Accept-Encoding" ); // Handle proxies
1097 header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
1101 * Retrieve the number of database queries during the WordPress execution.
1105 * @global wpdb $wpdb WordPress database abstraction object.
1107 * @return int Number of database queries.
1109 function get_num_queries() {
1111 return $wpdb->num_queries;
1115 * Whether input is yes or no.
1117 * Must be 'y' to be true.
1121 * @param string $yn Character string containing either 'y' (yes) or 'n' (no).
1122 * @return bool True if yes, false on anything else.
1124 function bool_from_yn( $yn ) {
1125 return ( strtolower( $yn ) == 'y' );
1129 * Load the feed template from the use of an action hook.
1131 * If the feed action does not have a hook, then the function will die with a
1132 * message telling the visitor that the feed is not valid.
1134 * It is better to only have one hook for each feed.
1138 * @global WP_Query $wp_query Used to tell if the use a comment feed.
1140 function do_feed() {
1143 $feed = get_query_var( 'feed' );
1145 // Remove the pad, if present.
1146 $feed = preg_replace( '/^_+/', '', $feed );
1148 if ( $feed == '' || $feed == 'feed' )
1149 $feed = get_default_feed();
1151 $hook = 'do_feed_' . $feed;
1152 if ( ! has_action( $hook ) )
1153 wp_die( __( 'ERROR: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
1156 * Fires once the given feed is loaded.
1158 * The dynamic hook name, $hook, refers to the feed name.
1162 * @param bool $is_comment_feed Whether the feed is a comment feed.
1164 do_action( $hook, $wp_query->is_comment_feed );
1168 * Load the RDF RSS 0.91 Feed template.
1172 * @see load_template()
1174 function do_feed_rdf() {
1175 load_template( ABSPATH . WPINC . '/feed-rdf.php' );
1179 * Load the RSS 1.0 Feed Template.
1183 * @see load_template()
1185 function do_feed_rss() {
1186 load_template( ABSPATH . WPINC . '/feed-rss.php' );
1190 * Load either the RSS2 comment feed or the RSS2 posts feed.
1194 * @see load_template()
1196 * @param bool $for_comments True for the comment feed, false for normal feed.
1198 function do_feed_rss2( $for_comments ) {
1199 if ( $for_comments )
1200 load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
1202 load_template( ABSPATH . WPINC . '/feed-rss2.php' );
1206 * Load either Atom comment feed or Atom posts feed.
1210 * @see load_template()
1212 * @param bool $for_comments True for the comment feed, false for normal feed.
1214 function do_feed_atom( $for_comments ) {
1216 load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
1218 load_template( ABSPATH . WPINC . '/feed-atom.php' );
1222 * Display the robots.txt file content.
1224 * The echo content should be with usage of the permalinks or for creating the
1229 function do_robots() {
1230 header( 'Content-Type: text/plain; charset=utf-8' );
1233 * Fires when displaying the robots.txt file.
1237 do_action( 'do_robotstxt' );
1239 $output = "User-agent: *\n";
1240 $public = get_option( 'blog_public' );
1241 if ( '0' == $public ) {
1242 $output .= "Disallow: /\n";
1244 $site_url = parse_url( site_url() );
1245 $path = ( !empty( $site_url['path'] ) ) ? $site_url['path'] : '';
1246 $output .= "Disallow: $path/wp-admin/\n";
1250 * Filter the robots.txt output.
1254 * @param string $output Robots.txt output.
1255 * @param bool $public Whether the site is considered "public".
1257 echo apply_filters( 'robots_txt', $output, $public );
1261 * Test whether blog is already installed.
1263 * The cache will be checked first. If you have a cache plugin, which saves
1264 * the cache values, then this will work. If you use the default WordPress
1265 * cache, and the database goes away, then you might have problems.
1267 * Checks for the 'siteurl' option for whether WordPress is installed.
1271 * @global wpdb $wpdb WordPress database abstraction object.
1273 * @return bool Whether the blog is already installed.
1275 function is_blog_installed() {
1279 * Check cache first. If options table goes away and we have true
1282 if ( wp_cache_get( 'is_blog_installed' ) )
1285 $suppress = $wpdb->suppress_errors();
1286 if ( ! defined( 'WP_INSTALLING' ) ) {
1287 $alloptions = wp_load_alloptions();
1289 // If siteurl is not set to autoload, check it specifically
1290 if ( !isset( $alloptions['siteurl'] ) )
1291 $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
1293 $installed = $alloptions['siteurl'];
1294 $wpdb->suppress_errors( $suppress );
1296 $installed = !empty( $installed );
1297 wp_cache_set( 'is_blog_installed', $installed );
1302 // If visiting repair.php, return true and let it take over.
1303 if ( defined( 'WP_REPAIRING' ) )
1306 $suppress = $wpdb->suppress_errors();
1309 * Loop over the WP tables. If none exist, then scratch install is allowed.
1310 * If one or more exist, suggest table repair since we got here because the
1311 * options table could not be accessed.
1313 $wp_tables = $wpdb->tables();
1314 foreach ( $wp_tables as $table ) {
1315 // The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
1316 if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
1318 if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
1321 if ( ! $wpdb->get_results( "DESCRIBE $table;" ) )
1324 // One or more tables exist. We are insane.
1326 wp_load_translations_early();
1328 // Die with a DB error.
1329 $wpdb->error = sprintf( __( 'One or more database tables are unavailable. The database may need to be <a href="%s">repaired</a>.' ), 'maint/repair.php?referrer=is_blog_installed' );
1333 $wpdb->suppress_errors( $suppress );
1335 wp_cache_set( 'is_blog_installed', false );
1341 * Retrieve URL with nonce added to URL query.
1345 * @param string $actionurl URL to add nonce action.
1346 * @param int|string $action Optional. Nonce action name. Default -1.
1347 * @param string $name Optional. Nonce name. Default '_wpnonce'.
1348 * @return string Escaped URL with nonce action added.
1350 function wp_nonce_url( $actionurl, $action = -1, $name = '_wpnonce' ) {
1351 $actionurl = str_replace( '&', '&', $actionurl );
1352 return esc_html( add_query_arg( $name, wp_create_nonce( $action ), $actionurl ) );
1356 * Retrieve or display nonce hidden field for forms.
1358 * The nonce field is used to validate that the contents of the form came from
1359 * the location on the current site and not somewhere else. The nonce does not
1360 * offer absolute protection, but should protect against most cases. It is very
1361 * important to use nonce field in forms.
1363 * The $action and $name are optional, but if you want to have better security,
1364 * it is strongly suggested to set those two parameters. It is easier to just
1365 * call the function without any parameters, because validation of the nonce
1366 * doesn't require any parameters, but since crackers know what the default is
1367 * it won't be difficult for them to find a way around your nonce and cause
1370 * The input name will be whatever $name value you gave. The input value will be
1371 * the nonce creation value.
1375 * @param int|string $action Optional. Action name. Default -1.
1376 * @param string $name Optional. Nonce name. Default '_wpnonce'.
1377 * @param bool $referer Optional. Whether to set the referer field for validation. Default true.
1378 * @param bool $echo Optional. Whether to display or return hidden form field. Default true.
1379 * @return string Nonce field HTML markup.
1381 function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1382 $name = esc_attr( $name );
1383 $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
1386 $nonce_field .= wp_referer_field( false );
1391 return $nonce_field;
1395 * Retrieve or display referer hidden field for forms.
1397 * The referer link is the current Request URI from the server super global. The
1398 * input name is '_wp_http_referer', in case you wanted to check manually.
1402 * @param bool $echo Optional. Whether to echo or return the referer field. Default true.
1403 * @return string Referer field HTML markup.
1405 function wp_referer_field( $echo = true ) {
1406 $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. esc_attr( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . '" />';
1409 echo $referer_field;
1410 return $referer_field;
1414 * Retrieve or display original referer hidden field for forms.
1416 * The input name is '_wp_original_http_referer' and will be either the same
1417 * value of wp_referer_field(), if that was posted already or it will be the
1418 * current page, if it doesn't exist.
1422 * @param bool $echo Optional. Whether to echo the original http referer. Default true.
1423 * @param string $jump_back_to Optional. Can be 'previous' or page you want to jump back to.
1424 * Default 'current'.
1425 * @return string Original referer field.
1427 function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
1428 if ( ! $ref = wp_get_original_referer() ) {
1429 $ref = 'previous' == $jump_back_to ? wp_get_referer() : wp_unslash( $_SERVER['REQUEST_URI'] );
1431 $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( $ref ) . '" />';
1433 echo $orig_referer_field;
1434 return $orig_referer_field;
1438 * Retrieve referer from '_wp_http_referer' or HTTP referer.
1440 * If it's the same as the current request URL, will return false.
1444 * @return false|string False on failure. Referer URL on success.
1446 function wp_get_referer() {
1447 if ( ! function_exists( 'wp_validate_redirect' ) )
1450 if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
1451 $ref = wp_unslash( $_REQUEST['_wp_http_referer'] );
1452 elseif ( ! empty( $_SERVER['HTTP_REFERER'] ) )
1453 $ref = wp_unslash( $_SERVER['HTTP_REFERER'] );
1455 if ( $ref && $ref !== wp_unslash( $_SERVER['REQUEST_URI'] ) )
1456 return wp_validate_redirect( $ref, false );
1461 * Retrieve original referer that was posted, if it exists.
1465 * @return string|false False if no original referer or original referer if set.
1467 function wp_get_original_referer() {
1468 if ( ! empty( $_REQUEST['_wp_original_http_referer'] ) && function_exists( 'wp_validate_redirect' ) )
1469 return wp_validate_redirect( wp_unslash( $_REQUEST['_wp_original_http_referer'] ), false );
1474 * Recursive directory creation based on full path.
1476 * Will attempt to set permissions on folders.
1480 * @param string $target Full path to attempt to create.
1481 * @return bool Whether the path was created. True if path already exists.
1483 function wp_mkdir_p( $target ) {
1486 // Strip the protocol.
1487 if ( wp_is_stream( $target ) ) {
1488 list( $wrapper, $target ) = explode( '://', $target, 2 );
1491 // From php.net/mkdir user contributed notes.
1492 $target = str_replace( '//', '/', $target );
1494 // Put the wrapper back on the target.
1495 if ( $wrapper !== null ) {
1496 $target = $wrapper . '://' . $target;
1500 * Safe mode fails with a trailing slash under certain PHP versions.
1501 * Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
1503 $target = rtrim($target, '/');
1504 if ( empty($target) )
1507 if ( file_exists( $target ) )
1508 return @is_dir( $target );
1510 // We need to find the permissions of the parent folder that exists and inherit that.
1511 $target_parent = dirname( $target );
1512 while ( '.' != $target_parent && ! is_dir( $target_parent ) ) {
1513 $target_parent = dirname( $target_parent );
1516 // Get the permission bits.
1517 if ( $stat = @stat( $target_parent ) ) {
1518 $dir_perms = $stat['mode'] & 0007777;
1523 if ( @mkdir( $target, $dir_perms, true ) ) {
1526 * If a umask is set that modifies $dir_perms, we'll have to re-set
1527 * the $dir_perms correctly with chmod()
1529 if ( $dir_perms != ( $dir_perms & ~umask() ) ) {
1530 $folder_parts = explode( '/', substr( $target, strlen( $target_parent ) + 1 ) );
1531 for ( $i = 1, $c = count( $folder_parts ); $i <= $c; $i++ ) {
1532 @chmod( $target_parent . '/' . implode( '/', array_slice( $folder_parts, 0, $i ) ), $dir_perms );
1543 * Test if a give filesystem path is absolute.
1545 * For example, '/foo/bar', or 'c:\windows'.
1549 * @param string $path File path.
1550 * @return bool True if path is absolute, false is not absolute.
1552 function path_is_absolute( $path ) {
1554 * This is definitive if true but fails if $path does not exist or contains
1557 if ( realpath($path) == $path )
1560 if ( strlen($path) == 0 || $path[0] == '.' )
1563 // Windows allows absolute paths like this.
1564 if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
1567 // A path starting with / or \ is absolute; anything else is relative.
1568 return ( $path[0] == '/' || $path[0] == '\\' );
1572 * Join two filesystem paths together.
1574 * For example, 'give me $path relative to $base'. If the $path is absolute,
1575 * then it the full path is returned.
1579 * @param string $base Base path.
1580 * @param string $path Path relative to $base.
1581 * @return string The path with the base or absolute path.
1583 function path_join( $base, $path ) {
1584 if ( path_is_absolute($path) )
1587 return rtrim($base, '/') . '/' . ltrim($path, '/');
1591 * Normalize a filesystem path.
1593 * Replaces backslashes with forward slashes for Windows systems, and ensures
1594 * no duplicate slashes exist.
1598 * @param string $path Path to normalize.
1599 * @return string Normalized path.
1601 function wp_normalize_path( $path ) {
1602 $path = str_replace( '\\', '/', $path );
1603 $path = preg_replace( '|/+|','/', $path );
1608 * Determine a writable directory for temporary files.
1610 * Function's preference is the return value of sys_get_temp_dir(),
1611 * followed by your PHP temporary upload directory, followed by WP_CONTENT_DIR,
1612 * before finally defaulting to /tmp/
1614 * In the event that this function does not find a writable location,
1615 * It may be overridden by the WP_TEMP_DIR constant in your wp-config.php file.
1619 * @staticvar string $temp
1621 * @return string Writable temporary directory.
1623 function get_temp_dir() {
1625 if ( defined('WP_TEMP_DIR') )
1626 return trailingslashit(WP_TEMP_DIR);
1629 return trailingslashit( $temp );
1631 if ( function_exists('sys_get_temp_dir') ) {
1632 $temp = sys_get_temp_dir();
1633 if ( @is_dir( $temp ) && wp_is_writable( $temp ) )
1634 return trailingslashit( $temp );
1637 $temp = ini_get('upload_tmp_dir');
1638 if ( @is_dir( $temp ) && wp_is_writable( $temp ) )
1639 return trailingslashit( $temp );
1641 $temp = WP_CONTENT_DIR . '/';
1642 if ( is_dir( $temp ) && wp_is_writable( $temp ) )
1649 * Determine if a directory is writable.
1651 * This function is used to work around certain ACL issues in PHP primarily
1652 * affecting Windows Servers.
1656 * @see win_is_writable()
1658 * @param string $path Path to check for write-ability.
1659 * @return bool Whether the path is writable.
1661 function wp_is_writable( $path ) {
1662 if ( 'WIN' === strtoupper( substr( PHP_OS, 0, 3 ) ) )
1663 return win_is_writable( $path );
1665 return @is_writable( $path );
1669 * Workaround for Windows bug in is_writable() function
1671 * PHP has issues with Windows ACL's for determine if a
1672 * directory is writable or not, this works around them by
1673 * checking the ability to open files rather than relying
1674 * upon PHP to interprate the OS ACL.
1678 * @see http://bugs.php.net/bug.php?id=27609
1679 * @see http://bugs.php.net/bug.php?id=30931
1681 * @param string $path Windows path to check for write-ability.
1682 * @return bool Whether the path is writable.
1684 function win_is_writable( $path ) {
1686 if ( $path[strlen( $path ) - 1] == '/' ) { // if it looks like a directory, check a random file within the directory
1687 return win_is_writable( $path . uniqid( mt_rand() ) . '.tmp');
1688 } elseif ( is_dir( $path ) ) { // If it's a directory (and not a file) check a random file within the directory
1689 return win_is_writable( $path . '/' . uniqid( mt_rand() ) . '.tmp' );
1691 // check tmp file for read/write capabilities
1692 $should_delete_tmp_file = !file_exists( $path );
1693 $f = @fopen( $path, 'a' );
1697 if ( $should_delete_tmp_file )
1703 * Get an array containing the current upload directory's path and url.
1705 * Checks the 'upload_path' option, which should be from the web root folder,
1706 * and if it isn't empty it will be used. If it is empty, then the path will be
1707 * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
1708 * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
1710 * The upload URL path is set either by the 'upload_url_path' option or by using
1711 * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
1713 * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
1714 * the administration settings panel), then the time will be used. The format
1715 * will be year first and then month.
1717 * If the path couldn't be created, then an error will be returned with the key
1718 * 'error' containing the error message. The error suggests that the parent
1719 * directory is not writable by the server.
1721 * On success, the returned array will have many indices:
1722 * 'path' - base directory and sub directory or full path to upload directory.
1723 * 'url' - base url and sub directory or absolute URL to upload directory.
1724 * 'subdir' - sub directory if uploads use year/month folders option is on.
1725 * 'basedir' - path without subdir.
1726 * 'baseurl' - URL path without subdir.
1727 * 'error' - set to false.
1731 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null.
1732 * @return array See above for description.
1734 function wp_upload_dir( $time = null ) {
1735 $siteurl = get_option( 'siteurl' );
1736 $upload_path = trim( get_option( 'upload_path' ) );
1738 if ( empty( $upload_path ) || 'wp-content/uploads' == $upload_path ) {
1739 $dir = WP_CONTENT_DIR . '/uploads';
1740 } elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) {
1741 // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
1742 $dir = path_join( ABSPATH, $upload_path );
1744 $dir = $upload_path;
1747 if ( !$url = get_option( 'upload_url_path' ) ) {
1748 if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) )
1749 $url = WP_CONTENT_URL . '/uploads';
1751 $url = trailingslashit( $siteurl ) . $upload_path;
1755 * Honor the value of UPLOADS. This happens as long as ms-files rewriting is disabled.
1756 * We also sometimes obey UPLOADS when rewriting is enabled -- see the next block.
1758 if ( defined( 'UPLOADS' ) && ! ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) ) {
1759 $dir = ABSPATH . UPLOADS;
1760 $url = trailingslashit( $siteurl ) . UPLOADS;
1763 // If multisite (and if not the main site in a post-MU network)
1764 if ( is_multisite() && ! ( is_main_network() && is_main_site() && defined( 'MULTISITE' ) ) ) {
1766 if ( ! get_site_option( 'ms_files_rewriting' ) ) {
1768 * If ms-files rewriting is disabled (networks created post-3.5), it is fairly
1769 * straightforward: Append sites/%d if we're not on the main site (for post-MU
1770 * networks). (The extra directory prevents a four-digit ID from conflicting with
1771 * a year-based directory for the main site. But if a MU-era network has disabled
1772 * ms-files rewriting manually, they don't need the extra directory, as they never
1773 * had wp-content/uploads for the main site.)
1776 if ( defined( 'MULTISITE' ) )
1777 $ms_dir = '/sites/' . get_current_blog_id();
1779 $ms_dir = '/' . get_current_blog_id();
1784 } elseif ( defined( 'UPLOADS' ) && ! ms_is_switched() ) {
1786 * Handle the old-form ms-files.php rewriting if the network still has that enabled.
1787 * When ms-files rewriting is enabled, then we only listen to UPLOADS when:
1788 * 1) We are not on the main site in a post-MU network, as wp-content/uploads is used
1790 * 2) We are not switched, as ms_upload_constants() hardcodes these constants to reflect
1791 * the original blog ID.
1793 * Rather than UPLOADS, we actually use BLOGUPLOADDIR if it is set, as it is absolute.
1794 * (And it will be set, see ms_upload_constants().) Otherwise, UPLOADS can be used, as
1795 * as it is relative to ABSPATH. For the final piece: when UPLOADS is used with ms-files
1796 * rewriting in multisite, the resulting URL is /files. (#WP22702 for background.)
1799 if ( defined( 'BLOGUPLOADDIR' ) )
1800 $dir = untrailingslashit( BLOGUPLOADDIR );
1802 $dir = ABSPATH . UPLOADS;
1803 $url = trailingslashit( $siteurl ) . 'files';
1811 if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
1812 // Generate the yearly and monthly dirs
1814 $time = current_time( 'mysql' );
1815 $y = substr( $time, 0, 4 );
1816 $m = substr( $time, 5, 2 );
1824 * Filter the uploads directory data.
1828 * @param array $uploads Array of upload directory data with keys of 'path',
1829 * 'url', 'subdir, 'basedir', and 'error'.
1831 $uploads = apply_filters( 'upload_dir',
1835 'subdir' => $subdir,
1836 'basedir' => $basedir,
1837 'baseurl' => $baseurl,
1841 // Make sure we have an uploads directory.
1842 if ( ! wp_mkdir_p( $uploads['path'] ) ) {
1843 if ( 0 === strpos( $uploads['basedir'], ABSPATH ) )
1844 $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir'];
1846 $error_path = basename( $uploads['basedir'] ) . $uploads['subdir'];
1848 $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
1849 $uploads['error'] = $message;
1856 * Get a filename that is sanitized and unique for the given directory.
1858 * If the filename is not unique, then a number will be added to the filename
1859 * before the extension, and will continue adding numbers until the filename is
1862 * The callback is passed three parameters, the first one is the directory, the
1863 * second is the filename, and the third is the extension.
1867 * @param string $dir Directory.
1868 * @param string $filename File name.
1869 * @param callback $unique_filename_callback Callback. Default null.
1870 * @return string New filename, if given wasn't unique.
1872 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
1873 // Sanitize the file name before we begin processing.
1874 $filename = sanitize_file_name($filename);
1876 // Separate the filename into a name and extension.
1877 $info = pathinfo($filename);
1878 $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
1879 $name = basename($filename, $ext);
1881 // Edge case: if file is named '.ext', treat as an empty name.
1882 if ( $name === $ext )
1886 * Increment the file number until we have a unique file to save in $dir.
1887 * Use callback if supplied.
1889 if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
1890 $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext );
1894 // Change '.ext' to lower case.
1895 if ( $ext && strtolower($ext) != $ext ) {
1896 $ext2 = strtolower($ext);
1897 $filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
1899 // Check for both lower and upper case extension or image sub-sizes may be overwritten.
1900 while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
1901 $new_number = $number + 1;
1902 $filename = str_replace( "$number$ext", "$new_number$ext", $filename );
1903 $filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
1904 $number = $new_number;
1909 while ( file_exists( $dir . "/$filename" ) ) {
1910 if ( '' == "$number$ext" )
1911 $filename = $filename . ++$number . $ext;
1913 $filename = str_replace( "$number$ext", ++$number . $ext, $filename );
1921 * Create a file in the upload folder with given content.
1923 * If there is an error, then the key 'error' will exist with the error message.
1924 * If success, then the key 'file' will have the unique file path, the 'url' key
1925 * will have the link to the new file. and the 'error' key will be set to false.
1927 * This function will not move an uploaded file to the upload folder. It will
1928 * create a new file with the content in $bits parameter. If you move the upload
1929 * file, read the content of the uploaded file, and then you can give the
1930 * filename and content to this function, which will add it to the upload
1933 * The permissions will be set on the new file automatically by this function.
1937 * @param string $name Filename.
1938 * @param null|string $deprecated Never used. Set to null.
1939 * @param mixed $bits File content
1940 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null.
1943 function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
1944 if ( !empty( $deprecated ) )
1945 _deprecated_argument( __FUNCTION__, '2.0' );
1947 if ( empty( $name ) )
1948 return array( 'error' => __( 'Empty filename' ) );
1950 $wp_filetype = wp_check_filetype( $name );
1951 if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) )
1952 return array( 'error' => __( 'Invalid file type' ) );
1954 $upload = wp_upload_dir( $time );
1956 if ( $upload['error'] !== false )
1960 * Filter whether to treat the upload bits as an error.
1962 * Passing a non-array to the filter will effectively short-circuit preparing
1963 * the upload bits, returning that value instead.
1967 * @param mixed $upload_bits_error An array of upload bits data, or a non-array error to return.
1969 $upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) );
1970 if ( !is_array( $upload_bits_error ) ) {
1971 $upload[ 'error' ] = $upload_bits_error;
1975 $filename = wp_unique_filename( $upload['path'], $name );
1977 $new_file = $upload['path'] . "/$filename";
1978 if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
1979 if ( 0 === strpos( $upload['basedir'], ABSPATH ) )
1980 $error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir'];
1982 $error_path = basename( $upload['basedir'] ) . $upload['subdir'];
1984 $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
1985 return array( 'error' => $message );
1988 $ifp = @ fopen( $new_file, 'wb' );
1990 return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
1992 @fwrite( $ifp, $bits );
1996 // Set correct file permissions
1997 $stat = @ stat( dirname( $new_file ) );
1998 $perms = $stat['mode'] & 0007777;
1999 $perms = $perms & 0000666;
2000 @ chmod( $new_file, $perms );
2004 $url = $upload['url'] . "/$filename";
2006 return array( 'file' => $new_file, 'url' => $url, 'error' => false );
2010 * Retrieve the file type based on the extension name.
2014 * @param string $ext The extension to search.
2015 * @return string|void The file type, example: audio, video, document, spreadsheet, etc.
2017 function wp_ext2type( $ext ) {
2018 $ext = strtolower( $ext );
2021 * Filter file type based on the extension name.
2025 * @see wp_ext2type()
2027 * @param array $ext2type Multi-dimensional array with extensions for a default set
2030 $ext2type = apply_filters( 'ext2type', array(
2031 'image' => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico' ),
2032 'audio' => array( 'aac', 'ac3', 'aif', 'aiff', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
2033 'video' => array( '3g2', '3gp', '3gpp', 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ),
2034 'document' => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'xps', 'oxps', 'rtf', 'wp', 'wpd', 'psd', 'xcf' ),
2035 'spreadsheet' => array( 'numbers', 'ods', 'xls', 'xlsx', 'xlsm', 'xlsb' ),
2036 'interactive' => array( 'swf', 'key', 'ppt', 'pptx', 'pptm', 'pps', 'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
2037 'text' => array( 'asc', 'csv', 'tsv', 'txt' ),
2038 'archive' => array( 'bz2', 'cab', 'dmg', 'gz', 'rar', 'sea', 'sit', 'sqx', 'tar', 'tgz', 'zip', '7z' ),
2039 'code' => array( 'css', 'htm', 'html', 'php', 'js' ),
2042 foreach ( $ext2type as $type => $exts )
2043 if ( in_array( $ext, $exts ) )
2048 * Retrieve the file type from the file name.
2050 * You can optionally define the mime array, if needed.
2054 * @param string $filename File name or path.
2055 * @param array $mimes Optional. Key is the file extension with value as the mime type.
2056 * @return array Values with extension first and mime type.
2058 function wp_check_filetype( $filename, $mimes = null ) {
2059 if ( empty($mimes) )
2060 $mimes = get_allowed_mime_types();
2064 foreach ( $mimes as $ext_preg => $mime_match ) {
2065 $ext_preg = '!\.(' . $ext_preg . ')$!i';
2066 if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
2067 $type = $mime_match;
2068 $ext = $ext_matches[1];
2073 return compact( 'ext', 'type' );
2077 * Attempt to determine the real file type of a file.
2079 * If unable to, the file name extension will be used to determine type.
2081 * If it's determined that the extension does not match the file's real type,
2082 * then the "proper_filename" value will be set with a proper filename and extension.
2084 * Currently this function only supports validating images known to getimagesize().
2088 * @param string $file Full path to the file.
2089 * @param string $filename The name of the file (may differ from $file due to $file being
2090 * in a tmp directory).
2091 * @param array $mimes Optional. Key is the file extension with value as the mime type.
2092 * @return array Values for the extension, MIME, and either a corrected filename or false
2093 * if original $filename is valid.
2095 function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
2096 $proper_filename = false;
2098 // Do basic extension validation and MIME mapping
2099 $wp_filetype = wp_check_filetype( $filename, $mimes );
2100 $ext = $wp_filetype['ext'];
2101 $type = $wp_filetype['type'];
2103 // We can't do any further validation without a file to work with
2104 if ( ! file_exists( $file ) ) {
2105 return compact( 'ext', 'type', 'proper_filename' );
2108 // We're able to validate images using GD
2109 if ( $type && 0 === strpos( $type, 'image/' ) && function_exists('getimagesize') ) {
2111 // Attempt to figure out what type of image it actually is
2112 $imgstats = @getimagesize( $file );
2114 // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
2115 if ( !empty($imgstats['mime']) && $imgstats['mime'] != $type ) {
2117 * Filter the list mapping image mime types to their respective extensions.
2121 * @param array $mime_to_ext Array of image mime types and their matching extensions.
2123 $mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array(
2124 'image/jpeg' => 'jpg',
2125 'image/png' => 'png',
2126 'image/gif' => 'gif',
2127 'image/bmp' => 'bmp',
2128 'image/tiff' => 'tif',
2131 // Replace whatever is after the last period in the filename with the correct extension
2132 if ( ! empty( $mime_to_ext[ $imgstats['mime'] ] ) ) {
2133 $filename_parts = explode( '.', $filename );
2134 array_pop( $filename_parts );
2135 $filename_parts[] = $mime_to_ext[ $imgstats['mime'] ];
2136 $new_filename = implode( '.', $filename_parts );
2138 if ( $new_filename != $filename ) {
2139 $proper_filename = $new_filename; // Mark that it changed
2141 // Redefine the extension / MIME
2142 $wp_filetype = wp_check_filetype( $new_filename, $mimes );
2143 $ext = $wp_filetype['ext'];
2144 $type = $wp_filetype['type'];
2150 * Filter the "real" file type of the given file.
2154 * @param array $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
2155 * 'proper_filename' keys.
2156 * @param string $file Full path to the file.
2157 * @param string $filename The name of the file (may differ from $file due to
2158 * $file being in a tmp directory).
2159 * @param array $mimes Key is the file extension with value as the mime type.
2161 return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes );
2165 * Retrieve list of mime types and file extensions.
2168 * @since 4.2.0 Support was added for GIMP (xcf) files.
2170 * @return array Array of mime types keyed by the file extension regex corresponding to those types.
2172 function wp_get_mime_types() {
2174 * Filter the list of mime types and file extensions.
2176 * This filter should be used to add, not remove, mime types. To remove
2177 * mime types, use the 'upload_mimes' filter.
2181 * @param array $wp_get_mime_types Mime types keyed by the file extension regex
2182 * corresponding to those types.
2184 return apply_filters( 'mime_types', array(
2186 'jpg|jpeg|jpe' => 'image/jpeg',
2187 'gif' => 'image/gif',
2188 'png' => 'image/png',
2189 'bmp' => 'image/bmp',
2190 'tiff|tif' => 'image/tiff',
2191 'ico' => 'image/x-icon',
2193 'asf|asx' => 'video/x-ms-asf',
2194 'wmv' => 'video/x-ms-wmv',
2195 'wmx' => 'video/x-ms-wmx',
2196 'wm' => 'video/x-ms-wm',
2197 'avi' => 'video/avi',
2198 'divx' => 'video/divx',
2199 'flv' => 'video/x-flv',
2200 'mov|qt' => 'video/quicktime',
2201 'mpeg|mpg|mpe' => 'video/mpeg',
2202 'mp4|m4v' => 'video/mp4',
2203 'ogv' => 'video/ogg',
2204 'webm' => 'video/webm',
2205 'mkv' => 'video/x-matroska',
2206 '3gp|3gpp' => 'video/3gpp', // Can also be audio
2207 '3g2|3gp2' => 'video/3gpp2', // Can also be audio
2209 'txt|asc|c|cc|h|srt' => 'text/plain',
2210 'csv' => 'text/csv',
2211 'tsv' => 'text/tab-separated-values',
2212 'ics' => 'text/calendar',
2213 'rtx' => 'text/richtext',
2214 'css' => 'text/css',
2215 'htm|html' => 'text/html',
2216 'vtt' => 'text/vtt',
2217 'dfxp' => 'application/ttaf+xml',
2219 'mp3|m4a|m4b' => 'audio/mpeg',
2220 'ra|ram' => 'audio/x-realaudio',
2221 'wav' => 'audio/wav',
2222 'ogg|oga' => 'audio/ogg',
2223 'mid|midi' => 'audio/midi',
2224 'wma' => 'audio/x-ms-wma',
2225 'wax' => 'audio/x-ms-wax',
2226 'mka' => 'audio/x-matroska',
2227 // Misc application formats.
2228 'rtf' => 'application/rtf',
2229 'js' => 'application/javascript',
2230 'pdf' => 'application/pdf',
2231 'swf' => 'application/x-shockwave-flash',
2232 'class' => 'application/java',
2233 'tar' => 'application/x-tar',
2234 'zip' => 'application/zip',
2235 'gz|gzip' => 'application/x-gzip',
2236 'rar' => 'application/rar',
2237 '7z' => 'application/x-7z-compressed',
2238 'exe' => 'application/x-msdownload',
2239 'psd' => 'application/octet-stream',
2240 'xcf' => 'application/octet-stream',
2241 // MS Office formats.
2242 'doc' => 'application/msword',
2243 'pot|pps|ppt' => 'application/vnd.ms-powerpoint',
2244 'wri' => 'application/vnd.ms-write',
2245 'xla|xls|xlt|xlw' => 'application/vnd.ms-excel',
2246 'mdb' => 'application/vnd.ms-access',
2247 'mpp' => 'application/vnd.ms-project',
2248 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2249 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
2250 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
2251 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
2252 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2253 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
2254 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
2255 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
2256 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
2257 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
2258 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2259 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
2260 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2261 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
2262 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
2263 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
2264 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
2265 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
2266 'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
2267 'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
2268 'oxps' => 'application/oxps',
2269 'xps' => 'application/vnd.ms-xpsdocument',
2270 // OpenOffice formats.
2271 'odt' => 'application/vnd.oasis.opendocument.text',
2272 'odp' => 'application/vnd.oasis.opendocument.presentation',
2273 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
2274 'odg' => 'application/vnd.oasis.opendocument.graphics',
2275 'odc' => 'application/vnd.oasis.opendocument.chart',
2276 'odb' => 'application/vnd.oasis.opendocument.database',
2277 'odf' => 'application/vnd.oasis.opendocument.formula',
2278 // WordPerfect formats.
2279 'wp|wpd' => 'application/wordperfect',
2281 'key' => 'application/vnd.apple.keynote',
2282 'numbers' => 'application/vnd.apple.numbers',
2283 'pages' => 'application/vnd.apple.pages',
2287 * Retrieve list of allowed mime types and file extensions.
2291 * @param int|WP_User $user Optional. User to check. Defaults to current user.
2292 * @return array Array of mime types keyed by the file extension regex corresponding
2295 function get_allowed_mime_types( $user = null ) {
2296 $t = wp_get_mime_types();
2298 unset( $t['swf'], $t['exe'] );
2299 if ( function_exists( 'current_user_can' ) )
2300 $unfiltered = $user ? user_can( $user, 'unfiltered_html' ) : current_user_can( 'unfiltered_html' );
2302 if ( empty( $unfiltered ) )
2303 unset( $t['htm|html'] );
2306 * Filter list of allowed mime types and file extensions.
2310 * @param array $t Mime types keyed by the file extension regex corresponding to
2311 * those types. 'swf' and 'exe' removed from full list. 'htm|html' also
2312 * removed depending on '$user' capabilities.
2313 * @param int|WP_User|null $user User ID, User object or null if not provided (indicates current user).
2315 return apply_filters( 'upload_mimes', $t, $user );
2319 * Display "Are You Sure" message to confirm the action being taken.
2321 * If the action has the nonce explain message, then it will be displayed
2322 * along with the "Are you sure?" message.
2326 * @param string $action The nonce action.
2328 function wp_nonce_ays( $action ) {
2329 if ( 'log-out' == $action ) {
2330 $html = sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'name' ) ) . '</p><p>';
2331 $redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
2332 $html .= sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url( $redirect_to ) );
2334 $html = __( 'Are you sure you want to do this?' );
2335 if ( wp_get_referer() )
2336 $html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
2339 wp_die( $html, __( 'WordPress Failure Notice' ), 403 );
2343 * Kill WordPress execution and display HTML message with error message.
2345 * This function complements the `die()` PHP function. The difference is that
2346 * HTML will be displayed to the user. It is recommended to use this function
2347 * only when the execution should not continue any further. It is not recommended
2348 * to call this function very often, and try to handle as many errors as possible
2349 * silently or more gracefully.
2351 * As a shorthand, the desired HTTP response code may be passed as an integer to
2352 * the `$title` parameter (the default title would apply) or the `$args` parameter.
2355 * @since 4.1.0 The `$title` and `$args` parameters were changed to optionally accept
2356 * an integer to be used as the response code.
2358 * @param string|WP_Error $message Optional. Error message. If this is a {@see WP_Error} object,
2359 * the error's messages are used. Default empty.
2360 * @param string|int $title Optional. Error title. If `$message` is a `WP_Error` object,
2361 * error data with the key 'title' may be used to specify the title.
2362 * If `$title` is an integer, then it is treated as the response
2363 * code. Default empty.
2364 * @param string|array|int $args {
2365 * Optional. Arguments to control behavior. If `$args` is an integer, then it is treated
2366 * as the response code. Default empty array.
2368 * @type int $response The HTTP response code. Default 500.
2369 * @type bool $back_link Whether to include a link to go back. Default false.
2370 * @type string $text_direction The text direction. This is only useful internally, when WordPress
2371 * is still loading and the site's locale is not set up yet. Accepts 'rtl'.
2372 * Default is the value of {@see is_rtl()}.
2375 function wp_die( $message = '', $title = '', $args = array() ) {
2377 if ( is_int( $args ) ) {
2378 $args = array( 'response' => $args );
2379 } elseif ( is_int( $title ) ) {
2380 $args = array( 'response' => $title );
2384 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2386 * Filter callback for killing WordPress execution for AJAX requests.
2390 * @param callback $function Callback function name.
2392 $function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
2393 } elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
2395 * Filter callback for killing WordPress execution for XML-RPC requests.
2399 * @param callback $function Callback function name.
2401 $function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
2404 * Filter callback for killing WordPress execution for all non-AJAX, non-XML-RPC requests.
2408 * @param callback $function Callback function name.
2410 $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
2413 call_user_func( $function, $message, $title, $args );
2417 * Kill WordPress execution and display HTML message with error message.
2419 * This is the default handler for wp_die if you want a custom one for your
2420 * site then you can overload using the wp_die_handler filter in wp_die
2425 * @param string $message Error message.
2426 * @param string $title Optional. Error title. Default empty.
2427 * @param string|array $args Optional. Arguments to control behavior. Default empty array.
2429 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
2430 $defaults = array( 'response' => 500 );
2431 $r = wp_parse_args($args, $defaults);
2433 $have_gettext = function_exists('__');
2435 if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
2436 if ( empty( $title ) ) {
2437 $error_data = $message->get_error_data();
2438 if ( is_array( $error_data ) && isset( $error_data['title'] ) )
2439 $title = $error_data['title'];
2441 $errors = $message->get_error_messages();
2442 switch ( count( $errors ) ) {
2447 $message = "<p>{$errors[0]}</p>";
2450 $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
2453 } elseif ( is_string( $message ) ) {
2454 $message = "<p>$message</p>";
2457 if ( isset( $r['back_link'] ) && $r['back_link'] ) {
2458 $back_text = $have_gettext? __('« Back') : '« Back';
2459 $message .= "\n<p><a href='javascript:history.back()'>$back_text</a></p>";
2462 if ( ! did_action( 'admin_head' ) ) :
2463 if ( !headers_sent() ) {
2464 status_header( $r['response'] );
2466 header( 'Content-Type: text/html; charset=utf-8' );
2469 if ( empty($title) )
2470 $title = $have_gettext ? __('WordPress › Error') : 'WordPress › Error';
2472 $text_direction = 'ltr';
2473 if ( isset($r['text_direction']) && 'rtl' == $r['text_direction'] )
2474 $text_direction = 'rtl';
2475 elseif ( function_exists( 'is_rtl' ) && is_rtl() )
2476 $text_direction = 'rtl';
2479 <!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono
2481 <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) && function_exists( 'is_rtl' ) ) language_attributes(); else echo "dir='$text_direction'"; ?>>
2483 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2484 <meta name="viewport" content="width=device-width">
2485 <title><?php echo $title ?></title>
2486 <style type="text/css">
2488 background: #f1f1f1;
2493 font-family: "Open Sans", sans-serif;
2497 -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);
2498 box-shadow: 0 1px 3px rgba(0,0,0,0.13);
2501 border-bottom: 1px solid #dadada;
2504 font: 24px "Open Sans", sans-serif;
2507 padding-bottom: 7px;
2515 margin: 25px 0 20px;
2518 font-family: Consolas, Monaco, monospace;
2521 margin-bottom: 10px;
2526 text-decoration: none;
2532 background: #f7f7f7;
2533 border: 1px solid #cccccc;
2535 display: inline-block;
2536 text-decoration: none;
2541 padding: 0 10px 1px;
2543 -webkit-border-radius: 3px;
2544 -webkit-appearance: none;
2546 white-space: nowrap;
2547 -webkit-box-sizing: border-box;
2548 -moz-box-sizing: border-box;
2549 box-sizing: border-box;
2551 -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08);
2552 box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08);
2553 vertical-align: top;
2556 .button.button-large {
2564 background: #fafafa;
2570 -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,.2);
2571 box-shadow: 1px 1px 1px rgba(0,0,0,.2);
2578 -webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
2579 box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
2582 <?php if ( 'rtl' == $text_direction ) : ?>
2583 body { font-family: Tahoma, Arial; }
2587 <body id="error-page">
2588 <?php endif; // ! did_action( 'admin_head' ) ?>
2589 <?php echo $message; ?>
2597 * Kill WordPress execution and display XML message with error message.
2599 * This is the handler for wp_die when processing XMLRPC requests.
2604 * @global wp_xmlrpc_server $wp_xmlrpc_server
2606 * @param string $message Error message.
2607 * @param string $title Optional. Error title. Default empty.
2608 * @param string|array $args Optional. Arguments to control behavior. Default empty array.
2610 function _xmlrpc_wp_die_handler( $message, $title = '', $args = array() ) {
2611 global $wp_xmlrpc_server;
2612 $defaults = array( 'response' => 500 );
2614 $r = wp_parse_args($args, $defaults);
2616 if ( $wp_xmlrpc_server ) {
2617 $error = new IXR_Error( $r['response'] , $message);
2618 $wp_xmlrpc_server->output( $error->getXml() );
2624 * Kill WordPress ajax execution.
2626 * This is the handler for wp_die when processing Ajax requests.
2631 * @param string $message Optional. Response to print. Default empty.
2633 function _ajax_wp_die_handler( $message = '' ) {
2634 if ( is_scalar( $message ) )
2635 die( (string) $message );
2640 * Kill WordPress execution.
2642 * This is the handler for wp_die when processing APP requests.
2647 * @param string $message Optional. Response to print. Default empty.
2649 function _scalar_wp_die_handler( $message = '' ) {
2650 if ( is_scalar( $message ) )
2651 die( (string) $message );
2656 * Encode a variable into JSON, with some sanity checks.
2660 * @param mixed $data Variable (usually an array or object) to encode as JSON.
2661 * @param int $options Optional. Options to be passed to json_encode(). Default 0.
2662 * @param int $depth Optional. Maximum depth to walk through $data. Must be
2663 * greater than 0. Default 512.
2664 * @return string|false The JSON encoded string, or false if it cannot be encoded.
2666 function wp_json_encode( $data, $options = 0, $depth = 512 ) {
2668 * json_encode() has had extra params added over the years.
2669 * $options was added in 5.3, and $depth in 5.5.
2670 * We need to make sure we call it with the correct arguments.
2672 if ( version_compare( PHP_VERSION, '5.5', '>=' ) ) {
2673 $args = array( $data, $options, $depth );
2674 } elseif ( version_compare( PHP_VERSION, '5.3', '>=' ) ) {
2675 $args = array( $data, $options );
2677 $args = array( $data );
2680 $json = call_user_func_array( 'json_encode', $args );
2682 // If json_encode() was successful, no need to do more sanity checking.
2683 // ... unless we're in an old version of PHP, and json_encode() returned
2684 // a string containing 'null'. Then we need to do more sanity checking.
2685 if ( false !== $json && ( version_compare( PHP_VERSION, '5.5', '>=' ) || false === strpos( $json, 'null' ) ) ) {
2690 $args[0] = _wp_json_sanity_check( $data, $depth );
2691 } catch ( Exception $e ) {
2695 return call_user_func_array( 'json_encode', $args );
2699 * Perform sanity checks on data that shall be encoded to JSON.
2705 * @see wp_json_encode()
2707 * @param mixed $data Variable (usually an array or object) to encode as JSON.
2708 * @param int $depth Maximum depth to walk through $data. Must be greater than 0.
2709 * @return mixed The sanitized data that shall be encoded to JSON.
2711 function _wp_json_sanity_check( $data, $depth ) {
2713 throw new Exception( 'Reached depth limit' );
2716 if ( is_array( $data ) ) {
2718 foreach ( $data as $id => $el ) {
2719 // Don't forget to sanitize the ID!
2720 if ( is_string( $id ) ) {
2721 $clean_id = _wp_json_convert_string( $id );
2726 // Check the element type, so that we're only recursing if we really have to.
2727 if ( is_array( $el ) || is_object( $el ) ) {
2728 $output[ $clean_id ] = _wp_json_sanity_check( $el, $depth - 1 );
2729 } elseif ( is_string( $el ) ) {
2730 $output[ $clean_id ] = _wp_json_convert_string( $el );
2732 $output[ $clean_id ] = $el;
2735 } elseif ( is_object( $data ) ) {
2736 $output = new stdClass;
2737 foreach ( $data as $id => $el ) {
2738 if ( is_string( $id ) ) {
2739 $clean_id = _wp_json_convert_string( $id );
2744 if ( is_array( $el ) || is_object( $el ) ) {
2745 $output->$clean_id = _wp_json_sanity_check( $el, $depth - 1 );
2746 } elseif ( is_string( $el ) ) {
2747 $output->$clean_id = _wp_json_convert_string( $el );
2749 $output->$clean_id = $el;
2752 } elseif ( is_string( $data ) ) {
2753 return _wp_json_convert_string( $data );
2762 * Convert a string to UTF-8, so that it can be safely encoded to JSON.
2768 * @see _wp_json_sanity_check()
2770 * @staticvar bool $use_mb
2772 * @param string $string The string which is to be converted.
2773 * @return string The checked string.
2775 function _wp_json_convert_string( $string ) {
2776 static $use_mb = null;
2777 if ( is_null( $use_mb ) ) {
2778 $use_mb = function_exists( 'mb_convert_encoding' );
2782 $encoding = mb_detect_encoding( $string, mb_detect_order(), true );
2784 return mb_convert_encoding( $string, 'UTF-8', $encoding );
2786 return mb_convert_encoding( $string, 'UTF-8', 'UTF-8' );
2789 return wp_check_invalid_utf8( $string, true );
2794 * Send a JSON response back to an Ajax request.
2798 * @param mixed $response Variable (usually an array or object) to encode as JSON,
2799 * then print and die.
2801 function wp_send_json( $response ) {
2802 @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
2803 echo wp_json_encode( $response );
2804 if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
2811 * Send a JSON response back to an Ajax request, indicating success.
2815 * @param mixed $data Data to encode as JSON, then print and die.
2817 function wp_send_json_success( $data = null ) {
2818 $response = array( 'success' => true );
2820 if ( isset( $data ) )
2821 $response['data'] = $data;
2823 wp_send_json( $response );
2827 * Send a JSON response back to an Ajax request, indicating failure.
2829 * If the `$data` parameter is a {@see WP_Error} object, the errors
2830 * within the object are processed and output as an array of error
2831 * codes and corresponding messages. All other types are output
2832 * without further processing.
2835 * @since 4.1.0 The `$data` parameter is now processed if a {@see WP_Error}
2836 * object is passed in.
2838 * @param mixed $data Data to encode as JSON, then print and die.
2840 function wp_send_json_error( $data = null ) {
2841 $response = array( 'success' => false );
2843 if ( isset( $data ) ) {
2844 if ( is_wp_error( $data ) ) {
2846 foreach ( $data->errors as $code => $messages ) {
2847 foreach ( $messages as $message ) {
2848 $result[] = array( 'code' => $code, 'message' => $message );
2852 $response['data'] = $result;
2854 $response['data'] = $data;
2858 wp_send_json( $response );
2862 * Retrieve the WordPress home page URL.
2864 * If the constant named 'WP_HOME' exists, then it will be used and returned
2865 * by the function. This can be used to counter the redirection on your local
2866 * development environment.
2873 * @param string $url URL for the home location.
2874 * @return string Homepage location.
2876 function _config_wp_home( $url = '' ) {
2877 if ( defined( 'WP_HOME' ) )
2878 return untrailingslashit( WP_HOME );
2883 * Retrieve the WordPress site URL.
2885 * If the constant named 'WP_SITEURL' is defined, then the value in that
2886 * constant will always be returned. This can be used for debugging a site
2887 * on your localhost while not having to change the database to your URL.
2894 * @param string $url URL to set the WordPress site location.
2895 * @return string The WordPress Site URL.
2897 function _config_wp_siteurl( $url = '' ) {
2898 if ( defined( 'WP_SITEURL' ) )
2899 return untrailingslashit( WP_SITEURL );
2904 * Set the localized direction for MCE plugin.
2906 * Will only set the direction to 'rtl', if the WordPress locale has
2907 * the text direction set to 'rtl'.
2909 * Fills in the 'directionality' setting, enables the 'directionality'
2910 * plugin, and adds the 'ltr' button to 'toolbar1', formerly
2911 * 'theme_advanced_buttons1' array keys. These keys are then returned
2912 * in the $input (TinyMCE settings) array.
2917 * @param array $input MCE settings array.
2918 * @return array Direction set for 'rtl', if needed by locale.
2920 function _mce_set_direction( $input ) {
2922 $input['directionality'] = 'rtl';
2924 if ( ! empty( $input['plugins'] ) && strpos( $input['plugins'], 'directionality' ) === false ) {
2925 $input['plugins'] .= ',directionality';
2928 if ( ! empty( $input['toolbar1'] ) && ! preg_match( '/\bltr\b/', $input['toolbar1'] ) ) {
2929 $input['toolbar1'] .= ',ltr';
2938 * Convert smiley code to the icon graphic file equivalent.
2940 * You can turn off smilies, by going to the write setting screen and unchecking
2941 * the box, or by setting 'use_smilies' option to false or removing the option.
2943 * Plugins may override the default smiley list by setting the $wpsmiliestrans
2944 * to an array, with the key the code the blogger types in and the value the
2947 * The $wp_smiliessearch global is for the regular expression and is set each
2948 * time the function is called.
2950 * The full list of smilies can be found in the function and won't be listed in
2951 * the description. Probably should create a Codex page for it, so that it is
2954 * @global array $wpsmiliestrans
2955 * @global array $wp_smiliessearch
2959 function smilies_init() {
2960 global $wpsmiliestrans, $wp_smiliessearch;
2962 // don't bother setting up smilies if they are disabled
2963 if ( !get_option( 'use_smilies' ) )
2966 if ( !isset( $wpsmiliestrans ) ) {
2967 $wpsmiliestrans = array(
2968 ':mrgreen:' => 'mrgreen.png',
2969 ':neutral:' => "\xf0\x9f\x98\x90",
2970 ':twisted:' => "\xf0\x9f\x98\x88",
2971 ':arrow:' => "\xe2\x9e\xa1",
2972 ':shock:' => "\xf0\x9f\x98\xaf",
2973 ':smile:' => 'simple-smile.png',
2974 ':???:' => "\xf0\x9f\x98\x95",
2975 ':cool:' => "\xf0\x9f\x98\x8e",
2976 ':evil:' => "\xf0\x9f\x91\xbf",
2977 ':grin:' => "\xf0\x9f\x98\x80",
2978 ':idea:' => "\xf0\x9f\x92\xa1",
2979 ':oops:' => "\xf0\x9f\x98\xb3",
2980 ':razz:' => "\xf0\x9f\x98\x9b",
2981 ':roll:' => 'rolleyes.png',
2982 ':wink:' => "\xf0\x9f\x98\x89",
2983 ':cry:' => "\xf0\x9f\x98\xa5",
2984 ':eek:' => "\xf0\x9f\x98\xae",
2985 ':lol:' => "\xf0\x9f\x98\x86",
2986 ':mad:' => "\xf0\x9f\x98\xa1",
2987 ':sad:' => 'frownie.png',
2988 '8-)' => "\xf0\x9f\x98\x8e",
2989 '8-O' => "\xf0\x9f\x98\xaf",
2990 ':-(' => 'frownie.png',
2991 ':-)' => 'simple-smile.png',
2992 ':-?' => "\xf0\x9f\x98\x95",
2993 ':-D' => "\xf0\x9f\x98\x80",
2994 ':-P' => "\xf0\x9f\x98\x9b",
2995 ':-o' => "\xf0\x9f\x98\xae",
2996 ':-x' => "\xf0\x9f\x98\xa1",
2997 ':-|' => "\xf0\x9f\x98\x90",
2998 ';-)' => "\xf0\x9f\x98\x89",
2999 // This one transformation breaks regular text with frequency.
3000 // '8)' => "\xf0\x9f\x98\x8e",
3001 '8O' => "\xf0\x9f\x98\xaf",
3002 ':(' => 'frownie.png',
3003 ':)' => 'simple-smile.png',
3004 ':?' => "\xf0\x9f\x98\x95",
3005 ':D' => "\xf0\x9f\x98\x80",
3006 ':P' => "\xf0\x9f\x98\x9b",
3007 ':o' => "\xf0\x9f\x98\xae",
3008 ':x' => "\xf0\x9f\x98\xa1",
3009 ':|' => "\xf0\x9f\x98\x90",
3010 ';)' => "\xf0\x9f\x98\x89",
3011 ':!:' => "\xe2\x9d\x97",
3012 ':?:' => "\xe2\x9d\x93",
3016 if (count($wpsmiliestrans) == 0) {
3021 * NOTE: we sort the smilies in reverse key order. This is to make sure
3022 * we match the longest possible smilie (:???: vs :?) as the regular
3023 * expression used below is first-match
3025 krsort($wpsmiliestrans);
3027 $spaces = wp_spaces_regexp();
3029 // Begin first "subpattern"
3030 $wp_smiliessearch = '/(?<=' . $spaces . '|^)';
3033 foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
3034 $firstchar = substr($smiley, 0, 1);
3035 $rest = substr($smiley, 1);
3038 if ($firstchar != $subchar) {
3039 if ($subchar != '') {
3040 $wp_smiliessearch .= ')(?=' . $spaces . '|$)'; // End previous "subpattern"
3041 $wp_smiliessearch .= '|(?<=' . $spaces . '|^)'; // Begin another "subpattern"
3043 $subchar = $firstchar;
3044 $wp_smiliessearch .= preg_quote($firstchar, '/') . '(?:';
3046 $wp_smiliessearch .= '|';
3048 $wp_smiliessearch .= preg_quote($rest, '/');
3051 $wp_smiliessearch .= ')(?=' . $spaces . '|$)/m';
3056 * Merge user defined arguments into defaults array.
3058 * This function is used throughout WordPress to allow for both string or array
3059 * to be merged into another array.
3063 * @param string|array $args Value to merge with $defaults
3064 * @param array $defaults Optional. Array that serves as the defaults. Default empty.
3065 * @return array Merged user defined values with defaults.
3067 function wp_parse_args( $args, $defaults = '' ) {
3068 if ( is_object( $args ) )
3069 $r = get_object_vars( $args );
3070 elseif ( is_array( $args ) )
3073 wp_parse_str( $args, $r );
3075 if ( is_array( $defaults ) )
3076 return array_merge( $defaults, $r );
3081 * Clean up an array, comma- or space-separated list of IDs.
3085 * @param array|string $list List of ids.
3086 * @return array Sanitized array of IDs.
3088 function wp_parse_id_list( $list ) {
3089 if ( !is_array($list) )
3090 $list = preg_split('/[\s,]+/', $list);
3092 return array_unique(array_map('absint', $list));
3096 * Extract a slice of an array, given a list of keys.
3100 * @param array $array The original array.
3101 * @param array $keys The list of keys.
3102 * @return array The array slice.
3104 function wp_array_slice_assoc( $array, $keys ) {
3106 foreach ( $keys as $key )
3107 if ( isset( $array[ $key ] ) )
3108 $slice[ $key ] = $array[ $key ];
3114 * Filters a list of objects, based on a set of key => value arguments.
3118 * @param array $list An array of objects to filter
3119 * @param array $args Optional. An array of key => value arguments to match
3120 * against each object. Default empty array.
3121 * @param string $operator Optional. The logical operation to perform. 'or' means
3122 * only one element from the array needs to match; 'and'
3123 * means all elements must match. Default 'and'.
3124 * @param bool|string $field A field from the object to place instead of the entire object.
3126 * @return array A list of objects or object fields.
3128 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
3129 if ( ! is_array( $list ) )
3132 $list = wp_list_filter( $list, $args, $operator );
3135 $list = wp_list_pluck( $list, $field );
3141 * Filters a list of objects, based on a set of key => value arguments.
3145 * @param array $list An array of objects to filter.
3146 * @param array $args Optional. An array of key => value arguments to match
3147 * against each object. Default empty array.
3148 * @param string $operator Optional. The logical operation to perform. 'AND' means
3149 * all elements from the array must match. 'OR' means only
3150 * one element needs to match. 'NOT' means no elements may
3151 * match. Default 'AND'.
3152 * @return array Array of found values.
3154 function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
3155 if ( ! is_array( $list ) )
3158 if ( empty( $args ) )
3161 $operator = strtoupper( $operator );
3162 $count = count( $args );
3163 $filtered = array();
3165 foreach ( $list as $key => $obj ) {
3166 $to_match = (array) $obj;
3169 foreach ( $args as $m_key => $m_value ) {
3170 if ( array_key_exists( $m_key, $to_match ) && $m_value == $to_match[ $m_key ] )
3174 if ( ( 'AND' == $operator && $matched == $count )
3175 || ( 'OR' == $operator && $matched > 0 )
3176 || ( 'NOT' == $operator && 0 == $matched ) ) {
3177 $filtered[$key] = $obj;
3185 * Pluck a certain field out of each object in a list.
3187 * This has the same functionality and prototype of
3188 * array_column() (PHP 5.5) but also supports objects.
3191 * @since 4.0.0 $index_key parameter added.
3193 * @param array $list List of objects or arrays
3194 * @param int|string $field Field from the object to place instead of the entire object
3195 * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
3197 * @return array Array of found values. If `$index_key` is set, an array of found values with keys
3198 * corresponding to `$index_key`. If `$index_key` is null, array keys from the original
3199 * `$list` will be preserved in the results.
3201 function wp_list_pluck( $list, $field, $index_key = null ) {
3202 if ( ! $index_key ) {
3204 * This is simple. Could at some point wrap array_column()
3205 * if we knew we had an array of arrays.
3207 foreach ( $list as $key => $value ) {
3208 if ( is_object( $value ) ) {
3209 $list[ $key ] = $value->$field;
3211 $list[ $key ] = $value[ $field ];
3218 * When index_key is not set for a particular item, push the value
3219 * to the end of the stack. This is how array_column() behaves.
3222 foreach ( $list as $value ) {
3223 if ( is_object( $value ) ) {
3224 if ( isset( $value->$index_key ) ) {
3225 $newlist[ $value->$index_key ] = $value->$field;
3227 $newlist[] = $value->$field;
3230 if ( isset( $value[ $index_key ] ) ) {
3231 $newlist[ $value[ $index_key ] ] = $value[ $field ];
3233 $newlist[] = $value[ $field ];
3242 * Determines if Widgets library should be loaded.
3244 * Checks to make sure that the widgets library hasn't already been loaded.
3245 * If it hasn't, then it will load the widgets library and run an action hook.
3249 function wp_maybe_load_widgets() {
3251 * Filter whether to load the Widgets library.
3253 * Passing a falsey value to the filter will effectively short-circuit
3254 * the Widgets library from loading.
3258 * @param bool $wp_maybe_load_widgets Whether to load the Widgets library.
3261 if ( ! apply_filters( 'load_default_widgets', true ) ) {
3265 require_once( ABSPATH . WPINC . '/default-widgets.php' );
3267 add_action( '_admin_menu', 'wp_widgets_add_menu' );
3271 * Append the Widgets menu to the themes main menu.
3275 * @global array $submenu
3277 function wp_widgets_add_menu() {
3280 if ( ! current_theme_supports( 'widgets' ) )
3283 $submenu['themes.php'][7] = array( __( 'Widgets' ), 'edit_theme_options', 'widgets.php' );
3284 ksort( $submenu['themes.php'], SORT_NUMERIC );
3288 * Flush all output buffers for PHP 5.2.
3290 * Make sure all output buffers are flushed before our singletons are destroyed.
3294 function wp_ob_end_flush_all() {
3295 $levels = ob_get_level();
3296 for ($i=0; $i<$levels; $i++)
3301 * Load custom DB error or display WordPress DB error.
3303 * If a file exists in the wp-content directory named db-error.php, then it will
3304 * be loaded instead of displaying the WordPress DB error. If it is not found,
3305 * then the WordPress DB error will be displayed instead.
3307 * The WordPress DB error sets the HTTP status header to 500 to try to prevent
3308 * search engines from caching the message. Custom DB messages should do the
3311 * This function was backported to WordPress 2.3.2, but originally was added
3312 * in WordPress 2.5.0.
3316 * @global wpdb $wpdb WordPress database abstraction object.
3318 function dead_db() {
3321 wp_load_translations_early();
3323 // Load custom DB error template, if present.
3324 if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
3325 require_once( WP_CONTENT_DIR . '/db-error.php' );
3329 // If installing or in the admin, provide the verbose message.
3330 if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
3331 wp_die($wpdb->error);
3333 // Otherwise, be terse.
3334 status_header( 500 );
3336 header( 'Content-Type: text/html; charset=utf-8' );
3339 <html xmlns="http://www.w3.org/1999/xhtml"<?php if ( is_rtl() ) echo ' dir="rtl"'; ?>>
3341 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
3342 <title><?php _e( 'Database Error' ); ?></title>
3346 <h1><?php _e( 'Error establishing a database connection' ); ?></h1>
3354 * Convert a value to non-negative integer.
3358 * @param mixed $maybeint Data you wish to have converted to a non-negative integer.
3359 * @return int A non-negative integer.
3361 function absint( $maybeint ) {
3362 return abs( intval( $maybeint ) );
3366 * Mark a function as deprecated and inform when it has been used.
3368 * There is a hook deprecated_function_run that will be called that can be used
3369 * to get the backtrace up to what file and function called the deprecated
3372 * The current behavior is to trigger a user error if WP_DEBUG is true.
3374 * This function is to be used in every function that is deprecated.
3379 * @param string $function The function that was called.
3380 * @param string $version The version of WordPress that deprecated the function.
3381 * @param string $replacement Optional. The function that should have been called. Default null.
3383 function _deprecated_function( $function, $version, $replacement = null ) {
3386 * Fires when a deprecated function is called.
3390 * @param string $function The function that was called.
3391 * @param string $replacement The function that should have been called.
3392 * @param string $version The version of WordPress that deprecated the function.
3394 do_action( 'deprecated_function_run', $function, $replacement, $version );
3397 * Filter whether to trigger an error for deprecated functions.
3401 * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
3403 if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
3404 if ( function_exists( '__' ) ) {
3405 if ( ! is_null( $replacement ) )
3406 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
3408 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
3410 if ( ! is_null( $replacement ) )
3411 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $function, $version, $replacement ) );
3413 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $function, $version ) );
3419 * Marks a constructor as deprecated and informs when it has been used.
3421 * Similar to _deprecated_function(), but with different strings. Used to
3422 * remove PHP4 style constructors.
3424 * The current behavior is to trigger a user error if `WP_DEBUG` is true.
3426 * This function is to be used in every PHP4 style constructor method that is deprecated.
3431 * @param string $class The class containing the deprecated constructor.
3432 * @param string $version The version of WordPress that deprecated the function.
3434 function _deprecated_constructor( $class, $version ) {
3437 * Fires when a deprecated constructor is called.
3441 * @param string $class The class containing the deprecated constructor.
3442 * @param string $version The version of WordPress that deprecated the function.
3444 do_action( 'deprecated_constructor_run', $class, $version );
3447 * Filter whether to trigger an error for deprecated functions.
3449 * `WP_DEBUG` must be true in addition to the filter evaluating to true.
3453 * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
3455 if ( WP_DEBUG && apply_filters( 'deprecated_constructor_trigger_error', true ) ) {
3456 if ( function_exists( '__' ) ) {
3457 trigger_error( sprintf( __( 'The called constructor method for %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ), $class, $version, '<pre>__construct()</pre>' ) );
3459 trigger_error( sprintf( 'The called constructor method for %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $class, $version, '<pre>__construct()</pre>' ) );
3466 * Mark a file as deprecated and inform when it has been used.
3468 * There is a hook deprecated_file_included that will be called that can be used
3469 * to get the backtrace up to what file and function included the deprecated
3472 * The current behavior is to trigger a user error if WP_DEBUG is true.
3474 * This function is to be used in every file that is deprecated.
3479 * @param string $file The file that was included.
3480 * @param string $version The version of WordPress that deprecated the file.
3481 * @param string $replacement Optional. The file that should have been included based on ABSPATH.
3483 * @param string $message Optional. A message regarding the change. Default empty.
3485 function _deprecated_file( $file, $version, $replacement = null, $message = '' ) {
3488 * Fires when a deprecated file is called.
3492 * @param string $file The file that was called.
3493 * @param string $replacement The file that should have been included based on ABSPATH.
3494 * @param string $version The version of WordPress that deprecated the file.
3495 * @param string $message A message regarding the change.
3497 do_action( 'deprecated_file_included', $file, $replacement, $version, $message );
3500 * Filter whether to trigger an error for deprecated files.
3504 * @param bool $trigger Whether to trigger the error for deprecated files. Default true.
3506 if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) {
3507 $message = empty( $message ) ? '' : ' ' . $message;
3508 if ( function_exists( '__' ) ) {
3509 if ( ! is_null( $replacement ) )
3510 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message );
3512 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) . $message );
3514 if ( ! is_null( $replacement ) )
3515 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $file, $version, $replacement ) . $message );
3517 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $file, $version ) . $message );
3522 * Mark a function argument as deprecated and inform when it has been used.
3524 * This function is to be used whenever a deprecated function argument is used.
3525 * Before this function is called, the argument must be checked for whether it was
3526 * used by comparing it to its default value or evaluating whether it is empty.
3529 * if ( ! empty( $deprecated ) ) {
3530 * _deprecated_argument( __FUNCTION__, '3.0' );
3534 * There is a hook deprecated_argument_run that will be called that can be used
3535 * to get the backtrace up to what file and function used the deprecated
3538 * The current behavior is to trigger a user error if WP_DEBUG is true.
3543 * @param string $function The function that was called.
3544 * @param string $version The version of WordPress that deprecated the argument used.
3545 * @param string $message Optional. A message regarding the change. Default null.
3547 function _deprecated_argument( $function, $version, $message = null ) {
3550 * Fires when a deprecated argument is called.
3554 * @param string $function The function that was called.
3555 * @param string $message A message regarding the change.
3556 * @param string $version The version of WordPress that deprecated the argument used.
3558 do_action( 'deprecated_argument_run', $function, $message, $version );
3561 * Filter whether to trigger an error for deprecated arguments.
3565 * @param bool $trigger Whether to trigger the error for deprecated arguments. Default true.
3567 if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
3568 if ( function_exists( '__' ) ) {
3569 if ( ! is_null( $message ) )
3570 trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s'), $function, $version, $message ) );
3572 trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
3574 if ( ! is_null( $message ) )
3575 trigger_error( sprintf( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s', $function, $version, $message ) );
3577 trigger_error( sprintf( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.', $function, $version ) );
3583 * Mark something as being incorrectly called.
3585 * There is a hook doing_it_wrong_run that will be called that can be used
3586 * to get the backtrace up to what file and function called the deprecated
3589 * The current behavior is to trigger a user error if WP_DEBUG is true.
3594 * @param string $function The function that was called.
3595 * @param string $message A message explaining what has been done incorrectly.
3596 * @param string $version The version of WordPress where the message was added.
3598 function _doing_it_wrong( $function, $message, $version ) {
3601 * Fires when the given function is being used incorrectly.
3605 * @param string $function The function that was called.
3606 * @param string $message A message explaining what has been done incorrectly.
3607 * @param string $version The version of WordPress where the message was added.
3609 do_action( 'doing_it_wrong_run', $function, $message, $version );
3612 * Filter whether to trigger an error for _doing_it_wrong() calls.
3616 * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
3618 if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
3619 if ( function_exists( '__' ) ) {
3620 $version = is_null( $version ) ? '' : sprintf( __( '(This message was added in version %s.)' ), $version );
3621 $message .= ' ' . __( 'Please see <a href="https://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.' );
3622 trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s' ), $function, $message, $version ) );
3624 $version = is_null( $version ) ? '' : sprintf( '(This message was added in version %s.)', $version );
3625 $message .= ' Please see <a href="https://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.';
3626 trigger_error( sprintf( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', $function, $message, $version ) );
3632 * Is the server running earlier than 1.5.0 version of lighttpd?
3636 * @return bool Whether the server is running lighttpd < 1.5.0.
3638 function is_lighttpd_before_150() {
3639 $server_parts = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] )? $_SERVER['SERVER_SOFTWARE'] : '' );
3640 $server_parts[1] = isset( $server_parts[1] )? $server_parts[1] : '';
3641 return 'lighttpd' == $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' );
3645 * Does the specified module exist in the Apache config?
3649 * @global bool $is_apache
3651 * @param string $mod The module, e.g. mod_rewrite.
3652 * @param bool $default Optional. The default return value if the module is not found. Default false.
3653 * @return bool Whether the specified module is loaded.
3655 function apache_mod_loaded($mod, $default = false) {
3661 if ( function_exists( 'apache_get_modules' ) ) {
3662 $mods = apache_get_modules();
3663 if ( in_array($mod, $mods) )
3665 } elseif ( function_exists( 'phpinfo' ) && false === strpos( ini_get( 'disable_functions' ), 'phpinfo' ) ) {
3668 $phpinfo = ob_get_clean();
3669 if ( false !== strpos($phpinfo, $mod) )
3676 * Check if IIS 7+ supports pretty permalinks.
3680 * @global bool $is_iis7
3682 * @return bool Whether IIS7 supports permalinks.
3684 function iis7_supports_permalinks() {
3687 $supports_permalinks = false;
3689 /* First we check if the DOMDocument class exists. If it does not exist, then we cannot
3690 * easily update the xml configuration file, hence we just bail out and tell user that
3691 * pretty permalinks cannot be used.
3693 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
3694 * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
3695 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
3696 * via ISAPI then pretty permalinks will not work.
3698 $supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && ( PHP_SAPI == 'cgi-fcgi' );
3702 * Filter whether IIS 7+ supports pretty permalinks.
3706 * @param bool $supports_permalinks Whether IIS7 supports permalinks. Default false.
3708 return apply_filters( 'iis7_supports_permalinks', $supports_permalinks );
3712 * File validates against allowed set of defined rules.
3714 * A return value of '1' means that the $file contains either '..' or './'. A
3715 * return value of '2' means that the $file contains ':' after the first
3716 * character. A return value of '3' means that the file is not in the allowed
3721 * @param string $file File path.
3722 * @param array $allowed_files List of allowed files.
3723 * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
3725 function validate_file( $file, $allowed_files = '' ) {
3726 if ( false !== strpos( $file, '..' ) )
3729 if ( false !== strpos( $file, './' ) )
3732 if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files ) )
3735 if (':' == substr( $file, 1, 1 ) )
3742 * Determine if SSL is used.
3746 * @return bool True if SSL, false if not used.
3749 if ( isset($_SERVER['HTTPS']) ) {
3750 if ( 'on' == strtolower($_SERVER['HTTPS']) )
3752 if ( '1' == $_SERVER['HTTPS'] )
3754 } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
3761 * Whether SSL login should be forced.
3765 * @see force_ssl_admin()
3767 * @param string|bool $force Optional Whether to force SSL login. Default null.
3768 * @return bool True if forced, false if not forced.
3770 function force_ssl_login( $force = null ) {
3771 return force_ssl_admin( $force );
3775 * Whether to force SSL used for the Administration Screens.
3779 * @staticvar bool $forced
3781 * @param string|bool $force Optional. Whether to force SSL in admin screens. Default null.
3782 * @return bool True if forced, false if not forced.
3784 function force_ssl_admin( $force = null ) {
3785 static $forced = false;
3787 if ( !is_null( $force ) ) {
3788 $old_forced = $forced;
3797 * Guess the URL for the site.
3799 * Will remove wp-admin links to retrieve only return URLs not in the wp-admin
3804 * @return string The guessed URL.
3806 function wp_guess_url() {
3807 if ( defined('WP_SITEURL') && '' != WP_SITEURL ) {
3810 $abspath_fix = str_replace( '\\', '/', ABSPATH );
3811 $script_filename_dir = dirname( $_SERVER['SCRIPT_FILENAME'] );
3813 // The request is for the admin
3814 if ( strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) !== false || strpos( $_SERVER['REQUEST_URI'], 'wp-login.php' ) !== false ) {
3815 $path = preg_replace( '#/(wp-admin/.*|wp-login.php)#i', '', $_SERVER['REQUEST_URI'] );
3817 // The request is for a file in ABSPATH
3818 } elseif ( $script_filename_dir . '/' == $abspath_fix ) {
3819 // Strip off any file/query params in the path
3820 $path = preg_replace( '#/[^/]*$#i', '', $_SERVER['PHP_SELF'] );
3823 if ( false !== strpos( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) {
3824 // Request is hitting a file inside ABSPATH
3825 $directory = str_replace( ABSPATH, '', $script_filename_dir );
3826 // Strip off the sub directory, and any file/query params
3827 $path = preg_replace( '#/' . preg_quote( $directory, '#' ) . '/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] );
3828 } elseif ( false !== strpos( $abspath_fix, $script_filename_dir ) ) {
3829 // Request is hitting a file above ABSPATH
3830 $subdirectory = substr( $abspath_fix, strpos( $abspath_fix, $script_filename_dir ) + strlen( $script_filename_dir ) );
3831 // Strip off any file/query params from the path, appending the sub directory to the install
3832 $path = preg_replace( '#/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] ) . $subdirectory;
3834 $path = $_SERVER['REQUEST_URI'];
3838 $schema = is_ssl() ? 'https://' : 'http://'; // set_url_scheme() is not defined yet
3839 $url = $schema . $_SERVER['HTTP_HOST'] . $path;
3842 return rtrim($url, '/');
3846 * Temporarily suspend cache additions.
3848 * Stops more data being added to the cache, but still allows cache retrieval.
3849 * This is useful for actions, such as imports, when a lot of data would otherwise
3850 * be almost uselessly added to the cache.
3852 * Suspension lasts for a single page load at most. Remember to call this
3853 * function again if you wish to re-enable cache adds earlier.
3857 * @staticvar bool $_suspend
3859 * @param bool $suspend Optional. Suspends additions if true, re-enables them if false.
3860 * @return bool The current suspend setting
3862 function wp_suspend_cache_addition( $suspend = null ) {
3863 static $_suspend = false;
3865 if ( is_bool( $suspend ) )
3866 $_suspend = $suspend;
3872 * Suspend cache invalidation.
3874 * Turns cache invalidation on and off. Useful during imports where you don't wont to do
3875 * invalidations every time a post is inserted. Callers must be sure that what they are
3876 * doing won't lead to an inconsistent cache when invalidation is suspended.
3880 * @global bool $_wp_suspend_cache_invalidation
3882 * @param bool $suspend Optional. Whether to suspend or enable cache invalidation. Default true.
3883 * @return bool The current suspend setting.
3885 function wp_suspend_cache_invalidation( $suspend = true ) {
3886 global $_wp_suspend_cache_invalidation;
3888 $current_suspend = $_wp_suspend_cache_invalidation;
3889 $_wp_suspend_cache_invalidation = $suspend;
3890 return $current_suspend;
3894 * Determine whether a site is the main site of the current network.
3898 * @global object $current_site
3900 * @param int $site_id Optional. Site ID to test. Defaults to current site.
3901 * Defaults to current site.
3902 * @return bool True if $site_id is the main site of the network, or if not
3903 * running Multisite.
3905 function is_main_site( $site_id = null ) {
3906 // This is the current network's information; 'site' is old terminology.
3907 global $current_site;
3909 if ( ! is_multisite() )
3913 $site_id = get_current_blog_id();
3915 return (int) $site_id === (int) $current_site->blog_id;
3919 * Determine whether a network is the main network of the Multisite install.
3923 * @param int $network_id Optional. Network ID to test. Defaults to current network.
3924 * @return bool True if $network_id is the main network, or if not running Multisite.
3926 function is_main_network( $network_id = null ) {
3927 if ( ! is_multisite() ) {
3931 $current_network_id = (int) get_current_site()->id;
3933 if ( null === $network_id ) {
3934 $network_id = $current_network_id;
3937 $network_id = (int) $network_id;
3939 return ( $network_id === get_main_network_id() );
3943 * Get the main network ID.
3947 * @global wpdb $wpdb WordPress database abstraction object.
3949 * @return int The ID of the main network.
3951 function get_main_network_id() {
3954 if ( ! is_multisite() ) {
3958 if ( defined( 'PRIMARY_NETWORK_ID' ) ) {
3959 $main_network_id = PRIMARY_NETWORK_ID;
3960 } elseif ( 1 === (int) get_current_site()->id ) {
3961 // If the current network has an ID of 1, assume it is the main network.
3962 $main_network_id = 1;
3964 $main_network_id = wp_cache_get( 'primary_network_id', 'site-options' );
3966 if ( false === $main_network_id ) {
3967 $main_network_id = (int) $wpdb->get_var( "SELECT id FROM {$wpdb->site} ORDER BY id LIMIT 1" );
3968 wp_cache_add( 'primary_network_id', $main_network_id, 'site-options' );
3973 * Filter the main network ID.
3977 * @param int $main_network_id The ID of the main network.
3979 return (int) apply_filters( 'get_main_network_id', $main_network_id );
3983 * Determine whether global terms are enabled.
3987 * @staticvar bool $global_terms
3989 * @return bool True if multisite and global terms enabled.
3991 function global_terms_enabled() {
3992 if ( ! is_multisite() )
3995 static $global_terms = null;
3996 if ( is_null( $global_terms ) ) {
3999 * Filter whether global terms are enabled.
4001 * Passing a non-null value to the filter will effectively short-circuit the function,
4002 * returning the value of the 'global_terms_enabled' site option instead.
4006 * @param null $enabled Whether global terms are enabled.
4008 $filter = apply_filters( 'global_terms_enabled', null );
4009 if ( ! is_null( $filter ) )
4010 $global_terms = (bool) $filter;
4012 $global_terms = (bool) get_site_option( 'global_terms_enabled', false );
4014 return $global_terms;
4018 * gmt_offset modification for smart timezone handling.
4020 * Overrides the gmt_offset option if we have a timezone_string available.
4024 * @return float|false Timezone GMT offset, false otherwise.
4026 function wp_timezone_override_offset() {
4027 if ( !$timezone_string = get_option( 'timezone_string' ) ) {
4031 $timezone_object = timezone_open( $timezone_string );
4032 $datetime_object = date_create();
4033 if ( false === $timezone_object || false === $datetime_object ) {
4036 return round( timezone_offset_get( $timezone_object, $datetime_object ) / HOUR_IN_SECONDS, 2 );
4040 * Sort-helper for timezones.
4049 function _wp_timezone_choice_usort_callback( $a, $b ) {
4050 // Don't use translated versions of Etc
4051 if ( 'Etc' === $a['continent'] && 'Etc' === $b['continent'] ) {
4052 // Make the order of these more like the old dropdown
4053 if ( 'GMT+' === substr( $a['city'], 0, 4 ) && 'GMT+' === substr( $b['city'], 0, 4 ) ) {
4054 return -1 * ( strnatcasecmp( $a['city'], $b['city'] ) );
4056 if ( 'UTC' === $a['city'] ) {
4057 if ( 'GMT+' === substr( $b['city'], 0, 4 ) ) {
4062 if ( 'UTC' === $b['city'] ) {
4063 if ( 'GMT+' === substr( $a['city'], 0, 4 ) ) {
4068 return strnatcasecmp( $a['city'], $b['city'] );
4070 if ( $a['t_continent'] == $b['t_continent'] ) {
4071 if ( $a['t_city'] == $b['t_city'] ) {
4072 return strnatcasecmp( $a['t_subcity'], $b['t_subcity'] );
4074 return strnatcasecmp( $a['t_city'], $b['t_city'] );
4076 // Force Etc to the bottom of the list
4077 if ( 'Etc' === $a['continent'] ) {
4080 if ( 'Etc' === $b['continent'] ) {
4083 return strnatcasecmp( $a['t_continent'], $b['t_continent'] );
4088 * Gives a nicely-formatted list of timezone strings.
4092 * @staticvar bool $mo_loaded
4094 * @param string $selected_zone Selected timezone.
4097 function wp_timezone_choice( $selected_zone ) {
4098 static $mo_loaded = false;
4100 $continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
4102 // Load translations for continents and cities
4103 if ( !$mo_loaded ) {
4104 $locale = get_locale();
4105 $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
4106 load_textdomain( 'continents-cities', $mofile );
4111 foreach ( timezone_identifiers_list() as $zone ) {
4112 $zone = explode( '/', $zone );
4113 if ( !in_array( $zone[0], $continents ) ) {
4117 // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
4119 0 => ( isset( $zone[0] ) && $zone[0] ),
4120 1 => ( isset( $zone[1] ) && $zone[1] ),
4121 2 => ( isset( $zone[2] ) && $zone[2] ),
4123 $exists[3] = ( $exists[0] && 'Etc' !== $zone[0] );
4124 $exists[4] = ( $exists[1] && $exists[3] );
4125 $exists[5] = ( $exists[2] && $exists[3] );
4128 'continent' => ( $exists[0] ? $zone[0] : '' ),
4129 'city' => ( $exists[1] ? $zone[1] : '' ),
4130 'subcity' => ( $exists[2] ? $zone[2] : '' ),
4131 't_continent' => ( $exists[3] ? translate( str_replace( '_', ' ', $zone[0] ), 'continents-cities' ) : '' ),
4132 't_city' => ( $exists[4] ? translate( str_replace( '_', ' ', $zone[1] ), 'continents-cities' ) : '' ),
4133 't_subcity' => ( $exists[5] ? translate( str_replace( '_', ' ', $zone[2] ), 'continents-cities' ) : '' )
4136 usort( $zonen, '_wp_timezone_choice_usort_callback' );
4138 $structure = array();
4140 if ( empty( $selected_zone ) ) {
4141 $structure[] = '<option selected="selected" value="">' . __( 'Select a city' ) . '</option>';
4144 foreach ( $zonen as $key => $zone ) {
4145 // Build value in an array to join later
4146 $value = array( $zone['continent'] );
4148 if ( empty( $zone['city'] ) ) {
4149 // It's at the continent level (generally won't happen)
4150 $display = $zone['t_continent'];
4152 // It's inside a continent group
4154 // Continent optgroup
4155 if ( !isset( $zonen[$key - 1] ) || $zonen[$key - 1]['continent'] !== $zone['continent'] ) {
4156 $label = $zone['t_continent'];
4157 $structure[] = '<optgroup label="'. esc_attr( $label ) .'">';
4160 // Add the city to the value
4161 $value[] = $zone['city'];
4163 $display = $zone['t_city'];
4164 if ( !empty( $zone['subcity'] ) ) {
4165 // Add the subcity to the value
4166 $value[] = $zone['subcity'];
4167 $display .= ' - ' . $zone['t_subcity'];
4172 $value = join( '/', $value );
4174 if ( $value === $selected_zone ) {
4175 $selected = 'selected="selected" ';
4177 $structure[] = '<option ' . $selected . 'value="' . esc_attr( $value ) . '">' . esc_html( $display ) . "</option>";
4179 // Close continent optgroup
4180 if ( !empty( $zone['city'] ) && ( !isset($zonen[$key + 1]) || (isset( $zonen[$key + 1] ) && $zonen[$key + 1]['continent'] !== $zone['continent']) ) ) {
4181 $structure[] = '</optgroup>';
4186 $structure[] = '<optgroup label="'. esc_attr__( 'UTC' ) .'">';
4188 if ( 'UTC' === $selected_zone )
4189 $selected = 'selected="selected" ';
4190 $structure[] = '<option ' . $selected . 'value="' . esc_attr( 'UTC' ) . '">' . __('UTC') . '</option>';
4191 $structure[] = '</optgroup>';
4193 // Do manual UTC offsets
4194 $structure[] = '<optgroup label="'. esc_attr__( 'Manual Offsets' ) .'">';
4195 $offset_range = array (-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5,
4196 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
4197 foreach ( $offset_range as $offset ) {
4199 $offset_name = '+' . $offset;
4201 $offset_name = (string) $offset;
4203 $offset_value = $offset_name;
4204 $offset_name = str_replace(array('.25','.5','.75'), array(':15',':30',':45'), $offset_name);
4205 $offset_name = 'UTC' . $offset_name;
4206 $offset_value = 'UTC' . $offset_value;
4208 if ( $offset_value === $selected_zone )
4209 $selected = 'selected="selected" ';
4210 $structure[] = '<option ' . $selected . 'value="' . esc_attr( $offset_value ) . '">' . esc_html( $offset_name ) . "</option>";
4213 $structure[] = '</optgroup>';
4215 return join( "\n", $structure );
4219 * Strip close comment and close php tags from file headers used by WP.
4224 * @see https://core.trac.wordpress.org/ticket/8497
4226 * @param string $str Header comment to clean up.
4229 function _cleanup_header_comment( $str ) {
4230 return trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $str));
4234 * Permanently delete comments or posts of any type that have held a status
4235 * of 'trash' for the number of days defined in EMPTY_TRASH_DAYS.
4237 * The default value of `EMPTY_TRASH_DAYS` is 30 (days).
4241 * @global wpdb $wpdb
4243 function wp_scheduled_delete() {
4246 $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
4248 $posts_to_delete = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);
4250 foreach ( (array) $posts_to_delete as $post ) {
4251 $post_id = (int) $post['post_id'];
4255 $del_post = get_post($post_id);
4257 if ( !$del_post || 'trash' != $del_post->post_status ) {
4258 delete_post_meta($post_id, '_wp_trash_meta_status');
4259 delete_post_meta($post_id, '_wp_trash_meta_time');
4261 wp_delete_post($post_id);
4265 $comments_to_delete = $wpdb->get_results($wpdb->prepare("SELECT comment_id FROM $wpdb->commentmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);
4267 foreach ( (array) $comments_to_delete as $comment ) {
4268 $comment_id = (int) $comment['comment_id'];
4272 $del_comment = get_comment($comment_id);
4274 if ( !$del_comment || 'trash' != $del_comment->comment_approved ) {
4275 delete_comment_meta($comment_id, '_wp_trash_meta_time');
4276 delete_comment_meta($comment_id, '_wp_trash_meta_status');
4278 wp_delete_comment($comment_id);
4284 * Retrieve metadata from a file.
4286 * Searches for metadata in the first 8kiB of a file, such as a plugin or theme.
4287 * Each piece of metadata must be on its own line. Fields can not span multiple
4288 * lines, the value will get cut at the end of the first line.
4290 * If the file data is not within that first 8kiB, then the author should correct
4291 * their plugin file and move the data headers to the top.
4293 * @link https://codex.wordpress.org/File_Header
4297 * @param string $file Path to the file.
4298 * @param array $default_headers List of headers, in the format array('HeaderKey' => 'Header Name').
4299 * @param string $context Optional. If specified adds filter hook "extra_{$context}_headers".
4301 * @return array Array of file headers in `HeaderKey => Header Value` format.
4303 function get_file_data( $file, $default_headers, $context = '' ) {
4304 // We don't need to write to the file, so just open for reading.
4305 $fp = fopen( $file, 'r' );
4307 // Pull only the first 8kiB of the file in.
4308 $file_data = fread( $fp, 8192 );
4310 // PHP will close file handle, but we are good citizens.
4313 // Make sure we catch CR-only line endings.
4314 $file_data = str_replace( "\r", "\n", $file_data );
4317 * Filter extra file headers by context.
4319 * The dynamic portion of the hook name, `$context`, refers to
4320 * the context where extra headers might be loaded.
4324 * @param array $extra_context_headers Empty array by default.
4326 if ( $context && $extra_headers = apply_filters( "extra_{$context}_headers", array() ) ) {
4327 $extra_headers = array_combine( $extra_headers, $extra_headers ); // keys equal values
4328 $all_headers = array_merge( $extra_headers, (array) $default_headers );
4330 $all_headers = $default_headers;
4333 foreach ( $all_headers as $field => $regex ) {
4334 if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] )
4335 $all_headers[ $field ] = _cleanup_header_comment( $match[1] );
4337 $all_headers[ $field ] = '';
4340 return $all_headers;
4346 * Useful for returning true to filters easily.
4350 * @see __return_false()
4352 * @return true True.
4354 function __return_true() {
4361 * Useful for returning false to filters easily.
4365 * @see __return_true()
4367 * @return false False.
4369 function __return_false() {
4376 * Useful for returning 0 to filters easily.
4382 function __return_zero() {
4387 * Returns an empty array.
4389 * Useful for returning an empty array to filters easily.
4393 * @return array Empty array.
4395 function __return_empty_array() {
4402 * Useful for returning null to filters easily.
4406 * @return null Null value.
4408 function __return_null() {
4413 * Returns an empty string.
4415 * Useful for returning an empty string to filters easily.
4419 * @see __return_null()
4421 * @return string Empty string.
4423 function __return_empty_string() {
4428 * Send a HTTP header to disable content type sniffing in browsers which support it.
4432 * @see http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
4433 * @see http://src.chromium.org/viewvc/chrome?view=rev&revision=6985
4435 function send_nosniff_header() {
4436 @header( 'X-Content-Type-Options: nosniff' );
4440 * Return a MySQL expression for selecting the week number based on the start_of_week option.
4445 * @param string $column Database column.
4446 * @return string SQL clause.
4448 function _wp_mysql_week( $column ) {
4449 switch ( $start_of_week = (int) get_option( 'start_of_week' ) ) {
4451 return "WEEK( $column, 1 )";
4457 return "WEEK( DATE_SUB( $column, INTERVAL $start_of_week DAY ), 0 )";
4460 return "WEEK( $column, 0 )";
4465 * Find hierarchy loops using a callback function that maps object IDs to parent IDs.
4470 * @param callback $callback Function that accepts ( ID, $callback_args ) and outputs parent_ID.
4471 * @param int $start The ID to start the loop check at.
4472 * @param int $start_parent The parent_ID of $start to use instead of calling $callback( $start ).
4473 * Use null to always use $callback
4474 * @param array $callback_args Optional. Additional arguments to send to $callback.
4475 * @return array IDs of all members of loop.
4477 function wp_find_hierarchy_loop( $callback, $start, $start_parent, $callback_args = array() ) {
4478 $override = is_null( $start_parent ) ? array() : array( $start => $start_parent );
4480 if ( !$arbitrary_loop_member = wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override, $callback_args ) )
4483 return wp_find_hierarchy_loop_tortoise_hare( $callback, $arbitrary_loop_member, $override, $callback_args, true );
4487 * Use the "The Tortoise and the Hare" algorithm to detect loops.
4489 * For every step of the algorithm, the hare takes two steps and the tortoise one.
4490 * If the hare ever laps the tortoise, there must be a loop.
4495 * @param callback $callback Function that accepts ( ID, callback_arg, ... ) and outputs parent_ID.
4496 * @param int $start The ID to start the loop check at.
4497 * @param array $override Optional. An array of ( ID => parent_ID, ... ) to use instead of $callback.
4498 * Default empty array.
4499 * @param array $callback_args Optional. Additional arguments to send to $callback. Default empty array.
4500 * @param bool $_return_loop Optional. Return loop members or just detect presence of loop? Only set
4501 * to true if you already know the given $start is part of a loop (otherwise
4502 * the returned array might include branches). Default false.
4503 * @return mixed Scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if
4506 function wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override = array(), $callback_args = array(), $_return_loop = false ) {
4507 $tortoise = $hare = $evanescent_hare = $start;
4510 // Set evanescent_hare to one past hare
4511 // Increment hare two steps
4515 ( $evanescent_hare = isset( $override[$hare] ) ? $override[$hare] : call_user_func_array( $callback, array_merge( array( $hare ), $callback_args ) ) )
4517 ( $hare = isset( $override[$evanescent_hare] ) ? $override[$evanescent_hare] : call_user_func_array( $callback, array_merge( array( $evanescent_hare ), $callback_args ) ) )
4519 if ( $_return_loop )
4520 $return[$tortoise] = $return[$evanescent_hare] = $return[$hare] = true;
4522 // tortoise got lapped - must be a loop
4523 if ( $tortoise == $evanescent_hare || $tortoise == $hare )
4524 return $_return_loop ? $return : $tortoise;
4526 // Increment tortoise by one step
4527 $tortoise = isset( $override[$tortoise] ) ? $override[$tortoise] : call_user_func_array( $callback, array_merge( array( $tortoise ), $callback_args ) );
4534 * Send a HTTP header to limit rendering of pages to same origin iframes.
4538 * @see https://developer.mozilla.org/en/the_x-frame-options_response_header
4540 function send_frame_options_header() {
4541 @header( 'X-Frame-Options: SAMEORIGIN' );
4545 * Retrieve a list of protocols to allow in HTML attributes.
4548 * @since 4.3.0 Added 'webcal' to the protocols array.
4553 * @staticvar array $protocols
4555 * @return array Array of allowed protocols. Defaults to an array containing 'http', 'https',
4556 * 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet',
4557 * 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp', and 'webcal'.
4559 function wp_allowed_protocols() {
4560 static $protocols = array();
4562 if ( empty( $protocols ) ) {
4563 $protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp', 'webcal' );
4566 * Filter the list of protocols allowed in HTML attributes.
4570 * @param array $protocols Array of allowed protocols e.g. 'http', 'ftp', 'tel', and more.
4572 $protocols = apply_filters( 'kses_allowed_protocols', $protocols );
4579 * Return a comma-separated string of functions that have been called to get
4580 * to the current point in code.
4584 * @see https://core.trac.wordpress.org/ticket/19589
4586 * @param string $ignore_class Optional. A class to ignore all function calls within - useful
4587 * when you want to just give info about the callee. Default null.
4588 * @param int $skip_frames Optional. A number of stack frames to skip - useful for unwinding
4589 * back to the source of the issue. Default 0.
4590 * @param bool $pretty Optional. Whether or not you want a comma separated string or raw
4591 * array returned. Default true.
4592 * @return string|array Either a string containing a reversed comma separated trace or an array
4593 * of individual calls.
4595 function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) {
4596 if ( version_compare( PHP_VERSION, '5.2.5', '>=' ) )
4597 $trace = debug_backtrace( false );
4599 $trace = debug_backtrace();
4602 $check_class = ! is_null( $ignore_class );
4603 $skip_frames++; // skip this function
4605 foreach ( $trace as $call ) {
4606 if ( $skip_frames > 0 ) {
4608 } elseif ( isset( $call['class'] ) ) {
4609 if ( $check_class && $ignore_class == $call['class'] )
4610 continue; // Filter out calls
4612 $caller[] = "{$call['class']}{$call['type']}{$call['function']}";
4614 if ( in_array( $call['function'], array( 'do_action', 'apply_filters' ) ) ) {
4615 $caller[] = "{$call['function']}('{$call['args'][0]}')";
4616 } elseif ( in_array( $call['function'], array( 'include', 'include_once', 'require', 'require_once' ) ) ) {
4617 $caller[] = $call['function'] . "('" . str_replace( array( WP_CONTENT_DIR, ABSPATH ) , '', $call['args'][0] ) . "')";
4619 $caller[] = $call['function'];
4624 return join( ', ', array_reverse( $caller ) );
4630 * Retrieve ids that are not already present in the cache.
4635 * @param array $object_ids ID list.
4636 * @param string $cache_key The cache bucket to check against.
4638 * @return array List of ids not present in the cache.
4640 function _get_non_cached_ids( $object_ids, $cache_key ) {
4642 foreach ( $object_ids as $id ) {
4644 if ( !wp_cache_get( $id, $cache_key ) ) {
4653 * Test if the current device has the capability to upload files.
4658 * @return bool Whether the device is able to upload files.
4660 function _device_can_upload() {
4661 if ( ! wp_is_mobile() )
4664 $ua = $_SERVER['HTTP_USER_AGENT'];
4666 if ( strpos($ua, 'iPhone') !== false
4667 || strpos($ua, 'iPad') !== false
4668 || strpos($ua, 'iPod') !== false ) {
4669 return preg_match( '#OS ([\d_]+) like Mac OS X#', $ua, $version ) && version_compare( $version[1], '6', '>=' );
4676 * Test if a given path is a stream URL
4678 * @param string $path The resource path or URL.
4679 * @return bool True if the path is a stream URL.
4681 function wp_is_stream( $path ) {
4682 $wrappers = stream_get_wrappers();
4683 $wrappers_re = '(' . join('|', $wrappers) . ')';
4685 return preg_match( "!^$wrappers_re://!", $path ) === 1;
4689 * Test if the supplied date is valid for the Gregorian calendar.
4695 * @param int $month Month number.
4696 * @param int $day Day number.
4697 * @param int $year Year number.
4698 * @param string $source_date The date to filter.
4699 * @return bool True if valid date, false if not valid date.
4701 function wp_checkdate( $month, $day, $year, $source_date ) {
4703 * Filter whether the given date is valid for the Gregorian calendar.
4707 * @param bool $checkdate Whether the given date is valid.
4708 * @param string $source_date Date to check.
4710 return apply_filters( 'wp_checkdate', checkdate( $month, $day, $year ), $source_date );
4714 * Load the auth check for monitoring whether the user is still logged in.
4716 * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
4718 * This is disabled for certain screens where a login screen could cause an
4719 * inconvenient interruption. A filter called wp_auth_check_load can be used
4720 * for fine-grained control.
4724 function wp_auth_check_load() {
4725 if ( ! is_admin() && ! is_user_logged_in() )
4728 if ( defined( 'IFRAME_REQUEST' ) )
4731 $screen = get_current_screen();
4732 $hidden = array( 'update', 'update-network', 'update-core', 'update-core-network', 'upgrade', 'upgrade-network', 'network' );
4733 $show = ! in_array( $screen->id, $hidden );
4736 * Filter whether to load the authentication check.
4738 * Passing a falsey value to the filter will effectively short-circuit
4739 * loading the authentication check.
4743 * @param bool $show Whether to load the authentication check.
4744 * @param WP_Screen $screen The current screen object.
4746 if ( apply_filters( 'wp_auth_check_load', $show, $screen ) ) {
4747 wp_enqueue_style( 'wp-auth-check' );
4748 wp_enqueue_script( 'wp-auth-check' );
4750 add_action( 'admin_print_footer_scripts', 'wp_auth_check_html', 5 );
4751 add_action( 'wp_print_footer_scripts', 'wp_auth_check_html', 5 );
4756 * Output the HTML that shows the wp-login dialog when the user is no longer logged in.
4760 function wp_auth_check_html() {
4761 $login_url = wp_login_url();
4762 $current_domain = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
4763 $same_domain = ( strpos( $login_url, $current_domain ) === 0 );
4766 * Filter whether the authentication check originated at the same domain.
4770 * @param bool $same_domain Whether the authentication check originated at the same domain.
4772 $same_domain = apply_filters( 'wp_auth_check_same_domain', $same_domain );
4773 $wrap_class = $same_domain ? 'hidden' : 'hidden fallback';
4776 <div id="wp-auth-check-wrap" class="<?php echo $wrap_class; ?>">
4777 <div id="wp-auth-check-bg"></div>
4778 <div id="wp-auth-check">
4779 <div class="wp-auth-check-close" tabindex="0" title="<?php esc_attr_e('Close'); ?>"></div>
4782 if ( $same_domain ) {
4784 <div id="wp-auth-check-form" data-src="<?php echo esc_url( add_query_arg( array( 'interim-login' => 1 ), $login_url ) ); ?>"></div>
4789 <div class="wp-auth-fallback">
4790 <p><b class="wp-auth-fallback-expired" tabindex="0"><?php _e('Session expired'); ?></b></p>
4791 <p><a href="<?php echo esc_url( $login_url ); ?>" target="_blank"><?php _e('Please log in again.'); ?></a>
4792 <?php _e('The login page will open in a new window. After logging in you can close it and return to this page.'); ?></p>
4800 * Check whether a user is still logged in, for the heartbeat.
4802 * Send a result that shows a log-in box if the user is no longer logged in,
4803 * or if their cookie is within the grace period.
4807 * @global int $login_grace_period
4809 * @param array $response The Heartbeat response.
4810 * @return array $response The Heartbeat response with 'wp-auth-check' value set.
4812 function wp_auth_check( $response ) {
4813 $response['wp-auth-check'] = is_user_logged_in() && empty( $GLOBALS['login_grace_period'] );
4818 * Return RegEx body to liberally match an opening HTML tag.
4820 * Matches an opening HTML tag that:
4821 * 1. Is self-closing or
4822 * 2. Has no body but has a closing tag of the same name or
4823 * 3. Contains a body and a closing tag of the same name
4825 * Note: this RegEx does not balance inner tags and does not attempt
4826 * to produce valid HTML
4830 * @param string $tag An HTML tag name. Example: 'video'.
4831 * @return string Tag RegEx.
4833 function get_tag_regex( $tag ) {
4834 if ( empty( $tag ) )
4836 return sprintf( '<%1$s[^<]*(?:>[\s\S]*<\/%1$s>|\s*\/>)', tag_escape( $tag ) );
4840 * Retrieve a canonical form of the provided charset appropriate for passing to PHP
4841 * functions such as htmlspecialchars() and charset html attributes.
4846 * @see https://core.trac.wordpress.org/ticket/23688
4848 * @param string $charset A charset name.
4849 * @return string The canonical form of the charset.
4851 function _canonical_charset( $charset ) {
4852 if ( 'UTF-8' === $charset || 'utf-8' === $charset || 'utf8' === $charset ||
4853 'UTF8' === $charset )
4856 if ( 'ISO-8859-1' === $charset || 'iso-8859-1' === $charset ||
4857 'iso8859-1' === $charset || 'ISO8859-1' === $charset )
4858 return 'ISO-8859-1';
4864 * Set the mbstring internal encoding to a binary safe encoding when func_overload
4867 * When mbstring.func_overload is in use for multi-byte encodings, the results from
4868 * strlen() and similar functions respect the utf8 characters, causing binary data
4869 * to return incorrect lengths.
4871 * This function overrides the mbstring encoding to a binary-safe encoding, and
4872 * resets it to the users expected encoding afterwards through the
4873 * `reset_mbstring_encoding` function.
4875 * It is safe to recursively call this function, however each
4876 * `mbstring_binary_safe_encoding()` call must be followed up with an equal number
4877 * of `reset_mbstring_encoding()` calls.
4881 * @see reset_mbstring_encoding()
4883 * @staticvar array $encodings
4884 * @staticvar bool $overloaded
4886 * @param bool $reset Optional. Whether to reset the encoding back to a previously-set encoding.
4889 function mbstring_binary_safe_encoding( $reset = false ) {
4890 static $encodings = array();
4891 static $overloaded = null;
4893 if ( is_null( $overloaded ) )
4894 $overloaded = function_exists( 'mb_internal_encoding' ) && ( ini_get( 'mbstring.func_overload' ) & 2 );
4896 if ( false === $overloaded )
4900 $encoding = mb_internal_encoding();
4901 array_push( $encodings, $encoding );
4902 mb_internal_encoding( 'ISO-8859-1' );
4905 if ( $reset && $encodings ) {
4906 $encoding = array_pop( $encodings );
4907 mb_internal_encoding( $encoding );
4912 * Reset the mbstring internal encoding to a users previously set encoding.
4914 * @see mbstring_binary_safe_encoding()
4918 function reset_mbstring_encoding() {
4919 mbstring_binary_safe_encoding( true );
4923 * Filter/validate a variable as a boolean.
4925 * Alternative to `filter_var( $var, FILTER_VALIDATE_BOOLEAN )`.
4929 * @param mixed $var Boolean value to validate.
4930 * @return bool Whether the value is validated.
4932 function wp_validate_boolean( $var ) {
4933 if ( is_bool( $var ) ) {
4937 if ( is_string( $var ) && 'false' === strtolower( $var ) ) {
4949 * @param string $file The path to the file to delete.
4951 function wp_delete_file( $file ) {
4953 * Filter the path of the file to delete.
4957 * @param string $medium Path to the file to delete.
4959 $delete = apply_filters( 'wp_delete_file', $file );
4960 if ( ! empty( $delete ) ) {
4966 * Outputs a small JS snippet on preview tabs/windows to remove `window.name` on unload.
4968 * This prevents reusing the same tab for a preview when the user has navigated away.
4972 function wp_post_preview_js() {
4975 if ( ! is_preview() || empty( $post ) ) {
4979 // Has to match the window name used in post_submit_meta_box()
4980 $name = 'wp-preview-' . (int) $post->ID;
4985 var query = document.location.search;
4987 if ( query && query.indexOf( 'preview=true' ) !== -1 ) {
4988 window.name = '<?php echo $name; ?>';
4991 if ( window.addEventListener ) {
4992 window.addEventListener( 'unload', function() { window.name = ''; }, false );